summaryrefslogtreecommitdiff
path: root/ext/pdo_oci
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_oci')
-rwxr-xr-xext/pdo_oci/config.m438
-rwxr-xr-xext/pdo_oci/oci_driver.c1172
-rwxr-xr-xext/pdo_oci/oci_statement.c72
-rwxr-xr-xext/pdo_oci/php_pdo_oci_int.h189
-rw-r--r--ext/pdo_oci/tests/pdo_oci_quote1.phpt163
-rw-r--r--ext/pdo_oci/tests/pecl_bug_11345.phpt29
-rw-r--r--ext/pdo_oci/tests/pecl_bug_6364.phpt71
7 files changed, 1027 insertions, 707 deletions
diff --git a/ext/pdo_oci/config.m4 b/ext/pdo_oci/config.m4
index c5a30a4f8..3a8f88097 100755
--- a/ext/pdo_oci/config.m4
+++ b/ext/pdo_oci/config.m4
@@ -1,4 +1,4 @@
-dnl $Id: config.m4,v 1.14.2.5 2006/02/16 02:03:13 pollita Exp $
+dnl $Id: config.m4,v 1.14.2.5.2.5 2007/08/17 13:30:36 sixd Exp $
if test "$PHP_PDO" != "no"; then
@@ -7,6 +7,8 @@ AC_DEFUN([AC_PDO_OCI_VERSION],[
if test -s "$PDO_OCI_DIR/orainst/unix.rgs"; then
PDO_OCI_VERSION=`grep '"ocommon"' $PDO_OCI_DIR/orainst/unix.rgs | sed 's/[ ][ ]*/:/g' | cut -d: -f 6 | cut -c 2-4`
test -z "$PDO_OCI_VERSION" && PDO_OCI_VERSION=7.3
+ elif test -f $PDO_OCI_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME.11.1; then
+ PDO_OCI_VERSION=11.1
elif test -f $PDO_OCI_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME.10.1; then
PDO_OCI_VERSION=10.1
elif test -f $PDO_OCI_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME.9.0; then
@@ -29,7 +31,7 @@ AC_DEFUN([AC_PDO_OCI_VERSION],[
AC_DEFUN([AC_PDO_OCI_CHECK_LIB_DIR],[
AC_CHECK_SIZEOF(long int, 4)
- AC_MSG_CHECKING([checking if we're at 64-bit platform])
+ AC_MSG_CHECKING([if we're on a 64-bit platform])
if test "$ac_cv_sizeof_long_int" = "4" ; then
AC_MSG_RESULT([no])
TMP_PDO_OCI_LIB_DIR="$PDO_OCI_DIR/lib32"
@@ -39,11 +41,11 @@ AC_DEFUN([AC_PDO_OCI_CHECK_LIB_DIR],[
fi
AC_MSG_CHECKING([OCI8 libraries dir])
- if test -d "$PDO_OCI_DIR/lib" -a ! -d "$PDO_OCI_DIR/lib32"; then
+ if test -d "$PDO_OCI_DIR/lib" && test ! -d "$PDO_OCI_DIR/lib32"; then
PDO_OCI_LIB_DIR="$PDO_OCI_DIR/lib"
- elif ! test -d "$PDO_OCI_DIR/lib" -a -d "$PDO_OCI_DIR/lib32"; then
+ elif test ! -d "$PDO_OCI_DIR/lib" && test -d "$PDO_OCI_DIR/lib32"; then
PDO_OCI_LIB_DIR="$PDO_OCI_DIR/lib32"
- elif test -d "$PDO_OCI_DIR/lib" -a -d "$PDO_OCI_DIR/lib32"; then
+ elif test -d "$PDO_OCI_DIR/lib" && test -d "$PDO_OCI_DIR/lib32"; then
PDO_OCI_LIB_DIR=$TMP_PDO_OCI_LIB_DIR
else
AC_MSG_ERROR([Oracle (OCI8) required libraries not found])
@@ -52,10 +54,11 @@ AC_DEFUN([AC_PDO_OCI_CHECK_LIB_DIR],[
])
PHP_ARG_WITH(pdo-oci, Oracle OCI support for PDO,
-[ --with-pdo-oci[=DIR] PDO: Oracle-OCI support. Default DIR is ORACLE_HOME.
- You may also use --with-pdo-oci=instantclient,prefix,version to use
- the InstantClient SDK. For Linux with 10.1.0.3 rpms (for example) use:
- --with-pdo-oci=instantclient,/usr,10.1.0.3])
+[ --with-pdo-oci[=DIR] PDO: Oracle-OCI support. DIR defaults to \$ORACLE_HOME.
+ Use --with-pdo-oci=instantclient,prefix,version
+ for an Oracle Instant Client SDK.
+ For Linux with 10.2.0.3 RPMs (for example) use:
+ --with-pdo-oci=instantclient,/usr,10.2.0.3])
if test "$PHP_PDO_OCI" != "no"; then
AC_MSG_CHECKING([Oracle Install-Dir])
@@ -75,8 +78,6 @@ You need to tell me where to find your oracle SDK, or set ORACLE_HOME.
AC_MSG_RESULT([yes])
fi
- AC_PDO_OCI_CHECK_LIB_DIR($PDO_OCI_DIR)
-
if test "instantclient" = "`echo $PDO_OCI_DIR | cut -d, -f1`" ; then
PDO_OCI_IC_PREFIX="`echo $PDO_OCI_DIR | cut -d, -f2`"
PDO_OCI_IC_VERS="`echo $PDO_OCI_DIR | cut -d, -f3`"
@@ -94,7 +95,7 @@ You need to tell me where to find your oracle SDK, or set ORACLE_HOME.
PHP_ADD_INCLUDE($PDO_OCI_IC_PREFIX/client/include)
AC_MSG_RESULT($PDO_OCI_IC_PREFIX/client/include)
else
- AC_MSG_ERROR([I'm too dumb to figure out where the include dir is in your instant client install])
+ AC_MSG_ERROR([I'm too dumb to figure out where the include dir is in your Instant Client install])
fi
if test -f "$PDO_OCI_IC_PREFIX/lib/oracle/$PDO_OCI_IC_VERS/client/lib/libclntsh.so" ; then
PDO_OCI_LIB_DIR="$PDO_OCI_IC_PREFIX/lib/oracle/$PDO_OCI_IC_VERS/client/lib"
@@ -103,10 +104,12 @@ You need to tell me where to find your oracle SDK, or set ORACLE_HOME.
elif test -f "$PDO_OCI_IC_PREFIX/libclntsh.so" ; then
PDO_OCI_LIB_DIR="$PDO_OCI_IC_PREFIX"
else
- AC_MSG_ERROR([I'm too dumb to figure out where the libraries are in your instant client install])
+ AC_MSG_ERROR([I'm too dumb to figure out where the libraries are in your Instant Client install])
fi
PDO_OCI_VERSION="`echo $PDO_OCI_IC_VERS | cut -d. -f1-2`"
else
+ AC_PDO_OCI_CHECK_LIB_DIR($PDO_OCI_DIR)
+
if test -d "$PDO_OCI_DIR/rdbms/public"; then
PHP_ADD_INCLUDE($PDO_OCI_DIR/rdbms/public)
PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/rdbms/public"
@@ -151,13 +154,19 @@ You need to tell me where to find your oracle SDK, or set ORACLE_HOME.
9.0)
PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
;;
-
+
10.1)
PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
;;
+
10.2)
PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
;;
+
+ 11.1)
+ PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
+ ;;
+
*)
AC_MSG_ERROR(Unsupported Oracle version! $PDO_OCI_VERSION)
;;
@@ -242,7 +251,6 @@ You need to tell me where to find your oracle SDK, or set ORACLE_HOME.
[
PHP_ADD_EXTENSION_DEP(pdo_oci, pdo)
])
-
fi
fi
diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c
index 735728152..7c01eeb1d 100755
--- a/ext/pdo_oci/oci_driver.c
+++ b/ext/pdo_oci/oci_driver.c
@@ -1,564 +1,608 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2007 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Wez Furlong <wez@php.net> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: oci_driver.c,v 1.24.2.4.2.3 2007/04/10 20:28:49 tony2001 Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_ini.h"
-#include "ext/standard/info.h"
-#include "pdo/php_pdo.h"
-#include "pdo/php_pdo_driver.h"
-#include "php_pdo_oci.h"
-#include "php_pdo_oci_int.h"
-#include "Zend/zend_exceptions.h"
-
-static int pdo_oci_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */
-{
- pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
- pdo_oci_error_info *einfo;
-
- einfo = &H->einfo;
-
- if (stmt) {
- pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
-
- if (S->einfo.errmsg) {
- einfo = &S->einfo;
- }
- }
-
- if (einfo->errcode) {
- add_next_index_long(info, einfo->errcode);
- add_next_index_string(info, einfo->errmsg, 1);
- }
-
- return 1;
-}
-/* }}} */
-
-ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, const char *file, int line TSRMLS_DC) /* {{{ */
-{
- text errbuf[1024] = "<<Unknown>>";
- char tmp_buf[2048];
- pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
- pdo_oci_error_info *einfo;
- pdo_oci_stmt *S = NULL;
- pdo_error_type *pdo_err = &dbh->error_code;
-
- if (stmt) {
- S = (pdo_oci_stmt*)stmt->driver_data;
- einfo = &S->einfo;
- pdo_err = &stmt->error_code;
- if (einfo->errmsg) {
- efree(einfo->errmsg);
- }
- }
- else {
- einfo = &H->einfo;
- if (einfo->errmsg) {
- pefree(einfo->errmsg, dbh->is_persistent);
- }
- }
-
- einfo->errmsg = NULL;
- einfo->errcode = 0;
- einfo->file = file;
- einfo->line = line;
-
- switch (status) {
- case OCI_SUCCESS:
- strcpy(*pdo_err, "00000");
- break;
- case OCI_ERROR:
- OCIErrorGet(err, (ub4)1, NULL, &einfo->errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
- slprintf(tmp_buf, sizeof(tmp_buf), "%s: %s (%s:%d)", what, errbuf, file, line);
- einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
- break;
- case OCI_SUCCESS_WITH_INFO:
- OCIErrorGet(err, (ub4)1, NULL, &einfo->errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
- slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_SUCCESS_WITH_INFO: %s (%s:%d)", what, errbuf, file, line);
- einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
- break;
- case OCI_NEED_DATA:
- slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_NEED_DATA (%s:%d)", what, file, line);
- einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
- break;
- case OCI_NO_DATA:
- slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_NO_DATA (%s:%d)", what, file, line);
- einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
- break;
- case OCI_INVALID_HANDLE:
- slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_INVALID_HANDLE (%s:%d)", what, file, line);
- einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
- break;
- case OCI_STILL_EXECUTING:
- slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_STILL_EXECUTING (%s:%d)", what, file, line);
- einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
- break;
- case OCI_CONTINUE:
- slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_CONTINUE (%s:%d)", what, file, line);
- einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
- break;
- }
-
- if (einfo->errcode) {
- switch (einfo->errcode) {
- case 1013: /* user requested cancel of current operation */
- zend_bailout();
- break;
-
-#if 0
- case 955: /* ORA-00955: name is already used by an existing object */
- *pdo_err = PDO_ERR_ALREADY_EXISTS;
- break;
-#endif
-
- case 12154: /* ORA-12154: TNS:could not resolve service name */
- strcpy(*pdo_err, "42S02");
- break;
-
- case 22: /* ORA-00022: invalid session id */
- case 1012: /* ORA-01012: */
- case 3113: /* ORA-03133: end of file on communication channel */
- case 604:
- case 1041:
- /* consider the connection closed */
- dbh->is_closed = 1;
- H->attached = 0;
- strcpy(*pdo_err, "01002"); /* FIXME */
- break;
-
- default:
- strcpy(*pdo_err, "HY000");
- }
- }
-
- if (stmt) {
- /* always propogate the error code back up to the dbh,
- * so that we can catch the error information when execute
- * is called via query. See Bug #33707 */
- if (H->einfo.errmsg) {
- pefree(H->einfo.errmsg, dbh->is_persistent);
- }
- H->einfo = *einfo;
- H->einfo.errmsg = einfo->errmsg ? pestrdup(einfo->errmsg, dbh->is_persistent) : NULL;
- strcpy(dbh->error_code, stmt->error_code);
- }
-
- /* little mini hack so that we can use this code from the dbh ctor */
- if (!dbh->methods) {
- zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s]: %s", *pdo_err, einfo->errmsg);
- }
-
- return einfo->errcode;
-}
-/* }}} */
-
-static int oci_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
-{
- pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
-
- if (H->svc) {
- /* rollback any outstanding work */
- OCITransRollback(H->svc, H->err, 0);
- }
-
- if (H->session) {
- OCIHandleFree(H->session, OCI_HTYPE_SESSION);
- H->session = NULL;
- }
-
- if (H->svc) {
- OCIHandleFree(H->svc, OCI_HTYPE_SVCCTX);
- H->svc = NULL;
- }
-
- if (H->server && H->attached) {
- H->last_err = OCIServerDetach(H->server, H->err, OCI_DEFAULT);
- if (H->last_err) {
- oci_drv_error("OCIServerDetach");
- }
- H->attached = 0;
- }
-
- if (H->server) {
- OCIHandleFree(H->server, OCI_HTYPE_SERVER);
- H->server = NULL;
- }
-
- OCIHandleFree(H->err, OCI_HTYPE_ERROR);
- H->err = NULL;
-
- if (H->charset && H->env) {
- OCIHandleFree(H->env, OCI_HTYPE_ENV);
- H->env = NULL;
- }
-
- if (H->einfo.errmsg) {
- pefree(H->einfo.errmsg, dbh->is_persistent);
- H->einfo.errmsg = NULL;
- }
-
- pefree(H, dbh->is_persistent);
-
- return 0;
-}
-/* }}} */
-
-static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC) /* {{{ */
-{
- pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
- pdo_oci_stmt *S = ecalloc(1, sizeof(*S));
- ub4 prefetch;
- char *nsql = NULL;
- int nsql_len = 0;
- int ret;
-
-#if HAVE_OCISTMTFETCH2
- S->exec_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR,
- PDO_CURSOR_FWDONLY TSRMLS_CC) == PDO_CURSOR_SCROLL ?
- OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT;
-#else
- S->exec_type = OCI_DEFAULT;
-#endif
-
- S->H = H;
- stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED;
- ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
-
- if (ret == 1) {
- /* query was re-written */
- sql = nsql;
- sql_len = nsql_len;
- } else if (ret == -1) {
- /* couldn't grok it */
- strcpy(dbh->error_code, stmt->error_code);
- efree(S);
- return 0;
- }
-
- /* create an OCI statement handle */
- OCIHandleAlloc(H->env, (dvoid*)&S->stmt, OCI_HTYPE_STMT, 0, NULL);
-
- /* and our own private error handle */
- OCIHandleAlloc(H->env, (dvoid*)&S->err, OCI_HTYPE_ERROR, 0, NULL);
-
- if (sql_len) {
- H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT);
- if (nsql) {
- efree(nsql);
- nsql = NULL;
- }
- if (H->last_err) {
- H->last_err = oci_drv_error("OCIStmtPrepare");
- OCIHandleFree(S->stmt, OCI_HTYPE_STMT);
- OCIHandleFree(S->err, OCI_HTYPE_ERROR);
- efree(S);
- return 0;
- }
-
- }
-
- prefetch = 1024 * pdo_attr_lval(driver_options, PDO_ATTR_PREFETCH, 100 TSRMLS_CC);
- if (prefetch) {
- H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0,
- OCI_ATTR_PREFETCH_MEMORY, H->err);
- if (!H->last_err) {
- prefetch /= 1024;
- H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0,
- OCI_ATTR_PREFETCH_ROWS, H->err);
- }
- }
-
- stmt->driver_data = S;
- stmt->methods = &oci_stmt_methods;
- if (nsql) {
- efree(nsql);
- nsql = NULL;
- }
-
- return 1;
-}
-/* }}} */
-
-static long oci_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */
-{
- pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
- OCIStmt *stmt;
- ub2 stmt_type;
- ub4 rowcount;
- int ret = -1;
-
- OCIHandleAlloc(H->env, (dvoid*)&stmt, OCI_HTYPE_STMT, 0, NULL);
-
- H->last_err = OCIStmtPrepare(stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT);
- if (H->last_err) {
- H->last_err = oci_drv_error("OCIStmtPrepare");
- OCIHandleFree(stmt, OCI_HTYPE_STMT);
- return -1;
- }
-
- H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, H->err);
-
- if (stmt_type == OCI_STMT_SELECT) {
- /* invalid usage; cancel it */
- OCIHandleFree(stmt, OCI_HTYPE_STMT);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "issuing a SELECT query here is invalid");
- return -1;
- }
-
- /* now we are good to go */
- H->last_err = OCIStmtExecute(H->svc, stmt, H->err, 1, 0, NULL, NULL,
- (dbh->auto_commit && !dbh->in_txn) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
-
- if (H->last_err) {
- H->last_err = oci_drv_error("OCIStmtExecute");
- } else {
- /* return the number of affected rows */
- H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, H->err);
- ret = rowcount;
- }
-
- OCIHandleFree(stmt, OCI_HTYPE_STMT);
-
- return ret;
-}
-/* }}} */
-
-static int oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC) /* {{{ */
-{
- return 0;
-}
-/* }}} */
-
-static int oci_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
-{
- /* with Oracle, there is nothing special to be done */
- return 1;
-}
-/* }}} */
-
-static int oci_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
-{
- pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
-
- H->last_err = OCITransCommit(H->svc, H->err, 0);
-
- if (H->last_err) {
- H->last_err = oci_drv_error("OCITransCommit");
- return 0;
- }
- return 1;
-}
-/* }}} */
-
-static int oci_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
-{
- pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
-
- H->last_err = OCITransRollback(H->svc, H->err, 0);
-
- if (H->last_err) {
- H->last_err = oci_drv_error("OCITransRollback");
- return 0;
- }
- return 1;
-}
-/* }}} */
-
-static int oci_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */
-{
- pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
-
- if (attr == PDO_ATTR_AUTOCOMMIT) {
- if (dbh->in_txn) {
- /* Assume they want to commit whatever is outstanding */
- H->last_err = OCITransCommit(H->svc, H->err, 0);
-
- if (H->last_err) {
- H->last_err = oci_drv_error("OCITransCommit");
- return 0;
- }
- dbh->in_txn = 0;
- }
-
- convert_to_long(val);
-
- dbh->auto_commit = Z_LVAL_P(val);
- return 1;
- } else {
- return 0;
- }
-
-}
-/* }}} */
-
-static struct pdo_dbh_methods oci_methods = {
- oci_handle_closer,
- oci_handle_preparer,
- oci_handle_doer,
- oci_handle_quoter,
- oci_handle_begin,
- oci_handle_commit,
- oci_handle_rollback,
- oci_handle_set_attribute,
- NULL,
- pdo_oci_fetch_error_func,
- NULL, /* get_attr */
- NULL, /* check_liveness */
- NULL /* get_driver_methods */
-};
-
-static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
-{
- pdo_oci_db_handle *H;
- int i, ret = 0;
- struct pdo_data_src_parser vars[] = {
- { "charset", NULL, 0 },
- { "dbname", "", 0 }
- };
-
- php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 2);
-
- H = pecalloc(1, sizeof(*H), dbh->is_persistent);
- dbh->driver_data = H;
-
- /* allocate an environment */
-#if HAVE_OCIENVNLSCREATE
- if (vars[0].optval) {
- H->charset = OCINlsCharSetNameToId(pdo_oci_Env, vars[0].optval);
- if (H->charset) {
- OCIEnvNlsCreate(&H->env, PDO_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, H->charset, H->charset);
- }
- }
-#endif
- if (H->env == NULL) {
- /* use the global environment */
- H->env = pdo_oci_Env;
- }
-
- /* something to hold errors */
- OCIHandleAlloc(H->env, (dvoid **)&H->err, OCI_HTYPE_ERROR, 0, NULL);
-
- /* handle for the server */
- OCIHandleAlloc(H->env, (dvoid **)&H->server, OCI_HTYPE_SERVER, 0, NULL);
-
- H->last_err = OCIServerAttach(H->server, H->err, (text*)vars[1].optval,
- strlen(vars[1].optval), OCI_DEFAULT);
-
- if (H->last_err) {
- oci_drv_error("pdo_oci_handle_factory");
- goto cleanup;
- }
-
- H->attached = 1;
-
- /* create a service context */
- H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->svc, OCI_HTYPE_SVCCTX, 0, NULL);
- if (H->last_err) {
- oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SVCCTX");
- goto cleanup;
- }
-
- H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->session, OCI_HTYPE_SESSION, 0, NULL);
- if (H->last_err) {
- oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SESSION");
- goto cleanup;
- }
-
- /* set server handle into service handle */
- H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->server, 0, OCI_ATTR_SERVER, H->err);
- if (H->last_err) {
- oci_drv_error("OCIAttrSet: OCI_ATTR_SERVER");
- goto cleanup;
- }
-
- /* username */
- if (dbh->username) {
- H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
- dbh->username, strlen(dbh->username),
- OCI_ATTR_USERNAME, H->err);
- if (H->last_err) {
- oci_drv_error("OCIAttrSet: OCI_ATTR_USERNAME");
- goto cleanup;
- }
- }
-
- /* password */
- if (dbh->password) {
- H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
- dbh->password, strlen(dbh->password),
- OCI_ATTR_PASSWORD, H->err);
- if (H->last_err) {
- oci_drv_error("OCIAttrSet: OCI_ATTR_PASSWORD");
- goto cleanup;
- }
- }
-
- /* Now fire up the session */
- H->last_err = OCISessionBegin(H->svc, H->err, H->session, OCI_CRED_RDBMS, OCI_DEFAULT);
- if (H->last_err) {
- oci_drv_error("OCISessionBegin:");
- goto cleanup;
- }
-
- /* set the server handle into service handle */
- H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->session, 0, OCI_ATTR_SESSION, H->err);
- if (H->last_err) {
- oci_drv_error("OCIAttrSet: OCI_ATTR_SESSION:");
- goto cleanup;
- }
-
- dbh->methods = &oci_methods;
- dbh->alloc_own_columns = 1;
- dbh->native_case = PDO_CASE_UPPER;
-
- ret = 1;
-
-cleanup:
- for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
- if (vars[i].freeme) {
- efree(vars[i].optval);
- }
- }
-
- if (!ret) {
- oci_handle_closer(dbh TSRMLS_CC);
- }
-
- return ret;
-}
-/* }}} */
-
-pdo_driver_t pdo_oci_driver = {
- PDO_DRIVER_HEADER(oci),
- pdo_oci_handle_factory
-};
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: oci_driver.c,v 1.24.2.4.2.6 2007/07/03 04:32:26 sixd Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "pdo/php_pdo.h"
+#include "pdo/php_pdo_driver.h"
+#include "php_pdo_oci.h"
+#include "php_pdo_oci_int.h"
+#include "Zend/zend_exceptions.h"
+
+static int pdo_oci_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC) /* {{{ */
+{
+ pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+ pdo_oci_error_info *einfo;
+
+ einfo = &H->einfo;
+
+ if (stmt) {
+ pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
+
+ if (S->einfo.errmsg) {
+ einfo = &S->einfo;
+ }
+ }
+
+ if (einfo->errcode) {
+ add_next_index_long(info, einfo->errcode);
+ add_next_index_string(info, einfo->errmsg, 1);
+ }
+
+ return 1;
+}
+/* }}} */
+
+ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line TSRMLS_DC) /* {{{ */
+{
+ text errbuf[1024] = "<<Unknown>>";
+ char tmp_buf[2048];
+ pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+ pdo_oci_error_info *einfo;
+ pdo_oci_stmt *S = NULL;
+ pdo_error_type *pdo_err = &dbh->error_code;
+
+ if (stmt) {
+ S = (pdo_oci_stmt*)stmt->driver_data;
+ einfo = &S->einfo;
+ pdo_err = &stmt->error_code;
+ if (einfo->errmsg) {
+ efree(einfo->errmsg);
+ }
+ }
+ else {
+ einfo = &H->einfo;
+ if (einfo->errmsg) {
+ pefree(einfo->errmsg, dbh->is_persistent);
+ }
+ }
+
+ einfo->errmsg = NULL;
+ einfo->errcode = 0;
+ einfo->file = file;
+ einfo->line = line;
+
+ if (isinit) { /* Initialization error */
+ strcpy(*pdo_err, "HY000");
+ slprintf(tmp_buf, sizeof(tmp_buf), "%s (%s:%d)", what, file, line);
+ einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
+ }
+ else {
+ switch (status) {
+ case OCI_SUCCESS:
+ strcpy(*pdo_err, "00000");
+ break;
+ case OCI_ERROR:
+ OCIErrorGet(err, (ub4)1, NULL, &einfo->errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
+ slprintf(tmp_buf, sizeof(tmp_buf), "%s: %s (%s:%d)", what, errbuf, file, line);
+ einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
+ break;
+ case OCI_SUCCESS_WITH_INFO:
+ OCIErrorGet(err, (ub4)1, NULL, &einfo->errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
+ slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_SUCCESS_WITH_INFO: %s (%s:%d)", what, errbuf, file, line);
+ einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
+ break;
+ case OCI_NEED_DATA:
+ slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_NEED_DATA (%s:%d)", what, file, line);
+ einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
+ break;
+ case OCI_NO_DATA:
+ slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_NO_DATA (%s:%d)", what, file, line);
+ einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
+ break;
+ case OCI_INVALID_HANDLE:
+ slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_INVALID_HANDLE (%s:%d)", what, file, line);
+ einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
+ break;
+ case OCI_STILL_EXECUTING:
+ slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_STILL_EXECUTING (%s:%d)", what, file, line);
+ einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
+ break;
+ case OCI_CONTINUE:
+ slprintf(tmp_buf, sizeof(tmp_buf), "%s: OCI_CONTINUE (%s:%d)", what, file, line);
+ einfo->errmsg = pestrdup(tmp_buf, dbh->is_persistent);
+ break;
+ }
+
+ if (einfo->errcode) {
+ switch (einfo->errcode) {
+ case 1013: /* user requested cancel of current operation */
+ zend_bailout();
+ break;
+
+#if 0
+ case 955: /* ORA-00955: name is already used by an existing object */
+ *pdo_err = PDO_ERR_ALREADY_EXISTS;
+ break;
+#endif
+
+ case 12154: /* ORA-12154: TNS:could not resolve service name */
+ strcpy(*pdo_err, "42S02");
+ break;
+
+ case 22: /* ORA-00022: invalid session id */
+ case 1012: /* ORA-01012: */
+ case 3113: /* ORA-03133: end of file on communication channel */
+ case 604:
+ case 1041:
+ /* consider the connection closed */
+ dbh->is_closed = 1;
+ H->attached = 0;
+ strcpy(*pdo_err, "01002"); /* FIXME */
+ break;
+
+ default:
+ strcpy(*pdo_err, "HY000");
+ }
+ }
+
+ if (stmt) {
+ /* always propogate the error code back up to the dbh,
+ * so that we can catch the error information when execute
+ * is called via query. See Bug #33707 */
+ if (H->einfo.errmsg) {
+ pefree(H->einfo.errmsg, dbh->is_persistent);
+ }
+ H->einfo = *einfo;
+ H->einfo.errmsg = einfo->errmsg ? pestrdup(einfo->errmsg, dbh->is_persistent) : NULL;
+ strcpy(dbh->error_code, stmt->error_code);
+ }
+ }
+
+ /* little mini hack so that we can use this code from the dbh ctor */
+ if (!dbh->methods) {
+ zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s]: %s", *pdo_err, einfo->errmsg);
+ }
+
+ return einfo->errcode;
+}
+/* }}} */
+
+static int oci_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
+{
+ pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+ if (H->svc) {
+ /* rollback any outstanding work */
+ OCITransRollback(H->svc, H->err, 0);
+ }
+
+ if (H->session) {
+ OCIHandleFree(H->session, OCI_HTYPE_SESSION);
+ H->session = NULL;
+ }
+
+ if (H->svc) {
+ OCIHandleFree(H->svc, OCI_HTYPE_SVCCTX);
+ H->svc = NULL;
+ }
+
+ if (H->server && H->attached) {
+ H->last_err = OCIServerDetach(H->server, H->err, OCI_DEFAULT);
+ if (H->last_err) {
+ oci_drv_error("OCIServerDetach");
+ }
+ H->attached = 0;
+ }
+
+ if (H->server) {
+ OCIHandleFree(H->server, OCI_HTYPE_SERVER);
+ H->server = NULL;
+ }
+
+ OCIHandleFree(H->err, OCI_HTYPE_ERROR);
+ H->err = NULL;
+
+ if (H->charset && H->env) {
+ OCIHandleFree(H->env, OCI_HTYPE_ENV);
+ H->env = NULL;
+ }
+
+ if (H->einfo.errmsg) {
+ pefree(H->einfo.errmsg, dbh->is_persistent);
+ H->einfo.errmsg = NULL;
+ }
+
+ pefree(H, dbh->is_persistent);
+
+ return 0;
+}
+/* }}} */
+
+static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC) /* {{{ */
+{
+ pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+ pdo_oci_stmt *S = ecalloc(1, sizeof(*S));
+ ub4 prefetch;
+ char *nsql = NULL;
+ int nsql_len = 0;
+ int ret;
+
+#if HAVE_OCISTMTFETCH2
+ S->exec_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR,
+ PDO_CURSOR_FWDONLY TSRMLS_CC) == PDO_CURSOR_SCROLL ?
+ OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT;
+#else
+ S->exec_type = OCI_DEFAULT;
+#endif
+
+ S->H = H;
+ stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED;
+ ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
+
+ if (ret == 1) {
+ /* query was re-written */
+ sql = nsql;
+ sql_len = nsql_len;
+ } else if (ret == -1) {
+ /* couldn't grok it */
+ strcpy(dbh->error_code, stmt->error_code);
+ efree(S);
+ return 0;
+ }
+
+ /* create an OCI statement handle */
+ OCIHandleAlloc(H->env, (dvoid*)&S->stmt, OCI_HTYPE_STMT, 0, NULL);
+
+ /* and our own private error handle */
+ OCIHandleAlloc(H->env, (dvoid*)&S->err, OCI_HTYPE_ERROR, 0, NULL);
+
+ if (sql_len) {
+ H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT);
+ if (nsql) {
+ efree(nsql);
+ nsql = NULL;
+ }
+ if (H->last_err) {
+ H->last_err = oci_drv_error("OCIStmtPrepare");
+ OCIHandleFree(S->stmt, OCI_HTYPE_STMT);
+ OCIHandleFree(S->err, OCI_HTYPE_ERROR);
+ efree(S);
+ return 0;
+ }
+
+ }
+
+ prefetch = 1024 * pdo_attr_lval(driver_options, PDO_ATTR_PREFETCH, 100 TSRMLS_CC);
+ if (prefetch) {
+ H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0,
+ OCI_ATTR_PREFETCH_MEMORY, H->err);
+ if (!H->last_err) {
+ prefetch /= 1024;
+ H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0,
+ OCI_ATTR_PREFETCH_ROWS, H->err);
+ }
+ }
+
+ stmt->driver_data = S;
+ stmt->methods = &oci_stmt_methods;
+ if (nsql) {
+ efree(nsql);
+ nsql = NULL;
+ }
+
+ return 1;
+}
+/* }}} */
+
+static long oci_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC) /* {{{ */
+{
+ pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+ OCIStmt *stmt;
+ ub2 stmt_type;
+ ub4 rowcount;
+ int ret = -1;
+
+ OCIHandleAlloc(H->env, (dvoid*)&stmt, OCI_HTYPE_STMT, 0, NULL);
+
+ H->last_err = OCIStmtPrepare(stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT);
+ if (H->last_err) {
+ H->last_err = oci_drv_error("OCIStmtPrepare");
+ OCIHandleFree(stmt, OCI_HTYPE_STMT);
+ return -1;
+ }
+
+ H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, H->err);
+
+ if (stmt_type == OCI_STMT_SELECT) {
+ /* invalid usage; cancel it */
+ OCIHandleFree(stmt, OCI_HTYPE_STMT);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "issuing a SELECT query here is invalid");
+ return -1;
+ }
+
+ /* now we are good to go */
+ H->last_err = OCIStmtExecute(H->svc, stmt, H->err, 1, 0, NULL, NULL,
+ (dbh->auto_commit && !dbh->in_txn) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT);
+
+ if (H->last_err) {
+ H->last_err = oci_drv_error("OCIStmtExecute");
+ } else {
+ /* return the number of affected rows */
+ H->last_err = OCIAttrGet(stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, H->err);
+ ret = rowcount;
+ }
+
+ OCIHandleFree(stmt, OCI_HTYPE_STMT);
+
+ return ret;
+}
+/* }}} */
+
+static int oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC) /* {{{ */
+{
+ int qcount = 0;
+ char const *cu, *l, *r;
+ char *c;
+
+ if (!unquotedlen) {
+ *quotedlen = 2;
+ *quoted = emalloc(*quotedlen+1);
+ strcpy(*quoted, "''");
+ return 1;
+ }
+
+ /* count single quotes */
+ for (cu = unquoted; (cu = strchr(cu,'\'')); qcount++, cu++)
+ ; /* empty loop */
+
+ *quotedlen = unquotedlen + qcount + 2;
+ *quoted = c = emalloc(*quotedlen+1);
+ *c++ = '\'';
+
+ /* foreach (chunk that ends in a quote) */
+ for (l = unquoted; (r = strchr(l,'\'')); l = r+1) {
+ strncpy(c, l, r-l+1);
+ c += (r-l+1);
+ *c++ = '\''; /* add second quote */
+ }
+
+ /* Copy remainder and add enclosing quote */
+ strncpy(c, l, *quotedlen-(c-*quoted)-1);
+ (*quoted)[*quotedlen-1] = '\'';
+ (*quoted)[*quotedlen] = '\0';
+
+ return 1;
+}
+/* }}} */
+
+static int oci_handle_begin(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
+{
+ /* with Oracle, there is nothing special to be done */
+ return 1;
+}
+/* }}} */
+
+static int oci_handle_commit(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
+{
+ pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+ H->last_err = OCITransCommit(H->svc, H->err, 0);
+
+ if (H->last_err) {
+ H->last_err = oci_drv_error("OCITransCommit");
+ return 0;
+ }
+ return 1;
+}
+/* }}} */
+
+static int oci_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
+{
+ pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+ H->last_err = OCITransRollback(H->svc, H->err, 0);
+
+ if (H->last_err) {
+ H->last_err = oci_drv_error("OCITransRollback");
+ return 0;
+ }
+ return 1;
+}
+/* }}} */
+
+static int oci_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) /* {{{ */
+{
+ pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+ if (attr == PDO_ATTR_AUTOCOMMIT) {
+ if (dbh->in_txn) {
+ /* Assume they want to commit whatever is outstanding */
+ H->last_err = OCITransCommit(H->svc, H->err, 0);
+
+ if (H->last_err) {
+ H->last_err = oci_drv_error("OCITransCommit");
+ return 0;
+ }
+ dbh->in_txn = 0;
+ }
+
+ convert_to_long(val);
+
+ dbh->auto_commit = Z_LVAL_P(val);
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+/* }}} */
+
+static struct pdo_dbh_methods oci_methods = {
+ oci_handle_closer,
+ oci_handle_preparer,
+ oci_handle_doer,
+ oci_handle_quoter,
+ oci_handle_begin,
+ oci_handle_commit,
+ oci_handle_rollback,
+ oci_handle_set_attribute,
+ NULL,
+ pdo_oci_fetch_error_func,
+ NULL, /* get_attr */
+ NULL, /* check_liveness */
+ NULL /* get_driver_methods */
+};
+
+static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
+{
+ pdo_oci_db_handle *H;
+ int i, ret = 0;
+ struct pdo_data_src_parser vars[] = {
+ { "charset", NULL, 0 },
+ { "dbname", "", 0 }
+ };
+
+ php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 2);
+
+ H = pecalloc(1, sizeof(*H), dbh->is_persistent);
+ dbh->driver_data = H;
+
+ /* allocate an environment */
+#if HAVE_OCIENVNLSCREATE
+ if (vars[0].optval) {
+ H->charset = OCINlsCharSetNameToId(pdo_oci_Env, vars[0].optval);
+ if (!H->charset) {
+ oci_init_error("OCINlsCharSetNameToId: unknown character set name");
+ goto cleanup;
+ } else {
+ if (OCIEnvNlsCreate(&H->env, PDO_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, H->charset, H->charset) != OCI_SUCCESS) {
+ oci_init_error("OCIEnvNlsCreate: Check the character set is valid and that PHP has access to Oracle libraries and NLS data");
+ goto cleanup;
+ }
+ }
+ }
+#endif
+ if (H->env == NULL) {
+ /* use the global environment */
+ H->env = pdo_oci_Env;
+ }
+
+ /* something to hold errors */
+ OCIHandleAlloc(H->env, (dvoid **)&H->err, OCI_HTYPE_ERROR, 0, NULL);
+
+ /* handle for the server */
+ OCIHandleAlloc(H->env, (dvoid **)&H->server, OCI_HTYPE_SERVER, 0, NULL);
+
+ H->last_err = OCIServerAttach(H->server, H->err, (text*)vars[1].optval,
+ strlen(vars[1].optval), OCI_DEFAULT);
+
+ if (H->last_err) {
+ oci_drv_error("pdo_oci_handle_factory");
+ goto cleanup;
+ }
+
+ H->attached = 1;
+
+ /* create a service context */
+ H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->svc, OCI_HTYPE_SVCCTX, 0, NULL);
+ if (H->last_err) {
+ oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SVCCTX");
+ goto cleanup;
+ }
+
+ H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->session, OCI_HTYPE_SESSION, 0, NULL);
+ if (H->last_err) {
+ oci_drv_error("OCIHandleAlloc: OCI_HTYPE_SESSION");
+ goto cleanup;
+ }
+
+ /* set server handle into service handle */
+ H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->server, 0, OCI_ATTR_SERVER, H->err);
+ if (H->last_err) {
+ oci_drv_error("OCIAttrSet: OCI_ATTR_SERVER");
+ goto cleanup;
+ }
+
+ /* username */
+ if (dbh->username) {
+ H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
+ dbh->username, strlen(dbh->username),
+ OCI_ATTR_USERNAME, H->err);
+ if (H->last_err) {
+ oci_drv_error("OCIAttrSet: OCI_ATTR_USERNAME");
+ goto cleanup;
+ }
+ }
+
+ /* password */
+ if (dbh->password) {
+ H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
+ dbh->password, strlen(dbh->password),
+ OCI_ATTR_PASSWORD, H->err);
+ if (H->last_err) {
+ oci_drv_error("OCIAttrSet: OCI_ATTR_PASSWORD");
+ goto cleanup;
+ }
+ }
+
+ /* Now fire up the session */
+ H->last_err = OCISessionBegin(H->svc, H->err, H->session, OCI_CRED_RDBMS, OCI_DEFAULT);
+ if (H->last_err) {
+ oci_drv_error("OCISessionBegin");
+ goto cleanup;
+ }
+
+ /* set the server handle into service handle */
+ H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->session, 0, OCI_ATTR_SESSION, H->err);
+ if (H->last_err) {
+ oci_drv_error("OCIAttrSet: OCI_ATTR_SESSION");
+ goto cleanup;
+ }
+
+ dbh->methods = &oci_methods;
+ dbh->alloc_own_columns = 1;
+ dbh->native_case = PDO_CASE_UPPER;
+
+ ret = 1;
+
+cleanup:
+ for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
+ if (vars[i].freeme) {
+ efree(vars[i].optval);
+ }
+ }
+
+ if (!ret) {
+ oci_handle_closer(dbh TSRMLS_CC);
+ }
+
+ return ret;
+}
+/* }}} */
+
+pdo_driver_t pdo_oci_driver = {
+ PDO_DRIVER_HEADER(oci),
+ pdo_oci_handle_factory
+};
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c
index 05e37c95a..c5572e36d 100755
--- a/ext/pdo_oci/oci_statement.c
+++ b/ext/pdo_oci/oci_statement.c
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: oci_statement.c,v 1.16.2.10.2.5 2007/01/26 15:07:45 tony2001 Exp $ */
+/* $Id: oci_statement.c,v 1.16.2.10.2.6 2007/06/30 02:30:34 sixd Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -32,18 +32,22 @@
#include "Zend/zend_extensions.h"
#define STMT_CALL(name, params) \
- S->last_err = name params; \
- S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name, S->last_err, __FILE__, __LINE__ TSRMLS_CC); \
- if (S->last_err) { \
- return 0; \
- }
+ do { \
+ S->last_err = name params; \
+ S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name, S->last_err, FALSE, __FILE__, __LINE__ TSRMLS_CC); \
+ if (S->last_err) { \
+ return 0; \
+ } \
+ } while(0)
#define STMT_CALL_MSG(name, msg, params) \
- S->last_err = name params; \
- S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name ": " #msg, S->last_err, __FILE__, __LINE__ TSRMLS_CC); \
- if (S->last_err) { \
- return 0; \
- }
+ do { \
+ S->last_err = name params; \
+ S->last_err = _oci_error(S->err, stmt->dbh, stmt, #name ": " #msg, S->last_err, FALSE, __FILE__, __LINE__ TSRMLS_CC); \
+ if (S->last_err) { \
+ return 0; \
+ } \
+ } while(0)
static php_stream *oci_create_lob_stream(pdo_stmt_t *stmt, OCILobLocator *lob TSRMLS_DC);
@@ -52,7 +56,7 @@ static int oci_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
HashTable *BC = stmt->bound_columns;
HashTable *BP = stmt->bound_params;
-
+
int i;
if (S->stmt) {
@@ -75,18 +79,18 @@ static int oci_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
FREE_HASHTABLE(stmt->bound_columns);
stmt->bound_columns = NULL;
}
-
+
if (BP) {
zend_hash_destroy(BP);
FREE_HASHTABLE(stmt->bound_params);
stmt->bound_params = NULL;
}
-
+
if (S->einfo.errmsg) {
efree(S->einfo.errmsg);
S->einfo.errmsg = NULL;
}
-
+
if (S->cols) {
for (i = 0; i < stmt->column_count; i++) {
if (S->cols[i].data) {
@@ -150,7 +154,7 @@ static int oci_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
(S->stmt, OCI_HTYPE_STMT, &colcount, 0, OCI_ATTR_PARAM_COUNT, S->err));
stmt->column_count = (int)colcount;
-
+
if (S->cols) {
int i;
for (i = 0; i < stmt->column_count; i++) {
@@ -170,7 +174,7 @@ static int oci_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
S->cols = ecalloc(colcount, sizeof(pdo_oci_column));
}
-
+
STMT_CALL_MSG(OCIAttrGet, "ATTR_ROW_COUNT",
(S->stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, S->err));
stmt->row_count = (long)rowcount;
@@ -188,7 +192,7 @@ static sb4 oci_bind_input_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, dv
php_error_docref(NULL TSRMLS_CC, E_WARNING, "param is NULL in oci_bind_input_cb; this should not happen");
return OCI_ERROR;
}
-
+
*indpp = &P->indicator;
if (P->thing) {
@@ -229,8 +233,8 @@ static sb4 oci_bind_output_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, d
*rcodepp = &P->retcode;
*indpp = &P->indicator;
return OCI_CONTINUE;
- }
-
+ }
+
if (Z_TYPE_P(param->parameter) == IS_OBJECT || Z_TYPE_P(param->parameter) == IS_RESOURCE) {
return OCI_CONTINUE;
}
@@ -242,7 +246,7 @@ static sb4 oci_bind_output_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, d
Z_STRVAL_P(param->parameter) = ecalloc(1, Z_STRLEN_P(param->parameter)+1);
P->used_for_output = 1;
- P->actual_len = Z_STRLEN_P(param->parameter);
+ P->actual_len = Z_STRLEN_P(param->parameter);
*alenpp = &P->actual_len;
*bufpp = Z_STRVAL_P(param->parameter);
*piecep = OCI_ONE_PIECE;
@@ -260,7 +264,7 @@ static int oci_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *pa
if (param->is_param) {
pdo_oci_bound_param *P;
sb4 value_sz = -1;
-
+
P = (pdo_oci_bound_param*)param->driver_data;
switch (event_type) {
@@ -274,7 +278,7 @@ static int oci_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *pa
case PDO_PARAM_EVT_ALLOC:
P = (pdo_oci_bound_param*)ecalloc(1, sizeof(pdo_oci_bound_param));
param->driver_data = P;
-
+
/* figure out what we're doing */
switch (PDO_PARAM_TYPE(param->param_type)) {
case PDO_PARAM_STMT:
@@ -293,9 +297,9 @@ static int oci_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *pa
if (param->max_value_len == 0) {
value_sz = 1332; /* maximum size before value is interpreted as a LONG value */
}
-
+
}
-
+
if (param->name) {
STMT_CALL(OCIBindByName, (S->stmt,
&P->bind, S->err, (text*)param->name,
@@ -309,7 +313,7 @@ static int oci_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *pa
&P->indicator, 0, &P->retcode, 0, 0,
OCI_DATA_AT_EXEC));
}
-
+
STMT_CALL(OCIBindDynamic, (P->bind,
S->err,
param, oci_bind_input_cb,
@@ -421,7 +425,7 @@ static int oci_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *pa
return 1;
}
}
-
+
return 1;
} /* }}} */
@@ -459,7 +463,7 @@ static int oci_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, long
if (S->last_err == OCI_SUCCESS_WITH_INFO || S->last_err == OCI_SUCCESS) {
return 1;
}
-
+
oci_stmt_error("OCIStmtFetch");
return 0;
@@ -528,7 +532,7 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */
col->name = estrndup(colname, namelen);
S->cols[colno].dtype = dtype;
-
+
/* how much room do we need to store the field */
switch (dtype) {
case SQLT_LBI:
@@ -550,7 +554,7 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */
S->cols[colno].datalen = sizeof(OCILobLocator*);
dyn = TRUE;
break;
-
+
case SQLT_BIN:
default:
if (dtype == SQLT_DAT || dtype == SQLT_NUM
@@ -588,7 +592,7 @@ static int oci_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */
STMT_CALL(OCIDefineDynamic, (S->cols[colno].def, S->err, &S->cols[colno],
oci_define_callback));
}
-
+
return 1;
} /* }}} */
@@ -614,7 +618,7 @@ static size_t oci_blob_write(php_stream *stream, const char *buf, size_t count T
if (r != OCI_SUCCESS) {
return (size_t)-1;
}
-
+
self->offset += amt;
return amt;
}
@@ -665,7 +669,7 @@ static int oci_blob_seek(php_stream *stream, off_t offset, int whence, off_t *ne
{
struct oci_lob_self *self = (struct oci_lob_self*)stream->abstract;
- return -1;
+ return -1;
}
*/
@@ -723,7 +727,7 @@ static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned lo
*len = 0;
return *ptr ? 1 : 0;
}
-
+
*ptr = C->data;
*len = C->fetched_len;
return 1;
diff --git a/ext/pdo_oci/php_pdo_oci_int.h b/ext/pdo_oci/php_pdo_oci_int.h
index c1f01bb87..1ef008834 100755
--- a/ext/pdo_oci/php_pdo_oci_int.h
+++ b/ext/pdo_oci/php_pdo_oci_int.h
@@ -1,94 +1,95 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2007 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Wez Furlong <wez@php.net> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: php_pdo_oci_int.h,v 1.4.2.2.2.1 2007/01/01 09:36:05 sebastian Exp $ */
-
-#include <oci.h>
-
-typedef struct {
- const char *file;
- int line;
- sb4 errcode;
- char *errmsg;
-} pdo_oci_error_info;
-
-/* stuff we use in an OCI database handle */
-typedef struct {
- OCIServer *server;
- OCISession *session;
- OCIEnv *env;
- OCIError *err;
- OCISvcCtx *svc;
- /* OCI9; 0 == use NLS_LANG */
- ub2 charset;
- sword last_err;
-
- unsigned attached:1;
- unsigned _reserved:31;
-
- pdo_oci_error_info einfo;
-} pdo_oci_db_handle;
-
-typedef struct {
- OCIDefine *def;
- ub2 fetched_len;
- ub2 retcode;
- sb2 indicator;
-
- char *data;
- ub4 datalen;
-
- ub2 dtype;
-
-} pdo_oci_column;
-
-typedef struct {
- pdo_oci_db_handle *H;
- OCIStmt *stmt;
- OCIError *err;
- sword last_err;
- ub2 stmt_type;
- ub4 exec_type;
- pdo_oci_column *cols;
- pdo_oci_error_info einfo;
- unsigned int have_blobs:1;
-} pdo_oci_stmt;
-
-typedef struct {
- OCIBind *bind; /* allocated by OCI */
- sb2 oci_type;
- sb2 indicator;
- ub2 retcode;
-
- ub4 actual_len;
-
- dvoid *thing; /* for LOBS, REFCURSORS etc. */
-
- unsigned used_for_output;
-} pdo_oci_bound_param;
-
-extern const ub4 PDO_OCI_INIT_MODE;
-extern pdo_driver_t pdo_oci_driver;
-extern OCIEnv *pdo_oci_Env;
-
-ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, const char *file, int line TSRMLS_DC);
-#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, __FILE__, __LINE__ TSRMLS_CC)
-#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, __FILE__, __LINE__ TSRMLS_CC)
-
-extern struct pdo_stmt_methods oci_stmt_methods;
-
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2007 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: php_pdo_oci_int.h,v 1.4.2.2.2.3 2007/06/30 02:30:35 sixd Exp $ */
+
+#include <oci.h>
+
+typedef struct {
+ const char *file;
+ int line;
+ sb4 errcode;
+ char *errmsg;
+} pdo_oci_error_info;
+
+/* stuff we use in an OCI database handle */
+typedef struct {
+ OCIServer *server;
+ OCISession *session;
+ OCIEnv *env;
+ OCIError *err;
+ OCISvcCtx *svc;
+ /* OCI9; 0 == use NLS_LANG */
+ ub2 charset;
+ sword last_err;
+
+ unsigned attached:1;
+ unsigned _reserved:31;
+
+ pdo_oci_error_info einfo;
+} pdo_oci_db_handle;
+
+typedef struct {
+ OCIDefine *def;
+ ub2 fetched_len;
+ ub2 retcode;
+ sb2 indicator;
+
+ char *data;
+ ub4 datalen;
+
+ ub2 dtype;
+
+} pdo_oci_column;
+
+typedef struct {
+ pdo_oci_db_handle *H;
+ OCIStmt *stmt;
+ OCIError *err;
+ sword last_err;
+ ub2 stmt_type;
+ ub4 exec_type;
+ pdo_oci_column *cols;
+ pdo_oci_error_info einfo;
+ unsigned int have_blobs:1;
+} pdo_oci_stmt;
+
+typedef struct {
+ OCIBind *bind; /* allocated by OCI */
+ sb2 oci_type;
+ sb2 indicator;
+ ub2 retcode;
+
+ ub4 actual_len;
+
+ dvoid *thing; /* for LOBS, REFCURSORS etc. */
+
+ unsigned used_for_output;
+} pdo_oci_bound_param;
+
+extern const ub4 PDO_OCI_INIT_MODE;
+extern pdo_driver_t pdo_oci_driver;
+extern OCIEnv *pdo_oci_Env;
+
+ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line TSRMLS_DC);
+#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, TRUE, __FILE__, __LINE__ TSRMLS_CC)
+#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, FALSE, __FILE__, __LINE__ TSRMLS_CC)
+#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, FALSE, __FILE__, __LINE__ TSRMLS_CC)
+
+extern struct pdo_stmt_methods oci_stmt_methods;
+
diff --git a/ext/pdo_oci/tests/pdo_oci_quote1.phpt b/ext/pdo_oci/tests/pdo_oci_quote1.phpt
new file mode 100644
index 000000000..d92317f8d
--- /dev/null
+++ b/ext/pdo_oci/tests/pdo_oci_quote1.phpt
@@ -0,0 +1,163 @@
+--TEST--
+Test PDO->quote() for PDO_OCI
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_oci')) die('skip not loaded');
+require(dirname(__FILE__).'/../../pdo/tests/pdo_test.inc');
+PDOTest::skip();
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../pdo/tests/pdo_test.inc';
+$db = PDOTest::factory();
+
+@$db->exec("drop table poq_tab");
+$db->query("create table poq_tab (t varchar2(100))");
+$stmt = $db->prepare('select * from poq_tab');
+
+// The intent is that the fetched data be identical to the unquoted string.
+// Remember!: use bind variables instead of PDO->quote()
+
+$a = array(null, "", "a", "ab", "abc", "ab'cd", "a\b\n", "'", "''", "a'", "'z", "a''b", '"');
+foreach ($a as $u) {
+ $q = $db->quote($u);
+ echo "Unquoted : ";
+ var_dump($u);
+ echo "Quoted : ";
+ var_dump($q);
+
+ $db->exec("delete from poq_tab");
+
+ $db->query("insert into poq_tab (t) values($q)");
+ $stmt->execute();
+ var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
+}
+
+echo "Done\n";
+
+@$db->exec("drop table poq_tab");
+
+?>
+--EXPECTF--
+Unquoted : NULL
+Quoted : string(2) "''"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ NULL
+ }
+}
+Unquoted : string(0) ""
+Quoted : string(2) "''"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ NULL
+ }
+}
+Unquoted : string(1) "a"
+Quoted : string(3) "'a'"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(1) "a"
+ }
+}
+Unquoted : string(2) "ab"
+Quoted : string(4) "'ab'"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(2) "ab"
+ }
+}
+Unquoted : string(3) "abc"
+Quoted : string(5) "'abc'"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(3) "abc"
+ }
+}
+Unquoted : string(5) "ab'cd"
+Quoted : string(8) "'ab''cd'"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(5) "ab'cd"
+ }
+}
+Unquoted : string(4) "a\b
+"
+Quoted : string(6) "'a\b
+'"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(4) "a\b
+"
+ }
+}
+Unquoted : string(1) "'"
+Quoted : string(4) "''''"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(1) "'"
+ }
+}
+Unquoted : string(2) "''"
+Quoted : string(6) "''''''"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(2) "''"
+ }
+}
+Unquoted : string(2) "a'"
+Quoted : string(5) "'a'''"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(2) "a'"
+ }
+}
+Unquoted : string(2) "'z"
+Quoted : string(5) "'''z'"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(2) "'z"
+ }
+}
+Unquoted : string(4) "a''b"
+Quoted : string(8) "'a''''b'"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(4) "a''b"
+ }
+}
+Unquoted : string(1) """
+Quoted : string(3) "'"'"
+array(1) {
+ [0]=>
+ array(1) {
+ ["t"]=>
+ string(1) """
+ }
+}
+Done
diff --git a/ext/pdo_oci/tests/pecl_bug_11345.phpt b/ext/pdo_oci/tests/pecl_bug_11345.phpt
new file mode 100644
index 000000000..b80773a33
--- /dev/null
+++ b/ext/pdo_oci/tests/pecl_bug_11345.phpt
@@ -0,0 +1,29 @@
+--TEST--
+PECL PDO_OCI Bug #11345 (Test invalid character set name)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_oci')) die('skip not loaded');
+require(dirname(__FILE__).'/../../pdo/tests/pdo_test.inc');
+PDOTest::skip();
+?>
+--FILE--
+<?php
+
+// This tests only part of PECL bug 11345. The other part - testing
+// when the National Language Support (NLS) environment can't be
+// initialized - is very difficult to test portably.
+
+try {
+ $dbh = new PDO('oci:dbname=xxx;charset=yyy', 'abc', 'def');
+}
+catch (PDOException $e) {
+ echo 'Connection failed: ' . $e->getMessage(). "\n";
+ exit;
+}
+
+echo "Done\n";
+
+?>
+
+--EXPECTF--
+Connection failed: SQLSTATE[HY000]: OCINlsCharSetNameToId: unknown character set name (%s) \ No newline at end of file
diff --git a/ext/pdo_oci/tests/pecl_bug_6364.phpt b/ext/pdo_oci/tests/pecl_bug_6364.phpt
new file mode 100644
index 000000000..b2981ec0b
--- /dev/null
+++ b/ext/pdo_oci/tests/pecl_bug_6364.phpt
@@ -0,0 +1,71 @@
+--TEST--
+PECL PDO_OCI Bug #6364 (segmentation fault on stored procedure call with OUT binds)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_oci')) die('skip not loaded');
+require(dirname(__FILE__).'/../../pdo/tests/pdo_test.inc');
+PDOTest::skip();
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../pdo/tests/pdo_test.inc';
+$dbh = PDOTest::factory();
+
+@$dbh->exec ("drop table bug_6364_t");
+
+$dbh->exec ("create table bug_6364_t (c1 varchar2(10), c2 varchar2(10), c3 varchar2(10), c4 varchar2(10), c5 varchar2(10))");
+
+$dbh->exec ("create or replace procedure bug_6364_sp(p1 IN varchar2, p2 IN varchar2, p3 IN varchar2, p4 OUT varchar2, p5 OUT varchar2) as begin insert into bug_6364_t (c1, c2, c3) values (p1, p2, p3); p4 := 'val4'; p5 := 'val5'; end;");
+
+$stmt = $dbh->prepare("call bug_6364_sp('p1','p2','p3',?,?)");
+
+$out_param1 = "a";
+$out_param2 = "a";
+
+$stmt->bindParam(1, $out_param1,PDO::PARAM_STR, 1024);
+$stmt->bindParam(2, $out_param2,PDO::PARAM_STR, 1024);
+
+$stmt->execute() or die ("Execution error: " . var_dump($dbh->errorInfo()));
+
+var_dump($out_param1);
+var_dump($out_param2);
+
+foreach ($dbh->query("select * from bug_6364_t") as $row) {
+ var_dump($row);
+}
+
+print "Done\n";
+
+// Cleanup
+$dbh->exec ("drop procedure bug_6364_sp");
+$dbh->exec ("drop table bug_6364_t");
+
+?>
+
+--EXPECTF--
+string(4) "val4"
+string(4) "val5"
+array(10) {
+ ["c1"]=>
+ string(2) "p1"
+ [0]=>
+ string(2) "p1"
+ ["c2"]=>
+ string(2) "p2"
+ [1]=>
+ string(2) "p2"
+ ["c3"]=>
+ string(2) "p3"
+ [2]=>
+ string(2) "p3"
+ ["c4"]=>
+ NULL
+ [3]=>
+ NULL
+ ["c5"]=>
+ NULL
+ [4]=>
+ NULL
+}
+Done