1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2014 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: Stig Sæther Bakken <ssb@php.net> |
16: | Thies C. Arntzen <thies@thieso.net> |
17: | Maxim Maletsky <maxim@maxim.cx> |
18: | |
19: | Collection support by Andy Sautins <asautins@veripost.net> |
20: | Temporary LOB support by David Benson <dbenson@mancala.com> |
21: | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
22: | |
23: | Redesigned by: Antony Dovgal <antony@zend.com> |
24: | Andi Gutmans <andi@zend.com> |
25: | Wez Furlong <wez@omniti.com> |
26: +----------------------------------------------------------------------+
27: */
28:
29: /* $Id: oci8.c,v 1.1.1.4 2014/06/15 20:03:52 misho Exp $ */
30:
31: #ifdef HAVE_CONFIG_H
32: #include "config.h"
33: #endif
34:
35: #include "php.h"
36: #include "ext/standard/info.h"
37: #include "php_ini.h"
38: #include "ext/standard/php_smart_str.h"
39:
40: #ifdef HAVE_STDINT_H
41: #include <stdint.h>
42: #endif
43: #ifdef PHP_WIN32
44: #include "win32/php_stdint.h"
45: #endif
46:
47: #if HAVE_OCI8
48:
49: #if PHP_MAJOR_VERSION > 5
50: #error This version of the PHP OCI8 extension is not compatible with PHP 6 or later
51: #elif PHP_MAJOR_VERSION < 5
52: #ifdef ZTS
53: #error The PHP OCI8 extension does not support ZTS mode in PHP 4
54: #endif
55: #endif
56:
57: #include "php_oci8.h"
58: #include "php_oci8_int.h"
59: #include "zend_hash.h"
60:
61: #if defined(HAVE_STDINT_H) || defined(PHP_WIN32)
62: #define OCI8_INT_TO_PTR(I) ((void *)(intptr_t)(I))
63: #define OCI8_PTR_TO_INT(P) ((int)(intptr_t)(P))
64: #else
65: #define OCI8_INT_TO_PTR(I) ((void *)(I))
66: #define OCI8_PTR_TO_INT(P) ((int)(P))
67: #endif
68:
69: ZEND_DECLARE_MODULE_GLOBALS(oci)
70: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
71: /* This "if" allows PECL builds from this file to be portable to older PHP releases */
72: static PHP_GINIT_FUNCTION(oci);
73: static PHP_GSHUTDOWN_FUNCTION(oci);
74: #endif
75:
76: /* Allow PHP 5.3 branch to be used in PECL for 5.x compatible builds */
77: #ifndef Z_ADDREF_P
78: #define Z_ADDREF_P(x) ZVAL_ADDREF(x)
79: #endif
80:
81: /* For a user friendly message about environment setup */
82: #if defined(PHP_WIN32)
83: #define PHP_OCI8_LIB_PATH_MSG "PATH"
84: #elif defined(__APPLE__)
85: #define PHP_OCI8_LIB_PATH_MSG "DYLD_LIBRARY_PATH"
86: #elif defined(_AIX)
87: #define PHP_OCI8_LIB_PATH_MSG "LIBPATH"
88: #elif defined(__hpux)
89: #define PHP_OCI8_LIB_PATH_MSG "SHLIB_PATH"
90: #else
91: #define PHP_OCI8_LIB_PATH_MSG "LD_LIBRARY_PATH"
92: #endif
93:
94: /* True globals, no need for thread safety */
95: int le_connection;
96: int le_pconnection;
97: int le_statement;
98: int le_descriptor;
99: int le_psessionpool;
100: int le_collection;
101:
102: zend_class_entry *oci_lob_class_entry_ptr;
103: zend_class_entry *oci_coll_class_entry_ptr;
104:
105: #ifndef SQLT_BFILEE
106: #define SQLT_BFILEE 114
107: #endif
108: #ifndef SQLT_CFILEE
109: #define SQLT_CFILEE 115
110: #endif
111:
112: #ifdef OCI_ERROR_MAXMSG_SIZE2
113: /* Bigger size is defined from 11.2.0.3 onwards */
114: #define PHP_OCI_ERRBUF_LEN OCI_ERROR_MAXMSG_SIZE2
115: #else
116: #define PHP_OCI_ERRBUF_LEN OCI_ERROR_MAXMSG_SIZE
117: #endif
118:
119: #if ZEND_MODULE_API_NO > 20020429
120: #define ONUPDATELONGFUNC OnUpdateLong
121: #else
122: #define ONUPDATELONGFUNC OnUpdateInt
123: #endif
124:
125: #ifdef ZTS
126: #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX)
127: #else
128: #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT)
129: #endif
130:
131: /* static protos {{{ */
132: static void php_oci_connection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
133: static void php_oci_pconnection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
134: static void php_oci_pconnection_list_np_dtor (zend_rsrc_list_entry * TSRMLS_DC);
135: static void php_oci_statement_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
136: static void php_oci_descriptor_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
137: static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC);
138: static void php_oci_collection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
139:
140: static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC);
141: static int php_oci_connection_ping(php_oci_connection * TSRMLS_DC);
142: static int php_oci_connection_status(php_oci_connection * TSRMLS_DC);
143: static int php_oci_connection_close(php_oci_connection * TSRMLS_DC);
144: static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC);
145:
146: static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC);
147: static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC);
148: static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC);
149: static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC);
150: static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC);
151: static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC);
152: /* }}} */
153:
154: /* {{{ dynamically loadable module stuff */
155: #if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G)
156: ZEND_GET_MODULE(oci8)
157: #endif /* COMPILE_DL */
158: /* }}} */
159:
160: #ifdef ZEND_ENGINE_2
161:
162: /* {{{ Function arginfo */
163: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_define_by_name, 0, 0, 3)
164: ZEND_ARG_INFO(0, statement_resource)
165: ZEND_ARG_INFO(0, column_name)
166: ZEND_ARG_INFO(1, variable)
167: ZEND_ARG_INFO(0, type)
168: ZEND_END_ARG_INFO()
169:
170: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_by_name, 0, 0, 3)
171: ZEND_ARG_INFO(0, statement_resource)
172: ZEND_ARG_INFO(0, column_name)
173: ZEND_ARG_INFO(1, variable)
174: ZEND_ARG_INFO(0, maximum_length)
175: ZEND_ARG_INFO(0, type)
176: ZEND_END_ARG_INFO()
177:
178: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_array_by_name, 0, 0, 4)
179: ZEND_ARG_INFO(0, statement_resource)
180: ZEND_ARG_INFO(0, column_name)
181: ZEND_ARG_INFO(1, variable)
182: ZEND_ARG_INFO(0, maximum_array_length)
183: ZEND_ARG_INFO(0, maximum_item_length)
184: ZEND_ARG_INFO(0, type)
185: ZEND_END_ARG_INFO()
186:
187: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_descriptor, 0, 0, 1)
188: ZEND_ARG_INFO(0, lob_descriptor)
189: ZEND_END_ARG_INFO()
190:
191: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save, 0, 0, 2)
192: ZEND_ARG_INFO(0, lob_descriptor)
193: ZEND_ARG_INFO(0, data)
194: ZEND_ARG_INFO(0, offset)
195: ZEND_END_ARG_INFO()
196:
197: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import, 0, 0, 2)
198: ZEND_ARG_INFO(0, lob_descriptor)
199: ZEND_ARG_INFO(0, filename)
200: ZEND_END_ARG_INFO()
201:
202: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_load, 0, 0, 1)
203: ZEND_ARG_INFO(0, lob_descriptor)
204: ZEND_END_ARG_INFO()
205:
206: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read, 0, 0, 2)
207: ZEND_ARG_INFO(0, lob_descriptor)
208: ZEND_ARG_INFO(0, length)
209: ZEND_END_ARG_INFO()
210:
211: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_eof, 0, 0, 1)
212: ZEND_ARG_INFO(0, lob_descriptor)
213: ZEND_END_ARG_INFO()
214:
215: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_tell, 0, 0, 1)
216: ZEND_ARG_INFO(0, lob_descriptor)
217: ZEND_END_ARG_INFO()
218:
219: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_rewind, 0, 0, 1)
220: ZEND_ARG_INFO(0, lob_descriptor)
221: ZEND_END_ARG_INFO()
222:
223: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek, 0, 0, 2)
224: ZEND_ARG_INFO(0, lob_descriptor)
225: ZEND_ARG_INFO(0, offset)
226: ZEND_ARG_INFO(0, whence)
227: ZEND_END_ARG_INFO()
228:
229: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_size, 0, 0, 1)
230: ZEND_ARG_INFO(0, lob_descriptor)
231: ZEND_END_ARG_INFO()
232:
233: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write, 0, 0, 2)
234: ZEND_ARG_INFO(0, lob_descriptor)
235: ZEND_ARG_INFO(0, string)
236: ZEND_ARG_INFO(0, length)
237: ZEND_END_ARG_INFO()
238:
239: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append, 0, 0, 2)
240: ZEND_ARG_INFO(0, lob_descriptor_to)
241: ZEND_ARG_INFO(0, lob_descriptor_from)
242: ZEND_END_ARG_INFO()
243:
244: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate, 0, 0, 1)
245: ZEND_ARG_INFO(0, lob_descriptor)
246: ZEND_ARG_INFO(0, length)
247: ZEND_END_ARG_INFO()
248:
249: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase, 0, 0, 1)
250: ZEND_ARG_INFO(0, lob_descriptor)
251: ZEND_ARG_INFO(0, offset)
252: ZEND_ARG_INFO(0, length)
253: ZEND_END_ARG_INFO()
254:
255: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush, 0, 0, 1)
256: ZEND_ARG_INFO(0, lob_descriptor)
257: ZEND_ARG_INFO(0, flag)
258: ZEND_END_ARG_INFO()
259:
260: ZEND_BEGIN_ARG_INFO_EX(arginfo_ocisetbufferinglob, 0, 0, 2)
261: ZEND_ARG_INFO(0, lob_descriptor)
262: ZEND_ARG_INFO(0, mode)
263: ZEND_END_ARG_INFO()
264:
265: ZEND_BEGIN_ARG_INFO_EX(arginfo_ocigetbufferinglob, 0, 0, 1)
266: ZEND_ARG_INFO(0, lob_descriptor)
267: ZEND_END_ARG_INFO()
268:
269: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_copy, 0, 0, 2)
270: ZEND_ARG_INFO(0, lob_descriptor_to)
271: ZEND_ARG_INFO(0, lob_descriptor_from)
272: ZEND_ARG_INFO(0, length)
273: ZEND_END_ARG_INFO()
274:
275: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_is_equal, 0, 0, 2)
276: ZEND_ARG_INFO(0, lob_descriptor)
277: ZEND_ARG_INFO(0, lob_descriptor)
278: ZEND_END_ARG_INFO()
279:
280: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export, 0, 0, 2)
281: ZEND_ARG_INFO(0, lob_descriptor)
282: ZEND_ARG_INFO(0, filename)
283: ZEND_ARG_INFO(0, start)
284: ZEND_ARG_INFO(0, length)
285: ZEND_END_ARG_INFO()
286:
287: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_descriptor, 0, 0, 1)
288: ZEND_ARG_INFO(0, connection_resource)
289: ZEND_ARG_INFO(0, type)
290: ZEND_END_ARG_INFO()
291:
292: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_rollback, 0, 0, 1)
293: ZEND_ARG_INFO(0, connection_resource)
294: ZEND_END_ARG_INFO()
295:
296: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_commit, 0, 0, 1)
297: ZEND_ARG_INFO(0, connection_resource)
298: ZEND_END_ARG_INFO()
299:
300: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_name, 0, 0, 2)
301: ZEND_ARG_INFO(0, statement_resource)
302: ZEND_ARG_INFO(0, column_number)
303: ZEND_END_ARG_INFO()
304:
305: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_size, 0, 0, 2)
306: ZEND_ARG_INFO(0, statement_resource)
307: ZEND_ARG_INFO(0, column_number_or_name)
308: ZEND_END_ARG_INFO()
309:
310: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_scale, 0, 0, 2)
311: ZEND_ARG_INFO(0, statement_resource)
312: ZEND_ARG_INFO(0, column_number)
313: ZEND_END_ARG_INFO()
314:
315: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_precision, 0, 0, 2)
316: ZEND_ARG_INFO(0, statement_resource)
317: ZEND_ARG_INFO(0, column_number)
318: ZEND_END_ARG_INFO()
319:
320: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type, 0, 0, 2)
321: ZEND_ARG_INFO(0, statement_resource)
322: ZEND_ARG_INFO(0, column_number)
323: ZEND_END_ARG_INFO()
324:
325: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type_raw, 0, 0, 2)
326: ZEND_ARG_INFO(0, statement_resource)
327: ZEND_ARG_INFO(0, column_number)
328: ZEND_END_ARG_INFO()
329:
330: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_is_null, 0, 0, 2)
331: ZEND_ARG_INFO(0, statement_resource)
332: ZEND_ARG_INFO(0, column_number_or_name)
333: ZEND_END_ARG_INFO()
334:
335: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_internal_debug, 0, 0, 1)
336: ZEND_ARG_INFO(0, mode)
337: ZEND_END_ARG_INFO()
338:
339: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_execute, 0, 0, 1)
340: ZEND_ARG_INFO(0, statement_resource)
341: ZEND_ARG_INFO(0, mode)
342: ZEND_END_ARG_INFO()
343:
344: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_cancel, 0, 0, 1)
345: ZEND_ARG_INFO(0, statement_resource)
346: ZEND_END_ARG_INFO()
347:
348: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch, 0, 0, 1)
349: ZEND_ARG_INFO(0, statement_resource)
350: ZEND_END_ARG_INFO()
351:
352: ZEND_BEGIN_ARG_INFO_EX(arginfo_ocifetchinto, 0, 0, 2)
353: ZEND_ARG_INFO(0, statement_resource)
354: ZEND_ARG_INFO(1, result)
355: ZEND_ARG_INFO(0, mode)
356: ZEND_END_ARG_INFO()
357:
358: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_all, 0, 0, 2)
359: ZEND_ARG_INFO(0, statement_resource)
360: ZEND_ARG_INFO(1, output)
361: ZEND_ARG_INFO(0, skip)
362: ZEND_ARG_INFO(0, maximum_rows)
363: ZEND_ARG_INFO(0, flags)
364: ZEND_END_ARG_INFO()
365:
366: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_object, 0, 0, 1)
367: ZEND_ARG_INFO(0, statement_resource)
368: ZEND_END_ARG_INFO()
369:
370: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_row, 0, 0, 1)
371: ZEND_ARG_INFO(0, statement_resource)
372: ZEND_END_ARG_INFO()
373:
374: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_assoc, 0, 0, 1)
375: ZEND_ARG_INFO(0, statement_resource)
376: ZEND_END_ARG_INFO()
377:
378: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_array, 0, 0, 1)
379: ZEND_ARG_INFO(0, statement_resource)
380: ZEND_ARG_INFO(0, mode)
381: ZEND_END_ARG_INFO()
382:
383: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_statement, 0, 0, 1)
384: ZEND_ARG_INFO(0, statement_resource)
385: ZEND_END_ARG_INFO()
386:
387: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_close, 0, 0, 1)
388: ZEND_ARG_INFO(0, connection_resource)
389: ZEND_END_ARG_INFO()
390:
391: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_connect, 0, 0, 2)
392: ZEND_ARG_INFO(0, username)
393: ZEND_ARG_INFO(0, password)
394: ZEND_ARG_INFO(0, connection_string)
395: ZEND_ARG_INFO(0, character_set)
396: ZEND_ARG_INFO(0, session_mode)
397: ZEND_END_ARG_INFO()
398:
399: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_connect, 0, 0, 2)
400: ZEND_ARG_INFO(0, username)
401: ZEND_ARG_INFO(0, password)
402: ZEND_ARG_INFO(0, connection_string)
403: ZEND_ARG_INFO(0, character_set)
404: ZEND_ARG_INFO(0, session_mode)
405: ZEND_END_ARG_INFO()
406:
407: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_pconnect, 0, 0, 2)
408: ZEND_ARG_INFO(0, username)
409: ZEND_ARG_INFO(0, password)
410: ZEND_ARG_INFO(0, connection_string)
411: ZEND_ARG_INFO(0, character_set)
412: ZEND_ARG_INFO(0, session_mode)
413: ZEND_END_ARG_INFO()
414:
415: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_error, 0, 0, 0)
416: ZEND_ARG_INFO(0, connection_or_statement_resource)
417: ZEND_END_ARG_INFO()
418:
419: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_fields, 0, 0, 1)
420: ZEND_ARG_INFO(0, statement_resource)
421: ZEND_END_ARG_INFO()
422:
423: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_parse, 0, 0, 2)
424: ZEND_ARG_INFO(0, connection_resource)
425: ZEND_ARG_INFO(0, sql_text)
426: ZEND_END_ARG_INFO()
427:
428: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_prefetch, 0, 0, 2)
429: ZEND_ARG_INFO(0, statement_resource)
430: ZEND_ARG_INFO(0, number_of_rows)
431: ZEND_END_ARG_INFO()
432:
433: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_identifier, 0, 0, 2)
434: ZEND_ARG_INFO(0, connection_resource)
435: ZEND_ARG_INFO(0, client_identifier)
436: ZEND_END_ARG_INFO()
437:
438: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_edition, 0, 0, 1)
439: ZEND_ARG_INFO(0, edition_name)
440: ZEND_END_ARG_INFO()
441:
442: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_module_name, 0, 0, 2)
443: ZEND_ARG_INFO(0, connection_resource)
444: ZEND_ARG_INFO(0, module_name)
445: ZEND_END_ARG_INFO()
446:
447: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_action, 0, 0, 2)
448: ZEND_ARG_INFO(0, connection_resource)
449: ZEND_ARG_INFO(0, action)
450: ZEND_END_ARG_INFO()
451:
452: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_info, 0, 0, 2)
453: ZEND_ARG_INFO(0, connection_resource)
454: ZEND_ARG_INFO(0, client_information)
455: ZEND_END_ARG_INFO()
456:
457: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_password_change, 0, 0, 4)
458: ZEND_ARG_INFO(0, connection_resource_or_connection_string)
459: ZEND_ARG_INFO(0, username)
460: ZEND_ARG_INFO(0, old_password)
461: ZEND_ARG_INFO(0, new_password)
462: ZEND_END_ARG_INFO()
463:
464: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_cursor, 0, 0, 1)
465: ZEND_ARG_INFO(0, connection_resource)
466: ZEND_END_ARG_INFO()
467:
468: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_result, 0, 0, 2)
469: ZEND_ARG_INFO(0, statement_resource)
470: ZEND_ARG_INFO(0, column_number_or_name)
471: ZEND_END_ARG_INFO()
472:
473: ZEND_BEGIN_ARG_INFO(arginfo_oci_client_version, 0)
474: ZEND_END_ARG_INFO()
475:
476: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_server_version, 0, 0, 1)
477: ZEND_ARG_INFO(0, connection_resource)
478: ZEND_END_ARG_INFO()
479:
480: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_statement_type, 0, 0, 1)
481: ZEND_ARG_INFO(0, statement_resource)
482: ZEND_END_ARG_INFO()
483:
484: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_rows, 0, 0, 1)
485: ZEND_ARG_INFO(0, statement_resource)
486: ZEND_END_ARG_INFO()
487:
488: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_collection, 0, 0, 1)
489: ZEND_ARG_INFO(0, collection)
490: ZEND_END_ARG_INFO()
491:
492: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append, 0, 0, 2)
493: ZEND_ARG_INFO(0, collection)
494: ZEND_ARG_INFO(0, value)
495: ZEND_END_ARG_INFO()
496:
497: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get, 0, 0, 2)
498: ZEND_ARG_INFO(0, collection)
499: ZEND_ARG_INFO(0, index)
500: ZEND_END_ARG_INFO()
501:
502: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign, 0, 0, 2)
503: ZEND_ARG_INFO(0, collection_to)
504: ZEND_ARG_INFO(0, collection_from)
505: ZEND_END_ARG_INFO()
506:
507: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign, 0, 0, 3)
508: ZEND_ARG_INFO(0, collection)
509: ZEND_ARG_INFO(0, index)
510: ZEND_ARG_INFO(0, value)
511: ZEND_END_ARG_INFO()
512:
513: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_size, 0, 0, 1)
514: ZEND_ARG_INFO(0, collection)
515: ZEND_END_ARG_INFO()
516:
517: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_max, 0, 0, 1)
518: ZEND_ARG_INFO(0, collection)
519: ZEND_END_ARG_INFO()
520:
521: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim, 0, 0, 2)
522: ZEND_ARG_INFO(0, collection)
523: ZEND_ARG_INFO(0, number)
524: ZEND_END_ARG_INFO()
525:
526: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_collection, 0, 0, 2)
527: ZEND_ARG_INFO(0, connection_resource)
528: ZEND_ARG_INFO(0, type_name)
529: ZEND_ARG_INFO(0, schema_name)
530: ZEND_END_ARG_INFO()
531: /* }}} */
532:
533: /* {{{ LOB Method arginfo */
534: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save_method, 0, 0, 1)
535: ZEND_ARG_INFO(0, data)
536: ZEND_ARG_INFO(0, offset)
537: ZEND_END_ARG_INFO()
538:
539: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import_method, 0, 0, 1)
540: ZEND_ARG_INFO(0, filename)
541: ZEND_END_ARG_INFO()
542:
543: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_load_method, 0)
544: ZEND_END_ARG_INFO()
545:
546: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read_method, 0, 0, 1)
547: ZEND_ARG_INFO(0, length)
548: ZEND_END_ARG_INFO()
549:
550: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_eof_method, 0)
551: ZEND_END_ARG_INFO()
552:
553: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_tell_method, 0)
554: ZEND_END_ARG_INFO()
555:
556: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_rewind_method, 0)
557: ZEND_END_ARG_INFO()
558:
559: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek_method, 0, 0, 1)
560: ZEND_ARG_INFO(0, offset)
561: ZEND_ARG_INFO(0, whence)
562: ZEND_END_ARG_INFO()
563:
564: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_size_method, 0)
565: ZEND_END_ARG_INFO()
566:
567: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_method, 0, 0, 1)
568: ZEND_ARG_INFO(0, string)
569: ZEND_ARG_INFO(0, length)
570: ZEND_END_ARG_INFO()
571:
572: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append_method, 0, 0, 1)
573: ZEND_ARG_INFO(0, lob_descriptor_from)
574: ZEND_END_ARG_INFO()
575:
576: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate_method, 0, 0, 0)
577: ZEND_ARG_INFO(0, length)
578: ZEND_END_ARG_INFO()
579:
580: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase_method, 0, 0, 0)
581: ZEND_ARG_INFO(0, offset)
582: ZEND_ARG_INFO(0, length)
583: ZEND_END_ARG_INFO()
584:
585: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush_method, 0, 0, 0)
586: ZEND_ARG_INFO(0, flag)
587: ZEND_END_ARG_INFO()
588:
589: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_setbuffering_method, 0, 0, 1)
590: ZEND_ARG_INFO(0, mode)
591: ZEND_END_ARG_INFO()
592:
593: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_getbuffering_method, 0)
594: ZEND_END_ARG_INFO()
595:
596: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export_method, 0, 0, 1)
597: ZEND_ARG_INFO(0, filename)
598: ZEND_ARG_INFO(0, start)
599: ZEND_ARG_INFO(0, length)
600: ZEND_END_ARG_INFO()
601:
602: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_temporary_method, 0, 0, 1)
603: ZEND_ARG_INFO(0, data)
604: ZEND_ARG_INFO(0, type)
605: ZEND_END_ARG_INFO()
606:
607: ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_close_method, 0)
608: ZEND_END_ARG_INFO()
609:
610: ZEND_BEGIN_ARG_INFO(arginfo_oci_free_descriptor_method, 0)
611: ZEND_END_ARG_INFO()
612: /* }}} */
613:
614: /* {{{ Collection Method arginfo */
615: ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_free_method, 0)
616: ZEND_END_ARG_INFO()
617:
618: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append_method, 0, 0, 1)
619: ZEND_ARG_INFO(0, value)
620: ZEND_END_ARG_INFO()
621:
622: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get_method, 0, 0, 1)
623: ZEND_ARG_INFO(0, index)
624: ZEND_END_ARG_INFO()
625:
626: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign_method, 0, 0, 1)
627: ZEND_ARG_INFO(0, collection_from)
628: ZEND_END_ARG_INFO()
629:
630: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign_method, 0, 0, 2)
631: ZEND_ARG_INFO(0, index)
632: ZEND_ARG_INFO(0, value)
633: ZEND_END_ARG_INFO()
634:
635: ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_size_method, 0)
636: ZEND_END_ARG_INFO()
637:
638: ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_max_method, 0)
639: ZEND_END_ARG_INFO()
640:
641: ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim_method, 0, 0, 1)
642: ZEND_ARG_INFO(0, number)
643: ZEND_END_ARG_INFO()
644: /* }}} */
645:
646: #else /* ZEND_ENGINE_2 */
647: /* {{{ Keep the old arginfo behavior when building with PHP 4 */
648:
649: static unsigned char arginfo_ocifetchinto[] = { 2, BYREF_NONE, BYREF_FORCE };
650: static unsigned char arginfo_oci_fetch_all[] = { 2, BYREF_NONE, BYREF_FORCE };
651: static unsigned char arginfo_oci_define_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
652: static unsigned char arginfo_oci_bind_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
653: static unsigned char arginfo_oci_bind_array_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
654:
655: #define arginfo_oci_free_descriptor NULL
656: #define arginfo_oci_lob_save NULL
657: #define arginfo_oci_lob_import NULL
658: #define arginfo_oci_lob_load NULL
659: #define arginfo_oci_lob_read NULL
660: #define arginfo_oci_lob_eof NULL
661: #define arginfo_oci_lob_tell NULL
662: #define arginfo_oci_lob_rewind NULL
663: #define arginfo_oci_lob_seek NULL
664: #define arginfo_oci_lob_size NULL
665: #define arginfo_oci_lob_write NULL
666: #define arginfo_oci_lob_append NULL
667: #define arginfo_oci_lob_truncate NULL
668: #define arginfo_oci_lob_erase NULL
669: #define arginfo_oci_lob_flush NULL
670: #define arginfo_ocisetbufferinglob NULL
671: #define arginfo_ocigetbufferinglob NULL
672: #define arginfo_oci_lob_copy NULL
673: #define arginfo_oci_lob_is_equal NULL
674: #define arginfo_oci_lob_export NULL
675: #define arginfo_oci_new_descriptor NULL
676: #define arginfo_oci_rollback NULL
677: #define arginfo_oci_commit NULL
678: #define arginfo_oci_field_name NULL
679: #define arginfo_oci_field_size NULL
680: #define arginfo_oci_field_scale NULL
681: #define arginfo_oci_field_precision NULL
682: #define arginfo_oci_field_type NULL
683: #define arginfo_oci_field_type_raw NULL
684: #define arginfo_oci_field_is_null NULL
685: #define arginfo_oci_internal_debug NULL
686: #define arginfo_oci_execute NULL
687: #define arginfo_oci_cancel NULL
688: #define arginfo_oci_fetch NULL
689: #define arginfo_oci_fetch_object NULL
690: #define arginfo_oci_fetch_row NULL
691: #define arginfo_oci_fetch_assoc NULL
692: #define arginfo_oci_fetch_array NULL
693: #define arginfo_oci_free_statement NULL
694: #define arginfo_oci_close NULL
695: #define arginfo_oci_new_connect NULL
696: #define arginfo_oci_connect NULL
697: #define arginfo_oci_pconnect NULL
698: #define arginfo_oci_error NULL
699: #define arginfo_oci_num_fields NULL
700: #define arginfo_oci_parse NULL
701: #define arginfo_oci_set_prefetch NULL
702: #define arginfo_oci_set_client_identifier NULL
703: #define arginfo_oci_set_edition NULL
704: #define arginfo_oci_set_module_name NULL
705: #define arginfo_oci_set_action NULL
706: #define arginfo_oci_set_client_info NULL
707: #define arginfo_oci_password_change NULL
708: #define arginfo_oci_new_cursor NULL
709: #define arginfo_oci_result NULL
710: #define arginfo_oci_client_version NULL
711: #define arginfo_oci_server_version NULL
712: #define arginfo_oci_statement_type NULL
713: #define arginfo_oci_num_rows NULL
714: #define arginfo_oci_free_collection NULL
715: #define arginfo_oci_collection_append NULL
716: #define arginfo_oci_collection_element_get NULL
717: #define arginfo_oci_collection_assign NULL
718: #define arginfo_oci_collection_element_assign NULL
719: #define arginfo_oci_collection_size NULL
720: #define arginfo_oci_collection_max NULL
721: #define arginfo_oci_collection_trim NULL
722: #define arginfo_oci_new_collection NULL
723: #define arginfo_oci_lob_size_method NULL
724: #define arginfo_oci_lob_getbuffering_method NULL
725: #define arginfo_oci_lob_close_method NULL
726: #define arginfo_oci_lob_save_method NULL
727: #define arginfo_oci_lob_import_method NULL
728: #define arginfo_oci_lob_read_method NULL
729: #define arginfo_oci_lob_seek_method NULL
730: #define arginfo_oci_lob_write_method NULL
731: #define arginfo_oci_lob_append_method NULL
732: #define arginfo_oci_lob_truncate_method NULL
733: #define arginfo_oci_lob_erase_method NULL
734: #define arginfo_oci_lob_flush_method NULL
735: #define arginfo_oci_lob_setbuffering_method NULL
736: #define arginfo_oci_lob_export_method NULL
737: #define arginfo_oci_lob_write_temporary_method NULL
738: #define arginfo_oci_lob_load_method NULL
739: #define arginfo_oci_lob_tell_method NULL
740: #define arginfo_oci_lob_rewind_method NULL
741: #define arginfo_oci_lob_eof_method NULL
742: #define arginfo_oci_free_descriptor_method NULL
743: #define arginfo_oci_collection_append_method NULL
744: #define arginfo_oci_collection_element_get_method NULL
745: #define arginfo_oci_collection_assign_method NULL
746: #define arginfo_oci_collection_size_method NULL
747: #define arginfo_oci_collection_element_assign_method NULL
748: #define arginfo_oci_collection_max_method NULL
749: #define arginfo_oci_collection_trim_method NULL
750: #define arginfo_oci_collection_free_method NULL
751: /* }}} */
752: #endif /* ZEND_ENGINE_2 */
753:
754: /* {{{ extension function prototypes
755: */
756: PHP_FUNCTION(oci_bind_by_name);
757: PHP_FUNCTION(oci_bind_array_by_name);
758: PHP_FUNCTION(oci_define_by_name);
759: PHP_FUNCTION(oci_field_is_null);
760: PHP_FUNCTION(oci_field_name);
761: PHP_FUNCTION(oci_field_size);
762: PHP_FUNCTION(oci_field_scale);
763: PHP_FUNCTION(oci_field_precision);
764: PHP_FUNCTION(oci_field_type);
765: PHP_FUNCTION(oci_field_type_raw);
766: PHP_FUNCTION(oci_execute);
767: PHP_FUNCTION(oci_fetch);
768: PHP_FUNCTION(oci_cancel);
769: PHP_FUNCTION(ocifetchinto);
770: PHP_FUNCTION(oci_fetch_object);
771: PHP_FUNCTION(oci_fetch_row);
772: PHP_FUNCTION(oci_fetch_assoc);
773: PHP_FUNCTION(oci_fetch_array);
774: PHP_FUNCTION(ocifetchstatement);
775: PHP_FUNCTION(oci_fetch_all);
776: PHP_FUNCTION(oci_free_statement);
777: PHP_FUNCTION(oci_internal_debug);
778: PHP_FUNCTION(oci_close);
779: PHP_FUNCTION(oci_connect);
780: PHP_FUNCTION(oci_new_connect);
781: PHP_FUNCTION(oci_pconnect);
782: PHP_FUNCTION(oci_error);
783: PHP_FUNCTION(oci_free_descriptor);
784: PHP_FUNCTION(oci_commit);
785: PHP_FUNCTION(oci_rollback);
786: PHP_FUNCTION(oci_new_descriptor);
787: PHP_FUNCTION(oci_num_fields);
788: PHP_FUNCTION(oci_parse);
789: PHP_FUNCTION(oci_new_cursor);
790: PHP_FUNCTION(oci_result);
791: PHP_FUNCTION(oci_client_version);
792: PHP_FUNCTION(oci_server_version);
793: PHP_FUNCTION(oci_statement_type);
794: PHP_FUNCTION(oci_num_rows);
795: PHP_FUNCTION(oci_set_prefetch);
796: PHP_FUNCTION(oci_set_client_identifier);
797: PHP_FUNCTION(oci_set_edition);
798: PHP_FUNCTION(oci_set_module_name);
799: PHP_FUNCTION(oci_set_action);
800: PHP_FUNCTION(oci_set_client_info);
801: PHP_FUNCTION(oci_password_change);
802: PHP_FUNCTION(oci_lob_save);
803: PHP_FUNCTION(oci_lob_import);
804: PHP_FUNCTION(oci_lob_export);
805: PHP_FUNCTION(oci_lob_load);
806: PHP_FUNCTION(oci_lob_tell);
807: PHP_FUNCTION(oci_lob_write);
808: PHP_FUNCTION(oci_lob_append);
809: PHP_FUNCTION(oci_lob_copy);
810: PHP_FUNCTION(oci_lob_truncate);
811: PHP_FUNCTION(oci_lob_erase);
812: PHP_FUNCTION(oci_lob_flush);
813: PHP_FUNCTION(ocisetbufferinglob);
814: PHP_FUNCTION(ocigetbufferinglob);
815: PHP_FUNCTION(oci_lob_is_equal);
816: PHP_FUNCTION(oci_lob_rewind);
817: PHP_FUNCTION(oci_lob_read);
818: PHP_FUNCTION(oci_lob_eof);
819: PHP_FUNCTION(oci_lob_seek);
820: PHP_FUNCTION(oci_lob_size);
821: PHP_FUNCTION(oci_lob_write_temporary);
822: PHP_FUNCTION(oci_lob_close);
823: PHP_FUNCTION(oci_new_collection);
824: PHP_FUNCTION(oci_free_collection);
825: PHP_FUNCTION(oci_collection_append);
826: PHP_FUNCTION(oci_collection_element_get);
827: PHP_FUNCTION(oci_collection_element_assign);
828: PHP_FUNCTION(oci_collection_assign);
829: PHP_FUNCTION(oci_collection_size);
830: PHP_FUNCTION(oci_collection_max);
831: PHP_FUNCTION(oci_collection_trim);
832: /* }}} */
833:
834: /* {{{ extension definition structures
835: */
836: static
837: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
838: /* This "if" allows PECL builds from this file to be portable to older PHP releases */
839: const
840: #endif
841: zend_function_entry php_oci_functions[] = {
842: PHP_FE(oci_define_by_name, arginfo_oci_define_by_name)
843: PHP_FE(oci_bind_by_name, arginfo_oci_bind_by_name)
844: PHP_FE(oci_bind_array_by_name, arginfo_oci_bind_array_by_name)
845: PHP_FE(oci_field_is_null, arginfo_oci_field_is_null)
846: PHP_FE(oci_field_name, arginfo_oci_field_name)
847: PHP_FE(oci_field_size, arginfo_oci_field_size)
848: PHP_FE(oci_field_scale, arginfo_oci_field_scale)
849: PHP_FE(oci_field_precision, arginfo_oci_field_precision)
850: PHP_FE(oci_field_type, arginfo_oci_field_type)
851: PHP_FE(oci_field_type_raw, arginfo_oci_field_type_raw)
852: PHP_FE(oci_execute, arginfo_oci_execute)
853: PHP_FE(oci_cancel, arginfo_oci_cancel)
854: PHP_FE(oci_fetch, arginfo_oci_fetch)
855: PHP_FE(oci_fetch_object, arginfo_oci_fetch_object)
856: PHP_FE(oci_fetch_row, arginfo_oci_fetch_row)
857: PHP_FE(oci_fetch_assoc, arginfo_oci_fetch_assoc)
858: PHP_FE(oci_fetch_array, arginfo_oci_fetch_array)
859: PHP_FE(ocifetchinto, arginfo_ocifetchinto)
860: PHP_FE(oci_fetch_all, arginfo_oci_fetch_all)
861: PHP_FE(oci_free_statement, arginfo_oci_free_statement)
862: PHP_FE(oci_internal_debug, arginfo_oci_internal_debug)
863: PHP_FE(oci_num_fields, arginfo_oci_num_fields)
864: PHP_FE(oci_parse, arginfo_oci_parse)
865: PHP_FE(oci_new_cursor, arginfo_oci_new_cursor)
866: PHP_FE(oci_result, arginfo_oci_result)
867: PHP_FE(oci_client_version, arginfo_oci_client_version)
868: PHP_FE(oci_server_version, arginfo_oci_server_version)
869: PHP_FE(oci_statement_type, arginfo_oci_statement_type)
870: PHP_FE(oci_num_rows, arginfo_oci_num_rows)
871: PHP_FE(oci_close, arginfo_oci_close)
872: PHP_FE(oci_connect, arginfo_oci_connect)
873: PHP_FE(oci_new_connect, arginfo_oci_new_connect)
874: PHP_FE(oci_pconnect, arginfo_oci_pconnect)
875: PHP_FE(oci_error, arginfo_oci_error)
876: PHP_FE(oci_free_descriptor, arginfo_oci_free_descriptor)
877: PHP_FE(oci_lob_save, arginfo_oci_lob_save)
878: PHP_FE(oci_lob_import, arginfo_oci_lob_import)
879: PHP_FE(oci_lob_size, arginfo_oci_lob_size)
880: PHP_FE(oci_lob_load, arginfo_oci_lob_load)
881: PHP_FE(oci_lob_read, arginfo_oci_lob_read)
882: PHP_FE(oci_lob_eof, arginfo_oci_lob_eof)
883: PHP_FE(oci_lob_tell, arginfo_oci_lob_tell)
884: PHP_FE(oci_lob_truncate, arginfo_oci_lob_truncate)
885: PHP_FE(oci_lob_erase, arginfo_oci_lob_erase)
886: PHP_FE(oci_lob_flush, arginfo_oci_lob_flush)
887: PHP_FE(ocisetbufferinglob, arginfo_ocisetbufferinglob)
888: PHP_FE(ocigetbufferinglob, arginfo_ocigetbufferinglob)
889: PHP_FE(oci_lob_is_equal, arginfo_oci_lob_is_equal)
890: PHP_FE(oci_lob_rewind, arginfo_oci_lob_rewind)
891: PHP_FE(oci_lob_write, arginfo_oci_lob_write)
892: PHP_FE(oci_lob_append, arginfo_oci_lob_append)
893: PHP_FE(oci_lob_copy, arginfo_oci_lob_copy)
894: PHP_FE(oci_lob_export, arginfo_oci_lob_export)
895: PHP_FE(oci_lob_seek, arginfo_oci_lob_seek)
896: PHP_FE(oci_commit, arginfo_oci_commit)
897: PHP_FE(oci_rollback, arginfo_oci_rollback)
898: PHP_FE(oci_new_descriptor, arginfo_oci_new_descriptor)
899: PHP_FE(oci_set_prefetch, arginfo_oci_set_prefetch)
900: PHP_FE(oci_set_client_identifier, arginfo_oci_set_client_identifier)
901: PHP_FE(oci_set_edition, arginfo_oci_set_edition)
902: PHP_FE(oci_set_module_name, arginfo_oci_set_module_name)
903: PHP_FE(oci_set_action, arginfo_oci_set_action)
904: PHP_FE(oci_set_client_info, arginfo_oci_set_client_info)
905: PHP_FE(oci_password_change, arginfo_oci_password_change)
906: PHP_FE(oci_free_collection, arginfo_oci_free_collection)
907: PHP_FE(oci_collection_append, arginfo_oci_collection_append)
908: PHP_FE(oci_collection_element_get, arginfo_oci_collection_element_get)
909: PHP_FE(oci_collection_element_assign, arginfo_oci_collection_element_assign)
910: PHP_FE(oci_collection_assign, arginfo_oci_collection_assign)
911: PHP_FE(oci_collection_size, arginfo_oci_collection_size)
912: PHP_FE(oci_collection_max, arginfo_oci_collection_max)
913: PHP_FE(oci_collection_trim, arginfo_oci_collection_trim)
914: PHP_FE(oci_new_collection, arginfo_oci_new_collection)
915:
916: PHP_FALIAS(oci_free_cursor, oci_free_statement, arginfo_oci_free_statement)
917: PHP_FALIAS(ocifreecursor, oci_free_statement, arginfo_oci_free_statement)
918: PHP_FALIAS(ocibindbyname, oci_bind_by_name, arginfo_oci_bind_by_name)
919: PHP_FALIAS(ocidefinebyname, oci_define_by_name, arginfo_oci_define_by_name)
920: PHP_FALIAS(ocicolumnisnull, oci_field_is_null, arginfo_oci_field_is_null)
921: PHP_FALIAS(ocicolumnname, oci_field_name, arginfo_oci_field_name)
922: PHP_FALIAS(ocicolumnsize, oci_field_size, arginfo_oci_field_size)
923: PHP_FALIAS(ocicolumnscale, oci_field_scale, arginfo_oci_field_scale)
924: PHP_FALIAS(ocicolumnprecision, oci_field_precision, arginfo_oci_field_precision)
925: PHP_FALIAS(ocicolumntype, oci_field_type, arginfo_oci_field_type)
926: PHP_FALIAS(ocicolumntyperaw, oci_field_type_raw, arginfo_oci_field_type_raw)
927: PHP_FALIAS(ociexecute, oci_execute, arginfo_oci_execute)
928: PHP_FALIAS(ocicancel, oci_cancel, arginfo_oci_cancel)
929: PHP_FALIAS(ocifetch, oci_fetch, arginfo_oci_fetch)
930: PHP_FALIAS(ocifetchstatement, oci_fetch_all, arginfo_oci_fetch_all)
931: PHP_FALIAS(ocifreestatement, oci_free_statement, arginfo_oci_free_statement)
932: PHP_FALIAS(ociinternaldebug, oci_internal_debug, arginfo_oci_internal_debug)
933: PHP_FALIAS(ocinumcols, oci_num_fields, arginfo_oci_num_fields)
934: PHP_FALIAS(ociparse, oci_parse, arginfo_oci_parse)
935: PHP_FALIAS(ocinewcursor, oci_new_cursor, arginfo_oci_new_cursor)
936: PHP_FALIAS(ociresult, oci_result, arginfo_oci_result)
937: PHP_FALIAS(ociserverversion, oci_server_version, arginfo_oci_server_version)
938: PHP_FALIAS(ocistatementtype, oci_statement_type, arginfo_oci_statement_type)
939: PHP_FALIAS(ocirowcount, oci_num_rows, arginfo_oci_num_rows)
940: PHP_FALIAS(ocilogoff, oci_close, arginfo_oci_close)
941: PHP_FALIAS(ocilogon, oci_connect, arginfo_oci_connect)
942: PHP_FALIAS(ocinlogon, oci_new_connect, arginfo_oci_new_connect)
943: PHP_FALIAS(ociplogon, oci_pconnect, arginfo_oci_pconnect)
944: PHP_FALIAS(ocierror, oci_error, arginfo_oci_error)
945: PHP_FALIAS(ocifreedesc, oci_free_descriptor, arginfo_oci_free_descriptor)
946: PHP_FALIAS(ocisavelob, oci_lob_save, arginfo_oci_lob_save)
947: PHP_FALIAS(ocisavelobfile, oci_lob_import, arginfo_oci_lob_import)
948: PHP_FALIAS(ociwritelobtofile, oci_lob_export, arginfo_oci_lob_export)
949: PHP_FALIAS(ociloadlob, oci_lob_load, arginfo_oci_lob_load)
950: PHP_FALIAS(ocicommit, oci_commit, arginfo_oci_commit)
951: PHP_FALIAS(ocirollback, oci_rollback, arginfo_oci_rollback)
952: PHP_FALIAS(ocinewdescriptor, oci_new_descriptor, arginfo_oci_new_descriptor)
953: PHP_FALIAS(ocisetprefetch, oci_set_prefetch, arginfo_oci_set_prefetch)
954: PHP_FALIAS(ocipasswordchange, oci_password_change, arginfo_oci_password_change)
955: PHP_FALIAS(ocifreecollection, oci_free_collection, arginfo_oci_free_collection)
956: PHP_FALIAS(ocinewcollection, oci_new_collection, arginfo_oci_new_collection)
957: PHP_FALIAS(ocicollappend, oci_collection_append, arginfo_oci_collection_append)
958: PHP_FALIAS(ocicollgetelem, oci_collection_element_get, arginfo_oci_collection_element_get)
959: PHP_FALIAS(ocicollassignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign)
960: PHP_FALIAS(ocicollsize, oci_collection_size, arginfo_oci_collection_size)
961: PHP_FALIAS(ocicollmax, oci_collection_max, arginfo_oci_collection_max)
962: PHP_FALIAS(ocicolltrim, oci_collection_trim, arginfo_oci_collection_trim)
963: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
964: PHP_FE_END
965: #else
966: {NULL,NULL,NULL}
967: #endif
968: };
969:
970: static
971: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
972: /* This "if" allows PECL builds from this file to be portable to older PHP releases */
973: const
974: #endif
975: zend_function_entry php_oci_lob_class_functions[] = {
976: PHP_FALIAS(load, oci_lob_load, arginfo_oci_lob_load_method)
977: PHP_FALIAS(tell, oci_lob_tell, arginfo_oci_lob_tell_method)
978: PHP_FALIAS(truncate, oci_lob_truncate, arginfo_oci_lob_truncate_method)
979: PHP_FALIAS(erase, oci_lob_erase, arginfo_oci_lob_erase_method)
980: PHP_FALIAS(flush, oci_lob_flush, arginfo_oci_lob_flush_method)
981: PHP_FALIAS(setbuffering,ocisetbufferinglob, arginfo_oci_lob_setbuffering_method)
982: PHP_FALIAS(getbuffering,ocigetbufferinglob, arginfo_oci_lob_getbuffering_method)
983: PHP_FALIAS(rewind, oci_lob_rewind, arginfo_oci_lob_rewind_method)
984: PHP_FALIAS(read, oci_lob_read, arginfo_oci_lob_read_method)
985: PHP_FALIAS(eof, oci_lob_eof, arginfo_oci_lob_eof_method)
986: PHP_FALIAS(seek, oci_lob_seek, arginfo_oci_lob_seek_method)
987: PHP_FALIAS(write, oci_lob_write, arginfo_oci_lob_write_method)
988: PHP_FALIAS(append, oci_lob_append, arginfo_oci_lob_append_method)
989: PHP_FALIAS(size, oci_lob_size, arginfo_oci_lob_size_method)
990: PHP_FALIAS(writetofile, oci_lob_export, arginfo_oci_lob_export_method)
991: PHP_FALIAS(export, oci_lob_export, arginfo_oci_lob_export_method)
992: PHP_FALIAS(import, oci_lob_import, arginfo_oci_lob_import_method)
993: PHP_FALIAS(writetemporary, oci_lob_write_temporary, arginfo_oci_lob_write_temporary_method)
994: PHP_FALIAS(close, oci_lob_close, arginfo_oci_lob_close_method)
995: PHP_FALIAS(save, oci_lob_save, arginfo_oci_lob_save_method)
996: PHP_FALIAS(savefile, oci_lob_import, arginfo_oci_lob_import_method)
997: PHP_FALIAS(free, oci_free_descriptor, arginfo_oci_free_descriptor_method)
998: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
999: PHP_FE_END
1000: #else
1001: {NULL,NULL,NULL}
1002: #endif
1003: };
1004:
1005: static
1006: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
1007: /* This "if" allows PECL builds from this file to be portable to older PHP releases */
1008: const
1009: #endif
1010: zend_function_entry php_oci_coll_class_functions[] = {
1011: PHP_FALIAS(append, oci_collection_append, arginfo_oci_collection_append_method)
1012: PHP_FALIAS(getelem, oci_collection_element_get, arginfo_oci_collection_element_get_method)
1013: PHP_FALIAS(assignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign_method)
1014: PHP_FALIAS(assign, oci_collection_assign, arginfo_oci_collection_assign_method)
1015: PHP_FALIAS(size, oci_collection_size, arginfo_oci_collection_size_method)
1016: PHP_FALIAS(max, oci_collection_max, arginfo_oci_collection_max_method)
1017: PHP_FALIAS(trim, oci_collection_trim, arginfo_oci_collection_trim_method)
1018: PHP_FALIAS(free, oci_free_collection, arginfo_oci_collection_free_method)
1019: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5)
1020: PHP_FE_END
1021: #else
1022: {NULL,NULL,NULL}
1023: #endif
1024: };
1025:
1026: zend_module_entry oci8_module_entry = {
1027: STANDARD_MODULE_HEADER,
1028: "oci8", /* extension name */
1029: php_oci_functions, /* extension function list */
1030: PHP_MINIT(oci), /* extension-wide startup function */
1031: PHP_MSHUTDOWN(oci), /* extension-wide shutdown function */
1032: PHP_RINIT(oci), /* per-request startup function */
1033: PHP_RSHUTDOWN(oci), /* per-request shutdown function */
1034: PHP_MINFO(oci), /* information function */
1035: PHP_OCI8_VERSION,
1036: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
1037: /* This check allows PECL builds from this file to be portable to older PHP releases */
1038: PHP_MODULE_GLOBALS(oci), /* globals descriptor */
1039: PHP_GINIT(oci), /* globals ctor */
1040: PHP_GSHUTDOWN(oci), /* globals dtor */
1041: NULL, /* post deactivate */
1042: STANDARD_MODULE_PROPERTIES_EX
1043: #else
1044: STANDARD_MODULE_PROPERTIES
1045: #endif
1046: };
1047: /* }}} */
1048:
1049: /* {{{ PHP_INI */
1050: PHP_INI_BEGIN()
1051: STD_PHP_INI_ENTRY( "oci8.max_persistent", "-1", PHP_INI_SYSTEM, ONUPDATELONGFUNC, max_persistent, zend_oci_globals, oci_globals)
1052: STD_PHP_INI_ENTRY( "oci8.persistent_timeout", "-1", PHP_INI_SYSTEM, ONUPDATELONGFUNC, persistent_timeout, zend_oci_globals, oci_globals)
1053: STD_PHP_INI_ENTRY( "oci8.ping_interval", "60", PHP_INI_SYSTEM, ONUPDATELONGFUNC, ping_interval, zend_oci_globals, oci_globals)
1054: STD_PHP_INI_BOOLEAN("oci8.privileged_connect", "0", PHP_INI_SYSTEM, OnUpdateBool, privileged_connect, zend_oci_globals, oci_globals)
1055: STD_PHP_INI_ENTRY( "oci8.statement_cache_size", "20", PHP_INI_SYSTEM, ONUPDATELONGFUNC, statement_cache_size, zend_oci_globals, oci_globals)
1056: STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, ONUPDATELONGFUNC, default_prefetch, zend_oci_globals, oci_globals)
1057: STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics", "0", PHP_INI_SYSTEM, OnUpdateBool, old_oci_close_semantics,zend_oci_globals, oci_globals)
1058: STD_PHP_INI_ENTRY( "oci8.connection_class", "", PHP_INI_ALL, OnUpdateString, connection_class, zend_oci_globals, oci_globals)
1059: STD_PHP_INI_BOOLEAN("oci8.events", "0", PHP_INI_SYSTEM, OnUpdateBool, events, zend_oci_globals, oci_globals)
1060: PHP_INI_END()
1061: /* }}} */
1062:
1063: /* {{{ startup, shutdown and info functions
1064: */
1065:
1066: /* {{{ php_oci_init_global_handles()
1067: *
1068: * Initialize global handles only when they are needed
1069: */
1070: static void php_oci_init_global_handles(TSRMLS_D)
1071: {
1072: sword errstatus;
1073: sb4 ora_error_code = 0;
1074: text tmp_buf[OCI_ERROR_MAXMSG_SIZE]; /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
1075:
1076: errstatus = OCIEnvNlsCreate(&OCI_G(env), PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
1077:
1078: if (errstatus == OCI_ERROR) {
1079: #ifdef HAVE_OCI_INSTANT_CLIENT
1080: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
1081: #else
1082: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
1083: #endif
1084: if (OCI_G(env)
1085: && OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
1086: && *tmp_buf) {
1087: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tmp_buf);
1088: }
1089:
1090: OCI_G(env) = NULL;
1091: OCI_G(err) = NULL;
1092: return;
1093: }
1094:
1095: errstatus = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
1096:
1097: if (errstatus == OCI_SUCCESS) {
1098: #if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11)
1099: /* This fixes PECL bug 15988 (sqlnet.ora not being read). The
1100: * root cause was fixed in Oracle 10.2.0.4 but there is no
1101: * compile time method to check for that precise patch level,
1102: * nor can it be guaranteed that runtime will use the same
1103: * patch level the code was compiled with. So, we do this
1104: * code for all non 11g versions.
1105: */
1106: OCICPool *cpoolh;
1107: ub4 cpoolmode = 0x80000000; /* Pass invalid mode to OCIConnectionPoolCreate */
1108: PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
1109: PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
1110: PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
1111: PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
1112: #endif
1113: } else {
1114: OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ERROR);
1115:
1116: if (ora_error_code) {
1117: int tmp_buf_len = strlen((char *)tmp_buf);
1118:
1119: if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
1120: tmp_buf[tmp_buf_len - 1] = '\0';
1121: }
1122:
1123: if (errstatus == OCI_SUCCESS_WITH_INFO) {
1124: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
1125: } else {
1126: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_ERROR: %s", tmp_buf);
1127:
1128: OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
1129:
1130: OCI_G(env) = NULL;
1131: OCI_G(err) = NULL;
1132: }
1133: }
1134: }
1135: } /* }}} */
1136:
1137: /* {{{ php_oci_cleanup_global_handles()
1138: *
1139: * Free global handles (if they were initialized before)
1140: */
1141: static void php_oci_cleanup_global_handles(TSRMLS_D)
1142: {
1143: if (OCI_G(err)) {
1144: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ERROR));
1145: OCI_G(err) = NULL;
1146: }
1147:
1148: if (OCI_G(env)) {
1149: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV));
1150: OCI_G(env) = NULL;
1151: }
1152: } /* }}} */
1153:
1154: /* {{{ PHP_GINIT_FUNCTION
1155: *
1156: * Zerofill globals during module init
1157: */
1158: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
1159: /* This check allows PECL builds from this file to be portable to older PHP releases */
1160: static PHP_GINIT_FUNCTION(oci)
1161: #else
1162: static void php_oci_init_globals(zend_oci_globals *oci_globals TSRMLS_DC)
1163: #endif
1164: {
1165: memset(oci_globals, 0, sizeof(zend_oci_globals));
1166: }
1167: /* }}} */
1168:
1169: /* {{{ PHP_GSHUTDOWN_FUNCTION
1170: *
1171: * Called for thread shutdown in ZTS, after module shutdown for non-ZTS
1172: */
1173: /* This check allows PECL builds from this file to be portable to older PHP releases */
1174: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
1175: static PHP_GSHUTDOWN_FUNCTION(oci)
1176: #else
1177: static void php_oci_shutdown_globals(zend_oci_globals *oci_globals TSRMLS_DC)
1178: #endif
1179: {
1180: php_oci_cleanup_global_handles(TSRMLS_C);
1181: }
1182: /* }}} */
1183:
1184: PHP_MINIT_FUNCTION(oci)
1185: {
1186: zend_class_entry oci_lob_class_entry;
1187: zend_class_entry oci_coll_class_entry;
1188:
1189: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
1190: /* This check allows PECL builds from this file to be portable to older PHP releases */
1191: /* this is handled by new globals management code */
1192: #else
1193: ZEND_INIT_MODULE_GLOBALS(oci, php_oci_init_globals, php_oci_shutdown_globals);
1194: #endif
1195: REGISTER_INI_ENTRIES();
1196:
1197: le_statement = zend_register_list_destructors_ex(php_oci_statement_list_dtor, NULL, "oci8 statement", module_number);
1198: le_connection = zend_register_list_destructors_ex(php_oci_connection_list_dtor, NULL, "oci8 connection", module_number);
1199: le_pconnection = zend_register_list_destructors_ex(php_oci_pconnection_list_np_dtor, php_oci_pconnection_list_dtor, "oci8 persistent connection", module_number);
1200: le_psessionpool = zend_register_list_destructors_ex(NULL, php_oci_spool_list_dtor, "oci8 persistent session pool", module_number);
1201: le_descriptor = zend_register_list_destructors_ex(php_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number);
1202: le_collection = zend_register_list_destructors_ex(php_oci_collection_list_dtor, NULL, "oci8 collection", module_number);
1203:
1204: INIT_CLASS_ENTRY(oci_lob_class_entry, "OCI-Lob", php_oci_lob_class_functions);
1205: INIT_CLASS_ENTRY(oci_coll_class_entry, "OCI-Collection", php_oci_coll_class_functions);
1206:
1207: oci_lob_class_entry_ptr = zend_register_internal_class(&oci_lob_class_entry TSRMLS_CC);
1208: oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry TSRMLS_CC);
1209:
1210: /* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */
1211: REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
1212: REGISTER_LONG_CONSTANT("OCI_SYSOPER",OCI_SYSOPER, CONST_CS | CONST_PERSISTENT);
1213: REGISTER_LONG_CONSTANT("OCI_SYSDBA",OCI_SYSDBA, CONST_CS | CONST_PERSISTENT);
1214: REGISTER_LONG_CONSTANT("OCI_CRED_EXT",PHP_OCI_CRED_EXT, CONST_CS | CONST_PERSISTENT);
1215: REGISTER_LONG_CONSTANT("OCI_DESCRIBE_ONLY",OCI_DESCRIBE_ONLY, CONST_CS | CONST_PERSISTENT);
1216: REGISTER_LONG_CONSTANT("OCI_COMMIT_ON_SUCCESS",OCI_COMMIT_ON_SUCCESS, CONST_CS | CONST_PERSISTENT);
1217: REGISTER_LONG_CONSTANT("OCI_NO_AUTO_COMMIT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
1218: REGISTER_LONG_CONSTANT("OCI_EXACT_FETCH",OCI_EXACT_FETCH, CONST_CS | CONST_PERSISTENT);
1219:
1220: /* for $LOB->seek() */
1221: REGISTER_LONG_CONSTANT("OCI_SEEK_SET",PHP_OCI_SEEK_SET, CONST_CS | CONST_PERSISTENT);
1222: REGISTER_LONG_CONSTANT("OCI_SEEK_CUR",PHP_OCI_SEEK_CUR, CONST_CS | CONST_PERSISTENT);
1223: REGISTER_LONG_CONSTANT("OCI_SEEK_END",PHP_OCI_SEEK_END, CONST_CS | CONST_PERSISTENT);
1224:
1225: /* for $LOB->flush() */
1226: REGISTER_LONG_CONSTANT("OCI_LOB_BUFFER_FREE",OCI_LOB_BUFFER_FREE, CONST_CS | CONST_PERSISTENT);
1227:
1228: /* for OCIBindByName (real "oci" names + short "php" names */
1229: REGISTER_LONG_CONSTANT("SQLT_BFILEE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
1230: REGISTER_LONG_CONSTANT("SQLT_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
1231: REGISTER_LONG_CONSTANT("SQLT_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
1232: REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
1233: REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
1234: REGISTER_LONG_CONSTANT("SQLT_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
1235: REGISTER_LONG_CONSTANT("SQLT_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
1236: REGISTER_LONG_CONSTANT("SQLT_RSET",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
1237: REGISTER_LONG_CONSTANT("SQLT_AFC",SQLT_AFC, CONST_CS | CONST_PERSISTENT);
1238: REGISTER_LONG_CONSTANT("SQLT_CHR",SQLT_CHR, CONST_CS | CONST_PERSISTENT);
1239: REGISTER_LONG_CONSTANT("SQLT_VCS",SQLT_VCS, CONST_CS | CONST_PERSISTENT);
1240: REGISTER_LONG_CONSTANT("SQLT_AVC",SQLT_AVC, CONST_CS | CONST_PERSISTENT);
1241: REGISTER_LONG_CONSTANT("SQLT_STR",SQLT_STR, CONST_CS | CONST_PERSISTENT);
1242: REGISTER_LONG_CONSTANT("SQLT_LVC",SQLT_LVC, CONST_CS | CONST_PERSISTENT);
1243: REGISTER_LONG_CONSTANT("SQLT_FLT",SQLT_FLT, CONST_CS | CONST_PERSISTENT);
1244: REGISTER_LONG_CONSTANT("SQLT_UIN",SQLT_UIN, CONST_CS | CONST_PERSISTENT);
1245: REGISTER_LONG_CONSTANT("SQLT_LNG",SQLT_LNG, CONST_CS | CONST_PERSISTENT);
1246: REGISTER_LONG_CONSTANT("SQLT_LBI",SQLT_LBI, CONST_CS | CONST_PERSISTENT);
1247: REGISTER_LONG_CONSTANT("SQLT_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
1248: REGISTER_LONG_CONSTANT("SQLT_ODT",SQLT_ODT, CONST_CS | CONST_PERSISTENT);
1249: #if defined(HAVE_OCI_INSTANT_CLIENT) || (defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 10)
1250: REGISTER_LONG_CONSTANT("SQLT_BDOUBLE",SQLT_BDOUBLE, CONST_CS | CONST_PERSISTENT);
1251: REGISTER_LONG_CONSTANT("SQLT_BFLOAT",SQLT_BFLOAT, CONST_CS | CONST_PERSISTENT);
1252: #endif
1253:
1254: REGISTER_LONG_CONSTANT("OCI_B_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
1255: REGISTER_LONG_CONSTANT("SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
1256: REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE", CONST_CS | CONST_PERSISTENT);
1257:
1258: REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
1259: REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
1260: REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
1261: REGISTER_LONG_CONSTANT("OCI_B_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
1262: REGISTER_LONG_CONSTANT("OCI_B_ROWID",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
1263: REGISTER_LONG_CONSTANT("OCI_B_CURSOR",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
1264: REGISTER_LONG_CONSTANT("OCI_B_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
1265: REGISTER_LONG_CONSTANT("OCI_B_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
1266: REGISTER_LONG_CONSTANT("OCI_B_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
1267:
1268: /* for OCIFetchStatement */
1269: REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_COLUMN", PHP_OCI_FETCHSTATEMENT_BY_COLUMN, CONST_CS | CONST_PERSISTENT);
1270: REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_ROW", PHP_OCI_FETCHSTATEMENT_BY_ROW, CONST_CS | CONST_PERSISTENT);
1271:
1272: /* for OCIFetchInto & OCIResult */
1273: REGISTER_LONG_CONSTANT("OCI_ASSOC",PHP_OCI_ASSOC, CONST_CS | CONST_PERSISTENT);
1274: REGISTER_LONG_CONSTANT("OCI_NUM",PHP_OCI_NUM, CONST_CS | CONST_PERSISTENT);
1275: REGISTER_LONG_CONSTANT("OCI_BOTH",PHP_OCI_BOTH, CONST_CS | CONST_PERSISTENT);
1276: REGISTER_LONG_CONSTANT("OCI_RETURN_NULLS",PHP_OCI_RETURN_NULLS, CONST_CS | CONST_PERSISTENT);
1277: REGISTER_LONG_CONSTANT("OCI_RETURN_LOBS",PHP_OCI_RETURN_LOBS, CONST_CS | CONST_PERSISTENT);
1278:
1279: /* for OCINewDescriptor (real "oci" names + short "php" names */
1280: REGISTER_LONG_CONSTANT("OCI_DTYPE_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
1281: REGISTER_LONG_CONSTANT("OCI_DTYPE_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
1282: REGISTER_LONG_CONSTANT("OCI_DTYPE_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
1283:
1284: REGISTER_LONG_CONSTANT("OCI_D_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
1285: REGISTER_LONG_CONSTANT("OCI_D_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
1286: REGISTER_LONG_CONSTANT("OCI_D_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
1287:
1288: /* for OCIWriteTemporaryLob */
1289: REGISTER_LONG_CONSTANT("OCI_TEMP_CLOB",OCI_TEMP_CLOB, CONST_CS | CONST_PERSISTENT);
1290: REGISTER_LONG_CONSTANT("OCI_TEMP_BLOB",OCI_TEMP_BLOB, CONST_CS | CONST_PERSISTENT);
1291:
1292: return SUCCESS;
1293: }
1294:
1295: PHP_RINIT_FUNCTION(oci)
1296: {
1297: OCI_G(debug_mode) = 0; /* start "fresh" */
1298: OCI_G(num_links) = OCI_G(num_persistent);
1299: OCI_G(errcode) = 0;
1300: OCI_G(edition) = NULL;
1301:
1302: return SUCCESS;
1303: }
1304:
1305: PHP_MSHUTDOWN_FUNCTION(oci)
1306: {
1307: /* Work around PHP_GSHUTDOWN_FUNCTION not being called in older versions of PHP */
1308: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) || (PHP_MAJOR_VERSION < 5)
1309: #ifndef ZTS
1310: php_oci_cleanup_global_handles(TSRMLS_C);
1311: #endif
1312: #endif
1313:
1314: OCI_G(shutdown) = 1;
1315:
1316: UNREGISTER_INI_ENTRIES();
1317:
1318: return SUCCESS;
1319: }
1320:
1321: PHP_RSHUTDOWN_FUNCTION(oci)
1322: {
1323: /* Check persistent connections and do the necessary actions if needed. If persistent_helper is
1324: * unable to process a pconnection because of a refcount, the processing would happen from
1325: * np-destructor which is called when refcount goes to zero - php_oci_pconnection_list_np_dtor
1326: */
1327: zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
1328:
1329: if (OCI_G(edition)) {
1330: efree(OCI_G(edition));
1331: }
1332:
1333: return SUCCESS;
1334: }
1335:
1336: PHP_MINFO_FUNCTION(oci)
1337: {
1338: char buf[32];
1339: char *ver;
1340:
1341: php_info_print_table_start();
1342: php_info_print_table_row(2, "OCI8 Support", "enabled");
1343: php_info_print_table_row(2, "Version", PHP_OCI8_VERSION);
1344: php_info_print_table_row(2, "Revision", "$Id: oci8.c,v 1.1.1.4 2014/06/15 20:03:52 misho Exp $");
1345:
1346: snprintf(buf, sizeof(buf), "%ld", OCI_G(num_persistent));
1347: php_info_print_table_row(2, "Active Persistent Connections", buf);
1348: snprintf(buf, sizeof(buf), "%ld", OCI_G(num_links));
1349: php_info_print_table_row(2, "Active Connections", buf);
1350:
1351: #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
1352: php_oci_client_get_version(&ver TSRMLS_CC);
1353: php_info_print_table_row(2, "Oracle Run-time Client Library Version", ver);
1354: efree(ver);
1355: #endif
1356: #if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
1357: snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
1358: #elif defined(PHP_OCI8_ORACLE_VERSION)
1359: snprintf(buf, sizeof(buf), "%s", PHP_OCI8_ORACLE_VERSION);
1360: #else
1361: snprintf(buf, sizeof(buf), "Unknown");
1362: #endif
1363: #if defined(HAVE_OCI_INSTANT_CLIENT)
1364: php_info_print_table_row(2, "Oracle Instant Client Version", buf);
1365: #else
1366: php_info_print_table_row(2, "Oracle Version", buf);
1367: #endif
1368:
1369: #if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
1370: #if defined(PHP_OCI8_DEF_DIR)
1371: php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DEF_DIR);
1372: #endif
1373: #if defined(PHP_OCI8_DEF_SHARED_LIBADD)
1374: php_info_print_table_row(2, "Libraries Used", PHP_OCI8_DEF_SHARED_LIBADD);
1375: #endif
1376: #endif
1377:
1378: php_info_print_table_row(2, "Temporary Lob support", "enabled");
1379: php_info_print_table_row(2, "Collections support", "enabled");
1380: php_info_print_table_end();
1381: DISPLAY_INI_ENTRIES();
1382: }
1383: /* }}} */
1384:
1385: /* list destructors {{{ */
1386:
1387: /* {{{ php_oci_connection_list_dtor()
1388: *
1389: * Non-persistent connection destructor
1390: */
1391: static void php_oci_connection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
1392: {
1393: php_oci_connection *connection = (php_oci_connection *)entry->ptr;
1394:
1395: if (connection) {
1396: php_oci_connection_close(connection TSRMLS_CC);
1397: OCI_G(num_links)--;
1398: }
1399: } /* }}} */
1400:
1401: /* {{{ php_oci_pconnection_list_dtor()
1402: *
1403: * Persistent connection destructor
1404: */
1405: static void php_oci_pconnection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
1406: {
1407: php_oci_connection *connection = (php_oci_connection *)entry->ptr;
1408:
1409: if (connection) {
1410: php_oci_connection_close(connection TSRMLS_CC);
1411: OCI_G(num_persistent)--;
1412: OCI_G(num_links)--;
1413: }
1414: } /* }}} */
1415:
1416: /* {{{ php_oci_pconnection_list_np_dtor()
1417: *
1418: * Non-Persistent destructor for persistent connection - This gets invoked when
1419: * the refcount of this goes to zero in the regular list
1420: */
1421: static void php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
1422: {
1423: php_oci_connection *connection = (php_oci_connection *)entry->ptr;
1424: zend_rsrc_list_entry *le;
1425:
1426: /*
1427: * We cannot get connection as NULL or as a stub in this function. This is the function that
1428: * turns a pconnection to a stub
1429: *
1430: * If oci_password_change() changed the password of a persistent connection, close the
1431: * connection and remove it from the persistent connection cache. This means subsequent scripts
1432: * will be prevented from being able to present the old (now invalid) password to a usable
1433: * connection to the database; they must use the new password.
1434: *
1435: * Check for conditions that warrant removal of the hash entry
1436: */
1437:
1438: if (!connection->is_open ||
1439: connection->passwd_changed ||
1440: (PG(connection_status) & PHP_CONNECTION_TIMEOUT) ||
1441: OCI_G(in_call)) {
1442:
1443: /* Remove the hash entry if present */
1444: if ((zend_hash_find(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void **) &le)== SUCCESS) && (le->type == le_pconnection) && (le->ptr == connection)) {
1445: zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
1446: }
1447: else {
1448: php_oci_connection_close(connection TSRMLS_CC);
1449: OCI_G(num_persistent)--;
1450: }
1451:
1452: if (OCI_G(debug_mode)) {
1453: php_printf ("OCI8 DEBUG L1: np_dtor cleaning up: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
1454: }
1455: }
1456: else {
1457: /*
1458: * Release the connection to underlying pool. We do this unconditionally so that
1459: * out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect
1460: * semantics. With the PECL OCI 1.3.x extensions, we release pconnections when oci_close
1461: * takes the refcount to zero.
1462: *
1463: * If oci_old_close_semantics is set, we artifically bump up the refcount and decremented
1464: * only at request shutdown.
1465: */
1466: php_oci_connection_release(connection TSRMLS_CC);
1467:
1468: if (OCI_G(debug_mode)) {
1469: php_printf ("OCI8 DEBUG L1: np_dtor releasing: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
1470: }
1471: }
1472: } /* }}} */
1473:
1474: /* {{{ php_oci_statement_list_dtor()
1475: *
1476: * Statement destructor
1477: */
1478: static void php_oci_statement_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
1479: {
1480: php_oci_statement *statement = (php_oci_statement *)entry->ptr;
1481: php_oci_statement_free(statement TSRMLS_CC);
1482: } /* }}} */
1483:
1484: /* {{{ php_oci_descriptor_list_dtor()
1485: *
1486: * Descriptor destructor
1487: */
1488: static void php_oci_descriptor_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
1489: {
1490: php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
1491: php_oci_lob_free(descriptor TSRMLS_CC);
1492: } /* }}} */
1493:
1494: /* {{{ php_oci_collection_list_dtor()
1495: *
1496: * Collection destructor
1497: */
1498: static void php_oci_collection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
1499: {
1500: php_oci_collection *collection = (php_oci_collection *)entry->ptr;
1501: php_oci_collection_close(collection TSRMLS_CC);
1502: } /* }}} */
1503:
1504: /* }}} */
1505:
1506: /* Hash Destructors {{{ */
1507:
1508: /* {{{ php_oci_define_hash_dtor()
1509: *
1510: * Define hash destructor
1511: */
1512: void php_oci_define_hash_dtor(void *data)
1513: {
1514: php_oci_define *define = (php_oci_define *) data;
1515:
1516: zval_ptr_dtor(&define->zval);
1517:
1518: if (define->name) {
1519: efree(define->name);
1520: define->name = NULL;
1521: }
1522: }
1523: /* }}} */
1524:
1525: /* {{{ php_oci_bind_hash_dtor()
1526: *
1527: * Bind hash destructor
1528: */
1529: void php_oci_bind_hash_dtor(void *data)
1530: {
1531: php_oci_bind *bind = (php_oci_bind *) data;
1532:
1533: if (bind->array.elements) {
1534: efree(bind->array.elements);
1535: }
1536:
1537: if (bind->array.element_lengths) {
1538: efree(bind->array.element_lengths);
1539: }
1540:
1541: if (bind->array.indicators) {
1542: efree(bind->array.indicators);
1543: }
1544:
1545: zval_ptr_dtor(&bind->zval);
1546: }
1547: /* }}} */
1548:
1549: /* {{{ php_oci_column_hash_dtor()
1550: *
1551: * Column hash destructor
1552: */
1553: void php_oci_column_hash_dtor(void *data)
1554: {
1555: php_oci_out_column *column = (php_oci_out_column *) data;
1556: TSRMLS_FETCH();
1557:
1558: if (column->stmtid) {
1559: zend_list_delete(column->stmtid);
1560: }
1561:
1562: if (column->is_descr) {
1563: zend_list_delete(column->descid);
1564: }
1565:
1566: if (column->data) {
1567: efree(column->data);
1568: }
1569:
1570: if (column->name) {
1571: efree(column->name);
1572: }
1573: }
1574: /* }}} */
1575:
1576: /* {{{ php_oci_descriptor_flush_hash_dtor()
1577: *
1578: * Flush descriptors on commit
1579: */
1580: void php_oci_descriptor_flush_hash_dtor(void *data)
1581: {
1582: php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
1583: TSRMLS_FETCH();
1584:
1585: if (descriptor && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
1586: php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
1587: descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
1588: }
1589: data = NULL;
1590: }
1591: /* }}} */
1592:
1593: /* }}} */
1594:
1595: /* {{{ php_oci_connection_descriptors_free()
1596: *
1597: * Free descriptors for a connection
1598: */
1599: void php_oci_connection_descriptors_free(php_oci_connection *connection TSRMLS_DC)
1600: {
1601: zend_hash_destroy(connection->descriptors);
1602: efree(connection->descriptors);
1603: connection->descriptors = NULL;
1604: connection->descriptor_count = 0;
1605: }
1606: /* }}} */
1607:
1608:
1609: /* {{{ php_oci_error()
1610: *
1611: * Fetch & print out error message if we get an error
1612: * Returns an Oracle error number
1613: */
1614: sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC)
1615: {
1616: text *errbuf = (text *)NULL;
1617: sb4 errcode = 0;
1618:
1619: switch (status) {
1620: case OCI_SUCCESS:
1621: break;
1622: case OCI_SUCCESS_WITH_INFO:
1623: errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
1624: if (errbuf) {
1625: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", errbuf);
1626: efree(errbuf);
1627: } else {
1628: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: failed to fetch error message");
1629: }
1630: break;
1631: case OCI_NEED_DATA:
1632: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NEED_DATA");
1633: break;
1634: case OCI_NO_DATA:
1635: errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
1636: if (errbuf) {
1637: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
1638: efree(errbuf);
1639: } else {
1640: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NO_DATA: failed to fetch error message");
1641: }
1642: break;
1643: case OCI_ERROR:
1644: errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
1645: if (errbuf) {
1646: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
1647: efree(errbuf);
1648: } else {
1649: php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to fetch error message");
1650: }
1651: break;
1652: case OCI_INVALID_HANDLE:
1653: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_INVALID_HANDLE");
1654: break;
1655: case OCI_STILL_EXECUTING:
1656: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_STILL_EXECUTING");
1657: break;
1658: case OCI_CONTINUE:
1659: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CONTINUE");
1660: break;
1661: default:
1662: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown OCI error code: %d", status);
1663: break;
1664: }
1665: return errcode;
1666: }
1667: /* }}} */
1668:
1669: /* {{{ php_oci_fetch_errmsg()
1670: *
1671: * Fetch error message into the buffer from the error handle provided
1672: */
1673: sb4 php_oci_fetch_errmsg(OCIError *error_handle, text **error_buf TSRMLS_DC)
1674: {
1675: sb4 error_code = 0;
1676: text err_buf[PHP_OCI_ERRBUF_LEN];
1677:
1678: memset(err_buf, 0, sizeof(err_buf));
1679: PHP_OCI_CALL(OCIErrorGet, (error_handle, (ub4)1, NULL, &error_code, err_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR));
1680:
1681: if (error_code) {
1682: int err_buf_len = strlen((char *)err_buf);
1683:
1684: if (err_buf_len && err_buf[err_buf_len - 1] == '\n') {
1685: err_buf[err_buf_len - 1] = '\0';
1686: }
1687: if (err_buf_len && error_buf) {
1688: *error_buf = NULL;
1689: *error_buf = (text *)estrndup((char *)err_buf, err_buf_len);
1690: }
1691: }
1692: return error_code;
1693: } /* }}} */
1694:
1695: /* {{{ php_oci_fetch_sqltext_offset()
1696: *
1697: * Compute offset in the SQL statement
1698: */
1699: int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset TSRMLS_DC)
1700: {
1701: sword errstatus;
1702:
1703: *sqltext = NULL;
1704: *error_offset = 0;
1705: PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
1706:
1707: if (errstatus != OCI_SUCCESS) {
1708: statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
1709: PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1710: return 1;
1711: }
1712:
1713: PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
1714:
1715: if (errstatus != OCI_SUCCESS) {
1716: statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
1717: PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
1718: return 1;
1719: }
1720: return 0;
1721: } /* }}} */
1722:
1723: /* {{{ php_oci_do_connect()
1724: *
1725: * Connect wrapper
1726: */
1727: void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
1728: {
1729: php_oci_connection *connection;
1730: char *username, *password;
1731: char *dbname = NULL, *charset = NULL;
1732: int username_len = 0, password_len = 0;
1733: int dbname_len = 0, charset_len = 0;
1734: long session_mode = OCI_DEFAULT;
1735:
1736: /* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
1737: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ssl", &username, &username_len, &password, &password_len, &dbname, &dbname_len, &charset, &charset_len, &session_mode) == FAILURE) {
1738: return;
1739: }
1740:
1741: if (!charset_len) {
1742: charset = NULL;
1743: }
1744:
1745: connection = php_oci_do_connect_ex(username, username_len, password, password_len, NULL, 0, dbname, dbname_len, charset, session_mode, persistent, exclusive TSRMLS_CC);
1746:
1747: if (!connection) {
1748: RETURN_FALSE;
1749: }
1750: RETURN_RESOURCE(connection->rsrc_id);
1751:
1752: } /* }}} */
1753:
1754: /* {{{ php_oci_do_connect_ex()
1755: *
1756: * The real connect function. Allocates all the resources needed, establishes the connection and
1757: * returns the result handle (or NULL)
1758: */
1759: php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC)
1760: {
1761: zend_rsrc_list_entry *le;
1762: zend_rsrc_list_entry new_le;
1763: php_oci_connection *connection = NULL;
1764: smart_str hashed_details = {0};
1765: time_t timestamp;
1766: php_oci_spool *session_pool = NULL;
1767: zend_bool use_spool = 1; /* Default is to use client-side session pool */
1768: zend_bool ping_done = 0;
1769:
1770: ub2 charsetid = 0;
1771: ub2 charsetid_nls_lang = 0;
1772:
1773: if (session_mode & ~(OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
1774: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid session mode specified (%ld)", session_mode);
1775: return NULL;
1776: }
1777: if (session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
1778: if ((session_mode & OCI_SYSOPER) && (session_mode & OCI_SYSDBA)) {
1779: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SYSDBA and OCI_SYSOPER cannot be used together");
1780: return NULL;
1781: }
1782: if (session_mode & PHP_OCI_CRED_EXT) {
1783: #ifdef PHP_WIN32
1784: /* Disable external authentication on Windows as Impersonation is not yet handled.
1785: * TODO: Re-enable this once OCI provides capability.
1786: */
1787: php_error_docref(NULL TSRMLS_CC, E_WARNING, "External Authentication is not supported on Windows");
1788: return NULL;
1789: #endif
1790: if (username_len != 1 || username[0] != '/' || password_len != 0) {
1791: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CRED_EXT can only be used with a username of \"/\" and a NULL password");
1792: return NULL;
1793: }
1794: }
1795: if (session_mode & (OCI_SYSOPER | OCI_SYSDBA)) {
1796: /* Increase security by not caching privileged oci_pconnect() connections. The
1797: * connection becomes equivalent to oci_connect() or oci_new_connect().
1798: */
1799: persistent = 0;
1800: if (!OCI_G(privileged_connect)) {
1801: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA");
1802: return NULL;
1803: }
1804: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
1805: /* Safe mode has been removed in PHP 5.4 */
1806: if (PG(safe_mode)) {
1807: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled in Safe Mode");
1808: return NULL;
1809: }
1810: #endif
1811: }
1812: }
1813:
1814: /* Initialize global handles if they weren't initialized before */
1815: if (OCI_G(env) == NULL) {
1816: php_oci_init_global_handles(TSRMLS_C);
1817: if (OCI_G(env) == NULL) {
1818: return NULL;
1819: }
1820: }
1821:
1822: /* We cannot use the new session create logic (OCISessionGet from
1823: * client-side session pool) when privileged connect or password
1824: * change is attempted or OCI_CRED_EXT mode is specified.
1825: * TODO: Re-enable this when OCI provides support.
1826: */
1827: if ((session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) || (new_password_len)) {
1828: use_spool = 0;
1829: }
1830:
1831: smart_str_appendl_ex(&hashed_details, "oci8***", sizeof("oci8***") - 1, 0);
1832: smart_str_appendl_ex(&hashed_details, username, username_len, 0);
1833: smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
1834:
1835: /* DRCP: connection_class is an attribute of a connection */
1836: if (OCI_G(connection_class)){
1837: smart_str_appendl_ex(&hashed_details, OCI_G(connection_class), strlen(OCI_G(connection_class)), 0);
1838: }
1839: smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
1840:
1841: /* Add edition attribute to the hash */
1842: if (OCI_G(edition)){
1843: smart_str_appendl_ex(&hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
1844: }
1845: smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
1846:
1847: if (password_len) {
1848: ulong password_hash;
1849: password_hash = zend_inline_hash_func(password, password_len);
1850: smart_str_append_unsigned_ex(&hashed_details, password_hash, 0);
1851: }
1852: smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
1853:
1854: if (dbname) {
1855: smart_str_appendl_ex(&hashed_details, dbname, dbname_len, 0);
1856: }
1857: smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
1858:
1859: if (charset && *charset) {
1860: PHP_OCI_CALL_RETURN(charsetid, OCINlsCharSetNameToId, (OCI_G(env), (CONST oratext *)charset));
1861: if (!charsetid) {
1862: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid character set name: %s", charset);
1863: } else {
1864: smart_str_append_unsigned_ex(&hashed_details, charsetid, 0);
1865: }
1866: }
1867:
1868: /* use NLS_LANG if no or invalid charset specified */
1869: if (!charsetid) {
1870: size_t rsize = 0;
1871: sword result;
1872:
1873: PHP_OCI_CALL_RETURN(result, OCINlsEnvironmentVariableGet, (&charsetid_nls_lang, 0, OCI_NLS_CHARSET_ID, 0, &rsize));
1874: if (result != OCI_SUCCESS) {
1875: charsetid_nls_lang = 0;
1876: }
1877: smart_str_append_unsigned_ex(&hashed_details, charsetid_nls_lang, 0);
1878: }
1879:
1880: timestamp = time(NULL);
1881:
1882: smart_str_append_unsigned_ex(&hashed_details, session_mode, 0);
1883: smart_str_0(&hashed_details);
1884:
1885: /* make it lowercase */
1886: php_strtolower(hashed_details.c, hashed_details.len);
1887:
1888: if (!exclusive && !new_password) {
1889: zend_bool found = 0;
1890:
1891: if (persistent && zend_hash_find(&EG(persistent_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
1892: found = 1;
1893: /* found */
1894: if (le->type == le_pconnection) {
1895: connection = (php_oci_connection *)le->ptr;
1896: }
1897: } else if (!persistent && zend_hash_find(&EG(regular_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
1898: found = 1;
1899: if (le->type == le_index_ptr) {
1900: int type, link;
1901: void *ptr;
1902:
1903: link = OCI8_PTR_TO_INT(le->ptr);
1904: ptr = zend_list_find(link,&type);
1905: if (ptr && (type == le_connection)) {
1906: connection = (php_oci_connection *)ptr;
1907: }
1908: }
1909: }
1910:
1911: /* Debug statements {{{ */
1912: if (OCI_G(debug_mode)) {
1913: if (connection && connection->is_stub) {
1914: php_printf ("OCI8 DEBUG L1: Got a cached stub: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
1915: } else if (connection) {
1916: php_printf ("OCI8 DEBUG L1: Got a cached connection: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
1917: } else {
1918: php_printf ("OCI8 DEBUG L1: Got NO cached connection at (%s:%d) \n", __FILE__, __LINE__);
1919: }
1920: } /* }}} */
1921:
1922: /* If we got a pconnection stub, then 'load'(OCISessionGet) the real connection from its
1923: * private spool A connection is a stub if it is only a cached structure and the real
1924: * connection is released to its underlying private session pool. We currently do not have
1925: * stub support for non-persistent conns.
1926: *
1927: * TODO: put in negative code for non-persistent stubs
1928: */
1929: if (connection && connection->is_persistent && connection->is_stub) {
1930: if (php_oci_create_session(connection, NULL, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
1931: smart_str_free_ex(&hashed_details, 0);
1932: zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
1933:
1934: return NULL;
1935: }
1936: /* We do the ping in php_oci_create_session, no need to ping again below */
1937: ping_done = 1;
1938: }
1939:
1940: if (connection) {
1941: if (connection->is_open) {
1942: /* found an open connection. now ping it */
1943: if (connection->is_persistent) {
1944: int rsrc_type;
1945:
1946: /* Check connection liveness in the following order:
1947: * 1) always check OCI_ATTR_SERVER_STATUS
1948: * 2) see if it's time to ping it
1949: * 3) ping it if needed
1950: */
1951: if (php_oci_connection_status(connection TSRMLS_CC)) {
1952: /* Only ping if:
1953: *
1954: * 1) next_ping > 0, which means that ping_interval is not -1 (aka "Off")
1955: *
1956: * 2) current_timestamp > next_ping, which means "it's time to check if it's
1957: * still alive"
1958: */
1959: if (!ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection TSRMLS_CC)) {
1960: /* server died */
1961: } else {
1962: php_oci_connection *tmp;
1963:
1964: /* okay, the connection is open and the server is still alive */
1965: connection->used_this_request = 1;
1966: tmp = (php_oci_connection *)zend_list_find(connection->rsrc_id, &rsrc_type);
1967:
1968: if (tmp != NULL && rsrc_type == le_pconnection && strlen(tmp->hash_key) == hashed_details.len &&
1969: memcmp(tmp->hash_key, hashed_details.c, hashed_details.len) == 0 && zend_list_addref(connection->rsrc_id) == SUCCESS) {
1970: /* do nothing */
1971: } else {
1972: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
1973: connection->rsrc_id = zend_list_insert(connection, le_pconnection TSRMLS_CC);
1974: #else
1975: connection->rsrc_id = zend_list_insert(connection, le_pconnection);
1976: #endif
1977: /* Persistent connections: For old close semantics we artificially
1978: * bump up the refcount to prevent the non-persistent destructor
1979: * from getting called until request shutdown. The refcount is
1980: * decremented in the persistent helper
1981: */
1982: if (OCI_G(old_oci_close_semantics)) {
1983: zend_list_addref(connection->rsrc_id);
1984: }
1985: }
1986: smart_str_free_ex(&hashed_details, 0);
1987: return connection;
1988: }
1989: }
1990: /* server died */
1991: } else {
1992: /* we do not ping non-persistent connections */
1993: smart_str_free_ex(&hashed_details, 0);
1994: zend_list_addref(connection->rsrc_id);
1995: return connection;
1996: }
1997: } /* is_open is true? */
1998:
1999: /* Server died - connection not usable. The is_open=true can also fall through to here,
2000: * if ping fails
2001: */
2002: if (persistent){
2003: int rsrc_type;
2004:
2005: connection->is_open = 0;
2006: connection->used_this_request = 1;
2007:
2008: /* We have to do a hash_del but need to preserve the resource if there is a positive
2009: * refcount. Set the data pointer in the list entry to NULL
2010: */
2011: if (connection == zend_list_find(connection->rsrc_id, &rsrc_type) && rsrc_type == le_pconnection) {
2012: le->ptr = NULL;
2013: }
2014:
2015: zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
2016: } else {
2017: /* We only remove the hash entry. The resource and the list entry with its pointer
2018: * to the resource are still intact
2019: */
2020: zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
2021: }
2022:
2023: connection = NULL;
2024: } else if (found) {
2025: /* found something, but it's not a connection, delete it */
2026: if (persistent) {
2027: zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
2028: } else {
2029: zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
2030: }
2031: }
2032: }
2033:
2034: /* Check if we have reached max_persistent. If so, try to remove a few timed-out connections. As
2035: * a last resort, return a non-persistent connection.
2036: */
2037: if (persistent) {
2038: zend_bool alloc_non_persistent = 0;
2039:
2040: if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
2041: /* try to find an idle connection and kill it */
2042: zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
2043:
2044: if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
2045: /* all persistent connactions are in use, fallback to non-persistent connection creation */
2046: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Too many open persistent connections (%ld)", OCI_G(num_persistent));
2047: alloc_non_persistent = 1;
2048: }
2049: }
2050:
2051: if (alloc_non_persistent) {
2052: connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
2053: connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
2054: connection->is_persistent = 0;
2055: } else {
2056: connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
2057: if (connection == NULL) {
2058: return NULL;
2059: }
2060: connection->hash_key = zend_strndup(hashed_details.c, hashed_details.len);
2061: if (connection->hash_key == NULL) {
2062: free(connection);
2063: return NULL;
2064: }
2065: connection->is_persistent = 1;
2066: }
2067: } else {
2068: connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
2069: connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
2070: connection->is_persistent = 0;
2071: }
2072:
2073: /* {{{ Get the session pool that suits this connection request from the persistent list. This
2074: * step is only for non-persistent connections as persistent connections have private session
2075: * pools. Non-persistent conns use shared session pool to allow for optimizations such as
2076: * caching the physical connection (for DRCP) even when the non-persistent php connection is
2077: * destroyed.
2078: *
2079: * TODO: Unconditionally do this once OCI provides extended OCISessionGet capability
2080: */
2081: if (use_spool && !connection->is_persistent) {
2082: if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang TSRMLS_CC))==NULL)
2083: {
2084: php_oci_connection_close(connection TSRMLS_CC);
2085: smart_str_free_ex(&hashed_details, 0);
2086: return NULL;
2087: }
2088: } /* }}} */
2089:
2090: connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0;
2091:
2092: /* Mark password as unchanged by PHP during the duration of the database session */
2093: connection->passwd_changed = 0;
2094:
2095: smart_str_free_ex(&hashed_details, 0);
2096:
2097: if (charsetid) {
2098: connection->charset = charsetid;
2099: } else {
2100: connection->charset = charsetid_nls_lang;
2101: }
2102:
2103: /* Old session creation semantics when session pool cannot be used Eg: privileged
2104: * connect/password change
2105: */
2106: if (!use_spool) {
2107: if (php_oci_old_create_session(connection, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
2108: php_oci_connection_close(connection TSRMLS_CC);
2109: return NULL;
2110: }
2111: } else {
2112: /* create using the client-side session pool */
2113: if (php_oci_create_session(connection, session_pool, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
2114: php_oci_connection_close(connection TSRMLS_CC);
2115: return NULL;
2116: }
2117: }
2118:
2119: /* Mark it as open */
2120: connection->is_open = 1;
2121:
2122: /* add to the appropriate hash */
2123: if (connection->is_persistent) {
2124: new_le.ptr = connection;
2125: new_le.type = le_pconnection;
2126: connection->used_this_request = 1;
2127: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
2128: connection->rsrc_id = zend_list_insert(connection, le_pconnection TSRMLS_CC);
2129: #else
2130: connection->rsrc_id = zend_list_insert(connection, le_pconnection);
2131: #endif
2132:
2133: /* Persistent connections: For old close semantics we artificially bump up the refcount to
2134: * prevent the non-persistent destructor from getting called until request shutdown. The
2135: * refcount is decremented in the persistent helper
2136: */
2137: if (OCI_G(old_oci_close_semantics)) {
2138: zend_list_addref(connection->rsrc_id);
2139: }
2140: zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
2141: OCI_G(num_persistent)++;
2142: OCI_G(num_links)++;
2143: } else if (!exclusive) {
2144: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
2145: connection->rsrc_id = zend_list_insert(connection, le_connection TSRMLS_CC);
2146: #else
2147: connection->rsrc_id = zend_list_insert(connection, le_connection);
2148: #endif
2149: new_le.ptr = OCI8_INT_TO_PTR(connection->rsrc_id);
2150: new_le.type = le_index_ptr;
2151: zend_hash_update(&EG(regular_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
2152: OCI_G(num_links)++;
2153: } else {
2154: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
2155: connection->rsrc_id = zend_list_insert(connection, le_connection TSRMLS_CC);
2156: #else
2157: connection->rsrc_id = zend_list_insert(connection, le_connection);
2158: #endif
2159: OCI_G(num_links)++;
2160: }
2161:
2162: /* Debug statements {{{ */
2163: if (OCI_G(debug_mode)) {
2164: if (connection->is_persistent) {
2165: php_printf ("OCI8 DEBUG L1: New Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
2166: } else {
2167: php_printf ("OCI8 DEBUG L1: New Non-Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
2168: }
2169: php_printf ("OCI8 DEBUG L1: num_persistent=(%ld), num_links=(%ld) at (%s:%d) \n", OCI_G(num_persistent), OCI_G(num_links), __FILE__, __LINE__);
2170: } /* }}} */
2171:
2172: return connection;
2173: }
2174: /* }}} */
2175:
2176: /* {{{ php_oci_connection_ping()
2177: *
2178: * Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version
2179: */
2180: static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC)
2181: {
2182: /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
2183: * such as from Pre-10.1 servers, the error is still from the server and we would have
2184: * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
2185: * Pre-10.2 clients
2186: */
2187: #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */
2188: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
2189: #else
2190: char version[256];
2191: /* use good old OCIServerVersion() */
2192: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX));
2193: #endif
2194:
2195: if (OCI_G(errcode) == OCI_SUCCESS) {
2196: return 1;
2197: } else {
2198: sb4 error_code = 0;
2199: text tmp_buf[OCI_ERROR_MAXMSG_SIZE];
2200:
2201: /* Treat ORA-1010 as a successful Ping */
2202: OCIErrorGet(OCI_G(err), (ub4)1, NULL, &error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ERROR);
2203: if (error_code == 1010) {
2204: return 1;
2205: }
2206: }
2207:
2208: /* ignore errors here, just return failure
2209: * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
2210: return 0;
2211: }
2212: /* }}} */
2213:
2214: /* {{{ php_oci_connection_status()
2215: *
2216: * Check connection status (pre-ping check)
2217: */
2218: static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC)
2219: {
2220: ub4 ss = 0;
2221:
2222: /* get OCI_ATTR_SERVER_STATUS */
2223: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err)));
2224:
2225: if (OCI_G(errcode) == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) {
2226: return 1;
2227: }
2228:
2229: /* ignore errors here, just return failure
2230: * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
2231: return 0;
2232: }
2233: /* }}} */
2234:
2235: /* {{{ php_oci_connection_rollback()
2236: *
2237: * Rollback connection
2238: */
2239: int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC)
2240: {
2241: PHP_OCI_CALL_RETURN(connection->errcode, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
2242: connection->needs_commit = 0;
2243:
2244: if (connection->errcode != OCI_SUCCESS) {
2245: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
2246: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
2247: return 1;
2248: }
2249: return 0;
2250: } /* }}} */
2251:
2252: /* {{{ php_oci_connection_commit()
2253: *
2254: * Commit connection
2255: */
2256: int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
2257: {
2258: PHP_OCI_CALL_RETURN(connection->errcode, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
2259: connection->needs_commit = 0;
2260:
2261: if (connection->errcode != OCI_SUCCESS) {
2262: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
2263: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
2264: return 1;
2265: }
2266: return 0;
2267: } /* }}} */
2268:
2269: /* {{{ php_oci_connection_close()
2270: *
2271: * Close the connection and free all its resources
2272: */
2273: static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
2274: {
2275: int result = 0;
2276: zend_bool in_call_save = OCI_G(in_call);
2277:
2278: if (!connection->is_stub) {
2279: /* Release resources associated with connection */
2280: php_oci_connection_release(connection TSRMLS_CC);
2281: }
2282:
2283: if (!connection->using_spool && connection->svc) {
2284: PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0));
2285: }
2286:
2287: if (connection->err) {
2288: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->err, (ub4) OCI_HTYPE_ERROR));
2289: }
2290: if (connection->authinfo) {
2291: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->authinfo, (ub4) OCI_HTYPE_AUTHINFO));
2292: }
2293:
2294: /* No Handlefrees for session pool connections */
2295: if (!connection->using_spool) {
2296: if (connection->session) {
2297: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->session, OCI_HTYPE_SESSION));
2298: }
2299:
2300: if (connection->is_attached) {
2301: PHP_OCI_CALL(OCIServerDetach, (connection->server, OCI_G(err), OCI_DEFAULT));
2302: }
2303:
2304: if (connection->svc) {
2305: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
2306: }
2307:
2308: if (connection->server) {
2309: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->server, (ub4) OCI_HTYPE_SERVER));
2310: }
2311:
2312: if (connection->env) {
2313: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
2314: }
2315: } else if (connection->private_spool) {
2316: /* Keep this as the last member to be freed, as there are dependencies
2317: * (like env) on the session pool
2318: */
2319: php_oci_spool_close(connection->private_spool TSRMLS_CC);
2320: }
2321:
2322: if (connection->is_persistent) {
2323: if (connection->hash_key) {
2324: free(connection->hash_key);
2325: }
2326: free(connection);
2327: } else {
2328: if (connection->hash_key) {
2329: efree(connection->hash_key);
2330: }
2331: efree(connection);
2332: }
2333: connection = NULL;
2334: OCI_G(in_call) = in_call_save;
2335: return result;
2336: } /* }}} */
2337:
2338: /* {{{ php_oci_connection_release()
2339: *
2340: * Release the connection's resources. This involves freeing descriptors and rolling back
2341: * transactions, setting timeout-related parameters etc. For session-pool using connections, the
2342: * underlying connection is released to its session pool.
2343: */
2344: int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
2345: {
2346: int result = 0;
2347: zend_bool in_call_save = OCI_G(in_call);
2348: time_t timestamp = time(NULL);
2349:
2350: if (connection->is_stub) {
2351: return 0;
2352: }
2353:
2354: if (connection->descriptors) {
2355: php_oci_connection_descriptors_free(connection TSRMLS_CC);
2356: }
2357:
2358: if (connection->svc) {
2359: /* rollback outstanding transactions */
2360: if (connection->needs_commit) {
2361: if (php_oci_connection_rollback(connection TSRMLS_CC)) {
2362: /* rollback failed */
2363: result = 1;
2364: }
2365: }
2366: }
2367:
2368: if (OCI_G(persistent_timeout) > 0) {
2369: connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
2370: }
2371:
2372: /* We may have half-cooked connections to clean up */
2373: if (connection->next_pingp) {
2374: if (OCI_G(ping_interval) >= 0) {
2375: *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
2376: } else {
2377: /* ping_interval is -1 */
2378: *(connection->next_pingp) = 0;
2379: }
2380: }
2381:
2382: /* Release the session (stubs are filtered out at the beginning)*/
2383: if (connection->using_spool) {
2384: ub4 rlsMode = OCI_DEFAULT;
2385:
2386: if (result) {
2387: rlsMode |= OCI_SESSRLS_DROPSESS;
2388: }
2389:
2390: /* Sessions for non-persistent connections should be dropped. For 11 and above, the session
2391: * pool has its own mechanism for doing so for purity NEW connections. We need to do so
2392: * explicitly for 10.2 and earlier.
2393: */
2394: #if (!(OCI_MAJOR_VERSION >= 11))
2395: if (!connection->is_persistent) {
2396: rlsMode |= OCI_SESSRLS_DROPSESS;
2397: }
2398: #endif
2399:
2400: if (connection->svc) {
2401: PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
2402: 0, rlsMode));
2403: }
2404: /* It no longer has relation with the database session. However authinfo and env are
2405: * cached
2406: */
2407: connection->svc = NULL;
2408: connection->server = NULL;
2409: connection->session = NULL;
2410:
2411: connection->is_attached = connection->is_open = connection->needs_commit = connection->used_this_request = 0;
2412: connection->is_stub = 1;
2413:
2414: /* Cut the link between the connection structure and the time_t structure allocated within
2415: * the OCI session
2416: */
2417: connection->next_pingp = NULL;
2418: }
2419:
2420: OCI_G(in_call) = in_call_save;
2421: return result;
2422: } /* }}} */
2423:
2424: /* {{{ php_oci_password_change()
2425: *
2426: * Change password for the user with the username given
2427: */
2428: int php_oci_password_change(php_oci_connection *connection, char *user, int user_len, char *pass_old, int pass_old_len, char *pass_new, int pass_new_len TSRMLS_DC)
2429: {
2430: PHP_OCI_CALL_RETURN(connection->errcode, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT));
2431:
2432: if (connection->errcode != OCI_SUCCESS) {
2433: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
2434: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
2435: return 1;
2436: }
2437: connection->passwd_changed = 1;
2438: return 0;
2439: } /* }}} */
2440:
2441:
2442: /* {{{ php_oci_client_get_version()
2443: *
2444: * Get Oracle client library version
2445: */
2446: void php_oci_client_get_version(char **version TSRMLS_DC)
2447: {
2448: char version_buff[256];
2449: sword major_version = 0;
2450: sword minor_version = 0;
2451: sword update_num = 0;
2452: sword patch_num = 0;
2453: sword port_update_num = 0;
2454:
2455: #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIClientVersion only available 10.2 onwards */
2456: PHP_OCI_CALL(OCIClientVersion, (&major_version, &minor_version, &update_num, &patch_num, &port_update_num));
2457: snprintf(version_buff, sizeof(version_buff), "%d.%d.%d.%d.%d", major_version, minor_version, update_num, patch_num, port_update_num);
2458: #else
2459: memcpy(version_buff, "Unknown", sizeof("Unknown"));
2460: #endif
2461: *version = estrdup(version_buff);
2462: } /* }}} */
2463:
2464:
2465: /* {{{ php_oci_server_get_version()
2466: *
2467: * Get Oracle server version
2468: */
2469: int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC)
2470: {
2471: char version_buff[256];
2472:
2473: PHP_OCI_CALL_RETURN(connection->errcode, OCIServerVersion, (connection->svc, connection->err, (text *)version_buff, sizeof(version_buff), OCI_HTYPE_SVCCTX));
2474:
2475: if (connection->errcode != OCI_SUCCESS) {
2476: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
2477: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
2478: return 1;
2479: }
2480:
2481: *version = estrdup(version_buff);
2482: return 0;
2483: } /* }}} */
2484:
2485: /* {{{ php_oci_column_to_zval()
2486: *
2487: * Convert php_oci_out_column struct into zval
2488: */
2489: int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSRMLS_DC)
2490: {
2491: php_oci_descriptor *descriptor;
2492: ub4 lob_length;
2493: int column_size;
2494: char *lob_buffer;
2495: int lob_fetch_status;
2496:
2497: if (column->indicator == -1) { /* column is NULL */
2498: ZVAL_NULL(value);
2499: return 0;
2500: }
2501:
2502: if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
2503: ZVAL_RESOURCE(value, column->stmtid);
2504: zend_list_addref(column->stmtid);
2505: } else if (column->is_descr) {
2506:
2507: if (column->data_type != SQLT_RDD) {
2508: int rsrc_type;
2509:
2510: /* reset descriptor's length */
2511: descriptor = (php_oci_descriptor *) zend_list_find(column->descid, &rsrc_type);
2512:
2513: if (!descriptor || rsrc_type != le_descriptor) {
2514: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find LOB descriptor #%d", column->descid);
2515: return 1;
2516: }
2517:
2518: descriptor->lob_size = -1;
2519: descriptor->lob_current_position = 0;
2520: descriptor->buffering = 0;
2521: }
2522:
2523: if (column->data_type != SQLT_RDD && (mode & PHP_OCI_RETURN_LOBS)) {
2524: /* PHP_OCI_RETURN_LOBS means that we want the content of the LOB back instead of the locator */
2525:
2526: lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, &lob_buffer, &lob_length TSRMLS_CC);
2527: php_oci_temp_lob_close(descriptor TSRMLS_CC);
2528: if (lob_fetch_status) {
2529: ZVAL_FALSE(value);
2530: return 1;
2531: } else {
2532: if (lob_length > 0) {
2533: ZVAL_STRINGL(value, lob_buffer, lob_length, 0);
2534: } else {
2535: ZVAL_EMPTY_STRING(value);
2536: }
2537: return 0;
2538: }
2539: } else {
2540: /* return the locator */
2541: object_init_ex(value, oci_lob_class_entry_ptr);
2542: add_property_resource(value, "descriptor", column->descid);
2543: zend_list_addref(column->descid);
2544: }
2545: } else {
2546: switch (column->retcode) {
2547: case 0:
2548: /* intact value */
2549: if (column->piecewise) {
2550: column_size = column->retlen4;
2551: } else {
2552: column_size = column->retlen;
2553: }
2554: break;
2555:
2556: default:
2557: ZVAL_FALSE(value);
2558: return 0;
2559: }
2560:
2561: ZVAL_STRINGL(value, column->data, column_size, 1);
2562: }
2563: return 0;
2564: }
2565: /* }}} */
2566:
2567: /* {{{ php_oci_fetch_row()
2568: *
2569: * Fetch the next row from the given statement
2570: */
2571: void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
2572: {
2573: zval *z_statement, *array;
2574: php_oci_statement *statement;
2575: php_oci_out_column *column;
2576: ub4 nrows = 1;
2577: int i;
2578: long fetch_mode = 0;
2579:
2580: if (expected_args > 2) {
2581: /* only for ocifetchinto BC */
2582:
2583: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|l", &z_statement, &array, &fetch_mode) == FAILURE) {
2584: return;
2585: }
2586:
2587: if (ZEND_NUM_ARGS() == 2) {
2588: fetch_mode = mode;
2589: }
2590: } else if (expected_args == 2) {
2591: /* only for oci_fetch_array() */
2592:
2593: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_statement, &fetch_mode) == FAILURE) {
2594: return;
2595: }
2596:
2597: if (ZEND_NUM_ARGS() == 1) {
2598: fetch_mode = mode;
2599: }
2600: } else {
2601: /* for all oci_fetch_*() */
2602:
2603: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
2604: return;
2605: }
2606:
2607: fetch_mode = mode;
2608: }
2609:
2610: if (!(fetch_mode & PHP_OCI_NUM) && !(fetch_mode & PHP_OCI_ASSOC)) {
2611: /* none of the modes present, use the default one */
2612: if (mode & PHP_OCI_ASSOC) {
2613: fetch_mode |= PHP_OCI_ASSOC;
2614: }
2615: if (mode & PHP_OCI_NUM) {
2616: fetch_mode |= PHP_OCI_NUM;
2617: }
2618: }
2619:
2620: PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
2621:
2622: if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
2623: RETURN_FALSE;
2624: }
2625:
2626: array_init(return_value);
2627:
2628: for (i = 0; i < statement->ncolumns; i++) {
2629:
2630: column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
2631:
2632: if (column == NULL) {
2633: continue;
2634: }
2635: if ((column->indicator == -1) && ((fetch_mode & PHP_OCI_RETURN_NULLS) == 0)) {
2636: continue;
2637: }
2638:
2639: if (!(column->indicator == -1)) {
2640: zval *element;
2641:
2642: MAKE_STD_ZVAL(element);
2643: php_oci_column_to_zval(column, element, fetch_mode TSRMLS_CC);
2644:
2645: if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
2646: add_index_zval(return_value, i, element);
2647: }
2648: if (fetch_mode & PHP_OCI_ASSOC) {
2649: if (fetch_mode & PHP_OCI_NUM) {
2650: Z_ADDREF_P(element);
2651: }
2652: add_assoc_zval(return_value, column->name, element);
2653: }
2654:
2655: } else {
2656: if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
2657: add_index_null(return_value, i);
2658: }
2659: if (fetch_mode & PHP_OCI_ASSOC) {
2660: add_assoc_null(return_value, column->name);
2661: }
2662: }
2663: }
2664:
2665: if (expected_args > 2) {
2666: /* Only for ocifetchinto BC. In all other cases we return array, not long */
2667: REPLACE_ZVAL_VALUE(&array, return_value, 1); /* copy return_value to given reference */
2668: zval_dtor(return_value);
2669: RETURN_LONG(statement->ncolumns);
2670: }
2671: }
2672: /* }}} */
2673:
2674: /* {{{ php_oci_persistent_helper()
2675: *
2676: * Helper function to close/rollback persistent connections at the end of request. A return value of
2677: * 1 indicates that the connection is to be destroyed
2678: */
2679: static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
2680: {
2681: time_t timestamp;
2682: php_oci_connection *connection;
2683:
2684: timestamp = time(NULL);
2685:
2686: /* Persistent connection stubs are also counted as they have private session pools */
2687: if (le->type == le_pconnection) {
2688: connection = (php_oci_connection *)le->ptr;
2689:
2690: if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
2691: if (OCI_G(debug_mode)) {
2692: php_printf ("OCI8 DEBUG L1: persistent_helper processing for timeout: (%p stub=%d) at (%s:%d) \n", connection, connection->is_stub, __FILE__, __LINE__);
2693: }
2694: if (connection->idle_expiry < timestamp) {
2695: /* connection has timed out */
2696: return ZEND_HASH_APPLY_REMOVE;
2697: }
2698: }
2699: }
2700: return ZEND_HASH_APPLY_KEEP;
2701: } /* }}} */
2702:
2703: /* {{{ php_oci_create_spool()
2704: *
2705: * Create(alloc + Init) Session pool for the given dbname and charsetid
2706: */
2707: static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC)
2708: {
2709: php_oci_spool *session_pool = NULL;
2710: zend_bool iserror = 0;
2711: ub4 poolmode = OCI_DEFAULT; /* Mode to be passed to OCISessionPoolCreate */
2712: OCIAuthInfo *spoolAuth = NULL;
2713:
2714: /* Allocate sessionpool out of persistent memory */
2715: session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
2716: if (session_pool == NULL) {
2717: iserror = 1;
2718: goto exit_create_spool;
2719: }
2720:
2721: /* Populate key if passed */
2722: if (hash_key_len) {
2723: session_pool->spool_hash_key = zend_strndup(hash_key, hash_key_len);
2724: if (session_pool->spool_hash_key == NULL) {
2725: iserror = 1;
2726: goto exit_create_spool;
2727: }
2728: }
2729:
2730: /* Create the session pool's env */
2731: if (!(session_pool->env = php_oci_create_env(charsetid TSRMLS_CC))) {
2732: iserror = 1;
2733: goto exit_create_spool;
2734: }
2735:
2736: /* Allocate the pool handle */
2737: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
2738:
2739: if (OCI_G(errcode) != OCI_SUCCESS) {
2740: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2741: iserror = 1;
2742: goto exit_create_spool;
2743: }
2744:
2745: /* Allocate the session pool error handle - This only for use in the destructor, as there is a
2746: * generic bug which can free up the OCI_G(err) variable before destroying connections. We
2747: * cannot use this for other roundtrip calls as there is no way the user can access this error
2748: */
2749: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0));
2750:
2751: if (OCI_G(errcode) != OCI_SUCCESS) {
2752: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2753: iserror = 1;
2754: goto exit_create_spool;
2755: }
2756:
2757: /* Disable RLB as we mostly have single-connection pools */
2758: #if (OCI_MAJOR_VERSION > 10)
2759: poolmode = OCI_SPC_NO_RLB | OCI_SPC_HOMOGENEOUS;
2760: #else
2761: poolmode = OCI_SPC_HOMOGENEOUS;
2762: #endif
2763:
2764: #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
2765: /* Allocate auth handle for session pool {{{ */
2766: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL));
2767:
2768: if (OCI_G(errcode) != OCI_SUCCESS) {
2769: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2770: iserror = 1;
2771: goto exit_create_spool;
2772: } /* }}} */
2773:
2774: /* Set the edition attribute on the auth handle {{{ */
2775: if (OCI_G(edition)) {
2776: PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) OCI_G(edition), (ub4)(strlen(OCI_G(edition))), (ub4)OCI_ATTR_EDITION, OCI_G(err)));
2777:
2778: if (OCI_G(errcode) != OCI_SUCCESS) {
2779: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2780: iserror = 1;
2781: goto exit_create_spool;
2782: }
2783: } /* }}} */
2784:
2785: /* Set the driver name attribute on the auth handle {{{ */
2786: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
2787:
2788: if (OCI_G(errcode) != OCI_SUCCESS) {
2789: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2790: iserror = 1;
2791: goto exit_create_spool;
2792: } /* }}} */
2793:
2794: /* Set the auth handle on the session pool {{{ */
2795: PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) (session_pool->poolh),(ub4) OCI_HTYPE_SPOOL, (dvoid *) spoolAuth, (ub4)0, (ub4)OCI_ATTR_SPOOL_AUTH, OCI_G(err)));
2796:
2797: if (OCI_G(errcode) != OCI_SUCCESS) {
2798: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2799: iserror = 1;
2800: goto exit_create_spool;
2801: } /* }}} */
2802: #endif
2803:
2804: /* Create the homogeneous session pool - We have different session pools for every different
2805: * username, password, charset and dbname.
2806: */
2807: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode));
2808:
2809: if (OCI_G(errcode) != OCI_SUCCESS) {
2810: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2811: iserror = 1;
2812: }
2813:
2814: exit_create_spool:
2815: if (iserror && session_pool) {
2816: php_oci_spool_close(session_pool TSRMLS_CC);
2817: session_pool = NULL;
2818: }
2819:
2820: if (spoolAuth) {
2821: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO));
2822: }
2823:
2824: if (OCI_G(debug_mode)) {
2825: php_printf ("OCI8 DEBUG L1: create_spool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
2826: }
2827:
2828: return session_pool;
2829: } /* }}} */
2830:
2831: /* {{{ php_oci_get_spool()
2832: *
2833: * Get Session pool for the given dbname and charsetid from the persistent list. Function called for
2834: * non-persistent connections.
2835: */
2836: static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC)
2837: {
2838: smart_str spool_hashed_details = {0};
2839: php_oci_spool *session_pool = NULL;
2840: zend_rsrc_list_entry spool_le = {0};
2841: zend_rsrc_list_entry *spool_out_le = NULL;
2842: zend_bool iserror = 0;
2843:
2844: /* Create the spool hash key {{{ */
2845: smart_str_appendl_ex(&spool_hashed_details, "oci8spool***", sizeof("oci8spool***") - 1, 0);
2846: smart_str_appendl_ex(&spool_hashed_details, username, username_len, 0);
2847: smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
2848: /* Add edition attribute to the hash */
2849: if (OCI_G(edition)){
2850: smart_str_appendl_ex(&spool_hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
2851: }
2852: smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
2853: if (password_len) {
2854: ulong password_hash;
2855: password_hash = zend_inline_hash_func(password, password_len);
2856: smart_str_append_unsigned_ex(&spool_hashed_details, password_hash, 0);
2857: }
2858: smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
2859:
2860: if (dbname_len) {
2861: smart_str_appendl_ex(&spool_hashed_details, dbname, dbname_len, 0);
2862: }
2863: smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
2864:
2865: smart_str_append_unsigned_ex(&spool_hashed_details, charsetid, 0);
2866:
2867: /* Session Pool Hash Key : oci8spool***username**edition**hashedpassword**dbname**charset */
2868:
2869: smart_str_0(&spool_hashed_details);
2870: php_strtolower(spool_hashed_details.c, spool_hashed_details.len);
2871: /* }}} */
2872:
2873: if (zend_hash_find(&EG(persistent_list),spool_hashed_details.c, spool_hashed_details.len+1, (void **)&spool_out_le) == FAILURE) {
2874:
2875: session_pool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, spool_hashed_details.c, spool_hashed_details.len, charsetid TSRMLS_CC);
2876:
2877: if (session_pool == NULL) {
2878: iserror = 1;
2879: goto exit_get_spool;
2880: }
2881: spool_le.ptr = session_pool;
2882: spool_le.type = le_psessionpool;
2883: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
2884: zend_list_insert(session_pool, le_psessionpool TSRMLS_CC);
2885: #else
2886: zend_list_insert(session_pool, le_psessionpool);
2887: #endif
2888: zend_hash_update(&EG(persistent_list), session_pool->spool_hash_key, strlen(session_pool->spool_hash_key)+1,(void *)&spool_le, sizeof(zend_rsrc_list_entry),NULL);
2889: } else if (spool_out_le->type == le_psessionpool &&
2890: strlen(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == spool_hashed_details.len &&
2891: memcmp(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key, spool_hashed_details.c, spool_hashed_details.len) == 0) {
2892: /* retrieve the cached session pool */
2893: session_pool = (php_oci_spool *)(spool_out_le->ptr);
2894: }
2895:
2896: exit_get_spool:
2897: smart_str_free_ex(&spool_hashed_details, 0);
2898: if (iserror && session_pool) {
2899: php_oci_spool_close(session_pool TSRMLS_CC);
2900: session_pool = NULL;
2901: }
2902:
2903: return session_pool;
2904:
2905: } /* }}} */
2906:
2907: /* {{{ php_oci_create_env()
2908: *
2909: * Create the OCI environment choosing the correct function for the OCI version
2910: */
2911: static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC)
2912: {
2913: OCIEnv *retenv = NULL;
2914:
2915: /* create an environment using the character set id */
2916: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIEnvNlsCreate, (&retenv, OCI_G(events) ? PHP_OCI_INIT_MODE | OCI_EVENTS : PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, charsetid, charsetid));
2917:
2918: if (OCI_G(errcode) != OCI_SUCCESS) {
2919: sb4 ora_error_code = 0;
2920: text ora_msg_buf[OCI_ERROR_MAXMSG_SIZE]; /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
2921:
2922: #ifdef HAVE_OCI_INSTANT_CLIENT
2923: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
2924: #else
2925: php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
2926: #endif
2927: if (retenv
2928: && OCIErrorGet(retenv, (ub4)1, NULL, &ora_error_code, ora_msg_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
2929: && *ora_msg_buf) {
2930: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ora_msg_buf);
2931: }
2932:
2933: return NULL;
2934: }
2935: return retenv;
2936: }/* }}} */
2937:
2938: /* {{{ php_oci_old_create_session()
2939: *
2940: * This function is to be deprecated in future in favour of OCISessionGet which is used in
2941: * php_oci_do_connect_ex
2942: */
2943: static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
2944: {
2945: ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
2946:
2947: if (OCI_G(debug_mode)) {
2948: php_printf ("OCI8 DEBUG: Bypassing client-side session pool for session create at (%s:%d) \n", __FILE__, __LINE__);
2949: }
2950:
2951: /* Create the OCI environment separate for each connection */
2952: if (!(connection->env = php_oci_create_env(connection->charset TSRMLS_CC))) {
2953: return 1;
2954: }
2955:
2956: /* Allocate our server handle {{{ */
2957: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->server), OCI_HTYPE_SERVER, 0, NULL));
2958:
2959: if (OCI_G(errcode) != OCI_SUCCESS) {
2960: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2961: return 1;
2962: } /* }}} */
2963:
2964: /* Attach to the server {{{ */
2965: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerAttach, (connection->server, OCI_G(err), (text *)dbname, dbname_len, (ub4) OCI_DEFAULT));
2966:
2967: if (OCI_G(errcode) != OCI_SUCCESS) {
2968: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2969: return 1;
2970: } /* }}} */
2971: connection->is_attached = 1;
2972:
2973: /* Allocate our session handle {{{ */
2974: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->session), OCI_HTYPE_SESSION, 0, NULL));
2975:
2976: if (OCI_G(errcode) != OCI_SUCCESS) {
2977: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2978: return 1;
2979: } /* }}} */
2980:
2981: /* Allocate our private error-handle {{{ */
2982: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
2983:
2984: if (OCI_G(errcode) != OCI_SUCCESS) {
2985: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2986: return 1;
2987: } /* }}} */
2988:
2989: /* Allocate our service-context {{{ */
2990: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->svc), OCI_HTYPE_SVCCTX, 0, NULL));
2991:
2992: if (OCI_G(errcode) != OCI_SUCCESS) {
2993: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
2994: return 1;
2995: } /* }}} */
2996:
2997: /* Set the username {{{ */
2998: if (username) {
2999: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) username, (ub4) username_len, (ub4) OCI_ATTR_USERNAME, OCI_G(err)));
3000:
3001: if (OCI_G(errcode) != OCI_SUCCESS) {
3002: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3003: return 1;
3004: }
3005: }/* }}} */
3006:
3007: /* Set the password {{{ */
3008: if (password) {
3009: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) password, (ub4) password_len, (ub4) OCI_ATTR_PASSWORD, OCI_G(err)));
3010:
3011: if (OCI_G(errcode) != OCI_SUCCESS) {
3012: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3013: return 1;
3014: }
3015: }/* }}} */
3016:
3017: /* Set the edition attribute on the session handle {{{ */
3018: #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
3019: if (OCI_G(edition)) {
3020: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(edition), (ub4) (strlen(OCI_G(edition))), (ub4) OCI_ATTR_EDITION, OCI_G(err)));
3021:
3022: if (OCI_G(errcode) != OCI_SUCCESS) {
3023: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3024: return 1;
3025: }
3026: }
3027: #endif /* }}} */
3028:
3029: /* Set the driver name attribute on the session handle {{{ */
3030: #if (OCI_MAJOR_VERSION >= 11)
3031: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
3032:
3033: if (OCI_G(errcode) != OCI_SUCCESS) {
3034: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3035: return 1;
3036: }
3037: #endif /* }}} */
3038:
3039: /* Set the server handle in the service handle {{{ */
3040: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->server, 0, OCI_ATTR_SERVER, OCI_G(err)));
3041:
3042: if (OCI_G(errcode) != OCI_SUCCESS) {
3043: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3044: return 1;
3045: } /* }}} */
3046:
3047: /* Set the authentication handle in the service handle {{{ */
3048: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->session, 0, OCI_ATTR_SESSION, OCI_G(err)));
3049:
3050: if (OCI_G(errcode) != OCI_SUCCESS) {
3051: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3052: return 1;
3053: } /* }}} */
3054:
3055: if (new_password) {
3056: /* Try to change password if new one was provided {{{ */
3057: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPasswordChange, (connection->svc, OCI_G(err), (text *)username, username_len, (text *)password, password_len, (text *)new_password, new_password_len, OCI_AUTH));
3058:
3059: if (OCI_G(errcode) != OCI_SUCCESS) {
3060: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3061: return 1;
3062: }
3063:
3064: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err)));
3065:
3066: if (OCI_G(errcode) != OCI_SUCCESS) {
3067: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3068: return 1;
3069: } /* }}} */
3070: } else {
3071: /* start the session {{{ */
3072: ub4 cred_type = OCI_CRED_RDBMS;
3073:
3074: /* Extract the overloaded session_mode parameter into valid Oracle credential and session mode values */
3075: if (session_mode & PHP_OCI_CRED_EXT) {
3076: cred_type = OCI_CRED_EXT;
3077: session_mode ^= PHP_OCI_CRED_EXT;
3078: }
3079:
3080: session_mode |= OCI_STMT_CACHE;
3081:
3082: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionBegin, (connection->svc, OCI_G(err), connection->session, (ub4) cred_type, (ub4) session_mode));
3083:
3084: if (OCI_G(errcode) != OCI_SUCCESS) {
3085: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3086: /* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
3087: * user's password has expired, but is still usable.
3088: */
3089: if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
3090: return 1;
3091: }
3092: } /* }}} */
3093: }
3094:
3095: /* Brand new connection: Init and update the next_ping in the connection */
3096: if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
3097: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3098: return 1;
3099: }
3100:
3101: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX, (ub4 *) &statement_cache_size, 0, (ub4) OCI_ATTR_STMTCACHESIZE, OCI_G(err)));
3102:
3103: if (OCI_G(errcode) != OCI_SUCCESS) {
3104: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3105: return 1;
3106: }
3107:
3108: /* Successfully created session */
3109: return 0;
3110: } /* }}} */
3111:
3112: /* {{{ php_oci_create_session()
3113: *
3114: * Create session using client-side session pool - new norm
3115: */
3116: static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
3117: {
3118: php_oci_spool *actual_spool = NULL;
3119: #if (OCI_MAJOR_VERSION > 10)
3120: ub4 purity = -2; /* Illegal value to initialize */
3121: #endif
3122: time_t timestamp = time(NULL);
3123: ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
3124:
3125: /* Persistent connections have private session pools */
3126: if (connection->is_persistent && !connection->private_spool &&
3127: !(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, 0, connection->charset TSRMLS_CC))) {
3128: return 1;
3129: }
3130: actual_spool = (connection->is_persistent) ? (connection->private_spool) : (session_pool);
3131:
3132: connection->env = actual_spool->env;
3133:
3134: /* Do this upfront so that connection close on an error would know that this is a session pool
3135: * connection. Failure to do this would result in crashes in error scenarios
3136: */
3137: if (!connection->using_spool) {
3138: connection->using_spool = 1;
3139: }
3140:
3141: if (OCI_G(debug_mode)) {
3142: if (session_pool) {
3143: php_printf ("OCI8 DEBUG L1: using shared pool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
3144: } else {
3145: php_printf ("OCI8 DEBUG L1: using private pool: (%p) at (%s:%d) \n", connection->private_spool, __FILE__, __LINE__);
3146: }
3147: }
3148:
3149: /* The passed in "connection" can be a cached stub from plist or freshly created. In the former
3150: * case, we do not have to allocate any handles
3151: */
3152:
3153: if (!connection->err) {
3154: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
3155:
3156: if (OCI_G(errcode) != OCI_SUCCESS) {
3157: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3158: return 1;
3159: }
3160: }
3161:
3162: /* {{{ Allocate and initialize the connection-private authinfo handle if not allocated yet */
3163: if (!connection->authinfo) {
3164: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->authinfo), OCI_HTYPE_AUTHINFO, 0, NULL));
3165:
3166: if (OCI_G(errcode) != OCI_SUCCESS) {
3167: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3168: return 1;
3169: }
3170:
3171: /* Set the Connection class and purity if OCI client version >= 11g */
3172: #if (OCI_MAJOR_VERSION > 10)
3173: PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(connection_class), (ub4)(strlen(OCI_G(connection_class))), (ub4)OCI_ATTR_CONNECTION_CLASS, OCI_G(err)));
3174:
3175: if (OCI_G(errcode) != OCI_SUCCESS) {
3176: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3177: return 1;
3178: }
3179:
3180: if (connection->is_persistent)
3181: purity = OCI_ATTR_PURITY_SELF;
3182: else
3183: purity = OCI_ATTR_PURITY_NEW;
3184:
3185: PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_AUTHINFO, (dvoid *) &purity, (ub4)0, (ub4)OCI_ATTR_PURITY, OCI_G(err)));
3186:
3187: if (OCI_G(errcode) != OCI_SUCCESS) {
3188: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3189: return 1;
3190: }
3191: #endif
3192: } /* }}} */
3193:
3194: /* Debug statements {{{ */
3195: if (OCI_G(debug_mode)) {
3196: ub4 numfree = 0, numbusy = 0, numopen = 0;
3197: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numopen, (ub4 *)0, OCI_ATTR_SPOOL_OPEN_COUNT, OCI_G(err)));
3198: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numbusy, (ub4 *)0, OCI_ATTR_SPOOL_BUSY_COUNT, OCI_G(err)));
3199: numfree = numopen - numbusy; /* number of free connections in the pool */
3200: php_printf ("OCI8 DEBUG L1: (numopen=%d)(numbusy=%d)(numfree=%d) at (%s:%d) \n", numopen, numbusy, numfree, __FILE__, __LINE__);
3201: } /* }}} */
3202:
3203: /* Ping loop: Ping and loop till we get a good connection. When a database instance goes
3204: * down, it can leave several bad connections that need to be flushed out before getting a
3205: * good one. In non-RAC, we always get a brand new connection at the end of the loop and in
3206: * RAC, we can get a good connection from a different instance before flushing out all bad
3207: * ones. We do not need to ping brand new connections.
3208: */
3209: do {
3210: /* Continue to use the global error handle as the connection is closed when an error occurs */
3211: PHP_OCI_CALL_RETURN(OCI_G(errcode),OCISessionGet, (connection->env, OCI_G(err), &(connection->svc), (OCIAuthInfo *)connection->authinfo, (OraText *)actual_spool->poolname, (ub4)actual_spool->poolname_len, NULL, 0, NULL, NULL, NULL, OCI_SESSGET_SPOOL));
3212:
3213: if (OCI_G(errcode) != OCI_SUCCESS) {
3214: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3215:
3216: /* Session creation returns OCI_SUCCESS_WITH_INFO when user's password has expired, but
3217: * is still usable.
3218: */
3219:
3220: if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
3221: return 1;
3222: }
3223: }
3224:
3225: /* {{{ Populate the session and server fields of the connection */
3226: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->server), (ub4 *)0, OCI_ATTR_SERVER, OCI_G(err)));
3227:
3228: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err))); /* }}} */
3229:
3230: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, OCI_G(err), (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&(connection->next_pingp)));
3231: if (OCI_G(errcode) != OCI_SUCCESS) {
3232: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3233: return 1;
3234: }
3235:
3236: if (!(connection->next_pingp)){
3237: /* This is a brand new connection, we need not ping, but have to initialize ping */
3238: if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
3239: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3240: return 1;
3241: }
3242: } else if ((*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp))) {
3243: if (php_oci_connection_ping(connection TSRMLS_CC)) {
3244: /* Got a good connection - update next_ping and get out of ping loop */
3245: *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
3246: } else {
3247: /* Bad connection - remove from pool */
3248: PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) OCI_SESSRLS_DROPSESS));
3249: connection->svc = NULL;
3250: connection->server = NULL;
3251: connection->session = NULL;
3252: }
3253: } /* If ping applicable */
3254: } while (!(connection->svc));
3255:
3256: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX, (ub4 *) &statement_cache_size, 0, (ub4) OCI_ATTR_STMTCACHESIZE, OCI_G(err)));
3257:
3258: if (OCI_G(errcode) != OCI_SUCCESS) {
3259: php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
3260: return 1;
3261: }
3262:
3263: /* Session is now taken from the session pool and attached and open */
3264: connection->is_stub = 0;
3265: connection->is_attached = connection->is_open = 1;
3266:
3267: return 0;
3268: } /* }}} */
3269:
3270: /* {{{ php_oci_spool_list_dtor()
3271: *
3272: * Session pool destructor function
3273: */
3274: static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
3275: {
3276: php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
3277:
3278: if (session_pool) {
3279: php_oci_spool_close(session_pool TSRMLS_CC);
3280: }
3281:
3282: return;
3283: } /* }}} */
3284:
3285: /* {{{ php_oci_spool_close()
3286: *
3287: * Destroys the OCI Session Pool
3288: */
3289: static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC)
3290: {
3291: if (session_pool->poolname_len) {
3292: PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
3293: (dvoid *) session_pool->err, OCI_SPD_FORCE));
3294: }
3295:
3296: if (session_pool->poolh) {
3297: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->poolh, OCI_HTYPE_SPOOL));
3298: }
3299:
3300: if (session_pool->err) {
3301: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->err, OCI_HTYPE_ERROR));
3302: }
3303:
3304: if (session_pool->env) {
3305: PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->env, OCI_HTYPE_ENV));
3306: }
3307:
3308: if (session_pool->spool_hash_key) {
3309: free(session_pool->spool_hash_key);
3310: }
3311:
3312: free(session_pool);
3313: } /* }}} */
3314:
3315: /* {{{ php_oci_ping_init()
3316: *
3317: * Initializes the next_ping time as a context value in the connection. We now use
3318: * OCIContext{Get,Set}Value to store the next_ping because we need to support ping for
3319: * non-persistent DRCP connections
3320: */
3321: static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC)
3322: {
3323: time_t *next_pingp = NULL;
3324:
3325: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, errh, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&next_pingp));
3326: if (OCI_G(errcode) != OCI_SUCCESS) {
3327: return OCI_G(errcode);
3328: }
3329:
3330: /* This must be a brand-new connection. Allocate memory for the ping */
3331: if (!next_pingp) {
3332: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIMemoryAlloc, (connection->session, errh, (void **)&next_pingp, OCI_DURATION_SESSION, sizeof(time_t), OCI_MEMORY_CLEARED));
3333: if (OCI_G(errcode) != OCI_SUCCESS) {
3334: return OCI_G(errcode);
3335: }
3336: }
3337:
3338: if (OCI_G(ping_interval) >= 0) {
3339: time_t timestamp = time(NULL);
3340: *next_pingp = timestamp + OCI_G(ping_interval);
3341: } else {
3342: *next_pingp = 0;
3343: }
3344:
3345: /* Set the new ping value into the connection */
3346: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextSetValue, (connection->session, errh, OCI_DURATION_SESSION, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), next_pingp));
3347: if (OCI_G(errcode) != OCI_SUCCESS) {
3348: OCIMemoryFree(connection->session, errh, next_pingp);
3349: return OCI_G(errcode);
3350: }
3351:
3352: /* Cache the pointer so we do not have to do OCIContextGetValue repeatedly */
3353: connection->next_pingp = next_pingp;
3354:
3355: return OCI_SUCCESS;
3356: } /* }}} */
3357:
3358: #endif /* HAVE_OCI8 */
3359:
3360: /*
3361: * Local variables:
3362: * tab-width: 4
3363: * c-basic-offset: 4
3364: * End:
3365: * vim600: noet sw=4 ts=4 fdm=marker
3366: * vim<600: noet sw=4 ts=4
3367: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>