mirror of
https://github.com/php/php-src.git
synced 2025-08-18 15:08:55 +02:00
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:
parent
8774e8e1aa
commit
3df94e1112
9 changed files with 5914 additions and 6696 deletions
61
ext/oci8/README
Normal file
61
ext/oci8/README
Normal 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
|
|
@ -19,7 +19,16 @@ AC_DEFUN([PHP_OCI_IF_DEFINED],[
|
|||
])
|
||||
|
||||
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])
|
||||
if test -d "$OCI8_DIR/lib" -a ! -d "$OCI8_DIR/lib32"; then
|
||||
OCI8_LIB_DIR=lib
|
||||
|
@ -76,26 +85,33 @@ AC_DEFUN([AC_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
|
||||
PHP_ARG_WITH(oci8-instant-client, for Oracle (OCI8) support using Oracle Instant Client,
|
||||
[ --with-oci8-instant-client[=DIR]
|
||||
Include Oracle (OCI8) support using
|
||||
Oracle Instant Client. DIR is the directory with the
|
||||
Instant Client libraries. On Linux it will default to
|
||||
/usr/lib/oracle/<most_recent_version>/client/lib
|
||||
Other platforms will need to have it explicitly specified])
|
||||
else
|
||||
PHP_OCI8_INSTANT_CLIENT="no";
|
||||
dnl --with-oci8=shared,instantclient,/path/to/client/dir/lib
|
||||
dnl or
|
||||
dnl --with-oci8=shared,/path/to/oracle/home
|
||||
PHP_ARG_WITH(oci8, for Oracle (OCI8) support,
|
||||
[ --with-oci8[=DIR] Include Oracle (OCI8) support.
|
||||
The default DIR is ORACLE_HOME.
|
||||
Use --with-oci8=instantclient,/path/to/oic/lib
|
||||
to use Oracle Instant Client installation])
|
||||
|
||||
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
|
||||
|
||||
if test "$PHP_OCI8" != "no"; then
|
||||
if test "$PHP_OCI8_INSTANT_CLIENT" != "no"; then
|
||||
AC_MSG_ERROR([--with-oci8 and --with-oci8-instant-client are mutually exclusive])
|
||||
fi
|
||||
if test "$PHP_OCI8" != "no" && test "$PHP_OCI8_INSTANT_CLIENT" = "no"; then
|
||||
|
||||
AC_MSG_CHECKING([Oracle Install Directory])
|
||||
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(psa, "", 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)
|
||||
PHP_ADD_LIBRARY(clntsh, 1, 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 OCI_ATTR_STATEMENT is not available in all 8.1.x versions
|
||||
dnl
|
||||
|
@ -160,7 +204,7 @@ if test "$PHP_OCI8" != "no"; then
|
|||
[
|
||||
PHP_CHECK_LIBRARY(clntsh, OCINlsCharSetNameToId,
|
||||
[
|
||||
AC_DEFINE(HAVE_OCI_9_2,1,[ ])
|
||||
AC_DEFINE(HAVE_OCI_ENV_NLS_CREATE,1,[ ])
|
||||
OCI8_VERSION=9.2
|
||||
], [], [
|
||||
-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
|
||||
])
|
||||
|
||||
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)
|
||||
PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD)
|
||||
PHP_ADD_LIBPATH($OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD)
|
||||
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(PHP_OCI8_HAVE_COLLECTIONS,1,[ ])
|
||||
;;
|
||||
|
@ -207,18 +268,22 @@ if test "$PHP_OCI8" != "no"; then
|
|||
PHP_CHECK_LIBRARY(clntsh, OCICollAssign,
|
||||
[
|
||||
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
|
||||
])
|
||||
|
||||
PHP_NEW_EXTENSION(oci8, oci8.c, $ext_shared)
|
||||
AC_DEFINE(HAVE_OCI8,1,[ ])
|
||||
|
||||
PHP_SUBST_OLD(OCI8_SHARED_LIBADD)
|
||||
PHP_SUBST_OLD(OCI8_DIR)
|
||||
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])
|
||||
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
|
||||
PHP_OCI8_INSTANT_CLIENT=`ls -d /usr/lib/oracle/*/client/lib 2> /dev/null | tail -1`
|
||||
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
|
||||
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
|
||||
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
|
||||
AC_MSG_RESULT($OCISDKRPMINC)
|
||||
PHP_ADD_INCLUDE($OCISDKRPMINC)
|
||||
|
@ -250,6 +318,10 @@ dnl Header directory for Instant Client SDK zip file install
|
|||
AC_MSG_RESULT($OCISDKZIPINC)
|
||||
PHP_ADD_INCLUDE($OCISDKZIPINC)
|
||||
OCI8INCDIR=$OCISDKZIPINC
|
||||
elif test -f "$OCISDKMANINC/oci.h"; then
|
||||
AC_MSG_RESULT($OCISDKMANINC)
|
||||
PHP_ADD_INCLUDE($OCISDKMANINC)
|
||||
OCI8INCDIR=$OCISDKMANINC
|
||||
else
|
||||
AC_MSG_ERROR([Oracle Instant Client SDK header files not found])
|
||||
fi
|
||||
|
@ -271,13 +343,15 @@ dnl Header directory for Instant Client SDK zip file install
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_DEFINE(HAVE_OCI_INSTANT_CLIENT,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(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,[ ])
|
||||
|
||||
PHP_SUBST_OLD(OCI8_SHARED_LIBADD)
|
||||
|
|
7480
ext/oci8/oci8.c
7480
ext/oci8/oci8.c
File diff suppressed because it is too large
Load diff
604
ext/oci8/oci8_collection.c
Normal file
604
ext/oci8/oci8_collection.c
Normal 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
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
686
ext/oci8/oci8_lob.c
Normal 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
992
ext/oci8/oci8_statement.c
Normal 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**)¶m, 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 */
|
|
@ -12,8 +12,11 @@
|
|||
| 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> |
|
||||
| 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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
@ -22,19 +25,6 @@
|
|||
#if HAVE_OCI8
|
||||
# ifndef 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
|
||||
#define PHP_OCI_API __declspec(dllexport)
|
||||
|
@ -42,175 +32,21 @@
|
|||
#define PHP_OCI_API
|
||||
#endif
|
||||
|
||||
#if defined(min)
|
||||
#undef min
|
||||
#ifdef ZTS
|
||||
# include "TSRM.h"
|
||||
#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;
|
||||
#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
|
||||
#define OCI(v) TSRMG(oci_globals_id, php_oci_globals *, v)
|
||||
#else
|
||||
#define OCI(v) (oci_globals.v)
|
||||
#endif
|
||||
PHP_MINIT_FUNCTION(oci);
|
||||
PHP_RINIT_FUNCTION(oci);
|
||||
PHP_MSHUTDOWN_FUNCTION(oci);
|
||||
PHP_RSHUTDOWN_FUNCTION(oci);
|
||||
PHP_MINFO_FUNCTION(oci);
|
||||
|
||||
# endif /* !PHP_OCI8_H */
|
||||
#else /* !HAVE_OCI8 */
|
||||
|
||||
# define oci8_module_ptr NULL
|
||||
|
@ -223,3 +59,5 @@ extern zend_module_entry oci8_module_entry;
|
|||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
|
||||
|
||||
|
|
404
ext/oci8/php_oci8_int.h
Normal file
404
ext/oci8/php_oci8_int.h
Normal 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:
|
||||
*/
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue