1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 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: 44bfa713983a99b3e59477f6532e5fb51b6dee94 $ */
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)
PHP_INI_END()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 */
php_oci_cleanup_global_handles(TSRMLS_D)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 */
PHP_GINIT_FUNCTION(oci)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)
PHP_GSHUTDOWN_FUNCTION(oci)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
PHP_MINIT_FUNCTION(oci)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
PHP_RINIT_FUNCTION(oci)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
PHP_MSHUTDOWN_FUNCTION(oci)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
PHP_RSHUTDOWN_FUNCTION(oci)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
PHP_MINFO_FUNCTION(oci)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: 44bfa713983a99b3e59477f6532e5fb51b6dee94 $");
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 */
php_oci_connection_list_dtor(zend_rsrc_list_entry * entry TSRMLS_DC)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 */
php_oci_pconnection_list_dtor(zend_rsrc_list_entry * entry TSRMLS_DC)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 */
php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry * entry TSRMLS_DC)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 */
php_oci_statement_list_dtor(zend_rsrc_list_entry * entry TSRMLS_DC)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 */
php_oci_descriptor_list_dtor(zend_rsrc_list_entry * entry TSRMLS_DC)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 */
php_oci_collection_list_dtor(zend_rsrc_list_entry * entry TSRMLS_DC)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 */
php_oci_define_hash_dtor(void * data)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 */
php_oci_bind_hash_dtor(void * data)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 */
php_oci_column_hash_dtor(void * data)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 */
php_oci_descriptor_flush_hash_dtor(void * data)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 */
php_oci_connection_descriptors_free(php_oci_connection * connection TSRMLS_DC)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 */
php_oci_error(OCIError * err_p,sword status TSRMLS_DC)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 */
php_oci_fetch_errmsg(OCIError * error_handle,text ** error_buf TSRMLS_DC)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 */
php_oci_fetch_sqltext_offset(php_oci_statement * statement,text ** sqltext,ub2 * error_offset TSRMLS_DC)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 */
php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent,int exclusive)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 */
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)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 */
php_oci_connection_ping(php_oci_connection * connection TSRMLS_DC)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 */
php_oci_connection_status(php_oci_connection * connection TSRMLS_DC)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 */
php_oci_connection_rollback(php_oci_connection * connection TSRMLS_DC)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 */
php_oci_connection_commit(php_oci_connection * connection TSRMLS_DC)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 */
php_oci_connection_close(php_oci_connection * connection TSRMLS_DC)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 */
php_oci_connection_release(php_oci_connection * connection TSRMLS_DC)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 */
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)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 */
php_oci_client_get_version(char ** version TSRMLS_DC)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 */
php_oci_server_get_version(php_oci_connection * connection,char ** version TSRMLS_DC)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 */
php_oci_column_to_zval(php_oci_out_column * column,zval * value,int mode TSRMLS_DC)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 */
php_oci_fetch_row(INTERNAL_FUNCTION_PARAMETERS,int mode,int expected_args)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 */
php_oci_persistent_helper(zend_rsrc_list_entry * le TSRMLS_DC)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 */
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)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 */
php_oci_get_spool(char * username,int username_len,char * password,int password_len,char * dbname,int dbname_len,int charsetid TSRMLS_DC)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 */
php_oci_create_env(ub2 charsetid TSRMLS_DC)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 */
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)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 */
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)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 */
php_oci_spool_list_dtor(zend_rsrc_list_entry * entry TSRMLS_DC)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 */
php_oci_spool_close(php_oci_spool * session_pool TSRMLS_DC)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 */
php_oci_ping_init(php_oci_connection * connection,OCIError * errh TSRMLS_DC)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 */
3368