PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/oci8 - oci8.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 794 981 80.9 %
Date: 2014-07-21 Functions: 46 46 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:13 +0000 (10 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.