summaryrefslogtreecommitdiff
path: root/ext/oci8
diff options
context:
space:
mode:
authorChristopher Jones <sixd@php.net>2008-02-16 01:20:22 +0000
committerChristopher Jones <sixd@php.net>2008-02-16 01:20:22 +0000
commit07a79208b61e4b5b168c1fd61630f311b5147ca7 (patch)
treee8f0f419bb1fb0c00a09f1b62b5f817799e626b0 /ext/oci8
parent2f62d300f7978b184c4a4144805f8562d9c7a7ba (diff)
downloadphp-git-07a79208b61e4b5b168c1fd61630f311b5147ca7.tar.gz
Streamlined code and incorporated review comments. Respect oci8.ping_interval when oci_pconnect called multiple times in a script. Changed OCIServerVersion to OCIPing (http://pecl.php.net/bugs/bug.php?id=11976)
Diffstat (limited to 'ext/oci8')
-rw-r--r--ext/oci8/oci8.c386
-rw-r--r--ext/oci8/php_oci8_int.h2
-rw-r--r--ext/oci8/tests/debug.phpt1
-rw-r--r--ext/oci8/tests/details.inc5
4 files changed, 216 insertions, 178 deletions
diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c
index 17ae75ca0d..54f5266d0d 100644
--- a/ext/oci8/oci8.c
+++ b/ext/oci8/oci8.c
@@ -67,7 +67,7 @@ int le_pconnection;
int le_statement;
int le_descriptor;
int le_psessionpool;
-#ifdef PHP_OCI8_HAVE_COLLECTIONS
+#ifdef PHP_OCI8_HAVE_COLLECTIONS
int le_collection;
#endif
@@ -97,7 +97,7 @@ static void php_oci_pconnection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static void php_oci_statement_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static void php_oci_descriptor_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC);
-#ifdef PHP_OCI8_HAVE_COLLECTIONS
+#ifdef PHP_OCI8_HAVE_COLLECTIONS
static void php_oci_collection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
#endif
@@ -380,7 +380,7 @@ zend_function_entry php_oci_lob_class_functions[] = {
};
#ifdef PHP_OCI8_HAVE_COLLECTIONS
-static
+static
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
/* This "if" allows PECL builds from this file to be portable to older PHP releases */
const
@@ -439,7 +439,7 @@ PHP_INI_END()
*/
/* {{{ php_oci_init_global_handles()
- Initialize global handles only when they are needed
+ Initialize global handles only when they are needed
*/
static void php_oci_init_global_handles(TSRMLS_D)
{
@@ -684,10 +684,10 @@ PHP_RSHUTDOWN_FUNCTION(oci)
{
#ifdef ZTS
zend_hash_apply_with_argument(&EG(regular_list), (apply_func_arg_t) php_oci_list_helper, (void *)le_descriptor TSRMLS_CC);
-#ifdef PHP_OCI8_HAVE_COLLECTIONS
+#ifdef PHP_OCI8_HAVE_COLLECTIONS
zend_hash_apply_with_argument(&EG(regular_list), (apply_func_arg_t) php_oci_list_helper, (void *)le_collection TSRMLS_CC);
#endif
- while (OCI_G(num_statements)) {
+ while (OCI_G(num_statements)) {
zend_hash_apply_with_argument(&EG(regular_list), (apply_func_arg_t) php_oci_list_helper, (void *)le_statement TSRMLS_CC);
}
#endif
@@ -721,8 +721,8 @@ PHP_MINFO_FUNCTION(oci)
php_info_print_table_row(2, "Oracle Version", PHP_OCI8_VERSION );
php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DIR );
php_info_print_table_row(2, "Libraries Used", PHP_OCI8_SHARED_LIBADD );
-#else
-# if defined(HAVE_OCI_INSTANT_CLIENT) && defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
+#else
+# if defined(HAVE_OCI_INSTANT_CLIENT) && defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
php_info_print_table_row(2, "Oracle Instant Client Version", buf);
# endif
@@ -782,7 +782,7 @@ static void php_oci_descriptor_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
php_oci_lob_free(descriptor TSRMLS_CC);
} /* }}} */
-#ifdef PHP_OCI8_HAVE_COLLECTIONS
+#ifdef PHP_OCI8_HAVE_COLLECTIONS
/* {{{ php_oci_collection_list_dtor()
Collection destructor */
static void php_oci_collection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
@@ -832,7 +832,7 @@ void php_oci_bind_hash_dtor(void *data)
/*
if (bind->array.retcodes) {
efree(bind->array.retcodes);
- }
+ }
*/
zval_ptr_dtor(&bind->zval);
@@ -920,7 +920,7 @@ sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC)
case OCI_NO_DATA:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NO_DATA");
break;
- case OCI_ERROR:
+ case OCI_ERROR:
errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
if (errbuf) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
@@ -981,14 +981,14 @@ int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, u
PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (text *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
- if (statement->errcode != OCI_SUCCESS) {
+ if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
return 1;
}
PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
- if (statement->errcode != OCI_SUCCESS) {
+ if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
return 1;
}
@@ -996,7 +996,7 @@ int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, u
} /* }}} */
#endif
-/* {{{ php_oci_do_connect()
+/* {{{ php_oci_do_connect()
Connect wrapper */
void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
{
@@ -1010,7 +1010,7 @@ void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclus
/* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ssl", &username, &username_len, &password, &password_len, &dbname, &dbname_len, &charset, &charset_len, &session_mode) == FAILURE) {
return;
- }
+ }
if (!charset_len) {
charset = NULL;
@@ -1027,7 +1027,7 @@ void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclus
/* {{{ php_oci_do_connect_ex()
* The real connect function. Allocates all the resources needed, establishes the connection and returns the result handle (or NULL) */
-php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC)
+php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC)
{
zend_rsrc_list_entry *le;
zend_rsrc_list_entry new_le;
@@ -1036,7 +1036,6 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
time_t timestamp;
php_oci_spool *session_pool = NULL;
zend_bool use_spool = 1; /* Default is to use client-side session pool */
- zend_bool connection_cached = 0;
#if HAVE_OCI_ENV_NLS_CREATE
ub2 charsetid = 0;
@@ -1072,7 +1071,7 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
/* We cannot use the new session create logic (OCISessionGet from
* client-side session pool) when privileged connect or password
* change is attempted. TODO: Remove this once OCI provides
- * capability
+ * capability
*/
if ((session_mode==OCI_SYSOPER) || (session_mode == OCI_SYSDBA) || (new_password_len)) {
use_spool = 0;
@@ -1155,24 +1154,48 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
}
}
}
- connection_cached = connection && connection->is_stub;
- /* If connection is stub, skip the below 'if' that deals with a
- * real connection. A connection is a stub if it is only a cached
- * structure and the real connection is released to its underlying
- * private session pool.
+ /* Debug statements {{{ */
+ if (OCI_G(debug_mode)) {
+ if (connection && connection->is_stub) {
+ php_printf ("OCI8 DEBUG L1: Got a cached stub: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ }
+ else if (connection) {
+ php_printf ("OCI8 DEBUG L1: Got a cached connection: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ }
+ else {
+ php_printf ("OCI8 DEBUG L1: Got NO cached connection at (%s:%d) \n", __FILE__, __LINE__);
+ }
+ } /* }}} */
+
+ /* If we got a pconnection stub, then 'load'(OCISessionGet) the
+ * real connection from its private spool
+ * A connection is a stub if it is only a cached structure and the
+ * real connection is released to its underlying private session pool.
+ * We currently do not have stub support for non-persistent conns.
+ *
+ * TODO: put in negative code for non-persistent stubs
*/
- if (connection && !connection_cached) {
+ if (connection && connection->is_persistent && connection->is_stub) {
+ if (php_oci_create_session(connection, NULL, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
+ smart_str_free_ex(&hashed_details, 0);
+ zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
+
+ return NULL;
+ }
+ }
+
+ 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
+ * 3) ping it if needed
* */
if (php_oci_connection_status(connection TSRMLS_CC)) {
- /* only ping if:
+ /* 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"
* */
@@ -1212,7 +1235,7 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
connection = NULL;
goto open;
}
- } else if (found && !connection) {
+ } else if (found) {
/* found something, but it's not a connection, delete it */
if (persistent) {
zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
@@ -1226,59 +1249,51 @@ open:
/* Check if we have reached max_persistent. If so, try to remove a few
* timeout out connections. As last resort, return a non-persistent conn
*/
- if (!connection_cached) {
- if (persistent) {
- zend_bool alloc_non_persistent = 0;
-
- if (OCI_G(max_persistent)!=-1 && OCI_G(num_persistent)>=OCI_G(max_persistent)) {
- /* try to find an idle connection and kill it */
- zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
-
- if (OCI_G(max_persistent)!=-1 && OCI_G(num_persistent)>=OCI_G(max_persistent)) {
- /* all persistent connactions are in use, fallback to non-persistent connection creation */
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Too many open persistent connections (%ld)", OCI_G(num_persistent));
- alloc_non_persistent = 1;
- }
- }
+ if (persistent) {
+ zend_bool alloc_non_persistent = 0;
- if (alloc_non_persistent) {
- connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
- connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
- connection->is_persistent = 0;
- } else {
- connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
- connection->hash_key = zend_strndup(hashed_details.c, hashed_details.len);
- connection->is_persistent = 1;
+ if (OCI_G(max_persistent)!=-1 && OCI_G(num_persistent)>=OCI_G(max_persistent)) {
+ /* try to find an idle connection and kill it */
+ zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
+
+ if (OCI_G(max_persistent)!=-1 && OCI_G(num_persistent)>=OCI_G(max_persistent)) {
+ /* all persistent connactions are in use, fallback to non-persistent connection creation */
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Too many open persistent connections (%ld)", OCI_G(num_persistent));
+ alloc_non_persistent = 1;
}
- } else {
+ }
+
+ if (alloc_non_persistent) {
connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
connection->is_persistent = 0;
+ } else {
+ connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
+ connection->hash_key = zend_strndup(hashed_details.c, hashed_details.len);
+ connection->is_persistent = 1;
}
+ } else {
+ connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
+ connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
+ connection->is_persistent = 0;
}
/* {{{ Get the session pool that suits this connection request from the
- * persistent list. This step is only for non-persistent connections as
+ * persistent 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
+ * use shared session pool to allow for optimizations such as caching the
* physical connection (for DRCP) even when the non-persistent php connection
* is destroyed.
* TODO: Unconditionally do this once OCI provides extended OCISessionGet capability */
if (use_spool && !connection->is_persistent) {
if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang TSRMLS_CC))==NULL)
{
- if (connection_cached){
- zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
- }
- else {
- php_oci_connection_close(connection TSRMLS_CC);
- }
+ php_oci_connection_close(connection TSRMLS_CC);
smart_str_free_ex(&hashed_details, 0);
return NULL;
- }
+ }
} /* }}} */
- /* TODO: Should the following be done for stubs too? */
connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0;
if (OCI_G(ping_interval) >= 0) {
connection->next_ping = timestamp + OCI_G(ping_interval);
@@ -1303,26 +1318,14 @@ open:
/* Old session creation semantics when session pool cannot be used Eg: privileged connect/password change {{{*/
if ( !use_spool) {
if (php_oci_old_create_session(connection, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
- if (connection_cached){
- zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
- }
- else {
- php_oci_connection_close(connection TSRMLS_CC);
- }
-
+ php_oci_connection_close(connection TSRMLS_CC);
return NULL;
}
} /* }}} */
- else {
+ else {
/* create using the client-side session pool */
if (php_oci_create_session(connection, session_pool, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
- if (connection_cached){
- zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
- }
- else {
- php_oci_connection_close(connection TSRMLS_CC);
- }
-
+ php_oci_connection_close(connection TSRMLS_CC);
return NULL;
}
}
@@ -1330,44 +1333,36 @@ open:
/* mark it as open */
connection->is_open = 1;
+ /* add to the appropriate hash */
if (connection->is_persistent) {
+ new_le.ptr = connection;
+ new_le.type = le_pconnection;
connection->used_this_request = 1;
+ connection->rsrc_id = zend_list_insert(connection, le_pconnection);
+ zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
+ OCI_G(num_persistent)++;
+ } else if (!exclusive) {
+ connection->rsrc_id = zend_list_insert(connection, le_connection);
+ new_le.ptr = (void *)connection->rsrc_id;
+ new_le.type = le_index_ptr;
+ zend_hash_update(&EG(regular_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
+ OCI_G(num_links)++;
+ } else {
+ connection->rsrc_id = zend_list_insert(connection, le_connection);
+ OCI_G(num_links)++;
}
- /* If this was a cached connection stub (released to pool), create a new resource id or increase the reference count if the resource is created in this request {{{*/
- if (connection_cached) {
- php_oci_connection *tmp;
- int rsrc_type;
-
- tmp = (php_oci_connection *)zend_list_find(connection->rsrc_id, &rsrc_type);
-
- if (tmp != NULL && rsrc_type == le_pconnection && strlen(tmp->hash_key) == strlen(connection->hash_key) &&
- memcmp(tmp->hash_key, connection->hash_key, strlen(connection->hash_key)) == 0 && zend_list_addref(connection->rsrc_id) == SUCCESS) {
- /* do nothing */
- }
+ /* Debug statements {{{ */
+ if (OCI_G(debug_mode)) {
+ if (connection->is_persistent) {
+ php_printf ("OCI8 DEBUG L1: New Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ }
else {
- connection->rsrc_id = zend_list_insert(connection, le_pconnection);
+ php_printf ("OCI8 DEBUG L1: New Non-Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
}
+ php_printf ("OCI8 DEBUG L1: num_persistent=(%ld), num_links=(%ld) at (%s:%d) \n", OCI_G(num_persistent), OCI_G(num_links), __FILE__, __LINE__);
} /* }}} */
- else {
- /* "connection" was allocated in this call - add to the appropriate hash */
- if (connection->is_persistent) {
- new_le.ptr = connection;
- new_le.type = le_pconnection;
- connection->rsrc_id = zend_list_insert(connection, le_pconnection);
- zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
- OCI_G(num_persistent)++;
- } else if (!exclusive) {
- connection->rsrc_id = zend_list_insert(connection, le_connection);
- new_le.ptr = (void *)connection->rsrc_id;
- new_le.type = le_index_ptr;
- zend_hash_update(&EG(regular_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
- OCI_G(num_links)++;
- } else {
- connection->rsrc_id = zend_list_insert(connection, le_connection);
- OCI_G(num_links)++;
- }
- }
+
return connection;
}
/* }}} */
@@ -1376,20 +1371,35 @@ open:
* Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version */
static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC)
{
- /* OCIPing() crashes Oracle servers older than 10.2 */
-#if 0
+ /* 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.1 clients
+ */
+#if HAVE_OCI_LOB_READ2 /* 10.1 and greater client - OCIPing was available in 10.1 */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
#else
char version[256];
- /* use good old OCIServerVersion() by default */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerVersion, (connection->server, OCI_G(err), (text*)version, sizeof(version), OCI_HTYPE_SERVER));
+ /* use good old OCIServerVersion() */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerVersion, (connection->svc, OCI_G(err), (text*)version, sizeof(version), OCI_HTYPE_SVCCTX));
#endif
if (OCI_G(errcode) == OCI_SUCCESS) {
return 1;
}
+ else {
+ sb4 error_code = 0;
+ text tmp_buf[PHP_OCI_ERRBUF_LEN];
- /* ignore errors here, just return failure
+ /* Treat ORA-1010 as a successful Ping */
+ OCIErrorGet(OCI_G(err), (ub4)1, NULL, &error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
+ if (error_code == 1010) {
+ return 1;
+ }
+ }
+
+ /* ignore errors here, just return failure
* php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
return 0;
}
@@ -1408,7 +1418,7 @@ static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC)
return 1;
}
- /* ignore errors here, just return failure
+ /* ignore errors here, just return failure
* php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
return 0;
}
@@ -1444,7 +1454,7 @@ int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
return 0;
} /* }}} */
-/* {{{ php_oci_connection_close()
+/* {{{ php_oci_connection_close()
Close the connection and free all its resources */
static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
{
@@ -1468,7 +1478,7 @@ static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
if (!connection->is_stub && connection->svc && connection->is_open) {
/* Use OCISessionRelease for session pool connections */
- if (connection->using_spool){
+ if (connection->using_spool) {
PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) 0));
}
else {
@@ -1506,11 +1516,10 @@ static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
}
} /* }}} */
-
- /* Keep this as the last member to be freed, as there are dependencies
+ else if (connection->private_spool) {
+ /* Keep this as the last member to be freed, as there are dependencies
* (like env) on the session pool
*/
- if (connection->private_spool) {
php_oci_spool_close(connection->private_spool TSRMLS_CC);
}
@@ -1530,14 +1539,14 @@ static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
return result;
} /* }}} */
-/* {{{ php_oci_connection_release()
+/* {{{ php_oci_connection_release()
Release the connection to its session pool. This looks similar to php_oci_connection_close, but the latter is used for connections that are to be terminated. The latter was not overloaded for "release" because of too many callers */
int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
{
int result = 0;
zend_bool in_call_save = OCI_G(in_call);
- if (connection->is_stub || !connection->using_spool){
+ if (connection->is_stub || !connection->using_spool) {
return 0; /* Not our concern */
}
@@ -1558,7 +1567,7 @@ int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
}
/* Release the session */
- if(connection->svc){
+ if (connection->svc) {
PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
0, OCI_DEFAULT));
}
@@ -1572,7 +1581,7 @@ int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
connection->is_stub = 1;
/* now a stub, so don't count it in the number of connnections */
- if (!connection->is_persistent){
+ if (!connection->is_persistent) {
OCI_G(num_links)--; /* Support for "connection" stubs - future use */
}
@@ -1595,9 +1604,9 @@ int php_oci_password_change(php_oci_connection *connection, char *user, int user
return 0;
} /* }}} */
-/* {{{ php_oci_server_get_version()
+/* {{{ php_oci_server_get_version()
Get Oracle server version */
-int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC)
+int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC)
{
char version_buff[256];
@@ -1613,7 +1622,7 @@ int php_oci_server_get_version(php_oci_connection *connection, char **version TS
return 0;
} /* }}} */
-/* {{{ php_oci_column_to_zval()
+/* {{{ php_oci_column_to_zval()
Convert php_oci_out_column struct into zval */
int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSRMLS_DC)
{
@@ -1623,8 +1632,8 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSR
char *lob_buffer;
int lob_fetch_status;
- if (column->indicator == -1) { /* column is NULL */
- ZVAL_NULL(value);
+ if (column->indicator == -1) { /* column is NULL */
+ ZVAL_NULL(value);
return 0;
}
@@ -1643,7 +1652,7 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSR
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find LOB descriptor #%d", column->descid);
return 1;
}
-
+
descriptor->lob_size = -1;
descriptor->lob_current_position = 0;
descriptor->buffering = 0;
@@ -1667,7 +1676,7 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSR
}
return 0;
}
- } else {
+ } else {
/* return the locator */
object_init_ex(value, oci_lob_class_entry_ptr);
add_property_resource(value, "descriptor", column->descid);
@@ -1675,7 +1684,7 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSR
}
} else {
switch (column->retcode) {
- case 0:
+ case 0:
/* intact value */
if (column->piecewise) {
column_size = column->retlen4;
@@ -1685,7 +1694,7 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSR
break;
default:
- ZVAL_FALSE(value);
+ ZVAL_FALSE(value);
return 0;
}
@@ -1695,7 +1704,7 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSR
}
/* }}} */
-/* {{{ php_oci_fetch_row()
+/* {{{ php_oci_fetch_row()
Fetch the next row from the given statement */
void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
{
@@ -1740,7 +1749,7 @@ void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_arg
/* 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;
}
@@ -1802,7 +1811,7 @@ void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_arg
}
/* }}} */
-/* {{{ php_oci_persistent_helper()
+/* {{{ php_oci_persistent_helper()
Helper function to close/rollback persistent connections at the end of request. A return value of 1 indicates that the connection is to be destroyed */
static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
{
@@ -1854,7 +1863,7 @@ static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
}
/* Release all persistent connections at the end of the request */
- if (connection->using_spool && !connection->is_stub && php_oci_connection_release(connection TSRMLS_CC)){
+ if (connection->using_spool && !connection->is_stub && php_oci_connection_release(connection TSRMLS_CC)) {
return ZEND_HASH_APPLY_REMOVE;
}
@@ -1892,32 +1901,38 @@ static php_oci_spool *php_oci_create_spool(char *username, int username_len, cha
/* Allocate the pool handle */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
- if (OCI_G(errcode) != OCI_SUCCESS){
+ if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
}
- /* allocate the session pool error handle */
+ /* allocate the session pool error handle - This only for use in the
+ * destructor, as there is a generic bug which can free up the OCI_G(err)
+ * variable before destroying connections. We cannot use this for other
+ * roundtrip calls as there is no way the user can access this error
+ */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0));
- if (OCI_G(errcode) != OCI_SUCCESS){
+ if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
- }
+ }
- /* Create the session pool */
- PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionPoolCreate,(session_pool->env, session_pool->err, session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolnamelen, (OraText *)dbname, (ub4)dbname_len, 1, UB4MAXVAL, 1,(OraText *)0, (ub4)0, (OraText *)0,(ub4)0, OCI_DEFAULT));
+ /* Create the homogeneous session pool - We have different session pools
+ * for every different username, password, charset and dbname.
+ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 1, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, OCI_SPC_HOMOGENEOUS));
- if (OCI_G(errcode) != OCI_SUCCESS){
- php_oci_error(session_pool->err, OCI_G(errcode) TSRMLS_CC);
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
iserror = 1;
goto exit_create_spool;
}
/* Set the session pool's timeout to the oci8.persistent_timeout param */
- if (OCI_G(persistent_timeout)){
+ if (OCI_G(persistent_timeout)) {
ub4 timeout = OCI_G(persistent_timeout);
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) session_pool->poolh, (ub4) OCI_HTYPE_SPOOL, (void *) &timeout, (ub4) sizeof(timeout), (ub4) OCI_ATTR_SPOOL_TIMEOUT, OCI_G(err)));
@@ -1934,11 +1949,15 @@ exit_create_spool:
session_pool = NULL;
}
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG L1: create_spool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
+ }
+
return session_pool;
} /* }}} */
/* {{{ php_oci_get_spool()
- Get Session pool for the given dbname and charsetid from the persistent
+ Get Session pool for the given dbname and charsetid from the persistent
list. Function called for non-persistent connections.
*/
static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC)
@@ -1971,11 +1990,11 @@ static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *
php_strtolower(spool_hashed_details.c, spool_hashed_details.len);
/* }}} */
- if(zend_hash_find(&EG(persistent_list),spool_hashed_details.c, spool_hashed_details.len+1, (void **)&spool_out_le) == FAILURE ) {
+ if (zend_hash_find(&EG(persistent_list),spool_hashed_details.c, spool_hashed_details.len+1, (void **)&spool_out_le) == FAILURE ) {
session_pool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, spool_hashed_details.c, spool_hashed_details.len, charsetid TSRMLS_CC);
- if (session_pool == NULL){
+ if (session_pool == NULL) {
iserror = 1;
goto exit_get_spool;
}
@@ -1984,7 +2003,7 @@ static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *
zend_list_insert(session_pool, le_psessionpool);
zend_hash_update(&EG(persistent_list), session_pool->spool_hash_key, strlen(session_pool->spool_hash_key)+1,(void *)&spool_le, sizeof(zend_rsrc_list_entry),NULL);
}
- else if(spool_out_le->type == le_psessionpool &&
+ else if (spool_out_le->type == le_psessionpool &&
strlen(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == spool_hashed_details.len &&
memcmp(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key, spool_hashed_details.c, spool_hashed_details.len) == 0 ) {
/* retrieve the cached session pool */
@@ -2046,12 +2065,12 @@ static OCIEnv* php_oci_create_env(ub2 charsetid TSRMLS_DC)
This function is to be deprecated in future in favour of OCISessionGet which is used in php_oci_do_connect_ex */
static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
{
- if(OCI_G(debug_mode)){
- php_printf ("OCI8 DEBUG: Bypassing client-side session pool for session create");
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG: Bypassing client-side session pool for session create at (%s:%d) \n", __FILE__, __LINE__);
}
/* Create the OCI environment separate for each connection */
- if (!(connection->env = php_oci_create_env(connection->charset TSRMLS_CC))){
+ if (!(connection->env = php_oci_create_env(connection->charset TSRMLS_CC))) {
return 1;
}
@@ -2103,7 +2122,7 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
- }
+ }
}/* }}} */
/* Set the password {{{ */
@@ -2113,10 +2132,10 @@ static int php_oci_old_create_session(php_oci_connection *connection, char *dbna
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
- }
+ }
}/* }}} */
- /* Set the server handle in the service handle {{{ */
+ /* 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) {
@@ -2209,23 +2228,36 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool
/* Persistent connections have private session pools */
if (connection->is_persistent && !connection->private_spool &&
- !(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, 0, connection->charset TSRMLS_CC))){
+ !(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, 0, connection->charset TSRMLS_CC))) {
return 1;
}
actual_spool = (connection->is_persistent) ? (connection->private_spool) : (session_pool);
connection->env = actual_spool->env;
- /* Do this upfront so that connection close on an error would know that this is a session pool connection. Failure to do this would result in crashes in error scenarios */
- if (!connection->using_spool){
+ /* 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;
}
- /* The passed in "connection" can be a cached stub from plist or a freshly created. In the former case, we do not have to allocate any handles */
+ if (OCI_G(debug_mode)) {
+ if (session_pool) {
+ php_printf ("OCI8 DEBUG L1: using shared pool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
+ }
+ else {
+ php_printf ("OCI8 DEBUG L1: using private pool: (%p) at (%s:%d) \n", connection->private_spool, __FILE__, __LINE__);
+ }
+ }
+
+ /* The passed in "connection" can be a cached stub from plist or a
+ * 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 (!connection->err) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
+
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
@@ -2233,9 +2265,9 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool
}
/* {{{ 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 (!connection->authinfo) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->authinfo), OCI_HTYPE_AUTHINFO, 0, NULL));
+
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
return 1;
@@ -2278,7 +2310,7 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool
} /* }}} */
/* 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->poolnamelen, NULL, 0, NULL, NULL, NULL, OCI_SESSGET_SPOOL));
+ PHP_OCI_CALL_RETURN(OCI_G(errcode),OCISessionGet, (connection->env, OCI_G(err), &(connection->svc), (OCIAuthInfo *)connection->authinfo, (OraText *)actual_spool->poolname, (ub4)actual_spool->poolname_len, NULL, 0, NULL, NULL, NULL, OCI_SESSGET_SPOOL));
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
@@ -2287,7 +2319,7 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool
* user's password has expired, but is still usable.
* */
- if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO){
+ if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
return 1;
}
}
@@ -2310,9 +2342,9 @@ static int php_oci_create_session(php_oci_connection *connection, php_oci_spool
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))); /* }}} */
- /* Session is now taken from the session pool and attached */
+ /* Session is now taken from the session pool and attached and open */
connection->is_stub = 0;
- connection->is_attached = 1;
+ connection->is_attached = connection->is_open = 1;
return 0;
} /* }}} */
@@ -2328,38 +2360,38 @@ static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
}
return;
-}
+} /* }}} */
/* {{{ php_oci_spool_close()
Destroys the OCI Session Pool */
static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC)
{
- if (session_pool->poolh){
- PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
- (dvoid *) session_pool->err,OCI_SPD_FORCE));
+ if (session_pool->poolname_len) {
+ PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
+ (dvoid *) session_pool->err, OCI_SPD_FORCE));
}
- if (session_pool->poolh){
+ if (session_pool->poolh) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->poolh, OCI_HTYPE_SPOOL));
}
- if (session_pool->err){
+ if (session_pool->err) {
PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->err, OCI_HTYPE_ERROR));
}
- if (session_pool->env){
+ 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);
+ if (session_pool->spool_hash_key) {
+ free(session_pool->spool_hash_key);
}
free(session_pool);
} /* }}} */
#ifdef ZTS
-/* {{{ php_oci_list_helper()
+/* {{{ php_oci_list_helper()
Helper function to destroy data on thread shutdown in ZTS mode */
static int php_oci_list_helper(zend_rsrc_list_entry *le, void *le_type TSRMLS_DC)
{
diff --git a/ext/oci8/php_oci8_int.h b/ext/oci8/php_oci8_int.h
index 17df30c69e..f71d99c046 100644
--- a/ext/oci8/php_oci8_int.h
+++ b/ext/oci8/php_oci8_int.h
@@ -102,7 +102,7 @@ typedef struct { /* php_oci_spool {{{ */
OCIError* err; /* pool's error handle */
OCISPool *poolh; /* pool handle */
void* poolname; /* session pool name */
- unsigned int poolnamelen; /* length of session pool name */
+ unsigned int poolname_len; /* length of session pool name */
char *spool_hash_key; /* Hash key for session pool in plist */
} php_oci_spool; /* }}} */
diff --git a/ext/oci8/tests/debug.phpt b/ext/oci8/tests/debug.phpt
index 669c425394..2910ce3557 100644
--- a/ext/oci8/tests/debug.phpt
+++ b/ext/oci8/tests/debug.phpt
@@ -21,6 +21,7 @@ echo "Done\n";
?>
--EXPECTF--
OCI8 DEBUG: OCINlsEnvironmentVariableGet at (%s:%d)
+OCI8 DEBUG L1: Got a cached connection: (%s) at (%s:%d)
Done
OCI8 DEBUG: OCISessionRelease at (%s:%d)
OCI8 DEBUG: OCIHandleFree at (%s:%d)
diff --git a/ext/oci8/tests/details.inc b/ext/oci8/tests/details.inc
index c09212fd2a..226ab359de 100644
--- a/ext/oci8/tests/details.inc
+++ b/ext/oci8/tests/details.inc
@@ -19,6 +19,11 @@ if (false !== getenv('PHP_OCI8_TEST_DB')) {
$password = getenv('PHP_OCI8_TEST_PASS'); // Password for $user
$dbase = getenv('PHP_OCI8_TEST_DB'); // Database connection string
$test_drcp = getenv('PHP_OCI8_TEST_DRCP');
+ if (false !== $test_drcp && 0 == strcasecmp($test_drcp,'TRUE')) {
+ $test_drcp = TRUE;
+ } else {
+ $test_drcp = FALSE;
+ }
$oracle_on_localhost = getenv('PHP_OCI8_TEST_DB_ON_LOCALHOST');
if (false !== $oracle_on_localhost && 0 == strcasecmp($oracle_on_localhost,'TRUE')) {
$oracle_on_localhost = TRUE;