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

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:01 +0000 (4 days ago)

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