Annotation of embedaddon/php/ext/interbase/interbase.c, revision 1.1.1.4
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.4 ! misho 5: | Copyright (c) 1997-2014 The PHP Group |
1.1 misho 6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Authors: Jouni Ahto <jouni.ahto@exdec.fi> |
16: | Andrew Avdeev <andy@rsc.mv.ru> |
17: | Ard Biesheuvel <a.k.biesheuvel@ewi.tudelft.nl> |
18: +----------------------------------------------------------------------+
19: */
20:
21: #ifdef HAVE_CONFIG_H
22: #include "config.h"
23: #endif
24:
25: #define _GNU_SOURCE
26:
27: #include "php.h"
28:
29: #if HAVE_IBASE
30:
31: #include "php_ini.h"
32: #include "ext/standard/php_standard.h"
33: #include "ext/standard/md5.h"
34: #include "php_interbase.h"
35: #include "php_ibase_includes.h"
36: #include "SAPI.h"
37:
38: #include <time.h>
39:
40: #define ROLLBACK 0
41: #define COMMIT 1
42: #define RETAIN 2
43:
44: #define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } }
45:
46: ZEND_DECLARE_MODULE_GLOBALS(ibase)
47: static PHP_GINIT_FUNCTION(ibase);
48:
49: /* {{{ arginfo */
50: ZEND_BEGIN_ARG_INFO(arginfo_ibase_errmsg, 0)
51: ZEND_END_ARG_INFO()
52:
53: ZEND_BEGIN_ARG_INFO(arginfo_ibase_errcode, 0)
54: ZEND_END_ARG_INFO()
55:
56: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_connect, 0, 0, 1)
57: ZEND_ARG_INFO(0, database)
58: ZEND_ARG_INFO(0, username)
59: ZEND_ARG_INFO(0, password)
60: ZEND_ARG_INFO(0, charset)
61: ZEND_ARG_INFO(0, buffers)
62: ZEND_ARG_INFO(0, dialect)
63: ZEND_ARG_INFO(0, role)
64: ZEND_END_ARG_INFO()
65:
66: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_pconnect, 0, 0, 1)
67: ZEND_ARG_INFO(0, database)
68: ZEND_ARG_INFO(0, username)
69: ZEND_ARG_INFO(0, password)
70: ZEND_ARG_INFO(0, charset)
71: ZEND_ARG_INFO(0, buffers)
72: ZEND_ARG_INFO(0, dialect)
73: ZEND_ARG_INFO(0, role)
74: ZEND_END_ARG_INFO()
75:
76: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_close, 0, 0, 0)
77: ZEND_ARG_INFO(0, link_identifier)
78: ZEND_END_ARG_INFO()
79:
80: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_drop_db, 0, 0, 0)
81: ZEND_ARG_INFO(0, link_identifier)
82: ZEND_END_ARG_INFO()
83:
84: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_trans, 0, 0, 0)
85: ZEND_ARG_INFO(0, trans_args)
86: ZEND_ARG_INFO(0, link_identifier)
87: ZEND_ARG_INFO(0, trans_args)
88: ZEND_ARG_INFO(0, link_identifier)
89: ZEND_END_ARG_INFO()
90:
91: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit, 0, 0, 1)
92: ZEND_ARG_INFO(0, link_identifier)
93: ZEND_END_ARG_INFO()
94:
95: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback, 0, 0, 1)
96: ZEND_ARG_INFO(0, link_identifier)
97: ZEND_END_ARG_INFO()
98:
99: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_commit_ret, 0, 0, 1)
100: ZEND_ARG_INFO(0, link_identifier)
101: ZEND_END_ARG_INFO()
102:
103: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_rollback_ret, 0, 0, 1)
104: ZEND_ARG_INFO(0, link_identifier)
105: ZEND_END_ARG_INFO()
106:
107: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_gen_id, 0, 0, 1)
108: ZEND_ARG_INFO(0, generator)
109: ZEND_ARG_INFO(0, increment)
110: ZEND_ARG_INFO(0, link_identifier)
111: ZEND_END_ARG_INFO()
112:
113: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_create, 0, 0, 0)
114: ZEND_ARG_INFO(0, link_identifier)
115: ZEND_END_ARG_INFO()
116:
117: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_open, 0, 0, 0)
118: ZEND_ARG_INFO(0, link_identifier)
119: ZEND_ARG_INFO(0, blob_id)
120: ZEND_END_ARG_INFO()
121:
122: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_add, 0, 0, 2)
123: ZEND_ARG_INFO(0, blob_handle)
124: ZEND_ARG_INFO(0, data)
125: ZEND_END_ARG_INFO()
126:
127: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_get, 0, 0, 2)
128: ZEND_ARG_INFO(0, blob_handle)
129: ZEND_ARG_INFO(0, len)
130: ZEND_END_ARG_INFO()
131:
132: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_close, 0, 0, 1)
133: ZEND_ARG_INFO(0, blob_handle)
134: ZEND_END_ARG_INFO()
135:
136: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_cancel, 0, 0, 1)
137: ZEND_ARG_INFO(0, blob_handle)
138: ZEND_END_ARG_INFO()
139:
140: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_info, 0, 0, 0)
141: ZEND_ARG_INFO(0, link_identifier)
142: ZEND_ARG_INFO(0, blob_id)
143: ZEND_END_ARG_INFO()
144:
145: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_echo, 0, 0, 0)
146: ZEND_ARG_INFO(0, link_identifier)
147: ZEND_ARG_INFO(0, blob_id)
148: ZEND_END_ARG_INFO()
149:
150: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_blob_import, 0, 0, 0)
151: ZEND_ARG_INFO(0, link_identifier)
152: ZEND_ARG_INFO(0, file)
153: ZEND_END_ARG_INFO()
154:
155: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_query, 0, 0, 0)
156: ZEND_ARG_INFO(0, link_identifier)
157: ZEND_ARG_INFO(0, link_identifier)
158: ZEND_ARG_INFO(0, query)
159: ZEND_ARG_INFO(0, bind_arg)
160: ZEND_ARG_INFO(0, bind_arg)
161: ZEND_END_ARG_INFO()
162:
163: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_affected_rows, 0, 0, 0)
164: ZEND_ARG_INFO(0, link_identifier)
165: ZEND_END_ARG_INFO()
166:
167: #if abies_0
168: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_rows, 0, 0, 1)
169: ZEND_ARG_INFO(0, result_identifier)
170: ZEND_END_ARG_INFO()
171: #endif
172:
173: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_row, 0, 0, 1)
174: ZEND_ARG_INFO(0, result)
175: ZEND_ARG_INFO(0, fetch_flags)
176: ZEND_END_ARG_INFO()
177:
178: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_assoc, 0, 0, 1)
179: ZEND_ARG_INFO(0, result)
180: ZEND_ARG_INFO(0, fetch_flags)
181: ZEND_END_ARG_INFO()
182:
183: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_fetch_object, 0, 0, 1)
184: ZEND_ARG_INFO(0, result)
185: ZEND_ARG_INFO(0, fetch_flags)
186: ZEND_END_ARG_INFO()
187:
188: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_name_result, 0, 0, 2)
189: ZEND_ARG_INFO(0, result)
190: ZEND_ARG_INFO(0, name)
191: ZEND_END_ARG_INFO()
192:
193: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_result, 0, 0, 1)
194: ZEND_ARG_INFO(0, result)
195: ZEND_END_ARG_INFO()
196:
197: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_prepare, 0, 0, 0)
198: ZEND_ARG_INFO(0, link_identifier)
199: ZEND_ARG_INFO(0, query)
200: ZEND_END_ARG_INFO()
201:
202: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_execute, 0, 0, 1)
203: ZEND_ARG_INFO(0, query)
204: ZEND_ARG_INFO(0, bind_arg)
205: ZEND_ARG_INFO(0, bind_arg)
206: ZEND_END_ARG_INFO()
207:
208: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_query, 0, 0, 1)
209: ZEND_ARG_INFO(0, query)
210: ZEND_END_ARG_INFO()
211:
212: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_fields, 0, 0, 1)
213: ZEND_ARG_INFO(0, query_result)
214: ZEND_END_ARG_INFO()
215:
216: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_field_info, 0, 0, 2)
217: ZEND_ARG_INFO(0, query_result)
218: ZEND_ARG_INFO(0, field_number)
219: ZEND_END_ARG_INFO()
220:
221: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_num_params, 0, 0, 1)
222: ZEND_ARG_INFO(0, query)
223: ZEND_END_ARG_INFO()
224:
225: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_param_info, 0, 0, 2)
226: ZEND_ARG_INFO(0, query)
227: ZEND_ARG_INFO(0, field_number)
228: ZEND_END_ARG_INFO()
229:
230: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_add_user, 0, 0, 3)
231: ZEND_ARG_INFO(0, service_handle)
232: ZEND_ARG_INFO(0, user_name)
233: ZEND_ARG_INFO(0, password)
234: ZEND_ARG_INFO(0, first_name)
235: ZEND_ARG_INFO(0, middle_name)
236: ZEND_ARG_INFO(0, last_name)
237: ZEND_END_ARG_INFO()
238:
239: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_modify_user, 0, 0, 3)
240: ZEND_ARG_INFO(0, service_handle)
241: ZEND_ARG_INFO(0, user_name)
242: ZEND_ARG_INFO(0, password)
243: ZEND_ARG_INFO(0, first_name)
244: ZEND_ARG_INFO(0, middle_name)
245: ZEND_ARG_INFO(0, last_name)
246: ZEND_END_ARG_INFO()
247:
248: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_delete_user, 0, 0, 3)
249: ZEND_ARG_INFO(0, service_handle)
250: ZEND_ARG_INFO(0, user_name)
251: ZEND_ARG_INFO(0, password)
252: ZEND_ARG_INFO(0, first_name)
253: ZEND_ARG_INFO(0, middle_name)
254: ZEND_ARG_INFO(0, last_name)
255: ZEND_END_ARG_INFO()
256:
257: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_attach, 0, 0, 3)
258: ZEND_ARG_INFO(0, host)
259: ZEND_ARG_INFO(0, dba_username)
260: ZEND_ARG_INFO(0, dba_password)
261: ZEND_END_ARG_INFO()
262:
263: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_service_detach, 0, 0, 1)
264: ZEND_ARG_INFO(0, service_handle)
265: ZEND_END_ARG_INFO()
266:
267: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_backup, 0, 0, 3)
268: ZEND_ARG_INFO(0, service_handle)
269: ZEND_ARG_INFO(0, source_db)
270: ZEND_ARG_INFO(0, dest_file)
271: ZEND_ARG_INFO(0, options)
272: ZEND_ARG_INFO(0, verbose)
273: ZEND_END_ARG_INFO()
274:
275: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_restore, 0, 0, 3)
276: ZEND_ARG_INFO(0, service_handle)
277: ZEND_ARG_INFO(0, source_file)
278: ZEND_ARG_INFO(0, dest_db)
279: ZEND_ARG_INFO(0, options)
280: ZEND_ARG_INFO(0, verbose)
281: ZEND_END_ARG_INFO()
282:
283: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_maintain_db, 0, 0, 3)
284: ZEND_ARG_INFO(0, service_handle)
285: ZEND_ARG_INFO(0, db)
286: ZEND_ARG_INFO(0, action)
287: ZEND_ARG_INFO(0, argument)
288: ZEND_END_ARG_INFO()
289:
290: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_db_info, 0, 0, 3)
291: ZEND_ARG_INFO(0, service_handle)
292: ZEND_ARG_INFO(0, db)
293: ZEND_ARG_INFO(0, action)
294: ZEND_ARG_INFO(0, argument)
295: ZEND_END_ARG_INFO()
296:
297: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_server_info, 0, 0, 2)
298: ZEND_ARG_INFO(0, service_handle)
299: ZEND_ARG_INFO(0, action)
300: ZEND_END_ARG_INFO()
301:
302: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_wait_event, 0, 0, 1)
303: ZEND_ARG_INFO(0, link_identifier)
304: ZEND_ARG_INFO(0, event)
305: ZEND_ARG_INFO(0, event2)
306: ZEND_END_ARG_INFO()
307:
308: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_set_event_handler, 0, 0, 2)
309: ZEND_ARG_INFO(0, link_identifier)
310: ZEND_ARG_INFO(0, handler)
311: ZEND_ARG_INFO(0, event)
312: ZEND_ARG_INFO(0, event2)
313: ZEND_END_ARG_INFO()
314:
315: ZEND_BEGIN_ARG_INFO_EX(arginfo_ibase_free_event_handler, 0, 0, 1)
316: ZEND_ARG_INFO(0, event)
317: ZEND_END_ARG_INFO()
318: /* }}} */
319:
320: /* {{{ extension definition structures */
321: const zend_function_entry ibase_functions[] = {
322: PHP_FE(ibase_connect, arginfo_ibase_connect)
323: PHP_FE(ibase_pconnect, arginfo_ibase_pconnect)
324: PHP_FE(ibase_close, arginfo_ibase_close)
325: PHP_FE(ibase_drop_db, arginfo_ibase_drop_db)
326: PHP_FE(ibase_query, arginfo_ibase_query)
327: PHP_FE(ibase_fetch_row, arginfo_ibase_fetch_row)
328: PHP_FE(ibase_fetch_assoc, arginfo_ibase_fetch_assoc)
329: PHP_FE(ibase_fetch_object, arginfo_ibase_fetch_object)
330: PHP_FE(ibase_free_result, arginfo_ibase_free_result)
331: PHP_FE(ibase_name_result, arginfo_ibase_name_result)
332: PHP_FE(ibase_prepare, arginfo_ibase_prepare)
333: PHP_FE(ibase_execute, arginfo_ibase_execute)
334: PHP_FE(ibase_free_query, arginfo_ibase_free_query)
335: PHP_FE(ibase_gen_id, arginfo_ibase_gen_id)
336: PHP_FE(ibase_num_fields, arginfo_ibase_num_fields)
337: PHP_FE(ibase_num_params, arginfo_ibase_num_params)
338: #if abies_0
339: PHP_FE(ibase_num_rows, arginfo_ibase_num_rows)
340: #endif
341: PHP_FE(ibase_affected_rows, arginfo_ibase_affected_rows)
342: PHP_FE(ibase_field_info, arginfo_ibase_field_info)
343: PHP_FE(ibase_param_info, arginfo_ibase_param_info)
344:
345: PHP_FE(ibase_trans, arginfo_ibase_trans)
346: PHP_FE(ibase_commit, arginfo_ibase_commit)
347: PHP_FE(ibase_rollback, arginfo_ibase_rollback)
348: PHP_FE(ibase_commit_ret, arginfo_ibase_commit_ret)
349: PHP_FE(ibase_rollback_ret, arginfo_ibase_rollback_ret)
350:
351: PHP_FE(ibase_blob_info, arginfo_ibase_blob_info)
352: PHP_FE(ibase_blob_create, arginfo_ibase_blob_create)
353: PHP_FE(ibase_blob_add, arginfo_ibase_blob_add)
354: PHP_FE(ibase_blob_cancel, arginfo_ibase_blob_cancel)
355: PHP_FE(ibase_blob_close, arginfo_ibase_blob_close)
356: PHP_FE(ibase_blob_open, arginfo_ibase_blob_open)
357: PHP_FE(ibase_blob_get, arginfo_ibase_blob_get)
358: PHP_FE(ibase_blob_echo, arginfo_ibase_blob_echo)
359: PHP_FE(ibase_blob_import, arginfo_ibase_blob_import)
360: PHP_FE(ibase_errmsg, arginfo_ibase_errmsg)
361: PHP_FE(ibase_errcode, arginfo_ibase_errcode)
362:
363: PHP_FE(ibase_add_user, arginfo_ibase_add_user)
364: PHP_FE(ibase_modify_user, arginfo_ibase_modify_user)
365: PHP_FE(ibase_delete_user, arginfo_ibase_delete_user)
366:
367: PHP_FE(ibase_service_attach, arginfo_ibase_service_attach)
368: PHP_FE(ibase_service_detach, arginfo_ibase_service_detach)
369: PHP_FE(ibase_backup, arginfo_ibase_backup)
370: PHP_FE(ibase_restore, arginfo_ibase_restore)
371: PHP_FE(ibase_maintain_db, arginfo_ibase_maintain_db)
372: PHP_FE(ibase_db_info, arginfo_ibase_db_info)
373: PHP_FE(ibase_server_info, arginfo_ibase_server_info)
374:
375: PHP_FE(ibase_wait_event, arginfo_ibase_wait_event)
376: PHP_FE(ibase_set_event_handler, arginfo_ibase_set_event_handler)
377: PHP_FE(ibase_free_event_handler, arginfo_ibase_free_event_handler)
378:
379: /**
380: * These aliases are provided in order to maintain forward compatibility. As Firebird
381: * and InterBase are developed independently, functionality might be different between
382: * the two branches in future versions.
383: * Firebird users should use the aliases, so future InterBase-specific changes will
384: * not affect their code
385: */
386: PHP_FALIAS(fbird_connect, ibase_connect, arginfo_ibase_connect)
387: PHP_FALIAS(fbird_pconnect, ibase_pconnect, arginfo_ibase_pconnect)
388: PHP_FALIAS(fbird_close, ibase_close, arginfo_ibase_close)
389: PHP_FALIAS(fbird_drop_db, ibase_drop_db, arginfo_ibase_drop_db)
390: PHP_FALIAS(fbird_query, ibase_query, arginfo_ibase_query)
391: PHP_FALIAS(fbird_fetch_row, ibase_fetch_row, arginfo_ibase_fetch_row)
392: PHP_FALIAS(fbird_fetch_assoc, ibase_fetch_assoc, arginfo_ibase_fetch_assoc)
393: PHP_FALIAS(fbird_fetch_object, ibase_fetch_object, arginfo_ibase_fetch_object)
394: PHP_FALIAS(fbird_free_result, ibase_free_result, arginfo_ibase_free_result)
395: PHP_FALIAS(fbird_name_result, ibase_name_result, arginfo_ibase_name_result)
396: PHP_FALIAS(fbird_prepare, ibase_prepare, arginfo_ibase_prepare)
397: PHP_FALIAS(fbird_execute, ibase_execute, arginfo_ibase_execute)
398: PHP_FALIAS(fbird_free_query, ibase_free_query, arginfo_ibase_free_query)
399: PHP_FALIAS(fbird_gen_id, ibase_gen_id, arginfo_ibase_gen_id)
400: PHP_FALIAS(fbird_num_fields, ibase_num_fields, arginfo_ibase_num_fields)
401: PHP_FALIAS(fbird_num_params, ibase_num_params, arginfo_ibase_num_params)
402: #if abies_0
403: PHP_FALIAS(fbird_num_rows, ibase_num_rows, arginfo_ibase_num_rows)
404: #endif
405: PHP_FALIAS(fbird_affected_rows, ibase_affected_rows, arginfo_ibase_affected_rows)
406: PHP_FALIAS(fbird_field_info, ibase_field_info, arginfo_ibase_field_info)
407: PHP_FALIAS(fbird_param_info, ibase_param_info, arginfo_ibase_param_info)
408:
409: PHP_FALIAS(fbird_trans, ibase_trans, arginfo_ibase_trans)
410: PHP_FALIAS(fbird_commit, ibase_commit, arginfo_ibase_commit)
411: PHP_FALIAS(fbird_rollback, ibase_rollback, arginfo_ibase_rollback)
412: PHP_FALIAS(fbird_commit_ret, ibase_commit_ret, arginfo_ibase_commit_ret)
413: PHP_FALIAS(fbird_rollback_ret, ibase_rollback_ret, arginfo_ibase_rollback_ret)
414:
415: PHP_FALIAS(fbird_blob_info, ibase_blob_info, arginfo_ibase_blob_info)
416: PHP_FALIAS(fbird_blob_create, ibase_blob_create, arginfo_ibase_blob_create)
417: PHP_FALIAS(fbird_blob_add, ibase_blob_add, arginfo_ibase_blob_add)
418: PHP_FALIAS(fbird_blob_cancel, ibase_blob_cancel, arginfo_ibase_blob_cancel)
419: PHP_FALIAS(fbird_blob_close, ibase_blob_close, arginfo_ibase_blob_close)
420: PHP_FALIAS(fbird_blob_open, ibase_blob_open, arginfo_ibase_blob_open)
421: PHP_FALIAS(fbird_blob_get, ibase_blob_get, arginfo_ibase_blob_get)
422: PHP_FALIAS(fbird_blob_echo, ibase_blob_echo, arginfo_ibase_blob_echo)
423: PHP_FALIAS(fbird_blob_import, ibase_blob_import, arginfo_ibase_blob_import)
424: PHP_FALIAS(fbird_errmsg, ibase_errmsg, arginfo_ibase_errmsg)
425: PHP_FALIAS(fbird_errcode, ibase_errcode, arginfo_ibase_errcode)
426:
427: PHP_FALIAS(fbird_add_user, ibase_add_user, arginfo_ibase_add_user)
428: PHP_FALIAS(fbird_modify_user, ibase_modify_user, arginfo_ibase_modify_user)
429: PHP_FALIAS(fbird_delete_user, ibase_delete_user, arginfo_ibase_delete_user)
430:
431: PHP_FALIAS(fbird_service_attach, ibase_service_attach, arginfo_ibase_service_attach)
432: PHP_FALIAS(fbird_service_detach, ibase_service_detach, arginfo_ibase_service_detach)
433: PHP_FALIAS(fbird_backup, ibase_backup, arginfo_ibase_backup)
434: PHP_FALIAS(fbird_restore, ibase_restore, arginfo_ibase_restore)
435: PHP_FALIAS(fbird_maintain_db, ibase_maintain_db, arginfo_ibase_maintain_db)
436: PHP_FALIAS(fbird_db_info, ibase_db_info, arginfo_ibase_db_info)
437: PHP_FALIAS(fbird_server_info, ibase_server_info, arginfo_ibase_server_info)
438:
439: PHP_FALIAS(fbird_wait_event, ibase_wait_event, arginfo_ibase_wait_event)
440: PHP_FALIAS(fbird_set_event_handler, ibase_set_event_handler, arginfo_ibase_set_event_handler)
441: PHP_FALIAS(fbird_free_event_handler, ibase_free_event_handler, arginfo_ibase_free_event_handler)
442: PHP_FE_END
443: };
444:
445: zend_module_entry ibase_module_entry = {
446: STANDARD_MODULE_HEADER,
447: "interbase",
448: ibase_functions,
449: PHP_MINIT(ibase),
450: PHP_MSHUTDOWN(ibase),
451: NULL,
452: PHP_RSHUTDOWN(ibase),
453: PHP_MINFO(ibase),
454: NO_VERSION_YET,
455: PHP_MODULE_GLOBALS(ibase),
456: PHP_GINIT(ibase),
457: NULL,
458: NULL,
459: STANDARD_MODULE_PROPERTIES_EX
460: };
461:
462: #ifdef COMPILE_DL_INTERBASE
463: ZEND_GET_MODULE(ibase)
464: #endif
465:
466: /* True globals, no need for thread safety */
467: int le_link, le_plink, le_trans;
468:
469: /* }}} */
470:
471: /* error handling ---------------------------- */
472:
473: /* {{{ proto string ibase_errmsg(void)
474: Return error message */
475: PHP_FUNCTION(ibase_errmsg)
476: {
477: if (zend_parse_parameters_none() == FAILURE) {
478: return;
479: }
480:
481: if (IBG(sql_code) != 0) {
482: RETURN_STRING(IBG(errmsg), 1);
483: }
484:
485: RETURN_FALSE;
486: }
487: /* }}} */
488:
489: /* {{{ proto int ibase_errcode(void)
490: Return error code */
491: PHP_FUNCTION(ibase_errcode)
492: {
493: if (zend_parse_parameters_none() == FAILURE) {
494: return;
495: }
496:
497: if (IBG(sql_code) != 0) {
498: RETURN_LONG(IBG(sql_code));
499: }
500: RETURN_FALSE;
501: }
502: /* }}} */
503:
504: /* print interbase error and save it for ibase_errmsg() */
505: void _php_ibase_error(TSRMLS_D) /* {{{ */
506: {
507: char *s = IBG(errmsg);
508: ISC_STATUS *statusp = IB_STATUS;
509:
510: IBG(sql_code) = isc_sqlcode(IB_STATUS);
511:
512: while ((s - IBG(errmsg)) < MAX_ERRMSG - (IBASE_MSGSIZE + 2) && isc_interprete(s, &statusp)) {
513: strcat(IBG(errmsg), " ");
514: s = IBG(errmsg) + strlen(IBG(errmsg));
515: }
516:
517: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg));
518: }
519: /* }}} */
520:
521: /* print php interbase module error and save it for ibase_errmsg() */
522: void _php_ibase_module_error(char *msg TSRMLS_DC, ...) /* {{{ */
523: {
524: va_list ap;
525:
526: #ifdef ZTS
527: va_start(ap, TSRMLS_C);
528: #else
529: va_start(ap, msg);
530: #endif
531:
532: /* vsnprintf NUL terminates the buf and writes at most n-1 chars+NUL */
533: vsnprintf(IBG(errmsg), MAX_ERRMSG, msg, ap);
534: va_end(ap);
535:
536: IBG(sql_code) = -999; /* no SQL error */
537:
538: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", IBG(errmsg));
539: }
540: /* }}} */
541:
542: /* {{{ internal macros, functions and structures */
543: typedef struct {
544: isc_db_handle *db_ptr;
545: long tpb_len;
546: char *tpb_ptr;
547: } ISC_TEB;
548:
549: /* }}} */
550:
551: /* Fill ib_link and trans with the correct database link and transaction. */
552: void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */
553: zval **link_id, ibase_db_link **ib_link, ibase_trans **trans)
554: {
555: int type;
556:
557: IBDEBUG("Transaction or database link?");
558: if (zend_list_find(Z_LVAL_PP(link_id), &type)) {
559: if (type == le_trans) {
560: /* Transaction resource: make sure it refers to one link only, then
561: fetch it; database link is stored in ib_trans->db_link[]. */
562: IBDEBUG("Type is le_trans");
563: ZEND_FETCH_RESOURCE(*trans, ibase_trans *, link_id, -1, LE_TRANS, le_trans);
564: if ((*trans)->link_cnt > 1) {
565: _php_ibase_module_error("Link id is ambiguous: transaction spans multiple connections."
566: TSRMLS_CC);
567: return;
568: }
569: *ib_link = (*trans)->db_link[0];
570: return;
571: }
572: }
573: IBDEBUG("Type is le_[p]link or id not found");
574: /* Database link resource, use default transaction. */
575: *trans = NULL;
576: ZEND_FETCH_RESOURCE2(*ib_link, ibase_db_link *, link_id, -1, LE_LINK, le_link, le_plink);
577: }
578: /* }}} */
579:
580: /* destructors ---------------------- */
581:
582: static void _php_ibase_commit_link(ibase_db_link *link TSRMLS_DC) /* {{{ */
583: {
584: unsigned short i = 0, j;
585: ibase_tr_list *l;
586: ibase_event *e;
587: IBDEBUG("Checking transactions to close...");
588:
589: for (l = link->tr_list; l != NULL; ++i) {
590: ibase_tr_list *p = l;
591: if (p->trans != NULL) {
592: if (i == 0) {
593: if (p->trans->handle != NULL) {
594: IBDEBUG("Committing default transaction...");
595: if (isc_commit_transaction(IB_STATUS, &p->trans->handle)) {
596: _php_ibase_error(TSRMLS_C);
597: }
598: }
599: efree(p->trans); /* default transaction is not a registered resource: clean up */
600: } else {
601: if (p->trans->handle != NULL) {
602: /* non-default trans might have been rolled back by other call of this dtor */
603: IBDEBUG("Rolling back other transactions...");
604: if (isc_rollback_transaction(IB_STATUS, &p->trans->handle)) {
605: _php_ibase_error(TSRMLS_C);
606: }
607: }
608: /* set this link pointer to NULL in the transaction */
609: for (j = 0; j < p->trans->link_cnt; ++j) {
610: if (p->trans->db_link[j] == link) {
611: p->trans->db_link[j] = NULL;
612: break;
613: }
614: }
615: }
616: }
617: l = l->next;
618: efree(p);
619: }
620: link->tr_list = NULL;
621:
622: for (e = link->event_head; e; e = e->event_next) {
623: _php_ibase_free_event(e TSRMLS_CC);
624: e->link = NULL;
625: }
626: }
627:
628: /* }}} */
629:
630: static void php_ibase_commit_link_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
631: {
632: ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
633:
634: _php_ibase_commit_link(link TSRMLS_CC);
635: }
636: /* }}} */
637:
638: static void _php_ibase_close_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
639: {
640: ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
641:
642: _php_ibase_commit_link(link TSRMLS_CC);
643: if (link->handle != NULL) {
644: IBDEBUG("Closing normal link...");
645: isc_detach_database(IB_STATUS, &link->handle);
646: }
647: IBG(num_links)--;
648: efree(link);
649: }
650: /* }}} */
651:
652: static void _php_ibase_close_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
653: {
654: ibase_db_link *link = (ibase_db_link *) rsrc->ptr;
655:
656: _php_ibase_commit_link(link TSRMLS_CC);
657: IBDEBUG("Closing permanent link...");
658: if (link->handle != NULL) {
659: isc_detach_database(IB_STATUS, &link->handle);
660: }
661: IBG(num_persistent)--;
662: IBG(num_links)--;
663: free(link);
664: }
665: /* }}} */
666:
667: static void _php_ibase_free_trans(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
668: {
669: ibase_trans *trans = (ibase_trans *)rsrc->ptr;
670: unsigned short i;
671:
672: IBDEBUG("Cleaning up transaction resource...");
673: if (trans->handle != NULL) {
674: IBDEBUG("Rolling back unhandled transaction...");
675: if (isc_rollback_transaction(IB_STATUS, &trans->handle)) {
676: _php_ibase_error(TSRMLS_C);
677: }
678: }
679:
680: /* now remove this transaction from all the connection-transaction lists */
681: for (i = 0; i < trans->link_cnt; ++i) {
682: if (trans->db_link[i] != NULL) {
683: ibase_tr_list **l;
684: for (l = &trans->db_link[i]->tr_list; *l != NULL; l = &(*l)->next) {
685: if ( (*l)->trans == trans) {
686: ibase_tr_list *p = *l;
687: *l = p->next;
688: efree(p);
689: break;
690: }
691: }
692: }
693: }
694: efree(trans);
695: }
696: /* }}} */
697:
698: /* TODO this function should be part of either Zend or PHP API */
699: static PHP_INI_DISP(php_ibase_password_displayer_cb)
700: {
701: TSRMLS_FETCH();
702:
703: if ((type == PHP_INI_DISPLAY_ORIG && ini_entry->orig_value)
704: || (type == PHP_INI_DISPLAY_ACTIVE && ini_entry->value)) {
705: PUTS("********");
706: } else if (!sapi_module.phpinfo_as_text) {
707: PUTS("<i>no value</i>");
708: } else {
709: PUTS("no value");
710: }
711: }
712:
713: /* {{{ startup, shutdown and info functions */
714: PHP_INI_BEGIN()
715: PHP_INI_ENTRY_EX("ibase.allow_persistent", "1", PHP_INI_SYSTEM, NULL, zend_ini_boolean_displayer_cb)
716: PHP_INI_ENTRY_EX("ibase.max_persistent", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers)
717: PHP_INI_ENTRY_EX("ibase.max_links", "-1", PHP_INI_SYSTEM, NULL, display_link_numbers)
718: PHP_INI_ENTRY("ibase.default_db", NULL, PHP_INI_SYSTEM, NULL)
719: PHP_INI_ENTRY("ibase.default_user", NULL, PHP_INI_ALL, NULL)
720: PHP_INI_ENTRY_EX("ibase.default_password", NULL, PHP_INI_ALL, NULL, php_ibase_password_displayer_cb)
721: PHP_INI_ENTRY("ibase.default_charset", NULL, PHP_INI_ALL, NULL)
722: PHP_INI_ENTRY("ibase.timestampformat", IB_DEF_DATE_FMT " " IB_DEF_TIME_FMT, PHP_INI_ALL, NULL)
723: PHP_INI_ENTRY("ibase.dateformat", IB_DEF_DATE_FMT, PHP_INI_ALL, NULL)
724: PHP_INI_ENTRY("ibase.timeformat", IB_DEF_TIME_FMT, PHP_INI_ALL, NULL)
725: PHP_INI_END()
726:
727: static PHP_GINIT_FUNCTION(ibase)
728: {
729: ibase_globals->num_persistent = ibase_globals->num_links = 0;
730: ibase_globals->sql_code = *ibase_globals->errmsg = 0;
731: ibase_globals->default_link = -1;
732: }
733:
734: PHP_MINIT_FUNCTION(ibase)
735: {
736: REGISTER_INI_ENTRIES();
737:
738: le_link = zend_register_list_destructors_ex(_php_ibase_close_link, NULL, LE_LINK, module_number);
739: le_plink = zend_register_list_destructors_ex(php_ibase_commit_link_rsrc, _php_ibase_close_plink, LE_PLINK, module_number);
740: le_trans = zend_register_list_destructors_ex(_php_ibase_free_trans, NULL, LE_TRANS, module_number);
741:
742: REGISTER_LONG_CONSTANT("IBASE_DEFAULT", PHP_IBASE_DEFAULT, CONST_PERSISTENT);
743: REGISTER_LONG_CONSTANT("IBASE_CREATE", PHP_IBASE_CREATE, CONST_PERSISTENT);
744: REGISTER_LONG_CONSTANT("IBASE_TEXT", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT); /* deprecated, for BC only */
745: REGISTER_LONG_CONSTANT("IBASE_FETCH_BLOBS", PHP_IBASE_FETCH_BLOBS, CONST_PERSISTENT);
746: REGISTER_LONG_CONSTANT("IBASE_FETCH_ARRAYS", PHP_IBASE_FETCH_ARRAYS, CONST_PERSISTENT);
747: REGISTER_LONG_CONSTANT("IBASE_UNIXTIME", PHP_IBASE_UNIXTIME, CONST_PERSISTENT);
748:
749: /* transactions */
750: REGISTER_LONG_CONSTANT("IBASE_WRITE", PHP_IBASE_WRITE, CONST_PERSISTENT);
751: REGISTER_LONG_CONSTANT("IBASE_READ", PHP_IBASE_READ, CONST_PERSISTENT);
752: REGISTER_LONG_CONSTANT("IBASE_COMMITTED", PHP_IBASE_COMMITTED, CONST_PERSISTENT);
753: REGISTER_LONG_CONSTANT("IBASE_CONSISTENCY", PHP_IBASE_CONSISTENCY, CONST_PERSISTENT);
754: REGISTER_LONG_CONSTANT("IBASE_CONCURRENCY", PHP_IBASE_CONCURRENCY, CONST_PERSISTENT);
755: REGISTER_LONG_CONSTANT("IBASE_REC_VERSION", PHP_IBASE_REC_VERSION, CONST_PERSISTENT);
756: REGISTER_LONG_CONSTANT("IBASE_REC_NO_VERSION", PHP_IBASE_REC_NO_VERSION, CONST_PERSISTENT);
757: REGISTER_LONG_CONSTANT("IBASE_NOWAIT", PHP_IBASE_NOWAIT, CONST_PERSISTENT);
758: REGISTER_LONG_CONSTANT("IBASE_WAIT", PHP_IBASE_WAIT, CONST_PERSISTENT);
759:
760: php_ibase_query_minit(INIT_FUNC_ARGS_PASSTHRU);
761: php_ibase_blobs_minit(INIT_FUNC_ARGS_PASSTHRU);
762: php_ibase_events_minit(INIT_FUNC_ARGS_PASSTHRU);
763: php_ibase_service_minit(INIT_FUNC_ARGS_PASSTHRU);
764:
765: return SUCCESS;
766: }
767:
768: PHP_MSHUTDOWN_FUNCTION(ibase)
769: {
770: #ifndef PHP_WIN32
771: /**
772: * When the Interbase client API library libgds.so is first loaded, it registers a call to
773: * gds__cleanup() with atexit(), in order to clean up after itself when the process exits.
774: * This means that the library is called at process shutdown, and cannot be unloaded beforehand.
775: * PHP tries to unload modules after every request [dl()'ed modules], and right before the
776: * process shuts down [modules loaded from php.ini]. This results in a segfault for this module.
777: * By NULLing the dlopen() handle in the module entry, Zend omits the call to dlclose(),
778: * ensuring that the module will remain present until the process exits. However, the functions
779: * and classes exported by the module will not be available until the module is 'reloaded'.
780: * When reloaded, dlopen() will return the handle of the already loaded module. The module will
781: * be unloaded automatically when the process exits.
782: */
783: zend_module_entry *ibase_entry;
784: if (SUCCESS == zend_hash_find(&module_registry, ibase_module_entry.name,
785: strlen(ibase_module_entry.name) +1, (void*) &ibase_entry)) {
786: ibase_entry->handle = NULL;
787: }
788: #endif
789: UNREGISTER_INI_ENTRIES();
790: return SUCCESS;
791: }
792:
793: PHP_RSHUTDOWN_FUNCTION(ibase)
794: {
795: IBG(num_links) = IBG(num_persistent);
796: IBG(default_link)= -1;
797:
798: RESET_ERRMSG;
799:
800: return SUCCESS;
801: }
802:
803: PHP_MINFO_FUNCTION(ibase)
804: {
805: char tmp[64], *s;
806:
807: php_info_print_table_start();
808: php_info_print_table_row(2, "Firebird/InterBase Support",
809: #ifdef COMPILE_DL_INTERBASE
810: "dynamic");
811: #else
812: "static");
813: #endif
814:
815: #ifdef FB_API_VER
816: snprintf( (s = tmp), sizeof(tmp), "Firebird API version %d", FB_API_VER);
817: #elif (SQLDA_CURRENT_VERSION > 1)
818: s = "Interbase 7.0 and up";
819: #elif !defined(DSC_null)
820: s = "Interbase 6";
821: #else
822: s = "Firebird 1.0";
823: #endif
824: php_info_print_table_row(2, "Compile-time Client Library Version", s);
825:
826: #if defined(__GNUC__) || defined(PHP_WIN32)
827: do {
828: info_func_t info_func = NULL;
829: #ifdef __GNUC__
830: info_func = (info_func_t)dlsym(RTLD_DEFAULT, "isc_get_client_version");
831: #else
832: HMODULE l = GetModuleHandle("fbclient");
833:
834: if (!l && !(l = GetModuleHandle("gds32"))) {
835: break;
836: }
837: info_func = (info_func_t)GetProcAddress(l, "isc_get_client_version");
838: #endif
839: if (info_func) {
840: info_func(s = tmp);
841: } else {
842: s = "Firebird 1.0/Interbase 6";
843: }
844: php_info_print_table_row(2, "Run-time Client Library Version", s);
845: } while (0);
846: #endif
847: php_info_print_table_end();
848:
849: DISPLAY_INI_ENTRIES();
850:
851: }
852: /* }}} */
853:
854: enum connect_args { DB = 0, USER = 1, PASS = 2, CSET = 3, ROLE = 4, BUF = 0, DLECT = 1, SYNC = 2 };
855:
856: static char const dpb_args[] = {
857: 0, isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name, 0
858: };
859:
860: int _php_ibase_attach_db(char **args, int *len, long *largs, isc_db_handle *db TSRMLS_DC)
861: {
862: short i, dpb_len, buf_len = 257-2; /* version byte at the front, and a null at the end */
863: char dpb_buffer[257] = { isc_dpb_version1, 0 }, *dpb;
864:
865: dpb = dpb_buffer + 1;
866:
867: for (i = 0; i < sizeof(dpb_args); ++i) {
868: if (dpb_args[i] && args[i] && len[i] && buf_len > 0) {
869: dpb_len = slprintf(dpb, buf_len, "%c%c%s", dpb_args[i],(unsigned char)len[i],args[i]);
870: dpb += dpb_len;
871: buf_len -= dpb_len;
872: }
873: }
874: if (largs[BUF] && buf_len > 0) {
875: dpb_len = slprintf(dpb, buf_len, "%c\2%c%c", isc_dpb_num_buffers,
876: (char)(largs[BUF] >> 8), (char)(largs[BUF] & 0xff));
877: dpb += dpb_len;
878: buf_len -= dpb_len;
879: }
880: if (largs[SYNC] && buf_len > 0) {
881: dpb_len = slprintf(dpb, buf_len, "%c\1%c", isc_dpb_force_write, largs[SYNC] == isc_spb_prp_wm_sync ? 1 : 0);
882: dpb += dpb_len;
883: buf_len -= dpb_len;
884: }
885: if (isc_attach_database(IB_STATUS, (short)len[DB], args[DB], db, (short)(dpb-dpb_buffer), dpb_buffer)) {
886: _php_ibase_error(TSRMLS_C);
887: return FAILURE;
888: }
889: return SUCCESS;
890: }
891: /* }}} */
892:
893: static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* {{{ */
894: {
895: char *c, hash[16], *args[] = { NULL, NULL, NULL, NULL, NULL };
896: int i, len[] = { 0, 0, 0, 0, 0 };
897: long largs[] = { 0, 0, 0 };
898: PHP_MD5_CTX hash_context;
899: zend_rsrc_list_entry new_index_ptr, *le;
900: isc_db_handle db_handle = NULL;
901: ibase_db_link *ib_link;
902:
903: RESET_ERRMSG;
904:
905: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ssssllsl",
906: &args[DB], &len[DB], &args[USER], &len[USER], &args[PASS], &len[PASS],
907: &args[CSET], &len[CSET], &largs[BUF], &largs[DLECT], &args[ROLE], &len[ROLE],
908: &largs[SYNC])) {
909: RETURN_FALSE;
910: }
911:
912: /* restrict to the server/db in the .ini if in safe mode */
913: if ((!len[DB] || PG(sql_safe_mode)) && (c = INI_STR("ibase.default_db"))) {
914: args[DB] = c;
915: len[DB] = strlen(c);
916: }
917: if (!len[USER] && (c = INI_STR("ibase.default_user"))) {
918: args[USER] = c;
919: len[USER] = strlen(c);
920: }
921: if (!len[PASS] && (c = INI_STR("ibase.default_password"))) {
922: args[PASS] = c;
923: len[PASS] = strlen(c);
924: }
925: if (!len[CSET] && (c = INI_STR("ibase.default_charset"))) {
926: args[CSET] = c;
927: len[CSET] = strlen(c);
928: }
929:
930: /* don't want usernames and passwords floating around */
931: PHP_MD5Init(&hash_context);
932: for (i = 0; i < sizeof(args)/sizeof(char*); ++i) {
933: PHP_MD5Update(&hash_context,args[i],len[i]);
934: }
935: for (i = 0; i < sizeof(largs)/sizeof(long); ++i) {
936: PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(long));
937: }
938: PHP_MD5Final(hash, &hash_context);
939:
940: /* try to reuse a connection */
941: if (SUCCESS == zend_hash_find(&EG(regular_list), hash, sizeof(hash), (void *) &le)) {
942: long xlink;
943: int type;
944:
945: if (Z_TYPE_P(le) != le_index_ptr) {
946: RETURN_FALSE;
947: }
948:
949: xlink = (long) le->ptr;
950: if (zend_list_find(xlink, &type) && ((!persistent && type == le_link) || type == le_plink)) {
951: zend_list_addref(xlink);
952: RETURN_RESOURCE(IBG(default_link) = xlink);
953: } else {
954: zend_hash_del(&EG(regular_list), hash, sizeof(hash));
955: }
956: }
957:
958: /* ... or a persistent one */
959: switch (zend_hash_find(&EG(persistent_list), hash, sizeof(hash), (void *) &le)) {
960: long l;
961:
962: static char info[] = { isc_info_base_level, isc_info_end };
963: char result[8];
964: ISC_STATUS status[20];
965:
966: case SUCCESS:
967:
968: if (Z_TYPE_P(le) != le_plink) {
969: RETURN_FALSE;
970: }
971: /* check if connection has timed out */
972: ib_link = (ibase_db_link *) le->ptr;
973: if (!isc_database_info(status, &ib_link->handle, sizeof(info), info, sizeof(result), result)) {
974: ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink);
975: break;
976: }
977: zend_hash_del(&EG(persistent_list), hash, sizeof(hash));
978:
979: default:
980:
981: /* no link found, so we have to open one */
982:
983: if ((l = INI_INT("ibase.max_links")) != -1 && IBG(num_links) >= l) {
984: _php_ibase_module_error("Too many open links (%ld)" TSRMLS_CC, IBG(num_links));
985: RETURN_FALSE;
986: }
987:
988: /* create the ib_link */
989: if (FAILURE == _php_ibase_attach_db(args, len, largs, &db_handle TSRMLS_CC)) {
990: RETURN_FALSE;
991: }
992:
993: /* use non-persistent if allowed number of persistent links is exceeded */
994: if (!persistent || ((l = INI_INT("ibase.max_persistent") != -1) && IBG(num_persistent) >= l)) {
995: ib_link = (ibase_db_link *) emalloc(sizeof(ibase_db_link));
996: ZEND_REGISTER_RESOURCE(return_value, ib_link, le_link);
997: } else {
998: zend_rsrc_list_entry new_le;
999:
1000: ib_link = (ibase_db_link *) malloc(sizeof(ibase_db_link));
1001: if (!ib_link) {
1002: RETURN_FALSE;
1003: }
1004:
1005: /* hash it up */
1006: Z_TYPE(new_le) = le_plink;
1007: new_le.ptr = ib_link;
1008: if (FAILURE == zend_hash_update(&EG(persistent_list), hash, sizeof(hash),
1009: (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)) {
1010: free(ib_link);
1011: RETURN_FALSE;
1012: }
1013: ZEND_REGISTER_RESOURCE(return_value, ib_link, le_plink);
1014: ++IBG(num_persistent);
1015: }
1016: ib_link->handle = db_handle;
1017: ib_link->dialect = largs[DLECT] ? (unsigned short)largs[DLECT] : SQL_DIALECT_CURRENT;
1018: ib_link->tr_list = NULL;
1019: ib_link->event_head = NULL;
1020:
1021: ++IBG(num_links);
1022: }
1023:
1024: /* add it to the hash */
1025: new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
1026: Z_TYPE(new_index_ptr) = le_index_ptr;
1027: if (FAILURE == zend_hash_update(&EG(regular_list), hash, sizeof(hash),
1028: (void *) &new_index_ptr, sizeof(zend_rsrc_list_entry), NULL)) {
1029: RETURN_FALSE;
1030: }
1031: zend_list_addref(IBG(default_link) = Z_LVAL_P(return_value));
1032: }
1033: /* }}} */
1034:
1035: /* {{{ proto resource ibase_connect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]])
1036: Open a connection to an InterBase database */
1037: PHP_FUNCTION(ibase_connect)
1038: {
1039: _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1040: }
1041: /* }}} */
1042:
1043: /* {{{ proto resource ibase_pconnect(string database [, string username [, string password [, string charset [, int buffers [, int dialect [, string role]]]]]])
1044: Open a persistent connection to an InterBase database */
1045: PHP_FUNCTION(ibase_pconnect)
1046: {
1047: _php_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INI_INT("ibase.allow_persistent"));
1048: }
1049: /* }}} */
1050:
1051: /* {{{ proto bool ibase_close([resource link_identifier])
1052: Close an InterBase connection */
1053: PHP_FUNCTION(ibase_close)
1054: {
1055: zval *link_arg = NULL;
1056: ibase_db_link *ib_link;
1057: int link_id;
1058:
1059: RESET_ERRMSG;
1060:
1061: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link_arg) == FAILURE) {
1062: return;
1063: }
1064:
1065: if (ZEND_NUM_ARGS() == 0) {
1066: link_id = IBG(default_link);
1067: CHECK_LINK(link_id);
1068: IBG(default_link) = -1;
1069: } else {
1070: link_id = Z_RESVAL_P(link_arg);
1071: }
1072:
1073: ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, link_id, LE_LINK, le_link, le_plink);
1074: zend_list_delete(link_id);
1075: RETURN_TRUE;
1076: }
1077: /* }}} */
1078:
1079: /* {{{ proto bool ibase_drop_db([resource link_identifier])
1080: Drop an InterBase database */
1081: PHP_FUNCTION(ibase_drop_db)
1082: {
1083: zval *link_arg = NULL;
1084: ibase_db_link *ib_link;
1085: ibase_tr_list *l;
1086: int link_id;
1087:
1088: RESET_ERRMSG;
1089:
1090: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link_arg) == FAILURE) {
1091: return;
1092: }
1093:
1094: if (ZEND_NUM_ARGS() == 0) {
1095: link_id = IBG(default_link);
1096: CHECK_LINK(link_id);
1097: IBG(default_link) = -1;
1098: } else {
1099: link_id = Z_RESVAL_P(link_arg);
1100: }
1101:
1102: ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &link_arg, link_id, LE_LINK, le_link, le_plink);
1103:
1104: if (isc_drop_database(IB_STATUS, &ib_link->handle)) {
1105: _php_ibase_error(TSRMLS_C);
1106: RETURN_FALSE;
1107: }
1108:
1109: /* isc_drop_database() doesn't invalidate the transaction handles */
1110: for (l = ib_link->tr_list; l != NULL; l = l->next) {
1111: if (l->trans != NULL) l->trans->handle = NULL;
1112: }
1113:
1114: zend_list_delete(link_id);
1115: RETURN_TRUE;
1116: }
1117: /* }}} */
1118:
1119: /* {{{ proto resource ibase_trans([int trans_args [, resource link_identifier [, ... ], int trans_args [, resource link_identifier [, ... ]] [, ...]]])
1120: Start a transaction over one or several databases */
1121:
1122: #define TPB_MAX_SIZE (8*sizeof(char))
1123:
1124: PHP_FUNCTION(ibase_trans)
1125: {
1.1.1.2 misho 1126: unsigned short i, link_cnt = 0, tpb_len = 0;
1127: int argn;
1.1 misho 1128: char last_tpb[TPB_MAX_SIZE];
1129: ibase_db_link **ib_link = NULL;
1130: ibase_trans *ib_trans;
1131: isc_tr_handle tr_handle = NULL;
1132: ISC_STATUS result;
1133:
1134: RESET_ERRMSG;
1135:
1136: argn = ZEND_NUM_ARGS();
1137:
1138: /* (1+argn) is an upper bound for the number of links this trans connects to */
1139: ib_link = (ibase_db_link **) safe_emalloc(sizeof(ibase_db_link *),1+argn,0);
1140:
1141: if (argn > 0) {
1142: long trans_argl = 0;
1143: char *tpb;
1144: ISC_TEB *teb;
1145: zval ***args = NULL;
1146:
1147: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argn) == FAILURE) {
1148: efree(args);
1149: efree(ib_link);
1150: RETURN_FALSE;
1151: }
1152:
1153: teb = (ISC_TEB *) safe_emalloc(sizeof(ISC_TEB),argn,0);
1154: tpb = (char *) safe_emalloc(TPB_MAX_SIZE,argn,0);
1155:
1156: /* enumerate all the arguments: assume every non-resource argument
1157: specifies modifiers for the link ids that follow it */
1158: for (i = 0; i < argn; ++i) {
1159:
1160: if (Z_TYPE_PP(args[i]) == IS_RESOURCE) {
1161:
1162: if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link[link_cnt], ibase_db_link *, args[i], -1, LE_LINK, le_link, le_plink)) {
1163: efree(teb);
1164: efree(tpb);
1165: efree(ib_link);
1166: efree(args);
1167: RETURN_FALSE;
1168: }
1169:
1170: /* copy the most recent modifier string into tbp[] */
1171: memcpy(&tpb[TPB_MAX_SIZE * link_cnt], last_tpb, TPB_MAX_SIZE);
1172:
1173: /* add a database handle to the TEB with the most recently specified set of modifiers */
1174: teb[link_cnt].db_ptr = &ib_link[link_cnt]->handle;
1175: teb[link_cnt].tpb_len = tpb_len;
1176: teb[link_cnt].tpb_ptr = &tpb[TPB_MAX_SIZE * link_cnt];
1177:
1178: ++link_cnt;
1179:
1180: } else {
1181:
1182: tpb_len = 0;
1183:
1184: convert_to_long_ex(args[i]);
1185: trans_argl = Z_LVAL_PP(args[i]);
1186:
1187: if (trans_argl != PHP_IBASE_DEFAULT) {
1188: last_tpb[tpb_len++] = isc_tpb_version3;
1189:
1190: /* access mode */
1191: if (PHP_IBASE_READ == (trans_argl & PHP_IBASE_READ)) {
1192: last_tpb[tpb_len++] = isc_tpb_read;
1193: } else if (PHP_IBASE_WRITE == (trans_argl & PHP_IBASE_WRITE)) {
1194: last_tpb[tpb_len++] = isc_tpb_write;
1195: }
1196:
1197: /* isolation level */
1198: if (PHP_IBASE_COMMITTED == (trans_argl & PHP_IBASE_COMMITTED)) {
1199: last_tpb[tpb_len++] = isc_tpb_read_committed;
1200: if (PHP_IBASE_REC_VERSION == (trans_argl & PHP_IBASE_REC_VERSION)) {
1201: last_tpb[tpb_len++] = isc_tpb_rec_version;
1202: } else if (PHP_IBASE_REC_NO_VERSION == (trans_argl & PHP_IBASE_REC_NO_VERSION)) {
1203: last_tpb[tpb_len++] = isc_tpb_no_rec_version;
1204: }
1205: } else if (PHP_IBASE_CONSISTENCY == (trans_argl & PHP_IBASE_CONSISTENCY)) {
1206: last_tpb[tpb_len++] = isc_tpb_consistency;
1207: } else if (PHP_IBASE_CONCURRENCY == (trans_argl & PHP_IBASE_CONCURRENCY)) {
1208: last_tpb[tpb_len++] = isc_tpb_concurrency;
1209: }
1210:
1211: /* lock resolution */
1212: if (PHP_IBASE_NOWAIT == (trans_argl & PHP_IBASE_NOWAIT)) {
1213: last_tpb[tpb_len++] = isc_tpb_nowait;
1214: } else if (PHP_IBASE_WAIT == (trans_argl & PHP_IBASE_WAIT)) {
1215: last_tpb[tpb_len++] = isc_tpb_wait;
1216: }
1217: }
1218: }
1219: }
1220:
1221: if (link_cnt > 0) {
1222: result = isc_start_multiple(IB_STATUS, &tr_handle, link_cnt, teb);
1223: }
1224:
1225: efree(args);
1226: efree(tpb);
1227: efree(teb);
1228: }
1229:
1230: if (link_cnt == 0) {
1231: link_cnt = 1;
1232: if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link[0], ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink)) {
1233: efree(ib_link);
1234: RETURN_FALSE;
1235: }
1236: result = isc_start_transaction(IB_STATUS, &tr_handle, 1, &ib_link[0]->handle, tpb_len, last_tpb);
1237: }
1238:
1239: /* start the transaction */
1240: if (result) {
1241: _php_ibase_error(TSRMLS_C);
1242: efree(ib_link);
1243: RETURN_FALSE;
1244: }
1245:
1246: /* register the transaction in our own data structures */
1247: ib_trans = (ibase_trans *) safe_emalloc(link_cnt-1, sizeof(ibase_db_link *), sizeof(ibase_trans));
1248: ib_trans->handle = tr_handle;
1249: ib_trans->link_cnt = link_cnt;
1250: ib_trans->affected_rows = 0;
1251: for (i = 0; i < link_cnt; ++i) {
1252: ibase_tr_list **l;
1253: ib_trans->db_link[i] = ib_link[i];
1254:
1255: /* the first item in the connection-transaction list is reserved for the default transaction */
1256: if (ib_link[i]->tr_list == NULL) {
1257: ib_link[i]->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1258: ib_link[i]->tr_list->trans = NULL;
1259: ib_link[i]->tr_list->next = NULL;
1260: }
1261:
1262: /* link the transaction into the connection-transaction list */
1263: for (l = &ib_link[i]->tr_list; *l != NULL; l = &(*l)->next);
1264: *l = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1265: (*l)->trans = ib_trans;
1266: (*l)->next = NULL;
1267: }
1268: efree(ib_link);
1269: ZEND_REGISTER_RESOURCE(return_value, ib_trans, le_trans);
1270: }
1271: /* }}} */
1272:
1273: int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans TSRMLS_DC) /* {{{ */
1274: {
1275: if (ib_link == NULL) {
1276: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid database link");
1277: return FAILURE;
1278: }
1279:
1280: /* the first item in the connection-transaction list is reserved for the default transaction */
1281: if (ib_link->tr_list == NULL) {
1282: ib_link->tr_list = (ibase_tr_list *) emalloc(sizeof(ibase_tr_list));
1283: ib_link->tr_list->trans = NULL;
1284: ib_link->tr_list->next = NULL;
1285: }
1286:
1287: if (*trans == NULL) {
1288: ibase_trans *tr = ib_link->tr_list->trans;
1289:
1290: if (tr == NULL) {
1291: tr = (ibase_trans *) emalloc(sizeof(ibase_trans));
1292: tr->handle = NULL;
1293: tr->link_cnt = 1;
1294: tr->affected_rows = 0;
1295: tr->db_link[0] = ib_link;
1296: ib_link->tr_list->trans = tr;
1297: }
1298: if (tr->handle == NULL) {
1299: if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) {
1300: _php_ibase_error(TSRMLS_C);
1301: return FAILURE;
1302: }
1303: }
1304: *trans = tr;
1305: }
1306: return SUCCESS;
1307: }
1308: /* }}} */
1309:
1310: static void _php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS, int commit) /* {{{ */
1311: {
1312: ibase_trans *trans = NULL;
1313: int res_id = 0;
1314: ISC_STATUS result;
1315: ibase_db_link *ib_link;
1316: zval *arg = NULL;
1317: int type;
1318:
1319: RESET_ERRMSG;
1320:
1321: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg) == FAILURE) {
1322: return;
1323: }
1324:
1325: if (ZEND_NUM_ARGS() == 0) {
1326: ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), LE_LINK, le_link, le_plink);
1327: if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
1328: /* this link doesn't have a default transaction */
1329: _php_ibase_module_error("Default link has no default transaction" TSRMLS_CC);
1330: RETURN_FALSE;
1331: }
1332: trans = ib_link->tr_list->trans;
1333: } else {
1334: /* one id was passed, could be db or trans id */
1335: if (zend_list_find(Z_RESVAL_P(arg), &type) && type == le_trans) {
1336: ZEND_FETCH_RESOURCE(trans, ibase_trans *, &arg, -1, LE_TRANS, le_trans);
1337: res_id = Z_RESVAL_P(arg);
1338: } else {
1339: ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, &arg, -1, LE_LINK, le_link, le_plink);
1340:
1341: if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) {
1342: /* this link doesn't have a default transaction */
1343: _php_ibase_module_error("Link has no default transaction" TSRMLS_CC);
1344: RETURN_FALSE;
1345: }
1346: trans = ib_link->tr_list->trans;
1347: }
1348: }
1349:
1350: switch (commit) {
1351: default: /* == case ROLLBACK: */
1352: result = isc_rollback_transaction(IB_STATUS, &trans->handle);
1353: break;
1354: case COMMIT:
1355: result = isc_commit_transaction(IB_STATUS, &trans->handle);
1356: break;
1357: case (ROLLBACK | RETAIN):
1358: result = isc_rollback_retaining(IB_STATUS, &trans->handle);
1359: break;
1360: case (COMMIT | RETAIN):
1361: result = isc_commit_retaining(IB_STATUS, &trans->handle);
1362: break;
1363: }
1364:
1365: if (result) {
1366: _php_ibase_error(TSRMLS_C);
1367: RETURN_FALSE;
1368: }
1369:
1370: /* Don't try to destroy implicitly opened transaction from list... */
1371: if ((commit & RETAIN) == 0 && res_id != 0) {
1372: zend_list_delete(res_id);
1373: }
1374: RETURN_TRUE;
1375: }
1376: /* }}} */
1377:
1378: /* {{{ proto bool ibase_commit( resource link_identifier )
1379: Commit transaction */
1380: PHP_FUNCTION(ibase_commit)
1381: {
1382: _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT);
1383: }
1384: /* }}} */
1385:
1386: /* {{{ proto bool ibase_rollback( resource link_identifier )
1387: Rollback transaction */
1388: PHP_FUNCTION(ibase_rollback)
1389: {
1390: _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK);
1391: }
1392: /* }}} */
1393:
1394: /* {{{ proto bool ibase_commit_ret( resource link_identifier )
1395: Commit transaction and retain the transaction context */
1396: PHP_FUNCTION(ibase_commit_ret)
1397: {
1398: _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, COMMIT | RETAIN);
1399: }
1400: /* }}} */
1401:
1402: /* {{{ proto bool ibase_rollback_ret( resource link_identifier )
1403: Rollback transaction and retain the transaction context */
1404: PHP_FUNCTION(ibase_rollback_ret)
1405: {
1406: _php_ibase_trans_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, ROLLBACK | RETAIN);
1407: }
1408: /* }}} */
1409:
1410: /* {{{ proto int ibase_gen_id(string generator [, int increment [, resource link_identifier ]])
1411: Increments the named generator and returns its new value */
1412: PHP_FUNCTION(ibase_gen_id)
1413: {
1414: zval *link = NULL;
1415: char query[128], *generator;
1416: int gen_len;
1417: long inc = 1;
1418: ibase_db_link *ib_link;
1419: ibase_trans *trans = NULL;
1420: XSQLDA out_sqlda;
1421: ISC_INT64 result;
1422:
1423: RESET_ERRMSG;
1424:
1425: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &generator, &gen_len,
1426: &inc, &link)) {
1427: RETURN_FALSE;
1428: }
1429:
1430: if (gen_len > 31) {
1431: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid generator name");
1432: RETURN_FALSE;
1433: }
1434:
1435: PHP_IBASE_LINK_TRANS(link, ib_link, trans);
1436:
1437: snprintf(query, sizeof(query), "SELECT GEN_ID(%s,%ld) FROM rdb$database", generator, inc);
1438:
1439: /* allocate a minimal descriptor area */
1440: out_sqlda.sqln = out_sqlda.sqld = 1;
1441: out_sqlda.version = SQLDA_CURRENT_VERSION;
1442:
1443: /* allocate the field for the result */
1444: out_sqlda.sqlvar[0].sqltype = SQL_INT64;
1445: out_sqlda.sqlvar[0].sqlscale = 0;
1446: out_sqlda.sqlvar[0].sqllen = sizeof(result);
1447: out_sqlda.sqlvar[0].sqldata = (void*) &result;
1448:
1449: /* execute the query */
1450: if (isc_dsql_exec_immed2(IB_STATUS, &ib_link->handle, &trans->handle, 0, query,
1451: SQL_DIALECT_CURRENT, NULL, &out_sqlda)) {
1452: _php_ibase_error(TSRMLS_C);
1453: RETURN_FALSE;
1454: }
1455:
1456: /* don't return the generator value as a string unless it doesn't fit in a long */
1457: #if SIZEOF_LONG < 8
1458: if (result < LONG_MIN || result > LONG_MAX) {
1459: char *res;
1460: int l;
1461:
1462: l = spprintf(&res, 0, "%" LL_MASK "d", result);
1463: RETURN_STRINGL(res, l, 0);
1464: }
1465: #endif
1466: RETURN_LONG((long)result);
1467: }
1468:
1469: /* }}} */
1470:
1471: #endif /* HAVE_IBASE */
1472:
1473: /*
1474: * Local variables:
1475: * tab-width: 4
1476: * c-basic-offset: 4
1477: * End:
1478: * vim600: sw=4 ts=4 fdm=marker
1479: * vim<600: sw=4 ts=4
1480: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>