Back to index

php5  5.3.10
oci8.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Stig Sæther Bakken <ssb@php.net>                            |
00016    |          Thies C. Arntzen <thies@thieso.net>                         |
00017    |          Maxim Maletsky <maxim@maxim.cx>                             |
00018    |                                                                      |
00019    | Collection support by Andy Sautins <asautins@veripost.net>           |
00020    | Temporary LOB support by David Benson <dbenson@mancala.com>          |
00021    | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at>        |
00022    |                                                                      |
00023    | Redesigned by: Antony Dovgal <antony@zend.com>                       |
00024    |                Andi Gutmans <andi@zend.com>                          |
00025    |                Wez Furlong <wez@omniti.com>                          |
00026    +----------------------------------------------------------------------+
00027 */
00028 
00029 /* $Id: oci8.c 321634 2012-01-01 13:15:04Z felipe $ */
00030 
00031 #ifdef HAVE_CONFIG_H
00032 #include "config.h"
00033 #endif
00034 
00035 #include "php.h"
00036 #include "ext/standard/info.h"
00037 #include "php_ini.h"
00038 #include "ext/standard/php_smart_str.h"
00039 
00040 #ifdef HAVE_STDINT_H
00041 #include <stdint.h>
00042 #endif
00043 #ifdef PHP_WIN32
00044 #include "win32/php_stdint.h"
00045 #endif
00046 
00047 #if HAVE_OCI8
00048 
00049 #if PHP_MAJOR_VERSION > 5
00050 #error This version of the PHP OCI8 extension is not compatible with PHP 6 or later
00051 #elif PHP_MAJOR_VERSION < 5
00052 #ifdef ZTS
00053 #error The PHP OCI8 extension does not support ZTS mode in PHP 4
00054 #endif
00055 #endif
00056 
00057 #include "php_oci8.h"
00058 #include "php_oci8_int.h"
00059 #include "zend_hash.h"
00060 
00061 #if defined(HAVE_STDINT_H) || defined(PHP_WIN32)
00062 #define OCI8_INT_TO_PTR(I)  ((void *)(intptr_t)(I))
00063 #define OCI8_PTR_TO_INT(P)  ((int)(intptr_t)(P))
00064 #else
00065 #define OCI8_INT_TO_PTR(I)  ((void *)(I))
00066 #define OCI8_PTR_TO_INT(P)  ((int)(P))
00067 #endif
00068 
00069 ZEND_DECLARE_MODULE_GLOBALS(oci)
00070 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
00071 /* This "if" allows PECL builds from this file to be portable to older PHP releases */
00072 static PHP_GINIT_FUNCTION(oci);
00073 static PHP_GSHUTDOWN_FUNCTION(oci);
00074 #endif
00075 
00076 /* Allow PHP 5.3 branch to be used in PECL for 5.x compatible builds */
00077 #ifndef Z_ADDREF_P
00078 #define Z_ADDREF_P(x) ZVAL_ADDREF(x)
00079 #endif
00080 
00081 /* For a user friendly message about environment setup */
00082 #if defined(PHP_WIN32)
00083 #define PHP_OCI8_LIB_PATH_MSG "PATH"
00084 #elif defined(__APPLE__)
00085 #define PHP_OCI8_LIB_PATH_MSG "DYLD_LIBRARY_PATH"
00086 #elif defined(_AIX)
00087 #define PHP_OCI8_LIB_PATH_MSG "LIBPATH"
00088 #elif defined(__hpux)
00089 #define PHP_OCI8_LIB_PATH_MSG "SHLIB_PATH"
00090 #else
00091 #define PHP_OCI8_LIB_PATH_MSG "LD_LIBRARY_PATH"
00092 #endif
00093 
00094 /* True globals, no need for thread safety */
00095 int le_connection;
00096 int le_pconnection;
00097 int le_statement;
00098 int le_descriptor;
00099 int le_psessionpool;
00100 int le_collection;
00101 
00102 zend_class_entry *oci_lob_class_entry_ptr;
00103 zend_class_entry *oci_coll_class_entry_ptr;
00104 
00105 #ifndef SQLT_BFILEE
00106 #define SQLT_BFILEE 114
00107 #endif
00108 #ifndef SQLT_CFILEE
00109 #define SQLT_CFILEE 115
00110 #endif
00111 
00112 #ifdef OCI_ERROR_MAXMSG_SIZE2
00113 /* Bigger size is defined from 11.2.0.3 onwards */
00114 #define PHP_OCI_ERRBUF_LEN OCI_ERROR_MAXMSG_SIZE2
00115 #else
00116 #define PHP_OCI_ERRBUF_LEN OCI_ERROR_MAXMSG_SIZE
00117 #endif 
00118 
00119 #if ZEND_MODULE_API_NO > 20020429
00120 #define ONUPDATELONGFUNC OnUpdateLong
00121 #else
00122 #define ONUPDATELONGFUNC OnUpdateInt
00123 #endif
00124 
00125 #ifdef ZTS
00126 #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX)
00127 #else
00128 #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT)
00129 #endif
00130 
00131 /* static protos {{{ */
00132 static void php_oci_connection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
00133 static void php_oci_pconnection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
00134 static void php_oci_pconnection_list_np_dtor (zend_rsrc_list_entry * TSRMLS_DC);
00135 static void php_oci_statement_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
00136 static void php_oci_descriptor_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
00137 static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC);
00138 static void php_oci_collection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
00139 
00140 static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC);
00141 static int php_oci_connection_ping(php_oci_connection * TSRMLS_DC);
00142 static int php_oci_connection_status(php_oci_connection * TSRMLS_DC);
00143 static int php_oci_connection_close(php_oci_connection * TSRMLS_DC);
00144 static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC);
00145 
00146 static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC);
00147 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);
00148 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);
00149 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);
00150 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);
00151 static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC);
00152 /* }}} */
00153 
00154 /* {{{ dynamically loadable module stuff */
00155 #if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G)
00156 ZEND_GET_MODULE(oci8)
00157 #endif /* COMPILE_DL */
00158 /* }}} */
00159 
00160 #ifdef ZEND_ENGINE_2
00161 
00162 /* {{{ Function arginfo */
00163 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_define_by_name, 0, 0, 3)
00164        ZEND_ARG_INFO(0, statement_resource)
00165        ZEND_ARG_INFO(0, column_name)
00166        ZEND_ARG_INFO(1, variable)
00167        ZEND_ARG_INFO(0, type)
00168 ZEND_END_ARG_INFO()
00169 
00170 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_by_name, 0, 0, 3)
00171        ZEND_ARG_INFO(0, statement_resource)
00172        ZEND_ARG_INFO(0, column_name)
00173        ZEND_ARG_INFO(1, variable)
00174        ZEND_ARG_INFO(0, maximum_length)
00175        ZEND_ARG_INFO(0, type)
00176 ZEND_END_ARG_INFO()
00177 
00178 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_array_by_name, 0, 0, 4)
00179        ZEND_ARG_INFO(0, statement_resource)
00180        ZEND_ARG_INFO(0, column_name)
00181        ZEND_ARG_INFO(1, variable)
00182        ZEND_ARG_INFO(0, maximum_array_length)
00183        ZEND_ARG_INFO(0, maximum_item_length)
00184        ZEND_ARG_INFO(0, type)
00185 ZEND_END_ARG_INFO()
00186 
00187 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_descriptor, 0, 0, 1)
00188        ZEND_ARG_INFO(0, lob_descriptor)
00189 ZEND_END_ARG_INFO()
00190 
00191 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save, 0, 0, 2)
00192        ZEND_ARG_INFO(0, lob_descriptor)
00193        ZEND_ARG_INFO(0, data)
00194        ZEND_ARG_INFO(0, offset)
00195 ZEND_END_ARG_INFO()
00196 
00197 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import, 0, 0, 2)
00198        ZEND_ARG_INFO(0, lob_descriptor)
00199        ZEND_ARG_INFO(0, filename)
00200 ZEND_END_ARG_INFO()
00201 
00202 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_load, 0, 0, 1)
00203        ZEND_ARG_INFO(0, lob_descriptor)
00204 ZEND_END_ARG_INFO()
00205 
00206 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read, 0, 0, 2)
00207        ZEND_ARG_INFO(0, lob_descriptor)
00208        ZEND_ARG_INFO(0, length)
00209 ZEND_END_ARG_INFO()
00210 
00211 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_eof, 0, 0, 1)
00212        ZEND_ARG_INFO(0, lob_descriptor)
00213 ZEND_END_ARG_INFO()
00214 
00215 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_tell, 0, 0, 1)
00216        ZEND_ARG_INFO(0, lob_descriptor)
00217 ZEND_END_ARG_INFO()
00218 
00219 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_rewind, 0, 0, 1)
00220        ZEND_ARG_INFO(0, lob_descriptor)
00221 ZEND_END_ARG_INFO()
00222 
00223 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek, 0, 0, 2)
00224        ZEND_ARG_INFO(0, lob_descriptor)
00225        ZEND_ARG_INFO(0, offset)
00226        ZEND_ARG_INFO(0, whence)
00227 ZEND_END_ARG_INFO()
00228 
00229 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_size, 0, 0, 1)
00230        ZEND_ARG_INFO(0, lob_descriptor)
00231 ZEND_END_ARG_INFO()
00232 
00233 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write, 0, 0, 2)
00234        ZEND_ARG_INFO(0, lob_descriptor)
00235        ZEND_ARG_INFO(0, string)
00236        ZEND_ARG_INFO(0, length)
00237 ZEND_END_ARG_INFO()
00238 
00239 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append, 0, 0, 2)
00240        ZEND_ARG_INFO(0, lob_descriptor_to)
00241        ZEND_ARG_INFO(0, lob_descriptor_from)
00242 ZEND_END_ARG_INFO()
00243 
00244 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate, 0, 0, 1)
00245        ZEND_ARG_INFO(0, lob_descriptor)
00246        ZEND_ARG_INFO(0, length)
00247 ZEND_END_ARG_INFO()
00248 
00249 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase, 0, 0, 1)
00250        ZEND_ARG_INFO(0, lob_descriptor)
00251        ZEND_ARG_INFO(0, offset)
00252        ZEND_ARG_INFO(0, length)
00253 ZEND_END_ARG_INFO()
00254 
00255 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush, 0, 0, 1)
00256        ZEND_ARG_INFO(0, lob_descriptor)
00257        ZEND_ARG_INFO(0, flag)
00258 ZEND_END_ARG_INFO()
00259 
00260 ZEND_BEGIN_ARG_INFO_EX(arginfo_ocisetbufferinglob, 0, 0, 2)
00261        ZEND_ARG_INFO(0, lob_descriptor)
00262        ZEND_ARG_INFO(0, mode)
00263 ZEND_END_ARG_INFO()
00264 
00265 ZEND_BEGIN_ARG_INFO_EX(arginfo_ocigetbufferinglob, 0, 0, 1)
00266        ZEND_ARG_INFO(0, lob_descriptor)
00267 ZEND_END_ARG_INFO()
00268 
00269 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_copy, 0, 0, 2)
00270        ZEND_ARG_INFO(0, lob_descriptor_to)
00271        ZEND_ARG_INFO(0, lob_descriptor_from)
00272        ZEND_ARG_INFO(0, length)
00273 ZEND_END_ARG_INFO()
00274 
00275 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_is_equal, 0, 0, 2)
00276        ZEND_ARG_INFO(0, lob_descriptor)
00277        ZEND_ARG_INFO(0, lob_descriptor)
00278 ZEND_END_ARG_INFO()
00279 
00280 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export, 0, 0, 2)
00281        ZEND_ARG_INFO(0, lob_descriptor)
00282        ZEND_ARG_INFO(0, filename)
00283        ZEND_ARG_INFO(0, start)
00284        ZEND_ARG_INFO(0, length)
00285 ZEND_END_ARG_INFO()
00286 
00287 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_descriptor, 0, 0, 1)
00288        ZEND_ARG_INFO(0, connection_resource)
00289        ZEND_ARG_INFO(0, type)
00290 ZEND_END_ARG_INFO()
00291 
00292 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_rollback, 0, 0, 1)
00293        ZEND_ARG_INFO(0, connection_resource)
00294 ZEND_END_ARG_INFO()
00295 
00296 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_commit, 0, 0, 1)
00297        ZEND_ARG_INFO(0, connection_resource)
00298 ZEND_END_ARG_INFO()
00299 
00300 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_name, 0, 0, 2)
00301        ZEND_ARG_INFO(0, statement_resource)
00302        ZEND_ARG_INFO(0, column_number)
00303 ZEND_END_ARG_INFO()
00304 
00305 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_size, 0, 0, 2)
00306        ZEND_ARG_INFO(0, statement_resource)
00307        ZEND_ARG_INFO(0, column_number_or_name)
00308 ZEND_END_ARG_INFO()
00309 
00310 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_scale, 0, 0, 2)
00311        ZEND_ARG_INFO(0, statement_resource)
00312        ZEND_ARG_INFO(0, column_number)
00313 ZEND_END_ARG_INFO()
00314 
00315 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_precision, 0, 0, 2)
00316        ZEND_ARG_INFO(0, statement_resource)
00317        ZEND_ARG_INFO(0, column_number)
00318 ZEND_END_ARG_INFO()
00319 
00320 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type, 0, 0, 2)
00321        ZEND_ARG_INFO(0, statement_resource)
00322        ZEND_ARG_INFO(0, column_number)
00323 ZEND_END_ARG_INFO()
00324 
00325 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type_raw, 0, 0, 2)
00326        ZEND_ARG_INFO(0, statement_resource)
00327        ZEND_ARG_INFO(0, column_number)
00328 ZEND_END_ARG_INFO()
00329 
00330 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_is_null, 0, 0, 2)
00331        ZEND_ARG_INFO(0, statement_resource)
00332        ZEND_ARG_INFO(0, column_number_or_name)
00333 ZEND_END_ARG_INFO()
00334 
00335 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_internal_debug, 0, 0, 1)
00336        ZEND_ARG_INFO(0, mode)
00337 ZEND_END_ARG_INFO()
00338 
00339 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_execute, 0, 0, 1)
00340        ZEND_ARG_INFO(0, statement_resource)
00341        ZEND_ARG_INFO(0, mode)
00342 ZEND_END_ARG_INFO()
00343 
00344 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_cancel, 0, 0, 1)
00345        ZEND_ARG_INFO(0, statement_resource)
00346 ZEND_END_ARG_INFO()
00347 
00348 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch, 0, 0, 1)
00349        ZEND_ARG_INFO(0, statement_resource)
00350 ZEND_END_ARG_INFO()
00351 
00352 ZEND_BEGIN_ARG_INFO_EX(arginfo_ocifetchinto, 0, 0, 2)
00353        ZEND_ARG_INFO(0, statement_resource)
00354        ZEND_ARG_INFO(1, result)
00355        ZEND_ARG_INFO(0, mode)
00356 ZEND_END_ARG_INFO()
00357 
00358 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_all, 0, 0, 2)
00359        ZEND_ARG_INFO(0, statement_resource)
00360        ZEND_ARG_INFO(1, output)
00361        ZEND_ARG_INFO(0, skip)
00362        ZEND_ARG_INFO(0, maximum_rows)
00363        ZEND_ARG_INFO(0, flags)
00364 ZEND_END_ARG_INFO()
00365 
00366 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_object, 0, 0, 1)
00367        ZEND_ARG_INFO(0, statement_resource)
00368 ZEND_END_ARG_INFO()
00369 
00370 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_row, 0, 0, 1)
00371        ZEND_ARG_INFO(0, statement_resource)
00372 ZEND_END_ARG_INFO()
00373 
00374 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_assoc, 0, 0, 1)
00375        ZEND_ARG_INFO(0, statement_resource)
00376 ZEND_END_ARG_INFO()
00377 
00378 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_array, 0, 0, 1)
00379        ZEND_ARG_INFO(0, statement_resource)
00380        ZEND_ARG_INFO(0, mode)
00381 ZEND_END_ARG_INFO()
00382 
00383 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_statement, 0, 0, 1)
00384        ZEND_ARG_INFO(0, statement_resource)
00385 ZEND_END_ARG_INFO()
00386 
00387 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_close, 0, 0, 1)
00388        ZEND_ARG_INFO(0, connection_resource)
00389 ZEND_END_ARG_INFO()
00390 
00391 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_connect, 0, 0, 2)
00392        ZEND_ARG_INFO(0, username)
00393        ZEND_ARG_INFO(0, password)
00394        ZEND_ARG_INFO(0, connection_string)
00395        ZEND_ARG_INFO(0, character_set)
00396        ZEND_ARG_INFO(0, session_mode)
00397 ZEND_END_ARG_INFO()
00398 
00399 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_connect, 0, 0, 2)
00400        ZEND_ARG_INFO(0, username)
00401        ZEND_ARG_INFO(0, password)
00402        ZEND_ARG_INFO(0, connection_string)
00403        ZEND_ARG_INFO(0, character_set)
00404        ZEND_ARG_INFO(0, session_mode)
00405 ZEND_END_ARG_INFO()
00406 
00407 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_pconnect, 0, 0, 2)
00408        ZEND_ARG_INFO(0, username)
00409        ZEND_ARG_INFO(0, password)
00410        ZEND_ARG_INFO(0, connection_string)
00411        ZEND_ARG_INFO(0, character_set)
00412        ZEND_ARG_INFO(0, session_mode)
00413 ZEND_END_ARG_INFO()
00414 
00415 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_error, 0, 0, 0)
00416        ZEND_ARG_INFO(0, connection_or_statement_resource)
00417 ZEND_END_ARG_INFO()
00418 
00419 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_fields, 0, 0, 1)
00420        ZEND_ARG_INFO(0, statement_resource)
00421 ZEND_END_ARG_INFO()
00422 
00423 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_parse, 0, 0, 2)
00424        ZEND_ARG_INFO(0, connection_resource)
00425        ZEND_ARG_INFO(0, sql_text)
00426 ZEND_END_ARG_INFO()
00427 
00428 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_prefetch, 0, 0, 2)
00429        ZEND_ARG_INFO(0, statement_resource)
00430        ZEND_ARG_INFO(0, number_of_rows)
00431 ZEND_END_ARG_INFO()
00432 
00433 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_identifier, 0, 0, 2)
00434        ZEND_ARG_INFO(0, connection_resource)
00435        ZEND_ARG_INFO(0, client_identifier)
00436 ZEND_END_ARG_INFO()
00437 
00438 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_edition, 0, 0, 1)
00439        ZEND_ARG_INFO(0, edition_name)
00440 ZEND_END_ARG_INFO()
00441 
00442 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_module_name, 0, 0, 2)
00443        ZEND_ARG_INFO(0, connection_resource)
00444        ZEND_ARG_INFO(0, module_name)
00445 ZEND_END_ARG_INFO()
00446 
00447 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_action, 0, 0, 2)
00448        ZEND_ARG_INFO(0, connection_resource)
00449        ZEND_ARG_INFO(0, action)
00450 ZEND_END_ARG_INFO()
00451 
00452 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_info, 0, 0, 2)
00453        ZEND_ARG_INFO(0, connection_resource)
00454        ZEND_ARG_INFO(0, client_information)
00455 ZEND_END_ARG_INFO()
00456 
00457 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_password_change, 0, 0, 4)
00458        ZEND_ARG_INFO(0, connection_resource_or_connection_string)
00459        ZEND_ARG_INFO(0, username)
00460        ZEND_ARG_INFO(0, old_password)
00461        ZEND_ARG_INFO(0, new_password)
00462 ZEND_END_ARG_INFO()
00463 
00464 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_cursor, 0, 0, 1)
00465        ZEND_ARG_INFO(0, connection_resource)
00466 ZEND_END_ARG_INFO()
00467 
00468 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_result, 0, 0, 2)
00469        ZEND_ARG_INFO(0, statement_resource)
00470        ZEND_ARG_INFO(0, column_number_or_name)
00471 ZEND_END_ARG_INFO()
00472 
00473 ZEND_BEGIN_ARG_INFO(arginfo_oci_client_version, 0)
00474 ZEND_END_ARG_INFO()
00475 
00476 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_server_version, 0, 0, 1)
00477        ZEND_ARG_INFO(0, connection_resource)
00478 ZEND_END_ARG_INFO()
00479 
00480 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_statement_type, 0, 0, 1)
00481        ZEND_ARG_INFO(0, statement_resource)
00482 ZEND_END_ARG_INFO()
00483 
00484 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_rows, 0, 0, 1)
00485        ZEND_ARG_INFO(0, statement_resource)
00486 ZEND_END_ARG_INFO()
00487 
00488 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_collection, 0, 0, 1)
00489        ZEND_ARG_INFO(0, collection)
00490 ZEND_END_ARG_INFO()
00491 
00492 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append, 0, 0, 2)
00493        ZEND_ARG_INFO(0, collection)
00494        ZEND_ARG_INFO(0, value)
00495 ZEND_END_ARG_INFO()
00496 
00497 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get, 0, 0, 2)
00498        ZEND_ARG_INFO(0, collection)
00499        ZEND_ARG_INFO(0, index)
00500 ZEND_END_ARG_INFO()
00501 
00502 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign, 0, 0, 2)
00503        ZEND_ARG_INFO(0, collection_to)
00504        ZEND_ARG_INFO(0, collection_from)
00505 ZEND_END_ARG_INFO()
00506 
00507 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign, 0, 0, 3)
00508        ZEND_ARG_INFO(0, collection)
00509        ZEND_ARG_INFO(0, index)
00510        ZEND_ARG_INFO(0, value)
00511 ZEND_END_ARG_INFO()
00512 
00513 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_size, 0, 0, 1)
00514        ZEND_ARG_INFO(0, collection)
00515 ZEND_END_ARG_INFO()
00516 
00517 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_max, 0, 0, 1)
00518        ZEND_ARG_INFO(0, collection)
00519 ZEND_END_ARG_INFO()
00520 
00521 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim, 0, 0, 2)
00522        ZEND_ARG_INFO(0, collection)
00523        ZEND_ARG_INFO(0, number)
00524 ZEND_END_ARG_INFO()
00525 
00526 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_collection, 0, 0, 2)
00527        ZEND_ARG_INFO(0, connection_resource)
00528        ZEND_ARG_INFO(0, type_name)
00529        ZEND_ARG_INFO(0, schema_name)
00530 ZEND_END_ARG_INFO()
00531 /* }}} */
00532 
00533 /* {{{ LOB Method arginfo */
00534 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save_method, 0, 0, 1)
00535        ZEND_ARG_INFO(0, data)
00536        ZEND_ARG_INFO(0, offset)
00537 ZEND_END_ARG_INFO()
00538 
00539 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import_method, 0, 0, 1)
00540        ZEND_ARG_INFO(0, filename)
00541 ZEND_END_ARG_INFO()
00542 
00543 ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_load_method, 0)
00544 ZEND_END_ARG_INFO()
00545 
00546 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read_method, 0, 0, 1)
00547        ZEND_ARG_INFO(0, length)
00548 ZEND_END_ARG_INFO()
00549 
00550 ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_eof_method, 0)
00551 ZEND_END_ARG_INFO()
00552 
00553 ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_tell_method, 0)
00554 ZEND_END_ARG_INFO()
00555 
00556 ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_rewind_method, 0)
00557 ZEND_END_ARG_INFO()
00558 
00559 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek_method, 0, 0, 1)
00560        ZEND_ARG_INFO(0, offset)
00561        ZEND_ARG_INFO(0, whence)
00562 ZEND_END_ARG_INFO()
00563 
00564 ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_size_method, 0)
00565 ZEND_END_ARG_INFO()
00566 
00567 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_method, 0, 0, 1)
00568        ZEND_ARG_INFO(0, string)
00569        ZEND_ARG_INFO(0, length)
00570 ZEND_END_ARG_INFO()
00571 
00572 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append_method, 0, 0, 1)
00573        ZEND_ARG_INFO(0, lob_descriptor_from)
00574 ZEND_END_ARG_INFO()
00575 
00576 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate_method, 0, 0, 0)
00577        ZEND_ARG_INFO(0, length)
00578 ZEND_END_ARG_INFO()
00579 
00580 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase_method, 0, 0, 0)
00581        ZEND_ARG_INFO(0, offset)
00582        ZEND_ARG_INFO(0, length)
00583 ZEND_END_ARG_INFO()
00584 
00585 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush_method, 0, 0, 0)
00586        ZEND_ARG_INFO(0, flag)
00587 ZEND_END_ARG_INFO()
00588 
00589 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_setbuffering_method, 0, 0, 1)
00590        ZEND_ARG_INFO(0, mode)
00591 ZEND_END_ARG_INFO()
00592 
00593 ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_getbuffering_method, 0)
00594 ZEND_END_ARG_INFO()
00595 
00596 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export_method, 0, 0, 1)
00597        ZEND_ARG_INFO(0, filename)
00598        ZEND_ARG_INFO(0, start)
00599        ZEND_ARG_INFO(0, length)
00600 ZEND_END_ARG_INFO()
00601 
00602 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_temporary_method, 0, 0, 1)
00603        ZEND_ARG_INFO(0, data)
00604        ZEND_ARG_INFO(0, type)
00605 ZEND_END_ARG_INFO()
00606 
00607 ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_close_method, 0)
00608 ZEND_END_ARG_INFO()
00609 
00610 ZEND_BEGIN_ARG_INFO(arginfo_oci_free_descriptor_method, 0)
00611 ZEND_END_ARG_INFO()
00612 /* }}} */
00613 
00614 /* {{{ Collection Method arginfo */
00615 ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_free_method, 0)
00616 ZEND_END_ARG_INFO()
00617 
00618 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append_method, 0, 0, 1)
00619        ZEND_ARG_INFO(0, value)
00620 ZEND_END_ARG_INFO()
00621 
00622 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get_method, 0, 0, 1)
00623        ZEND_ARG_INFO(0, index)
00624 ZEND_END_ARG_INFO()
00625 
00626 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign_method, 0, 0, 1)
00627        ZEND_ARG_INFO(0, collection_from)
00628 ZEND_END_ARG_INFO()
00629 
00630 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign_method, 0, 0, 2)
00631        ZEND_ARG_INFO(0, index)
00632        ZEND_ARG_INFO(0, value)
00633 ZEND_END_ARG_INFO()
00634 
00635 ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_size_method, 0)
00636 ZEND_END_ARG_INFO()
00637 
00638 ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_max_method, 0)
00639 ZEND_END_ARG_INFO()
00640 
00641 ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim_method, 0, 0, 1)
00642        ZEND_ARG_INFO(0, number)
00643 ZEND_END_ARG_INFO()
00644 /* }}} */
00645 
00646 #else /* ZEND_ENGINE_2 */
00647 /* {{{ Keep the old arginfo behavior when building with PHP 4 */
00648 
00649 static unsigned char arginfo_ocifetchinto[]  = { 2, BYREF_NONE, BYREF_FORCE };
00650 static unsigned char arginfo_oci_fetch_all[] = { 2, BYREF_NONE, BYREF_FORCE };
00651 static unsigned char arginfo_oci_define_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
00652 static unsigned char arginfo_oci_bind_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
00653 static unsigned char arginfo_oci_bind_array_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
00654 
00655 #define arginfo_oci_free_descriptor                                          NULL
00656 #define arginfo_oci_lob_save                                                 NULL
00657 #define arginfo_oci_lob_import                                               NULL
00658 #define arginfo_oci_lob_load                                                 NULL
00659 #define arginfo_oci_lob_read                                                 NULL
00660 #define arginfo_oci_lob_eof                                                  NULL
00661 #define arginfo_oci_lob_tell                                                 NULL
00662 #define arginfo_oci_lob_rewind                                               NULL
00663 #define arginfo_oci_lob_seek                                                 NULL
00664 #define arginfo_oci_lob_size                                                 NULL
00665 #define arginfo_oci_lob_write                                                NULL
00666 #define arginfo_oci_lob_append                                               NULL
00667 #define arginfo_oci_lob_truncate                                      NULL
00668 #define arginfo_oci_lob_erase                                                NULL
00669 #define arginfo_oci_lob_flush                                                NULL
00670 #define arginfo_ocisetbufferinglob                                    NULL
00671 #define arginfo_ocigetbufferinglob                                    NULL
00672 #define arginfo_oci_lob_copy                                                 NULL
00673 #define arginfo_oci_lob_is_equal                                      NULL
00674 #define arginfo_oci_lob_export                                               NULL
00675 #define arginfo_oci_new_descriptor                                    NULL
00676 #define arginfo_oci_rollback                                                 NULL
00677 #define arginfo_oci_commit                                                   NULL
00678 #define arginfo_oci_field_name                                               NULL
00679 #define arginfo_oci_field_size                                               NULL
00680 #define arginfo_oci_field_scale                                              NULL
00681 #define arginfo_oci_field_precision                                          NULL
00682 #define arginfo_oci_field_type                                               NULL
00683 #define arginfo_oci_field_type_raw                                    NULL
00684 #define arginfo_oci_field_is_null                                     NULL
00685 #define arginfo_oci_internal_debug                                    NULL
00686 #define arginfo_oci_execute                                                  NULL
00687 #define arginfo_oci_cancel                                                   NULL
00688 #define arginfo_oci_fetch                                                    NULL
00689 #define arginfo_oci_fetch_object                                      NULL
00690 #define arginfo_oci_fetch_row                                                NULL
00691 #define arginfo_oci_fetch_assoc                                              NULL
00692 #define arginfo_oci_fetch_array                                              NULL
00693 #define arginfo_oci_free_statement                                    NULL
00694 #define arginfo_oci_close                                                    NULL
00695 #define arginfo_oci_new_connect                                              NULL
00696 #define arginfo_oci_connect                                                  NULL
00697 #define arginfo_oci_pconnect                                                 NULL
00698 #define arginfo_oci_error                                                    NULL
00699 #define arginfo_oci_num_fields                                               NULL
00700 #define arginfo_oci_parse                                                    NULL
00701 #define arginfo_oci_set_prefetch                                      NULL
00702 #define arginfo_oci_set_client_identifier                      NULL
00703 #define arginfo_oci_set_edition                                              NULL
00704 #define arginfo_oci_set_module_name                                          NULL
00705 #define arginfo_oci_set_action                                               NULL
00706 #define arginfo_oci_set_client_info                                          NULL
00707 #define arginfo_oci_password_change                                          NULL
00708 #define arginfo_oci_new_cursor                                               NULL
00709 #define arginfo_oci_result                                                   NULL
00710 #define arginfo_oci_client_version                                    NULL
00711 #define arginfo_oci_server_version                                    NULL
00712 #define arginfo_oci_statement_type                                    NULL
00713 #define arginfo_oci_num_rows                                                 NULL
00714 #define arginfo_oci_free_collection                                          NULL
00715 #define arginfo_oci_collection_append                                 NULL
00716 #define arginfo_oci_collection_element_get                            NULL
00717 #define arginfo_oci_collection_assign                                 NULL
00718 #define arginfo_oci_collection_element_assign                  NULL
00719 #define arginfo_oci_collection_size                                          NULL
00720 #define arginfo_oci_collection_max                                    NULL
00721 #define arginfo_oci_collection_trim                                          NULL
00722 #define arginfo_oci_new_collection                                    NULL
00723 #define arginfo_oci_lob_size_method                                          NULL
00724 #define arginfo_oci_lob_getbuffering_method                           NULL
00725 #define arginfo_oci_lob_close_method                                  NULL
00726 #define arginfo_oci_lob_save_method                                          NULL
00727 #define arginfo_oci_lob_import_method                                 NULL
00728 #define arginfo_oci_lob_read_method                                          NULL
00729 #define arginfo_oci_lob_seek_method                                          NULL
00730 #define arginfo_oci_lob_write_method                                  NULL
00731 #define arginfo_oci_lob_append_method                                 NULL
00732 #define arginfo_oci_lob_truncate_method                               NULL
00733 #define arginfo_oci_lob_erase_method                                  NULL
00734 #define arginfo_oci_lob_flush_method                                  NULL
00735 #define arginfo_oci_lob_setbuffering_method                           NULL
00736 #define arginfo_oci_lob_export_method                                 NULL
00737 #define arginfo_oci_lob_write_temporary_method                 NULL
00738 #define arginfo_oci_lob_load_method                                          NULL
00739 #define arginfo_oci_lob_tell_method                                          NULL
00740 #define arginfo_oci_lob_rewind_method                                 NULL
00741 #define arginfo_oci_lob_eof_method                                    NULL
00742 #define arginfo_oci_free_descriptor_method                            NULL
00743 #define arginfo_oci_collection_append_method                   NULL
00744 #define arginfo_oci_collection_element_get_method              NULL
00745 #define arginfo_oci_collection_assign_method                   NULL
00746 #define arginfo_oci_collection_size_method                            NULL
00747 #define arginfo_oci_collection_element_assign_method    NULL
00748 #define arginfo_oci_collection_max_method                      NULL
00749 #define arginfo_oci_collection_trim_method                            NULL
00750 #define arginfo_oci_collection_free_method                            NULL
00751 /* }}} */
00752 #endif /* ZEND_ENGINE_2 */
00753 
00754 /* {{{ extension function prototypes
00755 */
00756 PHP_FUNCTION(oci_bind_by_name);
00757 PHP_FUNCTION(oci_bind_array_by_name);
00758 PHP_FUNCTION(oci_define_by_name);
00759 PHP_FUNCTION(oci_field_is_null);
00760 PHP_FUNCTION(oci_field_name);
00761 PHP_FUNCTION(oci_field_size);
00762 PHP_FUNCTION(oci_field_scale);
00763 PHP_FUNCTION(oci_field_precision);
00764 PHP_FUNCTION(oci_field_type);
00765 PHP_FUNCTION(oci_field_type_raw);
00766 PHP_FUNCTION(oci_execute);
00767 PHP_FUNCTION(oci_fetch);
00768 PHP_FUNCTION(oci_cancel);
00769 PHP_FUNCTION(ocifetchinto);
00770 PHP_FUNCTION(oci_fetch_object);
00771 PHP_FUNCTION(oci_fetch_row);
00772 PHP_FUNCTION(oci_fetch_assoc);
00773 PHP_FUNCTION(oci_fetch_array);
00774 PHP_FUNCTION(ocifetchstatement);
00775 PHP_FUNCTION(oci_fetch_all);
00776 PHP_FUNCTION(oci_free_statement);
00777 PHP_FUNCTION(oci_internal_debug);
00778 PHP_FUNCTION(oci_close);
00779 PHP_FUNCTION(oci_connect);
00780 PHP_FUNCTION(oci_new_connect);
00781 PHP_FUNCTION(oci_pconnect);
00782 PHP_FUNCTION(oci_error);
00783 PHP_FUNCTION(oci_free_descriptor);
00784 PHP_FUNCTION(oci_commit);
00785 PHP_FUNCTION(oci_rollback);
00786 PHP_FUNCTION(oci_new_descriptor);
00787 PHP_FUNCTION(oci_num_fields);
00788 PHP_FUNCTION(oci_parse);
00789 PHP_FUNCTION(oci_new_cursor);
00790 PHP_FUNCTION(oci_result);
00791 PHP_FUNCTION(oci_client_version);
00792 PHP_FUNCTION(oci_server_version);
00793 PHP_FUNCTION(oci_statement_type);
00794 PHP_FUNCTION(oci_num_rows);
00795 PHP_FUNCTION(oci_set_prefetch);
00796 PHP_FUNCTION(oci_set_client_identifier);
00797 PHP_FUNCTION(oci_set_edition);
00798 PHP_FUNCTION(oci_set_module_name);
00799 PHP_FUNCTION(oci_set_action);
00800 PHP_FUNCTION(oci_set_client_info);
00801 PHP_FUNCTION(oci_password_change);
00802 PHP_FUNCTION(oci_lob_save);
00803 PHP_FUNCTION(oci_lob_import);
00804 PHP_FUNCTION(oci_lob_export);
00805 PHP_FUNCTION(oci_lob_load);
00806 PHP_FUNCTION(oci_lob_tell);
00807 PHP_FUNCTION(oci_lob_write);
00808 PHP_FUNCTION(oci_lob_append);
00809 PHP_FUNCTION(oci_lob_copy);
00810 PHP_FUNCTION(oci_lob_truncate);
00811 PHP_FUNCTION(oci_lob_erase);
00812 PHP_FUNCTION(oci_lob_flush);
00813 PHP_FUNCTION(ocisetbufferinglob);
00814 PHP_FUNCTION(ocigetbufferinglob);
00815 PHP_FUNCTION(oci_lob_is_equal);
00816 PHP_FUNCTION(oci_lob_rewind);
00817 PHP_FUNCTION(oci_lob_read);
00818 PHP_FUNCTION(oci_lob_eof);
00819 PHP_FUNCTION(oci_lob_seek);
00820 PHP_FUNCTION(oci_lob_size);
00821 PHP_FUNCTION(oci_lob_write_temporary);
00822 PHP_FUNCTION(oci_lob_close);
00823 PHP_FUNCTION(oci_new_collection);
00824 PHP_FUNCTION(oci_free_collection);
00825 PHP_FUNCTION(oci_collection_append);
00826 PHP_FUNCTION(oci_collection_element_get);
00827 PHP_FUNCTION(oci_collection_element_assign);
00828 PHP_FUNCTION(oci_collection_assign);
00829 PHP_FUNCTION(oci_collection_size);
00830 PHP_FUNCTION(oci_collection_max);
00831 PHP_FUNCTION(oci_collection_trim);
00832 /* }}} */
00833 
00834 /* {{{ extension definition structures
00835 */
00836 static
00837 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
00838 /* This "if" allows PECL builds from this file to be portable to older PHP releases */
00839 const
00840 #endif
00841 zend_function_entry php_oci_functions[] = {
00842        PHP_FE(oci_define_by_name,                arginfo_oci_define_by_name)
00843        PHP_FE(oci_bind_by_name,                  arginfo_oci_bind_by_name)
00844        PHP_FE(oci_bind_array_by_name,            arginfo_oci_bind_array_by_name)
00845        PHP_FE(oci_field_is_null,                 arginfo_oci_field_is_null)
00846        PHP_FE(oci_field_name,                           arginfo_oci_field_name)
00847        PHP_FE(oci_field_size,                           arginfo_oci_field_size)
00848        PHP_FE(oci_field_scale,                          arginfo_oci_field_scale)
00849        PHP_FE(oci_field_precision,               arginfo_oci_field_precision)
00850        PHP_FE(oci_field_type,                           arginfo_oci_field_type)
00851        PHP_FE(oci_field_type_raw,                arginfo_oci_field_type_raw)
00852        PHP_FE(oci_execute,                              arginfo_oci_execute)
00853        PHP_FE(oci_cancel,                               arginfo_oci_cancel)
00854        PHP_FE(oci_fetch,                                arginfo_oci_fetch)
00855        PHP_FE(oci_fetch_object,                  arginfo_oci_fetch_object)
00856        PHP_FE(oci_fetch_row,                            arginfo_oci_fetch_row)
00857        PHP_FE(oci_fetch_assoc,                          arginfo_oci_fetch_assoc)
00858        PHP_FE(oci_fetch_array,                          arginfo_oci_fetch_array)
00859        PHP_FE(ocifetchinto,                      arginfo_ocifetchinto)
00860        PHP_FE(oci_fetch_all,                            arginfo_oci_fetch_all)
00861        PHP_FE(oci_free_statement,                arginfo_oci_free_statement)
00862        PHP_FE(oci_internal_debug,                arginfo_oci_internal_debug)
00863        PHP_FE(oci_num_fields,                           arginfo_oci_num_fields)
00864        PHP_FE(oci_parse,                                arginfo_oci_parse)
00865        PHP_FE(oci_new_cursor,                           arginfo_oci_new_cursor)
00866        PHP_FE(oci_result,                               arginfo_oci_result)
00867        PHP_FE(oci_client_version,                arginfo_oci_client_version)
00868        PHP_FE(oci_server_version,                arginfo_oci_server_version)
00869        PHP_FE(oci_statement_type,                arginfo_oci_statement_type)
00870        PHP_FE(oci_num_rows,                      arginfo_oci_num_rows)
00871        PHP_FE(oci_close,                                arginfo_oci_close)
00872        PHP_FE(oci_connect,                              arginfo_oci_connect)
00873        PHP_FE(oci_new_connect,                          arginfo_oci_new_connect)
00874        PHP_FE(oci_pconnect,                      arginfo_oci_pconnect)
00875        PHP_FE(oci_error,                                arginfo_oci_error)
00876        PHP_FE(oci_free_descriptor,               arginfo_oci_free_descriptor)
00877        PHP_FE(oci_lob_save,                      arginfo_oci_lob_save)
00878        PHP_FE(oci_lob_import,                           arginfo_oci_lob_import)
00879        PHP_FE(oci_lob_size,                      arginfo_oci_lob_size)
00880        PHP_FE(oci_lob_load,                      arginfo_oci_lob_load)
00881        PHP_FE(oci_lob_read,                      arginfo_oci_lob_read)
00882        PHP_FE(oci_lob_eof,                              arginfo_oci_lob_eof)
00883        PHP_FE(oci_lob_tell,                      arginfo_oci_lob_tell)
00884        PHP_FE(oci_lob_truncate,                  arginfo_oci_lob_truncate)
00885        PHP_FE(oci_lob_erase,                            arginfo_oci_lob_erase)
00886        PHP_FE(oci_lob_flush,                            arginfo_oci_lob_flush)
00887        PHP_FE(ocisetbufferinglob,                arginfo_ocisetbufferinglob)
00888        PHP_FE(ocigetbufferinglob,                arginfo_ocigetbufferinglob)
00889        PHP_FE(oci_lob_is_equal,                  arginfo_oci_lob_is_equal)
00890        PHP_FE(oci_lob_rewind,                           arginfo_oci_lob_rewind)
00891        PHP_FE(oci_lob_write,                            arginfo_oci_lob_write)
00892        PHP_FE(oci_lob_append,                           arginfo_oci_lob_append)
00893        PHP_FE(oci_lob_copy,                      arginfo_oci_lob_copy)
00894        PHP_FE(oci_lob_export,                           arginfo_oci_lob_export)
00895        PHP_FE(oci_lob_seek,                      arginfo_oci_lob_seek)
00896        PHP_FE(oci_commit,                               arginfo_oci_commit)
00897        PHP_FE(oci_rollback,                      arginfo_oci_rollback)
00898        PHP_FE(oci_new_descriptor,                arginfo_oci_new_descriptor)
00899        PHP_FE(oci_set_prefetch,                  arginfo_oci_set_prefetch)
00900        PHP_FE(oci_set_client_identifier,  arginfo_oci_set_client_identifier)
00901        PHP_FE(oci_set_edition,                          arginfo_oci_set_edition)
00902        PHP_FE(oci_set_module_name,               arginfo_oci_set_module_name)
00903        PHP_FE(oci_set_action,                           arginfo_oci_set_action)
00904        PHP_FE(oci_set_client_info,               arginfo_oci_set_client_info)
00905        PHP_FE(oci_password_change,               arginfo_oci_password_change)
00906        PHP_FE(oci_free_collection,               arginfo_oci_free_collection)
00907        PHP_FE(oci_collection_append,             arginfo_oci_collection_append)
00908        PHP_FE(oci_collection_element_get, arginfo_oci_collection_element_get)
00909        PHP_FE(oci_collection_element_assign,     arginfo_oci_collection_element_assign)
00910        PHP_FE(oci_collection_assign,             arginfo_oci_collection_assign)
00911        PHP_FE(oci_collection_size,               arginfo_oci_collection_size)
00912        PHP_FE(oci_collection_max,                arginfo_oci_collection_max)
00913        PHP_FE(oci_collection_trim,               arginfo_oci_collection_trim)
00914        PHP_FE(oci_new_collection,                arginfo_oci_new_collection)
00915 
00916        PHP_FALIAS(oci_free_cursor,        oci_free_statement,         arginfo_oci_free_statement)
00917        PHP_FALIAS(ocifreecursor,          oci_free_statement,         arginfo_oci_free_statement)
00918        PHP_FALIAS(ocibindbyname,          oci_bind_by_name,           arginfo_oci_bind_by_name)
00919        PHP_FALIAS(ocidefinebyname,        oci_define_by_name,         arginfo_oci_define_by_name)
00920        PHP_FALIAS(ocicolumnisnull,        oci_field_is_null,          arginfo_oci_field_is_null)
00921        PHP_FALIAS(ocicolumnname,          oci_field_name,                    arginfo_oci_field_name)
00922        PHP_FALIAS(ocicolumnsize,          oci_field_size,                    arginfo_oci_field_size)
00923        PHP_FALIAS(ocicolumnscale,         oci_field_scale,            arginfo_oci_field_scale)
00924        PHP_FALIAS(ocicolumnprecision,     oci_field_precision, arginfo_oci_field_precision)
00925        PHP_FALIAS(ocicolumntype,          oci_field_type,                    arginfo_oci_field_type)
00926        PHP_FALIAS(ocicolumntyperaw,       oci_field_type_raw,         arginfo_oci_field_type_raw)
00927        PHP_FALIAS(ociexecute,                    oci_execute,                arginfo_oci_execute)
00928        PHP_FALIAS(ocicancel,                     oci_cancel,                        arginfo_oci_cancel)
00929        PHP_FALIAS(ocifetch,               oci_fetch,                         arginfo_oci_fetch)
00930        PHP_FALIAS(ocifetchstatement,      oci_fetch_all,                     arginfo_oci_fetch_all)
00931        PHP_FALIAS(ocifreestatement,       oci_free_statement,         arginfo_oci_free_statement)
00932        PHP_FALIAS(ociinternaldebug,       oci_internal_debug,         arginfo_oci_internal_debug)
00933        PHP_FALIAS(ocinumcols,                    oci_num_fields,                    arginfo_oci_num_fields)
00934        PHP_FALIAS(ociparse,               oci_parse,                         arginfo_oci_parse)
00935        PHP_FALIAS(ocinewcursor,           oci_new_cursor,                    arginfo_oci_new_cursor)
00936        PHP_FALIAS(ociresult,                     oci_result,                        arginfo_oci_result)
00937        PHP_FALIAS(ociserverversion,       oci_server_version,         arginfo_oci_server_version)
00938        PHP_FALIAS(ocistatementtype,       oci_statement_type,         arginfo_oci_statement_type)
00939        PHP_FALIAS(ocirowcount,                   oci_num_rows,               arginfo_oci_num_rows)
00940        PHP_FALIAS(ocilogoff,                     oci_close,                         arginfo_oci_close)
00941        PHP_FALIAS(ocilogon,               oci_connect,                arginfo_oci_connect)
00942        PHP_FALIAS(ocinlogon,                     oci_new_connect,            arginfo_oci_new_connect)
00943        PHP_FALIAS(ociplogon,                     oci_pconnect,               arginfo_oci_pconnect)
00944        PHP_FALIAS(ocierror,               oci_error,                         arginfo_oci_error)
00945        PHP_FALIAS(ocifreedesc,                   oci_free_descriptor, arginfo_oci_free_descriptor)
00946        PHP_FALIAS(ocisavelob,                    oci_lob_save,               arginfo_oci_lob_save)
00947        PHP_FALIAS(ocisavelobfile,         oci_lob_import,                    arginfo_oci_lob_import)
00948        PHP_FALIAS(ociwritelobtofile,      oci_lob_export,                    arginfo_oci_lob_export)
00949        PHP_FALIAS(ociloadlob,                    oci_lob_load,               arginfo_oci_lob_load)
00950        PHP_FALIAS(ocicommit,                     oci_commit,                        arginfo_oci_commit)
00951        PHP_FALIAS(ocirollback,                   oci_rollback,               arginfo_oci_rollback)
00952        PHP_FALIAS(ocinewdescriptor,       oci_new_descriptor,         arginfo_oci_new_descriptor)
00953        PHP_FALIAS(ocisetprefetch,         oci_set_prefetch,           arginfo_oci_set_prefetch)
00954        PHP_FALIAS(ocipasswordchange,      oci_password_change, arginfo_oci_password_change)
00955        PHP_FALIAS(ocifreecollection,      oci_free_collection, arginfo_oci_free_collection)
00956        PHP_FALIAS(ocinewcollection,       oci_new_collection,         arginfo_oci_new_collection)
00957        PHP_FALIAS(ocicollappend,          oci_collection_append,      arginfo_oci_collection_append)
00958        PHP_FALIAS(ocicollgetelem,         oci_collection_element_get,        arginfo_oci_collection_element_get)
00959        PHP_FALIAS(ocicollassignelem,      oci_collection_element_assign,     arginfo_oci_collection_element_assign)
00960        PHP_FALIAS(ocicollsize,                   oci_collection_size, arginfo_oci_collection_size)
00961        PHP_FALIAS(ocicollmax,                    oci_collection_max,         arginfo_oci_collection_max)
00962        PHP_FALIAS(ocicolltrim,                   oci_collection_trim, arginfo_oci_collection_trim)
00963 #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)
00964        PHP_FE_END
00965 #else
00966        {NULL,NULL,NULL}
00967 #endif
00968 };
00969 
00970 static
00971 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
00972 /* This "if" allows PECL builds from this file to be portable to older PHP releases */
00973 const
00974 #endif
00975 zend_function_entry php_oci_lob_class_functions[] = {
00976        PHP_FALIAS(load,            oci_lob_load,               arginfo_oci_lob_load_method)
00977        PHP_FALIAS(tell,            oci_lob_tell,               arginfo_oci_lob_tell_method)
00978        PHP_FALIAS(truncate, oci_lob_truncate,           arginfo_oci_lob_truncate_method)
00979        PHP_FALIAS(erase,           oci_lob_erase,                     arginfo_oci_lob_erase_method)
00980        PHP_FALIAS(flush,           oci_lob_flush,                     arginfo_oci_lob_flush_method)
00981        PHP_FALIAS(setbuffering,ocisetbufferinglob,             arginfo_oci_lob_setbuffering_method)
00982        PHP_FALIAS(getbuffering,ocigetbufferinglob,             arginfo_oci_lob_getbuffering_method)
00983        PHP_FALIAS(rewind,          oci_lob_rewind,                    arginfo_oci_lob_rewind_method)
00984        PHP_FALIAS(read,            oci_lob_read,               arginfo_oci_lob_read_method)
00985        PHP_FALIAS(eof,                    oci_lob_eof,                arginfo_oci_lob_eof_method)
00986        PHP_FALIAS(seek,            oci_lob_seek,               arginfo_oci_lob_seek_method)
00987        PHP_FALIAS(write,           oci_lob_write,                     arginfo_oci_lob_write_method)
00988        PHP_FALIAS(append,          oci_lob_append,                    arginfo_oci_lob_append_method)
00989        PHP_FALIAS(size,            oci_lob_size,               arginfo_oci_lob_size_method)
00990        PHP_FALIAS(writetofile, oci_lob_export,                 arginfo_oci_lob_export_method)
00991        PHP_FALIAS(export,          oci_lob_export,                    arginfo_oci_lob_export_method)
00992        PHP_FALIAS(import,          oci_lob_import,                    arginfo_oci_lob_import_method)
00993        PHP_FALIAS(writetemporary,  oci_lob_write_temporary,    arginfo_oci_lob_write_temporary_method)
00994        PHP_FALIAS(close,                  oci_lob_close,                            arginfo_oci_lob_close_method)
00995        PHP_FALIAS(save,            oci_lob_save,               arginfo_oci_lob_save_method)
00996        PHP_FALIAS(savefile, oci_lob_import,                    arginfo_oci_lob_import_method)
00997        PHP_FALIAS(free,            oci_free_descriptor, arginfo_oci_free_descriptor_method)
00998 #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)
00999        PHP_FE_END
01000 #else
01001        {NULL,NULL,NULL}
01002 #endif
01003 };
01004 
01005 static
01006 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
01007 /* This "if" allows PECL builds from this file to be portable to older PHP releases */
01008 const
01009 #endif
01010 zend_function_entry php_oci_coll_class_functions[] = {
01011        PHP_FALIAS(append,            oci_collection_append,                  arginfo_oci_collection_append_method)
01012        PHP_FALIAS(getelem,           oci_collection_element_get,             arginfo_oci_collection_element_get_method)
01013        PHP_FALIAS(assignelem,        oci_collection_element_assign,   arginfo_oci_collection_element_assign_method)
01014        PHP_FALIAS(assign,            oci_collection_assign,                  arginfo_oci_collection_assign_method)
01015        PHP_FALIAS(size,              oci_collection_size,                           arginfo_oci_collection_size_method)
01016        PHP_FALIAS(max,                      oci_collection_max,                            arginfo_oci_collection_max_method)
01017        PHP_FALIAS(trim,              oci_collection_trim,                           arginfo_oci_collection_trim_method)
01018        PHP_FALIAS(free,              oci_free_collection,                           arginfo_oci_collection_free_method)
01019 #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)
01020        PHP_FE_END
01021 #else
01022        {NULL,NULL,NULL}
01023 #endif
01024 };
01025 
01026 zend_module_entry oci8_module_entry = {
01027        STANDARD_MODULE_HEADER,
01028        "oci8",                              /* extension name */
01029        php_oci_functions,     /* extension function list */
01030        PHP_MINIT(oci),               /* extension-wide startup function */
01031        PHP_MSHUTDOWN(oci),    /* extension-wide shutdown function */
01032        PHP_RINIT(oci),               /* per-request startup function */
01033        PHP_RSHUTDOWN(oci),    /* per-request shutdown function */
01034        PHP_MINFO(oci),               /* information function */
01035        PHP_OCI8_VERSION,
01036 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
01037        /* This check allows PECL builds from this file to be portable to older PHP releases */
01038        PHP_MODULE_GLOBALS(oci),  /* globals descriptor */
01039        PHP_GINIT(oci),                      /* globals ctor */
01040        PHP_GSHUTDOWN(oci),           /* globals dtor */
01041        NULL,                                /* post deactivate */
01042        STANDARD_MODULE_PROPERTIES_EX
01043 #else
01044        STANDARD_MODULE_PROPERTIES
01045 #endif
01046 };
01047 /* }}} */
01048 
01049 /* {{{ PHP_INI */
01050 PHP_INI_BEGIN()
01051        STD_PHP_INI_ENTRY(   "oci8.max_persistent",                    "-1",  PHP_INI_SYSTEM,      ONUPDATELONGFUNC,    max_persistent,                    zend_oci_globals,    oci_globals)
01052        STD_PHP_INI_ENTRY(   "oci8.persistent_timeout",         "-1",  PHP_INI_SYSTEM,      ONUPDATELONGFUNC,    persistent_timeout,         zend_oci_globals,    oci_globals)
01053        STD_PHP_INI_ENTRY(   "oci8.ping_interval",                     "60",  PHP_INI_SYSTEM,      ONUPDATELONGFUNC,    ping_interval,                     zend_oci_globals,    oci_globals)
01054        STD_PHP_INI_BOOLEAN("oci8.privileged_connect",          "0",   PHP_INI_SYSTEM,      OnUpdateBool,        privileged_connect,         zend_oci_globals,    oci_globals)
01055        STD_PHP_INI_ENTRY(   "oci8.statement_cache_size",       "20",  PHP_INI_SYSTEM,      ONUPDATELONGFUNC,    statement_cache_size,       zend_oci_globals,    oci_globals)
01056        STD_PHP_INI_ENTRY(   "oci8.default_prefetch",           "100", PHP_INI_SYSTEM,      ONUPDATELONGFUNC,    default_prefetch,           zend_oci_globals,    oci_globals)
01057        STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics",     "0",   PHP_INI_SYSTEM,      OnUpdateBool,        old_oci_close_semantics,zend_oci_globals, oci_globals)
01058        STD_PHP_INI_ENTRY(   "oci8.connection_class",           "",           PHP_INI_ALL,  OnUpdateString,             connection_class,           zend_oci_globals,    oci_globals)
01059        STD_PHP_INI_BOOLEAN("oci8.events",                             "0",   PHP_INI_SYSTEM,      OnUpdateBool,        events,                                   zend_oci_globals,    oci_globals)
01060 PHP_INI_END()
01061 /* }}} */
01062 
01063 /* {{{ startup, shutdown and info functions
01064 */
01065 
01066 /* {{{ php_oci_init_global_handles()
01067  *
01068  * Initialize global handles only when they are needed
01069  */
01070 static void php_oci_init_global_handles(TSRMLS_D)
01071 {
01072        sword errstatus;
01073        sb4   ora_error_code = 0;
01074        text  tmp_buf[OCI_ERROR_MAXMSG_SIZE];  /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
01075 
01076        errstatus = OCIEnvNlsCreate(&OCI_G(env), PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
01077 
01078        if (errstatus == OCI_ERROR) {
01079 #ifdef HAVE_OCI_INSTANT_CLIENT
01080               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");
01081 #else
01082               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");
01083 #endif
01084               if (OCI_G(env)
01085                      && OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
01086                      && *tmp_buf) {
01087                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tmp_buf);
01088               }
01089               
01090               OCI_G(env) = NULL;
01091               OCI_G(err) = NULL;
01092               return;
01093        }
01094 
01095        errstatus = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
01096 
01097        if (errstatus == OCI_SUCCESS) {
01098 #if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11)
01099               /* This fixes PECL bug 15988 (sqlnet.ora not being read).  The
01100                * root cause was fixed in Oracle 10.2.0.4 but there is no
01101                * compile time method to check for that precise patch level,
01102                * nor can it be guaranteed that runtime will use the same
01103                * patch level the code was compiled with.  So, we do this
01104                * code for all non 11g versions.
01105                */
01106               OCICPool *cpoolh;
01107               ub4 cpoolmode = 0x80000000; /* Pass invalid mode to OCIConnectionPoolCreate */
01108               PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
01109               PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
01110               PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
01111               PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
01112 #endif
01113        } else {
01114               OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ERROR);
01115 
01116               if (ora_error_code) {
01117                      int tmp_buf_len = strlen((char *)tmp_buf);
01118                      
01119                      if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
01120                             tmp_buf[tmp_buf_len - 1] = '\0';
01121                      }
01122                      
01123                      if (errstatus == OCI_SUCCESS_WITH_INFO) {
01124                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
01125                      } else {
01126                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_ERROR: %s", tmp_buf);
01127                             
01128                             OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
01129                             
01130                             OCI_G(env) = NULL;
01131                             OCI_G(err) = NULL;
01132                      }
01133               }
01134        }
01135 } /* }}} */
01136 
01137 /* {{{ php_oci_cleanup_global_handles()
01138  *
01139  * Free global handles (if they were initialized before)
01140  */
01141 static void php_oci_cleanup_global_handles(TSRMLS_D)
01142 {
01143        if (OCI_G(err)) {
01144               PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ERROR));
01145               OCI_G(err) = NULL;
01146        }
01147 
01148        if (OCI_G(env)) {
01149               PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV));
01150               OCI_G(env) = NULL;
01151        }
01152 } /* }}} */
01153 
01154 /* {{{ PHP_GINIT_FUNCTION
01155  *
01156  * Zerofill globals during module init
01157  */
01158 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
01159 /* This check allows PECL builds from this file to be portable to older PHP releases */
01160 static PHP_GINIT_FUNCTION(oci)
01161 #else
01162 static void php_oci_init_globals(zend_oci_globals *oci_globals TSRMLS_DC)
01163 #endif
01164 {
01165        memset(oci_globals, 0, sizeof(zend_oci_globals));
01166 }
01167 /* }}} */
01168 
01169 /* {{{ PHP_GSHUTDOWN_FUNCTION
01170  *
01171  * Called for thread shutdown in ZTS, after module shutdown for non-ZTS
01172  */
01173 /* This check allows PECL builds from this file to be portable to older PHP releases */
01174 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
01175 static PHP_GSHUTDOWN_FUNCTION(oci)
01176 #else
01177 static void php_oci_shutdown_globals(zend_oci_globals *oci_globals TSRMLS_DC)
01178 #endif
01179 {
01180        php_oci_cleanup_global_handles(TSRMLS_C);
01181 }
01182 /* }}} */
01183 
01184 PHP_MINIT_FUNCTION(oci)
01185 {
01186        zend_class_entry oci_lob_class_entry;
01187        zend_class_entry oci_coll_class_entry;
01188 
01189 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
01190        /* This check allows PECL builds from this file to be portable to older PHP releases */
01191        /* this is handled by new globals management code */
01192 #else
01193        ZEND_INIT_MODULE_GLOBALS(oci, php_oci_init_globals, php_oci_shutdown_globals);
01194 #endif
01195        REGISTER_INI_ENTRIES();
01196 
01197        le_statement = zend_register_list_destructors_ex(php_oci_statement_list_dtor, NULL, "oci8 statement", module_number);
01198        le_connection = zend_register_list_destructors_ex(php_oci_connection_list_dtor, NULL, "oci8 connection", module_number);
01199        le_pconnection = zend_register_list_destructors_ex(php_oci_pconnection_list_np_dtor, php_oci_pconnection_list_dtor, "oci8 persistent connection", module_number);
01200        le_psessionpool = zend_register_list_destructors_ex(NULL, php_oci_spool_list_dtor, "oci8 persistent session pool", module_number);
01201        le_descriptor = zend_register_list_destructors_ex(php_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number);
01202        le_collection = zend_register_list_destructors_ex(php_oci_collection_list_dtor, NULL, "oci8 collection", module_number);
01203 
01204        INIT_CLASS_ENTRY(oci_lob_class_entry, "OCI-Lob", php_oci_lob_class_functions);
01205        INIT_CLASS_ENTRY(oci_coll_class_entry, "OCI-Collection", php_oci_coll_class_functions);
01206 
01207        oci_lob_class_entry_ptr = zend_register_internal_class(&oci_lob_class_entry TSRMLS_CC);
01208        oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry TSRMLS_CC);
01209 
01210 /* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */
01211        REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
01212        REGISTER_LONG_CONSTANT("OCI_SYSOPER",OCI_SYSOPER, CONST_CS | CONST_PERSISTENT);
01213        REGISTER_LONG_CONSTANT("OCI_SYSDBA",OCI_SYSDBA, CONST_CS | CONST_PERSISTENT);
01214        REGISTER_LONG_CONSTANT("OCI_CRED_EXT",PHP_OCI_CRED_EXT, CONST_CS | CONST_PERSISTENT);
01215        REGISTER_LONG_CONSTANT("OCI_DESCRIBE_ONLY",OCI_DESCRIBE_ONLY, CONST_CS | CONST_PERSISTENT);
01216        REGISTER_LONG_CONSTANT("OCI_COMMIT_ON_SUCCESS",OCI_COMMIT_ON_SUCCESS, CONST_CS | CONST_PERSISTENT);
01217        REGISTER_LONG_CONSTANT("OCI_NO_AUTO_COMMIT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
01218        REGISTER_LONG_CONSTANT("OCI_EXACT_FETCH",OCI_EXACT_FETCH, CONST_CS | CONST_PERSISTENT);
01219 
01220 /* for $LOB->seek() */
01221        REGISTER_LONG_CONSTANT("OCI_SEEK_SET",PHP_OCI_SEEK_SET, CONST_CS | CONST_PERSISTENT);
01222        REGISTER_LONG_CONSTANT("OCI_SEEK_CUR",PHP_OCI_SEEK_CUR, CONST_CS | CONST_PERSISTENT);
01223        REGISTER_LONG_CONSTANT("OCI_SEEK_END",PHP_OCI_SEEK_END, CONST_CS | CONST_PERSISTENT);
01224 
01225 /*     for $LOB->flush() */
01226        REGISTER_LONG_CONSTANT("OCI_LOB_BUFFER_FREE",OCI_LOB_BUFFER_FREE, CONST_CS | CONST_PERSISTENT);
01227 
01228 /* for OCIBindByName (real "oci" names + short "php" names */
01229        REGISTER_LONG_CONSTANT("SQLT_BFILEE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
01230        REGISTER_LONG_CONSTANT("SQLT_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
01231        REGISTER_LONG_CONSTANT("SQLT_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
01232        REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
01233        REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
01234        REGISTER_LONG_CONSTANT("SQLT_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
01235        REGISTER_LONG_CONSTANT("SQLT_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
01236        REGISTER_LONG_CONSTANT("SQLT_RSET",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
01237        REGISTER_LONG_CONSTANT("SQLT_AFC",SQLT_AFC, CONST_CS | CONST_PERSISTENT);
01238        REGISTER_LONG_CONSTANT("SQLT_CHR",SQLT_CHR, CONST_CS | CONST_PERSISTENT);
01239        REGISTER_LONG_CONSTANT("SQLT_VCS",SQLT_VCS, CONST_CS | CONST_PERSISTENT);
01240        REGISTER_LONG_CONSTANT("SQLT_AVC",SQLT_AVC, CONST_CS | CONST_PERSISTENT);
01241        REGISTER_LONG_CONSTANT("SQLT_STR",SQLT_STR, CONST_CS | CONST_PERSISTENT);
01242        REGISTER_LONG_CONSTANT("SQLT_LVC",SQLT_LVC, CONST_CS | CONST_PERSISTENT);
01243        REGISTER_LONG_CONSTANT("SQLT_FLT",SQLT_FLT, CONST_CS | CONST_PERSISTENT);
01244        REGISTER_LONG_CONSTANT("SQLT_UIN",SQLT_UIN, CONST_CS | CONST_PERSISTENT);
01245        REGISTER_LONG_CONSTANT("SQLT_LNG",SQLT_LNG, CONST_CS | CONST_PERSISTENT);
01246        REGISTER_LONG_CONSTANT("SQLT_LBI",SQLT_LBI, CONST_CS | CONST_PERSISTENT);
01247        REGISTER_LONG_CONSTANT("SQLT_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
01248        REGISTER_LONG_CONSTANT("SQLT_ODT",SQLT_ODT, CONST_CS | CONST_PERSISTENT);
01249 #if defined(HAVE_OCI_INSTANT_CLIENT) || (defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 10)
01250        REGISTER_LONG_CONSTANT("SQLT_BDOUBLE",SQLT_BDOUBLE, CONST_CS | CONST_PERSISTENT);
01251        REGISTER_LONG_CONSTANT("SQLT_BFLOAT",SQLT_BFLOAT, CONST_CS | CONST_PERSISTENT);
01252 #endif
01253 
01254        REGISTER_LONG_CONSTANT("OCI_B_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
01255        REGISTER_LONG_CONSTANT("SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
01256        REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE", CONST_CS | CONST_PERSISTENT);
01257 
01258        REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
01259        REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
01260        REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
01261        REGISTER_LONG_CONSTANT("OCI_B_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
01262        REGISTER_LONG_CONSTANT("OCI_B_ROWID",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
01263        REGISTER_LONG_CONSTANT("OCI_B_CURSOR",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
01264        REGISTER_LONG_CONSTANT("OCI_B_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
01265        REGISTER_LONG_CONSTANT("OCI_B_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
01266        REGISTER_LONG_CONSTANT("OCI_B_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
01267 
01268 /* for OCIFetchStatement */
01269        REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_COLUMN", PHP_OCI_FETCHSTATEMENT_BY_COLUMN, CONST_CS | CONST_PERSISTENT);
01270        REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_ROW", PHP_OCI_FETCHSTATEMENT_BY_ROW, CONST_CS | CONST_PERSISTENT);
01271 
01272 /* for OCIFetchInto & OCIResult */
01273        REGISTER_LONG_CONSTANT("OCI_ASSOC",PHP_OCI_ASSOC, CONST_CS | CONST_PERSISTENT);
01274        REGISTER_LONG_CONSTANT("OCI_NUM",PHP_OCI_NUM, CONST_CS | CONST_PERSISTENT);
01275        REGISTER_LONG_CONSTANT("OCI_BOTH",PHP_OCI_BOTH, CONST_CS | CONST_PERSISTENT);
01276        REGISTER_LONG_CONSTANT("OCI_RETURN_NULLS",PHP_OCI_RETURN_NULLS, CONST_CS | CONST_PERSISTENT);
01277        REGISTER_LONG_CONSTANT("OCI_RETURN_LOBS",PHP_OCI_RETURN_LOBS, CONST_CS | CONST_PERSISTENT);
01278 
01279 /* for OCINewDescriptor (real "oci" names + short "php" names */
01280        REGISTER_LONG_CONSTANT("OCI_DTYPE_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
01281        REGISTER_LONG_CONSTANT("OCI_DTYPE_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
01282        REGISTER_LONG_CONSTANT("OCI_DTYPE_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
01283 
01284        REGISTER_LONG_CONSTANT("OCI_D_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
01285        REGISTER_LONG_CONSTANT("OCI_D_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
01286        REGISTER_LONG_CONSTANT("OCI_D_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
01287 
01288 /* for OCIWriteTemporaryLob */
01289        REGISTER_LONG_CONSTANT("OCI_TEMP_CLOB",OCI_TEMP_CLOB, CONST_CS | CONST_PERSISTENT);
01290        REGISTER_LONG_CONSTANT("OCI_TEMP_BLOB",OCI_TEMP_BLOB, CONST_CS | CONST_PERSISTENT);
01291 
01292        return SUCCESS;
01293 }
01294 
01295 PHP_RINIT_FUNCTION(oci)
01296 {
01297        OCI_G(debug_mode) = 0; /* start "fresh" */
01298        OCI_G(num_links) = OCI_G(num_persistent);
01299        OCI_G(errcode) = 0;
01300        OCI_G(edition) = NULL;
01301 
01302        return SUCCESS;
01303 }
01304 
01305 PHP_MSHUTDOWN_FUNCTION(oci)
01306 {
01307 /* Work around PHP_GSHUTDOWN_FUNCTION not being called in older versions of PHP */
01308 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) || (PHP_MAJOR_VERSION < 5)
01309 #ifndef ZTS
01310        php_oci_cleanup_global_handles(TSRMLS_C);
01311 #endif
01312 #endif
01313 
01314        OCI_G(shutdown) = 1;
01315 
01316        UNREGISTER_INI_ENTRIES();
01317 
01318        return SUCCESS;
01319 }
01320 
01321 PHP_RSHUTDOWN_FUNCTION(oci)
01322 {
01323        /* Check persistent connections and do the necessary actions if needed. If persistent_helper is
01324         * unable to process a pconnection because of a refcount, the processing would happen from
01325         * np-destructor which is called when refcount goes to zero - php_oci_pconnection_list_np_dtor
01326         */
01327        zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
01328 
01329        if (OCI_G(edition)) {
01330               efree(OCI_G(edition));
01331        }
01332 
01333        return SUCCESS;
01334 }
01335 
01336 PHP_MINFO_FUNCTION(oci)
01337 {
01338        char buf[32];
01339        char *ver;
01340 
01341        php_info_print_table_start();
01342        php_info_print_table_row(2, "OCI8 Support", "enabled");
01343        php_info_print_table_row(2, "Version", PHP_OCI8_VERSION);
01344        php_info_print_table_row(2, "Revision", "$Revision: 321634 $");
01345 
01346        snprintf(buf, sizeof(buf), "%ld", OCI_G(num_persistent));
01347        php_info_print_table_row(2, "Active Persistent Connections", buf);
01348        snprintf(buf, sizeof(buf), "%ld", OCI_G(num_links));
01349        php_info_print_table_row(2, "Active Connections", buf);
01350 
01351 #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
01352        php_oci_client_get_version(&ver TSRMLS_CC);
01353        php_info_print_table_row(2, "Oracle Run-time Client Library Version", ver);
01354        efree(ver);
01355 #endif
01356 #if    defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
01357        snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
01358 #elif defined(PHP_OCI8_ORACLE_VERSION)
01359        snprintf(buf, sizeof(buf), "%s", PHP_OCI8_ORACLE_VERSION);
01360 #else
01361        snprintf(buf, sizeof(buf), "Unknown");
01362 #endif
01363 #if defined(HAVE_OCI_INSTANT_CLIENT)
01364        php_info_print_table_row(2, "Oracle Instant Client Version", buf);
01365 #else
01366        php_info_print_table_row(2, "Oracle Version", buf);
01367 #endif
01368 
01369 #if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
01370 #if defined(PHP_OCI8_DEF_DIR)
01371        php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DEF_DIR);
01372 #endif
01373 #if defined(PHP_OCI8_DEF_SHARED_LIBADD)
01374        php_info_print_table_row(2, "Libraries Used", PHP_OCI8_DEF_SHARED_LIBADD);
01375 #endif
01376 #endif
01377 
01378        php_info_print_table_row(2, "Temporary Lob support", "enabled");
01379        php_info_print_table_row(2, "Collections support", "enabled");
01380        php_info_print_table_end();
01381        DISPLAY_INI_ENTRIES();
01382 }
01383 /* }}} */
01384 
01385 /* list destructors {{{ */
01386 
01387 /* {{{ php_oci_connection_list_dtor()
01388  *
01389  * Non-persistent connection destructor
01390  */
01391 static void php_oci_connection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
01392 {
01393        php_oci_connection *connection = (php_oci_connection *)entry->ptr;
01394 
01395        if (connection) {
01396               php_oci_connection_close(connection TSRMLS_CC);
01397               OCI_G(num_links)--;
01398        }
01399 } /* }}} */
01400 
01401 /* {{{ php_oci_pconnection_list_dtor()
01402  *
01403  * Persistent connection destructor
01404  */
01405 static void php_oci_pconnection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
01406 {
01407        php_oci_connection *connection = (php_oci_connection *)entry->ptr;
01408 
01409        if (connection) {
01410               php_oci_connection_close(connection TSRMLS_CC);
01411               OCI_G(num_persistent)--;
01412               OCI_G(num_links)--;
01413        }
01414 } /* }}} */
01415 
01416 /* {{{ php_oci_pconnection_list_np_dtor()
01417  *
01418  * Non-Persistent destructor for persistent connection - This gets invoked when
01419  * the refcount of this goes to zero in the regular list
01420  */
01421 static void php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
01422 {
01423        php_oci_connection *connection = (php_oci_connection *)entry->ptr;
01424        zend_rsrc_list_entry *le;
01425 
01426        /*
01427         * We cannot get connection as NULL or as a stub in this function. This is the function that
01428         * turns a pconnection to a stub
01429         *
01430         * If oci_password_change() changed the password of a persistent connection, close the
01431         * connection and remove it from the persistent connection cache.  This means subsequent scripts
01432         * will be prevented from being able to present the old (now invalid) password to a usable
01433         * connection to the database; they must use the new password.
01434         *
01435         * Check for conditions that warrant removal of the hash entry
01436         */
01437 
01438        if (!connection->is_open ||
01439               connection->passwd_changed ||
01440               (PG(connection_status) & PHP_CONNECTION_TIMEOUT) ||
01441               OCI_G(in_call)) {
01442 
01443               /* Remove the hash entry if present */
01444               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)) {
01445                      zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
01446               }
01447               else {
01448                      php_oci_connection_close(connection TSRMLS_CC);
01449                      OCI_G(num_persistent)--;
01450               }
01451 
01452               if (OCI_G(debug_mode)) {
01453                      php_printf ("OCI8 DEBUG L1: np_dtor cleaning up: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
01454               }
01455        }
01456        else {
01457               /*
01458                * Release the connection to underlying pool.  We do this unconditionally so that
01459                * out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect
01460                * semantics. With the PECL OCI 1.3.x extensions, we release pconnections when oci_close
01461                * takes the refcount to zero.
01462                *
01463                * If oci_old_close_semantics is set, we artifically bump up the refcount and decremented
01464                * only at request shutdown.
01465                */
01466               php_oci_connection_release(connection TSRMLS_CC);
01467 
01468               if (OCI_G(debug_mode)) {
01469                      php_printf ("OCI8 DEBUG L1: np_dtor releasing: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
01470               }
01471        }
01472 } /* }}} */
01473 
01474 /* {{{ php_oci_statement_list_dtor()
01475  *
01476  * Statement destructor
01477  */
01478 static void php_oci_statement_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
01479 {
01480        php_oci_statement *statement = (php_oci_statement *)entry->ptr;
01481        php_oci_statement_free(statement TSRMLS_CC);
01482 } /* }}} */
01483 
01484 /* {{{ php_oci_descriptor_list_dtor()
01485  *
01486  *     Descriptor destructor
01487  */
01488 static void php_oci_descriptor_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
01489 {
01490        php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
01491        php_oci_lob_free(descriptor TSRMLS_CC);
01492 } /* }}} */
01493 
01494 /* {{{ php_oci_collection_list_dtor()
01495  *
01496  * Collection destructor
01497  */
01498 static void php_oci_collection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
01499 {
01500        php_oci_collection *collection = (php_oci_collection *)entry->ptr;
01501        php_oci_collection_close(collection TSRMLS_CC);
01502 } /* }}} */
01503 
01504 /* }}} */
01505 
01506 /* Hash Destructors {{{ */
01507 
01508 /* {{{ php_oci_define_hash_dtor()
01509  *
01510  * Define hash destructor
01511  */
01512 void php_oci_define_hash_dtor(void *data)
01513 {
01514        php_oci_define *define = (php_oci_define *) data;
01515 
01516        zval_ptr_dtor(&define->zval);
01517 
01518        if (define->name) {
01519               efree(define->name);
01520               define->name = NULL;
01521        }
01522 }
01523 /* }}} */
01524 
01525 /* {{{ php_oci_bind_hash_dtor()
01526  *
01527  * Bind hash destructor
01528  */
01529 void php_oci_bind_hash_dtor(void *data)
01530 {
01531        php_oci_bind *bind = (php_oci_bind *) data;
01532 
01533        if (bind->array.elements) {
01534               efree(bind->array.elements);
01535        }
01536 
01537        if (bind->array.element_lengths) {
01538               efree(bind->array.element_lengths);
01539        }
01540 
01541        if (bind->array.indicators) {
01542               efree(bind->array.indicators);
01543        }
01544 
01545        zval_ptr_dtor(&bind->zval);
01546 }
01547 /* }}} */
01548 
01549 /* {{{ php_oci_column_hash_dtor()
01550  *
01551  * Column hash destructor
01552  */
01553 void php_oci_column_hash_dtor(void *data)
01554 {
01555        php_oci_out_column *column = (php_oci_out_column *) data;
01556        TSRMLS_FETCH();
01557 
01558        if (column->stmtid) {
01559               zend_list_delete(column->stmtid);
01560        }
01561 
01562        if (column->is_descr) {
01563               zend_list_delete(column->descid);
01564        }
01565 
01566        if (column->data) {
01567               efree(column->data);
01568        }
01569 
01570        if (column->name) {
01571               efree(column->name);
01572        }
01573 }
01574 /* }}} */
01575 
01576 /* {{{ php_oci_descriptor_flush_hash_dtor()
01577  *
01578  * Flush descriptors on commit
01579  */
01580 void php_oci_descriptor_flush_hash_dtor(void *data)
01581 {
01582        php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
01583        TSRMLS_FETCH();
01584 
01585        if (descriptor && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
01586               php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
01587               descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
01588        }
01589        data = NULL;
01590 }
01591 /* }}} */
01592 
01593 /* }}} */
01594 
01595 /* {{{ php_oci_connection_descriptors_free()
01596  *
01597  * Free descriptors for a connection
01598  */
01599 void php_oci_connection_descriptors_free(php_oci_connection *connection TSRMLS_DC)
01600 {
01601        zend_hash_destroy(connection->descriptors);
01602        efree(connection->descriptors);
01603        connection->descriptors = NULL;
01604        connection->descriptor_count = 0;
01605 }
01606 /* }}} */
01607 
01608 
01609 /* {{{ php_oci_error()
01610  *
01611  * Fetch & print out error message if we get an error
01612  * Returns an Oracle error number
01613  */
01614 sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC)
01615 {
01616        text *errbuf = (text *)NULL;
01617        sb4 errcode = 0;
01618 
01619        switch (status) {
01620               case OCI_SUCCESS:
01621                      break;
01622               case OCI_SUCCESS_WITH_INFO:
01623                      errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
01624                      if (errbuf) {
01625                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", errbuf);
01626                             efree(errbuf);
01627                      } else {
01628                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: failed to fetch error message");
01629                      }
01630                      break;
01631               case OCI_NEED_DATA:
01632                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NEED_DATA");
01633                      break;
01634               case OCI_NO_DATA:
01635                      errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
01636                      if (errbuf) {
01637                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
01638                             efree(errbuf);
01639                      } else {
01640                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NO_DATA: failed to fetch error message");
01641                      }
01642                      break;
01643               case OCI_ERROR:
01644                      errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
01645                      if (errbuf) {
01646                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
01647                             efree(errbuf);
01648                      } else {
01649                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to fetch error message");
01650                      }
01651                      break;
01652               case OCI_INVALID_HANDLE:
01653                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_INVALID_HANDLE");
01654                      break;
01655               case OCI_STILL_EXECUTING:
01656                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_STILL_EXECUTING");
01657                      break;
01658               case OCI_CONTINUE:
01659                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CONTINUE");
01660                      break;
01661               default:
01662                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown OCI error code: %d", status);
01663                      break;
01664        }
01665        return errcode;
01666 }
01667 /* }}} */
01668 
01669 /* {{{ php_oci_fetch_errmsg()
01670  *
01671  * Fetch error message into the buffer from the error handle provided
01672  */
01673 sb4 php_oci_fetch_errmsg(OCIError *error_handle, text **error_buf TSRMLS_DC)
01674 {
01675        sb4 error_code = 0;
01676        text err_buf[PHP_OCI_ERRBUF_LEN];
01677 
01678        memset(err_buf, 0, sizeof(err_buf));
01679        PHP_OCI_CALL(OCIErrorGet, (error_handle, (ub4)1, NULL, &error_code, err_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR));
01680 
01681        if (error_code) {
01682               int err_buf_len = strlen((char *)err_buf);
01683 
01684               if (err_buf_len && err_buf[err_buf_len - 1] == '\n') {
01685                      err_buf[err_buf_len - 1] = '\0';
01686               }
01687               if (err_buf_len && error_buf) {
01688                      *error_buf = NULL;
01689                      *error_buf = (text *)estrndup((char *)err_buf, err_buf_len);
01690               }
01691        }
01692        return error_code;
01693 } /* }}} */
01694 
01695 /* {{{ php_oci_fetch_sqltext_offset()
01696  *
01697  * Compute offset in the SQL statement
01698  */
01699 int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset TSRMLS_DC)
01700 {
01701        sword errstatus;
01702 
01703        *sqltext = NULL;
01704        *error_offset = 0;
01705        PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
01706 
01707        if (errstatus != OCI_SUCCESS) {
01708               statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
01709               PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
01710               return 1;
01711        }
01712 
01713        PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
01714 
01715        if (errstatus != OCI_SUCCESS) {
01716               statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
01717               PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
01718               return 1;
01719        }
01720        return 0;
01721 } /* }}} */
01722 
01723 /* {{{ php_oci_do_connect()
01724  *
01725  * Connect wrapper
01726  */
01727 void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
01728 {
01729        php_oci_connection *connection;
01730        char *username, *password;
01731        char *dbname = NULL, *charset = NULL;
01732        int username_len = 0, password_len = 0;
01733        int dbname_len = 0, charset_len = 0;
01734        long session_mode = OCI_DEFAULT;
01735 
01736        /* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
01737        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) {
01738               return;
01739        }
01740 
01741        if (!charset_len) {
01742               charset = NULL;
01743        }
01744 
01745        connection = php_oci_do_connect_ex(username, username_len, password, password_len, NULL, 0, dbname, dbname_len, charset, session_mode, persistent, exclusive TSRMLS_CC);
01746 
01747        if (!connection) {
01748               RETURN_FALSE;
01749        }
01750        RETURN_RESOURCE(connection->rsrc_id);
01751 
01752 } /* }}} */
01753 
01754 /* {{{ php_oci_do_connect_ex()
01755  *
01756  * The real connect function. Allocates all the resources needed, establishes the connection and
01757  * returns the result handle (or NULL)
01758  */
01759 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)
01760 {
01761        zend_rsrc_list_entry *le;
01762        zend_rsrc_list_entry new_le;
01763        php_oci_connection *connection = NULL;
01764        smart_str hashed_details = {0};
01765        time_t timestamp;
01766        php_oci_spool *session_pool = NULL;
01767        zend_bool use_spool = 1;       /* Default is to use client-side session pool */
01768        zend_bool ping_done = 0;
01769 
01770        ub2 charsetid = 0;
01771        ub2 charsetid_nls_lang = 0;
01772 
01773        if (session_mode & ~(OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
01774               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid session mode specified (%ld)", session_mode);
01775               return NULL;
01776        }
01777        if (session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
01778               if ((session_mode & OCI_SYSOPER) && (session_mode & OCI_SYSDBA)) {
01779                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SYSDBA and OCI_SYSOPER cannot be used together");
01780                      return NULL;
01781               }
01782               if (session_mode & PHP_OCI_CRED_EXT) {
01783 #ifdef PHP_WIN32
01784                      /* Disable external authentication on Windows as Impersonation is not yet handled.
01785                       * TODO: Re-enable this once OCI provides capability.
01786                       */
01787                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "External Authentication is not supported on Windows");
01788                      return NULL;
01789 #endif
01790                      if (username_len != 1 || username[0] != '/' || password_len != 0) {
01791                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CRED_EXT can only be used with a username of \"/\" and a NULL password");
01792                             return NULL;
01793                      }
01794               }
01795               if (session_mode & (OCI_SYSOPER | OCI_SYSDBA)) {
01796                      /* Increase security by not caching privileged oci_pconnect() connections. The
01797                       * connection becomes equivalent to oci_connect() or oci_new_connect().
01798                       */
01799                      persistent = 0;
01800                      if (!OCI_G(privileged_connect)) {
01801                             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");
01802                             return NULL;
01803                      }
01804 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5)
01805                      /* Safe mode has been removed in PHP 5.4 */
01806                      if (PG(safe_mode)) {
01807                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled in Safe Mode");
01808                             return NULL;
01809                      }
01810 #endif
01811               }
01812        }
01813 
01814        /* Initialize global handles if they weren't initialized before */
01815        if (OCI_G(env) == NULL) {
01816               php_oci_init_global_handles(TSRMLS_C);
01817               if (OCI_G(env) == NULL) {
01818                      return NULL;
01819               }
01820        }
01821 
01822        /* We cannot use the new session create logic (OCISessionGet from
01823         * client-side session pool) when privileged connect or password
01824         * change is attempted or OCI_CRED_EXT mode is specified.
01825         * TODO: Re-enable this when OCI provides support.
01826         */
01827        if ((session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) || (new_password_len)) {
01828               use_spool = 0;
01829        }
01830 
01831        smart_str_appendl_ex(&hashed_details, "oci8***", sizeof("oci8***") - 1, 0);
01832        smart_str_appendl_ex(&hashed_details, username, username_len, 0);
01833        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
01834 
01835        /* DRCP: connection_class is an attribute of a connection */
01836        if (OCI_G(connection_class)){
01837               smart_str_appendl_ex(&hashed_details, OCI_G(connection_class), strlen(OCI_G(connection_class)), 0);
01838        }
01839        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
01840 
01841        /* Add edition attribute to the hash */
01842        if (OCI_G(edition)){
01843               smart_str_appendl_ex(&hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
01844        }
01845        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
01846 
01847        if (password_len) {
01848               ulong password_hash;
01849               password_hash = zend_inline_hash_func(password, password_len);
01850               smart_str_append_unsigned_ex(&hashed_details, password_hash, 0);
01851        }
01852        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
01853 
01854        if (dbname) {
01855               smart_str_appendl_ex(&hashed_details, dbname, dbname_len, 0);
01856        }
01857        smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
01858 
01859        if (charset && *charset) {
01860               PHP_OCI_CALL_RETURN(charsetid, OCINlsCharSetNameToId, (OCI_G(env), (CONST oratext *)charset));
01861               if (!charsetid) {
01862                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid character set name: %s", charset);
01863               } else {
01864                      smart_str_append_unsigned_ex(&hashed_details, charsetid, 0);
01865               }
01866        }
01867 
01868        /* use NLS_LANG if no or invalid charset specified */
01869        if (!charsetid) {
01870               size_t rsize = 0;
01871               sword result;
01872 
01873               PHP_OCI_CALL_RETURN(result, OCINlsEnvironmentVariableGet, (&charsetid_nls_lang, 0, OCI_NLS_CHARSET_ID, 0, &rsize));
01874               if (result != OCI_SUCCESS) {
01875                      charsetid_nls_lang = 0;
01876               }
01877               smart_str_append_unsigned_ex(&hashed_details, charsetid_nls_lang, 0);
01878        }
01879 
01880        timestamp = time(NULL);
01881 
01882        smart_str_append_unsigned_ex(&hashed_details, session_mode, 0);
01883        smart_str_0(&hashed_details);
01884 
01885        /* make it lowercase */
01886        php_strtolower(hashed_details.c, hashed_details.len);
01887 
01888        if (!exclusive && !new_password) {
01889               zend_bool found = 0;
01890 
01891               if (persistent && zend_hash_find(&EG(persistent_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
01892                      found = 1;
01893                      /* found */
01894                      if (le->type == le_pconnection) {
01895                             connection = (php_oci_connection *)le->ptr;
01896                      }
01897               } else if (!persistent && zend_hash_find(&EG(regular_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
01898                      found = 1;
01899                      if (le->type == le_index_ptr) {
01900                             int type, link;
01901                             void *ptr;
01902 
01903                             link = OCI8_PTR_TO_INT(le->ptr);
01904                             ptr = zend_list_find(link,&type);
01905                             if (ptr && (type == le_connection)) {
01906                                    connection = (php_oci_connection *)ptr;
01907                             }
01908                      }
01909               }
01910 
01911               /* Debug statements {{{ */
01912               if (OCI_G(debug_mode)) {
01913                      if (connection && connection->is_stub) {
01914                             php_printf ("OCI8 DEBUG L1: Got a cached stub: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
01915                      } else if (connection) {
01916                             php_printf ("OCI8 DEBUG L1: Got a cached connection: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
01917                      } else {
01918                             php_printf ("OCI8 DEBUG L1: Got NO cached connection at (%s:%d) \n", __FILE__, __LINE__);
01919                      }
01920               } /* }}} */
01921 
01922               /* If we got a pconnection stub, then 'load'(OCISessionGet) the real connection from its
01923                * private spool A connection is a stub if it is only a cached structure and the real
01924                * connection is released to its underlying private session pool.  We currently do not have
01925                * stub support for non-persistent conns.
01926                *
01927                * TODO: put in negative code for non-persistent stubs
01928                */
01929               if (connection && connection->is_persistent && connection->is_stub) {
01930                      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)) {
01931                             smart_str_free_ex(&hashed_details, 0);
01932                             zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
01933 
01934                             return NULL;
01935                      }
01936                      /* We do the ping in php_oci_create_session, no need to ping again below */
01937                      ping_done = 1;
01938               }
01939 
01940               if (connection) {
01941                      if (connection->is_open) {
01942                             /* found an open connection. now ping it */
01943                             if (connection->is_persistent) {
01944                                    int rsrc_type;
01945 
01946                                    /* Check connection liveness in the following order:
01947                                     * 1) always check OCI_ATTR_SERVER_STATUS
01948                                     * 2) see if it's time to ping it
01949                                     * 3) ping it if needed
01950                                     */
01951                                    if (php_oci_connection_status(connection TSRMLS_CC)) {
01952                                           /* Only ping if:
01953                                            *
01954                                            * 1) next_ping > 0, which means that ping_interval is not -1 (aka "Off")
01955                                            *
01956                                            * 2) current_timestamp > next_ping, which means "it's time to check if it's
01957                                            * still alive"
01958                                            */
01959                                           if (!ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection TSRMLS_CC)) {
01960                                                  /* server died */
01961                                           } else {
01962                                                  php_oci_connection *tmp;
01963 
01964                                                  /* okay, the connection is open and the server is still alive */
01965                                                  connection->used_this_request = 1;
01966                                                  tmp = (php_oci_connection *)zend_list_find(connection->rsrc_id, &rsrc_type);
01967 
01968                                                  if (tmp != NULL && rsrc_type == le_pconnection && strlen(tmp->hash_key) == hashed_details.len &&
01969                                                         memcmp(tmp->hash_key, hashed_details.c, hashed_details.len) == 0 && zend_list_addref(connection->rsrc_id) == SUCCESS) {
01970                                                         /* do nothing */
01971                                                  } else {
01972 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
01973                                                         connection->rsrc_id = zend_list_insert(connection, le_pconnection TSRMLS_CC);
01974 #else
01975                                                         connection->rsrc_id = zend_list_insert(connection, le_pconnection);
01976 #endif
01977                                                         /* Persistent connections: For old close semantics we artificially
01978                                                          * bump up the refcount to prevent the non-persistent destructor
01979                                                          * from getting called until request shutdown. The refcount is
01980                                                          * decremented in the persistent helper
01981                                                          */
01982                                                         if (OCI_G(old_oci_close_semantics)) {
01983                                                                zend_list_addref(connection->rsrc_id);
01984                                                         }
01985                                                  }
01986                                                  smart_str_free_ex(&hashed_details, 0);
01987                                                  return connection;
01988                                           }
01989                                    }
01990                                    /* server died */
01991                             } else {
01992                                    /* we do not ping non-persistent connections */
01993                                    smart_str_free_ex(&hashed_details, 0);
01994                                    zend_list_addref(connection->rsrc_id);
01995                                    return connection;
01996                             }
01997                      } /* is_open is true? */
01998 
01999                      /* Server died - connection not usable. The is_open=true can also fall through to here,
02000                       * if ping fails
02001                       */
02002                      if (persistent){
02003                             int rsrc_type;
02004 
02005                             connection->is_open = 0;
02006                             connection->used_this_request = 1;
02007 
02008                             /* We have to do a hash_del but need to preserve the resource if there is a positive
02009                              * refcount. Set the data pointer in the list entry to NULL
02010                              */
02011                             if (connection == zend_list_find(connection->rsrc_id, &rsrc_type) && rsrc_type == le_pconnection) {
02012                                    le->ptr = NULL;
02013                             }
02014 
02015                             zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
02016                      } else {
02017                             /* We only remove the hash entry. The resource and the list entry with its pointer
02018                              * to the resource are still intact
02019                              */
02020                             zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
02021                      }
02022 
02023                      connection = NULL;
02024               } else if (found) {
02025                      /* found something, but it's not a connection, delete it */
02026                      if (persistent) {
02027                             zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
02028                      } else {
02029                             zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
02030                      }
02031               }
02032        }
02033 
02034        /* Check if we have reached max_persistent. If so, try to remove a few timed-out connections. As
02035         * a last resort, return a non-persistent connection.
02036         */
02037        if (persistent) {
02038               zend_bool alloc_non_persistent = 0;
02039 
02040               if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
02041                      /* try to find an idle connection and kill it */
02042                      zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
02043 
02044                      if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
02045                             /* all persistent connactions are in use, fallback to non-persistent connection creation */
02046                             php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Too many open persistent connections (%ld)", OCI_G(num_persistent));
02047                             alloc_non_persistent = 1;
02048                      }
02049               }
02050 
02051               if (alloc_non_persistent) {
02052                      connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
02053                      connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
02054                      connection->is_persistent = 0;
02055               } else {
02056                      connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
02057                      if (connection == NULL) {
02058                             return NULL;
02059                      }
02060                      connection->hash_key = zend_strndup(hashed_details.c, hashed_details.len);
02061                      if (connection->hash_key == NULL) {
02062                             free(connection);
02063                             return NULL;
02064                      }
02065                      connection->is_persistent = 1;
02066               }
02067        } else {
02068               connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
02069               connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
02070               connection->is_persistent = 0;
02071        }
02072 
02073        /* {{{ Get the session pool that suits this connection request from the persistent list. This
02074         * step is only for non-persistent connections as persistent connections have private session
02075         * pools. Non-persistent conns use shared session pool to allow for optimizations such as
02076         * caching the physical connection (for DRCP) even when the non-persistent php connection is
02077         * destroyed.
02078         *
02079         * TODO: Unconditionally do this once OCI provides extended OCISessionGet capability
02080         */
02081        if (use_spool && !connection->is_persistent) {
02082               if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang TSRMLS_CC))==NULL)
02083               {
02084                      php_oci_connection_close(connection TSRMLS_CC);
02085                      smart_str_free_ex(&hashed_details, 0);
02086                      return NULL;
02087               }
02088        } /* }}} */
02089 
02090        connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0;
02091 
02092        /* Mark password as unchanged by PHP during the duration of the database session */
02093        connection->passwd_changed = 0;
02094 
02095        smart_str_free_ex(&hashed_details, 0);
02096 
02097        if (charsetid) {
02098               connection->charset = charsetid;
02099        } else {
02100               connection->charset = charsetid_nls_lang;
02101        }
02102 
02103        /* Old session creation semantics when session pool cannot be used Eg: privileged
02104         * connect/password change
02105         */
02106        if (!use_spool) {
02107               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)) {
02108                      php_oci_connection_close(connection TSRMLS_CC);
02109                      return NULL;
02110               }
02111        } else {
02112               /* create using the client-side session pool */
02113               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)) {
02114                      php_oci_connection_close(connection TSRMLS_CC);
02115                      return NULL;
02116               }
02117        }
02118 
02119        /* Mark it as open */
02120        connection->is_open = 1;
02121 
02122        /* add to the appropriate hash */
02123        if (connection->is_persistent) {
02124               new_le.ptr = connection;
02125               new_le.type = le_pconnection;
02126               connection->used_this_request = 1;
02127 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
02128               connection->rsrc_id = zend_list_insert(connection, le_pconnection TSRMLS_CC);
02129 #else
02130               connection->rsrc_id = zend_list_insert(connection, le_pconnection);
02131 #endif
02132 
02133               /* Persistent connections: For old close semantics we artificially bump up the refcount to
02134                * prevent the non-persistent destructor from getting called until request shutdown. The
02135                * refcount is decremented in the persistent helper
02136                */
02137               if (OCI_G(old_oci_close_semantics)) {
02138                      zend_list_addref(connection->rsrc_id);
02139               }
02140               zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
02141               OCI_G(num_persistent)++;
02142               OCI_G(num_links)++;
02143        } else if (!exclusive) {
02144 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
02145               connection->rsrc_id = zend_list_insert(connection, le_connection TSRMLS_CC);
02146 #else
02147               connection->rsrc_id = zend_list_insert(connection, le_connection);
02148 #endif
02149               new_le.ptr = OCI8_INT_TO_PTR(connection->rsrc_id);
02150               new_le.type = le_index_ptr;
02151               zend_hash_update(&EG(regular_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
02152               OCI_G(num_links)++;
02153        } else {
02154 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
02155               connection->rsrc_id = zend_list_insert(connection, le_connection TSRMLS_CC);
02156 #else
02157               connection->rsrc_id = zend_list_insert(connection, le_connection);
02158 #endif
02159               OCI_G(num_links)++;
02160        }
02161 
02162        /* Debug statements {{{ */
02163        if (OCI_G(debug_mode)) {
02164               if (connection->is_persistent) {
02165                      php_printf ("OCI8 DEBUG L1: New Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
02166               } else {
02167                      php_printf ("OCI8 DEBUG L1: New Non-Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
02168               }
02169               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__);
02170        } /* }}} */
02171 
02172        return connection;
02173 }
02174 /* }}} */
02175 
02176 /* {{{ php_oci_connection_ping()
02177  *
02178  * Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version
02179  */
02180 static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC)
02181 {
02182        /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
02183         * such as from Pre-10.1 servers, the error is still from the server and we would have
02184         * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
02185         * Pre-10.2 clients
02186         */
02187 #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))  /* OCIPing available 10.2 onwards */
02188        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
02189 #else
02190        char version[256];
02191        /* use good old OCIServerVersion() */
02192        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX));
02193 #endif
02194 
02195        if (OCI_G(errcode) == OCI_SUCCESS) {
02196               return 1;
02197        } else {
02198               sb4 error_code = 0;
02199               text tmp_buf[OCI_ERROR_MAXMSG_SIZE];
02200 
02201               /* Treat ORA-1010 as a successful Ping */
02202               OCIErrorGet(OCI_G(err), (ub4)1, NULL, &error_code, tmp_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ERROR);
02203               if (error_code == 1010) {
02204                      return 1;
02205               }
02206        }
02207 
02208        /* ignore errors here, just return failure
02209         * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
02210        return 0;
02211 }
02212 /* }}} */
02213 
02214 /* {{{ php_oci_connection_status()
02215  *
02216  * Check connection status (pre-ping check)
02217  */
02218 static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC)
02219 {
02220        ub4 ss = 0;
02221 
02222        /* get OCI_ATTR_SERVER_STATUS */
02223        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)));
02224 
02225        if (OCI_G(errcode) == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) {
02226               return 1;
02227        }
02228 
02229        /* ignore errors here, just return failure
02230         * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
02231        return 0;
02232 }
02233 /* }}} */
02234 
02235 /* {{{ php_oci_connection_rollback()
02236  *
02237  * Rollback connection
02238  */
02239 int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC)
02240 {
02241        PHP_OCI_CALL_RETURN(connection->errcode, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
02242        connection->needs_commit = 0;
02243 
02244        if (connection->errcode != OCI_SUCCESS) {
02245               connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
02246               PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
02247               return 1;
02248        }
02249        return 0;
02250 } /* }}} */
02251 
02252 /* {{{ php_oci_connection_commit()
02253  *
02254  * Commit connection
02255  */
02256 int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
02257 {
02258        PHP_OCI_CALL_RETURN(connection->errcode, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
02259        connection->needs_commit = 0;
02260 
02261        if (connection->errcode != OCI_SUCCESS) {
02262               connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
02263               PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
02264               return 1;
02265        }
02266        return 0;
02267 } /* }}} */
02268 
02269 /* {{{ php_oci_connection_close()
02270  *
02271  * Close the connection and free all its resources
02272  */
02273 static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
02274 {
02275        int result = 0;
02276        zend_bool in_call_save = OCI_G(in_call);
02277 
02278        if (!connection->is_stub) {
02279               /* Release resources associated with connection */
02280               php_oci_connection_release(connection TSRMLS_CC);
02281        }
02282 
02283        if (!connection->using_spool && connection->svc) {
02284                      PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0));
02285        }
02286 
02287        if (connection->err) {
02288               PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->err, (ub4) OCI_HTYPE_ERROR));
02289        }
02290        if (connection->authinfo) {
02291               PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->authinfo, (ub4) OCI_HTYPE_AUTHINFO));
02292        }
02293 
02294        /* No Handlefrees for session pool connections */
02295        if (!connection->using_spool) {
02296               if (connection->session) {
02297                      PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->session, OCI_HTYPE_SESSION));
02298               }
02299 
02300               if (connection->is_attached) {
02301                      PHP_OCI_CALL(OCIServerDetach, (connection->server, OCI_G(err), OCI_DEFAULT));
02302               }
02303 
02304               if (connection->svc) {
02305                      PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
02306               }
02307 
02308               if (connection->server) {
02309                      PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->server, (ub4) OCI_HTYPE_SERVER));
02310               }
02311 
02312               if (connection->env) {
02313                      PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
02314               }
02315        } else if (connection->private_spool) {
02316        /* Keep this as the last member to be freed, as there are dependencies
02317         * (like env) on the session pool
02318         */
02319               php_oci_spool_close(connection->private_spool TSRMLS_CC);
02320        }
02321 
02322        if (connection->is_persistent) {
02323               if (connection->hash_key) {
02324                      free(connection->hash_key);
02325               }
02326               free(connection);
02327        } else {
02328               if (connection->hash_key) {
02329                      efree(connection->hash_key);
02330               }
02331               efree(connection);
02332        }
02333        connection = NULL;
02334        OCI_G(in_call) = in_call_save;
02335        return result;
02336 } /* }}} */
02337 
02338 /* {{{ php_oci_connection_release()
02339  *
02340  * Release the connection's resources. This involves freeing descriptors and rolling back
02341  * transactions, setting timeout-related parameters etc. For session-pool using connections, the
02342  * underlying connection is released to its session pool.
02343  */
02344 int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
02345 {
02346        int result = 0;
02347        zend_bool in_call_save = OCI_G(in_call);
02348        time_t timestamp = time(NULL);
02349 
02350        if (connection->is_stub) {
02351               return 0;
02352        }
02353 
02354        if (connection->descriptors) {
02355               php_oci_connection_descriptors_free(connection TSRMLS_CC);
02356        }
02357 
02358        if (connection->svc) {
02359               /* rollback outstanding transactions */
02360               if (connection->needs_commit) {
02361                      if (php_oci_connection_rollback(connection TSRMLS_CC)) {
02362                             /* rollback failed */
02363                             result = 1;
02364                      }
02365               }
02366        }
02367 
02368        if (OCI_G(persistent_timeout) > 0) {
02369               connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
02370        }
02371 
02372        /* We may have half-cooked connections to clean up */
02373        if (connection->next_pingp) {
02374               if (OCI_G(ping_interval) >= 0) {
02375                      *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
02376               } else {
02377                      /* ping_interval is -1 */
02378                      *(connection->next_pingp) = 0;
02379               }
02380        }
02381 
02382        /* Release the session (stubs are filtered out at the beginning)*/
02383        if (connection->using_spool) {
02384               ub4 rlsMode = OCI_DEFAULT;
02385 
02386               if (result) {
02387                      rlsMode |= OCI_SESSRLS_DROPSESS;
02388               }
02389 
02390               /* Sessions for non-persistent connections should be dropped.  For 11 and above, the session
02391                * pool has its own mechanism for doing so for purity NEW connections. We need to do so
02392                * explicitly for 10.2 and earlier.
02393                */
02394 #if (!(OCI_MAJOR_VERSION >= 11))
02395               if (!connection->is_persistent) {
02396                      rlsMode |= OCI_SESSRLS_DROPSESS;
02397               }
02398 #endif
02399 
02400               if (connection->svc) {
02401                      PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
02402                                                                        0, rlsMode));
02403               }
02404               /* It no longer has relation with the database session. However authinfo and env are
02405                * cached
02406                */
02407               connection->svc = NULL;
02408               connection->server = NULL;
02409               connection->session = NULL;
02410 
02411               connection->is_attached = connection->is_open = connection->needs_commit = connection->used_this_request = 0;
02412               connection->is_stub = 1;
02413 
02414               /* Cut the link between the connection structure and the time_t structure allocated within
02415                * the OCI session
02416                */
02417               connection->next_pingp = NULL;
02418        }
02419 
02420        OCI_G(in_call) = in_call_save;
02421        return result;
02422 } /* }}} */
02423 
02424 /* {{{ php_oci_password_change()
02425  *
02426  * Change password for the user with the username given
02427  */
02428 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)
02429 {
02430        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));
02431 
02432        if (connection->errcode != OCI_SUCCESS) {
02433               connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
02434               PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
02435               return 1;
02436        }
02437        connection->passwd_changed = 1;
02438        return 0;
02439 } /* }}} */
02440 
02441 
02442 /* {{{ php_oci_client_get_version()
02443  *
02444  * Get Oracle client library version
02445  */
02446 void php_oci_client_get_version(char **version TSRMLS_DC)
02447 {
02448        char  version_buff[256];
02449        sword major_version = 0;
02450        sword minor_version = 0; 
02451        sword update_num = 0;
02452        sword patch_num = 0;
02453        sword port_update_num = 0;
02454 
02455 #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))  /* OCIClientVersion only available 10.2 onwards */
02456        PHP_OCI_CALL(OCIClientVersion, (&major_version, &minor_version, &update_num, &patch_num, &port_update_num));
02457        snprintf(version_buff, sizeof(version_buff), "%d.%d.%d.%d.%d", major_version, minor_version, update_num, patch_num, port_update_num);
02458 #else
02459        memcpy(version_buff, "Unknown", sizeof("Unknown"));
02460 #endif
02461        *version = estrdup(version_buff);
02462 } /* }}} */
02463 
02464 
02465 /* {{{ php_oci_server_get_version()
02466  *
02467  * Get Oracle server version
02468  */
02469 int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC)
02470 {
02471        char version_buff[256];
02472 
02473        PHP_OCI_CALL_RETURN(connection->errcode, OCIServerVersion, (connection->svc, connection->err, (text *)version_buff, sizeof(version_buff), OCI_HTYPE_SVCCTX));
02474 
02475        if (connection->errcode != OCI_SUCCESS) {
02476               connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
02477               PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
02478               return 1;
02479        }
02480 
02481        *version = estrdup(version_buff);
02482        return 0;
02483 } /* }}} */
02484 
02485 /* {{{ php_oci_column_to_zval()
02486  *
02487  * Convert php_oci_out_column struct into zval
02488  */
02489 int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSRMLS_DC)
02490 {
02491        php_oci_descriptor *descriptor;
02492        ub4 lob_length;
02493        int column_size;
02494        char *lob_buffer;
02495        int lob_fetch_status;
02496 
02497        if (column->indicator == -1) { /* column is NULL */
02498               ZVAL_NULL(value);
02499               return 0;
02500        }
02501 
02502        if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
02503               ZVAL_RESOURCE(value, column->stmtid);
02504               zend_list_addref(column->stmtid);
02505        } else if (column->is_descr) {
02506 
02507               if (column->data_type != SQLT_RDD) {
02508                      int rsrc_type;
02509 
02510                      /* reset descriptor's length */
02511                      descriptor = (php_oci_descriptor *) zend_list_find(column->descid, &rsrc_type);
02512 
02513                      if (!descriptor || rsrc_type != le_descriptor) {
02514                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find LOB descriptor #%d", column->descid);
02515                             return 1;
02516                      }
02517 
02518                      descriptor->lob_size = -1;
02519                      descriptor->lob_current_position = 0;
02520                      descriptor->buffering = 0;
02521               }
02522 
02523               if (column->data_type != SQLT_RDD && (mode & PHP_OCI_RETURN_LOBS)) {
02524                      /* PHP_OCI_RETURN_LOBS means that we want the content of the LOB back instead of the locator */
02525 
02526                      lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, &lob_buffer, &lob_length TSRMLS_CC);
02527                      php_oci_temp_lob_close(descriptor TSRMLS_CC);
02528                      if (lob_fetch_status) {
02529                             ZVAL_FALSE(value);
02530                             return 1;
02531                      } else {
02532                             if (lob_length > 0) {
02533                                    ZVAL_STRINGL(value, lob_buffer, lob_length, 0);
02534                             } else {
02535                                    ZVAL_EMPTY_STRING(value);
02536                             }
02537                             return 0;
02538                      }
02539               } else {
02540                      /* return the locator */
02541                      object_init_ex(value, oci_lob_class_entry_ptr);
02542                      add_property_resource(value, "descriptor", column->descid);
02543                      zend_list_addref(column->descid);
02544               }
02545        } else {
02546               switch (column->retcode) {
02547                      case 0:
02548                             /* intact value */
02549                             if (column->piecewise) {
02550                                    column_size = column->retlen4;
02551                             } else {
02552                                    column_size = column->retlen;
02553                             }
02554                             break;
02555 
02556                      default:
02557                             ZVAL_FALSE(value);
02558                             return 0;
02559               }
02560 
02561               ZVAL_STRINGL(value, column->data, column_size, 1);
02562        }
02563        return 0;
02564 }
02565 /* }}} */
02566 
02567 /* {{{ php_oci_fetch_row()
02568  *
02569  * Fetch the next row from the given statement
02570  */
02571 void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
02572 {
02573        zval *z_statement, *array;
02574        php_oci_statement *statement;
02575        php_oci_out_column *column;
02576        ub4 nrows = 1;
02577        int i;
02578        long fetch_mode = 0;
02579 
02580        if (expected_args > 2) {
02581               /* only for ocifetchinto BC */
02582 
02583               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|l", &z_statement, &array, &fetch_mode) == FAILURE) {
02584                      return;
02585               }
02586 
02587               if (ZEND_NUM_ARGS() == 2) {
02588                      fetch_mode = mode;
02589               }
02590        } else if (expected_args == 2) {
02591               /* only for oci_fetch_array() */
02592 
02593               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_statement, &fetch_mode) == FAILURE) {
02594                      return;
02595               }
02596 
02597               if (ZEND_NUM_ARGS() == 1) {
02598                      fetch_mode = mode;
02599               }
02600        } else {
02601               /* for all oci_fetch_*() */
02602 
02603               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
02604                      return;
02605               }
02606 
02607               fetch_mode = mode;
02608        }
02609 
02610        if (!(fetch_mode & PHP_OCI_NUM) && !(fetch_mode & PHP_OCI_ASSOC)) {
02611               /* none of the modes present, use the default one */
02612               if (mode & PHP_OCI_ASSOC) {
02613                      fetch_mode |= PHP_OCI_ASSOC;
02614               }
02615               if (mode & PHP_OCI_NUM) {
02616                      fetch_mode |= PHP_OCI_NUM;
02617               }
02618        }
02619 
02620        PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
02621 
02622        if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
02623               RETURN_FALSE;
02624        }
02625 
02626        array_init(return_value);
02627 
02628        for (i = 0; i < statement->ncolumns; i++) {
02629 
02630               column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
02631 
02632               if (column == NULL) {
02633                      continue;
02634               }
02635               if ((column->indicator == -1) && ((fetch_mode & PHP_OCI_RETURN_NULLS) == 0)) {
02636                      continue;
02637               }
02638 
02639               if (!(column->indicator == -1)) {
02640                      zval *element;
02641 
02642                      MAKE_STD_ZVAL(element);
02643                      php_oci_column_to_zval(column, element, fetch_mode TSRMLS_CC);
02644 
02645                      if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
02646                             add_index_zval(return_value, i, element);
02647                      }
02648                      if (fetch_mode & PHP_OCI_ASSOC) {
02649                             if (fetch_mode & PHP_OCI_NUM) {
02650                                    Z_ADDREF_P(element);
02651                             }
02652                             add_assoc_zval(return_value, column->name, element);
02653                      }
02654 
02655               } else {
02656                      if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
02657                             add_index_null(return_value, i);
02658                      }
02659                      if (fetch_mode & PHP_OCI_ASSOC) {
02660                             add_assoc_null(return_value, column->name);
02661                      }
02662               }
02663        }
02664 
02665        if (expected_args > 2) {
02666               /* Only for ocifetchinto BC.  In all other cases we return array, not long */
02667               REPLACE_ZVAL_VALUE(&array, return_value, 1); /* copy return_value to given reference */
02668               zval_dtor(return_value);
02669               RETURN_LONG(statement->ncolumns);
02670        }
02671 }
02672 /* }}} */
02673 
02674 /* {{{ php_oci_persistent_helper()
02675  *
02676  * Helper function to close/rollback persistent connections at the end of request. A return value of
02677  * 1 indicates that the connection is to be destroyed
02678  */
02679 static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
02680 {
02681        time_t timestamp;
02682        php_oci_connection *connection;
02683 
02684        timestamp = time(NULL);
02685 
02686        /* Persistent connection stubs are also counted as they have private session pools */
02687        if (le->type == le_pconnection) {
02688               connection = (php_oci_connection *)le->ptr;
02689 
02690               if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
02691                      if (OCI_G(debug_mode)) {
02692                             php_printf ("OCI8 DEBUG L1: persistent_helper processing for timeout: (%p stub=%d) at (%s:%d) \n", connection, connection->is_stub, __FILE__, __LINE__);
02693                      }
02694                      if (connection->idle_expiry < timestamp) {
02695                             /* connection has timed out */
02696                             return ZEND_HASH_APPLY_REMOVE;
02697                      }
02698               }
02699        }
02700        return ZEND_HASH_APPLY_KEEP;
02701 } /* }}} */
02702 
02703 /* {{{ php_oci_create_spool()
02704  *
02705  *      Create(alloc + Init) Session pool for the given dbname and charsetid
02706  */
02707 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)
02708 {
02709        php_oci_spool *session_pool = NULL;
02710        zend_bool iserror = 0;
02711        ub4 poolmode = OCI_DEFAULT; /* Mode to be passed to OCISessionPoolCreate */
02712        OCIAuthInfo *spoolAuth = NULL;
02713 
02714        /* Allocate sessionpool out of persistent memory */
02715        session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
02716        if (session_pool == NULL) {
02717               iserror = 1;
02718               goto exit_create_spool;
02719        }
02720 
02721        /* Populate key if passed */
02722        if (hash_key_len) {
02723               session_pool->spool_hash_key = zend_strndup(hash_key, hash_key_len);
02724               if (session_pool->spool_hash_key == NULL) {
02725                      iserror = 1;
02726                      goto exit_create_spool;
02727               }
02728        }
02729 
02730        /* Create the session pool's env */
02731        if (!(session_pool->env = php_oci_create_env(charsetid TSRMLS_CC))) {
02732               iserror = 1;
02733               goto exit_create_spool;
02734        }
02735 
02736        /* Allocate the pool handle */
02737        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
02738 
02739        if (OCI_G(errcode) != OCI_SUCCESS) {
02740               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02741               iserror = 1;
02742               goto exit_create_spool;
02743        }
02744 
02745        /* Allocate the session pool error handle - This only for use in the destructor, as there is a
02746         * generic bug which can free up the OCI_G(err) variable before destroying connections. We
02747         * cannot use this for other roundtrip calls as there is no way the user can access this error
02748         */
02749        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));
02750 
02751        if (OCI_G(errcode) != OCI_SUCCESS) {
02752               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02753               iserror = 1;
02754               goto exit_create_spool;
02755        }
02756 
02757 /* Disable RLB as we mostly have single-connection pools */
02758 #if (OCI_MAJOR_VERSION > 10)
02759        poolmode = OCI_SPC_NO_RLB | OCI_SPC_HOMOGENEOUS;
02760 #else
02761        poolmode = OCI_SPC_HOMOGENEOUS;
02762 #endif
02763 
02764 #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
02765        /* Allocate auth handle for session pool {{{ */
02766        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL));
02767 
02768        if (OCI_G(errcode) != OCI_SUCCESS) {
02769               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02770               iserror = 1;
02771               goto exit_create_spool;
02772        } /* }}} */
02773 
02774        /* Set the edition attribute on the auth handle {{{ */
02775        if (OCI_G(edition)) {
02776               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)));
02777 
02778               if (OCI_G(errcode) != OCI_SUCCESS) {
02779                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02780                      iserror = 1;
02781                      goto exit_create_spool;
02782               }
02783        } /* }}} */
02784 
02785        /* Set the driver name attribute on the auth handle {{{ */
02786        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)));
02787 
02788        if (OCI_G(errcode) != OCI_SUCCESS) {
02789               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02790               iserror = 1;
02791               goto exit_create_spool;
02792        } /* }}} */
02793 
02794        /* Set the auth handle on the session pool {{{ */
02795        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)));
02796 
02797        if (OCI_G(errcode) != OCI_SUCCESS) {
02798               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02799               iserror = 1;
02800               goto exit_create_spool;
02801        } /* }}} */
02802 #endif
02803 
02804        /* Create the homogeneous session pool - We have different session pools for every different
02805         * username, password, charset and dbname.
02806         */
02807        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));
02808 
02809        if (OCI_G(errcode) != OCI_SUCCESS) {
02810               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02811               iserror = 1;
02812        }
02813 
02814 exit_create_spool:
02815        if (iserror && session_pool) {
02816               php_oci_spool_close(session_pool TSRMLS_CC);
02817               session_pool = NULL;
02818        }
02819 
02820        if (spoolAuth) {
02821               PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO));
02822        }
02823 
02824        if (OCI_G(debug_mode)) {
02825               php_printf ("OCI8 DEBUG L1: create_spool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
02826        }
02827 
02828        return session_pool;
02829 } /* }}} */
02830 
02831 /* {{{ php_oci_get_spool()
02832  *
02833  * Get Session pool for the given dbname and charsetid from the persistent list. Function called for
02834  * non-persistent connections.
02835  */
02836 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)
02837 {
02838        smart_str spool_hashed_details = {0};
02839        php_oci_spool *session_pool = NULL;
02840        zend_rsrc_list_entry spool_le = {0};
02841        zend_rsrc_list_entry *spool_out_le = NULL;
02842        zend_bool iserror = 0;
02843 
02844        /* Create the spool hash key {{{ */
02845        smart_str_appendl_ex(&spool_hashed_details, "oci8spool***", sizeof("oci8spool***") - 1, 0);
02846        smart_str_appendl_ex(&spool_hashed_details, username, username_len, 0);
02847        smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
02848        /* Add edition attribute to the hash */
02849        if (OCI_G(edition)){
02850               smart_str_appendl_ex(&spool_hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
02851        }
02852        smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
02853        if (password_len) {
02854               ulong password_hash;
02855               password_hash = zend_inline_hash_func(password, password_len);
02856               smart_str_append_unsigned_ex(&spool_hashed_details, password_hash, 0);
02857        }
02858        smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
02859 
02860        if (dbname_len) {
02861               smart_str_appendl_ex(&spool_hashed_details, dbname, dbname_len, 0);
02862        }
02863        smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
02864 
02865        smart_str_append_unsigned_ex(&spool_hashed_details, charsetid, 0);
02866 
02867        /* Session Pool Hash Key : oci8spool***username**edition**hashedpassword**dbname**charset */
02868 
02869        smart_str_0(&spool_hashed_details);
02870        php_strtolower(spool_hashed_details.c, spool_hashed_details.len);
02871        /* }}} */
02872 
02873        if (zend_hash_find(&EG(persistent_list),spool_hashed_details.c, spool_hashed_details.len+1, (void **)&spool_out_le) == FAILURE) {
02874 
02875               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);
02876 
02877               if (session_pool == NULL) {
02878                      iserror = 1;
02879                      goto exit_get_spool;
02880               }
02881               spool_le.ptr  = session_pool;
02882               spool_le.type = le_psessionpool;
02883 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
02884               zend_list_insert(session_pool, le_psessionpool TSRMLS_CC);
02885 #else
02886               zend_list_insert(session_pool, le_psessionpool);
02887 #endif
02888               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);
02889        } else if (spool_out_le->type == le_psessionpool &&
02890               strlen(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == spool_hashed_details.len &&
02891               memcmp(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key, spool_hashed_details.c, spool_hashed_details.len) == 0) {
02892               /* retrieve the cached session pool */
02893               session_pool = (php_oci_spool *)(spool_out_le->ptr);
02894        }
02895 
02896 exit_get_spool:
02897        smart_str_free_ex(&spool_hashed_details, 0);
02898        if (iserror && session_pool) {
02899               php_oci_spool_close(session_pool TSRMLS_CC);
02900               session_pool = NULL;
02901        }
02902 
02903        return session_pool;
02904 
02905 } /* }}} */
02906 
02907 /* {{{ php_oci_create_env()
02908  *
02909  * Create the OCI environment choosing the correct function for the OCI version
02910  */
02911 static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC)
02912 {
02913        OCIEnv *retenv = NULL;
02914 
02915        /* create an environment using the character set id */
02916        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));
02917 
02918        if (OCI_G(errcode) != OCI_SUCCESS) {
02919               sb4   ora_error_code = 0;
02920               text  ora_msg_buf[OCI_ERROR_MAXMSG_SIZE];  /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
02921 
02922 #ifdef HAVE_OCI_INSTANT_CLIENT
02923               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");
02924 #else
02925               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");
02926 #endif
02927               if (retenv
02928                      && OCIErrorGet(retenv, (ub4)1, NULL, &ora_error_code, ora_msg_buf, (ub4)OCI_ERROR_MAXMSG_SIZE, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
02929                      && *ora_msg_buf) {
02930                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ora_msg_buf);
02931               }
02932               
02933               return NULL;
02934        }
02935        return retenv;
02936 }/* }}} */
02937 
02938 /* {{{ php_oci_old_create_session()
02939  *
02940  * This function is to be deprecated in future in favour of OCISessionGet which is used in
02941  * php_oci_do_connect_ex
02942  */
02943 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)
02944 {
02945        ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
02946 
02947        if (OCI_G(debug_mode)) {
02948               php_printf ("OCI8 DEBUG: Bypassing client-side session pool for session create at (%s:%d) \n", __FILE__, __LINE__);
02949        }
02950 
02951        /* Create the OCI environment separate for each connection */
02952        if (!(connection->env = php_oci_create_env(connection->charset TSRMLS_CC))) {
02953               return 1;
02954        }
02955 
02956        /* Allocate our server handle {{{ */
02957        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->server), OCI_HTYPE_SERVER, 0, NULL));
02958 
02959        if (OCI_G(errcode) != OCI_SUCCESS) {
02960               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02961               return 1;
02962        } /* }}} */
02963 
02964        /* Attach to the server {{{ */
02965        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerAttach, (connection->server, OCI_G(err), (text *)dbname, dbname_len, (ub4) OCI_DEFAULT));
02966 
02967        if (OCI_G(errcode) != OCI_SUCCESS) {
02968               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02969               return 1;
02970        } /* }}} */
02971        connection->is_attached = 1;
02972 
02973        /* Allocate our session handle {{{ */
02974        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->session), OCI_HTYPE_SESSION, 0, NULL));
02975 
02976        if (OCI_G(errcode) != OCI_SUCCESS) {
02977               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02978               return 1;
02979        } /* }}} */
02980 
02981        /* Allocate our private error-handle {{{ */
02982        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
02983 
02984        if (OCI_G(errcode) != OCI_SUCCESS) {
02985               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02986               return 1;
02987        } /* }}} */
02988 
02989        /* Allocate our service-context {{{ */
02990        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->svc), OCI_HTYPE_SVCCTX, 0, NULL));
02991 
02992        if (OCI_G(errcode) != OCI_SUCCESS) {
02993               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
02994               return 1;
02995        } /* }}} */
02996 
02997        /* Set the username {{{ */
02998        if (username) {
02999               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)));
03000 
03001               if (OCI_G(errcode) != OCI_SUCCESS) {
03002                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03003                      return 1;
03004               }
03005        }/* }}} */
03006 
03007        /* Set the password {{{ */
03008        if (password) {
03009               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)));
03010 
03011               if (OCI_G(errcode) != OCI_SUCCESS) {
03012                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03013                      return 1;
03014               }
03015        }/* }}} */
03016 
03017        /* Set the edition attribute on the session handle {{{ */
03018 #if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
03019        if (OCI_G(edition)) {
03020               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)));
03021 
03022               if (OCI_G(errcode) != OCI_SUCCESS) {
03023                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03024                      return 1;
03025               }
03026        }
03027 #endif /* }}} */
03028 
03029        /* Set the driver name attribute on the session handle {{{ */
03030 #if (OCI_MAJOR_VERSION >= 11)
03031        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)));
03032 
03033        if (OCI_G(errcode) != OCI_SUCCESS) {
03034               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03035               return 1;
03036        }
03037 #endif /* }}} */
03038 
03039        /* Set the server handle in the service handle {{{ */
03040        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->server, 0, OCI_ATTR_SERVER, OCI_G(err)));
03041 
03042        if (OCI_G(errcode) != OCI_SUCCESS) {
03043               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03044               return 1;
03045        } /* }}} */
03046 
03047        /* Set the authentication handle in the service handle {{{ */
03048        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->session, 0, OCI_ATTR_SESSION, OCI_G(err)));
03049 
03050        if (OCI_G(errcode) != OCI_SUCCESS) {
03051               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03052               return 1;
03053        } /* }}} */
03054 
03055        if (new_password) {
03056               /* Try to change password if new one was provided {{{ */
03057               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));
03058 
03059               if (OCI_G(errcode) != OCI_SUCCESS) {
03060                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03061                      return 1;
03062               }
03063 
03064               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)));
03065 
03066               if (OCI_G(errcode) != OCI_SUCCESS) {
03067                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03068                      return 1;
03069               } /* }}} */
03070        } else {
03071               /* start the session {{{ */
03072               ub4 cred_type = OCI_CRED_RDBMS;
03073 
03074               /* Extract the overloaded session_mode parameter into valid Oracle credential and session mode values */
03075               if (session_mode & PHP_OCI_CRED_EXT) {
03076                      cred_type = OCI_CRED_EXT;
03077                      session_mode ^= PHP_OCI_CRED_EXT;
03078               }
03079 
03080               session_mode |= OCI_STMT_CACHE;
03081 
03082               PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionBegin, (connection->svc, OCI_G(err), connection->session, (ub4) cred_type, (ub4) session_mode));
03083 
03084               if (OCI_G(errcode) != OCI_SUCCESS) {
03085                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03086                      /* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
03087                       * user's password has expired, but is still usable.
03088                       */
03089                      if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
03090                             return 1;
03091                      }
03092               } /* }}} */
03093        }
03094 
03095        /* Brand new connection: Init and update the next_ping in the connection */
03096        if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
03097               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03098               return 1;
03099        }
03100 
03101        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)));
03102 
03103        if (OCI_G(errcode) != OCI_SUCCESS) {
03104               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03105               return 1;
03106        }
03107 
03108        /* Successfully created session */
03109        return 0;
03110 } /* }}} */
03111 
03112 /* {{{ php_oci_create_session()
03113  *
03114  * Create session using client-side session pool - new norm
03115  */
03116 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)
03117 {
03118        php_oci_spool *actual_spool = NULL;
03119 #if (OCI_MAJOR_VERSION > 10)
03120        ub4 purity = -2;                          /* Illegal value to initialize */
03121 #endif
03122        time_t timestamp = time(NULL);
03123        ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
03124 
03125        /* Persistent connections have private session pools */
03126        if (connection->is_persistent && !connection->private_spool &&
03127               !(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, 0, connection->charset TSRMLS_CC))) {
03128                      return 1;
03129        }
03130        actual_spool = (connection->is_persistent) ? (connection->private_spool) : (session_pool);
03131 
03132        connection->env = actual_spool->env;
03133 
03134        /* Do this upfront so that connection close on an error would know that this is a session pool
03135         * connection. Failure to do this would result in crashes in error scenarios
03136         */
03137        if (!connection->using_spool) {
03138               connection->using_spool = 1;
03139        }
03140 
03141        if (OCI_G(debug_mode)) {
03142               if (session_pool) {
03143                      php_printf ("OCI8 DEBUG L1: using shared pool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
03144               } else {
03145                      php_printf ("OCI8 DEBUG L1: using private pool: (%p) at (%s:%d) \n", connection->private_spool, __FILE__, __LINE__);
03146               }
03147        }
03148 
03149        /* The passed in "connection" can be a cached stub from plist or freshly created. In the former
03150         * case, we do not have to allocate any handles
03151         */
03152 
03153        if (!connection->err) {
03154               PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
03155 
03156               if (OCI_G(errcode) != OCI_SUCCESS) {
03157                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03158                      return 1;
03159               }
03160        }
03161 
03162        /* {{{ Allocate and initialize the connection-private authinfo handle if not allocated yet */
03163        if (!connection->authinfo) {
03164               PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->authinfo), OCI_HTYPE_AUTHINFO, 0, NULL));
03165 
03166               if (OCI_G(errcode) != OCI_SUCCESS) {
03167                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03168                      return 1;
03169               }
03170 
03171               /* Set the Connection class and purity if OCI client version >= 11g */
03172 #if (OCI_MAJOR_VERSION > 10)
03173               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)));
03174 
03175               if (OCI_G(errcode) != OCI_SUCCESS) {
03176                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03177                      return 1;
03178               }
03179 
03180               if (connection->is_persistent)
03181                      purity = OCI_ATTR_PURITY_SELF;
03182               else
03183                      purity = OCI_ATTR_PURITY_NEW;
03184 
03185               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)));
03186 
03187               if (OCI_G(errcode) != OCI_SUCCESS) {
03188                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03189                      return 1;
03190               }
03191 #endif
03192        } /* }}} */
03193 
03194        /* Debug statements {{{ */
03195        if (OCI_G(debug_mode)) {
03196               ub4 numfree = 0, numbusy = 0, numopen = 0;
03197               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)));
03198               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)));
03199               numfree = numopen - numbusy;       /* number of free connections in the pool */
03200               php_printf ("OCI8 DEBUG L1: (numopen=%d)(numbusy=%d) at (%s:%d) \n", numopen, numbusy, __FILE__, __LINE__);
03201        } /* }}} */
03202 
03203               /* Ping loop: Ping and loop till we get a good connection. When a database instance goes
03204                * down, it can leave several bad connections that need to be flushed out before getting a
03205                * good one. In non-RAC, we always get a brand new connection at the end of the loop and in
03206                * RAC, we can get a good connection from a different instance before flushing out all bad
03207                * ones. We do not need to ping brand new connections.
03208                */
03209        do {
03210               /* Continue to use the global error handle as the connection is closed when an error occurs */
03211               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));
03212 
03213               if (OCI_G(errcode) != OCI_SUCCESS) {
03214                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03215 
03216                      /* Session creation returns OCI_SUCCESS_WITH_INFO when user's password has expired, but
03217                       * is still usable.
03218                       */
03219 
03220                      if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
03221                             return 1;
03222                      }
03223               }
03224 
03225               /* {{{ Populate the session and server fields of the connection */
03226               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)));
03227 
03228               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))); /* }}} */
03229 
03230               PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, OCI_G(err), (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&(connection->next_pingp)));
03231               if (OCI_G(errcode) != OCI_SUCCESS) {
03232                      php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03233                      return 1;
03234               }
03235 
03236               if (!(connection->next_pingp)){
03237                      /* This is a brand new connection, we need not ping, but have to initialize ping */
03238                      if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
03239                             php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03240                             return 1;
03241                      }
03242               } else if ((*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp))) {
03243                      if (php_oci_connection_ping(connection TSRMLS_CC)) {
03244                             /* Got a good connection - update next_ping and get out of ping loop */
03245                             *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
03246                      } else {
03247                             /* Bad connection - remove from pool */
03248                             PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) OCI_SESSRLS_DROPSESS));
03249                             connection->svc = NULL;
03250                             connection->server = NULL;
03251                             connection->session = NULL;
03252                      }
03253               }      /* If ping applicable */
03254        } while (!(connection->svc));
03255 
03256        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)));
03257 
03258        if (OCI_G(errcode) != OCI_SUCCESS) {
03259               php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
03260               return 1;
03261        }
03262 
03263        /* Session is now taken from the session pool and attached and open */
03264        connection->is_stub = 0;
03265        connection->is_attached = connection->is_open = 1;
03266 
03267        return 0;
03268 } /* }}} */
03269 
03270 /* {{{ php_oci_spool_list_dtor()
03271  *
03272  * Session pool destructor function
03273  */
03274 static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
03275 {
03276        php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
03277 
03278        if (session_pool) {
03279               php_oci_spool_close(session_pool TSRMLS_CC);
03280        }
03281 
03282        return;
03283 } /* }}} */
03284 
03285 /* {{{ php_oci_spool_close()
03286  *
03287  * Destroys the OCI Session Pool
03288  */
03289 static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC)
03290 {
03291        if (session_pool->poolname_len) {
03292               PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
03293                      (dvoid *) session_pool->err, OCI_SPD_FORCE));
03294        }
03295 
03296        if (session_pool->poolh) {
03297               PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->poolh, OCI_HTYPE_SPOOL));
03298        }
03299 
03300        if (session_pool->err) {
03301               PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->err, OCI_HTYPE_ERROR));
03302        }
03303 
03304        if (session_pool->env) {
03305               PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->env, OCI_HTYPE_ENV));
03306        }
03307 
03308        if (session_pool->spool_hash_key) {
03309               free(session_pool->spool_hash_key);
03310        }
03311 
03312        free(session_pool);
03313 } /* }}} */
03314 
03315 /* {{{ php_oci_ping_init()
03316  *
03317  * Initializes the next_ping time as a context value in the connection.       We now use
03318  * OCIContext{Get,Set}Value to store the next_ping because we need to support ping for
03319  * non-persistent DRCP connections
03320  */
03321 static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC)
03322 {
03323        time_t *next_pingp = NULL;
03324 
03325        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, errh, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&next_pingp));
03326        if (OCI_G(errcode) != OCI_SUCCESS) {
03327               return OCI_G(errcode);
03328        }
03329 
03330        /* This must be a brand-new connection. Allocate memory for the ping */
03331        if (!next_pingp) {
03332               PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIMemoryAlloc, (connection->session, errh, (void **)&next_pingp, OCI_DURATION_SESSION, sizeof(time_t), OCI_MEMORY_CLEARED));
03333               if (OCI_G(errcode) != OCI_SUCCESS) {
03334                      return OCI_G(errcode);
03335               }
03336        }
03337 
03338        if (OCI_G(ping_interval) >= 0) {
03339               time_t timestamp = time(NULL);
03340               *next_pingp = timestamp + OCI_G(ping_interval);
03341        } else {
03342               *next_pingp = 0;
03343        }
03344 
03345        /* Set the new ping value into the connection */
03346        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextSetValue, (connection->session, errh, OCI_DURATION_SESSION, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), next_pingp));
03347        if (OCI_G(errcode) != OCI_SUCCESS) {
03348               OCIMemoryFree(connection->session, errh, next_pingp);
03349               return OCI_G(errcode);
03350        }
03351 
03352        /* Cache the pointer so we do not have to do OCIContextGetValue repeatedly */
03353        connection->next_pingp = next_pingp;
03354 
03355        return OCI_SUCCESS;
03356 } /* }}} */
03357 
03358 #endif /* HAVE_OCI8 */
03359 
03360 /*
03361  * Local variables:
03362  * tab-width: 4
03363  * c-basic-offset: 4
03364  * End:
03365  * vim600: noet sw=4 ts=4 fdm=marker
03366  * vim<600: noet sw=4 ts=4
03367  */