php-src/ext/oci8/oci8.c
Christopher Jones 2769ae0444 1. Introduce connection attribute functions:
oci_set_module_name
         oci_set_action
         oci_set_client_info
         oci_set_client_identifier
      
       These functions set values that are visible and used by the
       database.  They aid tracing, authentication and auditing.

    2. Introduce connection attribute function:

         oci_set_edition

       Oracle 11g R2 "editions" allow multiple versions of DB objects
       to exist at one time.  By setting different editions, two
       different versions of an application can run concurrently,
       making upgrades or A/B testing easier.

    3. Introduce OCI_NO_AUTO_COMMIT as an alias for the OCI_DEFAULT
       constant (which is not the default value) used by oci_execute().

    4. Allow the oci_set_prefetch value to be 0.  This is important in
       some cases using REF CURSORS in Oracle 11gR2.

    5. Set the DRIVER_NAME attribute of Oracle Database 11gR2
       connections to aid application tracing.  The value used is to
       "PHP OCI8" followed by the OCI8 version number.  Note the
       version number may get truncated in DB views such as
       v$session_connect_info.

    6. Generate an error if an invalid resource type is used in
       oci_bind_by_name

[DOC] Documentation will be added for the changes
2009-10-06 22:36:32 +00:00

3258 lines
116 KiB
C

/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Stig Sæther Bakken <ssb@php.net> |
| Thies C. Arntzen <thies@thieso.net> |
| Maxim Maletsky <maxim@maxim.cx> |
| |
| Collection support by Andy Sautins <asautins@veripost.net> |
| Temporary LOB support by David Benson <dbenson@mancala.com> |
| ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
| |
| Redesigned by: Antony Dovgal <antony@zend.com> |
| Andi Gutmans <andi@zend.com> |
| Wez Furlong <wez@omniti.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_ini.h"
#include "ext/standard/php_smart_str.h"
#if HAVE_OCI8
#if PHP_MAJOR_VERSION > 5
#error This version of the PHP OCI8 extension is not compatible with PHP 6 or later
#elif PHP_MAJOR_VERSION < 5
#ifdef ZTS
#error The PHP OCI8 extension does not support ZTS mode in PHP 4
#endif
#endif
#include "php_oci8.h"
#include "php_oci8_int.h"
#include "zend_hash.h"
ZEND_DECLARE_MODULE_GLOBALS(oci)
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
/* This "if" allows PECL builds from this file to be portable to older PHP releases */
static PHP_GINIT_FUNCTION(oci);
static PHP_GSHUTDOWN_FUNCTION(oci);
#endif
/* Allow PHP 5.3 branch to be used in PECL for 5.x compatible builds */
#ifndef Z_ADDREF_P
#define Z_ADDREF_P(x) ZVAL_ADDREF(x)
#endif
/* For a user friendly message about environment setup */
/* TODO: add cases for SHLIB_PATH, LIBPATH, LD_LIBRARY_PATH_64 etc */
#if defined(PHP_WIN32)
#define PHP_OCI8_LIB_PATH_MSG "PATH"
#elif defined(__APPLE__)
#define PHP_OCI8_LIB_PATH_MSG "DYLD_LIBRARY_PATH"
#else
#define PHP_OCI8_LIB_PATH_MSG "LD_LIBRARY_PATH"
#endif
/* True globals, no need for thread safety */
int le_connection;
int le_pconnection;
int le_statement;
int le_descriptor;
int le_psessionpool;
int le_collection;
zend_class_entry *oci_lob_class_entry_ptr;
zend_class_entry *oci_coll_class_entry_ptr;
#ifndef SQLT_BFILEE
#define SQLT_BFILEE 114
#endif
#ifndef SQLT_CFILEE
#define SQLT_CFILEE 115
#endif
#define PHP_OCI_ERRBUF_LEN 512
#if ZEND_MODULE_API_NO > 20020429
#define ONUPDATELONGFUNC OnUpdateLong
#else
#define ONUPDATELONGFUNC OnUpdateInt
#endif
#ifdef ZTS
#define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX)
#else
#define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT)
#endif
/* static protos {{{ */
static void php_oci_connection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static void php_oci_pconnection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static void php_oci_pconnection_list_np_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static void php_oci_statement_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static void php_oci_descriptor_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC);
static void php_oci_collection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC);
static int php_oci_connection_ping(php_oci_connection * TSRMLS_DC);
static int php_oci_connection_status(php_oci_connection * TSRMLS_DC);
static int php_oci_connection_close(php_oci_connection * TSRMLS_DC);
static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC);
static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC);
static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC);
static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC);
static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC);
static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC);
static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC);
/* }}} */
/* {{{ dynamically loadable module stuff */
#if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G)
ZEND_GET_MODULE(oci8)
#endif /* COMPILE_DL */
/* }}} */
#ifdef ZEND_ENGINE_2
/* {{{ Function arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_define_by_name, 0, 0, 3)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_name)
ZEND_ARG_INFO(1, variable)
ZEND_ARG_INFO(0, type)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_by_name, 0, 0, 3)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_name)
ZEND_ARG_INFO(1, variable)
ZEND_ARG_INFO(0, maximum_length)
ZEND_ARG_INFO(0, type)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_array_by_name, 0, 0, 4)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_name)
ZEND_ARG_INFO(1, variable)
ZEND_ARG_INFO(0, maximum_array_length)
ZEND_ARG_INFO(0, maximum_item_length)
ZEND_ARG_INFO(0, type)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_descriptor, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, data)
ZEND_ARG_INFO(0, offset)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, filename)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_load, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_eof, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_tell, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_rewind, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, offset)
ZEND_ARG_INFO(0, whence)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_size, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, string)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor_to)
ZEND_ARG_INFO(0, lob_descriptor_from)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, offset)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, flag)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_ocisetbufferinglob, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_ocigetbufferinglob, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_copy, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor_to)
ZEND_ARG_INFO(0, lob_descriptor_from)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_is_equal, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export, 0, 0, 2)
ZEND_ARG_INFO(0, lob_descriptor)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, start)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_descriptor, 0, 0, 1)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, type)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_rollback, 0, 0, 1)
ZEND_ARG_INFO(0, connection_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_commit, 0, 0, 1)
ZEND_ARG_INFO(0, connection_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_name, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_number)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_size, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_number_or_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_scale, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_number)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_precision, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_number)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_number)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type_raw, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_number)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_is_null, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_number_or_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_internal_debug, 0, 0, 1)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_execute, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_cancel, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_ocifetchinto, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(1, result)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_all, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(1, output)
ZEND_ARG_INFO(0, skip)
ZEND_ARG_INFO(0, maximum_rows)
ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_object, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_row, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_assoc, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_array, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_statement, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_close, 0, 0, 1)
ZEND_ARG_INFO(0, connection_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_connect, 0, 0, 2)
ZEND_ARG_INFO(0, username)
ZEND_ARG_INFO(0, password)
ZEND_ARG_INFO(0, connection_string)
ZEND_ARG_INFO(0, character_set)
ZEND_ARG_INFO(0, session_mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_connect, 0, 0, 2)
ZEND_ARG_INFO(0, username)
ZEND_ARG_INFO(0, password)
ZEND_ARG_INFO(0, connection_string)
ZEND_ARG_INFO(0, character_set)
ZEND_ARG_INFO(0, session_mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_pconnect, 0, 0, 2)
ZEND_ARG_INFO(0, username)
ZEND_ARG_INFO(0, password)
ZEND_ARG_INFO(0, connection_string)
ZEND_ARG_INFO(0, character_set)
ZEND_ARG_INFO(0, session_mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_error, 0, 0, 0)
ZEND_ARG_INFO(0, connection_or_statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_fields, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_parse, 0, 0, 2)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, sql_text)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_prefetch, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, number_of_rows)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_identifier, 0, 0, 2)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, client_identifier)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_edition, 0, 0, 1)
ZEND_ARG_INFO(0, edition_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_module_name, 0, 0, 2)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, module_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_action, 0, 0, 2)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, action)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_info, 0, 0, 2)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, client_information)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_password_change, 0, 0, 4)
ZEND_ARG_INFO(0, connection_resource_or_connection_string)
ZEND_ARG_INFO(0, username)
ZEND_ARG_INFO(0, old_password)
ZEND_ARG_INFO(0, new_password)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_cursor, 0, 0, 1)
ZEND_ARG_INFO(0, connection_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_result, 0, 0, 2)
ZEND_ARG_INFO(0, statement_resource)
ZEND_ARG_INFO(0, column_number_or_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_server_version, 0, 0, 1)
ZEND_ARG_INFO(0, connection_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_statement_type, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_rows, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_collection, 0, 0, 1)
ZEND_ARG_INFO(0, collection)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append, 0, 0, 2)
ZEND_ARG_INFO(0, collection)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get, 0, 0, 2)
ZEND_ARG_INFO(0, collection)
ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign, 0, 0, 2)
ZEND_ARG_INFO(0, collection_to)
ZEND_ARG_INFO(0, collection_from)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign, 0, 0, 3)
ZEND_ARG_INFO(0, collection)
ZEND_ARG_INFO(0, index)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_size, 0, 0, 1)
ZEND_ARG_INFO(0, collection)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_max, 0, 0, 1)
ZEND_ARG_INFO(0, collection)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim, 0, 0, 2)
ZEND_ARG_INFO(0, collection)
ZEND_ARG_INFO(0, number)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_collection, 0, 0, 2)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, type_name)
ZEND_ARG_INFO(0, schema_name)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ LOB Method arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save_method, 0, 0, 1)
ZEND_ARG_INFO(0, data)
ZEND_ARG_INFO(0, offset)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import_method, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_load_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read_method, 0, 0, 1)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_eof_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_tell_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_rewind_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek_method, 0, 0, 1)
ZEND_ARG_INFO(0, offset)
ZEND_ARG_INFO(0, whence)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_size_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_method, 0, 0, 1)
ZEND_ARG_INFO(0, string)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append_method, 0, 0, 1)
ZEND_ARG_INFO(0, lob_descriptor_from)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate_method, 0, 0, 0)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase_method, 0, 0, 0)
ZEND_ARG_INFO(0, offset)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush_method, 0, 0, 0)
ZEND_ARG_INFO(0, flag)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_setbuffering_method, 0, 0, 1)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_getbuffering_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export_method, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, start)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_temporary_method, 0, 0, 1)
ZEND_ARG_INFO(0, data)
ZEND_ARG_INFO(0, type)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_close_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_free_descriptor_method, 0)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ Collection Method arginfo */
ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_free_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append_method, 0, 0, 1)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get_method, 0, 0, 1)
ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign_method, 0, 0, 1)
ZEND_ARG_INFO(0, collection_from)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign_method, 0, 0, 2)
ZEND_ARG_INFO(0, index)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_size_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_max_method, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim_method, 0, 0, 1)
ZEND_ARG_INFO(0, number)
ZEND_END_ARG_INFO()
/* }}} */
#else /* ZEND_ENGINE_2 */
/* {{{ Keep the old arginfo behavior when building with PHP 4 */
static unsigned char arginfo_ocifetchinto[] = { 2, BYREF_NONE, BYREF_FORCE };
static unsigned char arginfo_oci_fetch_all[] = { 2, BYREF_NONE, BYREF_FORCE };
static unsigned char arginfo_oci_define_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
static unsigned char arginfo_oci_bind_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
static unsigned char arginfo_oci_bind_array_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
#define arginfo_oci_free_descriptor NULL
#define arginfo_oci_lob_save NULL
#define arginfo_oci_lob_import NULL
#define arginfo_oci_lob_load NULL
#define arginfo_oci_lob_read NULL
#define arginfo_oci_lob_eof NULL
#define arginfo_oci_lob_tell NULL
#define arginfo_oci_lob_rewind NULL
#define arginfo_oci_lob_seek NULL
#define arginfo_oci_lob_size NULL
#define arginfo_oci_lob_write NULL
#define arginfo_oci_lob_append NULL
#define arginfo_oci_lob_truncate NULL
#define arginfo_oci_lob_erase NULL
#define arginfo_oci_lob_flush NULL
#define arginfo_ocisetbufferinglob NULL
#define arginfo_ocigetbufferinglob NULL
#define arginfo_oci_lob_copy NULL
#define arginfo_oci_lob_is_equal NULL
#define arginfo_oci_lob_export NULL
#define arginfo_oci_new_descriptor NULL
#define arginfo_oci_rollback NULL
#define arginfo_oci_commit NULL
#define arginfo_oci_field_name NULL
#define arginfo_oci_field_size NULL
#define arginfo_oci_field_scale NULL
#define arginfo_oci_field_precision NULL
#define arginfo_oci_field_type NULL
#define arginfo_oci_field_type_raw NULL
#define arginfo_oci_field_is_null NULL
#define arginfo_oci_internal_debug NULL
#define arginfo_oci_execute NULL
#define arginfo_oci_cancel NULL
#define arginfo_oci_fetch NULL
#define arginfo_oci_fetch_object NULL
#define arginfo_oci_fetch_row NULL
#define arginfo_oci_fetch_assoc NULL
#define arginfo_oci_fetch_array NULL
#define arginfo_oci_free_statement NULL
#define arginfo_oci_close NULL
#define arginfo_oci_new_connect NULL
#define arginfo_oci_connect NULL
#define arginfo_oci_pconnect NULL
#define arginfo_oci_error NULL
#define arginfo_oci_num_fields NULL
#define arginfo_oci_parse NULL
#define arginfo_oci_set_prefetch NULL
#define arginfo_oci_set_client_identifier NULL
#define arginfo_oci_set_edition NULL
#define arginfo_oci_set_module_name NULL
#define arginfo_oci_set_action NULL
#define arginfo_oci_set_client_info NULL
#define arginfo_oci_password_change NULL
#define arginfo_oci_new_cursor NULL
#define arginfo_oci_result NULL
#define arginfo_oci_server_version NULL
#define arginfo_oci_statement_type NULL
#define arginfo_oci_num_rows NULL
#define arginfo_oci_free_collection NULL
#define arginfo_oci_collection_append NULL
#define arginfo_oci_collection_element_get NULL
#define arginfo_oci_collection_assign NULL
#define arginfo_oci_collection_element_assign NULL
#define arginfo_oci_collection_size NULL
#define arginfo_oci_collection_max NULL
#define arginfo_oci_collection_trim NULL
#define arginfo_oci_new_collection NULL
#define arginfo_oci_lob_size_method NULL
#define arginfo_oci_lob_getbuffering_method NULL
#define arginfo_oci_lob_close_method NULL
#define arginfo_oci_lob_save_method NULL
#define arginfo_oci_lob_import_method NULL
#define arginfo_oci_lob_read_method NULL
#define arginfo_oci_lob_seek_method NULL
#define arginfo_oci_lob_write_method NULL
#define arginfo_oci_lob_append_method NULL
#define arginfo_oci_lob_truncate_method NULL
#define arginfo_oci_lob_erase_method NULL
#define arginfo_oci_lob_flush_method NULL
#define arginfo_oci_lob_setbuffering_method NULL
#define arginfo_oci_lob_export_method NULL
#define arginfo_oci_lob_write_temporary_method NULL
#define arginfo_oci_lob_load_method NULL
#define arginfo_oci_lob_tell_method NULL
#define arginfo_oci_lob_rewind_method NULL
#define arginfo_oci_lob_eof_method NULL
#define arginfo_oci_free_descriptor_method NULL
#define arginfo_oci_collection_append_method NULL
#define arginfo_oci_collection_element_get_method NULL
#define arginfo_oci_collection_assign_method NULL
#define arginfo_oci_collection_size_method NULL
#define arginfo_oci_collection_element_assign_method NULL
#define arginfo_oci_collection_max_method NULL
#define arginfo_oci_collection_trim_method NULL
#define arginfo_oci_collection_free_method NULL
/* }}} */
#endif /* ZEND_ENGINE_2 */
/* {{{ extension function prototypes
*/
PHP_FUNCTION(oci_bind_by_name);
PHP_FUNCTION(oci_bind_array_by_name);
PHP_FUNCTION(oci_define_by_name);
PHP_FUNCTION(oci_field_is_null);
PHP_FUNCTION(oci_field_name);
PHP_FUNCTION(oci_field_size);
PHP_FUNCTION(oci_field_scale);
PHP_FUNCTION(oci_field_precision);
PHP_FUNCTION(oci_field_type);
PHP_FUNCTION(oci_field_type_raw);
PHP_FUNCTION(oci_execute);
PHP_FUNCTION(oci_fetch);
PHP_FUNCTION(oci_cancel);
PHP_FUNCTION(ocifetchinto);
PHP_FUNCTION(oci_fetch_object);
PHP_FUNCTION(oci_fetch_row);
PHP_FUNCTION(oci_fetch_assoc);
PHP_FUNCTION(oci_fetch_array);
PHP_FUNCTION(ocifetchstatement);
PHP_FUNCTION(oci_fetch_all);
PHP_FUNCTION(oci_free_statement);
PHP_FUNCTION(oci_internal_debug);
PHP_FUNCTION(oci_close);
PHP_FUNCTION(oci_connect);
PHP_FUNCTION(oci_new_connect);
PHP_FUNCTION(oci_pconnect);
PHP_FUNCTION(oci_error);
PHP_FUNCTION(oci_free_descriptor);
PHP_FUNCTION(oci_commit);
PHP_FUNCTION(oci_rollback);
PHP_FUNCTION(oci_new_descriptor);
PHP_FUNCTION(oci_num_fields);
PHP_FUNCTION(oci_parse);
PHP_FUNCTION(oci_new_cursor);
PHP_FUNCTION(oci_result);
PHP_FUNCTION(oci_server_version);
PHP_FUNCTION(oci_statement_type);
PHP_FUNCTION(oci_num_rows);
PHP_FUNCTION(oci_set_prefetch);
PHP_FUNCTION(oci_set_client_identifier);
PHP_FUNCTION(oci_set_edition);
PHP_FUNCTION(oci_set_module_name);
PHP_FUNCTION(oci_set_action);
PHP_FUNCTION(oci_set_client_info);
PHP_FUNCTION(oci_password_change);
PHP_FUNCTION(oci_lob_save);
PHP_FUNCTION(oci_lob_import);
PHP_FUNCTION(oci_lob_export);
PHP_FUNCTION(oci_lob_load);
PHP_FUNCTION(oci_lob_tell);
PHP_FUNCTION(oci_lob_write);
PHP_FUNCTION(oci_lob_append);
PHP_FUNCTION(oci_lob_copy);
PHP_FUNCTION(oci_lob_truncate);
PHP_FUNCTION(oci_lob_erase);
PHP_FUNCTION(oci_lob_flush);
PHP_FUNCTION(ocisetbufferinglob);
PHP_FUNCTION(ocigetbufferinglob);
PHP_FUNCTION(oci_lob_is_equal);
PHP_FUNCTION(oci_lob_rewind);
PHP_FUNCTION(oci_lob_read);
PHP_FUNCTION(oci_lob_eof);
PHP_FUNCTION(oci_lob_seek);
PHP_FUNCTION(oci_lob_size);
PHP_FUNCTION(oci_lob_write_temporary);
PHP_FUNCTION(oci_lob_close);
PHP_FUNCTION(oci_new_collection);
PHP_FUNCTION(oci_free_collection);
PHP_FUNCTION(oci_collection_append);
PHP_FUNCTION(oci_collection_element_get);
PHP_FUNCTION(oci_collection_element_assign);
PHP_FUNCTION(oci_collection_assign);
PHP_FUNCTION(oci_collection_size);
PHP_FUNCTION(oci_collection_max);
PHP_FUNCTION(oci_collection_trim);
/* }}} */
/* {{{ extension definition structures
*/
static
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
/* This "if" allows PECL builds from this file to be portable to older PHP releases */
const
#endif
zend_function_entry php_oci_functions[] = {
PHP_FE(oci_define_by_name, arginfo_oci_define_by_name)
PHP_FE(oci_bind_by_name, arginfo_oci_bind_by_name)
PHP_FE(oci_bind_array_by_name, arginfo_oci_bind_array_by_name)
PHP_FE(oci_field_is_null, arginfo_oci_field_is_null)
PHP_FE(oci_field_name, arginfo_oci_field_name)
PHP_FE(oci_field_size, arginfo_oci_field_size)
PHP_FE(oci_field_scale, arginfo_oci_field_scale)
PHP_FE(oci_field_precision, arginfo_oci_field_precision)
PHP_FE(oci_field_type, arginfo_oci_field_type)
PHP_FE(oci_field_type_raw, arginfo_oci_field_type_raw)
PHP_FE(oci_execute, arginfo_oci_execute)
PHP_FE(oci_cancel, arginfo_oci_cancel)
PHP_FE(oci_fetch, arginfo_oci_fetch)
PHP_FE(oci_fetch_object, arginfo_oci_fetch_object)
PHP_FE(oci_fetch_row, arginfo_oci_fetch_row)
PHP_FE(oci_fetch_assoc, arginfo_oci_fetch_assoc)
PHP_FE(oci_fetch_array, arginfo_oci_fetch_array)
PHP_FE(ocifetchinto, arginfo_ocifetchinto)
PHP_FE(oci_fetch_all, arginfo_oci_fetch_all)
PHP_FE(oci_free_statement, arginfo_oci_free_statement)
PHP_FE(oci_internal_debug, arginfo_oci_internal_debug)
PHP_FE(oci_num_fields, arginfo_oci_num_fields)
PHP_FE(oci_parse, arginfo_oci_parse)
PHP_FE(oci_new_cursor, arginfo_oci_new_cursor)
PHP_FE(oci_result, arginfo_oci_result)
PHP_FE(oci_server_version, arginfo_oci_server_version)
PHP_FE(oci_statement_type, arginfo_oci_statement_type)
PHP_FE(oci_num_rows, arginfo_oci_num_rows)
PHP_FE(oci_close, arginfo_oci_close)
PHP_FE(oci_connect, arginfo_oci_connect)
PHP_FE(oci_new_connect, arginfo_oci_new_connect)
PHP_FE(oci_pconnect, arginfo_oci_pconnect)
PHP_FE(oci_error, arginfo_oci_error)
PHP_FE(oci_free_descriptor, arginfo_oci_free_descriptor)
PHP_FE(oci_lob_save, arginfo_oci_lob_save)
PHP_FE(oci_lob_import, arginfo_oci_lob_import)
PHP_FE(oci_lob_size, arginfo_oci_lob_size)
PHP_FE(oci_lob_load, arginfo_oci_lob_load)
PHP_FE(oci_lob_read, arginfo_oci_lob_read)
PHP_FE(oci_lob_eof, arginfo_oci_lob_eof)
PHP_FE(oci_lob_tell, arginfo_oci_lob_tell)
PHP_FE(oci_lob_truncate, arginfo_oci_lob_truncate)
PHP_FE(oci_lob_erase, arginfo_oci_lob_erase)
PHP_FE(oci_lob_flush, arginfo_oci_lob_flush)
PHP_FE(ocisetbufferinglob, arginfo_ocisetbufferinglob)
PHP_FE(ocigetbufferinglob, arginfo_ocigetbufferinglob)
PHP_FE(oci_lob_is_equal, arginfo_oci_lob_is_equal)
PHP_FE(oci_lob_rewind, arginfo_oci_lob_rewind)
PHP_FE(oci_lob_write, arginfo_oci_lob_write)
PHP_FE(oci_lob_append, arginfo_oci_lob_append)
PHP_FE(oci_lob_copy, arginfo_oci_lob_copy)
PHP_FE(oci_lob_export, arginfo_oci_lob_export)
PHP_FE(oci_lob_seek, arginfo_oci_lob_seek)
PHP_FE(oci_commit, arginfo_oci_commit)
PHP_FE(oci_rollback, arginfo_oci_rollback)
PHP_FE(oci_new_descriptor, arginfo_oci_new_descriptor)
PHP_FE(oci_set_prefetch, arginfo_oci_set_prefetch)
PHP_FE(oci_set_client_identifier, arginfo_oci_set_client_identifier)
PHP_FE(oci_set_edition, arginfo_oci_set_edition)
PHP_FE(oci_set_module_name, arginfo_oci_set_module_name)
PHP_FE(oci_set_action, arginfo_oci_set_action)
PHP_FE(oci_set_client_info, arginfo_oci_set_client_info)
PHP_FE(oci_password_change, arginfo_oci_password_change)
PHP_FE(oci_free_collection, arginfo_oci_free_collection)
PHP_FE(oci_collection_append, arginfo_oci_collection_append)
PHP_FE(oci_collection_element_get, arginfo_oci_collection_element_get)
PHP_FE(oci_collection_element_assign, arginfo_oci_collection_element_assign)
PHP_FE(oci_collection_assign, arginfo_oci_collection_assign)
PHP_FE(oci_collection_size, arginfo_oci_collection_size)
PHP_FE(oci_collection_max, arginfo_oci_collection_max)
PHP_FE(oci_collection_trim, arginfo_oci_collection_trim)
PHP_FE(oci_new_collection, arginfo_oci_new_collection)
PHP_FALIAS(oci_free_cursor, oci_free_statement, arginfo_oci_free_statement)
PHP_FALIAS(ocifreecursor, oci_free_statement, arginfo_oci_free_statement)
PHP_FALIAS(ocibindbyname, oci_bind_by_name, arginfo_oci_bind_by_name)
PHP_FALIAS(ocidefinebyname, oci_define_by_name, arginfo_oci_define_by_name)
PHP_FALIAS(ocicolumnisnull, oci_field_is_null, arginfo_oci_field_is_null)
PHP_FALIAS(ocicolumnname, oci_field_name, arginfo_oci_field_name)
PHP_FALIAS(ocicolumnsize, oci_field_size, arginfo_oci_field_size)
PHP_FALIAS(ocicolumnscale, oci_field_scale, arginfo_oci_field_scale)
PHP_FALIAS(ocicolumnprecision, oci_field_precision, arginfo_oci_field_precision)
PHP_FALIAS(ocicolumntype, oci_field_type, arginfo_oci_field_type)
PHP_FALIAS(ocicolumntyperaw, oci_field_type_raw, arginfo_oci_field_type_raw)
PHP_FALIAS(ociexecute, oci_execute, arginfo_oci_execute)
PHP_FALIAS(ocicancel, oci_cancel, arginfo_oci_cancel)
PHP_FALIAS(ocifetch, oci_fetch, arginfo_oci_fetch)
PHP_FALIAS(ocifetchstatement, oci_fetch_all, arginfo_oci_fetch_all)
PHP_FALIAS(ocifreestatement, oci_free_statement, arginfo_oci_free_statement)
PHP_FALIAS(ociinternaldebug, oci_internal_debug, arginfo_oci_internal_debug)
PHP_FALIAS(ocinumcols, oci_num_fields, arginfo_oci_num_fields)
PHP_FALIAS(ociparse, oci_parse, arginfo_oci_parse)
PHP_FALIAS(ocinewcursor, oci_new_cursor, arginfo_oci_new_cursor)
PHP_FALIAS(ociresult, oci_result, arginfo_oci_result)
PHP_FALIAS(ociserverversion, oci_server_version, arginfo_oci_server_version)
PHP_FALIAS(ocistatementtype, oci_statement_type, arginfo_oci_statement_type)
PHP_FALIAS(ocirowcount, oci_num_rows, arginfo_oci_num_rows)
PHP_FALIAS(ocilogoff, oci_close, arginfo_oci_close)
PHP_FALIAS(ocilogon, oci_connect, arginfo_oci_connect)
PHP_FALIAS(ocinlogon, oci_new_connect, arginfo_oci_new_connect)
PHP_FALIAS(ociplogon, oci_pconnect, arginfo_oci_pconnect)
PHP_FALIAS(ocierror, oci_error, arginfo_oci_error)
PHP_FALIAS(ocifreedesc, oci_free_descriptor, arginfo_oci_free_descriptor)
PHP_FALIAS(ocisavelob, oci_lob_save, arginfo_oci_lob_save)
PHP_FALIAS(ocisavelobfile, oci_lob_import, arginfo_oci_lob_import)
PHP_FALIAS(ociwritelobtofile, oci_lob_export, arginfo_oci_lob_export)
PHP_FALIAS(ociloadlob, oci_lob_load, arginfo_oci_lob_load)
PHP_FALIAS(ocicommit, oci_commit, arginfo_oci_commit)
PHP_FALIAS(ocirollback, oci_rollback, arginfo_oci_rollback)
PHP_FALIAS(ocinewdescriptor, oci_new_descriptor, arginfo_oci_new_descriptor)
PHP_FALIAS(ocisetprefetch, oci_set_prefetch, arginfo_oci_set_prefetch)
PHP_FALIAS(ocipasswordchange, oci_password_change, arginfo_oci_password_change)
PHP_FALIAS(ocifreecollection, oci_free_collection, arginfo_oci_free_collection)
PHP_FALIAS(ocinewcollection, oci_new_collection, arginfo_oci_new_collection)
PHP_FALIAS(ocicollappend, oci_collection_append, arginfo_oci_collection_append)
PHP_FALIAS(ocicollgetelem, oci_collection_element_get, arginfo_oci_collection_element_get)
PHP_FALIAS(ocicollassignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign)
PHP_FALIAS(ocicollsize, oci_collection_size, arginfo_oci_collection_size)
PHP_FALIAS(ocicollmax, oci_collection_max, arginfo_oci_collection_max)
PHP_FALIAS(ocicolltrim, oci_collection_trim, arginfo_oci_collection_trim)
{NULL,NULL,NULL}
};
static
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
/* This "if" allows PECL builds from this file to be portable to older PHP releases */
const
#endif
zend_function_entry php_oci_lob_class_functions[] = {
PHP_FALIAS(load, oci_lob_load, arginfo_oci_lob_load_method)
PHP_FALIAS(tell, oci_lob_tell, arginfo_oci_lob_tell_method)
PHP_FALIAS(truncate, oci_lob_truncate, arginfo_oci_lob_truncate_method)
PHP_FALIAS(erase, oci_lob_erase, arginfo_oci_lob_erase_method)
PHP_FALIAS(flush, oci_lob_flush, arginfo_oci_lob_flush_method)
PHP_FALIAS(setbuffering,ocisetbufferinglob, arginfo_oci_lob_setbuffering_method)
PHP_FALIAS(getbuffering,ocigetbufferinglob, arginfo_oci_lob_getbuffering_method)
PHP_FALIAS(rewind, oci_lob_rewind, arginfo_oci_lob_rewind_method)
PHP_FALIAS(read, oci_lob_read, arginfo_oci_lob_read_method)
PHP_FALIAS(eof, oci_lob_eof, arginfo_oci_lob_eof_method)
PHP_FALIAS(seek, oci_lob_seek, arginfo_oci_lob_seek_method)
PHP_FALIAS(write, oci_lob_write, arginfo_oci_lob_write_method)
PHP_FALIAS(append, oci_lob_append, arginfo_oci_lob_append_method)
PHP_FALIAS(size, oci_lob_size, arginfo_oci_lob_size_method)
PHP_FALIAS(writetofile, oci_lob_export, arginfo_oci_lob_export_method)
PHP_FALIAS(export, oci_lob_export, arginfo_oci_lob_export_method)
PHP_FALIAS(import, oci_lob_import, arginfo_oci_lob_import_method)
PHP_FALIAS(writetemporary, oci_lob_write_temporary, arginfo_oci_lob_write_temporary_method)
PHP_FALIAS(close, oci_lob_close, arginfo_oci_lob_close_method)
PHP_FALIAS(save, oci_lob_save, arginfo_oci_lob_save_method)
PHP_FALIAS(savefile, oci_lob_import, arginfo_oci_lob_import_method)
PHP_FALIAS(free, oci_free_descriptor, arginfo_oci_free_descriptor_method)
{NULL,NULL,NULL}
};
static
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
/* This "if" allows PECL builds from this file to be portable to older PHP releases */
const
#endif
zend_function_entry php_oci_coll_class_functions[] = {
PHP_FALIAS(append, oci_collection_append, arginfo_oci_collection_append_method)
PHP_FALIAS(getelem, oci_collection_element_get, arginfo_oci_collection_element_get_method)
PHP_FALIAS(assignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign_method)
PHP_FALIAS(assign, oci_collection_assign, arginfo_oci_collection_assign_method)
PHP_FALIAS(size, oci_collection_size, arginfo_oci_collection_size_method)
PHP_FALIAS(max, oci_collection_max, arginfo_oci_collection_max_method)
PHP_FALIAS(trim, oci_collection_trim, arginfo_oci_collection_trim_method)
PHP_FALIAS(free, oci_free_collection, arginfo_oci_collection_free_method)
{NULL,NULL,NULL}
};
zend_module_entry oci8_module_entry = {
STANDARD_MODULE_HEADER,
"oci8", /* extension name */
php_oci_functions, /* extension function list */
PHP_MINIT(oci), /* extension-wide startup function */
PHP_MSHUTDOWN(oci), /* extension-wide shutdown function */
PHP_RINIT(oci), /* per-request startup function */
PHP_RSHUTDOWN(oci), /* per-request shutdown function */
PHP_MINFO(oci), /* information function */
PHP_OCI8_VERSION,
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
/* This check allows PECL builds from this file to be portable to older PHP releases */
PHP_MODULE_GLOBALS(oci), /* globals descriptor */
PHP_GINIT(oci), /* globals ctor */
PHP_GSHUTDOWN(oci), /* globals dtor */
NULL, /* post deactivate */
STANDARD_MODULE_PROPERTIES_EX
#else
STANDARD_MODULE_PROPERTIES
#endif
};
/* }}} */
/* {{{ PHP_INI */
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY( "oci8.max_persistent", "-1", PHP_INI_SYSTEM, ONUPDATELONGFUNC, max_persistent, zend_oci_globals, oci_globals)
STD_PHP_INI_ENTRY( "oci8.persistent_timeout", "-1", PHP_INI_SYSTEM, ONUPDATELONGFUNC, persistent_timeout, zend_oci_globals, oci_globals)
STD_PHP_INI_ENTRY( "oci8.ping_interval", "60", PHP_INI_SYSTEM, ONUPDATELONGFUNC, ping_interval, zend_oci_globals, oci_globals)
STD_PHP_INI_BOOLEAN("oci8.privileged_connect", "0", PHP_INI_SYSTEM, OnUpdateBool, privileged_connect, zend_oci_globals, oci_globals)
STD_PHP_INI_ENTRY( "oci8.statement_cache_size", "20", PHP_INI_SYSTEM, ONUPDATELONGFUNC, statement_cache_size, zend_oci_globals, oci_globals)
STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, ONUPDATELONGFUNC, default_prefetch, zend_oci_globals, oci_globals)
STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics", "0", PHP_INI_SYSTEM, OnUpdateBool, old_oci_close_semantics,zend_oci_globals, oci_globals)
STD_PHP_INI_ENTRY( "oci8.connection_class", "", PHP_INI_ALL, OnUpdateString, connection_class, zend_oci_globals, oci_globals)
STD_PHP_INI_BOOLEAN("oci8.events", "0", PHP_INI_SYSTEM, OnUpdateBool, events, zend_oci_globals, oci_globals)
PHP_INI_END()
/* }}} */
/* {{{ startup, shutdown and info functions
*/
/* {{{ php_oci_init_global_handles()
*
* Initialize global handles only when they are needed
*/
static void php_oci_init_global_handles(TSRMLS_D)
{
sword errstatus;
sb4 ora_error_code = 0;
text tmp_buf[PHP_OCI_ERRBUF_LEN];
errstatus = OCIEnvNlsCreate(&OCI_G(env), PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
if (errstatus == OCI_ERROR) {
#ifdef HAVE_OCI_INSTANT_CLIENT
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
#else
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
#endif
OCI_G(env) = NULL;
OCI_G(err) = NULL;
return;
}
errstatus = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
if (errstatus == OCI_SUCCESS) {
#if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11)
/* This fixes PECL bug 15988 (sqlnet.ora not being read). The
* root cause was fixed in Oracle 10.2.0.4 but there is no
* compile time method to check for that precise patch level,
* nor can it be guaranteed that runtime will use the same
* patch level the code was compiled with. So, we do this
* code for all non 11g versions.
*/
OCICPool *cpoolh;
ub4 cpoolmode = 0x80000000; /* Pass invalid mode to OCIConnectionPoolCreate */
PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
#endif
} else {
OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
if (ora_error_code) {
int tmp_buf_len = strlen((char *)tmp_buf);
if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
tmp_buf[tmp_buf_len - 1] = '\0';
}
if (errstatus == OCI_SUCCESS_WITH_INFO) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_ERROR: %s", tmp_buf);
OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
OCI_G(env) = NULL;
OCI_G(err) = NULL;
}
}
}
} /* }}} */
/* {{{ php_oci_cleanup_global_handles()
*
* Free global handles (if they were initialized before)
*/
static void php_oci_cleanup_global_handles(TSRMLS_D)
{
if (OCI_G(err)) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ERROR));
OCI_G(err) = NULL;
}
if (OCI_G(env)) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV));
OCI_G(env) = NULL;
}
} /* }}} */
/* {{{ PHP_GINIT_FUNCTION
*
* Zerofill globals during module init
*/
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
/* This check allows PECL builds from this file to be portable to older PHP releases */
static PHP_GINIT_FUNCTION(oci)
#else
static void php_oci_init_globals(zend_oci_globals *oci_globals TSRMLS_DC)
#endif
{
memset(oci_globals, 0, sizeof(zend_oci_globals));
}
/* }}} */
/* {{{ PHP_GSHUTDOWN_FUNCTION
*
* Called for thread shutdown in ZTS, after module shutdown for non-ZTS
*/
/* This check allows PECL builds from this file to be portable to older PHP releases */
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
static PHP_GSHUTDOWN_FUNCTION(oci)
#else
static void php_oci_shutdown_globals(zend_oci_globals *oci_globals TSRMLS_DC)
#endif
{
php_oci_cleanup_global_handles(TSRMLS_C);
}
/* }}} */
PHP_MINIT_FUNCTION(oci)
{
zend_class_entry oci_lob_class_entry;
zend_class_entry oci_coll_class_entry;
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
/* This check allows PECL builds from this file to be portable to older PHP releases */
/* this is handled by new globals management code */
#else
ZEND_INIT_MODULE_GLOBALS(oci, php_oci_init_globals, php_oci_shutdown_globals);
#endif
REGISTER_INI_ENTRIES();
le_statement = zend_register_list_destructors_ex(php_oci_statement_list_dtor, NULL, "oci8 statement", module_number);
le_connection = zend_register_list_destructors_ex(php_oci_connection_list_dtor, NULL, "oci8 connection", module_number);
le_pconnection = zend_register_list_destructors_ex(php_oci_pconnection_list_np_dtor, php_oci_pconnection_list_dtor, "oci8 persistent connection", module_number);
le_psessionpool = zend_register_list_destructors_ex(NULL, php_oci_spool_list_dtor, "oci8 persistent session pool", module_number);
le_descriptor = zend_register_list_destructors_ex(php_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number);
le_collection = zend_register_list_destructors_ex(php_oci_collection_list_dtor, NULL, "oci8 collection", module_number);
INIT_CLASS_ENTRY(oci_lob_class_entry, "OCI-Lob", php_oci_lob_class_functions);
INIT_CLASS_ENTRY(oci_coll_class_entry, "OCI-Collection", php_oci_coll_class_functions);
oci_lob_class_entry_ptr = zend_register_internal_class(&oci_lob_class_entry TSRMLS_CC);
oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry TSRMLS_CC);
/* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */
REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_SYSOPER",OCI_SYSOPER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_SYSDBA",OCI_SYSDBA, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_CRED_EXT",PHP_OCI_CRED_EXT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_DESCRIBE_ONLY",OCI_DESCRIBE_ONLY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_COMMIT_ON_SUCCESS",OCI_COMMIT_ON_SUCCESS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_NO_AUTO_COMMIT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_EXACT_FETCH",OCI_EXACT_FETCH, CONST_CS | CONST_PERSISTENT);
/* for $LOB->seek() */
REGISTER_LONG_CONSTANT("OCI_SEEK_SET",PHP_OCI_SEEK_SET, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_SEEK_CUR",PHP_OCI_SEEK_CUR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_SEEK_END",PHP_OCI_SEEK_END, CONST_CS | CONST_PERSISTENT);
/* for $LOB->flush() */
REGISTER_LONG_CONSTANT("OCI_LOB_BUFFER_FREE",OCI_LOB_BUFFER_FREE, CONST_CS | CONST_PERSISTENT);
/* for OCIBindByName (real "oci" names + short "php" names */
REGISTER_LONG_CONSTANT("SQLT_BFILEE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_RSET",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_AFC",SQLT_AFC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_CHR",SQLT_CHR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_VCS",SQLT_VCS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_AVC",SQLT_AVC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_STR",SQLT_STR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_LVC",SQLT_LVC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_FLT",SQLT_FLT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_UIN",SQLT_UIN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_LNG",SQLT_LNG, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_LBI",SQLT_LBI, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_ODT",SQLT_ODT, CONST_CS | CONST_PERSISTENT);
#if defined(HAVE_OCI_INSTANT_CLIENT) || (defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 10)
REGISTER_LONG_CONSTANT("SQLT_BDOUBLE",SQLT_BDOUBLE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_BFLOAT",SQLT_BFLOAT, CONST_CS | CONST_PERSISTENT);
#endif
REGISTER_LONG_CONSTANT("OCI_B_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE", CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_ROWID",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_CURSOR",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_B_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
/* for OCIFetchStatement */
REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_COLUMN", PHP_OCI_FETCHSTATEMENT_BY_COLUMN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_ROW", PHP_OCI_FETCHSTATEMENT_BY_ROW, CONST_CS | CONST_PERSISTENT);
/* for OCIFetchInto & OCIResult */
REGISTER_LONG_CONSTANT("OCI_ASSOC",PHP_OCI_ASSOC, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_NUM",PHP_OCI_NUM, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_BOTH",PHP_OCI_BOTH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_RETURN_NULLS",PHP_OCI_RETURN_NULLS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_RETURN_LOBS",PHP_OCI_RETURN_LOBS, CONST_CS | CONST_PERSISTENT);
/* for OCINewDescriptor (real "oci" names + short "php" names */
REGISTER_LONG_CONSTANT("OCI_DTYPE_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_DTYPE_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_DTYPE_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_D_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_D_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_D_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
/* for OCIWriteTemporaryLob */
REGISTER_LONG_CONSTANT("OCI_TEMP_CLOB",OCI_TEMP_CLOB, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_TEMP_BLOB",OCI_TEMP_BLOB, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
PHP_RINIT_FUNCTION(oci)
{
OCI_G(debug_mode) = 0; /* start "fresh" */
OCI_G(num_links) = OCI_G(num_persistent);
OCI_G(errcode) = 0;
OCI_G(edition) = NULL;
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(oci)
{
/* Work around PHP_GSHUTDOWN_FUNCTION not being called in older versions of PHP */
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) || (PHP_MAJOR_VERSION < 5)
#ifndef ZTS
php_oci_cleanup_global_handles(TSRMLS_C);
#endif
#endif
OCI_G(shutdown) = 1;
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(oci)
{
/* Check persistent connections and do the necessary actions if needed. If persistent_helper is
* unable to process a pconnection because of a refcount, the processing would happen from
* np-destructor which is called when refcount goes to zero - php_oci_pconnection_list_np_dtor
*/
zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
if (OCI_G(edition)) {
efree(OCI_G(edition));
}
return SUCCESS;
}
PHP_MINFO_FUNCTION(oci)
{
char buf[32];
php_info_print_table_start();
php_info_print_table_row(2, "OCI8 Support", "enabled");
php_info_print_table_row(2, "Version", PHP_OCI8_VERSION);
php_info_print_table_row(2, "Revision", "$Revision$");
snprintf(buf, sizeof(buf), "%ld", OCI_G(num_persistent));
php_info_print_table_row(2, "Active Persistent Connections", buf);
snprintf(buf, sizeof(buf), "%ld", OCI_G(num_links));
php_info_print_table_row(2, "Active Connections", buf);
#if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
#ifdef PHP_OCI8_ORACLE_VERSION
php_info_print_table_row(2, "Oracle Version", PHP_OCI8_ORACLE_VERSION);
#endif
#ifdef PHP_OCI8_DEF_DIR
php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DEF_DIR);
#endif
#ifdef PHP_OCI8_DEF_SHARED_LIBADD
php_info_print_table_row(2, "Libraries Used", PHP_OCI8_DEF_SHARED_LIBADD);
#endif
#elif defined(HAVE_OCI_INSTANT_CLIENT) && defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
php_info_print_table_row(2, "Oracle Instant Client Version", buf);
#endif
php_info_print_table_row(2, "Temporary Lob support", "enabled");
php_info_print_table_row(2, "Collections support", "enabled");
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
}
/* }}} */
/* list destructors {{{ */
/* {{{ php_oci_connection_list_dtor()
*
* Non-persistent connection destructor
*/
static void php_oci_connection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
if (connection) {
php_oci_connection_close(connection TSRMLS_CC);
OCI_G(num_links)--;
}
} /* }}} */
/* {{{ php_oci_pconnection_list_dtor()
*
* Persistent connection destructor
*/
static void php_oci_pconnection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
if (connection) {
php_oci_connection_close(connection TSRMLS_CC);
OCI_G(num_persistent)--;
OCI_G(num_links)--;
}
} /* }}} */
/* {{{ php_oci_pconnection_list_np_dtor()
*
* Non-Persistent destructor for persistent connection - This gets invoked when
* the refcount of this goes to zero in the regular list
*/
static void php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
zend_rsrc_list_entry *le;
/*
* We cannot get connection as NULL or as a stub in this function. This is the function that
* turns a pconnection to a stub
*
* If oci_password_change() changed the password of a persistent connection, close the
* connection and remove it from the persistent connection cache. This means subsequent scripts
* will be prevented from being able to present the old (now invalid) password to a usable
* connection to the database; they must use the new password.
*
* Check for conditions that warrant removal of the hash entry
*/
if (!connection->is_open ||
connection->passwd_changed ||
(PG(connection_status) & PHP_CONNECTION_TIMEOUT) ||
OCI_G(in_call)) {
/* Remove the hash entry if present */
if ((zend_hash_find(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void **) &le)== SUCCESS) && (le->type == le_pconnection) && (le->ptr == connection)) {
zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
}
else {
php_oci_connection_close(connection TSRMLS_CC);
OCI_G(num_persistent)--;
}
if (OCI_G(debug_mode)) {
php_printf ("OCI8 DEBUG L1: np_dtor cleaning up: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
}
}
else {
/*
* Release the connection to underlying pool. We do this unconditionally so that
* out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect
* semantics. With the PECL OCI 1.3.x extensions, we release pconnections when oci_close
* takes the refcount to zero.
*
* If oci_old_close_semantics is set, we artifically bump up the refcount and decremented
* only at request shutdown.
*/
php_oci_connection_release(connection TSRMLS_CC);
if (OCI_G(debug_mode)) {
php_printf ("OCI8 DEBUG L1: np_dtor releasing: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
}
}
} /* }}} */
/* {{{ php_oci_statement_list_dtor()
*
* Statement destructor
*/
static void php_oci_statement_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_statement *statement = (php_oci_statement *)entry->ptr;
php_oci_statement_free(statement TSRMLS_CC);
} /* }}} */
/* {{{ php_oci_descriptor_list_dtor()
*
* Descriptor destructor
*/
static void php_oci_descriptor_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
php_oci_lob_free(descriptor TSRMLS_CC);
} /* }}} */
/* {{{ php_oci_collection_list_dtor()
*
* Collection destructor
*/
static void php_oci_collection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_collection *collection = (php_oci_collection *)entry->ptr;
php_oci_collection_close(collection TSRMLS_CC);
} /* }}} */
/* }}} */
/* Hash Destructors {{{ */
/* {{{ php_oci_define_hash_dtor()
*
* Define hash destructor
*/
void php_oci_define_hash_dtor(void *data)
{
php_oci_define *define = (php_oci_define *) data;
zval_ptr_dtor(&define->zval);
if (define->name) {
efree(define->name);
define->name = NULL;
}
}
/* }}} */
/* {{{ php_oci_bind_hash_dtor()
*
* Bind hash destructor
*/
void php_oci_bind_hash_dtor(void *data)
{
php_oci_bind *bind = (php_oci_bind *) data;
if (bind->array.elements) {
efree(bind->array.elements);
}
if (bind->array.element_lengths) {
efree(bind->array.element_lengths);
}
if (bind->array.indicators) {
efree(bind->array.indicators);
}
zval_ptr_dtor(&bind->zval);
}
/* }}} */
/* {{{ php_oci_column_hash_dtor()
*
* Column hash destructor
*/
void php_oci_column_hash_dtor(void *data)
{
php_oci_out_column *column = (php_oci_out_column *) data;
TSRMLS_FETCH();
if (column->stmtid) {
zend_list_delete(column->stmtid);
}
if (column->is_descr) {
zend_list_delete(column->descid);
}
if (column->data) {
efree(column->data);
}
if (column->name) {
efree(column->name);
}
}
/* }}} */
/* {{{ php_oci_descriptor_flush_hash_dtor()
*
* Flush descriptors on commit
*/
void php_oci_descriptor_flush_hash_dtor(void *data)
{
php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
TSRMLS_FETCH();
if (descriptor && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
}
data = NULL;
}
/* }}} */
/* {{{ php_oci_descriptor_delete_from_hash()
*
* Delete descriptor from the hash
*/
int php_oci_descriptor_delete_from_hash(void *data, void *id TSRMLS_DC)
{
php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
int *desc_id = (int *) id;
if (descriptor && desc_id && descriptor->id == *desc_id) {
return 1;
}
return 0;
}
/* }}} */
/* }}} */
/* {{{ php_oci_error()
*
* Fetch & print out error message if we get an error
*/
sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC)
{
text *errbuf = (text *)NULL;
sb4 errcode = 0;
switch (status) {
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
if (errbuf) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", errbuf);
efree(errbuf);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: failed to fetch error message");
}
break;
case OCI_NEED_DATA:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NEED_DATA");
break;
case OCI_NO_DATA:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NO_DATA");
errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
if (errbuf) {
efree(errbuf);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NO_DATA: failed to fetch error message");
}
break;
case OCI_ERROR:
errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
if (errbuf) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
efree(errbuf);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to fetch error message");
}
break;
case OCI_INVALID_HANDLE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_INVALID_HANDLE");
break;
case OCI_STILL_EXECUTING:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_STILL_EXECUTING");
break;
case OCI_CONTINUE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CONTINUE");
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown OCI error code: %d", status);
break;
}
return errcode;
}
/* }}} */
/* {{{ php_oci_fetch_errmsg()
*
* Fetch error message into the buffer from the error handle provided
*/
sb4 php_oci_fetch_errmsg(OCIError *error_handle, text **error_buf TSRMLS_DC)
{
sb4 error_code = 0;
text err_buf[PHP_OCI_ERRBUF_LEN];
err_buf[0] = '\0';
memset(err_buf, 0, sizeof(err_buf));
PHP_OCI_CALL(OCIErrorGet, (error_handle, (ub4)1, NULL, &error_code, err_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR));
if (error_code) {
int err_buf_len = strlen((char *)err_buf);
if (err_buf_len && err_buf[err_buf_len - 1] == '\n') {
err_buf[err_buf_len - 1] = '\0';
}
if (err_buf_len && error_buf) {
*error_buf = NULL;
*error_buf = (text *)estrndup((char *)err_buf, err_buf_len);
}
}
return error_code;
} /* }}} */
/* {{{ php_oci_fetch_sqltext_offset()
*
* Compute offset in the SQL statement
*/
int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset TSRMLS_DC)
{
*sqltext = NULL;
*error_offset = 0;
PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
if (statement->errcode != OCI_SUCCESS) {
statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
if (statement->errcode != OCI_SUCCESS) {
statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_do_connect()
*
* Connect wrapper
*/
void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
{
php_oci_connection *connection;
char *username, *password;
char *dbname = NULL, *charset = NULL;
int username_len = 0, password_len = 0;
int dbname_len = 0, charset_len = 0;
long session_mode = OCI_DEFAULT;
/* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ssl", &username, &username_len, &password, &password_len, &dbname, &dbname_len, &charset, &charset_len, &session_mode) == FAILURE) {
return;
}
if (!charset_len) {
charset = NULL;
}
connection = php_oci_do_connect_ex(username, username_len, password, password_len, NULL, 0, dbname, dbname_len, charset, session_mode, persistent, exclusive TSRMLS_CC);
if (!connection) {
RETURN_FALSE;
}
RETURN_RESOURCE(connection->rsrc_id);
} /* }}} */
/* {{{ php_oci_do_connect_ex()
*
* The real connect function. Allocates all the resources needed, establishes the connection and
* returns the result handle (or NULL)
*/
php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC)
{
zend_rsrc_list_entry *le;
zend_rsrc_list_entry new_le;
php_oci_connection *connection = NULL;
smart_str hashed_details = {0};
time_t timestamp;
php_oci_spool *session_pool = NULL;
zend_bool use_spool = 1; /* Default is to use client-side session pool */
zend_bool ping_done = 0;
ub2 charsetid = 0;
ub2 charsetid_nls_lang = 0;
if (session_mode & ~(OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid session mode specified (%ld)", session_mode);
return NULL;
}
if (session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
if ((session_mode & OCI_SYSOPER) && (session_mode & OCI_SYSDBA)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SYSDBA and OCI_SYSOPER cannot be used together");
return NULL;
}
if (session_mode & PHP_OCI_CRED_EXT) {
#ifdef PHP_WIN32
/* Disable external authentication on Windows as Impersonation is not yet handled.
* TODO: Re-enable this once OCI provides capability.
*/
php_error_docref(NULL TSRMLS_CC, E_WARNING, "External Authentication is not supported on Windows");
return NULL;
#endif
if (username_len != 1 || username[0] != '/' || password_len != 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CRED_EXT can only be used with a username of \"/\" and a NULL password");
return NULL;
}
}
if (session_mode & (OCI_SYSOPER | OCI_SYSDBA)) {
/* Increase security by not caching privileged oci_pconnect() connections. The
* connection becomes equivalent to oci_connect() or oci_new_connect().
*/
persistent = 0;
if (!OCI_G(privileged_connect)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA");
return NULL;
}
/* Disable privileged connections in Safe Mode (N.b. safe mode has been removed in PHP
* 6 anyway)
*/
if (PG(safe_mode)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled in Safe Mode");
return NULL;
}
}
}
/* Initialize global handles if they weren't initialized before */
if (OCI_G(env) == NULL) {
php_oci_init_global_handles(TSRMLS_C);
if (OCI_G(env) == NULL) {
return NULL;
}
}
/* We cannot use the new session create logic (OCISessionGet from
* client-side session pool) when privileged connect or password
* change is attempted or OCI_CRED_EXT mode is specified.
* TODO: Re-enable this when OCI provides support.
*/
if ((session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) || (new_password_len)) {
use_spool = 0;
}
smart_str_appendl_ex(&hashed_details, "oci8***", sizeof("oci8***") - 1, 0);
smart_str_appendl_ex(&hashed_details, username, username_len, 0);
smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
/* DRCP: connection_class is an attribute of a connection */
if (OCI_G(connection_class)){
smart_str_appendl_ex(&hashed_details, OCI_G(connection_class), strlen(OCI_G(connection_class)), 0);
}
smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
/* Add edition attribute to the hash */
if (OCI_G(edition)){
smart_str_appendl_ex(&hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
}
smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
if (password_len) {
ulong password_hash;
password_hash = zend_inline_hash_func(password, password_len);
smart_str_append_unsigned_ex(&hashed_details, password_hash, 0);
}
smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
if (dbname) {
smart_str_appendl_ex(&hashed_details, dbname, dbname_len, 0);
}
smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
if (charset && *charset) {
PHP_OCI_CALL_RETURN(charsetid, OCINlsCharSetNameToId, (OCI_G(env), (CONST oratext *)charset));
if (!charsetid) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid character set name: %s", charset);
} else {
smart_str_append_unsigned_ex(&hashed_details, charsetid, 0);
}
}
/* use NLS_LANG if no or invalid charset specified */
if (!charsetid) {
size_t rsize = 0;
sword result;
PHP_OCI_CALL_RETURN(result, OCINlsEnvironmentVariableGet, (&charsetid_nls_lang, 0, OCI_NLS_CHARSET_ID, 0, &rsize));
if (result != OCI_SUCCESS) {
charsetid_nls_lang = 0;
}
smart_str_append_unsigned_ex(&hashed_details, charsetid_nls_lang, 0);
}
timestamp = time(NULL);
smart_str_append_unsigned_ex(&hashed_details, session_mode, 0);
smart_str_0(&hashed_details);
/* make it lowercase */
php_strtolower(hashed_details.c, hashed_details.len);
if (!exclusive && !new_password) {
zend_bool found = 0;
if (persistent && zend_hash_find(&EG(persistent_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
found = 1;
/* found */
if (le->type == le_pconnection) {
connection = (php_oci_connection *)le->ptr;
}
} else if (!persistent && zend_hash_find(&EG(regular_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
found = 1;
if (le->type == le_index_ptr) {
int type, link;
void *ptr;
link = (int) le->ptr;
ptr = zend_list_find(link,&type);
if (ptr && (type == le_connection)) {
connection = (php_oci_connection *)ptr;
}
}
}
/* Debug statements {{{ */
if (OCI_G(debug_mode)) {
if (connection && connection->is_stub) {
php_printf ("OCI8 DEBUG L1: Got a cached stub: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
} else if (connection) {
php_printf ("OCI8 DEBUG L1: Got a cached connection: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
} else {
php_printf ("OCI8 DEBUG L1: Got NO cached connection at (%s:%d) \n", __FILE__, __LINE__);
}
} /* }}} */
/* If we got a pconnection stub, then 'load'(OCISessionGet) the real connection from its
* private spool A connection is a stub if it is only a cached structure and the real
* connection is released to its underlying private session pool. We currently do not have
* stub support for non-persistent conns.
*
* TODO: put in negative code for non-persistent stubs
*/
if (connection && connection->is_persistent && connection->is_stub) {
if (php_oci_create_session(connection, NULL, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
smart_str_free_ex(&hashed_details, 0);
zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
return NULL;
}
/* We do the ping in php_oci_create_session, no need to ping again below */
ping_done = 1;
}
if (connection) {
if (connection->is_open) {
/* found an open connection. now ping it */
if (connection->is_persistent) {
int rsrc_type;
/* Check connection liveness in the following order:
* 1) always check OCI_ATTR_SERVER_STATUS
* 2) see if it's time to ping it
* 3) ping it if needed
*/
if (php_oci_connection_status(connection TSRMLS_CC)) {
/* Only ping if:
*
* 1) next_ping > 0, which means that ping_interval is not -1 (aka "Off")
*
* 2) current_timestamp > next_ping, which means "it's time to check if it's
* still alive"
*/
if (!ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection TSRMLS_CC)) {
/* server died */
} else {
php_oci_connection *tmp;
/* okay, the connection is open and the server is still alive */
connection->used_this_request = 1;
tmp = (php_oci_connection *)zend_list_find(connection->rsrc_id, &rsrc_type);
if (tmp != NULL && rsrc_type == le_pconnection && strlen(tmp->hash_key) == hashed_details.len &&
memcmp(tmp->hash_key, hashed_details.c, hashed_details.len) == 0 && zend_list_addref(connection->rsrc_id) == SUCCESS) {
/* do nothing */
} else {
connection->rsrc_id = zend_list_insert(connection, le_pconnection);
/* Persistent connections: For old close semantics we artificially
* bump up the refcount to prevent the non-persistent destructor
* from getting called until request shutdown. The refcount is
* decremented in the persistent helper
*/
if (OCI_G(old_oci_close_semantics)) {
zend_list_addref(connection->rsrc_id);
}
}
smart_str_free_ex(&hashed_details, 0);
return connection;
}
}
/* server died */
} else {
/* we do not ping non-persistent connections */
smart_str_free_ex(&hashed_details, 0);
zend_list_addref(connection->rsrc_id);
return connection;
}
} /* is_open is true? */
/* Server died - connection not usable. The is_open=true can also fall through to here,
* if ping fails
*/
if (persistent){
int rsrc_type;
connection->is_open = 0;
connection->used_this_request = 1;
/* We have to do a hash_del but need to preserve the resource if there is a positive
* refcount. Set the data pointer in the list entry to NULL
*/
if (connection == zend_list_find(connection->rsrc_id, &rsrc_type) && rsrc_type == le_pconnection) {
le->ptr = NULL;
}
zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
} else {
/* We only remove the hash entry. The resource and the list entry with its pointer
* to the resource are still intact
*/
zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
}
connection = NULL;
} else if (found) {
/* found something, but it's not a connection, delete it */
if (persistent) {
zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
} else {
zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
}
}
}
/* Check if we have reached max_persistent. If so, try to remove a few timed-out connections. As
* a last resort, return a non-persistent connection.
*/
if (persistent) {
zend_bool alloc_non_persistent = 0;
if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
/* try to find an idle connection and kill it */
zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
/* all persistent connactions are in use, fallback to non-persistent connection creation */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Too many open persistent connections (%ld)", OCI_G(num_persistent));
alloc_non_persistent = 1;
}
}
if (alloc_non_persistent) {
connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
connection->is_persistent = 0;
} else {
connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
connection->hash_key = zend_strndup(hashed_details.c, hashed_details.len);
connection->is_persistent = 1;
}
} else {
connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
connection->is_persistent = 0;
}
/* {{{ Get the session pool that suits this connection request from the persistent list. This
* step is only for non-persistent connections as persistent connections have private session
* pools. Non-persistent conns use shared session pool to allow for optimizations such as
* caching the physical connection (for DRCP) even when the non-persistent php connection is
* destroyed.
*
* TODO: Unconditionally do this once OCI provides extended OCISessionGet capability
*/
if (use_spool && !connection->is_persistent) {
if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang TSRMLS_CC))==NULL)
{
php_oci_connection_close(connection TSRMLS_CC);
smart_str_free_ex(&hashed_details, 0);
return NULL;
}
} /* }}} */
connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0;
/* Mark password as unchanged by PHP during the duration of the database session */
connection->passwd_changed = 0;
smart_str_free_ex(&hashed_details, 0);
if (charsetid) {
connection->charset = charsetid;
} else {
connection->charset = charsetid_nls_lang;
}
/* Old session creation semantics when session pool cannot be used Eg: privileged
* connect/password change
*/
if (!use_spool) {
if (php_oci_old_create_session(connection, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
php_oci_connection_close(connection TSRMLS_CC);
return NULL;
}
} else {
/* create using the client-side session pool */
if (php_oci_create_session(connection, session_pool, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
php_oci_connection_close(connection TSRMLS_CC);
return NULL;
}
}
/* Mark it as open */
connection->is_open = 1;
/* add to the appropriate hash */
if (connection->is_persistent) {
new_le.ptr = connection;
new_le.type = le_pconnection;
connection->used_this_request = 1;
connection->rsrc_id = zend_list_insert(connection, le_pconnection);
/* Persistent connections: For old close semantics we artificially bump up the refcount to
* prevent the non-persistent destructor from getting called until request shutdown. The
* refcount is decremented in the persistent helper
*/
if (OCI_G(old_oci_close_semantics)) {
zend_list_addref(connection->rsrc_id);
}
zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
OCI_G(num_persistent)++;
OCI_G(num_links)++;
} else if (!exclusive) {
connection->rsrc_id = zend_list_insert(connection, le_connection);
new_le.ptr = (void *)connection->rsrc_id;
new_le.type = le_index_ptr;
zend_hash_update(&EG(regular_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
OCI_G(num_links)++;
} else {
connection->rsrc_id = zend_list_insert(connection, le_connection);
OCI_G(num_links)++;
}
/* Debug statements {{{ */
if (OCI_G(debug_mode)) {
if (connection->is_persistent) {
php_printf ("OCI8 DEBUG L1: New Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
} else {
php_printf ("OCI8 DEBUG L1: New Non-Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
}
php_printf ("OCI8 DEBUG L1: num_persistent=(%ld), num_links=(%ld) at (%s:%d) \n", OCI_G(num_persistent), OCI_G(num_links), __FILE__, __LINE__);
} /* }}} */
return connection;
}
/* }}} */
/* {{{ php_oci_connection_ping()
*
* Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version
*/
static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC)
{
/* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
* such as from Pre-10.1 servers, the error is still from the server and we would have
* successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
* Pre-10.2 clients
*/
#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
#else
char version[256];
/* use good old OCIServerVersion() */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX));
#endif
if (OCI_G(errcode) == OCI_SUCCESS) {
return 1;
} else {
sb4 error_code = 0;
text tmp_buf[PHP_OCI_ERRBUF_LEN];
/* Treat ORA-1010 as a successful Ping */
OCIErrorGet(OCI_G(err), (ub4)1, NULL, &error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
if (error_code == 1010) {
return 1;
}
}
/* ignore errors here, just return failure
* php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
return 0;
}
/* }}} */
/* {{{ php_oci_connection_status()
*
* Check connection status (pre-ping check)
*/
static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC)
{
ub4 ss = 0;
/* get OCI_ATTR_SERVER_STATUS */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err)));
if (OCI_G(errcode) == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) {
return 1;
}
/* ignore errors here, just return failure
* php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
return 0;
}
/* }}} */
/* {{{ php_oci_connection_rollback()
*
* Rollback connection
*/
int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC)
{
PHP_OCI_CALL_RETURN(connection->errcode, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
connection->needs_commit = 0;
if (connection->errcode != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_connection_commit()
*
* Commit connection
*/
int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
{
PHP_OCI_CALL_RETURN(connection->errcode, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
connection->needs_commit = 0;
if (connection->errcode != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_connection_close()
*
* Close the connection and free all its resources
*/
static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
{
int result = 0;
zend_bool in_call_save = OCI_G(in_call);
if (!connection->is_stub) {
/* Release resources associated with connection */
php_oci_connection_release(connection TSRMLS_CC);
}
if (!connection->using_spool && connection->svc) {
PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0));
}
if (connection->err) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->err, (ub4) OCI_HTYPE_ERROR));
}
if (connection->authinfo) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->authinfo, (ub4) OCI_HTYPE_AUTHINFO));
}
/* No Handlefrees for session pool connections */
if (!connection->using_spool) {
if (connection->session) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->session, OCI_HTYPE_SESSION));
}
if (connection->is_attached) {
PHP_OCI_CALL(OCIServerDetach, (connection->server, OCI_G(err), OCI_DEFAULT));
}
if (connection->svc) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
}
if (connection->server) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->server, (ub4) OCI_HTYPE_SERVER));
}
if (connection->env) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
}
} else if (connection->private_spool) {
/* Keep this as the last member to be freed, as there are dependencies
* (like env) on the session pool
*/
php_oci_spool_close(connection->private_spool TSRMLS_CC);
}
if (connection->is_persistent) {
if (connection->hash_key) {
free(connection->hash_key);
}
free(connection);
} else {
if (connection->hash_key) {
efree(connection->hash_key);
}
efree(connection);
}
connection = NULL;
OCI_G(in_call) = in_call_save;
return result;
} /* }}} */
/* {{{ php_oci_connection_release()
*
* Release the connection's resources. This involves freeing descriptors and rolling back
* transactions, setting timeout-related parameters etc. For session-pool using connections, the
* underlying connection is released to its session pool.
*/
int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
{
int result = 0;
zend_bool in_call_save = OCI_G(in_call);
time_t timestamp = time(NULL);
if (connection->is_stub) {
return 0;
}
if (connection->descriptors) {
zend_hash_destroy(connection->descriptors);
efree(connection->descriptors);
connection->descriptors = NULL;
}
if (connection->svc) {
/* rollback outstanding transactions */
if (connection->needs_commit) {
if (php_oci_connection_rollback(connection TSRMLS_CC)) {
/* rollback failed */
result = 1;
}
}
}
if (OCI_G(persistent_timeout) > 0) {
connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
}
/* We may have half-cooked connections to clean up */
if (connection->next_pingp) {
if (OCI_G(ping_interval) >= 0) {
*(connection->next_pingp) = timestamp + OCI_G(ping_interval);
} else {
/* ping_interval is -1 */
*(connection->next_pingp) = 0;
}
}
/* Release the session (stubs are filtered out at the beginning)*/
if (connection->using_spool) {
ub4 rlsMode = OCI_DEFAULT;
if (result) {
rlsMode |= OCI_SESSRLS_DROPSESS;
}
/* Sessions for non-persistent connections should be dropped. For 11 and above, the session
* pool has its own mechanism for doing so for purity NEW connections. We need to do so
* explicitly for 10.2 and earlier.
*/
#if (!(OCI_MAJOR_VERSION >= 11))
if (!connection->is_persistent) {
rlsMode |= OCI_SESSRLS_DROPSESS;
}
#endif
if (connection->svc) {
PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
0, rlsMode));
}
/* It no longer has relation with the database session. However authinfo and env are
* cached
*/
connection->svc = NULL;
connection->server = NULL;
connection->session = NULL;
connection->is_attached = connection->is_open = connection->needs_commit = connection->used_this_request = 0;
connection->is_stub = 1;
/* Cut the link between the connection structure and the time_t structure allocated within
* the OCI session
*/
connection->next_pingp = NULL;
}
OCI_G(in_call) = in_call_save;
return result;
} /* }}} */
/* {{{ php_oci_password_change()
*
* Change password for the user with the username given
*/
int php_oci_password_change(php_oci_connection *connection, char *user, int user_len, char *pass_old, int pass_old_len, char *pass_new, int pass_new_len TSRMLS_DC)
{
PHP_OCI_CALL_RETURN(connection->errcode, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT));
if (connection->errcode != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->passwd_changed = 1;
return 0;
} /* }}} */
/* {{{ php_oci_server_get_version()
*
* Get Oracle server version
*/
int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC)
{
char version_buff[256];
PHP_OCI_CALL_RETURN(connection->errcode, OCIServerVersion, (connection->svc, connection->err, (text *)version_buff, sizeof(version_buff), OCI_HTYPE_SVCCTX));
if (connection->errcode != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
*version = estrdup(version_buff);
return 0;
} /* }}} */
/* {{{ php_oci_column_to_zval()
*
* Convert php_oci_out_column struct into zval
*/
int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSRMLS_DC)
{
php_oci_descriptor *descriptor;
ub4 lob_length;
int column_size;
char *lob_buffer;
int lob_fetch_status;
if (column->indicator == -1) { /* column is NULL */
ZVAL_NULL(value);
return 0;
}
if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
ZVAL_RESOURCE(value, column->stmtid);
zend_list_addref(column->stmtid);
} else if (column->is_descr) {
if (column->data_type != SQLT_RDD) {
int rsrc_type;
/* reset descriptor's length */
descriptor = (php_oci_descriptor *) zend_list_find(column->descid, &rsrc_type);
if (!descriptor || rsrc_type != le_descriptor) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find LOB descriptor #%d", column->descid);
return 1;
}
descriptor->lob_size = -1;
descriptor->lob_current_position = 0;
descriptor->buffering = 0;
}
if (column->data_type != SQLT_RDD && (mode & PHP_OCI_RETURN_LOBS)) {
/* PHP_OCI_RETURN_LOBS means that we want the content of the LOB back instead of the locator */
lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, &lob_buffer, &lob_length TSRMLS_CC);
php_oci_temp_lob_close(descriptor TSRMLS_CC);
if (lob_fetch_status) {
ZVAL_FALSE(value);
return 1;
} else {
if (lob_length > 0) {
ZVAL_STRINGL(value, lob_buffer, lob_length, 0);
} else {
ZVAL_EMPTY_STRING(value);
}
return 0;
}
} else {
/* return the locator */
object_init_ex(value, oci_lob_class_entry_ptr);
add_property_resource(value, "descriptor", column->descid);
zend_list_addref(column->descid);
}
} else {
switch (column->retcode) {
case 0:
/* intact value */
if (column->piecewise) {
column_size = column->retlen4;
} else {
column_size = column->retlen;
}
break;
default:
ZVAL_FALSE(value);
return 0;
}
ZVAL_STRINGL(value, column->data, column_size, 1);
}
return 0;
}
/* }}} */
/* {{{ php_oci_fetch_row()
*
* Fetch the next row from the given statement
*/
void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
{
zval *z_statement, *array;
php_oci_statement *statement;
php_oci_out_column *column;
ub4 nrows = 1;
int i;
long fetch_mode = 0;
if (expected_args > 2) {
/* only for ocifetchinto BC */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|l", &z_statement, &array, &fetch_mode) == FAILURE) {
return;
}
if (ZEND_NUM_ARGS() == 2) {
fetch_mode = mode;
}
} else if (expected_args == 2) {
/* only for oci_fetch_array() */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_statement, &fetch_mode) == FAILURE) {
return;
}
if (ZEND_NUM_ARGS() == 1) {
fetch_mode = mode;
}
} else {
/* for all oci_fetch_*() */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
return;
}
fetch_mode = mode;
}
if (!(fetch_mode & PHP_OCI_NUM) && !(fetch_mode & PHP_OCI_ASSOC)) {
/* none of the modes present, use the default one */
if (mode & PHP_OCI_ASSOC) {
fetch_mode |= PHP_OCI_ASSOC;
}
if (mode & PHP_OCI_NUM) {
fetch_mode |= PHP_OCI_NUM;
}
}
PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
RETURN_FALSE;
}
array_init(return_value);
for (i = 0; i < statement->ncolumns; i++) {
column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
if (column == NULL) {
continue;
}
if ((column->indicator == -1) && ((fetch_mode & PHP_OCI_RETURN_NULLS) == 0)) {
continue;
}
if (!(column->indicator == -1)) {
zval *element;
MAKE_STD_ZVAL(element);
php_oci_column_to_zval(column, element, fetch_mode TSRMLS_CC);
if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
add_index_zval(return_value, i, element);
}
if (fetch_mode & PHP_OCI_ASSOC) {
if (fetch_mode & PHP_OCI_NUM) {
Z_ADDREF_P(element);
}
add_assoc_zval(return_value, column->name, element);
}
} else {
if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
add_index_null(return_value, i);
}
if (fetch_mode & PHP_OCI_ASSOC) {
add_assoc_null(return_value, column->name);
}
}
}
if (expected_args > 2) {
/* Only for ocifetchinto BC. In all other cases we return array, not long */
REPLACE_ZVAL_VALUE(&array, return_value, 1); /* copy return_value to given reference */
zval_dtor(return_value);
RETURN_LONG(statement->ncolumns);
}
}
/* }}} */
/* {{{ php_oci_persistent_helper()
*
* Helper function to close/rollback persistent connections at the end of request. A return value of
* 1 indicates that the connection is to be destroyed
*/
static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
{
time_t timestamp;
php_oci_connection *connection;
timestamp = time(NULL);
/* Persistent connection stubs are also counted as they have private session pools */
if (le->type == le_pconnection) {
connection = (php_oci_connection *)le->ptr;
if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
if (OCI_G(debug_mode)) {
php_printf ("OCI8 DEBUG L1: persistent_helper processing for timeout: (%p stub=%d) at (%s:%d) \n", connection, connection->is_stub, __FILE__, __LINE__);
}
if (connection->idle_expiry < timestamp) {
/* connection has timed out */
return ZEND_HASH_APPLY_REMOVE;
}
}
}
return ZEND_HASH_APPLY_KEEP;
} /* }}} */
/* {{{ php_oci_create_spool()
*
* Create(alloc + Init) Session pool for the given dbname and charsetid
*/
static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC)
{
php_oci_spool *session_pool = NULL;
zend_bool iserror = 0;
ub4 poolmode = OCI_DEFAULT; /* Mode to be passed to OCISessionPoolCreate */
OCIAuthInfo *spoolAuth = NULL;
/*Allocate sessionpool out of persistent memory */
session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
/* Populate key if passed */
if (hash_key_len) {
session_pool->spool_hash_key = zend_strndup(hash_key, hash_key_len);
}
/* Create the session pool's env */
if (!(session_pool->env = php_oci_create_env(charsetid TSRMLS_CC))) {
iserror = 1;
goto exit_create_spool;
}
/* Allocate the pool handle */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
}
/* Allocate the session pool error handle - This only for use in the destructor, as there is a
* generic bug which can free up the OCI_G(err) variable before destroying connections. We
* cannot use this for other roundtrip calls as there is no way the user can access this error
*/
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
}
/* Disable RLB as we mostly have single-connection pools */
#if (OCI_MAJOR_VERSION > 10)
poolmode = OCI_SPC_NO_RLB | OCI_SPC_HOMOGENEOUS;
#else
poolmode = OCI_SPC_HOMOGENEOUS;
#endif
#if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
/* Allocate auth handle for session pool {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
} /* }}} */
/* Set the edition attribute on the auth handle {{{ */
if (OCI_G(edition)) {
PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) OCI_G(edition), (ub4)(strlen(OCI_G(edition))), (ub4)OCI_ATTR_EDITION, OCI_G(err)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
}
} /* }}} */
/* Set the driver name attribute on the auth handle {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
} /* }}} */
/* Set the auth handle on the session pool {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) (session_pool->poolh),(ub4) OCI_HTYPE_SPOOL, (dvoid *) spoolAuth, (ub4)0, (ub4)OCI_ATTR_SPOOL_AUTH, OCI_G(err)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
} /* }}} */
#endif
/* Create the homogeneous session pool - We have different session pools for every different
* username, password, charset and dbname.
*/
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
}
/* Set the session pool's timeout to the oci8.persistent_timeout param */
if (OCI_G(persistent_timeout)) {
ub4 timeout = OCI_G(persistent_timeout);
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) session_pool->poolh, (ub4) OCI_HTYPE_SPOOL, (void *) &timeout, (ub4) sizeof(timeout), (ub4) OCI_ATTR_SPOOL_TIMEOUT, OCI_G(err)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
}
}
exit_create_spool:
if (iserror && session_pool) {
php_oci_spool_close(session_pool TSRMLS_CC);
session_pool = NULL;
}
if (spoolAuth) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO));
}
if (OCI_G(debug_mode)) {
php_printf ("OCI8 DEBUG L1: create_spool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
}
return session_pool;
} /* }}} */
/* {{{ php_oci_get_spool()
*
* Get Session pool for the given dbname and charsetid from the persistent list. Function called for
* non-persistent connections.
*/
static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC)
{
smart_str spool_hashed_details = {0};
php_oci_spool *session_pool = NULL;
zend_rsrc_list_entry spool_le = {0};
zend_rsrc_list_entry *spool_out_le = NULL;
zend_bool iserror = 0;
/* Create the spool hash key {{{ */
smart_str_appendl_ex(&spool_hashed_details, "oci8spool***", sizeof("oci8spool***") - 1, 0);
smart_str_appendl_ex(&spool_hashed_details, username, username_len, 0);
smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
/* Add edition attribute to the hash */
if (OCI_G(edition)){
smart_str_appendl_ex(&spool_hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
}
smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
if (password_len) {
ulong password_hash;
password_hash = zend_inline_hash_func(password, password_len);
smart_str_append_unsigned_ex(&spool_hashed_details, password_hash, 0);
}
smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
if (dbname_len) {
smart_str_appendl_ex(&spool_hashed_details, dbname, dbname_len, 0);
}
smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
smart_str_append_unsigned_ex(&spool_hashed_details, charsetid, 0);
/* Session Pool Hash Key : oci8spool***username**edition**hashedpassword**dbname**charset */
smart_str_0(&spool_hashed_details);
php_strtolower(spool_hashed_details.c, spool_hashed_details.len);
/* }}} */
if (zend_hash_find(&EG(persistent_list),spool_hashed_details.c, spool_hashed_details.len+1, (void **)&spool_out_le) == FAILURE) {
session_pool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, spool_hashed_details.c, spool_hashed_details.len, charsetid TSRMLS_CC);
if (session_pool == NULL) {
iserror = 1;
goto exit_get_spool;
}
spool_le.ptr = session_pool;
spool_le.type = le_psessionpool;
zend_list_insert(session_pool, le_psessionpool);
zend_hash_update(&EG(persistent_list), session_pool->spool_hash_key, strlen(session_pool->spool_hash_key)+1,(void *)&spool_le, sizeof(zend_rsrc_list_entry),NULL);
} else if (spool_out_le->type == le_psessionpool &&
strlen(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == spool_hashed_details.len &&
memcmp(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key, spool_hashed_details.c, spool_hashed_details.len) == 0) {
/* retrieve the cached session pool */
session_pool = (php_oci_spool *)(spool_out_le->ptr);
}
exit_get_spool:
smart_str_free_ex(&spool_hashed_details, 0);
if (iserror && session_pool) {
php_oci_spool_close(session_pool TSRMLS_CC);
session_pool = NULL;
}
return session_pool;
} /* }}} */
/* {{{ php_oci_create_env()
*
* Create the OCI environment choosing the correct function for the OCI version
*/
static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC)
{
OCIEnv *retenv = NULL;
/* create an environment using the character set id */
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));
if (OCI_G(errcode) != OCI_SUCCESS) {
#ifdef HAVE_OCI_INSTANT_CLIENT
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
#else
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
#endif
return NULL;
}
return retenv;
}/* }}} */
/* {{{ php_oci_old_create_session()
*
* This function is to be deprecated in future in favour of OCISessionGet which is used in
* php_oci_do_connect_ex
*/
static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
{
ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
if (OCI_G(debug_mode)) {
php_printf ("OCI8 DEBUG: Bypassing client-side session pool for session create at (%s:%d) \n", __FILE__, __LINE__);
}
/* Create the OCI environment separate for each connection */
if (!(connection->env = php_oci_create_env(connection->charset TSRMLS_CC))) {
return 1;
}
/* Allocate our server handle {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->server), OCI_HTYPE_SERVER, 0, NULL));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
} /* }}} */
/* Attach to the server {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerAttach, (connection->server, OCI_G(err), (text *)dbname, dbname_len, (ub4) OCI_DEFAULT));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
} /* }}} */
connection->is_attached = 1;
/* Allocate our session handle {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->session), OCI_HTYPE_SESSION, 0, NULL));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
} /* }}} */
/* Allocate our private error-handle {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
} /* }}} */
/* Allocate our service-context {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->svc), OCI_HTYPE_SVCCTX, 0, NULL));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
} /* }}} */
/* Set the username {{{ */
if (username) {
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
}/* }}} */
/* Set the password {{{ */
if (password) {
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
}/* }}} */
/* Set the edition attribute on the session handle {{{ */
#if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
if (OCI_G(edition)) {
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
}
#endif /* }}} */
/* Set the driver name attribute on the session handle {{{ */
#if (OCI_MAJOR_VERSION >= 11)
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
#endif /* }}} */
/* Set the server handle in the service handle {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->server, 0, OCI_ATTR_SERVER, OCI_G(err)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
} /* }}} */
/* Set the authentication handle in the service handle {{{ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->session, 0, OCI_ATTR_SESSION, OCI_G(err)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
} /* }}} */
if (new_password) {
/* Try to change password if new one was provided {{{ */
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));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
} /* }}} */
} else {
/* start the session {{{ */
ub4 cred_type = OCI_CRED_RDBMS;
/* Extract the overloaded session_mode parameter into valid Oracle credential and session mode values */
if (session_mode & PHP_OCI_CRED_EXT) {
cred_type = OCI_CRED_EXT;
session_mode ^= PHP_OCI_CRED_EXT;
}
session_mode |= OCI_STMT_CACHE;
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionBegin, (connection->svc, OCI_G(err), connection->session, (ub4) cred_type, (ub4) session_mode));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
/* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
* user's password has expired, but is still usable.
*/
if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
return 1;
}
} /* }}} */
}
/* Brand new connection: Init and update the next_ping in the connection */
if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
/* Successfully created session */
return 0;
} /* }}} */
/* {{{ php_oci_create_session()
*
* Create session using client-side session pool - new norm
*/
static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
{
php_oci_spool *actual_spool = NULL;
#if (OCI_MAJOR_VERSION > 10)
ub4 purity = -2; /* Illegal value to initialize */
#endif
time_t timestamp = time(NULL);
ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
/* Persistent connections have private session pools */
if (connection->is_persistent && !connection->private_spool &&
!(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, 0, connection->charset TSRMLS_CC))) {
return 1;
}
actual_spool = (connection->is_persistent) ? (connection->private_spool) : (session_pool);
connection->env = actual_spool->env;
/* Do this upfront so that connection close on an error would know that this is a session pool
* connection. Failure to do this would result in crashes in error scenarios
*/
if (!connection->using_spool) {
connection->using_spool = 1;
}
if (OCI_G(debug_mode)) {
if (session_pool) {
php_printf ("OCI8 DEBUG L1: using shared pool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
} else {
php_printf ("OCI8 DEBUG L1: using private pool: (%p) at (%s:%d) \n", connection->private_spool, __FILE__, __LINE__);
}
}
/* The passed in "connection" can be a cached stub from plist or freshly created. In the former
* case, we do not have to allocate any handles
*/
if (!connection->err) {
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
}
/* {{{ Allocate and initialize the connection-private authinfo handle if not allocated yet */
if (!connection->authinfo) {
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->authinfo), OCI_HTYPE_AUTHINFO, 0, NULL));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
/* Set the Connection class and purity if OCI client version >= 11g */
#if (OCI_MAJOR_VERSION > 10)
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
if (connection->is_persistent)
purity = OCI_ATTR_PURITY_SELF;
else
purity = OCI_ATTR_PURITY_NEW;
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
#endif
} /* }}} */
/* Debug statements {{{ */
if (OCI_G(debug_mode)) {
ub4 numfree = 0, numbusy = 0, numopen = 0;
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)));
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)));
numfree = numopen - numbusy; /* number of free connections in the pool */
php_printf ("OCI8 DEBUG L1: (numopen=%d)(numbusy=%d) at (%s:%d) \n", numopen, numbusy, __FILE__, __LINE__);
} /* }}} */
/* Ping loop: Ping and loop till we get a good connection. When a database instance goes
* down, it can leave several bad connections that need to be flushed out before getting a
* good one. In non-RAC, we always get a brand new connection at the end of the loop and in
* RAC, we can get a good connection from a different instance before flushing out all bad
* ones. We do not need to ping brand new connections.
*/
do {
/* Continue to use the global error handle as the connection is closed when an error occurs */
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));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
/* Session creation returns OCI_SUCCESS_WITH_INFO when user's password has expired, but
* is still usable.
*/
if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
return 1;
}
}
/* {{{ Populate the session and server fields of the connection */
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)));
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))); /* }}} */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, OCI_G(err), (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&(connection->next_pingp)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
if (!(connection->next_pingp)){
/* This is a brand new connection, we need not ping, but have to initialize ping */
if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
} else if ((*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp))) {
if (php_oci_connection_ping(connection TSRMLS_CC)) {
/* Got a good connection - update next_ping and get out of ping loop */
*(connection->next_pingp) = timestamp + OCI_G(ping_interval);
} else {
/* Bad connection - remove from pool */
PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) OCI_SESSRLS_DROPSESS));
connection->svc = NULL;
connection->server = NULL;
connection->session = NULL;
}
} /* If ping applicable */
} while (!(connection->svc));
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)));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
}
/* Session is now taken from the session pool and attached and open */
connection->is_stub = 0;
connection->is_attached = connection->is_open = 1;
return 0;
} /* }}} */
/* {{{ php_oci_spool_list_dtor()
*
* Session pool destructor function
*/
static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
if (session_pool) {
php_oci_spool_close(session_pool TSRMLS_CC);
}
return;
} /* }}} */
/* {{{ php_oci_spool_close()
*
* Destroys the OCI Session Pool
*/
static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC)
{
if (session_pool->poolname_len) {
PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
(dvoid *) session_pool->err, OCI_SPD_FORCE));
}
if (session_pool->poolh) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->poolh, OCI_HTYPE_SPOOL));
}
if (session_pool->err) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->err, OCI_HTYPE_ERROR));
}
if (session_pool->env) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->env, OCI_HTYPE_ENV));
}
if (session_pool->spool_hash_key) {
free(session_pool->spool_hash_key);
}
free(session_pool);
} /* }}} */
/* {{{ php_oci_ping_init()
*
* Initializes the next_ping time as a context value in the connection. We now use
* OCIContext{Get,Set}Value to store the next_ping because we need to support ping for
* non-persistent DRCP connections
*/
static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC)
{
time_t *next_pingp = NULL;
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, errh, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&next_pingp));
if (OCI_G(errcode) != OCI_SUCCESS) {
return OCI_G(errcode);
}
/* This must be a brand-new connection. Allocate memory for the ping */
if (!next_pingp) {
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIMemoryAlloc, (connection->session, errh, (void **)&next_pingp, OCI_DURATION_SESSION, sizeof(time_t), OCI_MEMORY_CLEARED));
if (OCI_G(errcode) != OCI_SUCCESS) {
return OCI_G(errcode);
}
}
if (OCI_G(ping_interval) >= 0) {
time_t timestamp = time(NULL);
*next_pingp = timestamp + OCI_G(ping_interval);
} else {
*next_pingp = 0;
}
/* Set the new ping value into the connection */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextSetValue, (connection->session, errh, OCI_DURATION_SESSION, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), next_pingp));
if (OCI_G(errcode) != OCI_SUCCESS) {
OCIMemoryFree(connection->session, errh, next_pingp);
return OCI_G(errcode);
}
/* Cache the pointer so we do not have to do OCIContextGetValue repeatedly */
connection->next_pingp = next_pingp;
return OCI_SUCCESS;
} /* }}} */
#endif /* HAVE_OCI8 */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/