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: 805 995 80.9 %
Date: 2016-02-05 Functions: 46 46 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Fri, 05 Feb 2016 08:39:18 +0000 (2 days ago)

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