mirror of
https://github.com/php/pecl-database-pdo_oci.git
synced 2026-03-23 23:12:16 +01:00
Initial import from PHP
This commit is contained in:
68
LICENSE
Normal file
68
LICENSE
Normal file
@@ -0,0 +1,68 @@
|
||||
--------------------------------------------------------------------
|
||||
The PHP License, version 3.01
|
||||
Copyright (c) 1999 - 2024 The PHP Group. All rights reserved.
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, is permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
3. The name "PHP" must not be used to endorse or promote products
|
||||
derived from this software without prior written permission. For
|
||||
written permission, please contact group@php.net.
|
||||
|
||||
4. Products derived from this software may not be called "PHP", nor
|
||||
may "PHP" appear in their name, without prior written permission
|
||||
from group@php.net. You may indicate that your software works in
|
||||
conjunction with PHP by saying "Foo for PHP" instead of calling
|
||||
it "PHP Foo" or "phpfoo"
|
||||
|
||||
5. The PHP Group may publish revised and/or new versions of the
|
||||
license from time to time. Each version will be given a
|
||||
distinguishing version number.
|
||||
Once covered code has been published under a particular version
|
||||
of the license, you may always continue to use it under the terms
|
||||
of that version. You may also choose to use such covered code
|
||||
under the terms of any subsequent version of the license
|
||||
published by the PHP Group. No one other than the PHP Group has
|
||||
the right to modify the terms applicable to covered code created
|
||||
under this License.
|
||||
|
||||
6. Redistributions of any form whatsoever must retain the following
|
||||
acknowledgment:
|
||||
"This product includes PHP software, freely available from
|
||||
<http://www.php.net/software/>".
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
|
||||
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
|
||||
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals on behalf of the PHP Group.
|
||||
|
||||
The PHP Group can be contacted via Email at group@php.net.
|
||||
|
||||
For more information on the PHP Group and the PHP project,
|
||||
please see <http://www.php.net>.
|
||||
|
||||
PHP includes the Zend Engine, freely available at
|
||||
<http://www.zend.com>.
|
||||
204
config.m4
Normal file
204
config.m4
Normal file
@@ -0,0 +1,204 @@
|
||||
if test -z "$SED"; then
|
||||
PHP_PDO_OCI_SED="sed";
|
||||
else
|
||||
PHP_PDO_OCI_SED="$SED";
|
||||
fi
|
||||
|
||||
PHP_PDO_OCI_TAIL1=`echo a | tail -n1 2>/dev/null`
|
||||
if test "$PHP_PDO_OCI_TAIL1" = "a"; then
|
||||
PHP_PDO_OCI_TAIL1="tail -n1"
|
||||
else
|
||||
PHP_PDO_OCI_TAIL1="tail -1"
|
||||
fi
|
||||
|
||||
AC_DEFUN([AC_PDO_OCI_VERSION],[
|
||||
AC_MSG_CHECKING([Oracle version])
|
||||
PDO_OCI_LCS_BASE=$PDO_OCI_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME
|
||||
dnl Oracle 10g, 11g, 12c etc
|
||||
PDO_OCI_LCS=`ls $PDO_OCI_LCS_BASE.*.1 2> /dev/null | $PHP_PDO_OCI_TAIL1`
|
||||
if test -f "$PDO_OCI_LCS"; then
|
||||
dnl Oracle 10g, 11g 12c etc. The x.2 version libraries are named x.1 for
|
||||
dnl drop in compatibility
|
||||
PDO_OCI_VERSION=`echo $PDO_OCI_LCS | $PHP_PDO_OCI_SED -e 's/.*\.\(.*\)\.1$/\1.1/'`
|
||||
elif test -f $PDO_OCI_LCS_BASE.9.0; then
|
||||
dnl There is no case for Oracle 9.2. Oracle 9.2 libraries have a 9.0 suffix
|
||||
dnl for drop-in compatibility with Oracle 9.0
|
||||
PDO_OCI_VERSION=9.0
|
||||
else
|
||||
AC_MSG_ERROR(Oracle libclntsh.$SHLIB_SUFFIX_NAME client library not found or its version is lower than 9)
|
||||
fi
|
||||
AC_MSG_RESULT($PDO_OCI_VERSION)
|
||||
])
|
||||
|
||||
AC_DEFUN([AC_PDO_OCI_CHECK_LIB_DIR],[
|
||||
AC_CHECK_SIZEOF([long])
|
||||
AC_MSG_CHECKING([if we're at 64-bit platform])
|
||||
AS_IF([test "$ac_cv_sizeof_long" -eq 4],[
|
||||
AC_MSG_RESULT([no])
|
||||
TMP_PDO_OCI_LIB_DIR="$PDO_OCI_DIR/lib32"
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
TMP_PDO_OCI_LIB_DIR="$PDO_OCI_DIR/lib"
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([OCI8 libraries dir])
|
||||
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" && test -d "$PDO_OCI_DIR/lib32"; then
|
||||
PDO_OCI_LIB_DIR="$PDO_OCI_DIR/lib32"
|
||||
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 required OCI8 libraries not found])
|
||||
fi
|
||||
AC_MSG_RESULT($PDO_OCI_LIB_DIR)
|
||||
])
|
||||
|
||||
PHP_ARG_WITH([pdo-oci],
|
||||
[Oracle OCI support for PDO],
|
||||
[AS_HELP_STRING([[--with-pdo-oci[=DIR]]],
|
||||
[PDO: Oracle OCI support. DIR defaults to $ORACLE_HOME. Use
|
||||
--with-pdo-oci=instantclient,/path/to/instant/client/lib for an Oracle
|
||||
Instant Client installation.])])
|
||||
|
||||
if test "$PHP_PDO_OCI" != "no"; then
|
||||
|
||||
if test "$PHP_PDO" = "no" && test "$ext_shared" = "no"; then
|
||||
AC_MSG_ERROR([PDO is not enabled! Add --enable-pdo to your configure line.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([Oracle Install-Dir])
|
||||
if test "$PHP_PDO_OCI" = "yes" || test -z "$PHP_PDO_OCI"; then
|
||||
PDO_OCI_DIR=$ORACLE_HOME
|
||||
else
|
||||
PDO_OCI_DIR=$PHP_PDO_OCI
|
||||
fi
|
||||
AC_MSG_RESULT($PHP_PDO_OCI)
|
||||
|
||||
AC_MSG_CHECKING([if that is sane])
|
||||
if test -z "$PDO_OCI_DIR"; then
|
||||
AC_MSG_ERROR([You need to tell me where to find your Oracle Instant Client SDK, or set ORACLE_HOME.])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
if test "instantclient" = "`echo $PDO_OCI_DIR | cut -d, -f1`" ; then
|
||||
AC_CHECK_SIZEOF([long])
|
||||
AC_MSG_CHECKING([if we're at 64-bit platform])
|
||||
AS_IF([test "$ac_cv_sizeof_long" -eq 4],[
|
||||
AC_MSG_RESULT([no])
|
||||
PDO_OCI_CLIENT_DIR="client"
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
PDO_OCI_CLIENT_DIR="client64"
|
||||
])
|
||||
|
||||
PDO_OCI_LIB_DIR="`echo $PDO_OCI_DIR | cut -d, -f2`"
|
||||
AC_PDO_OCI_VERSION($PDO_OCI_LIB_DIR)
|
||||
|
||||
AC_MSG_CHECKING([for oci.h])
|
||||
dnl Header directory for Instant Client SDK RPM install
|
||||
OCISDKRPMINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/lib/oracle/\(.*\)/\('${PDO_OCI_CLIENT_DIR}'\)/lib[/]*$!\1/include/oracle/\2/\3!'`
|
||||
|
||||
dnl Header directory for manual installation
|
||||
OCISDKMANINC=`echo "$PDO_OCI_LIB_DIR" | $PHP_PDO_OCI_SED -e 's!^\(.*\)/lib[/]*$!\1/include!'`
|
||||
|
||||
dnl Header directory for Instant Client SDK zip file install
|
||||
OCISDKZIPINC=$PDO_OCI_LIB_DIR/sdk/include
|
||||
|
||||
|
||||
if test -f "$OCISDKRPMINC/oci.h" ; then
|
||||
PHP_ADD_INCLUDE($OCISDKRPMINC)
|
||||
AC_MSG_RESULT($OCISDKRPMINC)
|
||||
elif test -f "$OCISDKMANINC/oci.h" ; then
|
||||
PHP_ADD_INCLUDE($OCISDKMANINC)
|
||||
AC_MSG_RESULT($OCISDKMANINC)
|
||||
elif test -f "$OCISDKZIPINC/oci.h" ; then
|
||||
PHP_ADD_INCLUDE($OCISDKZIPINC)
|
||||
AC_MSG_RESULT($OCISDKZIPINC)
|
||||
else
|
||||
AC_MSG_ERROR([I'm too dumb to figure out where the include dir is in your Instant Client install])
|
||||
fi
|
||||
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"
|
||||
fi
|
||||
if test -d "$PDO_OCI_DIR/rdbms/demo"; then
|
||||
PHP_ADD_INCLUDE($PDO_OCI_DIR/rdbms/demo)
|
||||
PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/rdbms/demo"
|
||||
fi
|
||||
if test -d "$PDO_OCI_DIR/network/public"; then
|
||||
PHP_ADD_INCLUDE($PDO_OCI_DIR/network/public)
|
||||
PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/network/public"
|
||||
fi
|
||||
if test -d "$PDO_OCI_DIR/plsql/public"; then
|
||||
PHP_ADD_INCLUDE($PDO_OCI_DIR/plsql/public)
|
||||
PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/plsql/public"
|
||||
fi
|
||||
if test -d "$PDO_OCI_DIR/include"; then
|
||||
PHP_ADD_INCLUDE($PDO_OCI_DIR/include)
|
||||
PDO_OCI_INCLUDES="$PDO_OCI_INCLUDES -I$PDO_OCI_DIR/include"
|
||||
fi
|
||||
|
||||
if test -f "$PDO_OCI_LIB_DIR/sysliblist"; then
|
||||
PHP_EVAL_LIBLINE(`cat $PDO_OCI_LIB_DIR/sysliblist`, PDO_OCI_SYSLIB)
|
||||
elif test -f "$PDO_OCI_DIR/rdbms/lib/sysliblist"; then
|
||||
PHP_EVAL_LIBLINE(`cat $PDO_OCI_DIR/rdbms/lib/sysliblist`, PDO_OCI_SYSLIB)
|
||||
fi
|
||||
AC_PDO_OCI_VERSION($PDO_OCI_LIB_DIR)
|
||||
fi
|
||||
|
||||
case $PDO_OCI_VERSION in
|
||||
7.3|8.0|8.1)
|
||||
AC_MSG_ERROR([Oracle client libraries < 9 are not supported])
|
||||
;;
|
||||
esac
|
||||
|
||||
PHP_ADD_LIBRARY(clntsh, 1, PDO_OCI_SHARED_LIBADD)
|
||||
PHP_ADD_LIBPATH($PDO_OCI_LIB_DIR, PDO_OCI_SHARED_LIBADD)
|
||||
|
||||
PHP_CHECK_LIBRARY(clntsh, OCIEnvCreate,
|
||||
[
|
||||
AC_DEFINE(HAVE_OCIENVCREATE,1,[ ])
|
||||
], [], [
|
||||
-L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
|
||||
])
|
||||
|
||||
PHP_CHECK_LIBRARY(clntsh, OCIEnvNlsCreate,
|
||||
[
|
||||
AC_DEFINE(HAVE_OCIENVNLSCREATE,1,[ ])
|
||||
], [], [
|
||||
-L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
|
||||
])
|
||||
|
||||
dnl Scrollable cursors?
|
||||
PHP_CHECK_LIBRARY(clntsh, OCIStmtFetch2,
|
||||
[
|
||||
AC_DEFINE(HAVE_OCISTMTFETCH2,1,[ ])
|
||||
], [], [
|
||||
-L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
|
||||
])
|
||||
|
||||
dnl Can handle bytes vs. characters?
|
||||
PHP_CHECK_LIBRARY(clntsh, OCILobRead2,
|
||||
[
|
||||
AC_DEFINE(HAVE_OCILOBREAD2,1,[ ])
|
||||
], [], [
|
||||
-L$PDO_OCI_LIB_DIR $PDO_OCI_SHARED_LIBADD
|
||||
])
|
||||
|
||||
PHP_CHECK_PDO_INCLUDES
|
||||
|
||||
PHP_NEW_EXTENSION(pdo_oci, pdo_oci.c oci_driver.c oci_statement.c, $ext_shared,,-I$pdo_cv_inc_path)
|
||||
|
||||
PHP_SUBST_OLD(PDO_OCI_SHARED_LIBADD)
|
||||
PHP_SUBST_OLD(PDO_OCI_DIR)
|
||||
PHP_SUBST_OLD(PDO_OCI_VERSION)
|
||||
|
||||
PHP_ADD_EXTENSION_DEP(pdo_oci, pdo)
|
||||
|
||||
AC_DEFINE_UNQUOTED(PHP_PDO_OCI_CLIENT_VERSION, "$PDO_OCI_VERSION", [ ])
|
||||
fi
|
||||
45
config.w32
Normal file
45
config.w32
Normal file
@@ -0,0 +1,45 @@
|
||||
// vim:ft=javascript
|
||||
|
||||
ARG_WITH("pdo-oci", "Oracle OCI support for PDO", "no");
|
||||
|
||||
if (PHP_PDO_OCI != "no") {
|
||||
|
||||
pdo_oci_dirs = new Array(
|
||||
PHP_PDO_OCI,
|
||||
PHP_PDO_OCI + "\\oci",
|
||||
PHP_PHP_BUILD + "\\instantclient10_*\\sdk",
|
||||
PHP_PHP_BUILD + "\\oci92"
|
||||
);
|
||||
|
||||
pdo_oci_lib_paths = "";
|
||||
pdo_oci_inc_paths = "";
|
||||
|
||||
// find the oracle install
|
||||
for (i = 0; i < pdo_oci_dirs.length; i++) {
|
||||
pdo_oci_lib_paths += pdo_oci_dirs[i] + "\\lib;";
|
||||
pdo_oci_lib_paths += pdo_oci_dirs[i] + "\\lib\\msvc;";
|
||||
pdo_oci_inc_paths += pdo_oci_dirs[i] + "\\include;";
|
||||
}
|
||||
|
||||
pdo_oci_inc_paths += PHP_PHP_BUILD + "\\include\\instantclient;"
|
||||
pdo_oci_lib_paths += PHP_PHP_BUILD + "\\lib\\instantclient;";
|
||||
|
||||
pdo_oci_header = CHECK_HEADER_ADD_INCLUDE("oci.h", "CFLAGS_PDO_OCI", pdo_oci_inc_paths, null, null, true);
|
||||
|
||||
if (pdo_oci_header && CHECK_LIB("oci.lib", "pdo_oci", pdo_oci_lib_paths)) {
|
||||
|
||||
pdo_oci_inc_dir = FSO.GetParentFolderName(pdo_oci_header);
|
||||
|
||||
EXTENSION('pdo_oci', 'pdo_oci.c oci_driver.c oci_statement.c');
|
||||
|
||||
/* probe for some functions not present in older versions */
|
||||
pdo_oci_inc_dir = FSO.GetFolder(pdo_oci_header);
|
||||
CHECK_FUNC_IN_HEADER('oci.h', 'OCIEnvCreate', pdo_oci_inc_dir, 'CFLAGS_PDO_OCI');
|
||||
CHECK_FUNC_IN_HEADER('ociap.h', 'OCIStmtFetch2', pdo_oci_inc_dir, 'CFLAGS_PDO_OCI');
|
||||
CHECK_FUNC_IN_HEADER('ociap.h', 'OCIEnvNlsCreate', pdo_oci_inc_dir, 'CFLAGS_PDO_OCI');
|
||||
|
||||
} else {
|
||||
WARNING("pdo-oci not enabled; libraries and headers not found");
|
||||
}
|
||||
ADD_EXTENSION_DEP('pdo_oci', 'pdo');
|
||||
}
|
||||
895
oci_driver.c
Normal file
895
oci_driver.c
Normal file
@@ -0,0 +1,895 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: |
|
||||
| https://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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#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 inline ub4 pdo_oci_sanitize_prefetch(long prefetch);
|
||||
|
||||
static void pdo_oci_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info) /* {{{ */
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line) /* {{{ */
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
case 12154: /* ORA-12154: TNS:could not resolve service name */
|
||||
strcpy(*pdo_err, "42S02");
|
||||
break;
|
||||
|
||||
case 22: /* ORA-00022: invalid session id */
|
||||
case 378:
|
||||
case 602:
|
||||
case 603:
|
||||
case 604:
|
||||
case 609:
|
||||
case 1012: /* ORA-01012: */
|
||||
case 1033:
|
||||
case 1041:
|
||||
case 1043:
|
||||
case 1089:
|
||||
case 1090:
|
||||
case 1092:
|
||||
case 3113: /* ORA-03133: end of file on communication channel */
|
||||
case 3114:
|
||||
case 3122:
|
||||
case 3135:
|
||||
case 12153:
|
||||
case 27146:
|
||||
case 28511:
|
||||
/* 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 propagate 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 && status != OCI_SUCCESS_WITH_INFO) {
|
||||
zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode, "SQLSTATE[%s]: %s", *pdo_err, einfo->errmsg);
|
||||
}
|
||||
|
||||
return einfo->errcode;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void oci_handle_closer(pdo_dbh_t *dbh) /* {{{ */
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (H->err) {
|
||||
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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static bool oci_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t *stmt, zval *driver_options) /* {{{ */
|
||||
{
|
||||
pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
|
||||
pdo_oci_stmt *S = ecalloc(1, sizeof(*S));
|
||||
ub4 prefetch;
|
||||
zend_string *nsql = NULL;
|
||||
int ret;
|
||||
|
||||
#ifdef HAVE_OCISTMTFETCH2
|
||||
S->exec_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR,
|
||||
PDO_CURSOR_FWDONLY) == 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, sql, &nsql);
|
||||
|
||||
if (ret == 1) {
|
||||
/* query was re-written */
|
||||
sql = nsql;
|
||||
} else if (ret == -1) {
|
||||
/* couldn't grok it */
|
||||
strcpy(dbh->error_code, stmt->error_code);
|
||||
efree(S);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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 (ZSTR_LEN(sql) != 0) {
|
||||
H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*) ZSTR_VAL(sql), (ub4) ZSTR_LEN(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
|
||||
if (nsql) {
|
||||
zend_string_release(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 false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
prefetch = H->prefetch; /* Note 0 is allowed so in future REF CURSORs can be used & then passed with no row loss*/
|
||||
H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0,
|
||||
OCI_ATTR_PREFETCH_ROWS, H->err);
|
||||
if (!H->last_err) {
|
||||
prefetch *= PDO_OCI_PREFETCH_ROWSIZE;
|
||||
H->last_err = OCIAttrSet(S->stmt, OCI_HTYPE_STMT, &prefetch, 0,
|
||||
OCI_ATTR_PREFETCH_MEMORY, H->err);
|
||||
}
|
||||
|
||||
stmt->driver_data = S;
|
||||
stmt->methods = &oci_stmt_methods;
|
||||
if (nsql) {
|
||||
zend_string_release(nsql);
|
||||
nsql = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_long oci_handle_doer(pdo_dbh_t *dbh, const zend_string *sql) /* {{{ */
|
||||
{
|
||||
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*)ZSTR_VAL(sql), (ub4) ZSTR_LEN(sql), 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, 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);
|
||||
|
||||
sword last_err = H->last_err;
|
||||
|
||||
if (last_err) {
|
||||
H->last_err = oci_drv_error("OCIStmtExecute");
|
||||
}
|
||||
|
||||
if (!last_err || last_err == OCI_SUCCESS_WITH_INFO) {
|
||||
/* 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 zend_string* oci_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype ) /* {{{ */
|
||||
{
|
||||
int qcount = 0;
|
||||
char const *cu, *l, *r;
|
||||
char *c, *quoted;
|
||||
size_t quotedlen;
|
||||
zend_string *quoted_str;
|
||||
|
||||
if (ZSTR_LEN(unquoted) == 0) {
|
||||
return ZSTR_INIT_LITERAL("''", 0);
|
||||
}
|
||||
|
||||
/* count single quotes */
|
||||
for (cu = ZSTR_VAL(unquoted); (cu = strchr(cu,'\'')); qcount++, cu++)
|
||||
; /* empty loop */
|
||||
|
||||
quotedlen = ZSTR_LEN(unquoted) + qcount + 2;
|
||||
quoted = c = emalloc(quotedlen+1);
|
||||
*c++ = '\'';
|
||||
|
||||
/* foreach (chunk that ends in a quote) */
|
||||
for (l = ZSTR_VAL(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';
|
||||
|
||||
quoted_str = zend_string_init(quoted, quotedlen, 0);
|
||||
efree(quoted);
|
||||
return quoted_str;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static bool oci_handle_begin(pdo_dbh_t *dbh) /* {{{ */
|
||||
{
|
||||
/* with Oracle, there is nothing special to be done */
|
||||
return true;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static bool oci_handle_commit(pdo_dbh_t *dbh) /* {{{ */
|
||||
{
|
||||
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 false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static bool oci_handle_rollback(pdo_dbh_t *dbh) /* {{{ */
|
||||
{
|
||||
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 false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static bool oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) /* {{{ */
|
||||
{
|
||||
zend_long lval;
|
||||
pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
|
||||
|
||||
switch (attr) {
|
||||
case PDO_ATTR_AUTOCOMMIT:
|
||||
{
|
||||
bool bval;
|
||||
if (!pdo_get_bool_param(&bval, val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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 false;
|
||||
}
|
||||
dbh->in_txn = false;
|
||||
}
|
||||
|
||||
dbh->auto_commit = (unsigned int) bval;
|
||||
return true;
|
||||
}
|
||||
case PDO_ATTR_PREFETCH:
|
||||
{
|
||||
if (!pdo_get_long_param(&lval, val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
H->prefetch = pdo_oci_sanitize_prefetch(lval);
|
||||
return true;
|
||||
}
|
||||
case PDO_OCI_ATTR_ACTION:
|
||||
{
|
||||
#if (OCI_MAJOR_VERSION >= 10)
|
||||
zend_string *action = zval_try_get_string(val);
|
||||
if (UNEXPECTED(!action)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
|
||||
(dvoid *) ZSTR_VAL(action), (ub4) ZSTR_LEN(action),
|
||||
OCI_ATTR_ACTION, H->err);
|
||||
if (H->last_err) {
|
||||
oci_drv_error("OCIAttrSet: OCI_ATTR_ACTION");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
oci_drv_error("Unsupported attribute type");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
case PDO_OCI_ATTR_CLIENT_INFO:
|
||||
{
|
||||
#if (OCI_MAJOR_VERSION >= 10)
|
||||
zend_string *client_info = zval_try_get_string(val);
|
||||
if (UNEXPECTED(!client_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
|
||||
(dvoid *) ZSTR_VAL(client_info), (ub4) ZSTR_LEN(client_info),
|
||||
OCI_ATTR_CLIENT_INFO, H->err);
|
||||
if (H->last_err) {
|
||||
oci_drv_error("OCIAttrSet: OCI_ATTR_CLIENT_INFO");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
oci_drv_error("Unsupported attribute type");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
case PDO_OCI_ATTR_CLIENT_IDENTIFIER:
|
||||
{
|
||||
#if (OCI_MAJOR_VERSION >= 10)
|
||||
zend_string *identifier = zval_try_get_string(val);
|
||||
if (UNEXPECTED(!identifier)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
|
||||
(dvoid *) ZSTR_VAL(identifier), (ub4) ZSTR_LEN(identifier),
|
||||
OCI_ATTR_CLIENT_IDENTIFIER, H->err);
|
||||
if (H->last_err) {
|
||||
oci_drv_error("OCIAttrSet: OCI_ATTR_CLIENT_IDENTIFIER");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
oci_drv_error("Unsupported attribute type");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
case PDO_OCI_ATTR_MODULE:
|
||||
{
|
||||
#if (OCI_MAJOR_VERSION >= 10)
|
||||
zend_string *module = zval_try_get_string(val);
|
||||
if (UNEXPECTED(!module)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
|
||||
(dvoid *) ZSTR_VAL(module), (ub4) ZSTR_LEN(module),
|
||||
OCI_ATTR_MODULE, H->err);
|
||||
if (H->last_err) {
|
||||
oci_drv_error("OCIAttrSet: OCI_ATTR_MODULE");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
oci_drv_error("Unsupported attribute type");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
case PDO_OCI_ATTR_CALL_TIMEOUT:
|
||||
{
|
||||
#if (OCI_MAJOR_VERSION >= 18)
|
||||
if (!pdo_get_long_param(&lval, val)) {
|
||||
return false;
|
||||
}
|
||||
ub4 timeout = (ub4) lval;
|
||||
|
||||
H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX,
|
||||
(dvoid *) &timeout, (ub4) 0,
|
||||
OCI_ATTR_CALL_TIMEOUT, H->err);
|
||||
if (H->last_err) {
|
||||
oci_drv_error("OCIAttrSet: OCI_ATTR_CALL_TIMEOUT");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
oci_drv_error("Unsupported attribute type");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int oci_handle_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value) /* {{{ */
|
||||
{
|
||||
pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
|
||||
|
||||
switch (attr) {
|
||||
case PDO_ATTR_SERVER_VERSION:
|
||||
case PDO_ATTR_SERVER_INFO:
|
||||
{
|
||||
text infostr[512];
|
||||
char verstr[15];
|
||||
ub4 vernum;
|
||||
|
||||
if (OCIServerRelease(H->svc, H->err, infostr, (ub4)sizeof(infostr), (ub1)OCI_HTYPE_SVCCTX, &vernum))
|
||||
{
|
||||
ZVAL_STRING(return_value, "<<Unknown>>");
|
||||
} else {
|
||||
if (attr == PDO_ATTR_SERVER_INFO) {
|
||||
ZVAL_STRING(return_value, (char *)infostr);
|
||||
} else {
|
||||
slprintf(verstr, sizeof(verstr), "%d.%d.%d.%d.%d",
|
||||
(int)((vernum>>24) & 0xFF), /* version number */
|
||||
(int)((vernum>>20) & 0x0F), /* release number*/
|
||||
(int)((vernum>>12) & 0xFF), /* update number */
|
||||
(int)((vernum>>8) & 0x0F), /* port release number */
|
||||
(int)((vernum>>0) & 0xFF)); /* port update number */
|
||||
|
||||
ZVAL_STRING(return_value, verstr);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case PDO_ATTR_CLIENT_VERSION:
|
||||
{
|
||||
#if OCI_MAJOR_VERSION > 10 || (OCI_MAJOR_VERSION == 10 && OCI_MINOR_VERSION >= 2)
|
||||
/* Run time client version */
|
||||
sword major, minor, update, patch, port_update;
|
||||
char verstr[15];
|
||||
|
||||
OCIClientVersion(&major, &minor, &update, &patch, &port_update);
|
||||
slprintf(verstr, sizeof(verstr), "%d.%d.%d.%d.%d", major, minor, update, patch, port_update);
|
||||
ZVAL_STRING(return_value, verstr);
|
||||
#elif defined(PHP_PDO_OCI_CLIENT_VERSION)
|
||||
/* Compile time client version */
|
||||
ZVAL_STRING(return_value, PHP_PDO_OCI_CLIENT_VERSION);
|
||||
#else
|
||||
return FALSE;
|
||||
|
||||
#endif /* Check for OCIClientVersion() support */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case PDO_ATTR_AUTOCOMMIT:
|
||||
ZVAL_BOOL(return_value, dbh->auto_commit);
|
||||
return TRUE;
|
||||
|
||||
case PDO_ATTR_PREFETCH:
|
||||
ZVAL_LONG(return_value, H->prefetch);
|
||||
return TRUE;
|
||||
case PDO_OCI_ATTR_CALL_TIMEOUT:
|
||||
{
|
||||
#if (OCI_MAJOR_VERSION >= 18)
|
||||
ub4 timeout;
|
||||
|
||||
H->last_err = OCIAttrGet(H->svc, OCI_HTYPE_SVCCTX,
|
||||
(dvoid *) &timeout, NULL,
|
||||
OCI_ATTR_CALL_TIMEOUT, H->err);
|
||||
if (H->last_err) {
|
||||
oci_drv_error("OCIAttrGet: OCI_ATTR_CALL_TIMEOUT");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZVAL_LONG(return_value, (zend_long) timeout);
|
||||
return TRUE;
|
||||
#else
|
||||
oci_drv_error("Unsupported attribute type");
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_result pdo_oci_check_liveness(pdo_dbh_t *dbh) /* {{{ */
|
||||
{
|
||||
pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
|
||||
sb4 error_code = 0;
|
||||
#if (!((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))))
|
||||
char version[256];
|
||||
#endif
|
||||
|
||||
/* TODO move attached check to PDO level */
|
||||
if (H->attached == 0) {
|
||||
return FAILURE;
|
||||
}
|
||||
/* TODO add persistent_timeout check at PDO level */
|
||||
|
||||
|
||||
/* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
|
||||
* such as from Pre-10.1 servers, the error is still from the server and we would have
|
||||
* successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
|
||||
* Pre-10.2 clients
|
||||
*/
|
||||
#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */
|
||||
H->last_err = OCIPing (H->svc, H->err, OCI_DEFAULT);
|
||||
#else
|
||||
/* use good old OCIServerVersion() */
|
||||
H->last_err = OCIServerVersion (H->svc, H->err, (text *)version, sizeof(version), OCI_HTYPE_SVCCTX);
|
||||
#endif
|
||||
if (H->last_err == OCI_SUCCESS) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
OCIErrorGet (H->err, (ub4)1, NULL, &error_code, NULL, 0, OCI_HTYPE_ERROR);
|
||||
|
||||
if (error_code == 1010) {
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static const 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, /* last_id not supported */
|
||||
pdo_oci_fetch_error_func,
|
||||
oci_handle_get_attribute,
|
||||
pdo_oci_check_liveness, /* check_liveness */
|
||||
NULL, /* get_driver_methods */
|
||||
NULL, /* request_shutdown */
|
||||
NULL, /* in transaction, use PDO's internal tracking mechanism */
|
||||
NULL /* get_gc */
|
||||
};
|
||||
|
||||
static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
|
||||
{
|
||||
pdo_oci_db_handle *H;
|
||||
int i, ret = 0;
|
||||
struct pdo_data_src_parser vars[] = {
|
||||
{ "charset", NULL, 0 },
|
||||
{ "dbname", "", 0 },
|
||||
{ "user", NULL, 0 },
|
||||
{ "password", NULL, 0 }
|
||||
};
|
||||
|
||||
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 4);
|
||||
|
||||
H = pecalloc(1, sizeof(*H), dbh->is_persistent);
|
||||
dbh->driver_data = H;
|
||||
|
||||
dbh->skip_param_evt =
|
||||
1 << PDO_PARAM_EVT_FETCH_PRE |
|
||||
1 << PDO_PARAM_EVT_FETCH_POST |
|
||||
1 << PDO_PARAM_EVT_NORMALIZE;
|
||||
|
||||
H->prefetch = PDO_OCI_PREFETCH_DEFAULT;
|
||||
|
||||
/* allocate an environment */
|
||||
#ifdef HAVE_OCIENVNLSCREATE
|
||||
if (vars[0].optval) {
|
||||
H->charset = OCINlsCharSetNameToId(pdo_oci_Env, (const oratext *)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,
|
||||
(sb4) 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 && vars[2].optval) {
|
||||
dbh->username = pestrdup(vars[2].optval, dbh->is_persistent);
|
||||
}
|
||||
|
||||
if (dbh->username) {
|
||||
H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
|
||||
dbh->username, (ub4) 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 && vars[3].optval) {
|
||||
dbh->password = pestrdup(vars[3].optval, dbh->is_persistent);
|
||||
}
|
||||
|
||||
if (dbh->password) {
|
||||
H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
|
||||
dbh->password, (ub4) 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");
|
||||
/* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
|
||||
* user's password has expired, but is still usable.
|
||||
*/
|
||||
if (H->last_err != OCI_SUCCESS_WITH_INFO) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* Get max character width */
|
||||
H->last_err = OCINlsNumericInfoGet(H->env, H->err, &H->max_char_width, OCI_NLS_CHARSET_MAXBYTESZ);
|
||||
if (H->last_err) {
|
||||
oci_drv_error("OCINlsNumericInfoGet: OCI_NLS_CHARSET_MAXBYTESZ");
|
||||
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);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
const pdo_driver_t pdo_oci_driver = {
|
||||
PDO_DRIVER_HEADER(oci),
|
||||
pdo_oci_handle_factory
|
||||
};
|
||||
|
||||
static inline ub4 pdo_oci_sanitize_prefetch(long prefetch) /* {{{ */
|
||||
{
|
||||
if (prefetch < 0) {
|
||||
prefetch = 0;
|
||||
} else if (prefetch > UB4MAXVAL / PDO_OCI_PREFETCH_ROWSIZE) {
|
||||
prefetch = PDO_OCI_PREFETCH_DEFAULT;
|
||||
}
|
||||
return ((ub4)prefetch);
|
||||
}
|
||||
/* }}} */
|
||||
1003
oci_statement.c
Normal file
1003
oci_statement.c
Normal file
File diff suppressed because it is too large
Load Diff
153
pdo_oci.c
Normal file
153
pdo_oci.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: |
|
||||
| https://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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#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"
|
||||
#ifdef ZTS
|
||||
#include <TSRM/TSRM.h>
|
||||
#endif
|
||||
|
||||
/* {{{ pdo_oci_module_entry */
|
||||
|
||||
static const zend_module_dep pdo_oci_deps[] = {
|
||||
ZEND_MOD_REQUIRED("pdo")
|
||||
ZEND_MOD_END
|
||||
};
|
||||
|
||||
zend_module_entry pdo_oci_module_entry = {
|
||||
STANDARD_MODULE_HEADER_EX, NULL,
|
||||
pdo_oci_deps,
|
||||
"PDO_OCI",
|
||||
NULL,
|
||||
PHP_MINIT(pdo_oci),
|
||||
PHP_MSHUTDOWN(pdo_oci),
|
||||
PHP_RINIT(pdo_oci),
|
||||
NULL,
|
||||
PHP_MINFO(pdo_oci),
|
||||
PHP_PDO_OCI_VERSION,
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
#ifdef COMPILE_DL_PDO_OCI
|
||||
ZEND_GET_MODULE(pdo_oci)
|
||||
#endif
|
||||
|
||||
const ub4 PDO_OCI_INIT_MODE =
|
||||
#if 0 && defined(OCI_SHARED)
|
||||
/* shared mode is known to be bad for PHP */
|
||||
OCI_SHARED
|
||||
#else
|
||||
OCI_DEFAULT
|
||||
#endif
|
||||
#ifdef OCI_OBJECT
|
||||
|OCI_OBJECT
|
||||
#endif
|
||||
#ifdef ZTS
|
||||
|OCI_THREADED
|
||||
#endif
|
||||
;
|
||||
|
||||
/* true global environment */
|
||||
OCIEnv *pdo_oci_Env = NULL;
|
||||
|
||||
#ifdef ZTS
|
||||
/* lock for pdo_oci_Env initialization */
|
||||
static MUTEX_T pdo_oci_env_mutex;
|
||||
#endif
|
||||
|
||||
/* {{{ PHP_MINIT_FUNCTION */
|
||||
PHP_MINIT_FUNCTION(pdo_oci)
|
||||
{
|
||||
REGISTER_PDO_CLASS_CONST_LONG("OCI_ATTR_ACTION", (zend_long)PDO_OCI_ATTR_ACTION);
|
||||
REGISTER_PDO_CLASS_CONST_LONG("OCI_ATTR_CLIENT_INFO", (zend_long)PDO_OCI_ATTR_CLIENT_INFO);
|
||||
REGISTER_PDO_CLASS_CONST_LONG("OCI_ATTR_CLIENT_IDENTIFIER", (zend_long)PDO_OCI_ATTR_CLIENT_IDENTIFIER);
|
||||
REGISTER_PDO_CLASS_CONST_LONG("OCI_ATTR_MODULE", (zend_long)PDO_OCI_ATTR_MODULE);
|
||||
REGISTER_PDO_CLASS_CONST_LONG("OCI_ATTR_CALL_TIMEOUT", (zend_long)PDO_OCI_ATTR_CALL_TIMEOUT);
|
||||
|
||||
if (FAILURE == php_pdo_register_driver(&pdo_oci_driver)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// Defer OCI init to PHP_RINIT_FUNCTION because with php-fpm,
|
||||
// NLS_LANG is not yet available here.
|
||||
|
||||
#ifdef ZTS
|
||||
pdo_oci_env_mutex = tsrm_mutex_alloc();
|
||||
#endif
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_RINIT_FUNCTION */
|
||||
PHP_RINIT_FUNCTION(pdo_oci)
|
||||
{
|
||||
if (!pdo_oci_Env) {
|
||||
#ifdef ZTS
|
||||
tsrm_mutex_lock(pdo_oci_env_mutex);
|
||||
if (!pdo_oci_Env) { // double-checked locking idiom
|
||||
#endif
|
||||
#ifdef HAVE_OCIENVCREATE
|
||||
OCIEnvCreate(&pdo_oci_Env, PDO_OCI_INIT_MODE, NULL, NULL, NULL, NULL, 0, NULL);
|
||||
#else
|
||||
OCIInitialize(PDO_OCI_INIT_MODE, NULL, NULL, NULL, NULL);
|
||||
OCIEnvInit(&pdo_oci_Env, OCI_DEFAULT, 0, NULL);
|
||||
#endif
|
||||
#ifdef ZTS
|
||||
}
|
||||
tsrm_mutex_unlock(pdo_oci_env_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MSHUTDOWN_FUNCTION */
|
||||
PHP_MSHUTDOWN_FUNCTION(pdo_oci)
|
||||
{
|
||||
php_pdo_unregister_driver(&pdo_oci_driver);
|
||||
|
||||
if (pdo_oci_Env) {
|
||||
OCIHandleFree((dvoid*)pdo_oci_Env, OCI_HTYPE_ENV);
|
||||
}
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_mutex_free(pdo_oci_env_mutex);
|
||||
#endif
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ PHP_MINFO_FUNCTION */
|
||||
PHP_MINFO_FUNCTION(pdo_oci)
|
||||
{
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_row(2, "PDO Driver for OCI 8 and later", "enabled");
|
||||
php_info_print_table_end();
|
||||
}
|
||||
/* }}} */
|
||||
36
php_pdo_oci.h
Normal file
36
php_pdo_oci.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: |
|
||||
| https://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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef PHP_PDO_OCI_H
|
||||
#define PHP_PDO_OCI_H
|
||||
|
||||
extern zend_module_entry pdo_oci_module_entry;
|
||||
#define phpext_pdo_oci_ptr &pdo_oci_module_entry
|
||||
|
||||
#include "php_version.h"
|
||||
#define PHP_PDO_OCI_VERSION PHP_VERSION
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
PHP_MINIT_FUNCTION(pdo_oci);
|
||||
PHP_MSHUTDOWN_FUNCTION(pdo_oci);
|
||||
PHP_RINIT_FUNCTION(pdo_oci);
|
||||
PHP_RSHUTDOWN_FUNCTION(pdo_oci);
|
||||
PHP_MINFO_FUNCTION(pdo_oci);
|
||||
|
||||
#endif /* PHP_PDO_OCI_H */
|
||||
116
php_pdo_oci_int.h
Normal file
116
php_pdo_oci_int.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: |
|
||||
| https://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> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef PHP_PDO_OCI_INT_H
|
||||
#define PHP_PDO_OCI_INT_H
|
||||
|
||||
#include "zend_portability.h"
|
||||
|
||||
ZEND_DIAGNOSTIC_IGNORED_START("-Wstrict-prototypes")
|
||||
#include <oci.h>
|
||||
ZEND_DIAGNOSTIC_IGNORED_END
|
||||
|
||||
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 */
|
||||
ub4 prefetch;
|
||||
ub2 charset;
|
||||
sword last_err;
|
||||
sb4 max_char_width;
|
||||
|
||||
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 const 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);
|
||||
#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, TRUE, __FILE__, __LINE__)
|
||||
#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, FALSE, __FILE__, __LINE__)
|
||||
#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, FALSE, __FILE__, __LINE__)
|
||||
|
||||
extern const struct pdo_stmt_methods oci_stmt_methods;
|
||||
|
||||
/* Default prefetch size in number of rows */
|
||||
#define PDO_OCI_PREFETCH_DEFAULT 100
|
||||
|
||||
/* Arbitrary assumed row length for prefetch memory limit calcuation */
|
||||
#define PDO_OCI_PREFETCH_ROWSIZE 1024
|
||||
|
||||
|
||||
enum {
|
||||
PDO_OCI_ATTR_ACTION = PDO_ATTR_DRIVER_SPECIFIC,
|
||||
PDO_OCI_ATTR_CLIENT_INFO,
|
||||
PDO_OCI_ATTR_CLIENT_IDENTIFIER,
|
||||
PDO_OCI_ATTR_MODULE,
|
||||
PDO_OCI_ATTR_CALL_TIMEOUT
|
||||
};
|
||||
|
||||
#endif /* PHP_PDO_OCI_INT_H */
|
||||
22
tests/bug41996.phpt
Normal file
22
tests/bug41996.phpt
Normal file
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
PDO OCI Bug #41996 (Problem accessing Oracle ROWID)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
|
||||
$stmt = $db->prepare('SELECT rowid FROM dual');
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
var_dump(strlen($row[0]) > 0);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
28
tests/bug44301.phpt
Normal file
28
tests/bug44301.phpt
Normal file
@@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
PDO OCI Bug #44301 (Segfault when an exception is thrown on persistent connections)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
putenv("PDO_OCI_TEST_ATTR=" . serialize(array(PDO::ATTR_PERSISTENT => true)));
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare('SELECT * FROM no_table');
|
||||
$stmt->execute();
|
||||
} catch (PDOException $e) {
|
||||
print $e->getMessage();
|
||||
}
|
||||
$db = null;
|
||||
?>
|
||||
--EXPECTF--
|
||||
SQLSTATE[HY000]: General error: 942 OCIStmtExecute: ORA-00942: table or view does not exist
|
||||
(%s%epdo_oci%eoci_statement.c:%d)
|
||||
70
tests/bug46274.phpt
Normal file
70
tests/bug46274.phpt
Normal file
@@ -0,0 +1,70 @@
|
||||
--TEST--
|
||||
Bug #46274 (pdo_pgsql - Segfault when using PDO::ATTR_STRINGIFY_FETCHES and blob)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
|
||||
|
||||
$db->beginTransaction();
|
||||
|
||||
$db->query('CREATE TABLE test46274 (id INT NOT NULL, blob1 BLOB)');
|
||||
|
||||
$stmt = $db->prepare("INSERT INTO test46274 (id, blob1) VALUES (:id, EMPTY_BLOB()) RETURNING blob1 INTO :foo");
|
||||
|
||||
$data = 'foo';
|
||||
$blob = fopen('php://memory', 'a');
|
||||
fwrite($blob, $data);
|
||||
rewind($blob);
|
||||
|
||||
$id = 1;
|
||||
$stmt->bindparam(':id', $id);
|
||||
$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
|
||||
$stmt->execute();
|
||||
|
||||
$data = '';
|
||||
$blob = fopen('php://memory', 'a');
|
||||
fwrite($blob, $data);
|
||||
rewind($blob);
|
||||
|
||||
$id = 1;
|
||||
$stmt->bindparam(':id', $id);
|
||||
$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
|
||||
$stmt->execute();
|
||||
|
||||
$res = $db->query("SELECT blob1 from test46274");
|
||||
// Resource
|
||||
var_dump($res->fetch());
|
||||
|
||||
// Empty string
|
||||
var_dump($res->fetch());
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test46274");
|
||||
?>
|
||||
--EXPECT--
|
||||
array(2) {
|
||||
["blob1"]=>
|
||||
string(3) "foo"
|
||||
[0]=>
|
||||
string(3) "foo"
|
||||
}
|
||||
array(2) {
|
||||
["blob1"]=>
|
||||
string(0) ""
|
||||
[0]=>
|
||||
string(0) ""
|
||||
}
|
||||
77
tests/bug46274_2.phpt
Normal file
77
tests/bug46274_2.phpt
Normal file
@@ -0,0 +1,77 @@
|
||||
--TEST--
|
||||
Bug #46274 (pdo_pgsql - Segfault when using PDO::ATTR_STRINGIFY_FETCHES and blob)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
|
||||
|
||||
$db->beginTransaction();
|
||||
|
||||
$db->query('CREATE TABLE test46274_2 (id INT NOT NULL, blob1 BLOB)');
|
||||
|
||||
$stmt = $db->prepare("INSERT INTO test46274_2 (id, blob1) VALUES (:id, EMPTY_BLOB()) RETURNING blob1 INTO :foo");
|
||||
|
||||
$data = 'foo';
|
||||
$blob = fopen('php://memory', 'a');
|
||||
fwrite($blob, $data);
|
||||
rewind($blob);
|
||||
|
||||
$id = 1;
|
||||
$stmt->bindparam(':id', $id);
|
||||
$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
|
||||
$stmt->execute();
|
||||
|
||||
$data = '';
|
||||
$blob = fopen('php://memory', 'a');
|
||||
fwrite($blob, $data);
|
||||
rewind($blob);
|
||||
|
||||
$id = 1;
|
||||
$stmt->bindparam(':id', $id);
|
||||
$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
|
||||
$stmt->execute();
|
||||
|
||||
$res = $db->query("SELECT blob1 from test46274_2");
|
||||
// Resource
|
||||
var_dump($row = $res->fetch());
|
||||
var_dump(fread($row[0], 1024));
|
||||
fclose($row[0]);
|
||||
|
||||
// Empty string
|
||||
var_dump($row = $res->fetch());
|
||||
var_dump(fread($row[0], 1024));
|
||||
fclose($row[0]);
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test46274_2");
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
["blob1"]=>
|
||||
resource(%d) of type (stream)
|
||||
[0]=>
|
||||
resource(%d) of type (stream)
|
||||
}
|
||||
string(3) "foo"
|
||||
array(2) {
|
||||
["blob1"]=>
|
||||
resource(%d) of type (stream)
|
||||
[0]=>
|
||||
resource(%d) of type (stream)
|
||||
}
|
||||
string(0) ""
|
||||
44
tests/bug54379.phpt
Normal file
44
tests/bug54379.phpt
Normal file
@@ -0,0 +1,44 @@
|
||||
--TEST--
|
||||
Bug #54379 (PDO_OCI: UTF-8 output gets truncated)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../pdo/tests/pdo_test.inc';
|
||||
if (!preg_match('/charset=.*utf8/i', getenv('PDOTEST_DSN')))
|
||||
die('skip not UTF8 DSN');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$db->exec("CREATE TABLE test54379 (col1 NVARCHAR2(20))");
|
||||
$db->exec("INSERT INTO test54379 VALUES('12345678901234567890')");
|
||||
$db->exec("INSERT INTO test54379 VALUES('あいうえおかきくけこさしすせそたちつてと')");
|
||||
$stmt = $db->prepare("SELECT * FROM test54379");
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test54379");
|
||||
?>
|
||||
--EXPECT--
|
||||
array(2) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
["col1"]=>
|
||||
string(20) "12345678901234567890"
|
||||
}
|
||||
[1]=>
|
||||
array(1) {
|
||||
["col1"]=>
|
||||
string(60) "あいうえおかきくけこさしすせそたちつてと"
|
||||
}
|
||||
}
|
||||
184
tests/bug57702.phpt
Normal file
184
tests/bug57702.phpt
Normal file
@@ -0,0 +1,184 @@
|
||||
--TEST--
|
||||
PDO OCI Bug #57702 (Multi-row BLOB fetches)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require('ext/pdo/tests/pdo_test.inc');
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
|
||||
// Note the PDO test setup sets PDO::ATTR_STRINGIFY_FETCHES to true
|
||||
// (and sets PDO::ATTR_CASE to PDO::CASE_LOWER)
|
||||
|
||||
$query = "create table test57702 (id number, data1 blob, data2 blob)";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->execute();
|
||||
|
||||
function do_insert($db, $id, $data1, $data2)
|
||||
{
|
||||
$db->beginTransaction();
|
||||
$stmt = $db->prepare("insert into test57702 (id, data1, data2) values (:id, empty_blob(), empty_blob()) returning data1, data2 into :blob1, :blob2");
|
||||
$stmt->bindParam(':id', $id);
|
||||
$stmt->bindParam(':blob1', $blob1, PDO::PARAM_LOB);
|
||||
$stmt->bindParam(':blob2', $blob2, PDO::PARAM_LOB);
|
||||
$blob1 = null;
|
||||
$blob2 = null;
|
||||
$stmt->execute();
|
||||
|
||||
fwrite($blob1, $data1);
|
||||
fclose($blob1);
|
||||
fwrite($blob2, $data2);
|
||||
fclose($blob2);
|
||||
$db->commit();
|
||||
}
|
||||
|
||||
do_insert($db, 1, "row 1 col 1", "row 1 col 2");
|
||||
do_insert($db, 2, "row 2 col 1", "row 2 col 2");
|
||||
|
||||
////////////////////
|
||||
|
||||
echo "First Query\n";
|
||||
|
||||
// Fetch it back
|
||||
$stmt = $db->prepare('select data1, data2 from test57702 order by id');
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
var_dump($row['data1']);
|
||||
var_dump($row['data2']);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
var_dump($row['data1']);
|
||||
var_dump($row['data2']);
|
||||
|
||||
////////////////////
|
||||
|
||||
echo "\nSecond Query\n";
|
||||
|
||||
foreach($db->query("select data1 as d1, data2 as d2 from test57702 order by id") as $row) {
|
||||
var_dump($row['d1']);
|
||||
var_dump($row['d2']);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
echo "\nThird Query\n";
|
||||
|
||||
$stmt = $db->prepare('select data1 as d3_1, data2 as d3_2 from test57702 order by id');
|
||||
|
||||
$rs = $stmt->execute();
|
||||
$stmt->bindColumn('d3_1' , $clob1, PDO::PARAM_LOB);
|
||||
$stmt->bindColumn('d3_2' , $clob2, PDO::PARAM_LOB);
|
||||
|
||||
while ($stmt->fetch(PDO::FETCH_BOUND)) {
|
||||
var_dump($clob1);
|
||||
var_dump($clob2);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
echo "\nFourth Query\n";
|
||||
|
||||
$a = array();
|
||||
$i = 0;
|
||||
foreach($db->query("select data1 as d4_1, data2 as d4_2 from test57702 order by id") as $row) {
|
||||
$a[$i][0] = $row['d4_1'];
|
||||
$a[$i][1] = $row['d4_2'];
|
||||
$i++;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($a); $i++) {
|
||||
var_dump($a[$i][0]);
|
||||
var_dump($a[$i][1]);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
echo "\nFifth Query\n";
|
||||
|
||||
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); // Let's use streams
|
||||
|
||||
// Since each column only has one lob descriptor, the last row is
|
||||
// shown twice because the lob descriptor for each column is reused in
|
||||
// the stream
|
||||
|
||||
$a = array();
|
||||
$i = 0;
|
||||
foreach($db->query("select data1 as d4_1, data2 as d4_2 from test57702 order by id") as $row) {
|
||||
$a[$i][0] = $row['d4_1'];
|
||||
$a[$i][1] = $row['d4_2'];
|
||||
$i++;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($a); $i++) {
|
||||
var_dump(stream_get_contents($a[$i][0]));
|
||||
var_dump(stream_get_contents($a[$i][1]));
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
||||
echo "\nSixth Query\n";
|
||||
|
||||
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); // Let's use streams
|
||||
|
||||
$a = array();
|
||||
$i = 0;
|
||||
foreach($db->query("select data1 as d4_1, data2 as d4_2 from test57702 order by id") as $row) {
|
||||
$a[$i][0] = $row['d4_1'];
|
||||
$a[$i][1] = $row['d4_2'];
|
||||
var_dump(stream_get_contents($a[$i][0]));
|
||||
var_dump(stream_get_contents($a[$i][1]));
|
||||
$i++;
|
||||
}
|
||||
|
||||
print "done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test57702");
|
||||
?>
|
||||
--EXPECT--
|
||||
First Query
|
||||
string(11) "row 1 col 1"
|
||||
string(11) "row 1 col 2"
|
||||
string(11) "row 2 col 1"
|
||||
string(11) "row 2 col 2"
|
||||
|
||||
Second Query
|
||||
string(11) "row 1 col 1"
|
||||
string(11) "row 1 col 2"
|
||||
string(11) "row 2 col 1"
|
||||
string(11) "row 2 col 2"
|
||||
|
||||
Third Query
|
||||
string(11) "row 1 col 1"
|
||||
string(11) "row 1 col 2"
|
||||
string(11) "row 2 col 1"
|
||||
string(11) "row 2 col 2"
|
||||
|
||||
Fourth Query
|
||||
string(11) "row 1 col 1"
|
||||
string(11) "row 1 col 2"
|
||||
string(11) "row 2 col 1"
|
||||
string(11) "row 2 col 2"
|
||||
|
||||
Fifth Query
|
||||
string(11) "row 2 col 1"
|
||||
string(11) "row 2 col 2"
|
||||
string(11) "row 2 col 1"
|
||||
string(11) "row 2 col 2"
|
||||
|
||||
Sixth Query
|
||||
string(11) "row 1 col 1"
|
||||
string(11) "row 1 col 2"
|
||||
string(11) "row 2 col 1"
|
||||
string(11) "row 2 col 2"
|
||||
done
|
||||
140
tests/bug60994.phpt
Normal file
140
tests/bug60994.phpt
Normal file
@@ -0,0 +1,140 @@
|
||||
--TEST--
|
||||
PDO OCI Bug #60994 (Reading a multibyte CLOB caps at 8192 characters)
|
||||
--CREDITS--
|
||||
Chuck Burgess
|
||||
ashnazg@php.net
|
||||
--EXTENSIONS--
|
||||
mbstring
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../pdo/tests/pdo_test.inc';
|
||||
if (!strpos(strtolower(getenv('PDOTEST_DSN')), 'charset=al32utf8')) die('skip expected output valid for AL32UTF8 character set');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$dbh = PDOTest::factory();
|
||||
$dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
|
||||
$dbh->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
|
||||
|
||||
$dbh->exec('CREATE TABLE pdo_oci_bug60994 (id NUMBER, data CLOB, data2 NCLOB)');
|
||||
|
||||
$id = null;
|
||||
$insert = $dbh->prepare('INSERT INTO pdo_oci_bug60994 (id, data, data2) VALUES (:id, :data, :data2)');
|
||||
$insert->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$select = $dbh->prepare("SELECT data, data2 FROM pdo_oci_bug60994 WHERE id = :id");
|
||||
|
||||
|
||||
echo PHP_EOL, 'Test 1: j', PHP_EOL;
|
||||
$string1 = 'abc' . str_repeat('j', 8187) . 'xyz'; // 8193 chars total works fine here (even 1 million works fine, subject to memory_limit)
|
||||
$id = 1;
|
||||
$insert->bindParam(':data', $string1, \PDO::PARAM_STR, strlen($string1)); // length in bytes
|
||||
$insert->bindParam(':data2', $string1, \PDO::PARAM_STR, strlen($string1));
|
||||
$insert->execute();
|
||||
$select->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$select->execute();
|
||||
$row = $select->fetch();
|
||||
$stream1 = stream_get_contents($row['DATA']);
|
||||
$start1 = mb_substr($stream1, 0, 10);
|
||||
$ending1 = mb_substr($stream1, -10);
|
||||
echo 'size of string1 is ', strlen($string1), ' bytes, ', mb_strlen($string1), ' chars.', PHP_EOL;
|
||||
echo 'size of stream1 is ', strlen($stream1), ' bytes, ', mb_strlen($stream1), ' chars.', PHP_EOL;
|
||||
echo 'beg of stream1 is ', $start1, PHP_EOL;
|
||||
echo 'end of stream1 is ', $ending1, PHP_EOL;
|
||||
if ($string1 != $stream1 || $stream1 != stream_get_contents($row['DATA2'])) {
|
||||
echo 'Expected nclob value to match clob value for stream1', PHP_EOL;
|
||||
}
|
||||
|
||||
echo PHP_EOL, 'Test 2: £', PHP_EOL;
|
||||
$string2 = 'abc' . str_repeat('£', 8187) . 'xyz'; // 8193 chars total is when it breaks
|
||||
$id = 2;
|
||||
$insert->bindParam(':data', $string2, \PDO::PARAM_STR, strlen($string2)); // length in bytes
|
||||
$insert->bindParam(':data2', $string2, \PDO::PARAM_STR, strlen($string2));
|
||||
$insert->execute();
|
||||
$select->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$select->execute();
|
||||
$row = $select->fetch();
|
||||
$stream2 = stream_get_contents($row['DATA']);
|
||||
$start2 = mb_substr($stream2, 0, 10);
|
||||
$ending2 = mb_substr($stream2, -10);
|
||||
echo 'size of string2 is ', strlen($string2), ' bytes, ', mb_strlen($string2), ' chars.', PHP_EOL;
|
||||
echo 'size of stream2 is ', strlen($stream2), ' bytes, ', mb_strlen($stream2), ' chars.', PHP_EOL;
|
||||
echo 'beg of stream2 is ', $start2, PHP_EOL;
|
||||
echo 'end of stream2 is ', $ending2, PHP_EOL;
|
||||
if ($string2 != $stream2 || $stream2 != stream_get_contents($row['DATA2'])) {
|
||||
echo 'Expected nclob value to match clob value for stream2', PHP_EOL;
|
||||
}
|
||||
|
||||
echo PHP_EOL, 'Test 3: Җ', PHP_EOL;
|
||||
$string3 = 'abc' . str_repeat('Җ', 8187) . 'xyz'; // 8193 chars total is when it breaks
|
||||
$id = 3;
|
||||
$insert->bindParam(':data', $string3, \PDO::PARAM_STR, strlen($string3)); // length in bytes
|
||||
$insert->bindParam(':data2', $string3, \PDO::PARAM_STR, strlen($string3));
|
||||
$insert->execute();
|
||||
$select->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$select->execute();
|
||||
$row = $select->fetch();
|
||||
$stream3 = stream_get_contents($row['DATA']);
|
||||
$start3 = mb_substr($stream3, 0, 10);
|
||||
$ending3 = mb_substr($stream3, -10);
|
||||
echo 'size of string3 is ', strlen($string3), ' bytes, ', mb_strlen($string3), ' chars.', PHP_EOL;
|
||||
echo 'size of stream3 is ', strlen($stream3), ' bytes, ', mb_strlen($stream3), ' chars.', PHP_EOL;
|
||||
echo 'beg of stream3 is ', $start3, PHP_EOL;
|
||||
echo 'end of stream3 is ', $ending3, PHP_EOL;
|
||||
if ($string3 != $stream3 || $stream3 != stream_get_contents($row['DATA2'])) {
|
||||
echo 'Expected nclob value to match clob value for stream3', PHP_EOL;
|
||||
}
|
||||
|
||||
echo PHP_EOL, 'Test 4: の', PHP_EOL;
|
||||
$string4 = 'abc' . str_repeat('の', 8187) . 'xyz'; // 8193 chars total is when it breaks
|
||||
$id = 4;
|
||||
$insert->bindParam(':data', $string4, \PDO::PARAM_STR, strlen($string4)); // length in bytes
|
||||
$insert->bindParam(':data2', $string4, \PDO::PARAM_STR, strlen($string4));
|
||||
$insert->execute();
|
||||
$select->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$select->execute();
|
||||
$row = $select->fetch();
|
||||
$stream4 = stream_get_contents($row['DATA']);
|
||||
$start4 = mb_substr($stream4, 0, 10);
|
||||
$ending4 = mb_substr($stream4, -10);
|
||||
echo 'size of string4 is ', strlen($string4), ' bytes, ', mb_strlen($string4), ' chars.', PHP_EOL;
|
||||
echo 'size of stream4 is ', strlen($stream4), ' bytes, ', mb_strlen($stream4), ' chars.', PHP_EOL;
|
||||
echo 'beg of stream4 is ', $start4, PHP_EOL;
|
||||
echo 'end of stream4 is ', $ending4, PHP_EOL;
|
||||
if ($string4 != $stream4 || $stream4 != stream_get_contents($row['DATA2'])) {
|
||||
echo 'Expected nclob value to match clob value for stream4', PHP_EOL;
|
||||
}
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "pdo_oci_bug60994");
|
||||
?>
|
||||
--EXPECT--
|
||||
Test 1: j
|
||||
size of string1 is 8193 bytes, 8193 chars.
|
||||
size of stream1 is 8193 bytes, 8193 chars.
|
||||
beg of stream1 is abcjjjjjjj
|
||||
end of stream1 is jjjjjjjxyz
|
||||
|
||||
Test 2: £
|
||||
size of string2 is 16380 bytes, 8193 chars.
|
||||
size of stream2 is 16380 bytes, 8193 chars.
|
||||
beg of stream2 is abc£££££££
|
||||
end of stream2 is £££££££xyz
|
||||
|
||||
Test 3: Җ
|
||||
size of string3 is 16380 bytes, 8193 chars.
|
||||
size of stream3 is 16380 bytes, 8193 chars.
|
||||
beg of stream3 is abcҖҖҖҖҖҖҖ
|
||||
end of stream3 is ҖҖҖҖҖҖҖxyz
|
||||
|
||||
Test 4: の
|
||||
size of string4 is 24567 bytes, 8193 chars.
|
||||
size of stream4 is 24567 bytes, 8193 chars.
|
||||
beg of stream4 is abcののののののの
|
||||
end of stream4 is のののののののxyz
|
||||
31
tests/bug_33707.phpt
Normal file
31
tests/bug_33707.phpt
Normal file
@@ -0,0 +1,31 @@
|
||||
--TEST--
|
||||
PDO OCI Bug #33707 (Errors in select statements not reported)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
|
||||
|
||||
$rs = $db->query('select blah from a_table_that_does_not_exist');
|
||||
var_dump($rs);
|
||||
var_dump($db->errorInfo());
|
||||
?>
|
||||
--EXPECTF--
|
||||
bool(false)
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(5) "HY000"
|
||||
[1]=>
|
||||
int(942)
|
||||
[2]=>
|
||||
string(%d) "OCIStmtExecute: ORA-00942: table or view does not exist
|
||||
(%s:%d)"
|
||||
}
|
||||
58
tests/checkliveness.phpt
Normal file
58
tests/checkliveness.phpt
Normal file
@@ -0,0 +1,58 @@
|
||||
--TEST--
|
||||
PDO OCI checkliveness (code coverage)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
|
||||
$dsn = getenv('PDOTEST_DSN');
|
||||
$user = getenv('PDOTEST_USER');
|
||||
$pass = getenv('PDOTEST_PASS');
|
||||
$attr = getenv('PDOTEST_ATTR');
|
||||
|
||||
try {
|
||||
$db = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
echo 'Connection failed: ' . $e->getMessage();
|
||||
exit;
|
||||
}
|
||||
|
||||
// This triggers the call to check liveness
|
||||
try {
|
||||
$db = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
echo 'Connection failed: ' . $e->getMessage();
|
||||
exit;
|
||||
}
|
||||
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare('SELECT * FROM dual');
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
var_dump($row);
|
||||
} catch (PDOException $e) {
|
||||
print $e->getMessage();
|
||||
}
|
||||
|
||||
$db = null;
|
||||
?>
|
||||
--EXPECT--
|
||||
array(2) {
|
||||
["DUMMY"]=>
|
||||
string(1) "X"
|
||||
[0]=>
|
||||
string(1) "X"
|
||||
}
|
||||
25
tests/common.phpt
Normal file
25
tests/common.phpt
Normal file
@@ -0,0 +1,25 @@
|
||||
--TEST--
|
||||
OCI
|
||||
--EXTENSIONS--
|
||||
pdo_oci
|
||||
--REDIRECTTEST--
|
||||
# magic auto-configuration
|
||||
|
||||
$config = array(
|
||||
'TESTS' => 'ext/pdo/tests'
|
||||
);
|
||||
|
||||
|
||||
if (false !== getenv('PDO_OCI_TEST_DSN')) {
|
||||
# user set them from their shell
|
||||
$config['ENV']['PDOTEST_DSN'] = getenv('PDO_OCI_TEST_DSN');
|
||||
$config['ENV']['PDOTEST_USER'] = getenv('PDO_OCI_TEST_USER');
|
||||
$config['ENV']['PDOTEST_PASS'] = getenv('PDO_OCI_TEST_PASS');
|
||||
$config['ENV']['PDOTEST_ATTR'] = getenv('PDO_OCI_TEST_ATTR');
|
||||
} else {
|
||||
$config['ENV']['PDOTEST_DSN'] = 'oci:dbname=localhost/xe;charset=WE8MSWIN1252';
|
||||
$config['ENV']['PDOTEST_USER'] = 'SYSTEM';
|
||||
$config['ENV']['PDOTEST_PASS'] = 'oracle';
|
||||
}
|
||||
|
||||
return $config;
|
||||
121
tests/oci_success_with_info.phpt
Normal file
121
tests/oci_success_with_info.phpt
Normal file
@@ -0,0 +1,121 @@
|
||||
--TEST--
|
||||
Handling OCI_SUCCESS_WITH_INFO
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--XFAIL--
|
||||
This test frequently fails in CI
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function connectAsAdmin(): PDO {
|
||||
return PDOTest::test_factory(__DIR__ . '/../../pdo_oci/tests/common.phpt');
|
||||
}
|
||||
|
||||
function connectAsUser(string $username, string $password): PDO {
|
||||
return new PDO(getenv('PDOTEST_DSN'), $username, $password);
|
||||
}
|
||||
|
||||
function dropProfile(PDO $conn): void {
|
||||
$conn->exec(<<<'SQL'
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'DROP PROFILE BUG77120_PROFILE CASCADE';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE != -2380 THEN
|
||||
RAISE;
|
||||
END IF;
|
||||
END;
|
||||
SQL
|
||||
);
|
||||
}
|
||||
|
||||
function dropUser(PDO $conn): void {
|
||||
$conn->exec(<<<'SQL'
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'DROP USER BUG77120_USER CASCADE';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE != -1918 THEN
|
||||
RAISE;
|
||||
END IF;
|
||||
END;
|
||||
SQL
|
||||
);
|
||||
}
|
||||
|
||||
function triggerCompilationError(PDO $conn): void {
|
||||
$conn->exec(<<<'SQL'
|
||||
CREATE OR REPLACE FUNCTION BUG77120(INT A) RETURN INT
|
||||
AS
|
||||
BEGIN
|
||||
RETURN 0;
|
||||
END;
|
||||
SQL
|
||||
);
|
||||
}
|
||||
|
||||
require __DIR__ . '/../../pdo/tests/pdo_test.inc';
|
||||
|
||||
$conn = connectAsAdmin();
|
||||
|
||||
dropUser($conn);
|
||||
dropProfile($conn);
|
||||
|
||||
$password = bin2hex(random_bytes(8));
|
||||
|
||||
$conn->exec('CREATE PROFILE BUG77120_PROFILE LIMIT PASSWORD_LIFE_TIME 1/86400 PASSWORD_GRACE_TIME 1');
|
||||
$conn->exec('CREATE USER BUG77120_USER IDENTIFIED BY "' . $password . '" PROFILE BUG77120_PROFILE');
|
||||
$conn->exec('GRANT CREATE SESSION TO BUG77120_USER');
|
||||
|
||||
// let the password expire
|
||||
sleep(3); // 2 seconds is causing random test failures
|
||||
|
||||
$conn = connectAsUser('BUG77120_USER', $password);
|
||||
var_dump($conn->errorInfo());
|
||||
|
||||
$conn = connectAsAdmin();
|
||||
dropUser($conn);
|
||||
dropProfile($conn);
|
||||
|
||||
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
|
||||
triggerCompilationError($conn);
|
||||
var_dump($conn->errorInfo());
|
||||
|
||||
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
triggerCompilationError($conn);
|
||||
var_dump($conn->errorInfo());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(5) "HY000"
|
||||
[1]=>
|
||||
int(28002)
|
||||
[2]=>
|
||||
string(%d) "OCISessionBegin: OCI_SUCCESS_WITH_INFO: ORA-28002: %s
|
||||
(%s:%d)"
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(5) "HY000"
|
||||
[1]=>
|
||||
int(24344)
|
||||
[2]=>
|
||||
string(%d) "OCIStmtExecute: OCI_SUCCESS_WITH_INFO: ORA-24344: %s
|
||||
(%s:%d)"
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(5) "HY000"
|
||||
[1]=>
|
||||
int(24344)
|
||||
[2]=>
|
||||
string(%d) "OCIStmtExecute: OCI_SUCCESS_WITH_INFO: ORA-24344: %s
|
||||
(%s:%d)"
|
||||
}
|
||||
57
tests/pdo_oci_attr_action.phpt
Normal file
57
tests/pdo_oci_attr_action.phpt
Normal file
@@ -0,0 +1,57 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Setting session action
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$query = 'select action from v$session where sid = sys_context(\'USERENV\', \'SID\')';
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'ACTION NOT SET: ';
|
||||
var_dump($row['action']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_ACTION, "some action"));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'ACTION SET: ';
|
||||
var_dump($row['action']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_ACTION, "something else!"));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'ACTION RESET: ';
|
||||
var_dump($row['action']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_ACTION, null));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'ACTION NULLED: ';
|
||||
var_dump($row['action']);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
ACTION NOT SET: NULL
|
||||
bool(true)
|
||||
ACTION SET: string(11) "some action"
|
||||
bool(true)
|
||||
ACTION RESET: string(15) "something else!"
|
||||
bool(true)
|
||||
ACTION NULLED: NULL
|
||||
Done
|
||||
68
tests/pdo_oci_attr_autocommit_1.phpt
Normal file
68
tests/pdo_oci_attr_autocommit_1.phpt
Normal file
@@ -0,0 +1,68 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Basic autocommit functionality
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
print "PDO::ATTR_AUTOCOMMIT: Default: ";
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
|
||||
echo "Change setting to false - ";
|
||||
|
||||
$dbh->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
|
||||
|
||||
print "PDO::ATTR_AUTOCOMMIT: ";
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
|
||||
echo "Change setting back to true - ";
|
||||
|
||||
$dbh->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
|
||||
|
||||
print "PDO::ATTR_AUTOCOMMIT: ";
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
|
||||
// Use 2nd connection to check that autocommit does commit
|
||||
|
||||
echo "Insert data\n";
|
||||
$dbh->exec("create table test_pdo_oci_attr_autocommit_1 (col1 varchar2(20))");
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_1 (col1) values ('some data')");
|
||||
|
||||
$dbh2 = PDOTest::factory();
|
||||
|
||||
echo "Second connection should be able to see committed data\n";
|
||||
$s = $dbh2->prepare("select col1 from test_pdo_oci_attr_autocommit_1");
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo "Data is: " . $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test_pdo_oci_attr_autocommit_1");
|
||||
?>
|
||||
--EXPECT--
|
||||
PDO::ATTR_AUTOCOMMIT: Default: bool(true)
|
||||
Change setting to false - PDO::ATTR_AUTOCOMMIT: bool(false)
|
||||
Change setting back to true - PDO::ATTR_AUTOCOMMIT: bool(true)
|
||||
Insert data
|
||||
Second connection should be able to see committed data
|
||||
Data is: some data
|
||||
Done
|
||||
133
tests/pdo_oci_attr_autocommit_2.phpt
Normal file
133
tests/pdo_oci_attr_autocommit_2.phpt
Normal file
@@ -0,0 +1,133 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: beginTransaction and native transactions
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$dbh->exec("create table test_pdo_oci_attr_autocommit_2 (col1 varchar2(25))");
|
||||
|
||||
echo "Test 1 Check beginTransaction insertion\n";
|
||||
|
||||
$dbh->beginTransaction();
|
||||
try {
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('data 1')");
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('data 2')");
|
||||
$dbh->commit();
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
echo "Caught unexpected exception at line " . __LINE__ . "\n";
|
||||
echo $e->getMessage() . "\n";
|
||||
$dbh->rollback();
|
||||
}
|
||||
|
||||
echo "Test 2 Cause an exception and test beginTransaction rollback\n";
|
||||
|
||||
$dbh->beginTransaction();
|
||||
try {
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('not committed #1')");
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('data that is too long to fit and will barf')");
|
||||
$dbh->commit();
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
echo "Caught expected exception at line " . __LINE__ . "\n";
|
||||
echo $e->getMessage() . "\n";
|
||||
$dbh->rollback();
|
||||
}
|
||||
|
||||
echo "Test 3 Setting ATTR_AUTOCOMMIT to true will commit and end the transaction\n";
|
||||
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('data 3')");
|
||||
$dbh->setAttribute(PDO::ATTR_AUTOCOMMIT, true);
|
||||
print "PDO::ATTR_AUTOCOMMIT: ";
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
try {
|
||||
$dbh->rollback();
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
echo "Caught expected exception at line " . __LINE__ . "\n";
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "Test 4 Setting ATTR_AUTOCOMMIT to false will commit and end the transaction\n";
|
||||
|
||||
$dbh->beginTransaction();
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('data 4')");
|
||||
$dbh->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
|
||||
print "PDO::ATTR_AUTOCOMMIT: ";
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
try {
|
||||
$dbh->rollback();
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
echo "Caught expected exception at line " . __LINE__ . "\n";
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "Test 5 Handle transactions ourselves\n";
|
||||
|
||||
print "PDO::ATTR_AUTOCOMMIT: ";
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('not committed #2')");
|
||||
$dbh->exec("rollback");
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('data 5')");
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_2 (col1) values ('data 6')");
|
||||
|
||||
$dbh->exec("commit");
|
||||
|
||||
// Open new connection to really verify what was inserted
|
||||
|
||||
$dbh2 = PDOTest::factory();
|
||||
|
||||
echo "Query Results are:\n";
|
||||
$s = $dbh2->prepare("select col1 from test_pdo_oci_attr_autocommit_2");
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test_pdo_oci_attr_autocommit_2");
|
||||
?>
|
||||
--EXPECTF--
|
||||
Test 1 Check beginTransaction insertion
|
||||
Test 2 Cause an exception and test beginTransaction rollback
|
||||
Caught expected exception at line 33
|
||||
SQLSTATE[HY000]: General error: 12899 OCIStmtExecute: ORA-12899: %s
|
||||
%s
|
||||
Test 3 Setting ATTR_AUTOCOMMIT to true will commit and end the transaction
|
||||
PDO::ATTR_AUTOCOMMIT: bool(true)
|
||||
Caught expected exception at line %d
|
||||
There is no active transaction
|
||||
Test 4 Setting ATTR_AUTOCOMMIT to false will commit and end the transaction
|
||||
PDO::ATTR_AUTOCOMMIT: bool(false)
|
||||
Caught expected exception at line %d
|
||||
There is no active transaction
|
||||
Test 5 Handle transactions ourselves
|
||||
PDO::ATTR_AUTOCOMMIT: bool(false)
|
||||
Query Results are:
|
||||
data 1
|
||||
data 2
|
||||
data 3
|
||||
data 4
|
||||
data 5
|
||||
data 6
|
||||
Done
|
||||
54
tests/pdo_oci_attr_autocommit_3.phpt
Normal file
54
tests/pdo_oci_attr_autocommit_3.phpt
Normal file
@@ -0,0 +1,54 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: closing a connection in non-autocommit mode commits data
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
// Check connection can be created with AUTOCOMMIT off
|
||||
putenv('PDOTEST_ATTR='.serialize(array(PDO::ATTR_AUTOCOMMIT=>false)));
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
print "PDO::ATTR_AUTOCOMMIT: ";
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_AUTOCOMMIT));
|
||||
|
||||
echo "Insert data\n";
|
||||
|
||||
$dbh->exec("create table test_pdo_oci_attr_autocommit_3 (col1 varchar2(20))");
|
||||
|
||||
$dbh->exec("insert into test_pdo_oci_attr_autocommit_3 (col1) values ('some data')");
|
||||
|
||||
$dbh = null; // close first connection
|
||||
|
||||
echo "Second connection should be able to see committed data\n";
|
||||
$dbh2 = PDOTest::factory();
|
||||
$s = $dbh2->prepare("select col1 from test_pdo_oci_attr_autocommit_3");
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo "Data is: " . $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test_pdo_oci_attr_autocommit_3");
|
||||
?>
|
||||
--EXPECT--
|
||||
PDO::ATTR_AUTOCOMMIT: bool(false)
|
||||
Insert data
|
||||
Second connection should be able to see committed data
|
||||
Done
|
||||
68
tests/pdo_oci_attr_call_timeout.phpt
Normal file
68
tests/pdo_oci_attr_call_timeout.phpt
Normal file
@@ -0,0 +1,68 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Setting and using call timeout
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request');
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
if (strcasecmp(getenv('PDOTEST_USER'), "system") && strcasecmp(getenv('PDOTEST_USER'), "sys")) {
|
||||
die("skip needs to be run as a user with access to DBMS_LOCK");
|
||||
}
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
preg_match('/^[[:digit:]]+/', $dbh->getAttribute(PDO::ATTR_CLIENT_VERSION), $matches);
|
||||
if (!(isset($matches[0]) && $matches[0] >= 18)) {
|
||||
die("skip works only with Oracle 18c or greater version of Oracle client libraries");
|
||||
}
|
||||
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
function mysleep($dbh, $t)
|
||||
{
|
||||
$stmt = $dbh->prepare("begin dbms_lock.sleep(:t); end;");
|
||||
|
||||
if (!$stmt) {
|
||||
$error = $dbh->errorInfo();
|
||||
echo "Prepare error was ", $error[2], "\n";
|
||||
return;
|
||||
}
|
||||
$stmt->bindParam(":t", $t, PDO::PARAM_INT);
|
||||
|
||||
$r = $stmt->execute();
|
||||
if ($r) {
|
||||
echo "Execute succeeded\n";
|
||||
} else {
|
||||
$error = $dbh->errorInfo();
|
||||
echo "Execute error was ", $error[2], "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
|
||||
|
||||
echo "Test 1\n";
|
||||
|
||||
$dbh->setAttribute(PDO::OCI_ATTR_CALL_TIMEOUT, 4000); // milliseconds
|
||||
|
||||
echo "call timeout:\n";
|
||||
var_dump($dbh->getAttribute(PDO::OCI_ATTR_CALL_TIMEOUT));
|
||||
|
||||
$r = mysleep($dbh, 8); // seconds
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECTF--
|
||||
Test 1
|
||||
call timeout:
|
||||
int(4000)
|
||||
Execute error was OCIStmtExecute: ORA-%r(03136|03156)%r: %s
|
||||
(%s:%d)
|
||||
===DONE===
|
||||
83
tests/pdo_oci_attr_case.phpt
Normal file
83
tests/pdo_oci_attr_case.phpt
Normal file
@@ -0,0 +1,83 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Column Case
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
function do_query1($dbh)
|
||||
{
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_CASE));
|
||||
$s = $dbh->prepare("select dummy from dual");
|
||||
$s->execute();
|
||||
while ($r = $s->fetch(PDO::FETCH_ASSOC)) {
|
||||
var_dump($r);
|
||||
}
|
||||
}
|
||||
|
||||
function do_query2($dbh, $mode)
|
||||
{
|
||||
echo "Mode desired is $mode\n";
|
||||
$s = $dbh->prepare("select dummy from dual", array(PDO::ATTR_CASE, $mode));
|
||||
$s->execute();
|
||||
while ($r = $s->fetch(PDO::FETCH_ASSOC)) {
|
||||
var_dump($r);
|
||||
}
|
||||
}
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
echo "Test 1 - Force column names to lower case\n";
|
||||
$dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
|
||||
do_query1($dbh);
|
||||
|
||||
echo "Test 2 - Leave column names as returned by the database driver\n";
|
||||
$dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
|
||||
do_query1($dbh);
|
||||
|
||||
echo "Test 3 - Force column names to upper case\n";
|
||||
$dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
|
||||
do_query1($dbh);
|
||||
|
||||
echo "Test 4 - Setting on statement has no effect. Attempt lower case but get upper\n";
|
||||
$dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); // reset
|
||||
do_query2($dbh, PDO::CASE_LOWER);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Test 1 - Force column names to lower case
|
||||
int(2)
|
||||
array(1) {
|
||||
["dummy"]=>
|
||||
string(1) "X"
|
||||
}
|
||||
Test 2 - Leave column names as returned by the database driver
|
||||
int(0)
|
||||
array(1) {
|
||||
["DUMMY"]=>
|
||||
string(1) "X"
|
||||
}
|
||||
Test 3 - Force column names to upper case
|
||||
int(1)
|
||||
array(1) {
|
||||
["DUMMY"]=>
|
||||
string(1) "X"
|
||||
}
|
||||
Test 4 - Setting on statement has no effect. Attempt lower case but get upper
|
||||
Mode desired is 2
|
||||
array(1) {
|
||||
["DUMMY"]=>
|
||||
string(1) "X"
|
||||
}
|
||||
Done
|
||||
45
tests/pdo_oci_attr_client.phpt
Normal file
45
tests/pdo_oci_attr_client.phpt
Normal file
@@ -0,0 +1,45 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Client version
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
echo "ATTR_CLIENT_VERSION: ";
|
||||
$cv = $dbh->getAttribute(PDO::ATTR_CLIENT_VERSION);
|
||||
var_dump($cv);
|
||||
|
||||
$s = explode(".", $cv);
|
||||
if (count($s) > 1 && (($s[0] == 10 && $s[1] >= 2) || $s[0] >= 11)) {
|
||||
if (count($s) != 5) {
|
||||
echo "Wrong number of values in array\nVersion was: ";
|
||||
var_dump($cv);
|
||||
} else {
|
||||
echo "Version OK, so far as can be portably checked\n";
|
||||
}
|
||||
} else {
|
||||
if (count($s) != 2) {
|
||||
echo "Wrong number of values in array\nVersion was: ";
|
||||
var_dump($cv);
|
||||
} else {
|
||||
echo "Version OK, so far as can be portably checked\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
ATTR_CLIENT_VERSION: string(%d) "%d.%s"
|
||||
Version OK, so far as can be portably checked
|
||||
Done
|
||||
57
tests/pdo_oci_attr_client_identifier.phpt
Normal file
57
tests/pdo_oci_attr_client_identifier.phpt
Normal file
@@ -0,0 +1,57 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Setting session client identifier
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$query = 'select client_identifier from v$session where sid = sys_context(\'USERENV\', \'SID\')';
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'CLIENT_IDENTIFIER NOT SET: ';
|
||||
var_dump($row['client_identifier']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_CLIENT_IDENTIFIER, "some client identifier"));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'CLIENT_IDENTIFIER SET: ';
|
||||
var_dump($row['client_identifier']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_CLIENT_IDENTIFIER, "something else!"));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'CLIENT_IDENTIFIER RESET: ';
|
||||
var_dump($row['client_identifier']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_CLIENT_IDENTIFIER, null));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'CLIENT_IDENTIFIER NULLED: ';
|
||||
var_dump($row['client_identifier']);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
CLIENT_IDENTIFIER NOT SET: NULL
|
||||
bool(true)
|
||||
CLIENT_IDENTIFIER SET: string(22) "some client identifier"
|
||||
bool(true)
|
||||
CLIENT_IDENTIFIER RESET: string(15) "something else!"
|
||||
bool(true)
|
||||
CLIENT_IDENTIFIER NULLED: NULL
|
||||
Done
|
||||
57
tests/pdo_oci_attr_client_info.phpt
Normal file
57
tests/pdo_oci_attr_client_info.phpt
Normal file
@@ -0,0 +1,57 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Setting session client info
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$query = 'select client_info from v$session where sid = sys_context(\'USERENV\', \'SID\')';
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'CLIENT_INFO NOT SET: ';
|
||||
var_dump($row['client_info']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_CLIENT_INFO, "some client info"));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'CLIENT_INFO SET: ';
|
||||
var_dump($row['client_info']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_CLIENT_INFO, "something else!"));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'CLIENT_INFO RESET: ';
|
||||
var_dump($row['client_info']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_CLIENT_INFO, null));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'CLIENT_INFO NULLED: ';
|
||||
var_dump($row['client_info']);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
CLIENT_INFO NOT SET: NULL
|
||||
bool(true)
|
||||
CLIENT_INFO SET: string(16) "some client info"
|
||||
bool(true)
|
||||
CLIENT_INFO RESET: string(15) "something else!"
|
||||
bool(true)
|
||||
CLIENT_INFO NULLED: NULL
|
||||
Done
|
||||
23
tests/pdo_oci_attr_drivername.phpt
Normal file
23
tests/pdo_oci_attr_drivername.phpt
Normal file
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: verify driver name
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../../pdo/tests/pdo_test.inc';
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_DRIVER_NAME));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "oci"
|
||||
Done
|
||||
51
tests/pdo_oci_attr_module.phpt
Normal file
51
tests/pdo_oci_attr_module.phpt
Normal file
@@ -0,0 +1,51 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Setting session module
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$query = 'select module from v$session where sid = sys_context(\'USERENV\', \'SID\')';
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_MODULE, "some module"));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'MODULE SET: ';
|
||||
var_dump($row['module']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_MODULE, "something else!"));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'MODULE RESET: ';
|
||||
var_dump($row['module']);
|
||||
|
||||
var_dump($dbh->setAttribute(PDO::OCI_ATTR_MODULE, null));
|
||||
|
||||
$stmt = $dbh->query($query);
|
||||
$row = $stmt->fetch();
|
||||
echo 'MODULE NULLED: ';
|
||||
var_dump($row['module']);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
MODULE SET: string(11) "some module"
|
||||
bool(true)
|
||||
MODULE RESET: string(15) "something else!"
|
||||
bool(true)
|
||||
MODULE NULLED: NULL
|
||||
Done
|
||||
63
tests/pdo_oci_attr_nulls_1.phpt
Normal file
63
tests/pdo_oci_attr_nulls_1.phpt
Normal file
@@ -0,0 +1,63 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Oracle Nulls
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
function do_query($dbh)
|
||||
{
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_ORACLE_NULLS));
|
||||
$s = $dbh->prepare("select '' as myempty, null as mynull from dual");
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
var_dump($r[0]);
|
||||
var_dump($r[1]);
|
||||
}
|
||||
}
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
print "PDO::ATTR_ORACLE_NULLS: Default: ";
|
||||
do_query($dbh);
|
||||
|
||||
print "PDO::ATTR_ORACLE_NULLS: PDO::NULL_NATURAL: ";
|
||||
$dbh->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL); // No conversion.
|
||||
|
||||
do_query($dbh);
|
||||
|
||||
print "PDO::ATTR_ORACLE_NULLS: PDO::NULL_EMPTY_STRING: ";
|
||||
$dbh->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING); // Empty string is converted to NULL.
|
||||
|
||||
do_query($dbh);
|
||||
|
||||
print "PDO::ATTR_ORACLE_NULLS: PDO::NULL_TO_STRING: ";
|
||||
$dbh->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_TO_STRING); // NULL is converted to an empty string.
|
||||
|
||||
do_query($dbh);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
PDO::ATTR_ORACLE_NULLS: Default: int(0)
|
||||
NULL
|
||||
NULL
|
||||
PDO::ATTR_ORACLE_NULLS: PDO::NULL_NATURAL: int(0)
|
||||
NULL
|
||||
NULL
|
||||
PDO::ATTR_ORACLE_NULLS: PDO::NULL_EMPTY_STRING: int(1)
|
||||
NULL
|
||||
NULL
|
||||
PDO::ATTR_ORACLE_NULLS: PDO::NULL_TO_STRING: int(2)
|
||||
string(0) ""
|
||||
string(0) ""
|
||||
Done
|
||||
80
tests/pdo_oci_attr_prefetch_1.phpt
Normal file
80
tests/pdo_oci_attr_prefetch_1.phpt
Normal file
@@ -0,0 +1,80 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Set prefetch on connection
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
echo "Test connect\n";
|
||||
putenv('PDOTEST_ATTR='.serialize(array(PDO::ATTR_PREFETCH=>101)));
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
echo $dbh->getAttribute(PDO::ATTR_PREFETCH), "\n";
|
||||
|
||||
// Verify can fetch
|
||||
$s = $dbh->prepare("select dummy from dual" );
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Test set 102\n";
|
||||
$dbh->setAttribute(PDO::ATTR_PREFETCH, 102);
|
||||
echo $dbh->getAttribute(PDO::ATTR_PREFETCH), "\n";
|
||||
|
||||
// Verify can fetch
|
||||
$s = $dbh->prepare("select dummy from dual" );
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Test set -1: (Uses 0)\n";
|
||||
$dbh->setAttribute(PDO::ATTR_PREFETCH, -1);
|
||||
echo $dbh->getAttribute(PDO::ATTR_PREFETCH), "\n";
|
||||
|
||||
// Verify can fetch
|
||||
$s = $dbh->prepare("select dummy from dual" );
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Test set PHP_INT_MAX: (Uses default)\n";
|
||||
$dbh->setAttribute(PDO::ATTR_PREFETCH, PHP_INT_MAX);
|
||||
echo $dbh->getAttribute(PDO::ATTR_PREFETCH), "\n";
|
||||
|
||||
// Verify can fetch
|
||||
$s = $dbh->prepare("select dummy from dual" );
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Test connect
|
||||
101
|
||||
X
|
||||
Test set 102
|
||||
102
|
||||
X
|
||||
Test set -1: (Uses 0)
|
||||
0
|
||||
X
|
||||
Test set PHP_INT_MAX: (Uses default)
|
||||
100
|
||||
X
|
||||
Done
|
||||
49
tests/pdo_oci_attr_prefetch_2.phpt
Normal file
49
tests/pdo_oci_attr_prefetch_2.phpt
Normal file
@@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: prefetch on statements
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$s = $dbh->prepare("select '' as myempty, null as mynull from dual", array(PDO::ATTR_PREFETCH => 101));
|
||||
|
||||
echo "Test 1: Can't set prefetch after prepare\n";
|
||||
var_dump($s->setAttribute(PDO::ATTR_PREFETCH, 102));
|
||||
|
||||
// Verify can fetch
|
||||
$s = $dbh->prepare("select dummy from dual" );
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Test 2: Turn off prefetching\n";
|
||||
$s = $dbh->prepare("select '' as myempty, null as mynull from dual", array(PDO::ATTR_PREFETCH => 0));
|
||||
$s = $dbh->prepare("select dummy from dual" );
|
||||
$s->execute();
|
||||
while ($r = $s->fetch()) {
|
||||
echo $r[0] . "\n";
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Test 1: Can't set prefetch after prepare
|
||||
|
||||
Warning: PDOStatement::setAttribute(): SQLSTATE[IM001]: Driver does not support this function: This driver doesn't support setting attributes in %s on line %d
|
||||
bool(false)
|
||||
X
|
||||
Test 2: Turn off prefetching
|
||||
X
|
||||
Done
|
||||
42
tests/pdo_oci_attr_server.phpt
Normal file
42
tests/pdo_oci_attr_server.phpt
Normal file
@@ -0,0 +1,42 @@
|
||||
--TEST--
|
||||
PDO_OCI: Attribute: Server version and info
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
echo "Test 1\n";
|
||||
echo "ATTR_SERVER_VERSION: ";
|
||||
var_dump($dbh->getAttribute(PDO::ATTR_SERVER_VERSION));
|
||||
|
||||
echo "Test 2\n";
|
||||
echo "ATTR_SERVER_INFO\n";
|
||||
$si = $dbh->getAttribute(PDO::ATTR_SERVER_INFO);
|
||||
$pos = strpos($si, "Oracle");
|
||||
if ($pos === 0) {
|
||||
echo "Found 'Oracle' at position $pos as expected\n";
|
||||
} else {
|
||||
echo "Unexpected result. Server info was:\n";
|
||||
var_dump($si);
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Test 1
|
||||
ATTR_SERVER_VERSION: string(%d) "%d.%d.%d.%d.%d"
|
||||
Test 2
|
||||
ATTR_SERVER_INFO
|
||||
Found 'Oracle' at position 0 as expected
|
||||
Done
|
||||
68
tests/pdo_oci_class_constants.phpt
Normal file
68
tests/pdo_oci_class_constants.phpt
Normal file
@@ -0,0 +1,68 @@
|
||||
--TEST--
|
||||
PDO OCI specific class constants
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$expected = [
|
||||
'OCI_ATTR_CLIENT_INFO' => true,
|
||||
'OCI_ATTR_ACTION' => true,
|
||||
'OCI_ATTR_CLIENT_IDENTIFIER' => true,
|
||||
'OCI_ATTR_MODULE' => true,
|
||||
'OCI_ATTR_CALL_TIMEOUT' => true,
|
||||
];
|
||||
|
||||
$ref = new ReflectionClass('PDO');
|
||||
$constants = $ref->getConstants();
|
||||
$values = [];
|
||||
|
||||
foreach ($constants as $name => $value) {
|
||||
if (substr($name, 0, 8) == 'OCI_ATTR') {
|
||||
if (!isset($values[$value])) {
|
||||
$values[$value] = [$name];
|
||||
} else {
|
||||
$values[$value][] = $name;
|
||||
}
|
||||
|
||||
if (isset($expected[$name])) {
|
||||
unset($expected[$name]);
|
||||
unset($constants[$name]);
|
||||
}
|
||||
|
||||
} else {
|
||||
unset($constants[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($constants)) {
|
||||
printf("[001] Dumping list of unexpected constants\n");
|
||||
var_dump($constants);
|
||||
}
|
||||
|
||||
if (!empty($expected)) {
|
||||
printf("[002] Dumping list of missing constants\n");
|
||||
var_dump($expected);
|
||||
}
|
||||
|
||||
if (!empty($values)) {
|
||||
foreach ($values as $value => $constants) {
|
||||
if (count($constants) > 1) {
|
||||
printf("[003] Several constants share the same value '%s'\n", $value);
|
||||
var_dump($constants);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print "done!";
|
||||
?>
|
||||
--EXPECT--
|
||||
done!
|
||||
39
tests/pdo_oci_debugdumpparams.phpt
Normal file
39
tests/pdo_oci_debugdumpparams.phpt
Normal file
@@ -0,0 +1,39 @@
|
||||
--TEST--
|
||||
PDO_OCI: Bug #69356 (PDOStatement::debugDumpParams() truncates query)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$db = PDOTest::factory();
|
||||
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
|
||||
$stmt = $db->query("
|
||||
SELECT '
|
||||
Dumps the information contained by a prepared statement directly on the output. It will provide the SQL query in use, the number of parameters used (Params), the list of parameters, with their name, type (paramtype) as an integer, their key name or position, and the position in the query (if this is supported by the PDO driver, otherwise, it will be -1).
|
||||
This is a debug function, which dump directly the data on the normal output.
|
||||
Tip:
|
||||
As with anything that outputs its result directly to the browser, the output-control functions can be used to capture the output of this function, and save it in a string (for example).
|
||||
This will only dumps the parameters in the statement at the moment of the dump. Extra parameters are not stored in the statement, and not displayed.
|
||||
' FROM DUAL
|
||||
");
|
||||
var_dump($stmt->debugDumpParams());
|
||||
?>
|
||||
--EXPECT--
|
||||
SQL: [844]
|
||||
SELECT '
|
||||
Dumps the information contained by a prepared statement directly on the output. It will provide the SQL query in use, the number of parameters used (Params), the list of parameters, with their name, type (paramtype) as an integer, their key name or position, and the position in the query (if this is supported by the PDO driver, otherwise, it will be -1).
|
||||
This is a debug function, which dump directly the data on the normal output.
|
||||
Tip:
|
||||
As with anything that outputs its result directly to the browser, the output-control functions can be used to capture the output of this function, and save it in a string (for example).
|
||||
This will only dumps the parameters in the statement at the moment of the dump. Extra parameters are not stored in the statement, and not displayed.
|
||||
' FROM DUAL
|
||||
|
||||
Params: 0
|
||||
NULL
|
||||
56
tests/pdo_oci_fread_1.phpt
Normal file
56
tests/pdo_oci_fread_1.phpt
Normal file
@@ -0,0 +1,56 @@
|
||||
--TEST--
|
||||
PDO_OCI: check fread() EOF
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
if (!strpos(strtolower(getenv('PDOTEST_DSN')), 'charset=we8mswin1252')) die('skip expected output valid for WE8MSWIN1252 character set');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$dbh->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
|
||||
|
||||
// Initialization
|
||||
$stmtarray = array(
|
||||
"create table test_oci_fread_1 (id number, data clob)",
|
||||
"declare
|
||||
lob1 clob := 'abc' || lpad('j',4020,'j') || 'xyz';
|
||||
begin
|
||||
insert into test_oci_fread_1 (id,data) values (1, lob1);
|
||||
end;"
|
||||
);
|
||||
|
||||
foreach ($stmtarray as $stmt) {
|
||||
$dbh->exec($stmt);
|
||||
}
|
||||
|
||||
echo "Test 1\n";
|
||||
|
||||
$s = $dbh->query("select data from test_oci_fread_1 where id = 1");
|
||||
$r = $s->fetch();
|
||||
$sh = $r['data'];
|
||||
|
||||
while (!feof($sh)) {
|
||||
$buffer = fread($sh,1024);
|
||||
echo '*'.$buffer.'*';
|
||||
}
|
||||
echo "\n";
|
||||
fclose($sh);
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, test_oci_fread_1");
|
||||
?>
|
||||
--EXPECT--
|
||||
Test 1
|
||||
*abcjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj**jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj**jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj**jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjxyz*
|
||||
29
tests/pdo_oci_phpinfo.phpt
Normal file
29
tests/pdo_oci_phpinfo.phpt
Normal file
@@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
PDO_OCI: phpinfo() output
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
$db = PDOTest::factory();
|
||||
|
||||
ob_start();
|
||||
phpinfo();
|
||||
$tmp = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$reg = 'PDO Driver for OCI 8 and later => enabled';
|
||||
if (!preg_match("/$reg/", $tmp)) {
|
||||
printf("[001] Cannot find OCI PDO driver line in phpinfo() output\n");
|
||||
}
|
||||
|
||||
print "done!";
|
||||
?>
|
||||
--EXPECT--
|
||||
done!
|
||||
158
tests/pdo_oci_quote1.phpt
Normal file
158
tests/pdo_oci_quote1.phpt
Normal file
@@ -0,0 +1,158 @@
|
||||
--TEST--
|
||||
Test PDO->quote() for PDO_OCI
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../../pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::factory();
|
||||
|
||||
$db->query("create table test_pdo_oci_quote1 (t varchar2(100))");
|
||||
$stmt = $db->prepare('select * from test_pdo_oci_quote1');
|
||||
|
||||
// The intent is that the fetched data be identical to the unquoted string.
|
||||
// Remember!: use bind variables instead of PDO->quote()
|
||||
|
||||
$a = array("", "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 test_pdo_oci_quote1");
|
||||
|
||||
$db->query("insert into test_pdo_oci_quote1 (t) values($q)");
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test_pdo_oci_quote1");
|
||||
?>
|
||||
--EXPECT--
|
||||
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
|
||||
320
tests/pdo_oci_stmt_getcolumnmeta.phpt
Normal file
320
tests/pdo_oci_stmt_getcolumnmeta.phpt
Normal file
@@ -0,0 +1,320 @@
|
||||
--TEST--
|
||||
PDO_OCI: PDOStatement->getColumnMeta
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "Preparations before the test\n";
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
try {
|
||||
$db = PDOTest::factory();
|
||||
|
||||
$db->exec("CREATE TABLE test_pdo_oci_stmt_getcolumnmeta(id INT)");
|
||||
|
||||
$db->beginTransaction();
|
||||
|
||||
$stmt = $db->prepare('SELECT id FROM test_pdo_oci_stmt_getcolumnmeta ORDER BY id ASC');
|
||||
|
||||
echo "Test 1. calling function with invalid parameters\n";
|
||||
|
||||
// execute() has not been called yet
|
||||
// NOTE: no warning
|
||||
$tmp = $stmt->getColumnMeta(0);
|
||||
printf(" 1.1 Expecting false got %s\n", var_export($tmp, true));
|
||||
|
||||
echo(" 1.2 ");
|
||||
$stmt->execute();
|
||||
// PDOStatement::getColumnMeta() expects exactly 1 argument, 0 given in
|
||||
try {
|
||||
$tmp = $stmt->getColumnMeta();
|
||||
} catch (ArgumentCountError $e) {
|
||||
if (false !== $tmp) {
|
||||
printf("[1.2] Expecting false got %s\n", var_export($tmp, true));
|
||||
}
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
// invalid offset
|
||||
echo " 1.3 ";
|
||||
try {
|
||||
$tmp = $stmt->getColumnMeta(-1);
|
||||
} catch (ValueError $e) {
|
||||
if (false !== $tmp) {
|
||||
printf("[1.3] Expecting false got %s\n", var_export($tmp, true));
|
||||
}
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
// PDOStatement::getColumnMeta(): Argument #1 must be of type int, array given in
|
||||
echo " 1.4 ";
|
||||
try {
|
||||
$tmp = $stmt->getColumnMeta(array());
|
||||
} catch (TypeError $e) {
|
||||
if (false !== $tmp)
|
||||
printf("[1.4] Expecting false got %s\n", var_export($tmp, true));
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
// PDOStatement::getColumnMeta() expects exactly 1 argument, 2 given in
|
||||
echo " 1.5 ";
|
||||
try {
|
||||
$tmp = $stmt->getColumnMeta(1, 1);
|
||||
} catch (ArgumentCountError $e) {
|
||||
if (false !== $tmp)
|
||||
printf("[1.5] Expecting false got %s\n", var_export($tmp, true));
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
// invalid offset
|
||||
$tmp = $stmt->getColumnMeta(1);
|
||||
printf(" 1.6 Expecting false because of invalid offset got %s\n", var_export($tmp, true));
|
||||
|
||||
echo "Test 2. testing return values\n";
|
||||
echo "Test 2.1 testing array returned\n";
|
||||
|
||||
$stmt = $db->prepare('SELECT id FROM test_pdo_oci_stmt_getcolumnmeta ORDER BY id ASC');
|
||||
$stmt->execute();
|
||||
$native = $stmt->getColumnMeta(0);
|
||||
if (count($native) == 0) {
|
||||
printf("[008] Meta data seems wrong, %s / %s\n",
|
||||
var_export($native, true), var_export($emulated, true));
|
||||
}
|
||||
|
||||
|
||||
function test_return($meta, $offset, $native_type, $pdo_type){
|
||||
if (empty($meta)) {
|
||||
printf("[%03d + 2] getColumnMeta() failed, %d - %s\n", $offset,
|
||||
$stmt->errorCode(), var_export($stmt->errorInfo(), true));
|
||||
return false;
|
||||
}
|
||||
$elements = array('flags', 'scale', 'name', 'len', 'precision', 'pdo_type');
|
||||
foreach ($elements as $k => $element)
|
||||
if (!isset($meta[$element])) {
|
||||
printf("[%03d + 3] Element %s missing, %s\n", $offset,
|
||||
$element, var_export($meta, true));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_null($native_type)) {
|
||||
if (!isset($meta['native_type'])) {
|
||||
printf("[%03d + 4] Element native_type missing, %s\n", $offset,
|
||||
var_export($meta, true));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_array($native_type))
|
||||
$native_type = array($native_type);
|
||||
|
||||
$found = false;
|
||||
foreach ($native_type as $k => $type) {
|
||||
if ($meta['native_type'] == $type) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
printf("[%03d + 5] Expecting native type %s, %s\n", $offset,
|
||||
var_export($native_type, true), var_export($meta, true));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_null($pdo_type) && ($meta['pdo_type'] != $pdo_type)) {
|
||||
printf("[%03d + 6] Expecting PDO type %s got %s (%s)\n", $offset,
|
||||
$pdo_type, var_export($meta, true), var_export($meta['native_type']));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function test_meta(&$db, $offset, $sql_type, $value, $native_type, $pdo_type) {
|
||||
|
||||
$db->exec(<<<SQL
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'DROP TABLE test_pdo_oci_stmt_getcolumnmeta';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE != -942 THEN
|
||||
RAISE;
|
||||
END IF;
|
||||
END;
|
||||
SQL
|
||||
);
|
||||
|
||||
$sql = sprintf('CREATE TABLE test_pdo_oci_stmt_getcolumnmeta(id INT, label %s)', $sql_type);
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute();
|
||||
|
||||
if (!$db->exec(sprintf("INSERT INTO test_pdo_oci_stmt_getcolumnmeta(id, label) VALUES (1, '%s')", $value))) {
|
||||
printf("[%03d] + 1] Insert failed, %d - %s\n", $offset,
|
||||
$db->errorCode(), var_export($db->errorInfo(), true));
|
||||
return false;
|
||||
}
|
||||
|
||||
$stmt = $db->prepare('SELECT id, label FROM test_pdo_oci_stmt_getcolumnmeta');
|
||||
$stmt->execute();
|
||||
$meta = $stmt->getColumnMeta(1);
|
||||
return test_return($meta, $offset, $native_type, $pdo_type);
|
||||
}
|
||||
|
||||
echo "Test 2.2 testing numeric columns\n";
|
||||
|
||||
test_meta($db, 20, 'NUMBER' , 0 , 'NUMBER', PDO::PARAM_STR);
|
||||
test_meta($db, 30, 'NUMBER' , 256 , 'NUMBER', PDO::PARAM_STR);
|
||||
test_meta($db, 40, 'INT' , 256 , 'NUMBER', PDO::PARAM_STR);
|
||||
test_meta($db, 50, 'INTEGER' , 256 , 'NUMBER', PDO::PARAM_STR);
|
||||
test_meta($db, 60, 'NUMBER' , 256.01 , 'NUMBER', PDO::PARAM_STR);
|
||||
test_meta($db, 70, 'NUMBER' , -8388608 , 'NUMBER', PDO::PARAM_STR);
|
||||
|
||||
test_meta($db, 80, 'NUMBER' , 2147483648 , 'NUMBER', PDO::PARAM_STR);
|
||||
test_meta($db, 90, 'NUMBER' , 4294967295 , 'NUMBER', PDO::PARAM_STR);
|
||||
|
||||
test_meta($db, 100, 'DEC' , 1.01 , 'NUMBER' , PDO::PARAM_STR);
|
||||
test_meta($db, 110, 'DECIMAL' , 1.01 , 'NUMBER' , PDO::PARAM_STR);
|
||||
test_meta($db, 120, 'FLOAT' , 1.01 , 'FLOAT' , PDO::PARAM_STR);
|
||||
test_meta($db, 130, 'DOUBLE PRECISION', 1.01 , 'FLOAT' , PDO::PARAM_STR);
|
||||
test_meta($db, 140, 'BINARY_FLOAT' , 1.01 , 'BINARY_FLOAT' , PDO::PARAM_STR);
|
||||
test_meta($db, 150, 'BINARY_DOUBLE' , 1.01 , 'BINARY_DOUBLE', PDO::PARAM_STR);
|
||||
|
||||
echo "Test 2.3 testing temporal columns\n";
|
||||
|
||||
$db->exec("alter session set nls_date_format='YYYY-MM-DD'");
|
||||
test_meta($db, 160, 'DATE' , '2008-04-23' , 'DATE', PDO::PARAM_STR);
|
||||
|
||||
echo "Test 2.4 testing string columns\n";
|
||||
|
||||
test_meta($db, 170, 'CHAR(1)' , 'a' , 'CHAR' , PDO::PARAM_STR);
|
||||
test_meta($db, 180, 'CHAR(10)' , '0123456789' , 'CHAR' , PDO::PARAM_STR);
|
||||
test_meta($db, 190, 'CHAR(255)' , str_repeat('z', 255) , 'CHAR' , PDO::PARAM_STR);
|
||||
test_meta($db, 200, 'VARCHAR(1)' , 'a' , 'VARCHAR2' , PDO::PARAM_STR);
|
||||
test_meta($db, 210, 'VARCHAR(10)' , '0123456789' , 'VARCHAR2' , PDO::PARAM_STR);
|
||||
test_meta($db, 220, 'VARCHAR(255)' , str_repeat('z', 255) , 'VARCHAR2' , PDO::PARAM_STR);
|
||||
test_meta($db, 230, 'VARCHAR2(1)' , 'a' , 'VARCHAR2' , PDO::PARAM_STR);
|
||||
test_meta($db, 240, 'VARCHAR2(10)' , '0123456789' , 'VARCHAR2' , PDO::PARAM_STR);
|
||||
test_meta($db, 250, 'VARCHAR2(255)' , str_repeat('z', 255) , 'VARCHAR2' , PDO::PARAM_STR);
|
||||
|
||||
test_meta($db, 260, 'NCHAR(1)' , 'a' , 'NCHAR' , PDO::PARAM_STR);
|
||||
test_meta($db, 270, 'NCHAR(10)' , '0123456789' , 'NCHAR' , PDO::PARAM_STR);
|
||||
test_meta($db, 280, 'NCHAR(255)' , str_repeat('z', 255) , 'NCHAR' , PDO::PARAM_STR);
|
||||
test_meta($db, 290, 'NVARCHAR2(1)' , 'a' , 'NVARCHAR2', PDO::PARAM_STR);
|
||||
test_meta($db, 300, 'NVARCHAR2(10)' , '0123456789' , 'NVARCHAR2', PDO::PARAM_STR);
|
||||
test_meta($db, 310, 'NVARCHAR2(255)', str_repeat('z', 255) , 'NVARCHAR2', PDO::PARAM_STR);
|
||||
|
||||
echo "Test 2.5 testing lobs columns\n";
|
||||
|
||||
test_meta($db, 320, 'CLOB' , str_repeat('b', 255) , 'CLOB' , PDO::PARAM_LOB);
|
||||
test_meta($db, 330, 'BLOB' , str_repeat('b', 256) , 'BLOB' , PDO::PARAM_LOB);
|
||||
test_meta($db, 340, 'NCLOB' , str_repeat('b', 255) , 'NCLOB' , PDO::PARAM_LOB);
|
||||
|
||||
test_meta($db, 350, 'LONG' , str_repeat('b', 256) , 'LONG' , PDO::PARAM_STR);
|
||||
test_meta($db, 360, 'LONG RAW' , str_repeat('b', 256) , 'LONG RAW', PDO::PARAM_STR);
|
||||
test_meta($db, 370, 'RAW(256)' , str_repeat('b', 256) , 'RAW' , PDO::PARAM_STR);
|
||||
|
||||
|
||||
$db->exec(<<<SQL
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'DROP TABLE test_pdo_oci_stmt_getcolumnmeta';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE != -942 THEN
|
||||
RAISE;
|
||||
END IF;
|
||||
END;
|
||||
SQL
|
||||
);
|
||||
echo "Test 2.6 testing function return\n";
|
||||
|
||||
$stmt = $db->query('SELECT count(*) FROM dual');
|
||||
$meta = $stmt->getColumnMeta(0);
|
||||
test_return($meta, 380, 'NUMBER', PDO::PARAM_STR);
|
||||
$stmt = $db->query("SELECT TO_DATE('2008-04-23') FROM dual");
|
||||
$meta = $stmt->getColumnMeta(0);
|
||||
test_return($meta, 390, 'DATE', PDO::PARAM_STR);
|
||||
$stmt = $db->query("SELECT TO_CHAR(542) FROM dual");
|
||||
$meta = $stmt->getColumnMeta(0);
|
||||
test_return($meta, 400, 'VARCHAR2', PDO::PARAM_STR);
|
||||
|
||||
|
||||
echo "Test 2.7 testing flags returned\n";
|
||||
|
||||
$sql = sprintf('CREATE TABLE test_pdo_oci_stmt_getcolumnmeta(id INT NOT NULL, label INT NULL)');
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute();
|
||||
$db->exec('INSERT INTO test_pdo_oci_stmt_getcolumnmeta(id, label) VALUES (1, 1)');
|
||||
$stmt = $db->query('SELECT id, label FROM test_pdo_oci_stmt_getcolumnmeta');
|
||||
$meta = $stmt->getColumnMeta(0);
|
||||
// verify the flags array contains a not_null flag and not nullable flags
|
||||
if (!isset($meta['flags'])) {
|
||||
printf("[1001] No flags contained in metadata %s\n", var_export($meta, true));
|
||||
} else {
|
||||
$flags = $meta['flags'];
|
||||
$found = false;
|
||||
foreach ($flags as $k => $flag) {
|
||||
if ($flag == 'not_null')
|
||||
$found = true;
|
||||
if ($flag == 'nullable')
|
||||
printf("[1003] Flags seem wrong %s\n", var_export($meta, true));
|
||||
}
|
||||
if (!$found)
|
||||
printf("[1002] Flags seem wrong %s\n", var_export($meta, true));
|
||||
}
|
||||
$meta = $stmt->getColumnMeta(1);
|
||||
// verify the flags array contains a nullable flag and not not_null flags
|
||||
if (!isset($meta['flags'])) {
|
||||
printf("[1003] No flags contained in metadata %s\n", var_export($meta, true));
|
||||
} else {
|
||||
$flags = $meta['flags'];
|
||||
$found = false;
|
||||
foreach ($flags as $k => $flag) {
|
||||
if ($flag == 'not_null')
|
||||
printf("[1004] Flags seem wrong %s\n", var_export($meta, true));
|
||||
if ($flag == 'nullable')
|
||||
$found = true;
|
||||
}
|
||||
if (!$found)
|
||||
printf("[1005] Flags seem wrong %s\n", var_export($meta, true));
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// we should never get here, we use warnings, but never trust a system...
|
||||
printf("[001] %s, [%s} %s\n",
|
||||
$e->getMessage(), $db->errorInfo(), implode(' ', $db->errorInfo()));
|
||||
}
|
||||
|
||||
print "done!";
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test_pdo_oci_stmt_getcolumnmeta");
|
||||
?>
|
||||
--EXPECT--
|
||||
Preparations before the test
|
||||
Test 1. calling function with invalid parameters
|
||||
1.1 Expecting false got false
|
||||
1.2 PDOStatement::getColumnMeta() expects exactly 1 argument, 0 given
|
||||
1.3 PDOStatement::getColumnMeta(): Argument #1 ($column) must be greater than or equal to 0
|
||||
1.4 PDOStatement::getColumnMeta(): Argument #1 ($column) must be of type int, array given
|
||||
1.5 PDOStatement::getColumnMeta() expects exactly 1 argument, 2 given
|
||||
1.6 Expecting false because of invalid offset got false
|
||||
Test 2. testing return values
|
||||
Test 2.1 testing array returned
|
||||
Test 2.2 testing numeric columns
|
||||
Test 2.3 testing temporal columns
|
||||
Test 2.4 testing string columns
|
||||
Test 2.5 testing lobs columns
|
||||
Test 2.6 testing function return
|
||||
Test 2.7 testing flags returned
|
||||
done!
|
||||
108
tests/pdo_oci_stream_1.phpt
Normal file
108
tests/pdo_oci_stream_1.phpt
Normal file
@@ -0,0 +1,108 @@
|
||||
--TEST--
|
||||
PDO_OCI: stream_get_contents length & offset test
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
if (!strpos(strtolower(getenv('PDOTEST_DSN')), 'charset=we8mswin1252')) die('skip expected output valid for WE8MSWIN1252 character set');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$dbh->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
|
||||
|
||||
// Initialization
|
||||
$stmtarray = array(
|
||||
"create table test_pdo_oci_stream_1 (id number, data clob)",
|
||||
);
|
||||
|
||||
foreach ($stmtarray as $stmt) {
|
||||
$dbh->exec($stmt);
|
||||
}
|
||||
|
||||
$dbh->exec("
|
||||
declare
|
||||
lob1 clob := 'abc' || lpad('j',30000,'j') || 'xyz';
|
||||
begin
|
||||
insert into test_pdo_oci_stream_1 (id,data) values (1, 'abcdefghijklmnopqrstuvwxyz');
|
||||
insert into test_pdo_oci_stream_1 (id,data) values (2, lob1);
|
||||
end;");
|
||||
|
||||
echo "Test 1\n";
|
||||
|
||||
$s = $dbh->prepare("select data from test_pdo_oci_stream_1 where id = 1");
|
||||
$s->execute();
|
||||
$r = $s->fetch();
|
||||
|
||||
// stream_get_contents ( resource $handle [, int $maxlength = -1 [, int $offset = -1 ]] )
|
||||
echo 'Read '.stream_get_contents($r['data'], 1, 1)."$\n"; // b
|
||||
echo 'Read '.stream_get_contents($r['data'], 2, 1)."$\n"; // cd
|
||||
echo 'Read '.stream_get_contents($r['data'], 2, 0)."$\n"; // ab
|
||||
echo 'Read '.stream_get_contents($r['data'], 26, 0)."$\n"; // abcdefghijklmnopqrstuvwxyz
|
||||
echo 'Read '.stream_get_contents($r['data'], 27, 0)."$\n"; // abcdefghijklmnopqrstuvwxyz
|
||||
echo 'Read '.stream_get_contents($r['data'], 27, 1)."$\n"; // bcdefghijklmnopqrstuvwxyz
|
||||
echo 'Read '.stream_get_contents($r['data'], 1, 20)."$\n"; // u
|
||||
echo 'Read '.stream_get_contents($r['data'], 1, 25)."$\n"; // z
|
||||
echo 'Read '.stream_get_contents($r['data'], 1, 26)."$\n"; // <blank>
|
||||
echo 'Read '.stream_get_contents($r['data'], 1, 0)."$\n"; // a
|
||||
|
||||
echo "\nTest 2\n";
|
||||
|
||||
$s = $dbh->prepare("select data from test_pdo_oci_stream_1 where id = 2");
|
||||
$s->execute();
|
||||
$r = $s->fetch();
|
||||
|
||||
echo 'Read '.stream_get_contents($r['data'], 5, 0)."\n"; // abcjj
|
||||
echo 'Read '.stream_get_contents($r['data'], 5, 2)."\n"; // cjjjj
|
||||
echo 'Read '.stream_get_contents($r['data'], 6, 1)."\n"; // bcjjjj
|
||||
echo 'Read '.strlen(stream_get_contents($r['data'], -1,0))."\n"; // 30006
|
||||
echo 'Read '.strlen(stream_get_contents($r['data'], 0,0))."\n"; // 0
|
||||
echo 'Read '.strlen(stream_get_contents($r['data'], 0,1))."\n"; // 0
|
||||
echo 'Read '.strlen(stream_get_contents($r['data'], 10,100))."\n"; // 10
|
||||
echo 'Read '.stream_get_contents($r['data'], 6, 30000)."\n"; // jjjxyz
|
||||
echo 'Read '.stream_get_contents($r['data'], 7, 30000)."\n"; // jjjxyz
|
||||
echo 'Read '.strlen(stream_get_contents($r['data']))."\n"; // 0
|
||||
echo 'Read '.strlen(stream_get_contents($r['data'], 0))."\n"; // 0
|
||||
echo 'Read '.strlen(stream_get_contents($r['data'], -1))."\n"; // 0
|
||||
echo 'Read '.stream_get_contents($r['data'], -1, 30000)."\n"; // jjjxyz
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, test_pdo_oci_stream_1");
|
||||
?>
|
||||
--EXPECT--
|
||||
Test 1
|
||||
Read b$
|
||||
Read cd$
|
||||
Read ab$
|
||||
Read abcdefghijklmnopqrstuvwxyz$
|
||||
Read abcdefghijklmnopqrstuvwxyz$
|
||||
Read bcdefghijklmnopqrstuvwxyz$
|
||||
Read u$
|
||||
Read z$
|
||||
Read $
|
||||
Read a$
|
||||
|
||||
Test 2
|
||||
Read abcjj
|
||||
Read cjjjj
|
||||
Read bcjjjj
|
||||
Read 30006
|
||||
Read 0
|
||||
Read 0
|
||||
Read 10
|
||||
Read jjjxyz
|
||||
Read jjjxyz
|
||||
Read 0
|
||||
Read 0
|
||||
Read 0
|
||||
Read jjjxyz
|
||||
122
tests/pdo_oci_stream_2.phpt
Normal file
122
tests/pdo_oci_stream_2.phpt
Normal file
@@ -0,0 +1,122 @@
|
||||
--TEST--
|
||||
PDO OCI: Insert and fetch 1K records from a table that contains 1 number and 2 LOB columns (stress test)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (getenv('SKIP_SLOW_TESTS')) die('skip slow tests excluded by request');
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require(__DIR__ . '/../../pdo/tests/pdo_test.inc');
|
||||
|
||||
$db = PDOTest::factory();
|
||||
|
||||
$query = "create table test_pdo_oci_stream_2 (id number, data1 blob, data2 blob)";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->execute();
|
||||
|
||||
function do_insert($db, $id, $data1, $data2)
|
||||
{
|
||||
$db->beginTransaction();
|
||||
$stmt = $db->prepare("insert into test_pdo_oci_stream_2 (id, data1, data2) values (:id, empty_blob(), empty_blob()) returning data1, data2 into :blob1, :blob2");
|
||||
$stmt->bindParam(':id', $id);
|
||||
$stmt->bindParam(':blob1', $blob1, PDO::PARAM_LOB);
|
||||
$stmt->bindParam(':blob2', $blob2, PDO::PARAM_LOB);
|
||||
$blob1 = null;
|
||||
$blob2 = null;
|
||||
$stmt->execute();
|
||||
|
||||
fwrite($blob1, $data1);
|
||||
fclose($blob1);
|
||||
fwrite($blob2, $data2);
|
||||
fclose($blob2);
|
||||
$db->commit();
|
||||
}
|
||||
|
||||
$a1 = str_repeat('a', 4086);
|
||||
$a2 = str_repeat('b', 4087);
|
||||
$a3 = str_repeat('c', 4088);
|
||||
$a4 = str_repeat('d', 4089);
|
||||
$a5 = str_repeat('e', 4090);
|
||||
$a6 = str_repeat('f', 4091);
|
||||
$a7 = str_repeat('g', 4092);
|
||||
$a8 = str_repeat('h', 4093);
|
||||
$a9 = str_repeat('i', 4094);
|
||||
$a10 = str_repeat('j', 4095);
|
||||
|
||||
printf("Inserting 1000 Records ... ");
|
||||
for($i=0; $i<100; $i++) {
|
||||
do_insert($db, $i * 10 + 1, $a1, $a10);
|
||||
do_insert($db, $i * 10 + 2, $a2, $a9);
|
||||
do_insert($db, $i * 10 + 3, $a3, $a8);
|
||||
do_insert($db, $i * 10 + 4, $a4, $a7);
|
||||
do_insert($db, $i * 10 + 5, $a5, $a6);
|
||||
do_insert($db, $i * 10 + 6, $a6, $a5);
|
||||
do_insert($db, $i * 10 + 7, $a7, $a4);
|
||||
do_insert($db, $i * 10 + 8, $a8, $a3);
|
||||
do_insert($db, $i * 10 + 9, $a9, $a2);
|
||||
do_insert($db, $i * 10 + 10, $a10, $a1);
|
||||
}
|
||||
printf("Done\n");
|
||||
|
||||
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); // Let's use streams
|
||||
|
||||
// Since each column only has one lob descriptor, the last row is
|
||||
// shown twice because the lob descriptor for each column is reused in
|
||||
// the stream
|
||||
|
||||
$i = 0;
|
||||
$j = 9;
|
||||
$a_val = ord('a');
|
||||
foreach($db->query("select data1 as d4_1, data2 as d4_2 from test_pdo_oci_stream_2 order by id") as $row) {
|
||||
$a = $row['d4_1'];
|
||||
$a1 = $row['d4_2'];
|
||||
|
||||
$str1 = stream_get_contents($a);
|
||||
$str2 = stream_get_contents($a1);
|
||||
|
||||
$str1len = strlen($str1);
|
||||
$str2len = strlen($str2);
|
||||
|
||||
$b = ord($str1[0]);
|
||||
$b1 = ord($str2[0]);
|
||||
|
||||
if (($b != ($a_val + $i)) && ($str1len != (4086 + $i)) &&
|
||||
($b1 != ($a_val + $j)) && ($str2len != (4086 + $j))) {
|
||||
printf("There is a bug!\n");
|
||||
printf("Col1:\n");
|
||||
printf("a_val = %d\n", $a_val);
|
||||
printf("b = %d\n", $b);
|
||||
printf("i = %d\n", $i);
|
||||
printf("str1len = %d\n", $str1len);
|
||||
|
||||
printf("Col2:\n");
|
||||
printf("a_val = %d\n", $a_val);
|
||||
printf("b1 = %d\n", $b1);
|
||||
printf("j = %d\n", $j);
|
||||
printf("str2len = %d\n", $str1len);
|
||||
|
||||
}
|
||||
$i++;
|
||||
if ($i>9)
|
||||
$i = 0;
|
||||
$j--;
|
||||
if ($j<0)
|
||||
$j = 9;
|
||||
}
|
||||
echo "Fetch operation done!\n";
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test_pdo_oci_stream_2");
|
||||
?>
|
||||
--EXPECT--
|
||||
Inserting 1000 Records ... Done
|
||||
Fetch operation done!
|
||||
86
tests/pdo_oci_templob_1.phpt
Normal file
86
tests/pdo_oci_templob_1.phpt
Normal file
@@ -0,0 +1,86 @@
|
||||
--TEST--
|
||||
PDO OCI: Test to verify all implicitly created temporary LOB are cleaned up
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?PHP
|
||||
|
||||
require('ext/pdo/tests/pdo_test.inc');
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
|
||||
$clobquery1 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery2 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery3 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery4 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery5 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery6 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery7 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery8 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery9 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
$clobquery10 = "select TO_CLOB('Hello World') CLOB_DATA from dual";
|
||||
|
||||
$stmt= $db->prepare($clobquery1);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery2);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery3);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery4);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery5);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery6);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery7);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery8);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery9);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
$stmt= $db->prepare($clobquery10);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
|
||||
$query1 = "SELECT SYS_CONTEXT('USERENV', 'SID') SID FROM DUAL";
|
||||
|
||||
$stmt1 = $db->prepare($query1);
|
||||
$stmt1->execute();
|
||||
|
||||
$row1 = $stmt1->fetch();
|
||||
$sid_value = $row1[0];
|
||||
|
||||
$query2 = "SELECT (CACHE_LOBS+NOCACHE_LOBS+ABSTRACT_LOBS) FROM V\$TEMPORARY_LOBS WHERE SID = :SID_VALUE";
|
||||
|
||||
$stmt2 = $db->prepare($query2);
|
||||
$stmt2->bindParam(':SID_VALUE', $sid_value);
|
||||
$stmt2->execute();
|
||||
|
||||
$row2 = $stmt2->fetch();
|
||||
/* 1 temporary LOB still exists in V$TEMPORARY_LOBS since the destructor of $stmt is not yet called by PHP */
|
||||
if ($row2[0] > 1)
|
||||
{
|
||||
echo "TEMP_LOB is not yet cleared!" . $row2[0] . "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Success! All the temporary LOB in previously closed statements are properly cleaned.\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Success! All the temporary LOB in previously closed statements are properly cleaned.
|
||||
30
tests/pecl_bug_11345.phpt
Normal file
30
tests/pecl_bug_11345.phpt
Normal file
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
PECL PDO_OCI Bug #11345 (Test invalid character set name)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require(__DIR__.'/../../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)
|
||||
73
tests/pecl_bug_6364.phpt
Normal file
73
tests/pecl_bug_6364.phpt
Normal file
@@ -0,0 +1,73 @@
|
||||
--TEST--
|
||||
PECL PDO_OCI Bug #6364 (segmentation fault on stored procedure call with OUT binds)
|
||||
--EXTENSIONS--
|
||||
pdo
|
||||
pdo_oci
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (getenv('SKIP_ASAN')) die('xleak leaks memory under asan');
|
||||
require(__DIR__.'/../../pdo/tests/pdo_test.inc');
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../../pdo/tests/pdo_test.inc';
|
||||
$dbh = PDOTest::factory();
|
||||
|
||||
$dbh->exec ("create table test6364 (c1 varchar2(10), c2 varchar2(10), c3 varchar2(10), c4 varchar2(10), c5 varchar2(10))");
|
||||
|
||||
$dbh->exec ("create procedure test6364_sp(p1 IN varchar2, p2 IN varchar2, p3 IN varchar2, p4 OUT varchar2, p5 OUT varchar2) as begin insert into test6364 (c1, c2, c3) values (p1, p2, p3); p4 := 'val4'; p5 := 'val5'; end;");
|
||||
|
||||
$stmt = $dbh->prepare("call test6364_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 test6364") as $row) {
|
||||
var_dump($row);
|
||||
}
|
||||
|
||||
print "Done\n";
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require 'ext/pdo/tests/pdo_test.inc';
|
||||
$db = PDOTest::test_factory('ext/pdo_oci/tests/common.phpt');
|
||||
PDOTest::dropTableIfExists($db, "test6364");
|
||||
$db->exec("DROP PROCEDURE test6364_sp");
|
||||
?>
|
||||
--EXPECT--
|
||||
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
|
||||
Reference in New Issue
Block a user