OCI8
-Stig Bakken, Thies C. Arntzen, Andy Sautins, David Benson, Maxim Maletsky, Harald Radi, Antony Dovgal, Andi Gutmans, Wez Furlong
+Stig Bakken, Thies C. Arntzen, Andy Sautins, David Benson, Maxim Maletsky, Harald Radi, Antony Dovgal, Andi Gutmans, Wez Furlong, Christopher Jones, Oracle Corporation
6.2.0 Important: if Oracle Database 11.1.0.6 with DRCP connections is
used, then the Oracle database patch for bug 6474441 must be
- applied (see section 6.5) or a workaround below used. Without
- this patch, "ORA-01000: maximum open cursors exceeded", "ORA-01001
- invalid cursor" or "ORA-01002 fetch out of sequence" errors may
- occur.
+ applied (see section 6.5). Without this patch, "ORA-01000:
+ maximum open cursors exceeded", "ORA-01001 invalid cursor" or
+ "ORA-01002 fetch out of sequence" errors may occur.
If the Oracle 11.1.0.6 database patch cannot be applied, one of
the following three workarounds can be used to disable statement
"ORA-56609: Usage not supported with DRCP". This is an documented
restriction of Oracle Database 11g.
-6.4.2 LOGON Triggers can be used to set session properties
+6.4.2 Closing Connections
+
+With the PHP 5.3 OCI8 Beta extension, persistent connections can now
+be closed by the user, allowing greater control over connection
+resource usage. Persistent connections will now also be closed
+automatically when there is no PHP variable referencing them, such as
+at the end of scope of a PHP user function. This will rollback any
+uncommitted transaction. These changes to persistent connections make
+them behave similarly to non-persistent connections, simplifying the
+interface, allowing for greater application consistency and
+predictability. Use oci8.old_oci_close_semantics=1 to retain the
+historical behavior.
+
+6.4.3 LOGON Triggers can be used to set session properties
The patch for Oracle Database 11.1.0.6 bug 6474441 (see section 6.5)
allows PHP applications with DRCP connection to use a database LOGON
*/
/* $Id$ */
-/* TODO
- *
- * file://localhost/www/docs/oci10/ociaahan.htm#423823 - implement lob_empty() with OCI_ATTR_LOBEMPTY
- *
- * get OCI_ATTR_CHARSET_ID attr of column to detect UTF string and multiply buffer in 4 times
- *
- */
#ifdef HAVE_CONFIG_H
#include "config.h"
*/
/* {{{ 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)
{
sword errcode;
} /* }}} */
/* {{{ php_oci_cleanup_global_handles()
- Free global handles (if they were initialized before)
-*/
+ *
+ * Free global handles (if they were initialized before)
+ */
static void php_oci_cleanup_global_handles(TSRMLS_D)
{
if (OCI_G(err)) {
} /* }}} */
/* {{{ PHP_GINIT_FUNCTION
- Zerofill globals during module init
-*/
+ *
+ * Zerofill globals during module init
+ */
#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
/* This check allows PECL builds from this file to be portable to older PHP releases */
static PHP_GINIT_FUNCTION(oci)
OCI_G(debug_mode) = 0; /* start "fresh" */
OCI_G(num_links) = OCI_G(num_persistent);
OCI_G(errcode) = 0;
- OCI_G(request_shutdown) = 0;
return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(oci)
{
/* Set this to indicate request shutdown for all further processing */
- OCI_G(request_shutdown) = 1;
#ifdef ZTS
zend_hash_apply_with_argument(&EG(regular_list), (apply_func_arg_t) php_oci_list_helper, (void *)le_descriptor TSRMLS_CC);
}
#endif
- /* 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*/
+ /* Check persistent connections and do the necessary actions if needed. If persistent_helper is
+ * unable to process a pconnection because of a refcount, the processing would happen from
+ * np-destructor which is called when refcount goes to zero - php_oci_pconnection_list_np_dtor
+ */
zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
#ifdef ZTS
#if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
#ifdef PHP_OCI8_ORACLE_VERSION
- php_info_print_table_row(2, "Oracle Version", PHP_OCI8_ORACLE_VERSION );
+ php_info_print_table_row(2, "Oracle Version", PHP_OCI8_ORACLE_VERSION);
+#endif
+#ifdef PHP_OCI8_DIR
+ php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DIR);
+#endif
+#ifdef PHP_OCI8_SHARED_LIBADD
+ php_info_print_table_row(2, "Libraries Used", PHP_OCI8_SHARED_LIBADD);
#endif
- 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)
+#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
+#endif
#endif
#ifdef HAVE_OCI8_TEMP_LOB
- php_info_print_table_row(2, "Temporary Lob support", "enabled" );
+ php_info_print_table_row(2, "Temporary Lob support", "enabled");
#else
- php_info_print_table_row(2, "Temporary Lob support", "disabled" );
+ php_info_print_table_row(2, "Temporary Lob support", "disabled");
#endif
#ifdef PHP_OCI8_HAVE_COLLECTIONS
- php_info_print_table_row(2, "Collections support", "enabled" );
+ php_info_print_table_row(2, "Collections support", "enabled");
#else
- php_info_print_table_row(2, "Collections support", "disabled" );
+ php_info_print_table_row(2, "Collections support", "disabled");
#endif
php_info_print_table_end();
/* list destructors {{{ */
/* {{{ php_oci_connection_list_dtor()
- Non-persistent connection destructor */
+ *
+ * Non-persistent connection destructor
+ */
static void php_oci_connection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
} /* }}} */
/* {{{ php_oci_pconnection_list_dtor()
- Persistent connection destructor */
+ *
+ * Persistent connection destructor
+ */
static void php_oci_pconnection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
} /* }}} */
/* {{{ 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 */
+ *
+ * Non-Persistent destructor for persistent connection - This gets invoked when
+ * the refcount of this goes to zero in the regular list
+ */
static void php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_connection *connection = (php_oci_connection *)entry->ptr;
+ zend_rsrc_list_entry *le;
- /* We currently handle only session-pool using connections. TODO: Handle non-sessionpool connections as well */
- if (connection && connection->using_spool && !connection->is_stub) {
- zend_rsrc_list_entry *le;
+ /*
+ * We cannot get connection as NULL or as a stub in this function. This is the function that
+ * turns a pconnection to a stub
+ *
+ * If oci_password_change() changed the password of a persistent connection, close the
+ * connection and remove it from the persistent connection cache. This means subsequent scripts
+ * will be prevented from being able to present the old (now invalid) password to a usable
+ * connection to the database; they must use the new password.
+ *
+ * Check for conditions that warrant removal of the hash entry
+ */
- if (!connection->is_open) {
- /* Remove the hash entry if present */
- if ((zend_hash_find(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void **) &le)== SUCCESS) && (le->type == le_pconnection) && (le->ptr == connection)) {
- zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
- }
- else {
- php_oci_connection_close(connection TSRMLS_CC);
- }
+ if (!connection->is_open ||
+ connection->passwd_changed ||
+ (PG(connection_status) & PHP_CONNECTION_TIMEOUT) ||
+ OCI_G(in_call)) {
+
+ /* Remove the hash entry if present */
+ if ((zend_hash_find(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void **) &le)== SUCCESS) && (le->type == le_pconnection) && (le->ptr == connection)) {
+ zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
+ }
+ else {
+ php_oci_connection_close(connection TSRMLS_CC);
OCI_G(num_persistent)--;
+ }
- if (OCI_G(debug_mode)) {
- php_printf ("OCI8 DEBUG L1: np_dtor cleaning up: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
- }
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG L1: np_dtor cleaning up: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
}
- else if (OCI_G(request_shutdown)){
- /* Release the connection to underlying pool - same steps
- * as the persistent helper. If we do this
- * unconditionally, we would change existing behavior
- * regarding out-of-scope pconnects. In future, we can
- * enable this through a new flag
- */
- php_oci_connection_release(connection TSRMLS_CC);
+ }
+ else {
+ /*
+ * Release the connection to underlying pool. We do this unconditionally so that
+ * out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect
+ * semantics. With the PECL OCI 1.3.x extensions, we release pconnections when oci_close
+ * takes the refcount to zero.
+ *
+ * If oci_old_close_semantics is set, we artifically bump up the refcount and decremented
+ * only at request shutdown.
+ */
+ php_oci_connection_release(connection TSRMLS_CC);
- if (OCI_G(debug_mode)) {
- php_printf ("OCI8 DEBUG L1: np_dtor releasing: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
- }
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG L1: np_dtor releasing: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
}
}
} /* }}} */
/* {{{ php_oci_statement_list_dtor()
- Statement destructor */
+ *
+ * Statement destructor
+ */
static void php_oci_statement_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_statement *statement = (php_oci_statement *)entry->ptr;
} /* }}} */
/* {{{ php_oci_descriptor_list_dtor()
- Descriptor destructor */
+ *
+ * Descriptor destructor
+ */
static void php_oci_descriptor_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
#ifdef PHP_OCI8_HAVE_COLLECTIONS
/* {{{ php_oci_collection_list_dtor()
- Collection destructor */
+ *
+ * Collection destructor
+ */
static void php_oci_collection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_collection *collection = (php_oci_collection *)entry->ptr;
/* }}} */
-/* hash destructors {{{ */
+/* Hash Destructors {{{ */
/* {{{ php_oci_define_hash_dtor()
- Define hash destructor */
+ *
+ * Define hash destructor
+ */
void php_oci_define_hash_dtor(void *data)
{
php_oci_define *define = (php_oci_define *) data;
/* }}} */
/* {{{ php_oci_bind_hash_dtor()
- Bind hash destructor */
+ *
+ * Bind hash destructor
+ */
void php_oci_bind_hash_dtor(void *data)
{
php_oci_bind *bind = (php_oci_bind *) data;
/* }}} */
/* {{{ php_oci_column_hash_dtor()
- Column hash destructor */
+ *
+ * Column hash destructor
+ */
void php_oci_column_hash_dtor(void *data)
{
php_oci_out_column *column = (php_oci_out_column *) data;
/* }}} */
/* {{{ php_oci_descriptor_flush_hash_dtor()
- Flush descriptors on commit */
+ *
+ * Flush descriptors on commit
+ */
void php_oci_descriptor_flush_hash_dtor(void *data)
{
php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
/* }}} */
/* {{{ php_oci_descriptor_delete_from_hash()
- Delete descriptor from the hash */
+ *
+ * Delete descriptor from the hash
+ */
int php_oci_descriptor_delete_from_hash(void *data, void *id TSRMLS_DC)
{
php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
/* }}} */
/* {{{ php_oci_error()
- Fetch & print out error message if we get an error */
+ *
+ * Fetch & print out error message if we get an error
+ */
sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC)
{
text *errbuf = (text *)NULL;
/* }}} */
/* {{{ php_oci_fetch_errmsg()
- Fetch error message into the buffer from the error handle provided */
+ *
+ * Fetch error message into the buffer from the error handle provided
+ */
sb4 php_oci_fetch_errmsg(OCIError *error_handle, text **error_buf TSRMLS_DC)
{
sb4 error_code = 0;
} /* }}} */
/* {{{ php_oci_fetch_sqltext_offset()
- Compute offset in the SQL statement */
+ *
+ * Compute offset in the SQL statement
+ */
int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset TSRMLS_DC)
{
*sqltext = NULL;
} /* }}} */
/* {{{ php_oci_do_connect()
- Connect wrapper */
+ *
+ * Connect wrapper
+ */
void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
{
php_oci_connection *connection;
} /* }}} */
/* {{{ php_oci_do_connect_ex()
- * The real connect function. Allocates all the resources needed, establishes the connection and returns the result handle (or NULL) */
+ *
+ * The real connect function. Allocates all the resources needed, establishes the connection and
+ * returns the result handle (or NULL)
+ */
php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC)
{
zend_rsrc_list_entry *le;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA");
return NULL;
}
- /* Disable privileged connections in Safe Mode (N.b. safe mode has been removed in PHP 6 anyway) */
+ /* Disable privileged connections in Safe Mode (N.b. safe mode has been removed in PHP
+ * 6 anyway)
+ */
if (PG(safe_mode)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled in Safe Mode");
return NULL;
}
- /* Increase security by not caching privileged
- * oci_pconnect() connections. The connection becomes
- * equivalent to oci_connect() or oci_new_connect().
+
+ /* Increase security by not caching privileged oci_pconnect() connections. The
+ * connection becomes equivalent to oci_connect() or oci_new_connect().
*/
persistent = 0;
break;
break;
}
- /* 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
+ /* 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
*/
if ((session_mode == OCI_SYSOPER) || (session_mode == OCI_SYSDBA) || (new_password_len)) {
}
} /* }}} */
- /* 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.
+ /* 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->is_persistent) {
int rsrc_type;
- /* check connection liveness in the following order:
+ /* Check connection liveness in the following order:
* 1) always check OCI_ATTR_SERVER_STATUS
* 2) see if it's time to ping it
* 3) ping it if needed
*/
if (php_oci_connection_status(connection TSRMLS_CC)) {
- /* only ping if:
+ /* 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"
+ *
+ * 2) current_timestamp > next_ping, which means "it's time to check if it's
+ * still alive"
*/
- if ( !ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection TSRMLS_CC) ) {
+ if (!ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection TSRMLS_CC)) {
/* server died */
} else {
php_oci_connection *tmp;
/* do nothing */
} else {
connection->rsrc_id = zend_list_insert(connection, le_pconnection);
+ /* Persistent connections: For old close semantics we artificially
+ * bump up the refcount to prevent the non-persistent destructor
+ * from getting called until request shutdown. The refcount is
+ * decremented in the persistent helper
+ */
+ if (OCI_G(old_oci_close_semantics)) {
+ zend_list_addref(connection->rsrc_id);
+ }
}
smart_str_free_ex(&hashed_details, 0);
return connection;
}
} /* is_open is true? */
- /* Server died - connection not usable. The is_open=true can also fall through to here, if ping fails */
+ /* Server died - connection not usable. The is_open=true can also fall through to here,
+ * if ping fails
+ */
if (persistent){
int rsrc_type;
connection->is_open = 0;
connection->used_this_request = 1;
- /* We have to do a hash_del but need to preserve the resource if there is a positive refcount. Set the data pointer in the list entry to NULL */
- if (connection == zend_list_find(connection->rsrc_id, &rsrc_type)) {
+ /* We have to do a hash_del but need to preserve the resource if there is a positive
+ * refcount. Set the data pointer in the list entry to NULL
+ */
+ if (connection == zend_list_find(connection->rsrc_id, &rsrc_type) && rsrc_type == le_pconnection) {
le->ptr = NULL;
}
zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
} else {
+ /* We only remove the hash entry. The resource and the list entry with its pointer
+ * to the resource are still intact
+ */
zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
}
}
}
- /* 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.
+ /* 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;
connection->is_persistent = 0;
}
- /* {{{ Get the session pool that suits this connection request from the
- * persistent list. This step is only for non-persistent connections as
- * persistent connections have private session pools. Non-persistent conns
- * use shared session pool to allow for optimizations such as caching the
- * physical connection (for DRCP) even when the non-persistent php connection
- * is destroyed.
- * TODO: Unconditionally do this once OCI provides extended OCISessionGet capability */
+ /* {{{ Get the session pool that suits this connection request from the persistent list. This
+ * step is only for non-persistent connections as persistent connections have private session
+ * pools. Non-persistent conns use shared session pool to allow for optimizations such as
+ * caching the physical connection (for DRCP) even when the non-persistent php connection is
+ * destroyed.
+ *
+ * TODO: Unconditionally do this once OCI provides extended OCISessionGet capability
+ */
if (use_spool && !connection->is_persistent) {
if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang TSRMLS_CC))==NULL)
{
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 */
+ /* Mark password as unchanged by PHP during the duration of the database session */
connection->passwd_changed = 0;
smart_str_free_ex(&hashed_details, 0);
}
#endif
- /* Old session creation semantics when session pool cannot be used Eg: privileged connect/password change */
- if ( !use_spool) {
+ /* Old session creation semantics when session pool cannot be used Eg: privileged
+ * connect/password change
+ */
+ if (!use_spool) {
if (php_oci_old_create_session(connection, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
php_oci_connection_close(connection TSRMLS_CC);
return NULL;
}
}
- /* mark it as open */
+ /* Mark it as open */
connection->is_open = 1;
/* add to the appropriate hash */
new_le.type = le_pconnection;
connection->used_this_request = 1;
connection->rsrc_id = zend_list_insert(connection, le_pconnection);
+
+ /* Persistent connections: For old close semantics we artificially bump up the refcount to
+ * prevent the non-persistent destructor from getting called until request shutdown. The
+ * refcount is decremented in the persistent helper
+ */
+ if (OCI_G(old_oci_close_semantics)) {
+ zend_list_addref(connection->rsrc_id);
+ }
zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
OCI_G(num_persistent)++;
} else if (!exclusive) {
/* }}} */
/* {{{ php_oci_connection_ping()
- * Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version */
+ *
+ * Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version
+ */
static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC)
{
- /* Use OCIPing instead of OCIServerVersion. If OCIPing returns
- * ORA-1010 (invalid OCI operation) such as from Pre-10.1 servers,
- * the error is still from the server and we would have
- * successfully performed a roundtrip and validated the
- * connection. Use OCIServerVersion for Pre-10.2 clients
+ /* 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 */
+#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
#else
char version[256];
/* }}} */
/* {{{ php_oci_connection_status()
- Check connection status (pre-ping check) */
+ *
+ * Check connection status (pre-ping check)
+ */
static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC)
{
ub4 ss = 0;
/* }}} */
/* {{{ php_oci_connection_rollback()
- Rollback connection */
+ *
+ * Rollback connection
+ */
int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC)
{
PHP_OCI_CALL_RETURN(connection->errcode, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
} /* }}} */
/* {{{ php_oci_connection_commit()
- Commit connection */
+ *
+ * Commit connection
+ */
int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
{
PHP_OCI_CALL_RETURN(connection->errcode, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
} /* }}} */
/* {{{ php_oci_connection_close()
- Close the connection and free all its resources */
+ *
+ * Close the connection and free all its resources
+ */
static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
{
int result = 0;
zend_bool in_call_save = OCI_G(in_call);
- if (connection->descriptors) {
- zend_hash_destroy(connection->descriptors);
- efree(connection->descriptors);
- }
-
- if (connection->svc) {
- /* rollback outstanding transactions */
- if (connection->needs_commit) {
- if (php_oci_connection_rollback(connection TSRMLS_CC)) {
- /* rollback failed */
- result = 1;
- }
- }
+ if (!connection->is_stub) {
+ /* Release resources associated with connection */
+ php_oci_connection_release(connection TSRMLS_CC);
}
- if (!connection->is_stub && connection->svc && connection->is_open) {
- /* Update the next_ping in the connection. Needed also for non-peristent because non-persistent DRCP caches connection underneath */
- if (OCI_G(ping_interval) >= 0) {
- *(connection->next_pingp) = time(NULL) + OCI_G(ping_interval);
- } else {
- /* ping_interval is -1 */
- *(connection->next_pingp) = 0;
- }
-
- /* Use OCISessionRelease for session pool connections */
- if (connection->using_spool) {
- PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) 0));
- } else {
+ if (!connection->using_spool && connection->svc) {
PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0));
- }
}
if (connection->err) {
} /* }}} */
/* {{{ 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 */
+ *
+ * Release the connection's resources. This involves freeing descriptors and rolling back
+ * transactions, setting timeout-related parameters etc. For session-pool using connections, the
+ * underlying connection is released to its session pool.
+ */
int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
{
int result = 0;
zend_bool in_call_save = OCI_G(in_call);
+ time_t timestamp = time(NULL);
- if (connection->is_stub || !connection->using_spool) {
- return 0; /* Not our concern */
+ if (connection->is_stub) {
+ return 0;
}
if (connection->descriptors) {
}
}
- /* Release the session */
- if (connection->svc) {
+ 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) = time(NULL) + OCI_G(ping_interval);
+ *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
} else {
/* ping_interval is -1 */
*(connection->next_pingp) = 0;
}
-
- PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
- 0, result ? OCI_SESSRLS_DROPSESS : OCI_DEFAULT));
}
- /* It no longer has relation with the database session. However authinfo and env are cached */
- connection->svc = NULL;
- connection->server = NULL;
- connection->session = NULL;
+ /* Release the session (stubs are filtered out at the beginning)*/
+ if (connection->using_spool) {
+ ub4 rlsMode = OCI_DEFAULT;
- connection->is_attached = connection->is_open = connection->needs_commit = 0;
- connection->is_stub = 1;
+ if (result) {
+ rlsMode |= OCI_SESSRLS_DROPSESS;
+ }
- /* Cut the link between the connection structure and the time_t structure allocated within the OCI session */
- connection->next_pingp = NULL;
+ /* 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;
- if (!connection->is_persistent) {
- OCI_G(num_links)--; /* Support for "connection" stubs - future use */
+ connection->is_attached = connection->is_open = connection->needs_commit = connection->used_this_request = 0;
+ connection->is_stub = 1;
+
+ /* Cut the link between the connection structure and the time_t structure allocated within
+ * the OCI session
+ */
+ connection->next_pingp = NULL;
}
OCI_G(in_call) = in_call_save;
} /* }}} */
/* {{{ php_oci_password_change()
- Change password for the user with the username given */
+ *
+ * Change password for the user with the username given
+ */
int php_oci_password_change(php_oci_connection *connection, char *user, int user_len, char *pass_old, int pass_old_len, char *pass_new, int pass_new_len TSRMLS_DC)
{
PHP_OCI_CALL_RETURN(connection->errcode, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT));
} /* }}} */
/* {{{ php_oci_server_get_version()
- Get Oracle server version */
+ *
+ * Get Oracle server version
+ */
int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC)
{
char version_buff[256];
} /* }}} */
/* {{{ php_oci_column_to_zval()
- Convert php_oci_out_column struct into zval */
+ *
+ * Convert php_oci_out_column struct into zval
+ */
int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSRMLS_DC)
{
php_oci_descriptor *descriptor;
/* }}} */
/* {{{ php_oci_fetch_row()
- Fetch the next row from the given statement */
+ *
+ * Fetch the next row from the given statement
+ */
void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
{
zval *z_statement, *array;
}
if (expected_args > 2) {
- /* only for ocifetchinto BC
- * in all other cases we return array, not long
- */
+ /* Only for ocifetchinto BC. In all other cases we return array, not long */
REPLACE_ZVAL_VALUE(&array, return_value, 1); /* copy return_value to given reference */
zval_dtor(return_value);
RETURN_LONG(statement->ncolumns);
/* }}} */
/* {{{ php_oci_persistent_helper()
- Helper function to close/rollback persistent connections at the end of request. A return value of 1 indicates that the connection is to be destroyed */
+ *
+ * Helper function to close/rollback persistent connections at the end of request. A return value of
+ * 1 indicates that the connection is to be destroyed
+ */
static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
{
time_t timestamp;
php_oci_connection *connection;
- int rsrc_type;
timestamp = time(NULL);
- /* pconnection stubs are also counted as they have private session pools */
+ /* Persistent connection stubs are also counted as they have private session pools */
if (le->type == le_pconnection) {
connection = (php_oci_connection *)le->ptr;
- if (connection->using_spool && (connection == zend_list_find(connection->rsrc_id, &rsrc_type)) && rsrc_type == le_pconnection){
- /* Do nothing - keep the connection as some one is referring to it. TODO: We should ideally have this for non-session_pool connections as well */
+ if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
if (OCI_G(debug_mode)) {
- php_printf ("OCI8 DEBUG L1: persistent_helper skipping : (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ php_printf ("OCI8 DEBUG L1: persistent_helper processing for timeout: (%p stub=%d) at (%s:%d) \n", connection, connection->is_stub, __FILE__, __LINE__);
}
- }
- else if (connection->used_this_request) {
- if (OCI_G(debug_mode)) {
- php_printf ("OCI8 DEBUG L1: persistent_helper processing : (%p stub=%d) at (%s:%d) \n", connection, connection->is_stub, __FILE__, __LINE__);
- }
-
- if ((PG(connection_status) & PHP_CONNECTION_TIMEOUT) || OCI_G(in_call)) {
- return ZEND_HASH_APPLY_REMOVE;
- }
-
- /* Helps remove bad connections from the persistent list */
- if (!connection->is_open && !connection->is_stub) {
- return ZEND_HASH_APPLY_REMOVE;
- }
-
- if (connection->descriptors) {
- zend_hash_destroy(connection->descriptors);
- efree(connection->descriptors);
- connection->descriptors = NULL;
- }
-
- if (connection->needs_commit) {
- php_oci_connection_rollback(connection TSRMLS_CC);
- }
-
- /* 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.
- */
- if (connection->passwd_changed) {
- return ZEND_HASH_APPLY_REMOVE;
- }
-
- if (OCI_G(persistent_timeout) > 0) {
- connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
- }
-
- if (!connection->is_stub) {
- if (OCI_G(ping_interval) >= 0) {
- *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
- } else {
- /* ping_interval is -1 */
- *(connection->next_pingp) = 0;
- }
-
- /* Release all session pool-using persistent connections at the end of the request */
- if (connection->using_spool && php_oci_connection_release(connection TSRMLS_CC)) {
- return ZEND_HASH_APPLY_REMOVE;
- }
- }
-
- connection->used_this_request = 0;
- } else if (OCI_G(persistent_timeout) != -1) {
if (connection->idle_expiry < timestamp) {
/* connection has timed out */
return ZEND_HASH_APPLY_REMOVE;
} /* }}} */
/* {{{ php_oci_create_spool()
- Create(alloc + Init) Session pool for the given dbname and charsetid */
+ *
+ * Create(alloc + Init) Session pool for the given dbname and charsetid
+ */
static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC)
{
php_oci_spool *session_pool = NULL;
session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
/* Populate key if passed */
- if (hash_key_len)
+ if (hash_key_len) {
session_pool->spool_hash_key = zend_strndup(hash_key, hash_key_len);
+ }
/* Create the session pool's env */
if (!(session_pool->env = php_oci_create_env(charsetid TSRMLS_CC))) {
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
+ /* 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));
goto exit_create_spool;
}
-/* Disable RLB as we'd mostly have single-connection pools */
-#if (OCI_MAJOR_VERSION > 10 )
+/* 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
- /* Create the homogeneous session pool - We have different session pools
- * for every different username, password, charset and dbname.
+ /* Create the homogeneous session pool - We have different session pools for every different
+ * username, password, charset and dbname.
*/
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode));
} /* }}} */
/* {{{ php_oci_get_spool()
- Get Session pool for the given dbname and charsetid from the persistent
- list. Function called for non-persistent connections.
-*/
+ *
+ * Get Session pool for the given dbname and charsetid from the persistent list. Function called for
+ * non-persistent connections.
+ */
static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC)
{
smart_str spool_hashed_details = {0};
}
smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
- smart_str_appendl_ex(&spool_hashed_details, dbname, dbname_len, 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);
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);
zend_hash_update(&EG(persistent_list), session_pool->spool_hash_key, strlen(session_pool->spool_hash_key)+1,(void *)&spool_le, sizeof(zend_rsrc_list_entry),NULL);
} else if (spool_out_le->type == le_psessionpool &&
strlen(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == spool_hashed_details.len &&
- memcmp(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key, spool_hashed_details.c, spool_hashed_details.len) == 0 ) {
+ memcmp(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key, spool_hashed_details.c, spool_hashed_details.len) == 0) {
/* retrieve the cached session pool */
session_pool = (php_oci_spool *)(spool_out_le->ptr);
}
} /* }}} */
/* {{{ php_oci_create_env()
-Create the OCI environment choosing the correct function for the OCI version */
+ *
+ * Create the OCI environment choosing the correct function for the OCI version
+ */
static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC)
{
OCIEnv *retenv = NULL;
}/* }}} */
/* {{{ 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 */
+ *
+ * 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_oci_create_session()
- Create session using client-side session pool - new norm */
+ *
+ * Create session using client-side session pool - new norm
+ */
static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
{
php_oci_spool *actual_spool = NULL;
-#if (OCI_MAJOR_VERSION > 10 )
+#if (OCI_MAJOR_VERSION > 10)
ub4 purity = -2; /* Illegal value to initialize */
#endif
time_t timestamp = time(NULL);
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 */
+ /* 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
- * freshly created. In the former case, we do not have to allocate
- * any handles */
+ /* 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));
}
/* Set the Connection class and purity if OCI client version >= 11g */
-#if (OCI_MAJOR_VERSION > 10 )
+#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_printf ("OCI8 DEBUG L1: (numopen=%d)(numbusy=%d) at (%s:%d) \n", numopen, numbusy, __FILE__, __LINE__);
} /* }}} */
- /* Ping loop: Ping and loop till we get a good
- * connection. When a database instance goes down, it can
- * leave several bad connections that need to be flushed out
- * before getting a good one. In non-RAC, we always get a
- * brand new connection at the end of the loop and in RAC, we
- * can get a good connection from a different instance before
- * flushing out all bad ones. We do not need to ping brand new
- * connections.
+ /* 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 */
if (OCI_G(errcode) != OCI_SUCCESS) {
php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
- /* Session creation returns OCI_SUCCESS_WITH_INFO when
- * user's password has expired, but is still usable.
+ /* 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) {
} /* }}} */
/* {{{ php_oci_spool_list_dtor()
- Session pool destructor function */
+ *
+ * Session pool destructor function
+ */
static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
{
php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
} /* }}} */
/* {{{ php_oci_spool_close()
- Destroys the OCI Session Pool */
+ *
+ * Destroys the OCI Session Pool
+ */
static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC)
{
if (session_pool->poolname_len) {
} /* }}} */
/* {{{ php_oci_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 */
+ *
+ * Initializes the next_ping time as a context value in the connection. We now use
+ * OCIContext{Get,Set}Value to store the next_ping because we need to support ping for
+ * non-persistent DRCP connections
+ */
static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC)
{
time_t *next_pingp = NULL;
#ifdef ZTS
/* {{{ php_oci_list_helper()
- Helper function to destroy data on thread shutdown in ZTS mode */
+ *
+ * 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)
{
int type = (int) le_type;
#include "php_oci8.h"
#include "php_oci8_int.h"
-/* {{{ php_oci_collection_create()
+/* {{{ php_oci_collection_create()
Create and return connection handle */
php_oci_collection * php_oci_collection_create(php_oci_connection *connection, char *tdo, int tdo_len, char *schema, int schema_len TSRMLS_DC)
{
}
/* describe TDO */
- PHP_OCI_CALL_RETURN(connection->errcode, OCIDescribeAny,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDescribeAny,
(
connection->svc,
connection->err,
}
/* get the collection type code of the attribute */
- PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
(
(dvoid*) parmp1,
(ub4) OCI_DTYPE_PARAM,
case OCI_TYPECODE_TABLE:
case OCI_TYPECODE_VARRAY:
/* get collection element handle */
- PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
(
(dvoid*) parmp1,
(ub4) OCI_DTYPE_PARAM,
}
/* get REF of the TDO for the type */
- PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
(
(dvoid*) parmp2,
(ub4) OCI_DTYPE_PARAM,
}
/* get the TDO (only header) */
- PHP_OCI_CALL_RETURN(connection->errcode, OCITypeByRef,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCITypeByRef,
(
connection->env,
connection->err,
}
/* get typecode */
- PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
(
(dvoid*) parmp2,
(ub4) OCI_DTYPE_PARAM,
}
/* Create object to hold return table */
- PHP_OCI_CALL_RETURN(connection->errcode, OCIObjectNew,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIObjectNew,
(
- connection->env,
- connection->err,
- connection->svc,
- OCI_TYPECODE_TABLE,
- collection->tdo,
- (dvoid *)0,
- OCI_DURATION_DEFAULT,
- TRUE,
+ connection->env,
+ connection->err,
+ connection->svc,
+ OCI_TYPECODE_TABLE,
+ collection->tdo,
+ (dvoid *)0,
+ OCI_DURATION_DEFAULT,
+ TRUE,
(dvoid **) &(collection->collection)
)
);
return NULL;
} /* }}} */
-/* {{{ php_oci_collection_size()
+/* {{{ php_oci_collection_size()
Return size of the collection */
int php_oci_collection_size(php_oci_collection *collection, sb4 *size TSRMLS_DC)
{
return 0;
} /* }}} */
-/* {{{ php_oci_collection_max()
+/* {{{ php_oci_collection_max()
Return max number of elements in the collection */
int php_oci_collection_max(php_oci_collection *collection, long *max TSRMLS_DC)
{
return 0;
} /* }}} */
-/* {{{ php_oci_collection_trim()
+/* {{{ php_oci_collection_trim()
Trim collection to the given number of elements */
int php_oci_collection_trim(php_oci_collection *collection, long trim_size TSRMLS_DC)
{
return 0;
} /* }}} */
-/* {{{ php_oci_collection_append_null()
+/* {{{ php_oci_collection_append_null()
Append NULL element to the end of the collection */
int php_oci_collection_append_null(php_oci_collection *collection TSRMLS_DC)
{
return 0;
} /* }}} */
-/* {{{ php_oci_collection_append_date()
+/* {{{ php_oci_collection_append_date()
Append DATE element to the end of the collection (use "DD-MON-YY" format) */
int php_oci_collection_append_date(php_oci_collection *collection, char *date, int date_len TSRMLS_DC)
{
return 1;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
(
connection->env,
connection->err,
php_oci_connection *connection = collection->connection;
#if (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10)
- /* minimum PHP version ext/oci8/config.m4 accepts is 4.3.9 */
+ /* minimum PHP version ext/oci8/config.m4 accepts is 4.3.9 */
element_double = strtod(number, NULL);
#else
/* zend_strtod was introduced in PHP 4.3.10 */
return 1;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
(
connection->env,
connection->err,
return 0;
} /* }}} */
-/* {{{ php_oci_collection_append_string()
+/* {{{ php_oci_collection_append_string()
Append STRING to the end of the collection */
int php_oci_collection_append_string(php_oci_collection *collection, char *element, int element_len TSRMLS_DC)
{
return 1;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
(
connection->env,
connection->err,
return 0;
} /* }}} */
-/* {{{ php_oci_collection_append()
+/* {{{ php_oci_collection_append()
Append wrapper. Appends any supported element to the end of the collection */
int php_oci_collection_append(php_oci_collection *collection, char *element, int element_len TSRMLS_DC)
{
return php_oci_collection_append_string(collection, element, element_len TSRMLS_CC);
break;
- case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
- case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
- case OCI_TYPECODE_REAL : /* REAL */
- case OCI_TYPECODE_DOUBLE : /* DOUBLE */
- case OCI_TYPECODE_INTEGER : /* INT */
- case OCI_TYPECODE_SIGNED16 : /* SHORT */
- case OCI_TYPECODE_SIGNED32 : /* LONG */
- case OCI_TYPECODE_DECIMAL : /* DECIMAL */
- case OCI_TYPECODE_FLOAT : /* FLOAT */
- case OCI_TYPECODE_NUMBER : /* NUMBER */
- case OCI_TYPECODE_SMALLINT : /* SMALLINT */
+ case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
+ case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
+ case OCI_TYPECODE_REAL : /* REAL */
+ case OCI_TYPECODE_DOUBLE : /* DOUBLE */
+ case OCI_TYPECODE_INTEGER : /* INT */
+ case OCI_TYPECODE_SIGNED16 : /* SHORT */
+ case OCI_TYPECODE_SIGNED32 : /* LONG */
+ case OCI_TYPECODE_DECIMAL : /* DECIMAL */
+ case OCI_TYPECODE_FLOAT : /* FLOAT */
+ case OCI_TYPECODE_NUMBER : /* NUMBER */
+ case OCI_TYPECODE_SMALLINT : /* SMALLINT */
return php_oci_collection_append_number(collection, element, element_len TSRMLS_CC);
break;
return 1;
} /* }}} */
-/* {{{ php_oci_collection_element_get()
+/* {{{ php_oci_collection_element_get()
Get the element with the given index */
int php_oci_collection_element_get(php_oci_collection *collection, long index, zval **result_element TSRMLS_DC)
{
MAKE_STD_ZVAL(*result_element);
ZVAL_NULL(*result_element);
- PHP_OCI_CALL_RETURN(connection->errcode, OCICollGetElem,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollGetElem,
(
connection->env,
connection->err,
}
break;
- case OCI_TYPECODE_UNSIGNED16: /* UNSIGNED SHORT */
- case OCI_TYPECODE_UNSIGNED32: /* UNSIGNED LONG */
- case OCI_TYPECODE_REAL: /* REAL */
- case OCI_TYPECODE_DOUBLE: /* DOUBLE */
- case OCI_TYPECODE_INTEGER: /* INT */
- case OCI_TYPECODE_SIGNED16: /* SHORT */
- case OCI_TYPECODE_SIGNED32: /* LONG */
- case OCI_TYPECODE_DECIMAL: /* DECIMAL */
- case OCI_TYPECODE_FLOAT: /* FLOAT */
- case OCI_TYPECODE_NUMBER: /* NUMBER */
- case OCI_TYPECODE_SMALLINT: /* SMALLINT */
+ case OCI_TYPECODE_UNSIGNED16: /* UNSIGNED SHORT */
+ case OCI_TYPECODE_UNSIGNED32: /* UNSIGNED LONG */
+ case OCI_TYPECODE_REAL: /* REAL */
+ case OCI_TYPECODE_DOUBLE: /* DOUBLE */
+ case OCI_TYPECODE_INTEGER: /* INT */
+ case OCI_TYPECODE_SIGNED16: /* SHORT */
+ case OCI_TYPECODE_SIGNED32: /* LONG */
+ case OCI_TYPECODE_DECIMAL: /* DECIMAL */
+ case OCI_TYPECODE_FLOAT: /* FLOAT */
+ case OCI_TYPECODE_NUMBER: /* NUMBER */
+ case OCI_TYPECODE_SMALLINT: /* SMALLINT */
{
double double_number;
return 1;
} /* }}} */
-/* {{{ php_oci_collection_element_set_null()
+/* {{{ php_oci_collection_element_set_null()
Set the element with the given index to NULL */
int php_oci_collection_element_set_null(php_oci_collection *collection, long index TSRMLS_DC)
{
return 0;
} /* }}} */
-/* {{{ php_oci_collection_element_set_date()
+/* {{{ php_oci_collection_element_set_date()
Change element's value to the given DATE */
int php_oci_collection_element_set_date(php_oci_collection *collection, long index, char *date, int date_len TSRMLS_DC)
{
return 1;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
(
connection->env,
connection->err,
php_oci_connection *connection = collection->connection;
#if (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10)
- /* minimum PHP version ext/oci8/config.m4 accepts is 4.3.9 */
+ /* minimum PHP version ext/oci8/config.m4 accepts is 4.3.9 */
element_double = strtod(number, NULL);
#else
/* zend_strtod was introduced in PHP 4.3.10 */
return 1;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
(
connection->env,
connection->err,
return 1;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
(
connection->env,
connection->err,
return php_oci_collection_element_set_string(collection, index, value, value_len TSRMLS_CC);
break;
- case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
- case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
- case OCI_TYPECODE_REAL : /* REAL */
- case OCI_TYPECODE_DOUBLE : /* DOUBLE */
- case OCI_TYPECODE_INTEGER : /* INT */
- case OCI_TYPECODE_SIGNED16 : /* SHORT */
- case OCI_TYPECODE_SIGNED32 : /* LONG */
- case OCI_TYPECODE_DECIMAL : /* DECIMAL */
- case OCI_TYPECODE_FLOAT : /* FLOAT */
- case OCI_TYPECODE_NUMBER : /* NUMBER */
- case OCI_TYPECODE_SMALLINT : /* SMALLINT */
+ case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
+ case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
+ case OCI_TYPECODE_REAL : /* REAL */
+ case OCI_TYPECODE_DOUBLE : /* DOUBLE */
+ case OCI_TYPECODE_INTEGER : /* INT */
+ case OCI_TYPECODE_SIGNED16 : /* SHORT */
+ case OCI_TYPECODE_SIGNED32 : /* LONG */
+ case OCI_TYPECODE_DECIMAL : /* DECIMAL */
+ case OCI_TYPECODE_FLOAT : /* FLOAT */
+ case OCI_TYPECODE_NUMBER : /* NUMBER */
+ case OCI_TYPECODE_SMALLINT : /* SMALLINT */
return php_oci_collection_element_set_number(collection, index, value, value_len TSRMLS_CC);
break;
return 1;
} /* }}} */
-/* {{{ php_oci_collection_assign()
+/* {{{ php_oci_collection_assign()
Assigns a value to the collection from another collection */
int php_oci_collection_assign(php_oci_collection *collection_dest, php_oci_collection *collection_from TSRMLS_DC)
{
}
PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
-
-
+
if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
RETURN_FALSE;
}
descriptor->lob_current_position += offset;
break;
case PHP_OCI_SEEK_END:
- if (descriptor->lob_size + offset >= 0) {
+ if ((descriptor->lob_size + offset) >= 0) {
descriptor->lob_current_position = descriptor->lob_size + offset;
- }
+ }
else {
descriptor->lob_current_position = 0;
}
default:
descriptor->lob_current_position = (offset > 0) ? offset : 0;
break;
- }
-
+ }
RETURN_TRUE;
}
/* }}} */
zval **tmp, *z_descriptor = getThis();
php_oci_descriptor *descriptor;
int data_len;
- long write_len = 0;
+ long write_len = 0;
ub4 bytes_written;
char *data;
{
zval **tmp, *z_descriptor = getThis();
php_oci_descriptor *descriptor;
- char *filename, *buffer;
+ char *filename;
+ char *buffer;
int filename_len;
long start = -1, length = -1, block_length;
php_stream *stream;
RETURN_TRUE;
}
/* }}} */
-#endif
+#endif
/* {{{ proto object oci_new_descriptor(resource connection [, int type])
Initialize a new empty descriptor LOB/FILE (LOB is default) */
{
php_oci_out_column *column;
- column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+ column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
if (column) {
RETURN_LONG(column->data_type);
}
efree(columns);
efree(outarrs);
- }
+ }
RETURN_LONG(rows);
}
Disconnect from database */
PHP_FUNCTION(oci_close)
{
- /* oci_close for pconnect (if old_oci_close_semantics not set) would
- * release the connection back to the client-side session pool (and to the
+ /* oci_close for pconnect (if old_oci_close_semantics not set) would
+ * release the connection back to the client-side session pool (and to the
* server-side pool if Database Resident Connection Pool is being used).
* Subsequent pconnects in the same script are not guaranteed to get the
- * same database session. When a persistent connection goes out-of-scope,
- * the connection is not released to the session pool and is kept in the Plist
+ * same database session.
*/
zval *z_connection;
php_oci_connection *connection;
- int dummy_type = -1;
if (OCI_G(old_oci_close_semantics)) {
/* do nothing to keep BC */
PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
zend_list_delete(connection->rsrc_id);
- /* If refcount has fallen to zero(resource id removed from the list),
- * Release the OCI session associated with this connection structure back
- * to the underlying pool. The connection would be cached in the plist as a
- * stub
- */
- if(connection->is_persistent && connection->using_spool && !zend_list_find(connection->rsrc_id, &dummy_type)) {
-
- php_oci_connection_release(connection TSRMLS_CC);
- }
-
ZVAL_NULL(z_connection);
RETURN_TRUE;
int user_len, pass_old_len, pass_new_len, dbname_len;
php_oci_connection *connection;
- /* Disable in Safe Mode */
+ /* Disable in Safe Mode */
if (PG(safe_mode)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "is disabled in Safe Mode");
RETURN_FALSE;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|s", &z_connection, &tdo, &tdo_len, &schema, &schema_len) == FAILURE) {
return;
}
-
+
PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
if ( (collection = php_oci_collection_create(connection, tdo, tdo_len, schema, schema_len TSRMLS_CC)) ) {
PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0));
if (OCI_G(errcode) != OCI_SUCCESS) {
- connection->errcode = php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
- PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ OCI_G(errcode) = php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, OCI_G(errcode));
efree(descriptor);
return NULL;
}
} /* }}} */
-/* {{{ php_oci_lob_get_length()
+/* {{{ php_oci_lob_get_length()
Get length of the LOB. The length is cached so we don't need to ask Oracle every time */
int php_oci_lob_get_length (php_oci_descriptor *descriptor, ub4 *length TSRMLS_DC)
{
}
/* }}} */
-/* {{{ php_oci_lob_read()
+/* {{{ php_oci_lob_read()
Read specified portion of the LOB into the buffer */
int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long initial_offset, char **data, ub4 *data_len TSRMLS_DC)
{
if (length <= 0) {
return 0;
}
-
+
if (initial_offset > length) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be less than size of the LOB");
return 1;
connection->svc,
connection->err,
descriptor->descriptor,
- (oraub8 *)&bytes_read, /* IN/OUT bytes toread/read */
- (oraub8 *)&chars_read, /* IN/OUT chars toread/read */
- (oraub8) offset + 1, /* offset (starts with 1) */
+ (oraub8 *)&bytes_read, /* IN/OUT bytes toread/read */
+ (oraub8 *)&chars_read, /* IN/OUT chars toread/read */
+ (oraub8) offset + 1, /* offset (starts with 1) */
(dvoid *) bufp,
- (oraub8) buffer_size, /* size of buffer */
+ (oraub8) buffer_size, /* size of buffer */
OCI_FIRST_PIECE,
(dvoid *)&ctx,
- (OCICallbackLobRead2) php_oci_lob_callback, /* callback... */
- (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */
- (ub1) descriptor->charset_form /* The character set form of the buffer data. */
+ (OCICallbackLobRead2) php_oci_lob_callback, /* callback... */
+ (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */
+ (ub1) descriptor->charset_form /* The character set form of the buffer data. */
)
);
connection->svc,
connection->err,
descriptor->descriptor,
- &bytes_read, /* IN/OUT bytes toread/read */
- offset + 1, /* offset (starts with 1) */
+ &bytes_read, /* IN/OUT bytes toread/read */
+ offset + 1, /* offset (starts with 1) */
(dvoid *) bufp,
- (ub4) buffer_size, /* size of buffer */
+ (ub4) buffer_size, /* size of buffer */
(dvoid *)&ctx,
- (OCICallbackLobRead) php_oci_lob_callback, /* callback... */
- (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */
- (ub1) descriptor->charset_form /* The character set form of the buffer data. */
+ (OCICallbackLobRead) php_oci_lob_callback, /* callback... */
+ (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */
+ (ub1) descriptor->charset_form /* The character set form of the buffer data. */
)
);
return 1;
}
- descriptor->lob_current_position = (int)offset;
+ descriptor->lob_current_position = (int)offset;
if (descriptor->type == OCI_DTYPE_FILE) {
PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
return 0;
} /* }}} */
-/* {{{ php_oci_lob_write()
+/* {{{ php_oci_lob_write()
Write data to the LOB */
int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, int data_len, ub4 *bytes_written TSRMLS_DC)
{
- OCILobLocator *lob = (OCILobLocator *) descriptor->descriptor;
+ OCILobLocator *lob = (OCILobLocator *) descriptor->descriptor;
php_oci_connection *connection = (php_oci_connection *) descriptor->connection;
ub4 lob_length;
offset = descriptor->lob_current_position;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCILobWrite,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobWrite,
(
- connection->svc,
- connection->err,
- lob,
- (ub4 *)&data_len,
- (ub4) offset + 1,
- (dvoid *) data,
- (ub4) data_len,
- OCI_ONE_PIECE,
- (dvoid *)0,
- (OCICallbackLobWrite) 0,
- (ub2) descriptor->charset_id,
+ connection->svc,
+ connection->err,
+ lob,
+ (ub4 *)&data_len,
+ (ub4) offset + 1,
+ (dvoid *) data,
+ (ub4) data_len,
+ OCI_ONE_PIECE,
+ (dvoid *)0,
+ (OCICallbackLobWrite) 0,
+ (ub2) descriptor->charset_id,
(ub1) descriptor->charset_form
)
);
return 0;
} /* }}} */
-/* {{{ php_oci_lob_set_buffering()
+/* {{{ php_oci_lob_set_buffering()
Turn buffering off/onn for this particular LOB */
int php_oci_lob_set_buffering (php_oci_descriptor *descriptor, int on_off TSRMLS_DC)
{
return 1;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCILobCopy,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobCopy,
(
connection->svc,
connection->err,
return 0;
} /* }}} */
-/* {{{ php_oci_lob_close()
+/* {{{ php_oci_lob_close()
Close LOB */
int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
{
return 0;
} /* }}} */
-/* {{{ php_oci_temp_lob_close()
+/* {{{ php_oci_temp_lob_close()
Close Temporary LOB */
int php_oci_temp_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
{
} /* }}} */
-/* {{{ php_oci_lob_flush()
+/* {{{ php_oci_lob_flush()
Flush buffers for the LOB (only if they have been used) */
int php_oci_lob_flush(php_oci_descriptor *descriptor, long flush_flag TSRMLS_DC)
{
}
while ((loblen = read(fp, &buf, sizeof(buf))) > 0) {
- PHP_OCI_CALL_RETURN(connection->errcode,
+ PHP_OCI_CALL_RETURN(connection->errcode,
OCILobWrite,
(
- connection->svc,
- connection->err,
- lob,
- &loblen,
- offset,
- (dvoid *) &buf,
- loblen,
- OCI_ONE_PIECE,
- (dvoid *)0,
- (OCICallbackLobWrite) 0,
- (ub2) descriptor->charset_id,
+ connection->svc,
+ connection->err,
+ lob,
+ &loblen,
+ offset,
+ (dvoid *) &buf,
+ loblen,
+ OCI_ONE_PIECE,
+ (dvoid *)0,
+ (OCICallbackLobWrite) 0,
+ (ub2) descriptor->charset_id,
(ub1) descriptor->charset_form
)
);
return 0;
} /* }}} */
-/* {{{ php_oci_lob_is_equal()
+/* {{{ php_oci_lob_is_equal()
Compare two LOB descriptors and figure out if they are pointing to the same LOB */
int php_oci_lob_is_equal (php_oci_descriptor *descriptor_first, php_oci_descriptor *descriptor_second, boolean *result TSRMLS_DC)
{
return 0;
} /* }}} */
-/* {{{ php_oci_lob_write_tmp()
+/* {{{ php_oci_lob_write_tmp()
Create temporary LOB and write data to it */
int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, ub1 type, char *data, int data_len TSRMLS_DC)
{
php_oci_connection *connection = descriptor->connection;
- OCILobLocator *lob = descriptor->descriptor;
+ OCILobLocator *lob = descriptor->descriptor;
ub4 bytes_written = 0;
switch (type) {
return 1;
}
- PHP_OCI_CALL_RETURN(connection->errcode, OCILobCreateTemporary,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobCreateTemporary,
(
connection->svc,
connection->err,
#include "php_oci8.h"
#include "php_oci8_int.h"
-/* {{{ php_oci_statement_create()
+/* {{{ php_oci_statement_create()
Create statemend handle and allocate necessary resources */
php_oci_statement *php_oci_statement_create (php_oci_connection *connection, char *query, int query_len TSRMLS_DC)
{
if (query_len > 0) {
#if HAVE_OCI_STMT_PREPARE2
- PHP_OCI_CALL_RETURN(connection->errcode, OCIStmtPrepare2,
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIStmtPrepare2,
(
connection->svc,
&(statement->stmt),
/* {{{ php_oci_statement_set_prefetch()
Set prefetch buffer size for the statement (we're assuming that one row is ~1K sized) */
int php_oci_statement_set_prefetch(php_oci_statement *statement, long size TSRMLS_DC)
-{
+{
ub4 prefetch = size;
if (size < 1) {
}
/* }}} */
-/* {{{ php_oci_statement_fetch()
+/* {{{ php_oci_statement_fetch()
Fetch a row from the statement */
int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC)
{
while (statement->errcode == OCI_NEED_DATA) {
if (piecewisecols) {
PHP_OCI_CALL_RETURN(statement->errcode,
- OCIStmtGetPieceInfo,
+ OCIStmtGetPieceInfo,
(
statement->stmt,
statement->err,
}
}
- PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
if (piecewisecols) {
for (i = 0; i < statement->ncolumns; i++) {
}
/* }}} */
-/* {{{ php_oci_statement_get_column()
+/* {{{ php_oci_statement_get_column()
Get column from the result set */
php_oci_out_column *php_oci_statement_get_column(php_oci_statement *statement, long column_index, char *column_name, int column_name_len TSRMLS_DC)
{
php_oci_statement *nested_stmt;
TSRMLS_FETCH();
- nested_stmt = php_oci_statement_create(outcol->statement->connection, NULL, 0 TSRMLS_CC);
+ nested_stmt = php_oci_statement_create(outcol->statement->connection, NULL, 0 TSRMLS_CC);
if (!nested_stmt) {
return OCI_ERROR;
}
}
break;
case SQLT_RDD:
- case SQLT_BLOB:
+ case SQLT_BLOB:
case SQLT_CLOB:
case SQLT_BFILE: {
php_oci_descriptor *descr;
}
/* }}} */
-/* {{{ php_oci_statement_execute()
+/* {{{ php_oci_statement_execute()
Execute statement */
int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
{
iters = 1;
}
- if (statement->last_query) {
- /* if we execute refcursors we don't have a query and
+ if (statement->last_query) {
+ /* if we execute refcursors we don't have a query and
we don't want to execute!!! */
if (statement->binds) {
if (statement->errcode != OCI_SUCCESS) {
statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
- return 1;
+ return 1;
}
statement->ncolumns = colcount;
efree(statement->columns);
/* out of memory */
return 1;
- }
+ }
/* get column */
PHP_OCI_CALL_RETURN(statement->errcode, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)¶m, counter));
return 1;
}
- /* get character set id */
+ /* get character set id */
PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_id, (ub4 *)0, OCI_ATTR_CHARSET_ID, statement->err));
if (statement->errcode != OCI_SUCCESS) {
PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
- return 1;
+ return 1;
}
outcol->storage_size4 = outcol->data_size;
dynamic = OCI_DYNAMIC_FETCH;
break;
- case SQLT_RDD: /* ROWID */
- case SQLT_BLOB: /* binary LOB */
- case SQLT_CLOB: /* character LOB */
+ case SQLT_RDD: /* ROWID */
+ case SQLT_BLOB: /* binary LOB */
+ case SQLT_CLOB: /* character LOB */
case SQLT_BFILE: /* binary file LOB */
outcol->statement = statement; /* parent handle */
}
if (dynamic == OCI_DYNAMIC_FETCH) {
- PHP_OCI_CALL_RETURN(statement->errcode,
+ PHP_OCI_CALL_RETURN(statement->errcode,
OCIDefineByPos,
(
statement->stmt, /* IN/OUT handle to the requested SQL query */
);
} else {
- PHP_OCI_CALL_RETURN(statement->errcode,
+ PHP_OCI_CALL_RETURN(statement->errcode,
OCIDefineByPos,
(
- statement->stmt, /* IN/OUT handle to the requested SQL query */
+ statement->stmt, /* IN/OUT handle to the requested SQL query */
(OCIDefine **)&outcol->oci_define, /* IN/OUT pointer to a pointer to a define handle */
statement->err, /* IN/OUT An error handle */
counter, /* IN position in the select list */
/* additional OCIDefineDynamic() call */
switch (outcol->data_type) {
case SQLT_RSET:
- case SQLT_RDD:
- case SQLT_BLOB:
+ case SQLT_RDD:
+ case SQLT_BLOB:
case SQLT_CLOB:
case SQLT_BFILE:
- PHP_OCI_CALL_RETURN(statement->errcode,
+ PHP_OCI_CALL_RETURN(statement->errcode,
OCIDefineDynamic,
(
outcol->oci_define,
}
/* }}} */
-/* {{{ php_oci_statement_cancel()
+/* {{{ php_oci_statement_cancel()
Cancel statement */
int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC)
{
} /* }}} */
-/* {{{ php_oci_statement_free()
+/* {{{ php_oci_statement_free()
Destroy statement handle and free associated resources */
void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC)
{
- if (statement->stmt) {
+ if (statement->stmt) {
#if HAVE_OCI_STMT_PREPARE2
if (statement->last_query_len) { /* FIXME: magical */
PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
OCI_G(num_statements)--;
} /* }}} */
-/* {{{ php_oci_bind_pre_exec()
+/* {{{ php_oci_bind_pre_exec()
Helper function */
int php_oci_bind_pre_exec(void *data TSRMLS_DC)
{
/* reset all bind stuff to a normal state..-. */
- bind->indicator = 0;
+ bind->indicator = 0;
return 0;
}
/* }}} */
-/* {{{ php_oci_bind_post_exec()
+/* {{{ php_oci_bind_post_exec()
Helper function */
int php_oci_bind_post_exec(void *data TSRMLS_DC)
{
}
/* }}} */
-/* {{{ php_oci_bind_by_name()
+/* {{{ php_oci_bind_by_name()
Bind zval to the given placeholder */
int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long maxlength, long type TSRMLS_DC)
{
-#ifdef PHP_OCI8_HAVE_COLLECTIONS
+#ifdef PHP_OCI8_HAVE_COLLECTIONS
php_oci_collection *bind_collection = NULL;
#endif
php_oci_descriptor *bind_descriptor = NULL;
- php_oci_statement *bind_statement = NULL;
- dvoid *oci_desc = NULL;
- /* dvoid *php_oci_collection = NULL; */
- OCIStmt *oci_stmt = NULL;
- dvoid *bind_data = NULL;
+ php_oci_statement *bind_statement = NULL;
+ dvoid *oci_desc = NULL;
+ /* dvoid *php_oci_collection = NULL; */
+ OCIStmt *oci_stmt = NULL;
+ dvoid *bind_data = NULL;
php_oci_bind bind, *old_bind, *bindp;
int mode = OCI_DATA_AT_EXEC;
sb4 value_sz = -1;
break;
}
- if (value_sz == 0) {
+ if (value_sz == 0) {
value_sz = 1;
}
bindp->statement = oci_stmt;
bindp->parent_statement = statement;
bindp->zval = var;
- zval_add_ref(&var);
+ zval_add_ref(&var);
- PHP_OCI_CALL_RETURN(statement->errcode,
+ PHP_OCI_CALL_RETURN(statement->errcode,
OCIBindByName,
(
- statement->stmt, /* statement handle */
- (OCIBind **)&bindp->bind, /* bind hdl (will alloc) */
- statement->err, /* error handle */
- (text*) name, /* placeholder name */
- name_len, /* placeholder length */
- (dvoid *)bind_data, /* in/out data */
+ statement->stmt, /* statement handle */
+ (OCIBind **)&bindp->bind, /* bind hdl (will alloc) */
+ statement->err, /* error handle */
+ (text*) name, /* placeholder name */
+ name_len, /* placeholder length */
+ (dvoid *)bind_data, /* in/out data */
value_sz, /* PHP_OCI_MAX_DATA_SIZE, */ /* max size of input/output data */
- (ub2)type, /* in/out data type */
- (dvoid *)&bindp->indicator, /* indicator (ignored) */
- (ub2 *)0, /* size array (ignored) */
- (ub2 *)&bindp->retcode, /* return code (ignored) */
- (ub4)0, /* maxarr_len (PL/SQL only?) */
- (ub4 *)0, /* actual array size (PL/SQL only?) */
- mode /* mode */
+ (ub2)type, /* in/out data type */
+ (dvoid *)&bindp->indicator, /* indicator (ignored) */
+ (ub2 *)0, /* size array (ignored) */
+ (ub2 *)&bindp->retcode, /* return code (ignored) */
+ (ub4)0, /* maxarr_len (PL/SQL only?) */
+ (ub4 *)0, /* actual array size (PL/SQL only?) */
+ mode /* mode */
)
);
}
if (mode == OCI_DATA_AT_EXEC) {
- PHP_OCI_CALL_RETURN(statement->errcode, OCIBindDynamic,
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIBindDynamic,
(
bindp->bind,
statement->err,
#ifdef PHP_OCI8_HAVE_COLLECTIONS
if (type == SQLT_NTY) {
/* Bind object */
- PHP_OCI_CALL_RETURN(statement->errcode, OCIBindObject,
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIBindObject,
(
bindp->bind,
statement->err,
return 0;
} /* }}} */
-/* {{{ php_oci_bind_in_callback()
+/* {{{ php_oci_bind_in_callback()
Callback used when binding LOBs and VARCHARs */
sb4 php_oci_bind_in_callback(
- dvoid *ictxp, /* context pointer */
- OCIBind *bindp, /* bind handle */
- ub4 iter, /* 0-based execute iteration value */
- ub4 index, /* index of current array for PL/SQL or row index for SQL */
- dvoid **bufpp, /* pointer to data */
- ub4 *alenp, /* size after value/piece has been read */
- ub1 *piecep, /* which piece */
- dvoid **indpp) /* indicator value */
+ dvoid *ictxp, /* context pointer */
+ OCIBind *bindp, /* bind handle */
+ ub4 iter, /* 0-based execute iteration value */
+ ub4 index, /* index of current array for PL/SQL or row index for SQL */
+ dvoid **bufpp, /* pointer to data */
+ ub4 *alenp, /* size after value/piece has been read */
+ ub1 *piecep, /* which piece */
+ dvoid **indpp) /* indicator value */
{
php_oci_bind *phpbind;
zval *val;
*bufpp = 0;
*alenp = -1;
*indpp = (dvoid *)&phpbind->indicator;
- } else if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
+ } else if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
/* "normal string bind */
- convert_to_string(val);
+ convert_to_string(val);
*bufpp = Z_STRVAL_P(val);
*alenp = Z_STRLEN_P(val);
*bufpp = phpbind->statement;
*alenp = -1; /* seems to be allright */
*indpp = (dvoid *)&phpbind->indicator;
- } else {
+ } else {
/* descriptor bind */
*bufpp = phpbind->descriptor;
*alenp = -1; /* seems to be allright */
/* {{{ php_oci_bind_out_callback()
Callback used when binding LOBs and VARCHARs */
sb4 php_oci_bind_out_callback(
- dvoid *octxp, /* context pointer */
- OCIBind *bindp, /* bind handle */
- ub4 iter, /* 0-based execute iteration value */
- ub4 index, /* index of current array for PL/SQL or row index for SQL */
- dvoid **bufpp, /* pointer to data */
- ub4 **alenpp, /* size after value/piece has been read */
- ub1 *piecep, /* which piece */
- dvoid **indpp, /* indicator value */
- ub2 **rcodepp) /* return code */
+ dvoid *octxp, /* context pointer */
+ OCIBind *bindp, /* bind handle */
+ ub4 iter, /* 0-based execute iteration value */
+ ub4 index, /* index of current array for PL/SQL or row index for SQL */
+ dvoid **bufpp, /* pointer to data */
+ ub4 **alenpp, /* size after value/piece has been read */
+ ub1 *piecep, /* which piece */
+ dvoid **indpp, /* indicator value */
+ ub2 **rcodepp) /* return code */
{
php_oci_bind *phpbind;
zval *val;
Z_STRVAL_P(val) = ecalloc(1, Z_STRLEN_P(phpbind->zval) + 1);
/* XXX we assume that zend-zval len has 4 bytes */
- *alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
+ *alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
*bufpp = Z_STRVAL_P(phpbind->zval);
*piecep = OCI_ONE_PIECE;
*rcodepp = &phpbind->retcode;
}
/* }}} */
-/* {{{ php_oci_statement_get_column_helper()
+/* {{{ php_oci_statement_get_column_helper()
Helper function to get column by name and index */
php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS, int need_data)
{
return 0;
} /* }}} */
-/* {{{ php_oci_statement_get_numrows()
+/* {{{ php_oci_statement_get_numrows()
Get the number of rows fetched to the clientside (NOT the number of rows in the result set) */
int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSRMLS_DC)
{
return 0;
} /* }}} */
-/* {{{ php_oci_bind_array_by_name()
+/* {{{ php_oci_bind_array_by_name()
Bind arrays to PL/SQL types */
int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long max_table_length, long maxlength, long type TSRMLS_DC)
{
bindp->array.type = type;
zval_add_ref(&var);
- PHP_OCI_CALL_RETURN(statement->errcode,
- OCIBindByName,
+ PHP_OCI_CALL_RETURN(statement->errcode,
+ OCIBindByName,
(
statement->stmt,
(OCIBind **)&bindp->bind,
statement->err,
(text *)name,
name_len,
- (dvoid *) bindp->array.elements,
+ (dvoid *) bindp->array.elements,
(sb4) bind->array.max_length,
type,
(dvoid *)bindp->array.indicators,
return 0;
} /* }}} */
-/* {{{ php_oci_bind_array_helper_string()
+/* {{{ php_oci_bind_array_helper_string()
Bind arrays to PL/SQL types */
php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, long maxlength TSRMLS_DC)
{
for (i = 0; i < bind->array.current_length; i++) {
if (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
convert_to_string_ex(entry);
- bind->array.element_lengths[i] = Z_STRLEN_PP(entry);
+ bind->array.element_lengths[i] = Z_STRLEN_PP(entry);
if (Z_STRLEN_PP(entry) == 0) {
bind->array.indicators[i] = -1;
}
zend_hash_internal_pointer_reset(hash);
for (i = 0; i < max_table_length; i++) {
if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
- int element_length;
+ int element_length;
convert_to_string_ex(entry);
element_length = (maxlength > Z_STRLEN_PP(entry)) ? Z_STRLEN_PP(entry) : maxlength;
return bind;
} /* }}} */
-/* {{{ php_oci_bind_array_helper_number()
+/* {{{ php_oci_bind_array_helper_number()
Bind arrays to PL/SQL types */
php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length TSRMLS_DC)
{
return bind;
} /* }}} */
-/* {{{ php_oci_bind_array_helper_double()
+/* {{{ php_oci_bind_array_helper_double()
Bind arrays to PL/SQL types */
php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length TSRMLS_DC)
{
return bind;
} /* }}} */
-/* {{{ php_oci_bind_array_helper_date()
+/* {{{ php_oci_bind_array_helper_date()
Bind arrays to PL/SQL types */
php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, php_oci_connection *connection TSRMLS_DC)
{
<name>oci8</name>
<channel>pecl.php.net</channel>
<summary>OCI8 functions</summary>
- <description>These functions allow you to access Oracle database servers using
-the Oracle Call Interface (OCI8).
+ <description>These functions allow you to access Oracle database servers using the Oracle Call Interface (OCI8).
</description>
<lead>
<name>Antony Dovgal</name>
<name>Wez Furlong</name>
<user>wez</user>
<email>wez@php.net</email>
- <active>yes</active>
+ <active>no</active>
</lead>
<lead>
<name>Andi Gutmans</name>
<user>andi</user>
<email>andi@zend.com</email>
- <active>yes</active>
+ <active>no</active>
</lead>
<lead>
<name>Christopher Jones</name>
<email>sixd@php.net</email>
<active>yes</active>
</lead>
- <date>2007-10-05</date>
- <time>10:00:00</time>
+
+ <date>2008-04-17</date>
+ <time>16:00:00</time>
<version>
- <release>1.3.1</release>
- <api>1.3.1</api>
+ <release>1.3.2</release>
+ <api>1.3.2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<license uri="http://www.php.net/license">PHP</license>
- <notes>Fixed bug #44113 (New collection creation can fail with OCI-22303)
-Fixed bug #42841 (Crash with REF CURSORS when statement caching enabled)
-Fixed bug #42496 (Cursor leak selecting LOBs
-Fixed bug #43497 (Temporary LOB leak)
-Fixed PECL bug #12431 (ping functionality is broken)
-Allow compilation with 64bit Instant Client RPMs
-Allow -with-oci8=instantclient with no directory specified look for RPM install
+ <notes>
Refine DRCP connection pooling functionality
+Do scope-end release for oci_pconnect (oci8.old_oci_close_semantics=1 gives old behavior)
+Fixed bug #44372 (compilation with Oracle 10gR1 libraries)
+Fixed PECL bug #12431 (PEAR install using x86_64 RPM builds)
+Allow builds with PHP 4.3.9 onwards
</notes>
<contents>
<dir name="/">
<file name="array_bind_int.phpt" role="test" />
<file name="array_bind_str1.phpt" role="test" />
<file name="array_bind_str.phpt" role="test" />
+ <file name="bind_char_1.phpt" role="test" />
+ <file name="bind_char_2.phpt" role="test" />
+ <file name="bind_char_3.phpt" role="test" />
+ <file name="bind_char_4.phpt" role="test" />
<file name="bind_empty.phpt" role="test" />
<file name="bind_long.phpt" role="test" />
<file name="bind_long_raw.phpt" role="test" />
<file name="bug38173.phpt" role="test" />
<file name="bug40078.phpt" role="test" />
<file name="bug40415.phpt" role="test" />
+ <file name="bug41069.phpt" role="test" />
<file name="bug42134.phpt" role="test" />
<file name="bug42173.phpt" role="test" />
<file name="bug42496_1.phpt" role="test" />
<file name="bug42496_2.phpt" role="test" />
<file name="bug42841.phpt" role="test" />
+ <file name="bug43492_2.phpt" role="test" />
<file name="bug43492.phpt" role="test" />
+ <file name="bug43497_92.phpt" role="test" />
<file name="bug43497.phpt" role="test" />
+ <file name="bug44008.phpt" role="test" />
<file name="bug44113.phpt" role="test" />
+ <file name="bug44206.phpt" role="test" />
+ <file name="bug6109.phpt" role="test" />
<file name="close.phpt" role="test" />
<file name="coll_001.phpt" role="test" />
<file name="coll_002_func.phpt" role="test" />
<file name="define.phpt" role="test" />
<file name="descriptors.phpt" role="test" />
<file name="details.inc" role="test" />
+ <file name="drcp_cclass1.phpt" role="test" />
<file name="drcp_characterset.phpt" role="test" />
<file name="drcp_conn_close1.phpt" role="test" />
<file name="drcp_conn_close2.phpt" role="test" />
<file name="drcp_privileged.phpt" role="test" />
<file name="drcp_scope1.phpt" role="test" />
<file name="drcp_scope2.phpt" role="test" />
+ <file name="drcp_scope3.phpt" role="test" />
+ <file name="drcp_scope4.phpt" role="test" />
+ <file name="drcp_scope5.phpt" role="test" />
<file name="drop_table.inc" role="test" />
<file name="drop_type.inc" role="test" />
<file name="error1.phpt" role="test" />
<file name="fetch_all3.phpt" role="test" />
<file name="fetch_all.phpt" role="test" />
<file name="fetch_array.phpt" role="test" />
+ <file name="fetch_assoc.php" role="test" />
<file name="fetch_assoc.phpt" role="test" />
<file name="fetch_into1.phpt" role="test" />
<file name="fetch_into2.phpt" role="test" />
<file name="password_new.phpt" role="test" />
<file name="password_old.phpt" role="test" />
<file name="password.phpt" role="test" />
+ <file name="pecl_bug10194_blob_64.phpt" role="test" />
<file name="pecl_bug10194_blob.phpt" role="test" />
<file name="pecl_bug10194.phpt" role="test" />
<file name="pecl_bug8816.phpt" role="test" />
<file name="statement_type_old.phpt" role="test" />
<file name="statement_type.phpt" role="test" />
<file name="test.gif" role="test" />
+ <file name="testping.phpt" role="test" />
<file name="test.txt" role="test" />
<file name="uncommitted.phpt" role="test" />
<file name="xmltype_01.phpt" role="test" />
#endif
-/*
+/*
* The version of the OCI8 extension.
*/
#ifdef PHP_OCI8_VERSION
/* The definition of PHP_OCI8_VERSION changed in PHP 5.3 and building
- * this code with PHP 5.2 and earlier (i.e. from PECL) might conflict
+ * this code with PHP 5.2 and earlier (e.g. when using OCI8 from PECL)
+ * will conflict.
*/
#undef PHP_OCI8_VERSION
#endif
-#define PHP_OCI8_VERSION "1.3.1 Beta"
+#define PHP_OCI8_VERSION "1.3.2 Beta"
extern zend_module_entry oci8_module_entry;
#define phpext_oci8_ptr &oci8_module_entry
* c-basic-offset: 4
* End:
*/
-
-
OCI_G(in_call) = 0; \
} while (0)
+/* Check for errors that indicate the connection to the DB is no
+ * longer valid. If it isn't, then the PHP connection is marked to be
+ * reopened by the next PHP OCI8 connect command. This is most useful
+ * for persistent connections. The error number list is not
+ * exclusive. The error number comparisons and the
+ * OCI_ATTR_SERVER_STATUS check are done for maximum cross-version
+ * compatibility. In the far future, only the attribute check will be
+ * needed.
+ */
#define PHP_OCI_HANDLE_ERROR(connection, errcode) \
do { \
switch (errcode) { \
case 1013: \
zend_bailout(); \
break; \
- case 22: \
+ case 22: \
case 378: \
case 602: \
case 603: \
(connection)->is_open = 0; \
break; \
default: \
- { /* do both numeric checks (above) and the status check for maximum version compatibility */ \
+ { \
ub4 serverStatus = OCI_SERVER_NORMAL; \
PHP_OCI_CALL(OCIAttrGet, ((dvoid *)(connection)->server, OCI_HTYPE_SERVER, (dvoid *)&serverStatus, \
(ub4 *)0, OCI_ATTR_SERVER_STATUS, (connection)->err)); \
zend_bool old_oci_close_semantics; /* old_oci_close_semantics flag (to determine the way oci_close() should behave) */
int shutdown; /* in shutdown flag */
- int request_shutdown; /* in request shutdown flag */
OCIEnv *env; /* global environment handle */
--TEST--
Bug #43497 (OCI8 XML/getClobVal aka temporary LOBs leak UGA memory)
--SKIPIF--
-<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Oracle Version => 9/', $phpinfo);
+if ($ov === 1) {
+ die ("skip expected output only valid for Oracle clients from 10g onwards");
+}
+?>
--FILE--
<?php
--- /dev/null
+--TEST--
+Bug #43497 (OCI8 XML/getClobVal aka temporary LOBs leak UGA memory)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Oracle Version => 9.2/', $phpinfo);
+if ($ov !== 1) {
+ die ("skip expected output only valid for Oracle 9.2 clients");
+}
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+function sessionid($c) // determines and returns current session ID
+{
+ $query = "select sid from v\$session where audsid = userenv('sessionid')";
+
+ $stmt = oci_parse($c, $query);
+
+ if (oci_execute($stmt, OCI_DEFAULT)) {
+ $row = oci_fetch($stmt);
+ return oci_result($stmt, 1);
+ }
+
+ return null;
+}
+
+
+function templobs($c, $sid) // returns number of temporary LOBs
+{
+ $query = "select abstract_lobs from v\$temporary_lobs where sid = " . $sid;
+
+ $stmt = oci_parse($c, $query);
+
+ if (oci_execute($stmt, OCI_DEFAULT)) {
+ $row = oci_fetch($stmt);
+ $val = oci_result($stmt, 1);
+ oci_free_statement($stmt);
+ return $val;
+ }
+ return null;
+}
+
+
+// Read all XML data using explicit LOB locator
+function readxmltab_ex($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM)) {
+ $result[0]->free(); // cleanup properly
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+// Read all XML data using explicit LOB locator but without freeing the temp lobs
+function readxmltab_ex_nofree($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM)) {
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+// Read all XML data using implicit LOB locator
+function readxmltab_im($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM+OCI_RETURN_LOBS)) {
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+function createxmltab($c) // create table w/ field of XML type
+{
+ @dropxmltab($c);
+ $stmt = oci_parse($c, "create table bug43497_tab (id number primary key, xml xmltype)");
+ oci_execute($stmt);
+}
+
+function dropxmltab($c) // delete table
+{
+ $stmt = oci_parse($c, "drop table bug43497_tab");
+ oci_execute($stmt);
+}
+
+
+function fillxmltab($c)
+{
+ for ($id = 1; $id <= 100; $id++) {
+
+ // create an XML element string with random data
+ $s = "<data>";
+ for ($j = 0; $j < 128; $j++) {
+ $s .= rand();
+ }
+ $s .= "</data>\n";
+ for ($j = 0; $j < 4; $j++) {
+ $s .= $s;
+ }
+ $data = "<?xml version=\"1.0\"?><records>" . $s . "</records>";
+
+ // insert XML data into database
+
+ $stmt = oci_parse($c, "insert into bug43497_tab(id, xml) values (:id, sys.xmltype.createxml(:xml))");
+ oci_bind_by_name($stmt, ":id", $id);
+ $clob = oci_new_descriptor($c, OCI_D_LOB);
+ oci_bind_by_name($stmt, ":xml", $clob, -1, OCI_B_CLOB);
+ $clob->writetemporary($data);
+ oci_execute($stmt);
+
+ $clob->close();
+ $clob->free();
+ }
+}
+
+
+// Initialize
+
+createxmltab($c);
+fillxmltab($c);
+
+// Run Test
+
+$sid = sessionid($c);
+
+echo "Explicit LOB use\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_ex($c);
+}
+
+echo "\nImplicit LOB use\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_im($c);
+}
+
+echo "\nExplicit LOB with no free (i.e. a temp lob leak)\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_ex_nofree($c);
+}
+
+
+
+// Cleanup
+
+dropxmltab($c);
+
+oci_close($c);
+
+echo "Done\n";
+?>
+--EXPECT--
+Explicit LOB use
+
+Run = 1
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 100
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 200
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 300
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 400
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 500
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 600
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 700
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 800
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 900
+Loop count check = 100
+
+Implicit LOB use
+
+Run = 1
+Temporary LOBs = 1000
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 1100
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 1200
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 1300
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 1400
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 1500
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 1600
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 1700
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 1800
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 1900
+Loop count check = 100
+
+Explicit LOB with no free (i.e. a temp lob leak)
+
+Run = 1
+Temporary LOBs = 2000
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 2100
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 2200
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 2300
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 2400
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 2500
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 2600
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 2700
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 2800
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 2900
+Loop count check = 100
+Done
\ No newline at end of file
--FILE--
<?php
-require dirname(__FILE__).'/connect.inc';
+require(dirname(__FILE__).'/connect.inc');
// Initialization
// The test can take some time to complete and can exceed PHP's test
// timout limit on slow networks.
-for ($x = 0; $x < 70000; $x++)
-{
+for ($x = 0; $x < 70000; $x++) {
if (!($var = oci_new_collection($c, 'BUG44113_LIST_T'))) {
print "Failed new collection creation on $x\n";
break;
--SKIPIF--
<?php
if (!extension_loaded('oci8')) die ("skip no oci8 extension");
-require(__DIR__."/details.inc");
+require(dirname(__FILE__)."/details.inc");
if (!$test_drcp) die("skip testing DRCP connection class only works in DRCP mode");
if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
?>
--FILE--
<?php
-require(__DIR__."/details.inc");
+require(dirname(__FILE__)."/details.inc");
// Initialization
--TEST--
DRCP: oci_connect()
--SKIPIF--
-<?php
-if (!extension_loaded('oci8')) die("skip no oci8 extension");
-require(dirname(__FILE__)."/details.inc");
-if (!$test_drcp) die("skip expected test results are only valid for DRCP Mode");
-?>
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
--INI--
oci8.connection_class=test
oci8.old_oci_close_semantics=0
// Create the table
$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
drcp_create_table($c);
// OCI_NEW_CONNECT
// Create the table
$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
drcp_create_table($c);
// OCI_NEW_CONNECT
--- /dev/null
+--TEST--
+DRCP: oci_pconnect() with scope end when oci8.old_oci_close_semantics ON
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require dirname(__FILE__)."/drcp_functions.inc";
+require dirname(__FILE__)."/details.inc";
+
+// The test opens a connection within function1 and updates a table
+// (without committing). Another connection is opened from function
+// 2, and the table queried. When function1 ends, the connection from
+// function1 is not closed, so the updated value will be seen in
+// function2. Also the table can't be dropped because an uncommitted
+// transaction exists.
+
+// Create the table
+$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
+drcp_create_table($c);
+
+echo "This is with a OCI_PCONNECT\n";
+function1($user,$password,$dbase);
+
+// Should return the OLD value
+function2($user,$password,$dbase);
+
+// This is the first scope for the script
+
+function function1($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_update_table($c);
+}
+
+// This is the second scope
+
+function function2($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_select_value($c);
+}
+
+drcp_drop_table($c);
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_PCONNECT
+resource(%d) of type (oci8 persistent connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 persistent connection)
+The value of DEPT for id 105 is NEWDEPT
+
+Warning: oci_execute(): ORA-00054: %s
+Done
\ No newline at end of file
--- /dev/null
+--TEST--
+DRCP: oci_pconnect() with scope end when oci8.old_oci_close_semantics OFF
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require dirname(__FILE__)."/drcp_functions.inc";
+require dirname(__FILE__)."/details.inc";
+
+// The test opens a connection within function1 and updates a table
+// (without committing). Another connection is opened from function
+// 2, and the table queried. When function1 ends, the txn is rolled
+// back and hence the updated value will not be reflected in function2
+
+// Create the table
+$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
+drcp_create_table($c);
+
+echo "This is with a OCI_PCONNECT\n";
+function1($user,$password,$dbase);
+
+// Should return the OLD value
+function2($user,$password,$dbase);
+
+// This is the first scope for the script
+
+function function1($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_update_table($c);
+}
+
+// This is the second scope
+
+function function2($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_select_value($c);
+}
+
+drcp_drop_table($c);
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_PCONNECT
+resource(%d) of type (oci8 persistent connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 persistent connection)
+The value of DEPT for id 105 is HR
+Done
--- /dev/null
+--TEST--
+DRCP: oci_pconnect() with scope end when oci8.old_oci_close_semantics ON
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require dirname(__FILE__)."/drcp_functions.inc";
+require dirname(__FILE__)."/details.inc";
+
+// Similar to drcp_scope3.phpt but does a commit before end of
+// function2, allowing the table to be dropped cleanly at the end.
+
+// The test opens a connection within function1 and updates a table
+// (without committing). Another connection is opened from function
+// 2, and the table queried. When function1 ends, the connection from
+// function1 is not closed, so the updated value will be seen in
+// function2. Also the table can't be dropped because an uncommitted
+// transaction exists.
+
+// Create the table
+$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
+drcp_create_table($c);
+
+echo "This is with a OCI_PCONNECT\n";
+function1($user,$password,$dbase);
+
+// Should return the OLD value
+function2($user,$password,$dbase);
+
+// This is the first scope for the script
+
+function function1($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_update_table($c);
+}
+
+// This is the second scope
+
+function function2($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_select_value($c);
+ oci_commit($c);
+}
+
+drcp_drop_table($c);
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_PCONNECT
+resource(%d) of type (oci8 persistent connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 persistent connection)
+The value of DEPT for id 105 is NEWDEPT
+Done
\ No newline at end of file
--TEST--
-oci_password_change()
+oci_password_change() for non-persistent connections
--SKIPIF--
-<?php
-if (!extension_loaded('oci8')) die("skip no oci8 extension");
-require dirname(__FILE__)."/details.inc";
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/details.inc");
+if (empty($dbase)) die ("skip requires database connection string be set");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
if ($test_drcp) die("skip password change not supported in DRCP Mode");
?>
--FILE--
<?php
-require dirname(__FILE__)."/connect.inc";
+require(dirname(__FILE__)."/details.inc");
+
+// Create a user we can stuff around with and not affect subsequent tests
+$c0 = oci_connect($user, $password, $dbase);
+$stmts = array(
+ "drop user testuser",
+ "begin
+ execute immediate 'create user testuser identified by testuserpwd';
+ execute immediate 'grant connect, create session to testuser';
+ end;");
+foreach ($stmts as $sql) {
+ $s = oci_parse($c0, $sql);
+ @oci_execute($s);
+}
+
+// Connect and change the password
+$c1 = oci_connect("testuser", "testuserpwd", $dbase);
+var_dump($c1);
+$rn1 = (int)$c1;
+
+oci_password_change($c1, "testuser", "testuserpwd", "testuserpwd2");
-$new_password = "test";
-var_dump(oci_password_change($dbase, $user, $password, $new_password));
+// Second connect should return a new resource because the hash string will be different from $c1
+$c2 = oci_connect("testuser", "testuserpwd2", $dbase);
+var_dump($c2);
+$rn2 = (int)$c2;
+
+// Despite using the old password this connect should succeed and return the original resource
+$c3 = oci_connect("testuser", "testuserpwd", $dbase);
+var_dump($c3);
+$rn3 = (int)$c3;
+
+// Connections should differ
+if ($rn1 == $rn2) {
+ echo "First and second connections share a resource: Not OK\n";
+ var_dump($c1);
+}
+else {
+ echo "First and second connections are different: OK\n";
+}
-if (!empty($dbase)) {
- var_dump($new_c = ocilogon($user,$new_password,$dbase));
+// Connections should be the same
+if ($rn1 == $rn3) {
+ echo "First and third connections share a resource: OK\n";
}
else {
- var_dump($new_c = ocilogon($user,$new_password));
+ echo "First and third connections are different: Not OK\n";
+ var_dump($c1);
+ var_dump($c2);
}
-var_dump(oci_password_change($dbase, $user, $new_password, $password));
+// Clean up
+oci_close($c1);
+oci_close($c2);
+oci_close($c3);
+// Clean up
+$s = oci_parse($c0, "drop user cascade testuser");
+@oci_execute($s);
echo "Done\n";
resource(%d) of type (oci8 connection)
resource(%d) of type (oci8 connection)
resource(%d) of type (oci8 connection)
+First and second connections are different: OK
+First and third connections share a resource: OK
Done
<?php
if (!extension_loaded('oci8')) die("skip no oci8 extension");
require(dirname(__FILE__)."/details.inc");
+if (empty($dbase)) die ("skip requires database connection string be set");
if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
if ($test_drcp) die("skip password change not supported in DRCP Mode");
?>
// Connect (persistent) and change the password
$c1 = oci_pconnect("testuser", "testuserpwd", $dbase);
var_dump($c1);
-
-ob_start();
-var_dump($c1);
-$r1 = ob_get_clean();
-preg_match("/resource\(([0-9]*)\) of.*/", $r1, $matches);
-$rn1 = $matches[0]; /* resource number */
+$rn1 = (int)$c1;
oci_password_change($c1, "testuser", "testuserpwd", "testuserpwd2");
// Second connect should return a new resource because the hash string will be different from $c1
$c2 = oci_pconnect("testuser", "testuserpwd2", $dbase);
var_dump($c2);
-
-ob_start();
-var_dump($c2);
-$r2 = ob_get_clean();
-preg_match("/resource\(([0-9]*)\) of.*/", $r2, $matches);
-$rn2 = $matches[0]; /* resource number */
+$rn2 = (int)$c2;
// Despite using the old password this connect should succeed and return the original resource
$c3 = oci_pconnect("testuser", "testuserpwd", $dbase);
var_dump($c3);
-
-ob_start();
-var_dump($c3);
-$r3 = ob_get_clean();
-preg_match("/resource\(([0-9]*)\) of.*/", $r3, $matches);
-$rn3 = $matches[0]; /* resource number */
+$rn3 = (int)$c3;
// Connections should differ
if ($rn1 == $rn2) {
}
// Clean up
-// Can't drop a user that is connected and can't close a persistent
-// connection. So this test will leave the dummy user around, but the
-// schema will not be usable..
-$s = oci_parse($c0, "revoke connect, create session from testuser");
+oci_close($c1);
+oci_close($c2);
+oci_close($c3);
+
+// Clean up
+$s = oci_parse($c0, "drop user cascade testuser");
@oci_execute($s);
echo "Done\n";
--SKIPIF--
<?php
if (!extension_loaded('oci8')) die("skip no oci8 extension");
-require dirname(__FILE__)."/details.inc";
+require dirname(__FILE__)."/connect.inc";
+if (empty($dbase)) die ("skip requires database connection string be set");
if ($test_drcp) die("skip password change not supported in DRCP Mode");
+
+// This test is known to fail with Oracle 10g client libraries
+// connecting to Oracle Database 11.1.0.6 (Oracle bug 6277160)
+$sv = oci_server_version($c);
+$sv = preg_match('/11.1/', $sv, $matches);
+if ($sv === 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 10/', $phpinfo);
+ if ($iv === 1) {
+ die ("skip test known to fail using Oracle 10gR2 client libs connecting to Oracle 11.1 (6277160)");
+ }
+}
?>
--FILE--
<?php
--SKIPIF--
<?php
if (!extension_loaded('oci8')) die("skip no oci8 extension");
-require dirname(__FILE__)."/details.inc";
+require dirname(__FILE__)."/connect.inc";
+if (empty($dbase)) die ("skip requires database connection string be set");
if ($test_drcp) die("skip password change not supported in DRCP Mode");
+
+// This test is known to fail with Oracle 10g client libraries
+// connecting to Oracle Database 11.1.0.6 (Oracle bug 6277160)
+$sv = oci_server_version($c);
+$sv = preg_match('/11.1/', $sv, $matches);
+if ($sv === 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 10/', $phpinfo);
+ if ($iv === 1) {
+ die ("skip test known to fail using Oracle 10gR2 client libs connecting to Oracle 11.1 (6277160)");
+ }
+}
?>
--FILE--
<?php
require dirname(__FILE__)."/connect.inc";
$new_password = "test";
-var_dump(ocipasswordchange($c, $user, $password, $new_password));
+var_dump(ocipasswordchange($dbase, $user, $password, $new_password));
if (!empty($dbase)) {
var_dump($new_c = ocilogon($user,$new_password,$dbase));
var_dump($new_c = ocilogon($user,$new_password));
}
-var_dump(ocipasswordchange($new_c, $user, $new_password, $password));
+var_dump(ocipasswordchange($dbase, $user, $new_password, $password));
echo "Done\n";
?>
--EXPECTF--
-bool(true)
resource(%d) of type (oci8 connection)
-bool(true)
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
Done
--SKIPIF--
<?php
if (!extension_loaded('oci8')) die("skip no oci8 extension");
-if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only");
+if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platforms only");
?>
--INI--
memory_limit=3M
--SKIPIF--
<?php
if (!extension_loaded('oci8')) die("skip no oci8 extension");
-if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
+if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platforms only");
?>
--INI--
memory_limit=6M
--FILE--
<?php
-require(__DIR__.'/details.inc');
+require(dirname(__FILE__).'/details.inc');
for ($i = 0; $i < 2; $i++) {
if (!empty($dbase)) {