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