Updated OCI8 driver

This updated fixes (this list is not complete):
-------------------
#33915 - crash in _oci_close_session
#26393 - Segfault during request shutdown in _oci_close_session() (oci8.c:2443)

#32741 - hang on ociexecute() with collections (only with 10g, works with 9i)
#32325 - can't retrieve collection using OCI8
#33583 - Apache1.3.33 Segmentation fault with php5 & OCI_New_Collection

#32361 - connection oci_connect stay persist after process the php
#29013 - multiple logins cause handles become invalid
#28944 - OCITypeByName: OCI-21522 with two connections

Fixed by connection handling rewrite.

#32140 - NVARCHAR columns are truncated
#31042 - oci_fetch_* sets field value to false
#27156 - OCIFetchInto returns false as column value when column contains >1 umlaut

Fixed by multiplying buffer size by 3.

#33866 - OCIlogon do not returns conn resource for account with expired paswd
#33365 - logon fails when password expires

Fixed by adding new oci_password_change() call syntax.

#33159 - DB-connect via webserver fails after DB-restart ORA-24327
#30808 - oci8 cannot connect after restarting DB
#30127 - lost oracle connection. need restart apache.
#29902 - oci8 doesn't disconnect sessions, overloads oracle server
#29779 - (the same issue with the Oracle server going offline)
#26829 - Killed Oracle Sessions openned with OCIPLogon()

Fixed by adding oci8.ping_interval option.

#32988ext/oci8: OCI doesn't support DB external authentication

Fixed by adding support of external credentials (turned off by default).

Added new INI options:
----------------------
oci8.ping_interval
oci8.max_persistent
oci8.persistent_timeout
oci8.privileged_connect
oci8.statement_cache_size
oci8.default_prefetch
oci8.old_oci_close_semantics

See the updated docs for the detailed descriptions.

Major changes:
--------------
- connection handling algorithm rewritten. That should add stability and fix all non-reproducible crashes etc;
- extension refactored and divided into several files to improve readability and to make it easier to maintain;
- added support of statement caching;
- added support of privileged connections using external credentials;
- added new INI options to manage persistent connections;
- fixed oci_close() to close connections correctly.
This commit is contained in:
Antony Dovgal 2005-09-06 19:31:59 +00:00
parent 8774e8e1aa
commit 3df94e1112
9 changed files with 5914 additions and 6696 deletions

61
ext/oci8/README Normal file
View file

@ -0,0 +1,61 @@
Installing OCI8
---------------
1. Common requirements.
2. Installing as shared extension.
3. Installing as statically compiled extension.
4. Installing from PECL.
1. Common requirements
----------------------
In case if you use Oracle Instant Client, you don't have to set ORACLE_HOME and
most of the other environment variables to build PHP with OCI8 support.
The only variables you may have to set are:
LD_LIBRARY_PATH - it must include Instant Client libraries dir
NLS_LANG - in case if you want to change the default encoding used during
interaction with Oracle servers
If you use common Oracle Client installation that comes along with the Oracle
server installation, you MUST set at least ORACLE_HOME environment variable
and make it visible for your web-server BEFORE it starts. Most appropriate
places to add ORACLE_HOME definition are:
- /etc/profile
- /etc/profile.local
- /etc/profile.d
and others.
2. Installing as shared extension
---------------------------------
To install OCI8 as shared extension (i.e. the one you should put into
your php.ini) use the following configure lines to configure PHP:
a) if you use common Oracle Client installation:
./configure --with-oci8=shared,$ORACLE_HOME
b) with Oracle Instant Client:
./configure --with-oci8=shared,instantclient,/path/to/instant/client/lib
If you use rpm-based installation of Oracle Instant Client, your configure
line will look like this:
./configure --with-oci8=shared,instantclient,/usr/lib/oracle/<OIC version>/client/lib
Follow the usual building procedure after that and you'll get OCI8 shared
extension (i.e. oci8.so). Add it into the php.ini file like this:
extension=oci8.so
and don't forget to specify the right extension_dir for PHP to be able
to find shared extensions correctly.
3. Installing as statically compiled extension
----------------------------------------------
To install OCI8 as statically compiled module use the following configure lines:
a) with common Oracle Client installation
./configure --with-oci8=$ORACLE_HOME
b) with Oracle Instant Client
./configure --with-oci8=instantclient,/path/to/instant/client/lib
After successful compile, you don't have to add oci8.so to the php.ini, the module will
be usable without any additional actions.
4. Installing from PECL
-----------------------
TBD

View file

@ -19,7 +19,16 @@ AC_DEFUN([PHP_OCI_IF_DEFINED],[
]) ])
AC_DEFUN([AC_OCI8_CHECK_LIB_DIR],[ AC_DEFUN([AC_OCI8_CHECK_LIB_DIR],[
PHP_CHECK_64BIT([ TMP_OCI8_LIB_DIR=lib32 ], [ TMP_OCI8_LIB_DIR=lib ]) AC_CHECK_SIZEOF(long int, 4)
AC_MSG_CHECKING([checking if we're at 64-bit platform])
if test "$ac_cv_sizeof_long_int" = "4" ; then
AC_MSG_RESULT([no])
TMP_OCI8_LIB_DIR=lib32
else
AC_MSG_RESULT([yes])
TMP_OCI8_LIB_DIR=lib
fi
AC_MSG_CHECKING([OCI8 libraries dir]) AC_MSG_CHECKING([OCI8 libraries dir])
if test -d "$OCI8_DIR/lib" -a ! -d "$OCI8_DIR/lib32"; then if test -d "$OCI8_DIR/lib" -a ! -d "$OCI8_DIR/lib32"; then
OCI8_LIB_DIR=lib OCI8_LIB_DIR=lib
@ -76,26 +85,33 @@ AC_DEFUN([AC_OCI8_VERSION],[
AC_MSG_RESULT($OCI8_VERSION) AC_MSG_RESULT($OCI8_VERSION)
]) ])
PHP_ARG_WITH(oci8, for Oracle (OCI8) support using ORACLE_HOME installation,
[ --with-oci8[=DIR] Include Oracle (OCI8) support using an ORACLE_HOME
install. The default DIR is ORACLE_HOME])
if test "$PHP_OCI8" = "no"; then dnl --with-oci8=shared,instantclient,/path/to/client/dir/lib
PHP_ARG_WITH(oci8-instant-client, for Oracle (OCI8) support using Oracle Instant Client, dnl or
[ --with-oci8-instant-client[=DIR] dnl --with-oci8=shared,/path/to/oracle/home
Include Oracle (OCI8) support using PHP_ARG_WITH(oci8, for Oracle (OCI8) support,
Oracle Instant Client. DIR is the directory with the [ --with-oci8[=DIR] Include Oracle (OCI8) support.
Instant Client libraries. On Linux it will default to The default DIR is ORACLE_HOME.
/usr/lib/oracle/<most_recent_version>/client/lib Use --with-oci8=instantclient,/path/to/oic/lib
Other platforms will need to have it explicitly specified]) to use Oracle Instant Client installation])
else
PHP_OCI8_INSTANT_CLIENT="no"; PHP_OCI8_INSTANT_CLIENT="no"
if test "`echo $PHP_OCI8 | cut -d, -f2`" = "instantclient"; then
PHP_OCI8_INSTANT_CLIENT="`echo $PHP_OCI8 | cut -d, -f3`"
PHP_OCI8="`echo $PHP_OCI8 | cut -d, -f1,4`"
if test "$PHP_OCI8_INSTANT_CLIENT" = ""; then
PHP_OCI8_INSTANT_CLIENT="yes"
fi
elif test "`echo $PHP_OCI8 | cut -d, -f1`" = "instantclient"; then
PHP_OCI8_INSTANT_CLIENT="`echo $PHP_OCI8 | cut -d, -f2`"
PHP_OCI8="`echo $PHP_OCI8 | cut -d, -f3,4`"
if test "$PHP_OCI8_INSTANT_CLIENT" = ""; then
PHP_OCI8_INSTANT_CLIENT="yes"
fi
fi fi
if test "$PHP_OCI8" != "no"; then if test "$PHP_OCI8" != "no" && test "$PHP_OCI8_INSTANT_CLIENT" = "no"; then
if test "$PHP_OCI8_INSTANT_CLIENT" != "no"; then
AC_MSG_ERROR([--with-oci8 and --with-oci8-instant-client are mutually exclusive])
fi
AC_MSG_CHECKING([Oracle Install Directory]) AC_MSG_CHECKING([Oracle Install Directory])
if test "$PHP_OCI8" = "yes"; then if test "$PHP_OCI8" = "yes"; then
@ -138,12 +154,40 @@ if test "$PHP_OCI8" != "no"; then
PHP_ADD_LIBRARY_WITH_PATH(core4, "", OCI8_SHARED_LIBADD) PHP_ADD_LIBRARY_WITH_PATH(core4, "", OCI8_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(psa, "", OCI8_SHARED_LIBADD) PHP_ADD_LIBRARY_WITH_PATH(psa, "", OCI8_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(clntsh, $OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD) PHP_ADD_LIBRARY_WITH_PATH(clntsh, $OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD)
PHP_CHECK_LIBRARY(clntsh, OCIEnvCreate,
[
AC_DEFINE(HAVE_OCI_ENV_CREATE,1,[ ])
], [], [
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
])
PHP_CHECK_LIBRARY(clntsh, OCIStmtPrepare2,
[
AC_DEFINE(HAVE_OCI_STMT_PREPARE2,1,[ ])
], [], [
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
])
;; ;;
8.1) 8.1)
PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD) PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD)
PHP_ADD_LIBPATH($OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD) PHP_ADD_LIBPATH($OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD)
PHP_CHECK_LIBRARY(clntsh, OCIEnvCreate,
[
AC_DEFINE(HAVE_OCI_ENV_CREATE,1,[ ])
], [], [
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
])
PHP_CHECK_LIBRARY(clntsh, OCIStmtPrepare2,
[
AC_DEFINE(HAVE_OCI_STMT_PREPARE2,1,[ ])
], [], [
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
])
dnl dnl
dnl OCI_ATTR_STATEMENT is not available in all 8.1.x versions dnl OCI_ATTR_STATEMENT is not available in all 8.1.x versions
dnl dnl
@ -160,7 +204,7 @@ if test "$PHP_OCI8" != "no"; then
[ [
PHP_CHECK_LIBRARY(clntsh, OCINlsCharSetNameToId, PHP_CHECK_LIBRARY(clntsh, OCINlsCharSetNameToId,
[ [
AC_DEFINE(HAVE_OCI_9_2,1,[ ]) AC_DEFINE(HAVE_OCI_ENV_NLS_CREATE,1,[ ])
OCI8_VERSION=9.2 OCI8_VERSION=9.2
], [], [ ], [], [
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD -L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
@ -168,13 +212,30 @@ if test "$PHP_OCI8" != "no"; then
], [], [ ], [], [
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD -L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
]) ])
PHP_CHECK_LIBRARY(clntsh, OCIEnvCreate,
[
AC_DEFINE(HAVE_OCI_ENV_CREATE,1,[ ])
], [], [
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
])
PHP_CHECK_LIBRARY(clntsh, OCIStmtPrepare2,
[
AC_DEFINE(HAVE_OCI_STMT_PREPARE2,1,[ ])
], [], [
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
])
;; ;;
10.1) 10.1)
PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD) PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD)
PHP_ADD_LIBPATH($OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD) PHP_ADD_LIBPATH($OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD)
AC_DEFINE(HAVE_OCI8_ATTR_STATEMENT,1,[ ]) AC_DEFINE(HAVE_OCI8_ATTR_STATEMENT,1,[ ])
AC_DEFINE(HAVE_OCI_9_2,1,[ ]) AC_DEFINE(HAVE_OCI_ENV_NLS_CREATE,1,[ ])
AC_DEFINE(HAVE_OCI_ENV_CREATE,1,[ ])
AC_DEFINE(HAVE_OCI_STMT_PREPARE2,1,[ ])
AC_DEFINE(HAVE_OCI8_TEMP_LOB,1,[ ]) AC_DEFINE(HAVE_OCI8_TEMP_LOB,1,[ ])
AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ]) AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ])
;; ;;
@ -207,18 +268,22 @@ if test "$PHP_OCI8" != "no"; then
PHP_CHECK_LIBRARY(clntsh, OCICollAssign, PHP_CHECK_LIBRARY(clntsh, OCICollAssign,
[ [
AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ]) AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ])
], [], [ PHP_NEW_EXTENSION(oci8, oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c, $ext_shared)
],
[
PHP_NEW_EXTENSION(oci8, oci8.c oci8_lob.c oci8_statement.c oci8_interface.c, $ext_shared)
],
[
-L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD -L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
]) ])
PHP_NEW_EXTENSION(oci8, oci8.c, $ext_shared)
AC_DEFINE(HAVE_OCI8,1,[ ]) AC_DEFINE(HAVE_OCI8,1,[ ])
PHP_SUBST_OLD(OCI8_SHARED_LIBADD) PHP_SUBST_OLD(OCI8_SHARED_LIBADD)
PHP_SUBST_OLD(OCI8_DIR) PHP_SUBST_OLD(OCI8_DIR)
PHP_SUBST_OLD(OCI8_VERSION) PHP_SUBST_OLD(OCI8_VERSION)
elif test "$PHP_OCI8_INSTANT_CLIENT" != "no"; then elif test "$PHP_OCI8" != "no" && test "$PHP_OCI8_INSTANT_CLIENT" != "no"; then
AC_MSG_CHECKING([Oracle Instant Client directory]) AC_MSG_CHECKING([Oracle Instant Client directory])
if test "$PHP_OCI8_INSTANT_CLIENT" = "yes"; then if test "$PHP_OCI8_INSTANT_CLIENT" = "yes"; then
@ -227,7 +292,7 @@ dnl directory to the libraries. But on Linux we default to the most recent
dnl version in /usr/lib dnl version in /usr/lib
PHP_OCI8_INSTANT_CLIENT=`ls -d /usr/lib/oracle/*/client/lib 2> /dev/null | tail -1` PHP_OCI8_INSTANT_CLIENT=`ls -d /usr/lib/oracle/*/client/lib 2> /dev/null | tail -1`
if test -z "$PHP_OCI8_INSTANT_CLIENT"; then if test -z "$PHP_OCI8_INSTANT_CLIENT"; then
AC_MSG_ERROR([Oracle Instant Client directory not found. Try --with-oci8-instant-client=DIR]) AC_MSG_ERROR([Oracle Instant Client directory not found. Try --with-oci8=instantclient,DIR])
fi fi
fi fi
AC_MSG_RESULT($PHP_OCI8_INSTANT_CLIENT) AC_MSG_RESULT($PHP_OCI8_INSTANT_CLIENT)
@ -242,6 +307,9 @@ dnl Header directory for Instant Client SDK RPM install
dnl Header directory for Instant Client SDK zip file install dnl Header directory for Instant Client SDK zip file install
OCISDKZIPINC=$PHP_OCI8_INSTANT_CLIENT/sdk/include OCISDKZIPINC=$PHP_OCI8_INSTANT_CLIENT/sdk/include
dnl Header directory for manual installation
OCISDKMANINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | sed -e 's!\(.*\)/lib[[/]]*$!\1/include!'`
if test -f "$OCISDKRPMINC/oci.h"; then if test -f "$OCISDKRPMINC/oci.h"; then
AC_MSG_RESULT($OCISDKRPMINC) AC_MSG_RESULT($OCISDKRPMINC)
PHP_ADD_INCLUDE($OCISDKRPMINC) PHP_ADD_INCLUDE($OCISDKRPMINC)
@ -250,6 +318,10 @@ dnl Header directory for Instant Client SDK zip file install
AC_MSG_RESULT($OCISDKZIPINC) AC_MSG_RESULT($OCISDKZIPINC)
PHP_ADD_INCLUDE($OCISDKZIPINC) PHP_ADD_INCLUDE($OCISDKZIPINC)
OCI8INCDIR=$OCISDKZIPINC OCI8INCDIR=$OCISDKZIPINC
elif test -f "$OCISDKMANINC/oci.h"; then
AC_MSG_RESULT($OCISDKMANINC)
PHP_ADD_INCLUDE($OCISDKMANINC)
OCI8INCDIR=$OCISDKMANINC
else else
AC_MSG_ERROR([Oracle Instant Client SDK header files not found]) AC_MSG_ERROR([Oracle Instant Client SDK header files not found])
fi fi
@ -271,13 +343,15 @@ dnl Header directory for Instant Client SDK zip file install
;; ;;
esac esac
AC_DEFINE(HAVE_OCI_INSTANT_CLIENT,1,[ ])
AC_DEFINE(HAVE_OCI8_ATTR_STATEMENT,1,[ ]) AC_DEFINE(HAVE_OCI8_ATTR_STATEMENT,1,[ ])
AC_DEFINE(HAVE_OCI_9_2,1,[ ]) AC_DEFINE(HAVE_OCI_ENV_NLS_CREATE,1,[ ])
AC_DEFINE(HAVE_OCI_ENV_CREATE,1,[ ])
AC_DEFINE(HAVE_OCI_STMT_PREPARE2,1,[ ])
AC_DEFINE(HAVE_OCI8_TEMP_LOB,1,[ ]) AC_DEFINE(HAVE_OCI8_TEMP_LOB,1,[ ])
AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ]) AC_DEFINE(PHP_OCI8_HAVE_COLLECTIONS,1,[ ])
AC_DEFINE(HAVE_OCI_INSTANT_CLIENT,1,[ ])
PHP_NEW_EXTENSION(oci8, oci8.c, $ext_shared) PHP_NEW_EXTENSION(oci8, oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c, $ext_shared)
AC_DEFINE(HAVE_OCI8,1,[ ]) AC_DEFINE(HAVE_OCI8,1,[ ])
PHP_SUBST_OLD(OCI8_SHARED_LIBADD) PHP_SUBST_OLD(OCI8_SHARED_LIBADD)

File diff suppressed because it is too large Load diff

604
ext/oci8/oci8_collection.c Normal file
View file

@ -0,0 +1,604 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Stig Sæther Bakken <ssb@php.net> |
| Thies C. Arntzen <thies@thieso.net> |
| Redesigned by: Antony Dovgal <antony@zend.com> |
| Andi Gutmans <andi@zend.com> |
| Wez Furlong <wez@omniti.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_ini.h"
#if HAVE_OCI8
#include "php_oci8.h"
#include "php_oci8_int.h"
/* {{{ php_oci_collection_create()
Create and return connection handle */
php_oci_collection * php_oci_collection_create(php_oci_connection* connection, char *tdo, long tdo_len, char *schema, long schema_len TSRMLS_DC)
{
dvoid *dschp1;
dvoid *parmp1;
dvoid *parmp2;
php_oci_collection *collection;
collection = emalloc(sizeof(php_oci_collection));
collection->connection = connection;
collection->collection = NULL;
/* get type handle by name */
connection->errcode = PHP_OCI_CALL(OCITypeByName, (connection->env, connection->err, connection->svc, (text *) schema, (ub4) schema_len, (text *) tdo, (ub4) tdo_len, (CONST text *) 0, (ub4) 0, OCI_DURATION_SESSION, OCI_TYPEGET_ALL, &(collection->tdo)));
if (connection->errcode) {
goto CLEANUP;
}
/* allocate describe handle */
connection->errcode = PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **) &dschp1, (ub4) OCI_HTYPE_DESCRIBE, (size_t) 0, (dvoid **) 0));
if (connection->errcode) {
goto CLEANUP;
}
/* describe TDO */
connection->errcode = PHP_OCI_CALL(OCIDescribeAny, (connection->svc, connection->err, (dvoid *) collection->tdo, (ub4) 0, OCI_OTYPE_PTR, (ub1) OCI_DEFAULT, (ub1) OCI_PTYPE_TYPE, dschp1));
if (connection->errcode) {
goto CLEANUP;
}
/* get first parameter handle */
connection->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *) dschp1, (ub4) OCI_HTYPE_DESCRIBE, (dvoid *)&parmp1, (ub4 *)0, (ub4)OCI_ATTR_PARAM, connection->err));
if (connection->errcode) {
goto CLEANUP;
}
/* get the collection type code of the attribute */
connection->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid*) parmp1, (ub4) OCI_DTYPE_PARAM, (dvoid*) &(collection->coll_typecode), (ub4 *) 0, (ub4) OCI_ATTR_COLLECTION_TYPECODE, connection->err));
if (connection->errcode) {
goto CLEANUP;
}
switch(collection->coll_typecode) {
case OCI_TYPECODE_TABLE:
case OCI_TYPECODE_VARRAY:
/* get collection element handle */
connection->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid*) parmp1, (ub4) OCI_DTYPE_PARAM, (dvoid*) &parmp2, (ub4 *) 0, (ub4) OCI_ATTR_COLLECTION_ELEMENT, connection->err));
if (connection->errcode) {
goto CLEANUP;
}
/* get REF of the TDO for the type */
connection->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid*) parmp2, (ub4) OCI_DTYPE_PARAM, (dvoid*) &(collection->elem_ref), (ub4 *) 0, (ub4) OCI_ATTR_REF_TDO, connection->err));
if (connection->errcode) {
goto CLEANUP;
}
/* get the TDO (only header) */
connection->errcode = PHP_OCI_CALL(OCITypeByRef, (connection->env, connection->err, collection->elem_ref, OCI_DURATION_SESSION, OCI_TYPEGET_HEADER, &(collection->element_type)));
if (connection->errcode) {
goto CLEANUP;
}
/* get typecode */
connection->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid*) parmp2, (ub4) OCI_DTYPE_PARAM, (dvoid*) &(collection->element_typecode), (ub4 *) 0, (ub4) OCI_ATTR_TYPECODE, connection->err));
if (connection->errcode) {
goto CLEANUP;
}
break;
/* we only support VARRAYs and TABLEs */
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCINewCollection - Unknown Type %d", collection->coll_typecode);
break;
}
/* Create object to hold return table */
connection->errcode = PHP_OCI_CALL(OCIObjectNew,
(
connection->env,
connection->err,
connection->svc,
OCI_TYPECODE_TABLE,
collection->tdo,
(dvoid *)0,
OCI_DURATION_DEFAULT,
TRUE,
(dvoid **) &(collection->collection)
)
);
if (connection->errcode) {
goto CLEANUP;
}
PHP_OCI_REGISTER_RESOURCE(collection, le_collection);
return collection;
CLEANUP:
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
php_oci_collection_close(collection TSRMLS_CC);
return NULL;
} /* }}} */
/* {{{ php_oci_collection_size()
Return size of the collection */
int php_oci_collection_size(php_oci_collection *collection, sb4 *size TSRMLS_DC)
{
php_oci_connection *connection = collection->connection;
connection->errcode = PHP_OCI_CALL(OCICollSize, (connection->env, connection->err, collection->collection, (sb4 *)size));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ 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)
{
php_oci_connection *connection = collection->connection;
*max = PHP_OCI_CALL(OCICollMax, (connection->env, collection->collection));
/* error handling is not necessary here? */
return 0;
} /* }}} */
/* {{{ 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)
{
php_oci_connection *connection = collection->connection;
connection->errcode = PHP_OCI_CALL(OCICollTrim, (connection->env, connection->err, trim_size, collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ 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)
{
OCIInd null_index = OCI_IND_NULL;
php_oci_connection *connection = collection->connection;
/* append NULL element */
connection->errcode = PHP_OCI_CALL(OCICollAppend, (connection->env, connection->err, (dvoid *)0, &null_index, collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ 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, long date_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
OCIDate oci_date;
php_oci_connection *connection = collection->connection;
/* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */
connection->errcode = PHP_OCI_CALL(OCIDateFromText, (connection->err, date, date_len, NULL, 0, NULL, 0, &oci_date));
if (connection->errcode != OCI_SUCCESS) {
/* failed to convert string to date */
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
connection->errcode = PHP_OCI_CALL(OCICollAppend, (connection->env, connection->err, (dvoid *) &oci_date, (dvoid *) &new_index, (OCIColl *) collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_collection_append_number()
Append NUMBER to the end of the collection */
int php_oci_collection_append_number(php_oci_collection *collection, char *number, long number_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
double element_double;
OCINumber oci_number;
php_oci_connection *connection = collection->connection;
element_double = zend_strtod(number, NULL);
connection->errcode = PHP_OCI_CALL(OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
connection->errcode = PHP_OCI_CALL(OCICollAppend, (connection->env, connection->err, (dvoid *) &oci_number, (dvoid *) &new_index, (OCIColl *) collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ 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, long element_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
OCIString *ocistr = (OCIString *)0;
php_oci_connection *connection = collection->connection;
connection->errcode = PHP_OCI_CALL(OCIStringAssignText, (connection->env, connection->err, element, element_len, &ocistr));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
connection->errcode = PHP_OCI_CALL(OCICollAppend, (connection->env, connection->err, (dvoid *) ocistr, (dvoid *) &new_index, (OCIColl *) collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ 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, long element_len TSRMLS_DC)
{
if (element_len == 0) {
return php_oci_collection_append_null(collection TSRMLS_CC);
}
switch(collection->element_typecode) {
case OCI_TYPECODE_DATE:
return php_oci_collection_append_date(collection, element, element_len TSRMLS_CC);
break;
case OCI_TYPECODE_VARCHAR2 :
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 */
return php_oci_collection_append_number(collection, element, element_len TSRMLS_CC);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
return 1;
break;
}
/* never reached */
return 1;
} /* }}} */
/* {{{ 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)
{
php_oci_connection *connection = collection->connection;
dvoid *element;
OCIInd *element_index;
boolean exists;
char buff[1024];
int buff_len = 1024;
MAKE_STD_ZVAL(*result_element);
ZVAL_NULL(*result_element);
connection->errcode = PHP_OCI_CALL(OCICollGetElem, (connection->env, connection->err, collection->collection, (ub4)index, &exists, &element, (dvoid **)&element_index));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
FREE_ZVAL(*result_element);
return 1;
}
if (exists == 0) {
/* element doesn't exist */
FREE_ZVAL(*result_element);
return 1;
}
if (*element_index == OCI_IND_NULL) {
/* this is not an error, we're returning NULL here */
return 0;
}
switch (collection->element_typecode) {
case OCI_TYPECODE_DATE:
connection->errcode = PHP_OCI_CALL(OCIDateToText, (connection->err, element, 0, 0, 0, 0, &buff_len, buff));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
FREE_ZVAL(*result_element);
return 1;
}
ZVAL_STRINGL(*result_element, buff, buff_len, 1);
Z_STRVAL_P(*result_element)[buff_len] = '\0';
return 0;
break;
case OCI_TYPECODE_VARCHAR2:
{
OCIString *oci_string = *(OCIString **)element;
text *str;
str = (text *)PHP_OCI_CALL(OCIStringPtr, (connection->env, oci_string));
if (str) {
ZVAL_STRING(*result_element, str, 1);
}
return 0;
}
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 */
{
double double_number;
connection->errcode = PHP_OCI_CALL(OCINumberToReal, (connection->err, (CONST OCINumber *) element, (uword) sizeof(double), (dvoid *) &double_number));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
FREE_ZVAL(*result_element);
return 1;
}
ZVAL_DOUBLE(*result_element, double_number);
return 0;
}
break;
default:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
FREE_ZVAL(*result_element);
return 1;
break;
}
/* never reached */
return 1;
} /* }}} */
/* {{{ 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)
{
OCIInd null_index = OCI_IND_NULL;
php_oci_connection *connection = collection->connection;
/* set NULL element */
connection->errcode = PHP_OCI_CALL(OCICollAssignElem, (connection->env, connection->err, (ub4) index, (dvoid *)"", &null_index, collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ 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, long date_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
OCIDate oci_date;
php_oci_connection *connection = collection->connection;
/* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */
connection->errcode = PHP_OCI_CALL(OCIDateFromText, (connection->err, date, date_len, NULL, 0, NULL, 0, &oci_date));
if (connection->errcode != OCI_SUCCESS) {
/* failed to convert string to date */
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
connection->errcode = PHP_OCI_CALL(OCICollAssignElem, (connection->env, connection->err, (ub4)index, (dvoid *) &oci_date, (dvoid *) &new_index, (OCIColl *) collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_collection_element_set_number()
Change element's value to the given NUMBER */
int php_oci_collection_element_set_number(php_oci_collection *collection, long index, char *number, long number_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
double element_double;
OCINumber oci_number;
php_oci_connection *connection = collection->connection;
element_double = zend_strtod(number, NULL);
connection->errcode = PHP_OCI_CALL(OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
connection->errcode = PHP_OCI_CALL(OCICollAssignElem, (connection->env, connection->err, (ub4) index, (dvoid *) &oci_number, (dvoid *) &new_index, (OCIColl *) collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_collection_element_set_string()
Change element's value to the given string */
int php_oci_collection_element_set_string(php_oci_collection *collection, long index, char *element, long element_len TSRMLS_DC)
{
OCIInd new_index = OCI_IND_NOTNULL;
OCIString *ocistr = (OCIString *)0;
php_oci_connection *connection = collection->connection;
connection->errcode = PHP_OCI_CALL(OCIStringAssignText, (connection->env, connection->err, element, element_len, &ocistr));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
connection->errcode = PHP_OCI_CALL(OCICollAssignElem, (connection->env, connection->err, (ub4)index, (dvoid *) ocistr, (dvoid *) &new_index, (OCIColl *) collection->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_collection_element_set()
Collection element setter */
int php_oci_collection_element_set(php_oci_collection *collection, long index, char *value, long value_len TSRMLS_DC)
{
if (value_len == 0) {
return php_oci_collection_element_set_null(collection, index TSRMLS_CC);
}
switch(collection->element_typecode) {
case OCI_TYPECODE_DATE:
return php_oci_collection_element_set_date(collection, index, value, value_len TSRMLS_CC);
break;
case OCI_TYPECODE_VARCHAR2 :
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 */
return php_oci_collection_element_set_number(collection, index, value, value_len TSRMLS_CC);
break;
default:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
return 1;
break;
}
/* never reached */
return 1;
} /* }}} */
/* {{{ 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_connection *connection = collection_dest->connection;
connection->errcode = PHP_OCI_CALL(OCICollAssign, (connection->env, connection->err, collection_from->collection, collection_dest->collection));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_collection_close()
Destroy collection and all associated resources */
void php_oci_collection_close(php_oci_collection *collection TSRMLS_DC)
{
php_oci_connection *connection = collection->connection;
if (collection->collection) {
connection->errcode = PHP_OCI_CALL(OCIObjectFree, (connection->env, connection->err, (dvoid *)collection->collection, (ub2)OCI_OBJECTFREE_FORCE));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
}
}
efree(collection);
return;
} /* }}} */
#endif /* HAVE_OCI8 */

2065
ext/oci8/oci8_interface.c Normal file

File diff suppressed because it is too large Load diff

686
ext/oci8/oci8_lob.c Normal file
View file

@ -0,0 +1,686 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Stig Sæther Bakken <ssb@php.net> |
| Thies C. Arntzen <thies@thieso.net> |
| Redesigned by: Antony Dovgal <antony@zend.com> |
| Andi Gutmans <andi@zend.com> |
| Wez Furlong <wez@omniti.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_ini.h"
#if HAVE_OCI8
#include "php_oci8.h"
#include "php_oci8_int.h"
/* for import/export functions */
#include <fcntl.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
/* {{{ php_oci_lob_create()
Create LOB descriptor and allocate all the resources needed */
php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long type TSRMLS_DC)
{
php_oci_descriptor *descriptor;
switch (type) {
case OCI_DTYPE_FILE:
case OCI_DTYPE_LOB:
case OCI_DTYPE_ROWID:
/* these three are allowed */
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown descriptor type %ld.", type);
return NULL;
break;
}
descriptor = emalloc(sizeof(php_oci_descriptor));
descriptor->type = type;
OCI_G(errcode) = PHP_OCI_CALL(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);
efree(descriptor);
return NULL;
}
descriptor->connection = connection;
PHP_OCI_REGISTER_RESOURCE(descriptor, le_descriptor);
descriptor->lob_current_position = 0;
descriptor->lob_size = -1; /* we should set it to -1 to know, that it's just not initialized */
descriptor->buffering = PHP_OCI_LOB_BUFFER_DISABLED; /* buffering is off by default */
if (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE) {
/* add Lobs & Files to hash. we'll flush them at the end */
if (!connection->descriptors) {
ALLOC_HASHTABLE(connection->descriptors);
zend_hash_init(connection->descriptors, 13, NULL, php_oci_descriptor_flush_hash_dtor, 0);
}
zend_hash_next_index_insert(connection->descriptors,&descriptor,sizeof(php_oci_descriptor *),NULL);
}
return descriptor;
} /* }}} */
/* {{{ 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_connection *connection = descriptor->connection;
*length = 0;
if (descriptor->lob_size >= 0) {
*length = descriptor->lob_size;
return 0;
} else {
if (descriptor->type == OCI_DTYPE_FILE) {
connection->errcode = PHP_OCI_CALL(OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
}
connection->errcode = PHP_OCI_CALL(OCILobGetLength, (connection->svc, connection->err, descriptor->descriptor, (ub4 *)length));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
descriptor->lob_size = *length;
if (descriptor->type == OCI_DTYPE_FILE) {
connection->errcode = PHP_OCI_CALL(OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
}
}
return 0;
} /* }}} */
/* {{{ 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 offset, char **data, ub4 *data_len TSRMLS_DC)
{
php_oci_connection *connection = descriptor->connection;
ub4 length = 0;
ub4 block_length = PHP_OCI_LOB_BUFFER_SIZE;
int bytes_read;
int requested_len = read_length; /* this is by default */
*data_len = 0;
*data = NULL;
if (php_oci_lob_get_length(descriptor, &length TSRMLS_CC)) {
return 1;
}
if (offset > length) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be less than size of the LOB");
return 1;
}
if (read_length == -1) {
requested_len = length;
}
if (requested_len > (length - offset)) {
requested_len = length - offset;
}
if (requested_len == 0) {
return 0;
}
if (requested_len < block_length) {
block_length = requested_len;
}
if (descriptor->type == OCI_DTYPE_FILE) {
connection->errcode = PHP_OCI_CALL(OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
}
*data = emalloc(block_length + 1);
bytes_read = block_length;
while (bytes_read > 0 && *data_len < requested_len && offset < length) {
connection->errcode = PHP_OCI_CALL(OCILobRead,
(
connection->svc,
connection->err,
descriptor->descriptor,
&bytes_read, /* IN/OUT bytes toread/read */
offset + 1, /* offset (starts with 1) */
(dvoid *) ((char *) *data + *data_len),
block_length, /* size of buffer */
(dvoid *)0,
(OCICallbackLobRead) 0, /* callback... */
(ub2) connection->charset, /* The character set ID of the buffer data. */
(ub1) SQLCS_IMPLICIT /* The character set form of the buffer data. */
)
);
offset += bytes_read;
*data_len += bytes_read;
block_length = PHP_OCI_LOB_BUFFER_SIZE;
descriptor->lob_current_position += bytes_read;
if (*data_len < requested_len && connection->errcode == OCI_NEED_DATA) {
*data = erealloc(*data, *data_len + PHP_OCI_LOB_BUFFER_SIZE + 1);
continue;
} else {
break;
}
}
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
efree(*data);
*data = NULL;
return 1;
}
if (descriptor->type == OCI_DTYPE_FILE) {
connection->errcode = PHP_OCI_CALL(OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
efree(*data);
*data = NULL;
return 1;
}
}
*data = erealloc(*data, *data_len + 1);
(*data)[ *data_len ] = 0;
return 0;
} /* }}} */
/* {{{ php_oci_lob_write()
Write data to the LOB */
int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, long data_len, ub4 *bytes_written TSRMLS_DC)
{
OCILobLocator *lob = (OCILobLocator *) descriptor->descriptor;
php_oci_connection *connection = (php_oci_connection *) descriptor->connection;
ub4 lob_length;
*bytes_written = 0;
if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
return 1;
}
if (!data || data_len <= 0) {
return 0;
}
if (offset < 0) {
offset = 0;
}
if (offset > descriptor->lob_current_position) {
offset = descriptor->lob_current_position;
}
connection->errcode = PHP_OCI_CALL(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) 0, (ub1) SQLCS_IMPLICIT));
if (connection->errcode) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
*bytes_written = 0;
return 1;
}
*bytes_written = data_len;
descriptor->lob_current_position += data_len;
if (descriptor->lob_current_position > descriptor->lob_size) {
descriptor->lob_size = descriptor->lob_current_position;
}
/* marking buffer as used */
if (descriptor->buffering == PHP_OCI_LOB_BUFFER_ENABLED) {
descriptor->buffering = PHP_OCI_LOB_BUFFER_USED;
}
return 0;
} /* }}} */
/* {{{ 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)
{
php_oci_connection *connection = descriptor->connection;
if (!on_off && descriptor->buffering == PHP_OCI_LOB_BUFFER_DISABLED) {
/* disabling when it's already off */
return 0;
}
if (on_off && descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
/* enabling when it's already on */
return 0;
}
if (on_off) {
connection->errcode = PHP_OCI_CALL(OCILobEnableBuffering, (connection->svc, connection->err, descriptor->descriptor));
}
else {
connection->errcode = PHP_OCI_CALL(OCILobDisableBuffering, (connection->svc, connection->err, descriptor->descriptor));
}
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
descriptor->buffering = on_off ? PHP_OCI_LOB_BUFFER_ENABLED : PHP_OCI_LOB_BUFFER_DISABLED;
return 0;
} /* }}} */
/* {{{ php_oci_lob_get_buffering()
Return current buffering state for the LOB */
int php_oci_lob_get_buffering (php_oci_descriptor *descriptor TSRMLS_DC)
{
if (descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
return 1;
}
else {
return 0;
}
} /* }}} */
/* {{{ php_oci_lob_copy()
Copy one LOB (or its part) to another one */
int php_oci_lob_copy (php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from, long length TSRMLS_DC)
{
php_oci_connection *connection = descriptor_dest->connection;
int length_dest, length_from, copy_len;
if (php_oci_lob_get_length(descriptor_dest, &length_dest TSRMLS_CC)) {
return 1;
}
if (php_oci_lob_get_length(descriptor_from, &length_from TSRMLS_CC)) {
return 1;
}
if (length == -1) {
copy_len = length_from - descriptor_from->lob_current_position;
}
else {
copy_len = length;
}
if ((int)copy_len <= 0) {
/* silently fail, there is nothing to copy */
return 1;
}
connection->errcode = PHP_OCI_CALL(OCILobCopy, (connection->svc, connection->err, descriptor_dest->descriptor, descriptor_from->descriptor, copy_len, descriptor_dest->lob_current_position+1, descriptor_from->lob_current_position+1));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_lob_close()
Close LOB */
int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
{
php_oci_connection *connection = descriptor->connection;
int is_temporary;
connection->errcode = PHP_OCI_CALL(OCILobClose, (connection->svc, connection->err, descriptor->descriptor));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = PHP_OCI_CALL(OCILobIsTemporary, (connection->env,connection->err, descriptor->descriptor, &is_temporary));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
if (is_temporary) {
connection->errcode = PHP_OCI_CALL(OCILobFreeTemporary, (connection->svc, connection->err, descriptor->descriptor));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
}
return 0;
} /* }}} */
/* {{{ php_oci_lob_flush()
Flush buffers for the LOB (only if they have been used) */
int php_oci_lob_flush(php_oci_descriptor *descriptor, int flush_flag TSRMLS_DC)
{
OCILobLocator *lob = descriptor->descriptor;
php_oci_connection *connection = descriptor->connection;
if (!lob) {
return 1;
}
switch (flush_flag) {
case 0:
case OCI_LOB_BUFFER_FREE:
/* only these two are allowed */
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid flag value: %d", flush_flag);
return 1;
break;
}
/* do not really flush buffer, but report success
* to suppress OCI error when flushing not used buffer
* */
if (descriptor->buffering != PHP_OCI_LOB_BUFFER_USED) {
return 0;
}
connection->errcode = PHP_OCI_CALL(OCILobFlushBuffer, (connection->svc, connection->err, lob, flush_flag));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
/* marking buffer as enabled and not used */
descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
return 0;
} /* }}} */
/* {{{ php_oci_lob_free()
Close LOB descriptor and free associated resources */
void php_oci_lob_free (php_oci_descriptor *descriptor TSRMLS_DC)
{
/* flushing Lobs & Files with buffering enabled */
if ((descriptor->type == OCI_DTYPE_FILE || descriptor->type == OCI_DTYPE_LOB) && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED) {
php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
}
PHP_OCI_CALL(OCIDescriptorFree, (descriptor->descriptor, descriptor->type));
efree(descriptor);
} /* }}} */
/* {{{ php_oci_lob_import()
Import LOB contents from the given file */
int php_oci_lob_import (php_oci_descriptor *descriptor, char *filename TSRMLS_DC)
{
int fp, loblen;
OCILobLocator *lob = (OCILobLocator *)descriptor->descriptor;
php_oci_connection *connection = descriptor->connection;
char buf[8192];
ub4 offset = 1;
if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)) {
return 1;
}
if ((fp = VCWD_OPEN(filename, O_RDONLY|O_BINARY)) == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't open file %s", filename);
return 1;
}
while ((loblen = read(fp, &buf, sizeof(buf))) > 0) {
connection->errcode = PHP_OCI_CALL(
OCILobWrite,
(
connection->svc,
connection->err,
lob,
&loblen,
(ub4) offset,
(dvoid *) &buf,
(ub4) loblen,
OCI_ONE_PIECE,
(dvoid *)0,
(OCICallbackLobWrite) 0,
(ub2) 0,
(ub1) SQLCS_IMPLICIT
)
);
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
close(fp);
return 1;
}
offset += loblen;
}
close(fp);
return 0;
} /* }}} */
/* {{{ php_oci_lob_append()
Append data to the end of the LOB */
int php_oci_lob_append (php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from TSRMLS_DC)
{
php_oci_connection *connection = descriptor_dest->connection;
OCILobLocator *lob_dest = descriptor_dest->descriptor;
OCILobLocator *lob_from = descriptor_from->descriptor;
ub4 dest_len, from_len;
if (php_oci_lob_get_length(descriptor_dest, &dest_len TSRMLS_CC)) {
return 1;
}
if (php_oci_lob_get_length(descriptor_from, &from_len TSRMLS_CC)) {
return 1;
}
if (from_len <= 0) {
return 0;
}
connection->errcode = PHP_OCI_CALL(OCILobAppend, (connection->svc, connection->err, lob_dest, lob_from));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
return 0;
} /* }}} */
/* {{{ php_oci_lob_truncate()
Truncate LOB to the given length */
int php_oci_lob_truncate (php_oci_descriptor *descriptor, long new_lob_length TSRMLS_DC)
{
php_oci_connection *connection = descriptor->connection;
OCILobLocator *lob = descriptor->descriptor;
ub4 lob_length;
if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
return 1;
}
if (lob_length <= 0) {
return 0;
}
if (new_lob_length < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size must be greater than or equal to 0");
return 1;
}
if (new_lob_length > lob_length) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size must be less than or equal to the current LOB size");
return 1;
}
connection->errcode = PHP_OCI_CALL(OCILobTrim, (connection->svc, connection->err, lob, new_lob_length));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
descriptor->lob_size = new_lob_length;
return 0;
} /* }}} */
/* {{{ php_oci_lob_erase()
Erase (or fill with whitespaces, depending on LOB type) the LOB (or its part) */
int php_oci_lob_erase (php_oci_descriptor *descriptor, long offset, long length, ub4 *bytes_erased TSRMLS_DC)
{
php_oci_connection *connection = descriptor->connection;
OCILobLocator *lob = descriptor->descriptor;
ub4 lob_length;
*bytes_erased = 0;
if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
return 1;
}
if (offset == -1) {
offset = descriptor->lob_current_position;
}
if (length == -1) {
length = lob_length;
}
connection->errcode = PHP_OCI_CALL(OCILobErase, (connection->svc, connection->err, lob, (ub4 *)&length, offset+1));
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
*bytes_erased = length;
return 0;
} /* }}} */
/* {{{ php_oci_lob_is_equal()
Compare to 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)
{
php_oci_connection *connection = descriptor_first->connection;
OCILobLocator *first_lob = descriptor_first->descriptor;
OCILobLocator *second_lob = descriptor_second->descriptor;
connection->errcode = PHP_OCI_CALL(OCILobIsEqual, (connection->env, first_lob, second_lob, result));
if (connection->errcode) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
return 0;
} /* }}} */
/* {{{ 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, long data_len TSRMLS_DC)
{
php_oci_connection *connection = descriptor->connection;
OCILobLocator *lob = descriptor->descriptor;
ub4 bytes_written = 0;
switch (type) {
case OCI_TEMP_BLOB:
case OCI_TEMP_CLOB:
/* only these two are allowed */
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid temporary lob type: %d", type);
return 1;
break;
}
if (!data || data_len <= 0) {
/* nothing to write, silently fail */
return 1;
}
connection->errcode = PHP_OCI_CALL(OCILobCreateTemporary, (connection->svc, connection->err, lob, OCI_DEFAULT, OCI_DEFAULT, type, OCI_ATTR_NOCACHE, OCI_DURATION_SESSION));
if (connection->errcode) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
connection->errcode = PHP_OCI_CALL(OCILobOpen, (connection->svc, connection->err, lob, OCI_LOB_READWRITE));
if (connection->errcode) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return 1;
}
return php_oci_lob_write(descriptor, 0, data, data_len, &bytes_written TSRMLS_CC);
} /* }}} */
#endif /* HAVE_OCI8 */

992
ext/oci8/oci8_statement.c Normal file
View file

@ -0,0 +1,992 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Stig Sæther Bakken <ssb@php.net> |
| Thies C. Arntzen <thies@thieso.net> |
| Redesigned by: Antony Dovgal <antony@zend.com> |
| Andi Gutmans <andi@zend.com> |
| Wez Furlong <wez@omniti.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "ext/standard/info.h"
#include "php_ini.h"
#if HAVE_OCI8
#include "php_oci8.h"
#include "php_oci8_int.h"
/* {{{ php_oci_statement_create()
Create statemend handle and allocate necessary resources */
php_oci_statement *php_oci_statement_create (php_oci_connection *connection, char *query, long query_len, zend_bool cached TSRMLS_DC)
{
php_oci_statement *statement;
statement = ecalloc(1,sizeof(php_oci_statement));
#if HAVE_OCI_STMT_PREPARE2
if (!query_len) {
/* do not allocate stmt handle for refcursors, we'll get it from OCIStmtPrepare2() */
PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->stmt), OCI_HTYPE_STMT, 0, NULL));
}
#else
PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->stmt), OCI_HTYPE_STMT, 0, NULL));
#endif
PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->err), OCI_HTYPE_ERROR, 0, NULL));
if (query_len > 0) {
#if HAVE_OCI_STMT_PREPARE2
connection->errcode = PHP_OCI_CALL(OCIStmtPrepare2, (connection->svc, &(statement->stmt), connection->err, (text *)query, query_len, NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT));
#else
connection->errcode = PHP_OCI_CALL(OCIStmtPrepare, (statement->stmt, connection->err, (text *)query, query_len, OCI_NTV_SYNTAX, OCI_DEFAULT));
#endif
if (connection->errcode != OCI_SUCCESS) {
php_oci_error(connection->err, connection->errcode TSRMLS_CC);
#if HAVE_OCI_STMT_PREPARE2
PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, OCI_DEFAULT));
PHP_OCI_CALL(OCIHandleFree,(statement->err, OCI_HTYPE_ERROR));
#else
PHP_OCI_CALL(OCIHandleFree,(statement->stmt, OCI_HTYPE_STMT));
PHP_OCI_CALL(OCIHandleFree,(statement->err, OCI_HTYPE_ERROR));
#endif
efree(statement);
PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
return NULL;
}
}
if (query && query_len) {
statement->last_query = estrndup(query, query_len);
statement->last_query_len = query_len;
}
else {
statement->last_query = NULL;
statement->last_query_len = 0;
}
statement->connection = connection;
statement->has_data = 0;
if (OCI_G(default_prefetch) > 0) {
php_oci_statement_set_prefetch(statement, OCI_G(default_prefetch) TSRMLS_CC);
}
PHP_OCI_REGISTER_RESOURCE(statement, le_statement);
return statement;
}
/* }}} */
/* {{{ 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, ub4 size TSRMLS_DC)
{
ub4 prefetch = size * 1024;
if (size < 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows has to be greater than or equal to 1");
return 1;
}
statement->errcode = PHP_OCI_CALL (OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_MEMORY, statement->err));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
prefetch = size;
statement->errcode = PHP_OCI_CALL (OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
return 0;
}
/* }}} */
/* {{{ php_oci_statement_fetch()
Fetch a row from the statement */
int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC)
{
int i;
php_oci_out_column *column;
statement->errcode = PHP_OCI_CALL(OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
if ( statement->errcode == OCI_NO_DATA || nrows == 0 ) {
if (statement->last_query == NULL) {
/* reset define-list for refcursors */
if (statement->columns) {
zend_hash_destroy(statement->columns);
efree(statement->columns);
statement->columns = NULL;
statement->ncolumns = 0;
}
statement->executed = 0;
}
statement->errcode = 0; /* OCI_NO_DATA is NO error for us!!! */
statement->has_data = 0;
if (nrows == 0) {
/* this is exactly what we requested */
return 0;
}
return 1;
}
/* reset length for all piecewise columns */
for (i = 0; i < statement->ncolumns; i++) {
column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
if (column->piecewise) {
column->retlen4 = 0;
}
}
while (statement->errcode == OCI_NEED_DATA) {
for (i = 0; i < statement->ncolumns; i++) {
column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
if (column->piecewise) {
if (!column->data) {
column->data = (text *) emalloc(PHP_OCI_PIECE_SIZE);
} else {
column->data = erealloc(column->data, column->retlen4 + PHP_OCI_PIECE_SIZE);
}
column->cb_retlen = PHP_OCI_PIECE_SIZE;
PHP_OCI_CALL( OCIStmtSetPieceInfo, ((void *) column->oci_define, OCI_HTYPE_DEFINE, statement->err, ((char*)column->data) + column->retlen4, &(column->cb_retlen), OCI_NEXT_PIECE, &column->indicator, &column->retcode));
}
}
statement->errcode = PHP_OCI_CALL( OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
for (i = 0; i < statement->ncolumns; i++) {
column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
if (column && column->piecewise) {
column->retlen4 += column->cb_retlen;
}
}
}
if (statement->errcode == OCI_SUCCESS_WITH_INFO || statement->errcode == OCI_SUCCESS) {
statement->has_data = 1;
/* do the stuff needed for OCIDefineByName */
for (i = 0; i < statement->ncolumns; i++) {
column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
if (column == NULL) {
continue;
}
if (!column->define) {
continue;
}
zval_dtor(column->define->zval);
php_oci_column_to_zval(column, column->define->zval, 0 TSRMLS_CC);
}
return 0;
}
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
statement->has_data = 0;
return 1;
}
/* }}} */
/* {{{ 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, long column_name_len TSRMLS_DC)
{
php_oci_out_column *column = NULL;
int i;
if (statement->columns == NULL) { /* we release the columns at the end of a fetch */
return NULL;
}
if (column_name) {
for (i = 0; i < statement->ncolumns; i++) {
column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
if (column == NULL) {
continue;
} else if (((int) column->name_len == column_name_len) && (!strncmp(column->name, column_name, column_name_len))) {
return column;
}
}
} else if (column_index != -1) {
if (zend_hash_index_find(statement->columns, column_index, (void **)&column) == FAILURE) {
return NULL;
}
return column;
}
return NULL;
}
/* }}} */
/* {{{ php_oci_statement_execute()
Execute statement */
int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
{
php_oci_out_column *outcol;
php_oci_out_column column;
OCIParam *param = NULL;
text *colname;
ub4 counter;
ub2 define_type;
ub4 iters;
ub4 colcount;
ub2 dynamic;
int dtype;
dvoid *buf;
php_oci_descriptor *descr;
switch (mode) {
case OCI_COMMIT_ON_SUCCESS:
case OCI_DEFAULT:
/* only these two are allowed */
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid execute mode given: %d", mode);
return 1;
break;
}
if (!statement->stmttype) {
/* get statement type */
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement->stmttype, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
}
if (statement->stmttype == OCI_STMT_SELECT) {
iters = 0;
} else {
iters = 1;
}
if (statement->last_query) {
/* if we execute refcursors we don't have a query and
we don't want to execute!!! */
if (statement->binds) {
zend_hash_apply(statement->binds, (apply_func_t) php_oci_bind_pre_exec TSRMLS_CC);
}
/* execute statement */
statement->errcode = PHP_OCI_CALL(OCIStmtExecute, (statement->connection->svc, statement->stmt, statement->err, iters, 0, NULL, NULL, mode));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
if (statement->binds) {
zend_hash_apply(statement->binds, (apply_func_t) php_oci_bind_post_exec TSRMLS_CC);
}
if (mode & OCI_COMMIT_ON_SUCCESS) {
statement->connection->needs_commit = 0;
} else {
statement->connection->needs_commit = 1;
}
}
if (statement->stmttype == OCI_STMT_SELECT && statement->executed == 0) {
/* we only need to do the define step is this very statement is executed the first time! */
statement->executed = 1;
ALLOC_HASHTABLE(statement->columns);
zend_hash_init(statement->columns, 13, NULL, php_oci_column_hash_dtor, 0);
counter = 1;
/* get number of columns */
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *)&colcount, (ub4 *)0, OCI_ATTR_PARAM_COUNT, statement->err));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
statement->ncolumns = colcount;
for (counter = 1; counter <= colcount; counter++) {
memset(&column,0,sizeof(php_oci_out_column));
if (zend_hash_index_update(statement->columns, counter, &column, sizeof(php_oci_out_column), (void**) &outcol) == FAILURE) {
efree(statement->columns);
/* out of memory */
return 1;
}
outcol->statement = statement;
/* get column */
statement->errcode = PHP_OCI_CALL(OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)&param, counter));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
/* get column datatype */
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_type, (ub4 *)0, OCI_ATTR_DATA_TYPE, statement->err));
if (statement->errcode != OCI_SUCCESS) {
PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
/* get size of the column */
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_size, (dvoid *)0, OCI_ATTR_DATA_SIZE, statement->err));
if (statement->errcode != OCI_SUCCESS) {
PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
outcol->storage_size4 = outcol->data_size;
outcol->retlen = outcol->data_size;
/* get scale of the column */
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err));
if (statement->errcode != OCI_SUCCESS) {
PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
/* get precision of the column */
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err));
if (statement->errcode != OCI_SUCCESS) {
PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
/* get name of the column */
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid **)&colname, (ub4 *)&outcol->name_len, (ub4)OCI_ATTR_NAME, statement->err));
if (statement->errcode != OCI_SUCCESS) {
PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
outcol->name = estrndup((char*) colname, outcol->name_len);
/* find a user-setted define */
if (statement->defines) {
zend_hash_find(statement->defines,outcol->name,outcol->name_len,(void **) &outcol->define);
}
buf = 0;
switch (outcol->data_type) {
case SQLT_RSET:
outcol->statement = php_oci_statement_create(statement->connection, NULL, 0, 0 TSRMLS_CC);
outcol->stmtid = outcol->statement->id;
define_type = SQLT_RSET;
outcol->is_cursor = 1;
outcol->storage_size4 = -1;
outcol->retlen = -1;
dynamic = OCI_DEFAULT;
buf = &(outcol->statement->stmt);
break;
case SQLT_RDD: /* ROWID */
case SQLT_BLOB: /* binary LOB */
case SQLT_CLOB: /* character LOB */
case SQLT_BFILE: /* binary file LOB */
define_type = outcol->data_type;
outcol->is_descr = 1;
outcol->storage_size4 = -1;
dynamic = OCI_DEFAULT;
if (outcol->data_type == SQLT_BFILE) {
dtype = OCI_DTYPE_FILE;
} else if (outcol->data_type == SQLT_RDD ) {
dtype = OCI_DTYPE_ROWID;
} else {
dtype = OCI_DTYPE_LOB;
}
descr = php_oci_lob_create(statement->connection, dtype TSRMLS_CC);
if (!descr) {
efree(outcol->name);
return 1;
}
outcol->descid = descr->id;
buf = &(descr->descriptor);
break;
case SQLT_LNG:
case SQLT_LBI:
if (outcol->data_type == SQLT_LBI) {
define_type = SQLT_BIN;
} else {
define_type = SQLT_CHR;
}
outcol->storage_size4 = PHP_OCI_MAX_DATA_SIZE;
outcol->piecewise = 1;
dynamic = OCI_DYNAMIC_FETCH;
break;
case SQLT_BIN:
default:
define_type = SQLT_CHR;
if ((outcol->data_type == SQLT_DAT) || (outcol->data_type == SQLT_NUM)
#ifdef SQLT_TIMESTAMP
|| (outcol->data_type == SQLT_TIMESTAMP)
#endif
#ifdef SQLT_TIMESTAMP_TZ
|| (outcol->data_type == SQLT_TIMESTAMP_TZ)
#endif
) {
outcol->storage_size4 = 512; /* XXX this should fit "most" NLS date-formats and Numbers */
} else {
outcol->storage_size4++; /* add one for string terminator */
}
outcol->storage_size4 *= 3;
dynamic = OCI_DEFAULT;
buf = outcol->data = (text *) emalloc(outcol->storage_size4);
break;
}
if (dynamic == OCI_DYNAMIC_FETCH) {
statement->errcode = PHP_OCI_CALL(
OCIDefineByPos,
(
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 */
(dvoid *)NULL, /* IN/OUT pointer to a buffer */
outcol->storage_size4, /* IN The size of each valuep buffer in bytes */
define_type, /* IN The data type */
(dvoid *)&outcol->indicator, /* IN pointer to an indicator variable or arr */
(ub2 *)NULL, /* IN/OUT Pointer to array of length of data fetched */
(ub2 *)NULL, /* OUT Pointer to array of column-level return codes */
OCI_DYNAMIC_FETCH /* IN mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
)
);
} else {
statement->errcode = PHP_OCI_CALL(
OCIDefineByPos,
(
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 */
(dvoid *)buf, /* IN/OUT pointer to a buffer */
outcol->storage_size4, /* IN The size of each valuep buffer in bytes */
define_type, /* IN The data type */
(dvoid *)&outcol->indicator, /* IN pointer to an indicator variable or arr */
(ub2 *)&outcol->retlen, /* IN/OUT Pointer to array of length of data fetched */
(ub2 *)&outcol->retcode, /* OUT Pointer to array of column-level return codes */
OCI_DEFAULT /* IN mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
)
);
}
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 0;
}
}
}
return 0;
}
/* }}} */
/* {{{ php_oci_statement_cancel()
Cancel statement */
int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC)
{
return php_oci_statement_fetch(statement, 0 TSRMLS_CC);
} /* }}} */
/* {{{ 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 HAVE_OCI_STMT_PREPARE2
if (statement->last_query_len) { /* FIXME: magical */
PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, OCI_DEFAULT));
}
else {
PHP_OCI_CALL(OCIHandleFree, (statement->stmt, OCI_HTYPE_STMT));
}
#else
PHP_OCI_CALL(OCIHandleFree, (statement->stmt, OCI_HTYPE_STMT));
#endif
statement->stmt = 0;
}
if (statement->err) {
PHP_OCI_CALL(OCIHandleFree, (statement->err, OCI_HTYPE_ERROR));
statement->err = 0;
}
if (statement->last_query) {
efree(statement->last_query);
}
if (statement->columns) {
zend_hash_destroy(statement->columns);
efree(statement->columns);
}
if (statement->binds) {
zend_hash_destroy(statement->binds);
efree(statement->binds);
}
if (statement->defines) {
zend_hash_destroy(statement->defines);
efree(statement->defines);
}
efree(statement);
} /* }}} */
/* {{{ php_oci_bind_pre_exec()
Helper function */
int php_oci_bind_pre_exec(void *data TSRMLS_DC)
{
php_oci_bind *bind = (php_oci_bind *) data;
/* reset all bind stuff to a normal state..-. */
bind->indicator = 0;
return 0;
}
/* }}} */
/* {{{ php_oci_bind_post_exec()
Helper function */
int php_oci_bind_post_exec(void *data TSRMLS_DC)
{
php_oci_bind *bind = (php_oci_bind *) data;
if (bind->indicator == -1) { /* NULL */
zval *val = bind->zval;
if (Z_TYPE_P(val) == IS_STRING) {
*Z_STRVAL_P(val) = '\0'; /* XXX avoid warning in debug mode */
}
zval_dtor(val);
ZVAL_NULL(val);
} else if (Z_TYPE_P(bind->zval) == IS_STRING) {
Z_STRVAL_P(bind->zval) = erealloc(Z_STRVAL_P(bind->zval), Z_STRLEN_P(bind->zval)+1);
Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] = '\0';
}
return 0;
}
/* }}} */
/* {{{ php_oci_bind_by_name()
Bind zval to the given placeholder */
int php_oci_bind_by_name(php_oci_statement *statement, char *name, long name_len, zval* var, long maxlength, long type TSRMLS_DC)
{
php_oci_collection *bind_collection = NULL;
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_bind bind, *bindp;
int mode = OCI_DATA_AT_EXEC;
sb4 value_sz = -1;
switch (type) {
#ifdef PHP_OCI8_HAVE_COLLECTIONS
case SQLT_NTY:
{
zval **tmp;
if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
return 1;
}
PHP_OCI_ZVAL_TO_COLLECTION_EX(*tmp, bind_collection);
value_sz = sizeof(void*);
mode = OCI_DEFAULT;
if (!bind_collection->collection) {
return 1;
}
}
break;
#endif
case SQLT_BFILEE:
case SQLT_CFILEE:
case SQLT_CLOB:
case SQLT_BLOB:
case SQLT_RDD:
{
zval **tmp;
if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
return 1;
}
PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, bind_descriptor);
value_sz = sizeof(void*);
oci_desc = bind_descriptor->descriptor;
if (!oci_desc) {
return 1;
}
}
break;
case SQLT_INT:
case SQLT_NUM:
convert_to_long(var);
bind_data = (ub4 *)&Z_LVAL_P(var);
value_sz = sizeof(ub4);
mode = OCI_DEFAULT;
break;
case SQLT_CHR:
/* this is the default case when type was not specified */
convert_to_string(var);
if (maxlength == -1) {
value_sz = Z_STRLEN_P(var);
}
else {
value_sz = maxlength;
}
break;
case SQLT_RSET:
PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement);
value_sz = sizeof(void*);
oci_stmt = bind_statement->stmt;
if (!oci_stmt) {
return 1;
}
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %ld", type);
return 1;
break;
}
if (value_sz == 0) {
value_sz = 1;
}
if (!statement->binds) {
ALLOC_HASHTABLE(statement->binds);
zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
}
memset((void*)&bind,0,sizeof(php_oci_bind));
zend_hash_update(statement->binds, name, name_len + 1, &bind, sizeof(php_oci_bind), (void **)&bindp);
bindp->descriptor = oci_desc;
bindp->statement = oci_stmt;
bindp->zval = var;
zval_add_ref(&var);
statement->errcode = PHP_OCI_CALL(
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 */
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 */
)
);
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
if (mode == OCI_DATA_AT_EXEC) {
statement->errcode = PHP_OCI_CALL(OCIBindDynamic, (bindp->bind, statement->err, (dvoid *)bindp, php_oci_bind_in_callback, (dvoid *)bindp, php_oci_bind_out_callback));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
}
#ifdef PHP_OCI8_HAVE_COLLECTIONS
if (type == SQLT_NTY) {
/* Bind object */
statement->errcode = PHP_OCI_CALL(OCIBindObject, (bindp->bind, statement->err, bind_collection->tdo, (dvoid **) &(bind_collection->collection), (ub4 *) 0, (dvoid **) 0, (ub4 *) 0));
if (statement->errcode) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
}
#endif
return 0;
} /* }}} */
/* {{{ 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 */
{
php_oci_bind *phpbind;
zval *val;
TSRMLS_FETCH();
if (!(phpbind=(php_oci_bind *)ictxp) || !(val = phpbind->zval)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
return OCI_ERROR;
}
if (ZVAL_IS_NULL(val)) {
/* we're going to insert a NULL column */
phpbind->indicator = -1;
*bufpp = 0;
*alenp = -1;
*indpp = (dvoid *)&phpbind->indicator;
} else if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
/* "normal string bind */
convert_to_string(val);
*bufpp = Z_STRVAL_P(val);
*alenp = Z_STRLEN_P(val);
*indpp = (dvoid *)&phpbind->indicator;
} else if (phpbind->statement != 0) {
/* RSET */
*bufpp = phpbind->statement;
*alenp = -1; /* seems to be allright */
*indpp = (dvoid *)&phpbind->indicator;
} else {
/* descriptor bind */
*bufpp = phpbind->descriptor;
*alenp = -1; /* seems to be allright */
*indpp = (dvoid *)&phpbind->indicator;
}
*piecep = OCI_ONE_PIECE; /* pass all data in one go */
return OCI_CONTINUE;
}/* }}} */
/* {{{ 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 */
{
php_oci_bind *phpbind;
zval *val;
sb4 retval = OCI_ERROR;
TSRMLS_FETCH();
if (!(phpbind=(php_oci_bind *)octxp) || !(val = phpbind->zval)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
return retval;
}
if ((Z_TYPE_P(val) == IS_OBJECT) || (Z_TYPE_P(val) == IS_RESOURCE)) {
retval = OCI_CONTINUE;
} else {
convert_to_string(val);
zval_dtor(val);
Z_STRLEN_P(val) = PHP_OCI_PIECE_SIZE; /* 64K-1 is max XXX */
Z_STRVAL_P(val) = emalloc(Z_STRLEN_P(phpbind->zval));
/* XXX we assume that zend-zval len has 4 bytes */
*alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
*bufpp = Z_STRVAL_P(phpbind->zval);
*piecep = OCI_ONE_PIECE;
*rcodepp = &phpbind->retcode;
*indpp = &phpbind->indicator;
retval = OCI_CONTINUE;
}
return retval;
}
/* }}} */
/* {{{ 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)
{
zval *z_statement, *column_index;
php_oci_statement *statement;
php_oci_out_column *column;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_statement, &column_index) == FAILURE) {
return NULL;
}
statement = (php_oci_statement *) zend_fetch_resource(&z_statement TSRMLS_CC, -1, "oci8 statement", NULL, 1, le_statement);
if (!statement) {
return NULL;
}
if (Z_TYPE_P(column_index) == IS_STRING) {
column = php_oci_statement_get_column(statement, -1, Z_STRVAL_P(column_index), Z_STRLEN_P(column_index) TSRMLS_CC);
if (!column) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column name \"%s\"", Z_STRVAL_P(column_index));
return NULL;
}
}
else {
convert_to_long(column_index);
column = php_oci_statement_get_column(statement, Z_LVAL_P(column_index), NULL, 0 TSRMLS_CC);
if (!column) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column index \"%ld\"", Z_LVAL_P(column_index));
return NULL;
}
}
return column;
} /* }}} */
/* {{{ php_oci_statement_get_type()
Return type of the statement */
int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type TSRMLS_DC)
{
ub2 statement_type;
*type = 0;
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement_type, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
*type = statement_type;
return 0;
} /* }}} */
/* {{{ 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)
{
ub4 statement_numrows;
*numrows = 0;
statement->errcode = PHP_OCI_CALL(OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub4 *)&statement_numrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, statement->err));
if (statement->errcode != OCI_SUCCESS) {
php_oci_error(statement->err, statement->errcode TSRMLS_CC);
PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
return 1;
}
*numrows = statement_numrows;
return 0;
} /* }}} */
#endif /* HAVE_OCI8 */

View file

@ -12,8 +12,11 @@
| obtain it through the world-wide-web, please send a note to | | obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. | | license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
| Authors: Stig Sæther Bakken <ssb@php.net> | | Authors: Stig Sæther Bakken <ssb@php.net> |
| Thies C. Arntzen <thies@thieso.net> | | Thies C. Arntzen <thies@thieso.net> |
| Redesigned by: Antony Dovgal <antony@zend.com> |
| Andi Gutmans <andi@zend.com> |
| Wez Furlong <wez@omniti.com> |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
*/ */
@ -22,19 +25,6 @@
#if HAVE_OCI8 #if HAVE_OCI8
# ifndef PHP_OCI8_H # ifndef PHP_OCI8_H
# define PHP_OCI8_H # define PHP_OCI8_H
# endif
# if (defined(__osf__) && defined(__alpha))
# ifndef A_OSF
# define A_OSF
# endif
# ifndef OSF1
# define OSF1
# endif
# ifndef _INTRINSICS
# define _INTRINSICS
# endif
# endif /* osf alpha */
#ifdef PHP_WIN32 #ifdef PHP_WIN32
#define PHP_OCI_API __declspec(dllexport) #define PHP_OCI_API __declspec(dllexport)
@ -42,175 +32,21 @@
#define PHP_OCI_API #define PHP_OCI_API
#endif #endif
#if defined(min) #ifdef ZTS
#undef min # include "TSRM.h"
#endif #endif
#if defined(max)
#undef max
#endif
#include <oci.h>
#define OCI_SEEK_SET 0
#define OCI_SEEK_CUR 1
#define OCI_SEEK_END 2
typedef struct {
int num;
int persistent;
int is_open;
char *dbname;
OCIServer *pServer;
#if 0
OCIFocbkStruct failover;
#endif
} oci_server;
typedef struct {
int num;
zend_bool persistent;
zend_bool is_open;
zend_bool exclusive;
#if ZTS
THREAD_T thread;
#else
zend_bool thread;
#endif
zend_llist *sessions_list;
oci_server *server;
OCISession *pSession;
OCIEnv *pEnv; /* sessions own environment */
ub2 charsetId; /* sessions used character set (mostly this will be 0, so NLS_LANG will be used. */
} oci_session;
typedef struct {
int id;
int is_open;
oci_session *session;
OCISvcCtx *pServiceContext;
sword error;
OCIError *pError;
int needs_commit;
HashTable *descriptors;
} oci_connection;
typedef struct {
int id;
oci_connection *conn;
dvoid *ocidescr;
ub4 type;
int lob_current_position;
int lob_size; /* -1 = Lob wasn't initialized yet */
int buffering; /* 0 - off, 1 - on, 2 - on and buffer was used */
} oci_descriptor;
typedef struct {
int id;
oci_connection *conn;
OCIType *tdo;
OCITypeCode coll_typecode;
OCIRef *elem_ref;
OCIType *element_type;
OCITypeCode element_typecode;
OCIColl *coll;
} oci_collection;
typedef struct {
zval *zval;
text *name;
ub4 name_len;
ub4 type;
} oci_define;
typedef struct {
int id;
oci_connection *conn;
sword error;
OCIError *pError;
OCIStmt *pStmt;
char *last_query;
HashTable *columns;
HashTable *binds;
HashTable *defines;
int ncolumns;
int executed;
int has_data;
ub2 stmttype;
} oci_statement;
typedef struct {
OCIBind *pBind;
zval *zval;
dvoid *descr; /* used for binding of LOBS etc */
OCIStmt *pStmt; /* used for binding REFCURSORs */
sb2 indicator;
ub2 retcode;
} oci_bind;
typedef struct {
oci_statement *statement;
OCIDefine *pDefine;
char *name;
ub4 name_len;
ub2 data_type;
ub2 data_size;
ub4 storage_size4;
sb2 indicator;
ub2 retcode;
ub2 retlen;
ub4 retlen4;
ub2 is_descr;
ub2 is_cursor;
int descr;
oci_statement *pstmt;
int stmtid;
int descid;
void *data;
oci_define *define;
int piecewise;
ub4 cb_retlen;
ub2 scale;
ub2 precision;
} oci_out_column;
typedef struct {
sword error;
OCIError *pError;
/*
char *default_username;
char *default_password;
char *default_dbname;
*/
long debug_mode;
int shutdown;
/* XXX NYI
long allow_persistent;
long max_persistent;
long max_links;
*/
OCIEnv *pEnv;
int in_call;
} php_oci_globals;
extern zend_module_entry oci8_module_entry; extern zend_module_entry oci8_module_entry;
#define phpext_oci8_ptr &oci8_module_entry #define phpext_oci8_ptr &oci8_module_entry
#define OCI_MAX_NAME_LEN 64
#define OCI_MAX_DATA_SIZE INT_MAX
#define OCI_PIECE_SIZE (64*1024)-1
#ifdef ZTS PHP_MINIT_FUNCTION(oci);
#define OCI(v) TSRMG(oci_globals_id, php_oci_globals *, v) PHP_RINIT_FUNCTION(oci);
#else PHP_MSHUTDOWN_FUNCTION(oci);
#define OCI(v) (oci_globals.v) PHP_RSHUTDOWN_FUNCTION(oci);
#endif PHP_MINFO_FUNCTION(oci);
# endif /* !PHP_OCI8_H */
#else /* !HAVE_OCI8 */ #else /* !HAVE_OCI8 */
# define oci8_module_ptr NULL # define oci8_module_ptr NULL
@ -223,3 +59,5 @@ extern zend_module_entry oci8_module_entry;
* c-basic-offset: 4 * c-basic-offset: 4
* End: * End:
*/ */

404
ext/oci8/php_oci8_int.h Normal file
View file

@ -0,0 +1,404 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Stig Sæther Bakken <ssb@php.net> |
| Thies C. Arntzen <thies@thieso.net> |
| Redesigned by: Antony Dovgal <antony@zend.com> |
| Andi Gutmans <andi@zend.com> |
| Wez Furlong <wez@omniti.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#undef HAVE_OCI_STMT_PREPARE2
#if HAVE_OCI8
# ifndef PHP_OCI8_INT_H
# define PHP_OCI8_INT_H
/* misc defines {{{ */
# if (defined(__osf__) && defined(__alpha))
# ifndef A_OSF
# define A_OSF
# endif
# ifndef OSF1
# define OSF1
# endif
# ifndef _INTRINSICS
# define _INTRINSICS
# endif
# endif /* osf alpha */
#if defined(min)
#undef min
#endif
#if defined(max)
#undef max
#endif
/* }}} */
#include <oci.h>
extern int le_connection;
extern int le_pconnection;
extern int le_statement;
extern int le_descriptor;
#ifdef PHP_OCI8_HAVE_COLLECTIONS
extern int le_collection;
#endif
extern int le_server;
extern int le_session;
extern zend_class_entry *oci_lob_class_entry_ptr;
#ifdef PHP_OCI8_HAVE_COLLECTIONS
extern zend_class_entry *oci_coll_class_entry_ptr;
#endif
/* constants {{{ */
#define PHP_OCI_SEEK_SET 0
#define PHP_OCI_SEEK_CUR 1
#define PHP_OCI_SEEK_END 2
#define PHP_OCI_MAX_NAME_LEN 64
#define PHP_OCI_MAX_DATA_SIZE INT_MAX
#define PHP_OCI_PIECE_SIZE (64*1024)-1
#define PHP_OCI_LOB_BUFFER_SIZE 1048576l
#define PHP_OCI_ASSOC 1<<0
#define PHP_OCI_NUM 1<<1
#define PHP_OCI_BOTH (PHP_OCI_ASSOC|PHP_OCI_NUM)
#define PHP_OCI_RETURN_NULLS 1<<2
#define PHP_OCI_RETURN_LOBS 1<<3
#define PHP_OCI_FETCHSTATEMENT_BY_COLUMN 1<<4
#define PHP_OCI_FETCHSTATEMENT_BY_ROW 1<<5
#define PHP_OCI_FETCHSTATEMENT_BY (PHP_OCI_FETCHSTATEMENT_BY_COLUMN | PHP_OCI_FETCHSTATEMENT_BY_ROW)
#define PHP_OCI_LOB_BUFFER_DISABLED 0
#define PHP_OCI_LOB_BUFFER_ENABLED 1
#define PHP_OCI_LOB_BUFFER_USED 2
/* }}} */
typedef struct { /* php_oci_connection {{{ */
OCIEnv *env; /* private env handle */
ub2 charset; /* charset ID */
OCIServer *server; /* private server handle */
OCISvcCtx *svc; /* private service context handle */
OCISession *session; /* private session handle */
OCIError *err; /* private error handle */
sword errcode; /* last errcode */
HashTable *descriptors; /* descriptors hash, used to flush all the LOBs using this connection on commit */
unsigned is_open:1; /* hels to determine if the connection is dead or not */
unsigned is_attached:1; /* hels to determine if we should detach from the server when closing/freeing the connection */
unsigned is_persistent:1; /* self-descriptive */
unsigned used_this_request:1; /* helps to determine if we should reset connection's next ping time and check its timeout */
unsigned needs_commit:1; /* helps to determine if we should rollback this connection on close/shutdown */
int rsrc_id; /* resource ID */
time_t idle_expiry; /* time when the connection will be considered as expired */
time_t next_ping; /* time of the next ping */
char *hash_key; /* hashed details of the connection */
} php_oci_connection; /* }}} */
typedef struct { /* php_oci_descriptor {{{ */
int id;
php_oci_connection *connection; /* parent connection handle */
dvoid *descriptor; /* OCI descriptor handle */
ub4 type; /* descriptor type */
int lob_current_position; /* LOB internal pointer */
int lob_size; /* cached LOB size. -1 = Lob wasn't initialized yet */
int buffering; /* cached buffering flag. 0 - off, 1 - on, 2 - on and buffer was used */
} php_oci_descriptor; /* }}} */
typedef struct { /* php_oci_collection {{{ */
int id;
php_oci_connection *connection; /* parent connection handle */
OCIType *tdo; /* collection's type handle */
OCITypeCode coll_typecode; /* collection's typecode handle */
OCIRef *elem_ref; /* element's reference handle */
OCIType *element_type; /* element's type handle */
OCITypeCode element_typecode; /* element's typecode handle */
OCIColl *collection; /* collection handle */
} php_oci_collection; /* }}} */
typedef struct { /* php_oci_define {{{ */
zval *zval; /* zval used in define */
text *name; /* placeholder's name */
ub4 name_len; /* placeholder's name length */
ub4 type; /* define type */
} php_oci_define; /* }}} */
typedef struct { /* php_oci_statement {{{ */
int id;
php_oci_connection *connection; /* parent connection handle */
sword errcode; /* last errcode*/
OCIError *err; /* private error handle */
OCIStmt *stmt; /* statement handle */
char *last_query; /* last query issued. also used to determine if this is a statement or a refcursor recieved from Oracle */
long last_query_len; /* last query length */
HashTable *columns; /* hash containing all the result columns */
HashTable *binds; /* binds hash */
HashTable *defines; /* defines hash */
int ncolumns; /* number of columns in the result */
unsigned executed:1; /* statement executed flag */
unsigned has_data:1; /* statement has more data flag */
ub2 stmttype; /* statement type */
} php_oci_statement; /* }}} */
typedef struct { /* php_oci_bind {{{ */
OCIBind *bind; /* bind handle */
zval *zval; /* value */
dvoid *descriptor; /* used for binding of LOBS etc */
OCIStmt *statement; /* used for binding REFCURSORs */
sb2 indicator; /* */
ub2 retcode; /* */
} php_oci_bind; /* }}} */
typedef struct { /* php_oci_out_column {{{ */
php_oci_statement *statement; /* statement handle. used when fetching REFCURSORS */
OCIDefine *oci_define; /* define handle */
char *name; /* column name */
ub4 name_len; /* column name length */
ub2 data_type; /* column data type */
ub2 data_size; /* data size */
ub4 storage_size4; /* size used when allocating buffers */
sb2 indicator; /* */
ub2 retcode; /* code returned when fetching this particular column */
ub2 retlen; /* */
ub4 retlen4; /* */
ub2 is_descr; /* column contains a descriptor */
ub2 is_cursor; /* column contains a cursor */
int stmtid; /* statement id for cursors */
int descid; /* descriptor id for descriptors */
void *data; /* */
php_oci_define *define; /* define handle */
int piecewise; /* column is fetched piece-by-piece */
ub4 cb_retlen; /* */
ub2 scale; /* column scale */
ub2 precision; /* column precision */
} php_oci_out_column; /* }}} */
/* {{{ macros */
#define PHP_OCI_CALL(func, params) \
func params; \
if (OCI_G(debug_mode)) { \
php_printf ("OCI8 DEBUG: " #func " in %s() (%s:%d) \n", __FUNCTION__, __FILE__, __LINE__); \
}
/*
\
*/
#define PHP_OCI_HANDLE_ERROR(connection, errcode) \
{ \
switch (errcode) { \
case 1013: \
zend_bailout(); \
break; \
case 22: \
case 1012: \
case 3113: \
case 604: \
case 1041: \
case 3114: \
connection->is_open = 0; \
break; \
} \
} \
#define PHP_OCI_REGISTER_RESOURCE(resource, le_resource) \
resource->id = ZEND_REGISTER_RESOURCE(NULL, resource, le_resource); \
zend_list_addref(resource->connection->rsrc_id);
#define PHP_OCI_ZVAL_TO_CONNECTION(zval, connection) \
ZEND_FETCH_RESOURCE2(connection, php_oci_connection *, &zval, -1, "oci8 connection", le_connection, le_pconnection);
#define PHP_OCI_ZVAL_TO_STATEMENT(zval, statement) \
ZEND_FETCH_RESOURCE(statement, php_oci_statement *, &zval, -1, "oci8 statement", le_statement)
#define PHP_OCI_ZVAL_TO_DESCRIPTOR(zval, descriptor) \
ZEND_FETCH_RESOURCE(descriptor, php_oci_descriptor *, &zval, -1, "oci8 descriptor", le_descriptor)
#define PHP_OCI_ZVAL_TO_COLLECTION(zval, collection) \
ZEND_FETCH_RESOURCE(collection, php_oci_collection *, &zval, -1, "oci8 collection", le_collection)
#define PHP_OCI_FETCH_RESOURCE_EX(zval, var, type, name, resource_type) \
var = (type) zend_fetch_resource(&zval TSRMLS_CC, -1, name, NULL, 1, resource_type); \
if (!var) { \
return 1; \
}
#define PHP_OCI_ZVAL_TO_CONNECTION_EX(zval, connection) \
PHP_OCI_FETCH_RESOURCE_EX(zval, connection, php_oci_connection *, "oci8 connection", le_connection)
#define PHP_OCI_ZVAL_TO_STATEMENT_EX(zval, statement) \
PHP_OCI_FETCH_RESOURCE_EX(zval, statement, php_oci_statement *, "oci8 statement", le_statement)
#define PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(zval, descriptor) \
PHP_OCI_FETCH_RESOURCE_EX(zval, descriptor, php_oci_descriptor *, "oci8 descriptor", le_descriptor)
#define PHP_OCI_ZVAL_TO_COLLECTION_EX(zval, collection) \
PHP_OCI_FETCH_RESOURCE_EX(zval, collection, php_oci_collection *, "oci8 collection", le_collection)
/* }}} */
/* PROTOS */
/* main prototypes {{{ */
void php_oci_column_hash_dtor (void *data);
void php_oci_define_hash_dtor (void *data);
void php_oci_bind_hash_dtor (void *data);
void php_oci_descriptor_flush_hash_dtor (void *data);
sb4 php_oci_error (OCIError *, sword TSRMLS_DC);
sb4 php_oci_fetch_errmsg(OCIError *, text ** TSRMLS_DC);
#ifdef HAVE_OCI8_ATTR_STATEMENT
int php_oci_fetch_sqltext_offset(php_oci_statement *, text **, ub2 * TSRMLS_DC);
#endif
void php_oci_do_connect (INTERNAL_FUNCTION_PARAMETERS, int , int);
php_oci_connection *php_oci_do_connect_ex(char *username, long username_len, char *password, long password_len, char *new_password, long new_password_len, char *dbname, long dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC);
int php_oci_connection_rollback(php_oci_connection * TSRMLS_DC);
int php_oci_connection_commit(php_oci_connection * TSRMLS_DC);
int php_oci_password_change(php_oci_connection *, char *, long, char *, long, char *, long TSRMLS_DC);
int php_oci_server_get_version(php_oci_connection *, char ** TSRMLS_DC);
void php_oci_fetch_row(INTERNAL_FUNCTION_PARAMETERS, int, int);
int php_oci_column_to_zval(php_oci_out_column *, zval *, int TSRMLS_DC);
/* }}} */
/* lob related prototypes {{{ */
php_oci_descriptor * php_oci_lob_create (php_oci_connection *, long TSRMLS_DC);
int php_oci_lob_get_length (php_oci_descriptor *, ub4 * TSRMLS_DC);
int php_oci_lob_read (php_oci_descriptor *, long, long, char **, ub4 * TSRMLS_DC);
int php_oci_lob_write (php_oci_descriptor *, ub4, char *, long, ub4 * TSRMLS_DC);
int php_oci_lob_flush (php_oci_descriptor *, int TSRMLS_DC);
int php_oci_lob_set_buffering (php_oci_descriptor *, int TSRMLS_DC);
int php_oci_lob_get_buffering (php_oci_descriptor * TSRMLS_DC);
int php_oci_lob_copy (php_oci_descriptor *, php_oci_descriptor *, long TSRMLS_DC);
#ifdef HAVE_OCI8_TEMP_LOB
int php_oci_lob_close (php_oci_descriptor * TSRMLS_DC);
int php_oci_lob_write_tmp (php_oci_descriptor *, ub1, char *, long TSRMLS_DC);
#endif
void php_oci_lob_free(php_oci_descriptor * TSRMLS_DC);
int php_oci_lob_import(php_oci_descriptor *descriptor, char * TSRMLS_DC);
int php_oci_lob_append (php_oci_descriptor *, php_oci_descriptor * TSRMLS_DC);
int php_oci_lob_truncate (php_oci_descriptor *, long TSRMLS_DC);
int php_oci_lob_erase (php_oci_descriptor *, long, long, ub4 * TSRMLS_DC);
int php_oci_lob_is_equal (php_oci_descriptor *, php_oci_descriptor *, boolean * TSRMLS_DC);
/* }}} */
/* collection related prototypes {{{ */
php_oci_collection * php_oci_collection_create(php_oci_connection *, char *, long, char *, long TSRMLS_DC);
int php_oci_collection_size(php_oci_collection *, sb4 * TSRMLS_DC);
int php_oci_collection_max(php_oci_collection *, long * TSRMLS_DC);
int php_oci_collection_trim(php_oci_collection *, long TSRMLS_DC);
int php_oci_collection_append(php_oci_collection *, char *, long TSRMLS_DC);
int php_oci_collection_element_get(php_oci_collection *, long, zval** TSRMLS_DC);
int php_oci_collection_element_set(php_oci_collection *, long, char*, long TSRMLS_DC);
int php_oci_collection_element_set_null(php_oci_collection *, long TSRMLS_DC);
int php_oci_collection_element_set_date(php_oci_collection *, long, char *, long TSRMLS_DC);
int php_oci_collection_element_set_number(php_oci_collection *, long, char *, long TSRMLS_DC);
int php_oci_collection_element_set_string(php_oci_collection *, long, char *, long TSRMLS_DC);
int php_oci_collection_assign(php_oci_collection *, php_oci_collection * TSRMLS_DC);
void php_oci_collection_close(php_oci_collection * TSRMLS_DC);
int php_oci_collection_append_null(php_oci_collection * TSRMLS_DC);
int php_oci_collection_append_date(php_oci_collection *, char *, long TSRMLS_DC);
int php_oci_collection_append_number(php_oci_collection *, char *, long TSRMLS_DC);
int php_oci_collection_append_string(php_oci_collection *, char *, long TSRMLS_DC);
/* }}} */
/* statement related prototypes {{{ */
php_oci_statement * php_oci_statement_create (php_oci_connection *, char *, long, zend_bool TSRMLS_DC);
int php_oci_statement_set_prefetch (php_oci_statement *, ub4 TSRMLS_DC);
int php_oci_statement_fetch (php_oci_statement *, ub4 TSRMLS_DC);
php_oci_out_column * php_oci_statement_get_column (php_oci_statement *, long, char*, long TSRMLS_DC);
int php_oci_statement_execute (php_oci_statement *, ub4 TSRMLS_DC);
int php_oci_statement_cancel (php_oci_statement * TSRMLS_DC);
void php_oci_statement_free (php_oci_statement * TSRMLS_DC);
int php_oci_bind_pre_exec(void *data TSRMLS_DC);
int php_oci_bind_post_exec(void *data TSRMLS_DC);
int php_oci_bind_by_name(php_oci_statement *, char *, long, zval*, long, long TSRMLS_DC);
sb4 php_oci_bind_in_callback(dvoid *, OCIBind *, ub4, ub4, dvoid **, ub4 *, ub1 *, dvoid **);
sb4 php_oci_bind_out_callback(dvoid *, OCIBind *, ub4, ub4, dvoid **, ub4 **, ub1 *, dvoid **, ub2 **);
php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS);
int php_oci_statement_get_type(php_oci_statement *, ub2 * TSRMLS_DC);
int php_oci_statement_get_numrows(php_oci_statement *, ub4 * TSRMLS_DC);
/* }}} */
ZEND_BEGIN_MODULE_GLOBALS(oci) /* {{{ */
sword errcode; /* global last error code (used when connect fails, for example) */
OCIError *err; /* global error handle */
/*
char *default_username;
char *default_password;
char *default_dbname;
*/
zend_bool debug_mode; /* debug mode flag */
long max_persistent; /* maximum number of persistent connections per process */
long num_persistent; /* number of existing persistent connections */
long num_links; /* non-persistent + persistent connections */
long ping_interval; /* time interval between pings */
long persistent_timeout; /* time period after which idle persistent connection is considered expired */
long statement_cache_size; /* statement cache size. used with 9i+ clients only*/
long default_prefetch; /* default prefetch setting */
zend_bool privileged_connect; /* privileged connect flag (On/Off) */
zend_bool old_oci_close_semantics; /* old_oci_close_semantics flag (to determine the way oci_close() should behave) */
int shutdown; /* in shutdown flag */
OCIEnv *env; /* global environment handle */
ZEND_END_MODULE_GLOBALS(oci) /* }}} */
#ifdef ZTS
#define OCI_G(v) TSRMG(oci_globals_id, zend_oci_globals *, v)
#else
#define OCI_G(v) (oci_globals.v)
#endif
ZEND_EXTERN_MODULE_GLOBALS(oci)
# endif /* !PHP_OCI8_INT_H */
#else /* !HAVE_OCI8 */
# define oci8_module_ptr NULL
#endif /* HAVE_OCI8 */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/