1
0
mirror of https://github.com/php/php-src.git synced 2026-04-11 18:13:00 +02:00
Files
archived-php-src/ext/oci8/oci8.c
Peter Kokot 92ac598aab Remove local variables
This patch removes the so called local variables defined per
file basis for certain editors to properly show tab width, and
similar settings. These are mainly used by Vim and Emacs editors
yet with recent changes the once working definitions don't work
anymore in Vim without custom plugins or additional configuration.
Neither are these settings synced across the PHP code base.

A simpler and better approach is EditorConfig and fixing code
using some code style fixing tools in the future instead.

This patch also removes the so called modelines for Vim. Modelines
allow Vim editor specifically to set some editor configuration such as
syntax highlighting, indentation style and tab width to be set in the
first line or the last 5 lines per file basis. Since the php test
files have syntax highlighting already set in most editors properly and
EditorConfig takes care of the indentation settings, this patch removes
these as well for the Vim 6.0 and newer versions.

With the removal of local variables for certain editors such as
Emacs and Vim, the footer is also probably not needed anymore when
creating extensions using ext_skel.php script.

Additionally, Vim modelines for setting php syntax and some editor
settings has been removed from some *.phpt files.  All these are
mostly not relevant for phpt files neither work properly in the
middle of the file.
2019-02-03 21:03:00 +01:00

3470 lines
117 KiB
C

/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 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@php.net> |
| Wez Furlong <wez@omniti.com> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_ini.h"
#include "zend_smart_str.h"
#if HAVE_OCI8
/* PHP 5.2 is the minimum supported version for OCI8 2.0 */
#if PHP_MAJOR_VERSION < 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 1)
#error Use PHP OCI8 1.4 for your version of PHP
#elif PHP_MAJOR_VERSION < 7
/* PHP 7 is the minimum supported version for OCI8 2.1 */
#error Use PHP OCI8 2.0 for your version of PHP
#endif
#include "php_oci8.h"
#include "php_oci8_int.h"
#include "zend_hash.h"
ZEND_DECLARE_MODULE_GLOBALS(oci)
static PHP_GINIT_FUNCTION(oci);
static PHP_GSHUTDOWN_FUNCTION(oci);
/* 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 */
#if defined(PHP_WIN32)
#define PHP_OCI8_LIB_PATH_MSG "PATH"
#elif defined(__APPLE__)
#define PHP_OCI8_LIB_PATH_MSG "DYLD_LIBRARY_PATH"
#elif defined(_AIX)
#define PHP_OCI8_LIB_PATH_MSG "LIBPATH"
#elif defined(__hpux)
#define PHP_OCI8_LIB_PATH_MSG "SHLIB_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
#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_resource *);
static void php_oci_pconnection_list_dtor (zend_resource *);
static void php_oci_pconnection_list_np_dtor (zend_resource *);
static void php_oci_statement_list_dtor (zend_resource *);
static void php_oci_descriptor_list_dtor (zend_resource *);
static void php_oci_spool_list_dtor(zend_resource *entry);
static void php_oci_collection_list_dtor (zend_resource *);
static int php_oci_persistent_helper(zval *zv);
static int php_oci_connection_ping(php_oci_connection *);
static int php_oci_connection_status(php_oci_connection *);
static int php_oci_connection_close(php_oci_connection *);
static void php_oci_spool_close(php_oci_spool *session_pool);
static OCIEnv *php_oci_create_env(ub2 charsetid);
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);
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);
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);
static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, zend_string *hash_key, int charsetid);
static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh);
/* }}} */
/* {{{ dynamically loadable module stuff */
#if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G) || defined(COMPILE_DL_OCI8_12C)
ZEND_GET_MODULE(oci8)
#endif /* COMPILE_DL */
/* }}} */
/* {{{ 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_or_name)
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_or_name)
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_or_name)
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_or_name)
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_or_name)
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_get_implicit_resultset, 0, 0, 1)
ZEND_ARG_INFO(0, statement_resource)
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_set_db_operation, 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_call_timeout, 0, 0, 2)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, call_timeout)
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(arginfo_oci_client_version, 0)
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()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_register_taf_callback, 0, 0, 1)
ZEND_ARG_INFO(0, connection_resource)
ZEND_ARG_INFO(0, function_name)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_unregister_taf_callback, 0, 0, 1)
ZEND_ARG_INFO(0, connection_resource)
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()
/* }}} */
/* {{{ 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_get_implicit_resultset);
PHP_FUNCTION(oci_new_cursor);
PHP_FUNCTION(oci_result);
PHP_FUNCTION(oci_client_version);
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_db_operation);
PHP_FUNCTION(oci_set_call_timeout);
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);
PHP_FUNCTION(oci_register_taf_callback);
PHP_FUNCTION(oci_unregister_taf_callback);
/* }}} */
/* {{{ extension definition structures
*/
static const 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_get_implicit_resultset, arginfo_oci_get_implicit_resultset)
PHP_FE(oci_new_cursor, arginfo_oci_new_cursor)
PHP_FE(oci_result, arginfo_oci_result)
PHP_FE(oci_client_version, arginfo_oci_client_version)
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_db_operation, arginfo_oci_set_db_operation)
PHP_FE(oci_set_call_timeout, arginfo_oci_set_call_timeout)
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_FE(oci_register_taf_callback, arginfo_oci_register_taf_callback)
PHP_FE(oci_unregister_taf_callback, arginfo_oci_unregister_taf_callback)
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)
PHP_FE_END
};
static const 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)
PHP_FE_END
};
static const 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)
PHP_FE_END
};
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,
PHP_MODULE_GLOBALS(oci), /* globals descriptor */
PHP_GINIT(oci), /* globals ctor */
PHP_GSHUTDOWN(oci), /* globals dtor */
NULL, /* post deactivate */
STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */
/* {{{ PHP_INI */
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY( "oci8.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_oci_globals, oci_globals)
STD_PHP_INI_ENTRY( "oci8.persistent_timeout", "-1", PHP_INI_SYSTEM, OnUpdateLong, persistent_timeout, zend_oci_globals, oci_globals)
STD_PHP_INI_ENTRY( "oci8.ping_interval", "60", PHP_INI_SYSTEM, OnUpdateLong, 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, OnUpdateLong, statement_cache_size, zend_oci_globals, oci_globals)
STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, OnUpdateLong, 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)
#if (OCI_MAJOR_VERSION >= 11)
STD_PHP_INI_ENTRY( "oci8.connection_class", "", PHP_INI_ALL, OnUpdateString, connection_class, zend_oci_globals, oci_globals)
#endif
#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
STD_PHP_INI_BOOLEAN("oci8.events", "0", PHP_INI_SYSTEM, OnUpdateBool, events, zend_oci_globals, oci_globals)
#endif
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(void)
{
sword errstatus;
sb4 ora_error_code = 0;
text tmp_buf[PHP_OCI_ERRBUF_LEN]; /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
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, 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, 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
if (OCI_G(env)
&& OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
&& *tmp_buf) {
php_error_docref(NULL, E_WARNING, "%s", tmp_buf);
}
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 = (int) 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, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
} else {
php_error_docref(NULL, 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(void)
{
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
*/
static PHP_GINIT_FUNCTION(oci)
{
memset(oci_globals, 0, sizeof(zend_oci_globals));
}
/* }}} */
/* {{{ PHP_GSHUTDOWN_FUNCTION
*
* Called for thread shutdown in ZTS, after module shutdown for non-ZTS
*/
static PHP_GSHUTDOWN_FUNCTION(oci)
{
php_oci_cleanup_global_handles();
}
/* }}} */
PHP_MINIT_FUNCTION(oci)
{
zend_class_entry oci_lob_class_entry;
zend_class_entry oci_coll_class_entry;
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);
oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry);
/* 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
#if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
REGISTER_LONG_CONSTANT("SQLT_BOL",SQLT_BOL, 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);
#if defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 12
REGISTER_LONG_CONSTANT("OCI_B_BOL",SQLT_BOL, CONST_CS | CONST_PERSISTENT);
#endif
/* 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);
/* for Transparent Application Failover */
REGISTER_LONG_CONSTANT("OCI_FO_END", OCI_FO_END, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_ABORT", OCI_FO_ABORT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_REAUTH", OCI_FO_REAUTH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_BEGIN", OCI_FO_BEGIN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_ERROR", OCI_FO_ERROR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_NONE", OCI_FO_NONE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_SESSION", OCI_FO_SESSION, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_SELECT", OCI_FO_SELECT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_TXNAL", OCI_FO_TXNAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("OCI_FO_RETRY", OCI_FO_RETRY, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
PHP_RINIT_FUNCTION(oci)
{
OCI_G(num_links) = OCI_G(num_persistent);
OCI_G(errcode) = 0;
OCI_G(edition) = NULL;
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(oci)
{
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), php_oci_persistent_helper);
if (OCI_G(edition)) {
efree(OCI_G(edition));
}
return SUCCESS;
}
PHP_MINFO_FUNCTION(oci)
{
char buf[32];
#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
char ver[256];
#endif
php_info_print_table_start();
php_info_print_table_row(2, "OCI8 Support", "enabled");
#if defined(HAVE_OCI8_DTRACE)
php_info_print_table_row(2, "OCI8 DTrace Support", "enabled");
#else
php_info_print_table_row(2, "OCI8 DTrace Support", "disabled");
#endif
php_info_print_table_row(2, "OCI8 Version", PHP_OCI8_VERSION);
#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))
php_oci_client_get_version(ver, sizeof(ver));
php_info_print_table_row(2, "Oracle Run-time Client Library Version", ver);
#else
php_info_print_table_row(2, "Oracle Run-time Client Library Version", "Unknown");
#endif
#if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
#elif defined(PHP_OCI8_ORACLE_VERSION)
snprintf(buf, sizeof(buf), "%s", PHP_OCI8_ORACLE_VERSION);
#else
snprintf(buf, sizeof(buf), "Unknown");
#endif
#if defined(HAVE_OCI_INSTANT_CLIENT)
php_info_print_table_row(2, "Oracle Compile-time Instant Client Version", buf);
#else
php_info_print_table_row(2, "Oracle Compile-time Version", buf);
#endif
#if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
#if defined(PHP_OCI8_DEF_DIR)
php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DEF_DIR);
#endif
#if defined(PHP_OCI8_DEF_SHARED_LIBADD)
php_info_print_table_row(2, "Libraries Used", PHP_OCI8_DEF_SHARED_LIBADD);
#endif
#endif
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
php_info_print_table_start();
php_info_print_table_header(2, "Statistics", "");
snprintf(buf, sizeof(buf), ZEND_LONG_FMT, OCI_G(num_persistent));
php_info_print_table_row(2, "Active Persistent Connections", buf);
snprintf(buf, sizeof(buf), ZEND_LONG_FMT, OCI_G(num_links));
php_info_print_table_row(2, "Active Connections", buf);
php_info_print_table_end();
}
/* }}} */
/* {{{ list destructors */
/* {{{ php_oci_connection_list_dtor()
*
* Non-persistent connection destructor
*/
static void php_oci_connection_list_dtor(zend_resource *entry)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
if (connection) {
php_oci_connection_close(connection);
OCI_G(num_links)--;
}
}
/* }}} */
/* {{{ php_oci_pconnection_list_dtor()
*
* Persistent connection destructor
*/
static void php_oci_pconnection_list_dtor(zend_resource *entry)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
if (connection) {
php_oci_connection_close(connection);
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_resource *entry)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
zval *zvp;
zend_resource *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 (connection->hash_key) {
zvp = zend_hash_find(&EG(persistent_list), connection->hash_key);
le = zvp ? Z_RES_P(zvp) : NULL;
if (le != NULL && le->type == le_pconnection && le->ptr == connection) {
zend_hash_del(&EG(persistent_list), connection->hash_key);
}
else {
php_oci_connection_close(connection);
OCI_G(num_persistent)--;
}
}
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CONNECT_P_DTOR_CLOSE_ENABLED()) {
DTRACE_OCI8_CONNECT_P_DTOR_CLOSE(connection);
}
#endif /* HAVE_OCI8_DTRACE */
} 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 artificially bump up the refcount and decremented
* only at request shutdown.
*/
php_oci_connection_release(connection);
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CONNECT_P_DTOR_RELEASE_ENABLED()) {
DTRACE_OCI8_CONNECT_P_DTOR_RELEASE(connection);
}
#endif /* HAVE_OCI8_DTRACE */
}
}
/* }}} */
/* {{{ php_oci_statement_list_dtor()
*
* Statement destructor
*/
static void php_oci_statement_list_dtor(zend_resource *entry)
{
php_oci_statement *statement = (php_oci_statement *)entry->ptr;
php_oci_statement_free(statement);
}
/* }}} */
/* {{{ php_oci_descriptor_list_dtor()
*
* Descriptor destructor
*/
static void php_oci_descriptor_list_dtor(zend_resource *entry)
{
php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
php_oci_lob_free(descriptor);
}
/* }}} */
/* {{{ php_oci_collection_list_dtor()
*
* Collection destructor
*/
static void php_oci_collection_list_dtor(zend_resource *entry)
{
php_oci_collection *collection = (php_oci_collection *)entry->ptr;
php_oci_collection_close(collection);
}
/* }}} */
/* }}} */
/* {{{ Hash Destructors */
/* {{{ php_oci_define_hash_dtor()
*
* Define hash destructor
*/
void php_oci_define_hash_dtor(zval *data)
{
php_oci_define *define = (php_oci_define *) Z_PTR_P(data);
if (define->name) {
efree(define->name);
define->name = NULL;
}
zval_ptr_dtor(&define->val);
efree(define);
}
/* }}} */
/* {{{ php_oci_bind_hash_dtor()
*
* Bind hash destructor
*/
void php_oci_bind_hash_dtor(zval *data)
{
php_oci_bind *bind = (php_oci_bind *) Z_PTR_P(data);
if (!Z_ISUNDEF(bind->val)) {
zval_ptr_dtor(&bind->val);
ZVAL_UNDEF(&bind->val);
}
if (bind->array.elements) {
efree(bind->array.elements);
bind->array.elements = NULL;
}
if (bind->array.element_lengths) {
efree(bind->array.element_lengths);
bind->array.element_lengths = NULL;
}
if (bind->array.indicators) {
efree(bind->array.indicators);
bind->array.indicators = NULL;
}
efree(bind);
}
/* }}} */
/* {{{ php_oci_column_hash_dtor()
*
* Column hash destructor
*/
void php_oci_column_hash_dtor(zval *data)
{
php_oci_out_column *column = (php_oci_out_column *) Z_PTR_P(data);
if (column->stmtid) {
zend_list_close(column->stmtid);
}
if (column->descid) {
if (GC_REFCOUNT(column->descid) == 1)
zend_list_close(column->descid);
else {
GC_DELREF(column->descid);
}
}
if (column->data) {
efree(column->data);
}
if (column->name) {
efree(column->name);
}
efree(column);
}
/* }}} */
/* {{{ php_oci_descriptor_flush_hash_dtor()
*
* Flush descriptors on commit
*/
void php_oci_descriptor_flush_hash_dtor(zval *data)
{
php_oci_descriptor *descriptor = (php_oci_descriptor *) Z_PTR_P(data);
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);
descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
}
data = NULL;
}
/* }}} */
/* }}} */
/* {{{ php_oci_connection_descriptors_free()
*
* Free descriptors for a connection
*/
void php_oci_connection_descriptors_free(php_oci_connection *connection)
{
zend_hash_destroy(connection->descriptors);
efree(connection->descriptors);
connection->descriptors = NULL;
connection->descriptor_count = 0;
}
/* }}} */
/* {{{ php_oci_error()
*
* Fetch & print out error message if we get an error
* Returns an Oracle error number
*/
sb4 php_oci_error(OCIError *err_p, sword errstatus)
{
text errbuf[PHP_OCI_ERRBUF_LEN];
sb4 errcode = 0; /* Oracle error number */
switch (errstatus) {
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
if (errcode) {
php_error_docref(NULL, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", errbuf);
} else {
php_error_docref(NULL, E_WARNING, "OCI_SUCCESS_WITH_INFO: failed to fetch error message");
}
break;
case OCI_NEED_DATA:
php_error_docref(NULL, E_WARNING, "OCI_NEED_DATA");
break;
case OCI_NO_DATA:
errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
if (errcode) {
php_error_docref(NULL, E_WARNING, "%s", errbuf);
} else {
php_error_docref(NULL, E_WARNING, "OCI_NO_DATA: failed to fetch error message");
}
break;
case OCI_ERROR:
errcode = php_oci_fetch_errmsg(err_p, errbuf, sizeof(errbuf));
if (errcode) {
php_error_docref(NULL, E_WARNING, "%s", errbuf);
} else {
php_error_docref(NULL, E_WARNING, "failed to fetch error message");
}
break;
case OCI_INVALID_HANDLE:
php_error_docref(NULL, E_WARNING, "OCI_INVALID_HANDLE");
break;
case OCI_STILL_EXECUTING:
php_error_docref(NULL, E_WARNING, "OCI_STILL_EXECUTING");
break;
case OCI_CONTINUE:
php_error_docref(NULL, E_WARNING, "OCI_CONTINUE");
break;
default:
php_error_docref(NULL, E_WARNING, "Unknown OCI error code: %d", errstatus);
break;
}
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_ERROR_ENABLED()) {
DTRACE_OCI8_ERROR((int)errstatus, (long)errcode);
}
#endif /* HAVE_OCI8_DTRACE */
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, size_t error_buf_size)
{
sb4 error_code = 0;
PHP_OCI_CALL(OCIErrorGet, (error_handle, (ub4)1, NULL, &error_code, error_buf, (ub4)error_buf_size, (ub4)OCI_HTYPE_ERROR));
if (error_code) {
int err_buf_len = (int) strlen((char *)error_buf);
if (err_buf_len && error_buf[err_buf_len - 1] == '\n') {
error_buf[err_buf_len - 1] = '\0';
}
}
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)
{
sword errstatus;
*sqltext = NULL;
*error_offset = 0;
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
if (errstatus != OCI_SUCCESS) {
statement->errcode = php_oci_error(statement->err, errstatus);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
if (errstatus != OCI_SUCCESS) {
statement->errcode = php_oci_error(statement->err, errstatus);
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;
size_t username_len = 0, password_len = 0;
size_t dbname_len = 0, charset_len = 0;
zend_long session_mode = OCI_DEFAULT;
/* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
ZEND_PARSE_PARAMETERS_START(2, 5)
Z_PARAM_STRING(username, username_len)
Z_PARAM_STRING(password, password_len)
Z_PARAM_OPTIONAL
Z_PARAM_STRING(dbname, dbname_len)
Z_PARAM_STRING(charset, charset_len)
Z_PARAM_LONG(session_mode)
ZEND_PARSE_PARAMETERS_END();
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CONNECT_ENTRY_ENABLED()) {
DTRACE_OCI8_CONNECT_ENTRY(username, dbname, charset, session_mode, persistent, exclusive);
}
#endif /* HAVE_OCI8_DTRACE */
if (!charset_len) {
charset = NULL;
}
connection = php_oci_do_connect_ex(username, (int) username_len, password, (int) password_len, NULL, 0, dbname, (int) dbname_len, charset, session_mode, persistent, exclusive);
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CONNECT_RETURN_ENABLED()) {
DTRACE_OCI8_CONNECT_RETURN(connection);
}
#endif /* HAVE_OCI8_DTRACE */
if (!connection) {
RETURN_FALSE;
}
RETURN_RES(connection->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, zend_long session_mode, int persistent, int exclusive)
{
zval *zvp;
zend_resource *le;
zend_resource 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, E_WARNING, "Invalid session mode specified (" ZEND_LONG_FMT ")", 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, 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, 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, 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, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA");
return NULL;
}
}
}
/* Initialize global handles if they weren't initialized before */
if (OCI_G(env) == NULL) {
php_oci_init_global_handles();
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) {
zend_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, 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);
if (persistent) {
smart_str_appendl_ex(&hashed_details, "pc", sizeof("pc") - 1, 0);
}
smart_str_0(&hashed_details);
/* make it lowercase */
php_strtolower(ZSTR_VAL(hashed_details.s), ZSTR_LEN(hashed_details.s));
if (!exclusive && !new_password) {
zend_bool found = 0;
if (persistent && ((zvp = zend_hash_find(&EG(persistent_list), hashed_details.s))) != NULL) {
zend_resource *le = Z_RES_P(zvp);
found = 1;
/* found */
if (le->type == le_pconnection) {
connection = (php_oci_connection *)le->ptr;
}
} else if (!persistent && ((zvp = zend_hash_find(&EG(regular_list), hashed_details.s)) != NULL)) {
le = Z_RES_P(zvp);
found = 1;
if (le->type == le_index_ptr) {
zend_resource *ptr;
ptr = (zend_resource *) le->ptr;
if (ptr && (ptr->type == le_connection)) {
connection = (php_oci_connection *)ptr->ptr;
}
}
}
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CONNECT_LOOKUP_ENABLED()) {
DTRACE_OCI8_CONNECT_LOOKUP(connection, connection && connection->is_stub ? 1 : 0);
}
#endif /* HAVE_OCI8_DTRACE */
/* 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, (int) session_mode)) {
smart_str_free(&hashed_details);
zend_hash_del(&EG(persistent_list), connection->hash_key);
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) {
/* 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)) {
/* 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)) {
/* server died */
} else {
php_oci_connection *tmp = (php_oci_connection *) NULL;
zval *tmp_val = (zval *) NULL;
/* okay, the connection is open and the server is still alive */
connection->used_this_request = 1;
if (connection->id) {
tmp_val = zend_hash_index_find(&EG(regular_list), connection->id->handle);
if ((tmp_val != NULL) && (Z_TYPE_P(tmp_val) == IS_RESOURCE)) {
tmp = Z_RES_VAL_P(tmp_val);
}
if ((tmp_val != NULL) && (tmp != NULL) &&
(ZSTR_LEN(tmp->hash_key) == ZSTR_LEN(hashed_details.s)) &&
(memcmp(ZSTR_VAL(tmp->hash_key), ZSTR_VAL(hashed_details.s),
ZSTR_LEN(tmp->hash_key)) == 0)) {
connection = tmp;
GC_ADDREF(connection->id);
}
} else {
PHP_OCI_REGISTER_RESOURCE(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)) {
GC_ADDREF(connection->id);
}
}
smart_str_free(&hashed_details);
return connection;
}
}
/* server died */
} else {
/* we do not ping non-persistent connections */
smart_str_free(&hashed_details);
GC_ADDREF(connection->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){
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 == connection->id->ptr) {
le->ptr = NULL;
}
zend_hash_del(&EG(persistent_list), hashed_details.s);
} 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.s);
}
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.s);
} else {
zend_hash_del(&EG(regular_list), hashed_details.s);
}
}
}
/* 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), php_oci_persistent_helper);
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, E_NOTICE, "Too many open persistent connections (" ZEND_LONG_FMT ")", 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 = zend_string_dup(hashed_details.s, 0);
connection->is_persistent = 0;
ZVAL_UNDEF(&connection->taf_callback);
#ifdef HAVE_OCI8_DTRACE
connection->client_id = NULL;
#endif
} else {
connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
if (connection == NULL) {
return NULL;
}
connection->hash_key = zend_string_dup(hashed_details.s, 1);
if (connection->hash_key == NULL) {
free(connection);
return NULL;
}
connection->is_persistent = 1;
ZVAL_UNDEF(&connection->taf_callback);
#ifdef HAVE_OCI8_DTRACE
connection->client_id = NULL;
#endif
}
} else {
connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
connection->hash_key = zend_string_dup(hashed_details.s, 0);
connection->is_persistent = 0;
ZVAL_UNDEF(&connection->taf_callback);
#ifdef HAVE_OCI8_DTRACE
connection->client_id = NULL;
#endif
}
/* {{{ 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))==NULL)
{
php_oci_connection_close(connection);
smart_str_free(&hashed_details);
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(&hashed_details);
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, (int) session_mode)) {
php_oci_connection_close(connection);
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, (int) session_mode)) {
php_oci_connection_close(connection);
return NULL;
}
}
/* Mark it as open */
connection->is_open = 1;
/* add to the appropriate hash */
if (connection->is_persistent) {
#if PHP_VERSION_ID < 70300
new_le.ptr = connection;
new_le.type = le_pconnection;
#endif
connection->used_this_request = 1;
PHP_OCI_REGISTER_RESOURCE(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)) {
GC_ADDREF(connection->id);
}
#if PHP_VERSION_ID < 70300
zend_hash_update_mem(&EG(persistent_list), connection->hash_key, (void *)&new_le, sizeof(zend_resource));
#else
zend_register_persistent_resource_ex(connection->hash_key, connection, le_pconnection);
#endif
OCI_G(num_persistent)++;
OCI_G(num_links)++;
} else if (!exclusive) {
PHP_OCI_REGISTER_RESOURCE(connection, le_connection);
new_le.ptr = connection->id;
new_le.type = le_index_ptr;
zend_hash_update_mem(&EG(regular_list), connection->hash_key, (void *)&new_le, sizeof(zend_resource));
OCI_G(num_links)++;
} else {
PHP_OCI_REGISTER_RESOURCE(connection, le_connection);
OCI_G(num_links)++;
}
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CONNECT_TYPE_ENABLED()) {
DTRACE_OCI8_CONNECT_TYPE(connection->is_persistent ? 1 : 0, exclusive ? 1 : 0, connection, OCI_G(num_persistent), OCI_G(num_links));
}
#endif /* HAVE_OCI8_DTRACE */
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)
{
sword errstatus;
#if (!((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))))
char version[256];
#endif
OCI_G(errcode) = 0; /* assume ping is successful */
/* 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(errstatus, OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
#else
/* use good old OCIServerVersion() */
PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX));
#endif
if (errstatus == 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;
}
OCI_G(errcode) = error_code;
}
return 0;
}
/* }}} */
/* {{{ php_oci_connection_status()
*
* Check connection status (pre-ping check)
*/
static int php_oci_connection_status(php_oci_connection *connection)
{
ub4 ss = OCI_SERVER_NOT_CONNECTED;
sword errstatus;
/* get OCI_ATTR_SERVER_STATUS */
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err)));
if (errstatus == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) {
return 1;
}
/* ignore errors here, just return failure */
return 0;
}
/* }}} */
/* {{{ php_oci_connection_rollback()
*
* Rollback connection
*/
int php_oci_connection_rollback(php_oci_connection *connection)
{
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
connection->rb_on_disconnect = 0;
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
return 0;
}
/* }}} */
/* {{{ php_oci_connection_commit()
*
* Commit connection
*/
int php_oci_connection_commit(php_oci_connection *connection)
{
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
connection->rb_on_disconnect = 0;
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
return 0;
}
/* }}} */
/* {{{ php_oci_connection_close()
*
* Close the connection and free all its resources
*/
static int php_oci_connection_close(php_oci_connection *connection)
{
int result = 0;
zend_bool in_call_save = OCI_G(in_call);
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CONNECTION_CLOSE_ENABLED()) {
DTRACE_OCI8_CONNECTION_CLOSE(connection);
}
#endif /* HAVE_OCI8_DTRACE */
if (!connection->is_stub) {
/* Release resources associated with connection */
php_oci_connection_release(connection);
}
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);
connection->private_spool = NULL;
}
if (GC_REFCOUNT(connection->hash_key) >= 2) {
zend_hash_del(&EG(regular_list), connection->hash_key);
}
if (connection->hash_key) {
pefree(connection->hash_key, connection->is_persistent);
connection->hash_key = NULL;
}
#ifdef HAVE_OCI8_DTRACE
if (connection->client_id) {
pefree(connection->client_id, connection->is_persistent);
connection->client_id = NULL;
}
#endif /* HAVE_OCI8_DTRACE */
if (!Z_ISUNDEF(connection->taf_callback)) {
/* If it's NULL, then its value should be freed already */
if (!Z_ISNULL(connection->taf_callback)) {
zval_ptr_dtor(&connection->taf_callback);
}
ZVAL_UNDEF(&connection->taf_callback);
}
pefree(connection, connection->is_persistent);
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)
{
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) {
php_oci_connection_descriptors_free(connection);
}
if (connection->svc) {
/* rollback outstanding transactions */
if (connection->rb_on_disconnect) {
if (php_oci_connection_rollback(connection)) {
/* 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->rb_on_disconnect = 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;
#ifdef HAVE_OCI8_DTRACE
if (connection->client_id) {
pefree(connection->client_id, connection->is_persistent);
connection->client_id = NULL;
}
#endif /* HAVE_OCI8_DTRACE */
}
/* Always set id to null, so next time a new resource is being registered. */
connection->id = 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)
{
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = 0; /* retain backwards compat with OCI8 1.4 */
connection->passwd_changed = 1;
return 0;
}
/* }}} */
/* {{{ php_oci_client_get_version()
*
* Get Oracle client library version
*/
void php_oci_client_get_version(char *version, size_t version_size)
{
#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIClientVersion only available 10.2 onwards */
sword major_version = 0;
sword minor_version = 0;
sword update_num = 0;
sword patch_num = 0;
sword port_update_num = 0;
PHP_OCI_CALL(OCIClientVersion, (&major_version, &minor_version, &update_num, &patch_num, &port_update_num));
snprintf(version, version_size, "%d.%d.%d.%d.%d", major_version, minor_version, update_num, patch_num, port_update_num);
#else
memcpy(version, "Unknown", sizeof("Unknown"));
#endif
}
/* }}} */
/* {{{ php_oci_server_get_version()
*
* Get Oracle server version
*/
int php_oci_server_get_version(php_oci_connection *connection, char *version, size_t version_size)
{
sword errstatus;
PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, connection->err, (text *)version, (ub4) version_size, OCI_HTYPE_SVCCTX));
if (errstatus != OCI_SUCCESS) {
connection->errcode = php_oci_error(connection->err, errstatus);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
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)
{
php_oci_descriptor *descriptor;
ub4 lob_length;
int column_size;
char *lob_buffer = (char *)0;
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_RES(value, column->stmtid);
GC_ADDREF(column->stmtid);
} else if (column->is_descr) {
if (column->data_type != SQLT_RDD) {
/* reset descriptor's length */
descriptor = (php_oci_descriptor *) column->descid->ptr;
if (!descriptor) {
php_error_docref(NULL, E_WARNING, "Unable to find LOB descriptor #%d", column->descid->handle);
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 */
if (column->chunk_size)
descriptor->chunk_size = column->chunk_size;
lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, &lob_buffer, &lob_length);
if (descriptor->chunk_size) /* Cache the chunk_size to avoid recalling OCILobGetChunkSize */
column->chunk_size = descriptor->chunk_size;
php_oci_temp_lob_close(descriptor);
if (lob_fetch_status) {
ZVAL_FALSE(value);
return 1;
} else {
if (lob_length > 0) {
ZVAL_STRINGL(value, lob_buffer, lob_length);
} else {
ZVAL_EMPTY_STRING(value);
}
if (lob_buffer)
efree(lob_buffer);
return 0;
}
} else {
/* return the locator */
object_init_ex(value, oci_lob_class_entry_ptr);
add_property_resource(value, "descriptor", column->descid);
GC_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);
}
return 0;
}
/* }}} */
/* {{{ php_oci_fetch_row()
*
* Fetch the next row from the given statement
* Has logic for Oracle 12c Implicit Result Sets
*/
void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
{
zval *z_statement, *array;
zval *placeholder = (zval*) NULL;
/* zend_array *temp_array = (zend_array *) NULL;*/
php_oci_statement *statement; /* statement that will be fetched from */
#if (OCI_MAJOR_VERSION >= 12)
php_oci_statement *invokedstatement; /* statement this function was invoked with */
#endif /* OCI_MAJOR_VERSION */
php_oci_out_column *column;
ub4 nrows = 1;
int i;
zend_long fetch_mode = 0;
if (expected_args > 2) {
/* only for ocifetchinto BC */
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_RESOURCE(z_statement)
Z_PARAM_ZVAL(array)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(fetch_mode)
ZEND_PARSE_PARAMETERS_END();
if (ZEND_NUM_ARGS() == 2) {
fetch_mode = mode;
}
if (Z_ISREF_P(array))
placeholder = Z_REFVAL_P(array);
else
placeholder = array;
} else if (expected_args == 2) {
/* only for oci_fetch_array() */
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_RESOURCE(z_statement)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(fetch_mode)
ZEND_PARSE_PARAMETERS_END();
if (ZEND_NUM_ARGS() == 1) {
fetch_mode = mode;
}
} else {
/* for all oci_fetch_*() */
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_RESOURCE(z_statement)
ZEND_PARSE_PARAMETERS_END();
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;
}
}
#if (OCI_MAJOR_VERSION < 12)
PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
if (php_oci_statement_fetch(statement, nrows)) {
RETURN_FALSE; /* end of fetch */
}
#else /* OCI_MAJOR_VERSION */
PHP_OCI_ZVAL_TO_STATEMENT(z_statement, invokedstatement);
if (invokedstatement->impres_flag == PHP_OCI_IMPRES_NO_CHILDREN ||
invokedstatement->impres_flag == PHP_OCI_IMPRES_IS_CHILD) {
/* Already know there are no Implicit Result Sets */
statement = invokedstatement;
} else if (invokedstatement->impres_flag == PHP_OCI_IMPRES_HAS_CHILDREN) {
/* Previously saw an Implicit Result Set in an earlier invocation of php_oci_fetch_row */
statement = (php_oci_statement *)invokedstatement->impres_child_stmt;
} else {
sword errstatus;
/* Check for an Implicit Result Set on this statement handle */
PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)invokedstatement->stmt, OCI_HTYPE_STMT,
(dvoid *) &invokedstatement->impres_count,
(ub4 *)NULL, OCI_ATTR_IMPLICIT_RESULT_COUNT, invokedstatement->err));
if (errstatus) {
RETURN_FALSE;
}
if (invokedstatement->impres_count > 0) {
/* Make it so the fetch occurs on the first Implicit Result Set */
statement = php_oci_get_implicit_resultset(invokedstatement);
if (!statement || php_oci_statement_execute(statement, (ub4)OCI_DEFAULT))
RETURN_FALSE;
invokedstatement->impres_count--;
invokedstatement->impres_child_stmt = (struct php_oci_statement *)statement;
invokedstatement->impres_flag = PHP_OCI_IMPRES_HAS_CHILDREN;
} else {
statement = invokedstatement; /* didn't find Implicit Result Sets */
invokedstatement->impres_flag = PHP_OCI_IMPRES_NO_CHILDREN; /* Don't bother checking again */
}
}
if (php_oci_statement_fetch(statement, nrows)) {
/* End of fetch */
if (invokedstatement->impres_count > 0) {
/* Check next Implicit Result Set */
statement = php_oci_get_implicit_resultset(invokedstatement);
if (!statement || php_oci_statement_execute(statement, (ub4)OCI_DEFAULT))
RETURN_FALSE;
invokedstatement->impres_count--;
invokedstatement->impres_child_stmt = (struct php_oci_statement *)statement;
if (php_oci_statement_fetch(statement, nrows)) {
/* End of all fetches */
RETURN_FALSE;
}
} else {
RETURN_FALSE;
}
}
#endif /* OCI_MAJOR_VERSION */
if (placeholder == NULL) {
placeholder = return_value;
} else {
zval_ptr_dtor(placeholder);
}
array_init(placeholder);
for (i = 0; i < statement->ncolumns; i++) {
column = php_oci_statement_get_column(statement, i + 1, NULL, 0);
if (column == NULL) {
continue;
}
if ((column->indicator == -1) && ((fetch_mode & PHP_OCI_RETURN_NULLS) == 0)) {
continue;
}
if (!(column->indicator == -1)) {
zval element;
php_oci_column_to_zval(column, &element, (int) fetch_mode);
if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
add_index_zval(placeholder, i, &element);
}
if (fetch_mode & PHP_OCI_ASSOC) {
if (fetch_mode & PHP_OCI_NUM) {
Z_TRY_ADDREF_P(&element);
}
add_assoc_zval(placeholder, column->name, &element);
}
} else {
if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
add_index_null(placeholder, i);
}
if (fetch_mode & PHP_OCI_ASSOC) {
add_assoc_null(placeholder, column->name);
}
}
}
if (expected_args > 2) {
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(zval *zv)
{
zend_resource *le = Z_RES_P(zv);
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;
/* Remove TAF callback function as it's bound to current request */
if (connection->used_this_request && !Z_ISUNDEF(connection->taf_callback) && !Z_ISNULL(connection->taf_callback)) {
php_oci_unregister_taf_callback(connection);
}
if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CONNECT_EXPIRY_ENABLED()) {
DTRACE_OCI8_CONNECT_EXPIRY(connection, connection->is_stub ? 1 : 0, (long)connection->idle_expiry, (long)timestamp);
}
#endif /* HAVE_OCI8_DTRACE */
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, zend_string *hash_key, int charsetid)
{
php_oci_spool *session_pool = NULL;
zend_bool iserror = 0;
ub4 poolmode = OCI_DEFAULT; /* Mode to be passed to OCISessionPoolCreate */
OCIAuthInfo *spoolAuth = NULL;
sword errstatus;
/* Allocate sessionpool out of persistent memory */
session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
if (session_pool == NULL) {
iserror = 1;
goto exit_create_spool;
}
/* Populate key if passed */
if (hash_key && (ZSTR_LEN(hash_key) > 0)) {
session_pool->spool_hash_key = zend_string_dup(hash_key, 1);
if (session_pool->spool_hash_key == NULL) {
iserror = 1;
goto exit_create_spool;
}
}
/* Create the session pool's env */
if (!(session_pool->env = php_oci_create_env(charsetid))) {
iserror = 1;
goto exit_create_spool;
}
/* Allocate the pool handle */
PHP_OCI_CALL_RETURN(errstatus, OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
if (errstatus != OCI_SUCCESS) {
OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
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(errstatus, OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0));
if (errstatus != OCI_SUCCESS) {
OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
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(errstatus, OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL));
if (errstatus != OCI_SUCCESS) {
OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
iserror = 1;
goto exit_create_spool;
}
/* }}} */
/* {{{ Set the edition attribute on the auth handle */
if (OCI_G(edition)) {
PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) OCI_G(edition), (ub4)(strlen(OCI_G(edition))), (ub4)OCI_ATTR_EDITION, OCI_G(err)));
if (errstatus != OCI_SUCCESS) {
OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
iserror = 1;
goto exit_create_spool;
}
}
/* }}} */
/* {{{ Set the driver name attribute on the auth handle */
PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
if (errstatus != OCI_SUCCESS) {
OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
iserror = 1;
goto exit_create_spool;
}
/* }}} */
/* {{{ Set the auth handle on the session pool */
PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, ((dvoid *) (session_pool->poolh),(ub4) OCI_HTYPE_SPOOL, (dvoid *) spoolAuth, (ub4)0, (ub4)OCI_ATTR_SPOOL_AUTH, OCI_G(err)));
if (errstatus != OCI_SUCCESS) {
OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
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(errstatus, OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode));
if (errstatus != OCI_SUCCESS) {
OCI_G(errcode) = php_oci_error(OCI_G(err), errstatus);
iserror = 1;
}
exit_create_spool:
if (iserror && session_pool) {
php_oci_spool_close(session_pool);
session_pool = NULL;
}
if (spoolAuth) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO));
}
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_SESSPOOL_CREATE_ENABLED()) {
DTRACE_OCI8_SESSPOOL_CREATE(session_pool);
}
#endif /* HAVE_OCI8_DTRACE */
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)
{
smart_str spool_hashed_details = {0};
php_oci_spool *session_pool = NULL;
#if PHP_VERSION_ID < 70300
zend_resource spool_le = {{0}};
#endif
zend_resource *spool_out_le = NULL;
zend_bool iserror = 0;
zval *spool_out_zv = NULL;
/* {{{ 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) {
zend_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(ZSTR_VAL(spool_hashed_details.s), ZSTR_LEN(spool_hashed_details.s));
/* }}} */
spool_out_zv = zend_hash_find(&EG(persistent_list), spool_hashed_details.s);
if (spool_out_zv != NULL) {
spool_out_le = Z_RES_P(spool_out_zv);
}
if (spool_out_le == NULL) {
session_pool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, spool_hashed_details.s, charsetid);
if (session_pool == NULL) {
iserror = 1;
goto exit_get_spool;
}
#if PHP_VERSION_ID < 70300
spool_le.ptr = session_pool;
spool_le.type = le_psessionpool;
PHP_OCI_REGISTER_RESOURCE(session_pool, le_psessionpool);
zend_hash_update_mem(&EG(persistent_list), session_pool->spool_hash_key, (void *)&spool_le, sizeof(zend_resource));
#else
zend_register_persistent_resource_ex(session_pool->spool_hash_key, session_pool, le_psessionpool);
#endif
} else if (spool_out_le->type == le_psessionpool &&
ZSTR_LEN(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == ZSTR_LEN(spool_hashed_details.s) &&
memcmp(ZSTR_VAL(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key), ZSTR_VAL(spool_hashed_details.s), ZSTR_LEN(spool_hashed_details.s)) == 0) {
/* retrieve the cached session pool */
session_pool = (php_oci_spool *)(spool_out_le->ptr);
}
exit_get_spool:
smart_str_free(&spool_hashed_details);
if (iserror && session_pool) {
php_oci_spool_close(session_pool);
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)
{
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) {
sb4 ora_error_code = 0;
text ora_msg_buf[PHP_OCI_ERRBUF_LEN]; /* Use traditional smaller size: non-PL/SQL errors should fit and it keeps the stack smaller */
#ifdef HAVE_OCI_INSTANT_CLIENT
php_error_docref(NULL, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
#else
php_error_docref(NULL, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
#endif
if (retenv
&& OCIErrorGet(retenv, (ub4)1, NULL, &ora_error_code, ora_msg_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ENV) == OCI_SUCCESS
&& *ora_msg_buf) {
php_error_docref(NULL, E_WARNING, "%s", ora_msg_buf);
}
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)
{
ub4 statement_cache_size = 0;
if (OCI_G(statement_cache_size) > 0) {
if (OCI_G(statement_cache_size) > SB4MAXVAL)
statement_cache_size = (ub4) SB4MAXVAL;
else
statement_cache_size = (ub4) OCI_G(statement_cache_size);
}
/* Create the OCI environment separate for each connection */
if (!(connection->env = php_oci_create_env(connection->charset))) {
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
/* 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)) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode));
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));
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)
{
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 = 0;
if (OCI_G(statement_cache_size) > 0) {
if (OCI_G(statement_cache_size) > SB4MAXVAL)
statement_cache_size = (ub4) SB4MAXVAL;
else
statement_cache_size = (ub4) OCI_G(statement_cache_size);
}
/* 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, connection->charset))) {
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;
}
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_SESSPOOL_TYPE_ENABLED()) {
DTRACE_OCI8_SESSPOOL_TYPE(session_pool ? 1 : 0, session_pool ? session_pool : connection->private_spool);
}
#endif /* HAVE_OCI8_DTRACE */
/* 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));
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));
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));
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));
return 1;
}
#endif
}
/* }}} */
/* {{{ Debug statements */
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_SESSPOOL_STATS_ENABLED()) {
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 */
DTRACE_OCI8_SESSPOOL_STATS(numfree, numbusy, numopen);
}
#endif /* HAVE_OCI8_DTRACE */
/* }}} */
/* 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));
/* 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));
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)) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode));
return 1;
}
} else if ((*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp))) {
if (php_oci_connection_ping(connection)) {
/* 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));
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_resource *entry)
{
php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
if (session_pool) {
php_oci_spool_close(session_pool);
}
return;
}
/* }}} */
/* {{{ php_oci_spool_close()
*
* Destroys the OCI Session Pool
*/
static void php_oci_spool_close(php_oci_spool *session_pool)
{
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)
{
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;
}
/* }}} */
/* {{{ php_oci_dtrace_check_connection()
*
* DTrace output for connections that may have become invalid and marked for reopening
*/
void php_oci_dtrace_check_connection(php_oci_connection *connection, sb4 errcode, ub4 serverStatus)
{
#ifdef HAVE_OCI8_DTRACE
if (DTRACE_OCI8_CHECK_CONNECTION_ENABLED()) {
DTRACE_OCI8_CHECK_CONNECTION(connection, connection->client_id, connection->is_open ? 1 : 0, (long)errcode, (unsigned long)serverStatus);
}
#endif /* HAVE_OCI8_DTRACE */
}
/* }}} */
#endif /* HAVE_OCI8 */