summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Jones <sixd@php.net>2010-08-07 00:28:09 +0000
committerChristopher Jones <sixd@php.net>2010-08-07 00:28:09 +0000
commit05be95c0bee8c215d813ea71e000fa0b76abaf86 (patch)
treee1f53f5490f30a7c83e79ad929797559deb359e2
downloadphp-git-05be95c0bee8c215d813ea71e000fa0b76abaf86.tar.gz
Tagging the 1.4.3 releaseoci8-1.4.3
-rw-r--r--CREDITS2
-rw-r--r--README12
-rw-r--r--config.m4360
-rw-r--r--config.w3282
-rw-r--r--oci8.c3246
-rw-r--r--oci8.dsp133
-rw-r--r--oci8_collection.c793
-rw-r--r--oci8_interface.c2355
-rw-r--r--oci8_lob.c953
-rw-r--r--oci8_statement.c1722
-rw-r--r--php_oci8.h74
-rw-r--r--php_oci8_int.h518
-rw-r--r--tests/array_bind_001.phpt69
-rw-r--r--tests/array_bind_002.phpt77
-rw-r--r--tests/array_bind_003.phpt73
-rw-r--r--tests/array_bind_004.phpt65
-rw-r--r--tests/array_bind_005.phpt74
-rw-r--r--tests/array_bind_006.phpt74
-rw-r--r--tests/array_bind_007.phpt77
-rw-r--r--tests/array_bind_008.phpt78
-rw-r--r--tests/array_bind_009.phpt17
-rw-r--r--tests/array_bind_010.phpt36
-rw-r--r--tests/array_bind_011.phpt67
-rw-r--r--tests/array_bind_012.phpt26
-rw-r--r--tests/array_bind_013.phpt39
-rw-r--r--tests/array_bind_014.phpt73
-rw-r--r--tests/array_bind_date.phpt74
-rw-r--r--tests/array_bind_date1.phpt74
-rw-r--r--tests/array_bind_float.phpt74
-rw-r--r--tests/array_bind_float1.phpt74
-rw-r--r--tests/array_bind_int.phpt74
-rw-r--r--tests/array_bind_int1.phpt74
-rw-r--r--tests/array_bind_str.phpt74
-rw-r--r--tests/array_bind_str1.phpt74
-rw-r--r--tests/b47243_1.phpt22
-rw-r--r--tests/b47243_2.phpt23
-rw-r--r--tests/b47243_3.phpt24
-rw-r--r--tests/bind_char_1.phpt306
-rw-r--r--tests/bind_char_1_11gR1.phpt297
-rw-r--r--tests/bind_char_2.phpt127
-rw-r--r--tests/bind_char_2_11gR1.phpt123
-rw-r--r--tests/bind_char_3.phpt345
-rw-r--r--tests/bind_char_3_11gR1.phpt344
-rw-r--r--tests/bind_char_4.phpt347
-rw-r--r--tests/bind_char_4_11gR1.phpt346
-rw-r--r--tests/bind_empty.phpt127
-rw-r--r--tests/bind_long.phpt41
-rw-r--r--tests/bind_long_raw.phpt38
-rw-r--r--tests/bind_raw.phpt39
-rw-r--r--tests/bind_rowid.phpt86
-rw-r--r--tests/bug26133.phpt62
-rw-r--r--tests/bug27303_1.phpt261
-rw-r--r--tests/bug27303_1_11gR1.phpt258
-rw-r--r--tests/bug27303_2.phpt263
-rw-r--r--tests/bug27303_2_11gR1.phpt260
-rw-r--r--tests/bug27303_3.phpt252
-rw-r--r--tests/bug27303_4.phpt261
-rw-r--r--tests/bug27303_4_11gR1.phpt258
-rw-r--r--tests/bug32325.phpt63
-rw-r--r--tests/bug35973.phpt43
-rw-r--r--tests/bug36010.phpt26
-rw-r--r--tests/bug36096.phpt28
-rw-r--r--tests/bug36403.phpt76
-rw-r--r--tests/bug37220.phpt68
-rw-r--r--tests/bug37581.phpt69
-rw-r--r--tests/bug38161.phpt30
-rw-r--r--tests/bug38173.phpt79
-rw-r--r--tests/bug40078.phpt55
-rw-r--r--tests/bug40415.phpt200
-rw-r--r--tests/bug41069.phpt275
-rw-r--r--tests/bug42134.phpt100
-rw-r--r--tests/bug42173.phpt168
-rw-r--r--tests/bug42496_1.phpt61
-rw-r--r--tests/bug42496_2.phpt59
-rw-r--r--tests/bug42841.phpt187
-rw-r--r--tests/bug43492.phpt378
-rw-r--r--tests/bug43492_2.phpt369
-rw-r--r--tests/bug43497.phpt303
-rw-r--r--tests/bug43497_92.phpt303
-rw-r--r--tests/bug44008.phpt54
-rw-r--r--tests/bug44113.phpt56
-rw-r--r--tests/bug44206.phpt43
-rw-r--r--tests/bug45458.phpt84
-rw-r--r--tests/bug46994.phpt86
-rw-r--r--tests/bug47189.phpt48
-rw-r--r--tests/bug47281.phpt73
-rw-r--r--tests/bug51253.phpt165
-rw-r--r--tests/bug51291.phpt434
-rw-r--r--tests/close.phpt17
-rw-r--r--tests/coll_001.phpt27
-rw-r--r--tests/coll_002.phpt30
-rw-r--r--tests/coll_002_func.phpt30
-rw-r--r--tests/coll_003.phpt34
-rw-r--r--tests/coll_003_func.phpt34
-rw-r--r--tests/coll_004.phpt29
-rw-r--r--tests/coll_004_func.phpt29
-rw-r--r--tests/coll_005.phpt27
-rw-r--r--tests/coll_006.phpt30
-rw-r--r--tests/coll_006_func.phpt30
-rw-r--r--tests/coll_007.phpt34
-rw-r--r--tests/coll_008.phpt29
-rw-r--r--tests/coll_009.phpt42
-rw-r--r--tests/coll_009_func.phpt42
-rw-r--r--tests/coll_010.phpt41
-rw-r--r--tests/coll_010_func.phpt41
-rw-r--r--tests/coll_011.phpt43
-rw-r--r--tests/coll_011_func.phpt43
-rw-r--r--tests/coll_012.phpt41
-rw-r--r--tests/coll_012_func.phpt41
-rw-r--r--tests/coll_013.phpt38
-rw-r--r--tests/coll_013_func.phpt38
-rw-r--r--tests/coll_014.phpt38
-rw-r--r--tests/coll_014_func.phpt38
-rw-r--r--tests/coll_015.phpt38
-rw-r--r--tests/coll_015_func.phpt38
-rw-r--r--tests/coll_016.phpt48
-rw-r--r--tests/coll_016_func.phpt48
-rw-r--r--tests/coll_017.phpt38
-rw-r--r--tests/coll_017_func.phpt38
-rw-r--r--tests/coll_018.phpt93
-rw-r--r--tests/coll_019.phpt104
-rw-r--r--tests/commit_001.phpt156
-rw-r--r--tests/commit_002.phpt90
-rw-r--r--tests/commit_old.phpt146
-rw-r--r--tests/conn_attr.inc151
-rw-r--r--tests/conn_attr_1.phpt104
-rw-r--r--tests/conn_attr_2.phpt111
-rw-r--r--tests/conn_attr_3.phpt94
-rw-r--r--tests/conn_attr_4.phpt122
-rw-r--r--tests/conn_attr_5.phpt76
-rw-r--r--tests/connect.inc18
-rw-r--r--tests/connect.phpt22
-rw-r--r--tests/connect_1.phpt35
-rw-r--r--tests/connect_1_old.phpt35
-rw-r--r--tests/connect_old.phpt22
-rw-r--r--tests/connect_scope1.phpt93
-rw-r--r--tests/connect_scope2.phpt93
-rw-r--r--tests/connect_scope_try1.phpt100
-rw-r--r--tests/connect_scope_try2.phpt100
-rw-r--r--tests/connect_scope_try3.phpt100
-rw-r--r--tests/connect_scope_try4.phpt100
-rw-r--r--tests/connect_scope_try5.phpt100
-rw-r--r--tests/connect_scope_try6.phpt100
-rw-r--r--tests/connect_with_charset_001.phpt37
-rw-r--r--tests/connect_without_oracle_home.phpt34
-rw-r--r--tests/connect_without_oracle_home_old.phpt34
-rw-r--r--tests/create_table.inc11
-rw-r--r--tests/create_type.inc17
-rw-r--r--tests/cursor_bind.phpt99
-rw-r--r--tests/cursor_bind_err.phpt70
-rw-r--r--tests/cursors.phpt65
-rw-r--r--tests/cursors_old.phpt86
-rw-r--r--tests/debug.phpt71
-rw-r--r--tests/default_prefetch.phpt73
-rw-r--r--tests/default_prefetch1.phpt72
-rw-r--r--tests/default_prefetch2.phpt74
-rw-r--r--tests/define.phpt62
-rw-r--r--tests/define1.phpt73
-rw-r--r--tests/define2.phpt94
-rw-r--r--tests/define3.phpt112
-rw-r--r--tests/define4.phpt88
-rw-r--r--tests/define5.phpt86
-rw-r--r--tests/define_old.phpt63
-rw-r--r--tests/descriptors.phpt49
-rw-r--r--tests/details.inc63
-rw-r--r--tests/drcp_cclass1.phpt80
-rw-r--r--tests/drcp_characterset.phpt61
-rw-r--r--tests/drcp_conn_close1.phpt45
-rw-r--r--tests/drcp_conn_close2.phpt46
-rw-r--r--tests/drcp_connect1.phpt86
-rw-r--r--tests/drcp_connection_class.phpt24
-rw-r--r--tests/drcp_functions.inc93
-rw-r--r--tests/drcp_newconnect.phpt43
-rw-r--r--tests/drcp_pconn_close1.phpt44
-rw-r--r--tests/drcp_pconn_close2.phpt46
-rw-r--r--tests/drcp_privileged.phpt47
-rw-r--r--tests/drcp_scope1.phpt92
-rw-r--r--tests/drcp_scope2.phpt91
-rw-r--r--tests/drcp_scope3.phpt61
-rw-r--r--tests/drcp_scope4.phpt62
-rw-r--r--tests/drcp_scope5.phpt63
-rw-r--r--tests/driver_name.phpt71
-rw-r--r--tests/drop_table.inc7
-rw-r--r--tests/drop_type.inc7
-rw-r--r--tests/edition_1.phpt156
-rw-r--r--tests/edition_2.phpt248
-rw-r--r--tests/error.phpt40
-rw-r--r--tests/error1.phpt27
-rw-r--r--tests/error2.phpt24
-rw-r--r--tests/error_bind.phpt70
-rw-r--r--tests/error_old.phpt40
-rw-r--r--tests/error_parse.phpt142
-rw-r--r--tests/exec_fetch.phpt24
-rw-r--r--tests/execute_mode.phpt19
-rw-r--r--tests/extauth_01.phpt198
-rw-r--r--tests/extauth_02.phpt198
-rw-r--r--tests/extauth_03.phpt198
-rw-r--r--tests/extauth_04.phpt56
-rw-r--r--tests/fetch.phpt76
-rw-r--r--tests/fetch_all.phpt108
-rw-r--r--tests/fetch_all2.phpt242
-rw-r--r--tests/fetch_all3.phpt612
-rw-r--r--tests/fetch_all4.phpt82
-rw-r--r--tests/fetch_all5.phpt127
-rw-r--r--tests/fetch_array.phpt308
-rw-r--r--tests/fetch_assoc.phpt82
-rw-r--r--tests/fetch_into.phpt90
-rw-r--r--tests/fetch_into1.phpt192
-rw-r--r--tests/fetch_into2.phpt70
-rw-r--r--tests/fetch_object.phpt137
-rw-r--r--tests/fetch_object_2.phpt127
-rw-r--r--tests/fetch_row.phpt84
-rw-r--r--tests/field_funcs.phpt105
-rw-r--r--tests/field_funcs1.phpt194
-rw-r--r--tests/field_funcs2.phpt69
-rw-r--r--tests/field_funcs_old.phpt105
-rw-r--r--tests/function_aliases.phpt198
-rw-r--r--tests/lob_001.phptbin0 -> 1305 bytes
-rw-r--r--tests/lob_002.phpt66
-rw-r--r--tests/lob_003.phptbin0 -> 1628 bytes
-rw-r--r--tests/lob_004.phpt80
-rw-r--r--tests/lob_005.phpt52
-rw-r--r--tests/lob_006.phptbin0 -> 1694 bytes
-rw-r--r--tests/lob_007.phpt66
-rw-r--r--tests/lob_008.phpt65
-rw-r--r--tests/lob_009.phpt69
-rw-r--r--tests/lob_009.txt6
-rw-r--r--tests/lob_010.phpt46
-rw-r--r--tests/lob_011.phpt78
-rw-r--r--tests/lob_012.phpt50
-rw-r--r--tests/lob_013.phpt54
-rw-r--r--tests/lob_014.phpt56
-rw-r--r--tests/lob_015.phpt53
-rw-r--r--tests/lob_016.phpt67
-rw-r--r--tests/lob_017.phpt69
-rw-r--r--tests/lob_018.phpt67
-rw-r--r--tests/lob_019.phptbin0 -> 1548 bytes
-rw-r--r--tests/lob_020.phptbin0 -> 3076 bytes
-rw-r--r--tests/lob_021.phpt70
-rw-r--r--tests/lob_022.phpt80
-rw-r--r--tests/lob_023.phpt84
-rw-r--r--tests/lob_024.phpt75
-rw-r--r--tests/lob_025.phpt82
-rw-r--r--tests/lob_026.phpt100
-rw-r--r--tests/lob_027.phpt103
-rw-r--r--tests/lob_028.phpt84
-rw-r--r--tests/lob_029.phpt125
-rw-r--r--tests/lob_030.phpt75
-rw-r--r--tests/lob_031.phpt107
-rw-r--r--tests/lob_032.phpt33
-rw-r--r--tests/lob_033.phpt38
-rw-r--r--tests/lob_034.phpt50
-rw-r--r--tests/lob_035.phpt108
-rw-r--r--tests/lob_036.phpt40
-rw-r--r--tests/lob_037.phpt68
-rw-r--r--tests/lob_038.phpt189
-rw-r--r--tests/lob_039.phpt65
-rw-r--r--tests/lob_040.phpt1041
-rw-r--r--tests/lob_041.phpt92
-rw-r--r--tests/lob_042.phpt69
-rw-r--r--tests/lob_043.phpt104
-rw-r--r--tests/lob_aliases.phpt99
-rw-r--r--tests/lob_null.phpt265
-rw-r--r--tests/lob_temp.phpt36
-rw-r--r--tests/lob_temp1.phpt32
-rw-r--r--tests/minfo.phpt19
-rw-r--r--tests/num.phpt256
-rw-r--r--tests/oci8safemode.phpt23
-rw-r--r--tests/oci_execute_segfault.phpt48
-rw-r--r--tests/old_oci_close.phpt23
-rw-r--r--tests/old_oci_close1.phpt25
-rw-r--r--tests/password.phpt83
-rw-r--r--tests/password_2.phpt83
-rw-r--r--tests/password_new.phpt49
-rw-r--r--tests/password_old.phpt49
-rw-r--r--tests/pecl_bug10194.phpt47
-rw-r--r--tests/pecl_bug10194_blob.phpt54
-rw-r--r--tests/pecl_bug10194_blob_64.phpt54
-rw-r--r--tests/pecl_bug16035.phpt26
-rw-r--r--tests/pecl_bug16842.phpt69
-rw-r--r--tests/pecl_bug6109.phpt40
-rw-r--r--tests/pecl_bug8816.phpt98
-rw-r--r--tests/persistent.phpt26
-rw-r--r--tests/prefetch.phpt72
-rw-r--r--tests/prefetch_old.phpt75
-rw-r--r--tests/privileged_connect.phpt25
-rw-r--r--tests/privileged_connect1.phpt27
-rw-r--r--tests/refcur_prefetch_1.phpt256
-rw-r--r--tests/refcur_prefetch_2.phpt317
-rw-r--r--tests/refcur_prefetch_3.phpt161
-rw-r--r--tests/reflection1.phpt1096
-rw-r--r--tests/reflection2.phpt258
-rw-r--r--tests/select_null.phpt25
-rw-r--r--tests/serverversion.phpt30
-rw-r--r--tests/skipif.inc10
-rw-r--r--tests/statement_cache.phpt35
-rw-r--r--tests/statement_type.phpt48
-rw-r--r--tests/statement_type_old.phpt56
-rw-r--r--tests/test.gifbin0 -> 2523 bytes
-rw-r--r--tests/test.txt9
-rw-r--r--tests/testping.phpt25
-rw-r--r--tests/uncommitted.phpt16
-rw-r--r--tests/xmltype_01.phpt121
-rw-r--r--tests/xmltype_02.phpt197
304 files changed, 38598 insertions, 0 deletions
diff --git a/CREDITS b/CREDITS
new file mode 100644
index 0000000000..4c1e0d05b7
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,2 @@
+OCI8
+Stig Bakken, Thies C. Arntzen, Andy Sautins, David Benson, Maxim Maletsky, Harald Radi, Antony Dovgal, Andi Gutmans, Wez Furlong, Christopher Jones, Oracle Corporation
diff --git a/README b/README
new file mode 100644
index 0000000000..037d54952e
--- /dev/null
+++ b/README
@@ -0,0 +1,12 @@
+The OCI8 Extension
+------------------
+
+The OCI8 extension allows PHP to access Oracle databases. It can be
+built using Oracle 9.2, 10, or 11 client libraries. It allows Oracle's
+standard cross-version connectivity, for example PHP using Oracle 10.2
+libraries can connect to Oracle Database 9.2 onwards.
+
+This release of OCI8 can be used with PHP versions 4.3.9 to 5.x.
+
+OCI8 installation instructions and documentation is available at
+http://www.php.net/oci8
diff --git a/config.m4 b/config.m4
new file mode 100644
index 0000000000..70e9cffd56
--- /dev/null
+++ b/config.m4
@@ -0,0 +1,360 @@
+dnl
+dnl $Id$
+dnl
+
+if test -z "$SED"; then
+ PHP_OCI8_SED="sed";
+else
+ PHP_OCI8_SED="$SED";
+fi
+
+AC_DEFUN([PHP_OCI_IF_DEFINED],[
+ old_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS=$3
+ AC_EGREP_CPP(yes,[
+#include <oci.h>
+#if defined($1)
+ yes
+#endif
+ ],[
+ CPPFLAGS=$old_CPPFLAGS
+ $2
+ ],[
+ CPPFLAGS=$old_CPPFLAGS
+ ])
+])
+
+AC_DEFUN([AC_OCI8_CHECK_LIB_DIR],[
+ AC_MSG_CHECKING([ORACLE_HOME library validity])
+ if test ! -d "$OCI8_DIR"; then
+ AC_MSG_ERROR([${OCI8_DIR} is not a directory])
+ fi
+ if test -d "$OCI8_DIR/lib" && test ! -d "$OCI8_DIR/lib32"; then
+ OCI8_LIB_DIR=lib
+ elif test ! -d "$OCI8_DIR/lib" && test -d "$OCI8_DIR/lib32"; then
+ OCI8_LIB_DIR=lib32
+ elif test -d "$OCI8_DIR/lib" && test -d "$OCI8_DIR/lib32"; then
+ OCI8_LIB_DIR=$PHP_OCI8_OH_LIBDIR
+ else
+ dnl This isn't an ORACLE_HOME. Try heuristic examination of the dir to help the user
+ if test -f "$OCI8_DIR/libociei.$SHLIB_SUFFIX_NAME"; then
+ AC_MSG_ERROR([Expected an ORACLE_HOME top level directory but ${OCI8_DIR} appears to be an Instant Client directory. Try --with-oci8=instantclient,${OCI8_DIR}])
+ else
+ AC_MSG_ERROR([Oracle library directory not found in ${OCI8_DIR}])
+ fi
+ fi
+ AC_MSG_RESULT($OCI8_LIB_DIR)
+])
+
+AC_DEFUN([AC_OCI8IC_VERSION],[
+ AC_MSG_CHECKING([Oracle Instant Client version])
+ if test -f $PHP_OCI8_INSTANT_CLIENT/libnnz11.$SHLIB_SUFFIX_NAME; then
+ if test -f $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME.11.1; then
+ if test ! -f $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME; then
+ AC_MSG_ERROR([Link from $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME to libclntsh.$SHLIB_SUFFIX_NAME.11.1 not found])
+ fi
+ OCI8_ORACLE_VERSION=11.1
+ else
+ AC_MSG_ERROR([Oracle Instant Client library version not supported])
+ fi
+ elif test -f $PHP_OCI8_INSTANT_CLIENT/libnnz10.$SHLIB_SUFFIX_NAME; then
+ if test -f $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME.10.1; then
+ if test ! -f $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME; then
+ AC_MSG_ERROR([Link from $PHP_OCI8_INSTANT_CLIENT/libclntsh.$SHLIB_SUFFIX_NAME to libclntsh.$SHLIB_SUFFIX_NAME.10.1 not found])
+ fi
+ OCI8_ORACLE_VERSION=10.1
+ else
+ AC_MSG_ERROR([Oracle Instant Client library version not supported])
+ fi
+ else
+ AC_MSG_ERROR([Oracle Instant Client libraries not found])
+ fi
+ AC_MSG_RESULT([$OCI8_ORACLE_VERSION])
+])
+
+
+AC_DEFUN([AC_OCI8_ORACLE_VERSION],[
+ AC_MSG_CHECKING([Oracle version])
+ if test -s "$OCI8_DIR/orainst/unix.rgs"; then
+ OCI8_ORACLE_VERSION=`grep '"ocommon"' $OCI8_DIR/orainst/unix.rgs | $PHP_OCI8_SED 's/[ ][ ]*/:/g' | cut -d: -f 6 | cut -c 2-4`
+ test -z "$OCI8_ORACLE_VERSION" && OCI8_ORACLE_VERSION=7.3
+ elif test -f $OCI8_DIR/$OCI8_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME.11.1; then
+ OCI8_ORACLE_VERSION=11.1
+ elif test -f $OCI8_DIR/$OCI8_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME.10.1; then
+ dnl There is no case for Oracle 10.2. Oracle 10.2 libraries have a 10.1 suffix for drop-in compatibility with Oracle 10.1
+ OCI8_ORACLE_VERSION=10.1
+ elif test -f $OCI8_DIR/$OCI8_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME.9.0; then
+ dnl There is no case for Oracle 9.2. Oracle 9.2 libraries have a 9.0 suffix for drop-in compatibility with Oracle 9.0
+ OCI8_ORACLE_VERSION=9.0
+ elif test -f $OCI8_DIR/$OCI8_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME.8.0; then
+ OCI8_ORACLE_VERSION=8.1
+ elif test -f $OCI8_DIR/$OCI8_LIB_DIR/libclntsh.$SHLIB_SUFFIX_NAME.1.0; then
+ OCI8_ORACLE_VERSION=8.0
+ elif test -f $OCI8_DIR/$OCI8_LIB_DIR/libclntsh.a; then
+ if test -f $OCI8_DIR/$OCI8_LIB_DIR/libcore4.a; then
+ OCI8_ORACLE_VERSION=8.0
+ else
+ OCI8_ORACLE_VERSION=8.1
+ fi
+ else
+ AC_MSG_ERROR(Oracle client libraries not found)
+ fi
+ AC_MSG_RESULT($OCI8_ORACLE_VERSION)
+])
+
+
+dnl --with-oci8=shared,instantclient,/path/to/client/dir/lib
+dnl or
+dnl --with-oci8=shared,/path/to/oracle/home
+PHP_ARG_WITH(oci8, for Oracle (OCI8) support,
+[ --with-oci8[=DIR] Include Oracle (OCI8) support. DIR defaults to \$ORACLE_HOME.
+ Use --with-oci8=instantclient,/path/to/instant/client/lib
+ to use an Oracle Instant Client installation])
+
+if test "$PHP_OCI8" != "no"; then
+
+ if test -z "$PHP_OCI8"; then
+ dnl --with-oci8=$ORACLE_HOME where ORACLE_HOME isn't set (or is mistyped) will match this case
+ AC_MSG_ERROR([Empty parameter value passed to --with-oci8])
+ fi
+
+ dnl Check PHP version is compatible with this extension
+
+ AC_MSG_CHECKING([PHP version])
+
+ tmp_version=$PHP_VERSION
+ if test -z "$tmp_version"; then
+ if test -z "$PHP_CONFIG"; then
+ AC_MSG_ERROR([php-config not found])
+ fi
+ php_version=`$PHP_CONFIG --version 2>/dev/null|head -n 1|$PHP_OCI8_SED -e 's#\([0-9]\.[0-9]*\.[0-9]*\)\(.*\)#\1#'`
+ else
+ php_version=`echo "$tmp_version"|$PHP_OCI8_SED -e 's#\([0-9]\.[0-9]*\.[0-9]*\)\(.*\)#\1#'`
+ fi
+
+ if test -z "$php_version"; then
+ AC_MSG_ERROR([failed to detect PHP version, please report])
+ fi
+
+ ac_IFS=$IFS
+ IFS="."
+ set $php_version
+ IFS=$ac_IFS
+ oci8_php_version=`expr [$]1 \* 1000000 + [$]2 \* 1000 + [$]3`
+
+ if test "$oci8_php_version" -lt "4003009"; then
+ AC_MSG_ERROR([You need at least PHP 4.3.9 to be able to use this version of OCI8. PHP $php_version found])
+ elif test "$oci8_php_version" -ge "6000000"; then
+ AC_MSG_ERROR([This version of OCI8 is not compatible with PHP 6 or higher])
+ else
+ AC_MSG_RESULT([$php_version, ok])
+ fi
+
+ dnl Set some port specific directory components for use later
+
+ AC_CHECK_SIZEOF(long int, 4)
+ AC_MSG_CHECKING([checking if we're on a 64-bit platform])
+ if test "$ac_cv_sizeof_long_int" = "4"; then
+ AC_MSG_RESULT([no])
+ PHP_OCI8_OH_LIBDIR=lib32
+ PHP_OCI8_IC_LIBDIR_SUFFIX=""
+ else
+ AC_MSG_RESULT([yes])
+ PHP_OCI8_OH_LIBDIR=lib
+ PHP_OCI8_IC_LIBDIR_SUFFIX=64
+ fi
+
+ dnl Determine if the user wants to use Oracle Instant Client libraries
+
+ PHP_OCI8_INSTANT_CLIENT="no"
+
+ dnl PECL Bug 14268 (Allow "pecl install oci8" command to "autodetect"
+ dnl an Instant Client RPM install). This also has a benefit for non
+ dnl "pecl install" builds: if the user does --with-oci8 or
+ dnl --with-oci8=shared but the ORACLE_HOME environment variable is not
+ dnl actually set, the install tries to locate the Instant Client RPM
+ if test "$PHP_OCI8" = "yes" && test -z "$ORACLE_HOME"; then
+ AC_MSG_WARN([OCI8 extension: ORACLE_HOME is not set, looking for default Oracle Instant Client instead])
+ PHP_OCI8=instantclient
+ fi
+
+ if test "`echo $PHP_OCI8`" = "instantclient"; then
+ PHP_OCI8_INSTANT_CLIENT="yes"
+ elif test "`echo $PHP_OCI8 | cut -d, -f2`" = "instantclient"; then
+ PHP_OCI8_INSTANT_CLIENT="`echo $PHP_OCI8 | cut -d, -f3`"
+ PHP_OCI8="`echo $PHP_OCI8 | cut -d, -f1,4`"
+ if test "$PHP_OCI8_INSTANT_CLIENT" = ""; then
+ PHP_OCI8_INSTANT_CLIENT="yes"
+ fi
+ if test -z "$PHP_OCI8"; then
+ PHP_OCI8=yes
+ fi
+ elif test "`echo $PHP_OCI8 | cut -d, -f1`" = "instantclient"; then
+ PHP_OCI8_INSTANT_CLIENT="`echo $PHP_OCI8 | cut -d, -f2`"
+ PHP_OCI8="`echo $PHP_OCI8 | cut -d, -f3,4`"
+ if test "$PHP_OCI8_INSTANT_CLIENT" = ""; then
+ PHP_OCI8_INSTANT_CLIENT="yes"
+ fi
+ if test -z "$PHP_OCI8"; then
+ PHP_OCI8=yes
+ fi
+ fi
+
+ if test "$PHP_OCI8_INSTANT_CLIENT" = "no"; then
+ dnl ***************************************
+ dnl Branch for using an ORACLE_HOME install
+ dnl ***************************************
+
+ AC_MSG_CHECKING([Oracle ORACLE_HOME install directory])
+
+ if test "$PHP_OCI8" = "yes"; then
+ OCI8_DIR=$ORACLE_HOME
+ else
+ OCI8_DIR=$PHP_OCI8
+ fi
+ AC_MSG_RESULT($OCI8_DIR)
+
+ AC_OCI8_CHECK_LIB_DIR($OCI8_DIR)
+
+ if test -d "$OCI8_DIR/rdbms/public"; then
+ PHP_ADD_INCLUDE($OCI8_DIR/rdbms/public)
+ OCI8_INCLUDES="$OCI8_INCLUDES -I$OCI8_DIR/rdbms/public"
+ fi
+ if test -d "$OCI8_DIR/rdbms/demo"; then
+ PHP_ADD_INCLUDE($OCI8_DIR/rdbms/demo)
+ OCI8_INCLUDES="$OCI8_INCLUDES -I$OCI8_DIR/rdbms/demo"
+ fi
+ if test -d "$OCI8_DIR/network/public"; then
+ PHP_ADD_INCLUDE($OCI8_DIR/network/public)
+ OCI8_INCLUDES="$OCI8_INCLUDES -I$OCI8_DIR/network/public"
+ fi
+ if test -d "$OCI8_DIR/plsql/public"; then
+ PHP_ADD_INCLUDE($OCI8_DIR/plsql/public)
+ OCI8_INCLUDES="$OCI8_INCLUDES -I$OCI8_DIR/plsql/public"
+ fi
+
+ if test -f "$OCI8_DIR/$OCI8_LIB_DIR/sysliblist"; then
+ PHP_EVAL_LIBLINE(`cat $OCI8_DIR/$OCI8_LIB_DIR/sysliblist`, OCI8_SYSLIB)
+ elif test -f "$OCI8_DIR/rdbms/$OCI8_LIB_DIR/sysliblist"; then
+ PHP_EVAL_LIBLINE(`cat $OCI8_DIR/rdbms/$OCI8_LIB_DIR/sysliblist`, OCI8_SYSLIB)
+ fi
+
+ AC_OCI8_ORACLE_VERSION($OCI8_DIR)
+
+ case $OCI8_ORACLE_VERSION in
+ 7.3|8.0|8.1)
+ AC_MSG_ERROR([Oracle client libraries < 9.2 are not supported])
+ ;;
+
+ 9.0)
+ PHP_CHECK_LIBRARY(clntsh, OCIEnvNlsCreate,
+ [
+ OCI8_ORACLE_VERSION=9.2
+ ],
+ [
+ AC_MSG_ERROR([Oracle client libraries < 9.2 are not supported])
+ ], [
+ -L$OCI8_DIR/$OCI8_LIB_DIR $OCI8_SHARED_LIBADD
+ ])
+ ;;
+
+ 10.1|11.1)
+ AC_DEFINE(HAVE_OCI_LOB_READ2,1,[ ])
+ ;;
+
+ *)
+ AC_MSG_ERROR([Oracle version $OCI8_ORACLE_VERSION is not supported])
+ ;;
+ esac
+
+ PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD)
+ PHP_ADD_LIBPATH($OCI8_DIR/$OCI8_LIB_DIR, OCI8_SHARED_LIBADD)
+ PHP_NEW_EXTENSION(oci8, oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c, $ext_shared)
+ AC_DEFINE(HAVE_OCI8,1,[ ])
+
+ PHP_SUBST_OLD(OCI8_SHARED_LIBADD)
+ PHP_SUBST_OLD(OCI8_DIR)
+ PHP_SUBST_OLD(OCI8_ORACLE_VERSION)
+
+ dnl Fix Bug #46623
+ AC_DEFINE_UNQUOTED(PHP_OCI8_DEF_DIR, "$OCI8_DIR", [ ])
+ AC_DEFINE_UNQUOTED(PHP_OCI8_DEF_SHARED_LIBADD, "$OCI8_SHARED_LIBADD", [ ])
+
+ else
+ dnl ***************************************************
+ dnl Branch for using an Oracle Instant Client directory
+ dnl ***************************************************
+
+ AC_MSG_CHECKING([Oracle Instant Client directory])
+
+ if test "$PHP_OCI8_INSTANT_CLIENT" = "yes"; then
+ dnl Find the directory if user specified "instantclient" but did not
+ dnl give a dir. Generally the Instant Client can be anywhere so the
+ dnl user must pass in the library directory. But on Linux we default
+ dnl to the most recent version in /usr/lib which is where the Oracle
+ dnl Instant Client RPM gets installed.
+ PHP_OCI8_INSTANT_CLIENT=`ls -d /usr/lib/oracle/*/client${PHP_OCI8_IC_LIBDIR_SUFFIX}/lib/libclntsh.* 2> /dev/null | tail -1 | $PHP_OCI8_SED -e 's#/libclntsh[^/]*##'`
+ if test -z "$PHP_OCI8_INSTANT_CLIENT"; then
+ AC_MSG_ERROR([Oracle Instant Client directory /usr/lib/oracle/.../client${PHP_OCI8_IC_LIBDIR_SUFFIX}/lib libraries not found. Try --with-oci8=instantclient,DIR])
+ fi
+ fi
+ AC_MSG_RESULT($PHP_OCI8_INSTANT_CLIENT)
+
+ OCI8_DIR=$PHP_OCI8_INSTANT_CLIENT
+
+ AC_MSG_CHECKING([Oracle Instant Client SDK header directory])
+
+ dnl Header directory for Instant Client SDK RPM install
+ OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!^/usr/lib/oracle/\(.*\)/client\('${PHP_OCI8_IC_LIBDIR_SUFFIX}'\)*/lib[/]*$!/usr/include/oracle/\1/client\2!'`
+
+ dnl Header directory for Instant Client SDK zip file install
+ OCISDKZIPINC=$PHP_OCI8_INSTANT_CLIENT/sdk/include
+
+ dnl Header directory for manual installation
+ OCISDKMANINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!\(.*\)/lib[/]*$!\1/include!'`
+
+ if test -f "$OCISDKRPMINC/oci.h"; then
+ AC_MSG_RESULT($OCISDKRPMINC)
+ PHP_ADD_INCLUDE($OCISDKRPMINC)
+ OCI8INCDIR=$OCISDKRPMINC
+ elif test -f "$OCISDKZIPINC/oci.h"; then
+ AC_MSG_RESULT($OCISDKZIPINC)
+ PHP_ADD_INCLUDE($OCISDKZIPINC)
+ OCI8INCDIR=$OCISDKZIPINC
+ elif test -f "$OCISDKMANINC/oci.h"; then
+ AC_MSG_RESULT($OCISDKMANINC)
+ PHP_ADD_INCLUDE($OCISDKMANINC)
+ OCI8INCDIR=$OCISDKMANINC
+ else
+ AC_MSG_ERROR([Oracle Instant Client SDK header files not found])
+ fi
+
+ OCISYSLIBLIST=`echo "$OCI8INCDIR" | $PHP_OCI8_SED -e 's!\(.*\)/include$!\1/demo/sysliblist!'`
+ if test -f "$OCISYSLIBLIST"; then
+ PHP_EVAL_LIBLINE(`cat $OCISYSLIBLIST`, OCI8_SYSLIB)
+ fi
+
+ AC_OCI8IC_VERSION($PHP_OCI8_INSTANT_CLIENT)
+ case $OCI8_ORACLE_VERSION in
+ 10.1|11.1)
+ PHP_ADD_LIBRARY(clntsh, 1, OCI8_SHARED_LIBADD)
+ PHP_ADD_LIBPATH($PHP_OCI8_INSTANT_CLIENT, OCI8_SHARED_LIBADD)
+ ;;
+
+ *)
+ AC_MSG_ERROR([Oracle Instant Client version $PHP_OCI8_INSTANT_CLIENT is not supported])
+ ;;
+ esac
+
+ AC_DEFINE(HAVE_OCI_INSTANT_CLIENT,1,[ ])
+ AC_DEFINE(HAVE_OCI_LOB_READ2,1,[ ])
+
+ PHP_NEW_EXTENSION(oci8, oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c, $ext_shared)
+ AC_DEFINE(HAVE_OCI8,1,[ ])
+
+ PHP_SUBST_OLD(OCI8_SHARED_LIBADD)
+ PHP_SUBST_OLD(OCI8_DIR)
+ PHP_SUBST_OLD(OCI8_ORACLE_VERSION)
+
+ fi
+fi
diff --git a/config.w32 b/config.w32
new file mode 100644
index 0000000000..fdd7fa5e48
--- /dev/null
+++ b/config.w32
@@ -0,0 +1,82 @@
+// $Id$
+// vim:ft=javascript
+
+if (PHP_OCI8 != "no" && PHP_OCI8_11G != "no") {
+ if (!PHP_OCI8_SHARED && !PHP_OCI8_11G_SHARED) {
+ WARNING("oci8 and oci8-11g provide the same extension and cannot both be built statically");
+ PHP_OCI8 = "no"
+ PHP_OCI8_11G = "no"
+ }
+}
+
+ARG_WITH("oci8", "OCI8 support", "no");
+
+if (PHP_OCI8 != "no") {
+
+ oci8_dirs = new Array(
+ PHP_OCI8
+ );
+
+ oci8_lib_paths = "";
+ oci8_inc_paths = "";
+
+ // find the Oracle install
+ for (i = 0; i < oci8_dirs.length; i++) {
+ oci8_lib_paths += oci8_dirs[i] + "\\lib;";
+ oci8_lib_paths += oci8_dirs[i] + "\\lib\\msvc;";
+ oci8_inc_paths += oci8_dirs[i] + "\\include;";
+ }
+
+ oci8_inc_paths += PHP_PHP_BUILD + "\\include\\instantclient;"
+ oci8_lib_paths += PHP_PHP_BUILD + "\\lib\\instantclient;";
+
+ if (CHECK_HEADER_ADD_INCLUDE("oci.h", "CFLAGS_OCI8", oci8_inc_paths) &&
+ CHECK_LIB("oci.lib", "oci8", oci8_lib_paths))
+ {
+ EXTENSION('oci8', 'oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c');
+
+ AC_DEFINE('HAVE_OCI8', 1);
+ AC_DEFINE('HAVE_OCI_INSTANT_CLIENT', 1);
+ AC_DEFINE('HAVE_OCI_LOB_READ2', 1);
+
+ } else {
+ WARNING("oci8 not enabled: Oracle Database libraries or Oracle 10g Instant Client not found");
+ PHP_OCI8 = "no"
+ }
+}
+
+ARG_WITH("oci8-11g", "OCI8 support using Oracle 11g Instant Client", "no");
+
+if (PHP_OCI8_11G != "no") {
+
+ oci8_11g_dirs = new Array(
+ PHP_OCI8_11G
+ );
+
+ oci8_11g_lib_paths = "";
+ oci8_11g_inc_paths = "";
+
+ // find the Oracle install
+ for (i = 0; i < oci8_11g_dirs.length; i++) {
+ oci8_11g_lib_paths += oci8_11g_dirs[i] + "\\lib;";
+ oci8_11g_lib_paths += oci8_11g_dirs[i] + "\\lib\\msvc;";
+ oci8_11g_inc_paths += oci8_11g_dirs[i] + "\\include;";
+ }
+
+ oci8_11g_inc_paths += PHP_PHP_BUILD + "\\include\\instantclient_11;"
+ oci8_11g_lib_paths += PHP_PHP_BUILD + "\\lib\\instantclient_11;";
+
+ if (CHECK_HEADER_ADD_INCLUDE("oci.h", "CFLAGS_OCI8_11G", oci8_11g_inc_paths) &&
+ CHECK_LIB("oci.lib", "oci8_11g", oci8_11g_lib_paths))
+ {
+ EXTENSION('oci8_11g', 'oci8.c oci8_lob.c oci8_statement.c oci8_collection.c oci8_interface.c', null, null, null, "ext\\oci8_11g")
+
+ AC_DEFINE('HAVE_OCI8', 1);
+ AC_DEFINE('HAVE_OCI_INSTANT_CLIENT', 1);
+ AC_DEFINE('HAVE_OCI_LOB_READ2', 1);
+
+ } else {
+ WARNING("oci8-11g not enabled: Oracle Database libraries or Oracle 11g Instant Client not found");
+ PHP_OCI8_11G = "no"
+ }
+}
diff --git a/oci8.c b/oci8.c
new file mode 100644
index 0000000000..1be6315eef
--- /dev/null
+++ b/oci8.c
@@ -0,0 +1,3246 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@php.net> |
+ | Thies C. Arntzen <thies@thieso.net> |
+ | Maxim Maletsky <maxim@maxim.cx> |
+ | |
+ | Collection support by Andy Sautins <asautins@veripost.net> |
+ | Temporary LOB support by David Benson <dbenson@mancala.com> |
+ | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
+ | |
+ | Redesigned by: Antony Dovgal <antony@zend.com> |
+ | Andi Gutmans <andi@zend.com> |
+ | Wez Furlong <wez@omniti.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "ext/standard/info.h"
+#include "php_ini.h"
+#include "ext/standard/php_smart_str.h"
+
+#if HAVE_OCI8
+
+#if PHP_MAJOR_VERSION > 5
+#error This version of the PHP OCI8 extension is not compatible with PHP 6 or later
+#elif PHP_MAJOR_VERSION < 5
+#ifdef ZTS
+#error The PHP OCI8 extension does not support ZTS mode in PHP 4
+#endif
+#endif
+
+#include "php_oci8.h"
+#include "php_oci8_int.h"
+#include "zend_hash.h"
+
+ZEND_DECLARE_MODULE_GLOBALS(oci)
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
+/* This "if" allows PECL builds from this file to be portable to older PHP releases */
+static PHP_GINIT_FUNCTION(oci);
+static PHP_GSHUTDOWN_FUNCTION(oci);
+#endif
+
+/* Allow PHP 5.3 branch to be used in PECL for 5.x compatible builds */
+#ifndef Z_ADDREF_P
+#define Z_ADDREF_P(x) ZVAL_ADDREF(x)
+#endif
+
+/* For a user friendly message about environment setup */
+/* TODO: add cases for SHLIB_PATH, LIBPATH, LD_LIBRARY_PATH_64 etc */
+#if defined(PHP_WIN32)
+#define PHP_OCI8_LIB_PATH_MSG "PATH"
+#elif defined(__APPLE__)
+#define PHP_OCI8_LIB_PATH_MSG "DYLD_LIBRARY_PATH"
+#else
+#define PHP_OCI8_LIB_PATH_MSG "LD_LIBRARY_PATH"
+#endif
+
+/* True globals, no need for thread safety */
+int le_connection;
+int le_pconnection;
+int le_statement;
+int le_descriptor;
+int le_psessionpool;
+int le_collection;
+
+zend_class_entry *oci_lob_class_entry_ptr;
+zend_class_entry *oci_coll_class_entry_ptr;
+
+#ifndef SQLT_BFILEE
+#define SQLT_BFILEE 114
+#endif
+#ifndef SQLT_CFILEE
+#define SQLT_CFILEE 115
+#endif
+
+#define PHP_OCI_ERRBUF_LEN 1024
+
+#if ZEND_MODULE_API_NO > 20020429
+#define ONUPDATELONGFUNC OnUpdateLong
+#else
+#define ONUPDATELONGFUNC OnUpdateInt
+#endif
+
+#ifdef ZTS
+#define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX)
+#else
+#define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT)
+#endif
+
+/* static protos {{{ */
+static void php_oci_connection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
+static void php_oci_pconnection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
+static void php_oci_pconnection_list_np_dtor (zend_rsrc_list_entry * TSRMLS_DC);
+static void php_oci_statement_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
+static void php_oci_descriptor_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
+static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC);
+static void php_oci_collection_list_dtor (zend_rsrc_list_entry * TSRMLS_DC);
+
+static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC);
+static int php_oci_connection_ping(php_oci_connection * TSRMLS_DC);
+static int php_oci_connection_status(php_oci_connection * TSRMLS_DC);
+static int php_oci_connection_close(php_oci_connection * TSRMLS_DC);
+static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC);
+
+static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC);
+static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC);
+static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC);
+static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC);
+static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC);
+static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC);
+/* }}} */
+
+/* {{{ dynamically loadable module stuff */
+#if defined(COMPILE_DL_OCI8) || defined(COMPILE_DL_OCI8_11G)
+ZEND_GET_MODULE(oci8)
+#endif /* COMPILE_DL */
+/* }}} */
+
+#ifdef ZEND_ENGINE_2
+
+/* {{{ Function arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_define_by_name, 0, 0, 3)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_name)
+ ZEND_ARG_INFO(1, variable)
+ ZEND_ARG_INFO(0, type)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_by_name, 0, 0, 3)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_name)
+ ZEND_ARG_INFO(1, variable)
+ ZEND_ARG_INFO(0, maximum_length)
+ ZEND_ARG_INFO(0, type)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_bind_array_by_name, 0, 0, 4)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_name)
+ ZEND_ARG_INFO(1, variable)
+ ZEND_ARG_INFO(0, maximum_array_length)
+ ZEND_ARG_INFO(0, maximum_item_length)
+ ZEND_ARG_INFO(0, type)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_descriptor, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, filename)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_load, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_eof, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_tell, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_rewind, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, whence)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_size, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, string)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor_to)
+ ZEND_ARG_INFO(0, lob_descriptor_from)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, flag)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ocisetbufferinglob, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ocigetbufferinglob, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_copy, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor_to)
+ ZEND_ARG_INFO(0, lob_descriptor_from)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_is_equal, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export, 0, 0, 2)
+ ZEND_ARG_INFO(0, lob_descriptor)
+ ZEND_ARG_INFO(0, filename)
+ ZEND_ARG_INFO(0, start)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_descriptor, 0, 0, 1)
+ ZEND_ARG_INFO(0, connection_resource)
+ ZEND_ARG_INFO(0, type)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_rollback, 0, 0, 1)
+ ZEND_ARG_INFO(0, connection_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_commit, 0, 0, 1)
+ ZEND_ARG_INFO(0, connection_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_name, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_number)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_size, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_number_or_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_scale, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_number)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_precision, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_number)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_number)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_type_raw, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_number)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_field_is_null, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_number_or_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_internal_debug, 0, 0, 1)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_execute, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_cancel, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ocifetchinto, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(1, result)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_all, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(1, output)
+ ZEND_ARG_INFO(0, skip)
+ ZEND_ARG_INFO(0, maximum_rows)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_object, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_row, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_assoc, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_fetch_array, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_statement, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_close, 0, 0, 1)
+ ZEND_ARG_INFO(0, connection_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_connect, 0, 0, 2)
+ ZEND_ARG_INFO(0, username)
+ ZEND_ARG_INFO(0, password)
+ ZEND_ARG_INFO(0, connection_string)
+ ZEND_ARG_INFO(0, character_set)
+ ZEND_ARG_INFO(0, session_mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_connect, 0, 0, 2)
+ ZEND_ARG_INFO(0, username)
+ ZEND_ARG_INFO(0, password)
+ ZEND_ARG_INFO(0, connection_string)
+ ZEND_ARG_INFO(0, character_set)
+ ZEND_ARG_INFO(0, session_mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_pconnect, 0, 0, 2)
+ ZEND_ARG_INFO(0, username)
+ ZEND_ARG_INFO(0, password)
+ ZEND_ARG_INFO(0, connection_string)
+ ZEND_ARG_INFO(0, character_set)
+ ZEND_ARG_INFO(0, session_mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_error, 0, 0, 0)
+ ZEND_ARG_INFO(0, connection_or_statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_fields, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_parse, 0, 0, 2)
+ ZEND_ARG_INFO(0, connection_resource)
+ ZEND_ARG_INFO(0, sql_text)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_prefetch, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, number_of_rows)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_identifier, 0, 0, 2)
+ ZEND_ARG_INFO(0, connection_resource)
+ ZEND_ARG_INFO(0, client_identifier)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_edition, 0, 0, 1)
+ ZEND_ARG_INFO(0, edition_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_module_name, 0, 0, 2)
+ ZEND_ARG_INFO(0, connection_resource)
+ ZEND_ARG_INFO(0, module_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_action, 0, 0, 2)
+ ZEND_ARG_INFO(0, connection_resource)
+ ZEND_ARG_INFO(0, action)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_set_client_info, 0, 0, 2)
+ ZEND_ARG_INFO(0, connection_resource)
+ ZEND_ARG_INFO(0, client_information)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_password_change, 0, 0, 4)
+ ZEND_ARG_INFO(0, connection_resource_or_connection_string)
+ ZEND_ARG_INFO(0, username)
+ ZEND_ARG_INFO(0, old_password)
+ ZEND_ARG_INFO(0, new_password)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_cursor, 0, 0, 1)
+ ZEND_ARG_INFO(0, connection_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_result, 0, 0, 2)
+ ZEND_ARG_INFO(0, statement_resource)
+ ZEND_ARG_INFO(0, column_number_or_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_server_version, 0, 0, 1)
+ ZEND_ARG_INFO(0, connection_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_statement_type, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_num_rows, 0, 0, 1)
+ ZEND_ARG_INFO(0, statement_resource)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_free_collection, 0, 0, 1)
+ ZEND_ARG_INFO(0, collection)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append, 0, 0, 2)
+ ZEND_ARG_INFO(0, collection)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get, 0, 0, 2)
+ ZEND_ARG_INFO(0, collection)
+ ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign, 0, 0, 2)
+ ZEND_ARG_INFO(0, collection_to)
+ ZEND_ARG_INFO(0, collection_from)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign, 0, 0, 3)
+ ZEND_ARG_INFO(0, collection)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_size, 0, 0, 1)
+ ZEND_ARG_INFO(0, collection)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_max, 0, 0, 1)
+ ZEND_ARG_INFO(0, collection)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim, 0, 0, 2)
+ ZEND_ARG_INFO(0, collection)
+ ZEND_ARG_INFO(0, number)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_new_collection, 0, 0, 2)
+ ZEND_ARG_INFO(0, connection_resource)
+ ZEND_ARG_INFO(0, type_name)
+ ZEND_ARG_INFO(0, schema_name)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ LOB Method arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_save_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_import_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, filename)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_load_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_read_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_eof_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_tell_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_rewind_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_seek_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, whence)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_size_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, string)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_append_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, lob_descriptor_from)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_truncate_method, 0, 0, 0)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_erase_method, 0, 0, 0)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_flush_method, 0, 0, 0)
+ ZEND_ARG_INFO(0, flag)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_setbuffering_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_getbuffering_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_export_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, filename)
+ ZEND_ARG_INFO(0, start)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_lob_write_temporary_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ ZEND_ARG_INFO(0, type)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_lob_close_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_free_descriptor_method, 0)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ Collection Method arginfo */
+ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_free_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_append_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_get_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_assign_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, collection_from)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_element_assign_method, 0, 0, 2)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_size_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_oci_collection_max_method, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim_method, 0, 0, 1)
+ ZEND_ARG_INFO(0, number)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+#else /* ZEND_ENGINE_2 */
+/* {{{ Keep the old arginfo behavior when building with PHP 4 */
+
+static unsigned char arginfo_ocifetchinto[] = { 2, BYREF_NONE, BYREF_FORCE };
+static unsigned char arginfo_oci_fetch_all[] = { 2, BYREF_NONE, BYREF_FORCE };
+static unsigned char arginfo_oci_define_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
+static unsigned char arginfo_oci_bind_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
+static unsigned char arginfo_oci_bind_array_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
+
+#define arginfo_oci_free_descriptor NULL
+#define arginfo_oci_lob_save NULL
+#define arginfo_oci_lob_import NULL
+#define arginfo_oci_lob_load NULL
+#define arginfo_oci_lob_read NULL
+#define arginfo_oci_lob_eof NULL
+#define arginfo_oci_lob_tell NULL
+#define arginfo_oci_lob_rewind NULL
+#define arginfo_oci_lob_seek NULL
+#define arginfo_oci_lob_size NULL
+#define arginfo_oci_lob_write NULL
+#define arginfo_oci_lob_append NULL
+#define arginfo_oci_lob_truncate NULL
+#define arginfo_oci_lob_erase NULL
+#define arginfo_oci_lob_flush NULL
+#define arginfo_ocisetbufferinglob NULL
+#define arginfo_ocigetbufferinglob NULL
+#define arginfo_oci_lob_copy NULL
+#define arginfo_oci_lob_is_equal NULL
+#define arginfo_oci_lob_export NULL
+#define arginfo_oci_new_descriptor NULL
+#define arginfo_oci_rollback NULL
+#define arginfo_oci_commit NULL
+#define arginfo_oci_field_name NULL
+#define arginfo_oci_field_size NULL
+#define arginfo_oci_field_scale NULL
+#define arginfo_oci_field_precision NULL
+#define arginfo_oci_field_type NULL
+#define arginfo_oci_field_type_raw NULL
+#define arginfo_oci_field_is_null NULL
+#define arginfo_oci_internal_debug NULL
+#define arginfo_oci_execute NULL
+#define arginfo_oci_cancel NULL
+#define arginfo_oci_fetch NULL
+#define arginfo_oci_fetch_object NULL
+#define arginfo_oci_fetch_row NULL
+#define arginfo_oci_fetch_assoc NULL
+#define arginfo_oci_fetch_array NULL
+#define arginfo_oci_free_statement NULL
+#define arginfo_oci_close NULL
+#define arginfo_oci_new_connect NULL
+#define arginfo_oci_connect NULL
+#define arginfo_oci_pconnect NULL
+#define arginfo_oci_error NULL
+#define arginfo_oci_num_fields NULL
+#define arginfo_oci_parse NULL
+#define arginfo_oci_set_prefetch NULL
+#define arginfo_oci_set_client_identifier NULL
+#define arginfo_oci_set_edition NULL
+#define arginfo_oci_set_module_name NULL
+#define arginfo_oci_set_action NULL
+#define arginfo_oci_set_client_info NULL
+#define arginfo_oci_password_change NULL
+#define arginfo_oci_new_cursor NULL
+#define arginfo_oci_result NULL
+#define arginfo_oci_server_version NULL
+#define arginfo_oci_statement_type NULL
+#define arginfo_oci_num_rows NULL
+#define arginfo_oci_free_collection NULL
+#define arginfo_oci_collection_append NULL
+#define arginfo_oci_collection_element_get NULL
+#define arginfo_oci_collection_assign NULL
+#define arginfo_oci_collection_element_assign NULL
+#define arginfo_oci_collection_size NULL
+#define arginfo_oci_collection_max NULL
+#define arginfo_oci_collection_trim NULL
+#define arginfo_oci_new_collection NULL
+#define arginfo_oci_lob_size_method NULL
+#define arginfo_oci_lob_getbuffering_method NULL
+#define arginfo_oci_lob_close_method NULL
+#define arginfo_oci_lob_save_method NULL
+#define arginfo_oci_lob_import_method NULL
+#define arginfo_oci_lob_read_method NULL
+#define arginfo_oci_lob_seek_method NULL
+#define arginfo_oci_lob_write_method NULL
+#define arginfo_oci_lob_append_method NULL
+#define arginfo_oci_lob_truncate_method NULL
+#define arginfo_oci_lob_erase_method NULL
+#define arginfo_oci_lob_flush_method NULL
+#define arginfo_oci_lob_setbuffering_method NULL
+#define arginfo_oci_lob_export_method NULL
+#define arginfo_oci_lob_write_temporary_method NULL
+#define arginfo_oci_lob_load_method NULL
+#define arginfo_oci_lob_tell_method NULL
+#define arginfo_oci_lob_rewind_method NULL
+#define arginfo_oci_lob_eof_method NULL
+#define arginfo_oci_free_descriptor_method NULL
+#define arginfo_oci_collection_append_method NULL
+#define arginfo_oci_collection_element_get_method NULL
+#define arginfo_oci_collection_assign_method NULL
+#define arginfo_oci_collection_size_method NULL
+#define arginfo_oci_collection_element_assign_method NULL
+#define arginfo_oci_collection_max_method NULL
+#define arginfo_oci_collection_trim_method NULL
+#define arginfo_oci_collection_free_method NULL
+/* }}} */
+#endif /* ZEND_ENGINE_2 */
+
+/* {{{ extension function prototypes
+*/
+PHP_FUNCTION(oci_bind_by_name);
+PHP_FUNCTION(oci_bind_array_by_name);
+PHP_FUNCTION(oci_define_by_name);
+PHP_FUNCTION(oci_field_is_null);
+PHP_FUNCTION(oci_field_name);
+PHP_FUNCTION(oci_field_size);
+PHP_FUNCTION(oci_field_scale);
+PHP_FUNCTION(oci_field_precision);
+PHP_FUNCTION(oci_field_type);
+PHP_FUNCTION(oci_field_type_raw);
+PHP_FUNCTION(oci_execute);
+PHP_FUNCTION(oci_fetch);
+PHP_FUNCTION(oci_cancel);
+PHP_FUNCTION(ocifetchinto);
+PHP_FUNCTION(oci_fetch_object);
+PHP_FUNCTION(oci_fetch_row);
+PHP_FUNCTION(oci_fetch_assoc);
+PHP_FUNCTION(oci_fetch_array);
+PHP_FUNCTION(ocifetchstatement);
+PHP_FUNCTION(oci_fetch_all);
+PHP_FUNCTION(oci_free_statement);
+PHP_FUNCTION(oci_internal_debug);
+PHP_FUNCTION(oci_close);
+PHP_FUNCTION(oci_connect);
+PHP_FUNCTION(oci_new_connect);
+PHP_FUNCTION(oci_pconnect);
+PHP_FUNCTION(oci_error);
+PHP_FUNCTION(oci_free_descriptor);
+PHP_FUNCTION(oci_commit);
+PHP_FUNCTION(oci_rollback);
+PHP_FUNCTION(oci_new_descriptor);
+PHP_FUNCTION(oci_num_fields);
+PHP_FUNCTION(oci_parse);
+PHP_FUNCTION(oci_new_cursor);
+PHP_FUNCTION(oci_result);
+PHP_FUNCTION(oci_server_version);
+PHP_FUNCTION(oci_statement_type);
+PHP_FUNCTION(oci_num_rows);
+PHP_FUNCTION(oci_set_prefetch);
+PHP_FUNCTION(oci_set_client_identifier);
+PHP_FUNCTION(oci_set_edition);
+PHP_FUNCTION(oci_set_module_name);
+PHP_FUNCTION(oci_set_action);
+PHP_FUNCTION(oci_set_client_info);
+PHP_FUNCTION(oci_password_change);
+PHP_FUNCTION(oci_lob_save);
+PHP_FUNCTION(oci_lob_import);
+PHP_FUNCTION(oci_lob_export);
+PHP_FUNCTION(oci_lob_load);
+PHP_FUNCTION(oci_lob_tell);
+PHP_FUNCTION(oci_lob_write);
+PHP_FUNCTION(oci_lob_append);
+PHP_FUNCTION(oci_lob_copy);
+PHP_FUNCTION(oci_lob_truncate);
+PHP_FUNCTION(oci_lob_erase);
+PHP_FUNCTION(oci_lob_flush);
+PHP_FUNCTION(ocisetbufferinglob);
+PHP_FUNCTION(ocigetbufferinglob);
+PHP_FUNCTION(oci_lob_is_equal);
+PHP_FUNCTION(oci_lob_rewind);
+PHP_FUNCTION(oci_lob_read);
+PHP_FUNCTION(oci_lob_eof);
+PHP_FUNCTION(oci_lob_seek);
+PHP_FUNCTION(oci_lob_size);
+PHP_FUNCTION(oci_lob_write_temporary);
+PHP_FUNCTION(oci_lob_close);
+PHP_FUNCTION(oci_new_collection);
+PHP_FUNCTION(oci_free_collection);
+PHP_FUNCTION(oci_collection_append);
+PHP_FUNCTION(oci_collection_element_get);
+PHP_FUNCTION(oci_collection_element_assign);
+PHP_FUNCTION(oci_collection_assign);
+PHP_FUNCTION(oci_collection_size);
+PHP_FUNCTION(oci_collection_max);
+PHP_FUNCTION(oci_collection_trim);
+/* }}} */
+
+/* {{{ extension definition structures
+*/
+static
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
+/* This "if" allows PECL builds from this file to be portable to older PHP releases */
+const
+#endif
+zend_function_entry php_oci_functions[] = {
+ PHP_FE(oci_define_by_name, arginfo_oci_define_by_name)
+ PHP_FE(oci_bind_by_name, arginfo_oci_bind_by_name)
+ PHP_FE(oci_bind_array_by_name, arginfo_oci_bind_array_by_name)
+ PHP_FE(oci_field_is_null, arginfo_oci_field_is_null)
+ PHP_FE(oci_field_name, arginfo_oci_field_name)
+ PHP_FE(oci_field_size, arginfo_oci_field_size)
+ PHP_FE(oci_field_scale, arginfo_oci_field_scale)
+ PHP_FE(oci_field_precision, arginfo_oci_field_precision)
+ PHP_FE(oci_field_type, arginfo_oci_field_type)
+ PHP_FE(oci_field_type_raw, arginfo_oci_field_type_raw)
+ PHP_FE(oci_execute, arginfo_oci_execute)
+ PHP_FE(oci_cancel, arginfo_oci_cancel)
+ PHP_FE(oci_fetch, arginfo_oci_fetch)
+ PHP_FE(oci_fetch_object, arginfo_oci_fetch_object)
+ PHP_FE(oci_fetch_row, arginfo_oci_fetch_row)
+ PHP_FE(oci_fetch_assoc, arginfo_oci_fetch_assoc)
+ PHP_FE(oci_fetch_array, arginfo_oci_fetch_array)
+ PHP_FE(ocifetchinto, arginfo_ocifetchinto)
+ PHP_FE(oci_fetch_all, arginfo_oci_fetch_all)
+ PHP_FE(oci_free_statement, arginfo_oci_free_statement)
+ PHP_FE(oci_internal_debug, arginfo_oci_internal_debug)
+ PHP_FE(oci_num_fields, arginfo_oci_num_fields)
+ PHP_FE(oci_parse, arginfo_oci_parse)
+ PHP_FE(oci_new_cursor, arginfo_oci_new_cursor)
+ PHP_FE(oci_result, arginfo_oci_result)
+ PHP_FE(oci_server_version, arginfo_oci_server_version)
+ PHP_FE(oci_statement_type, arginfo_oci_statement_type)
+ PHP_FE(oci_num_rows, arginfo_oci_num_rows)
+ PHP_FE(oci_close, arginfo_oci_close)
+ PHP_FE(oci_connect, arginfo_oci_connect)
+ PHP_FE(oci_new_connect, arginfo_oci_new_connect)
+ PHP_FE(oci_pconnect, arginfo_oci_pconnect)
+ PHP_FE(oci_error, arginfo_oci_error)
+ PHP_FE(oci_free_descriptor, arginfo_oci_free_descriptor)
+ PHP_FE(oci_lob_save, arginfo_oci_lob_save)
+ PHP_FE(oci_lob_import, arginfo_oci_lob_import)
+ PHP_FE(oci_lob_size, arginfo_oci_lob_size)
+ PHP_FE(oci_lob_load, arginfo_oci_lob_load)
+ PHP_FE(oci_lob_read, arginfo_oci_lob_read)
+ PHP_FE(oci_lob_eof, arginfo_oci_lob_eof)
+ PHP_FE(oci_lob_tell, arginfo_oci_lob_tell)
+ PHP_FE(oci_lob_truncate, arginfo_oci_lob_truncate)
+ PHP_FE(oci_lob_erase, arginfo_oci_lob_erase)
+ PHP_FE(oci_lob_flush, arginfo_oci_lob_flush)
+ PHP_FE(ocisetbufferinglob, arginfo_ocisetbufferinglob)
+ PHP_FE(ocigetbufferinglob, arginfo_ocigetbufferinglob)
+ PHP_FE(oci_lob_is_equal, arginfo_oci_lob_is_equal)
+ PHP_FE(oci_lob_rewind, arginfo_oci_lob_rewind)
+ PHP_FE(oci_lob_write, arginfo_oci_lob_write)
+ PHP_FE(oci_lob_append, arginfo_oci_lob_append)
+ PHP_FE(oci_lob_copy, arginfo_oci_lob_copy)
+ PHP_FE(oci_lob_export, arginfo_oci_lob_export)
+ PHP_FE(oci_lob_seek, arginfo_oci_lob_seek)
+ PHP_FE(oci_commit, arginfo_oci_commit)
+ PHP_FE(oci_rollback, arginfo_oci_rollback)
+ PHP_FE(oci_new_descriptor, arginfo_oci_new_descriptor)
+ PHP_FE(oci_set_prefetch, arginfo_oci_set_prefetch)
+ PHP_FE(oci_set_client_identifier, arginfo_oci_set_client_identifier)
+ PHP_FE(oci_set_edition, arginfo_oci_set_edition)
+ PHP_FE(oci_set_module_name, arginfo_oci_set_module_name)
+ PHP_FE(oci_set_action, arginfo_oci_set_action)
+ PHP_FE(oci_set_client_info, arginfo_oci_set_client_info)
+ PHP_FE(oci_password_change, arginfo_oci_password_change)
+ PHP_FE(oci_free_collection, arginfo_oci_free_collection)
+ PHP_FE(oci_collection_append, arginfo_oci_collection_append)
+ PHP_FE(oci_collection_element_get, arginfo_oci_collection_element_get)
+ PHP_FE(oci_collection_element_assign, arginfo_oci_collection_element_assign)
+ PHP_FE(oci_collection_assign, arginfo_oci_collection_assign)
+ PHP_FE(oci_collection_size, arginfo_oci_collection_size)
+ PHP_FE(oci_collection_max, arginfo_oci_collection_max)
+ PHP_FE(oci_collection_trim, arginfo_oci_collection_trim)
+ PHP_FE(oci_new_collection, arginfo_oci_new_collection)
+
+ PHP_FALIAS(oci_free_cursor, oci_free_statement, arginfo_oci_free_statement)
+ PHP_FALIAS(ocifreecursor, oci_free_statement, arginfo_oci_free_statement)
+ PHP_FALIAS(ocibindbyname, oci_bind_by_name, arginfo_oci_bind_by_name)
+ PHP_FALIAS(ocidefinebyname, oci_define_by_name, arginfo_oci_define_by_name)
+ PHP_FALIAS(ocicolumnisnull, oci_field_is_null, arginfo_oci_field_is_null)
+ PHP_FALIAS(ocicolumnname, oci_field_name, arginfo_oci_field_name)
+ PHP_FALIAS(ocicolumnsize, oci_field_size, arginfo_oci_field_size)
+ PHP_FALIAS(ocicolumnscale, oci_field_scale, arginfo_oci_field_scale)
+ PHP_FALIAS(ocicolumnprecision, oci_field_precision, arginfo_oci_field_precision)
+ PHP_FALIAS(ocicolumntype, oci_field_type, arginfo_oci_field_type)
+ PHP_FALIAS(ocicolumntyperaw, oci_field_type_raw, arginfo_oci_field_type_raw)
+ PHP_FALIAS(ociexecute, oci_execute, arginfo_oci_execute)
+ PHP_FALIAS(ocicancel, oci_cancel, arginfo_oci_cancel)
+ PHP_FALIAS(ocifetch, oci_fetch, arginfo_oci_fetch)
+ PHP_FALIAS(ocifetchstatement, oci_fetch_all, arginfo_oci_fetch_all)
+ PHP_FALIAS(ocifreestatement, oci_free_statement, arginfo_oci_free_statement)
+ PHP_FALIAS(ociinternaldebug, oci_internal_debug, arginfo_oci_internal_debug)
+ PHP_FALIAS(ocinumcols, oci_num_fields, arginfo_oci_num_fields)
+ PHP_FALIAS(ociparse, oci_parse, arginfo_oci_parse)
+ PHP_FALIAS(ocinewcursor, oci_new_cursor, arginfo_oci_new_cursor)
+ PHP_FALIAS(ociresult, oci_result, arginfo_oci_result)
+ PHP_FALIAS(ociserverversion, oci_server_version, arginfo_oci_server_version)
+ PHP_FALIAS(ocistatementtype, oci_statement_type, arginfo_oci_statement_type)
+ PHP_FALIAS(ocirowcount, oci_num_rows, arginfo_oci_num_rows)
+ PHP_FALIAS(ocilogoff, oci_close, arginfo_oci_close)
+ PHP_FALIAS(ocilogon, oci_connect, arginfo_oci_connect)
+ PHP_FALIAS(ocinlogon, oci_new_connect, arginfo_oci_new_connect)
+ PHP_FALIAS(ociplogon, oci_pconnect, arginfo_oci_pconnect)
+ PHP_FALIAS(ocierror, oci_error, arginfo_oci_error)
+ PHP_FALIAS(ocifreedesc, oci_free_descriptor, arginfo_oci_free_descriptor)
+ PHP_FALIAS(ocisavelob, oci_lob_save, arginfo_oci_lob_save)
+ PHP_FALIAS(ocisavelobfile, oci_lob_import, arginfo_oci_lob_import)
+ PHP_FALIAS(ociwritelobtofile, oci_lob_export, arginfo_oci_lob_export)
+ PHP_FALIAS(ociloadlob, oci_lob_load, arginfo_oci_lob_load)
+ PHP_FALIAS(ocicommit, oci_commit, arginfo_oci_commit)
+ PHP_FALIAS(ocirollback, oci_rollback, arginfo_oci_rollback)
+ PHP_FALIAS(ocinewdescriptor, oci_new_descriptor, arginfo_oci_new_descriptor)
+ PHP_FALIAS(ocisetprefetch, oci_set_prefetch, arginfo_oci_set_prefetch)
+ PHP_FALIAS(ocipasswordchange, oci_password_change, arginfo_oci_password_change)
+ PHP_FALIAS(ocifreecollection, oci_free_collection, arginfo_oci_free_collection)
+ PHP_FALIAS(ocinewcollection, oci_new_collection, arginfo_oci_new_collection)
+ PHP_FALIAS(ocicollappend, oci_collection_append, arginfo_oci_collection_append)
+ PHP_FALIAS(ocicollgetelem, oci_collection_element_get, arginfo_oci_collection_element_get)
+ PHP_FALIAS(ocicollassignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign)
+ PHP_FALIAS(ocicollsize, oci_collection_size, arginfo_oci_collection_size)
+ PHP_FALIAS(ocicollmax, oci_collection_max, arginfo_oci_collection_max)
+ PHP_FALIAS(ocicolltrim, oci_collection_trim, arginfo_oci_collection_trim)
+ {NULL,NULL,NULL}
+};
+
+static
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
+/* This "if" allows PECL builds from this file to be portable to older PHP releases */
+const
+#endif
+zend_function_entry php_oci_lob_class_functions[] = {
+ PHP_FALIAS(load, oci_lob_load, arginfo_oci_lob_load_method)
+ PHP_FALIAS(tell, oci_lob_tell, arginfo_oci_lob_tell_method)
+ PHP_FALIAS(truncate, oci_lob_truncate, arginfo_oci_lob_truncate_method)
+ PHP_FALIAS(erase, oci_lob_erase, arginfo_oci_lob_erase_method)
+ PHP_FALIAS(flush, oci_lob_flush, arginfo_oci_lob_flush_method)
+ PHP_FALIAS(setbuffering,ocisetbufferinglob, arginfo_oci_lob_setbuffering_method)
+ PHP_FALIAS(getbuffering,ocigetbufferinglob, arginfo_oci_lob_getbuffering_method)
+ PHP_FALIAS(rewind, oci_lob_rewind, arginfo_oci_lob_rewind_method)
+ PHP_FALIAS(read, oci_lob_read, arginfo_oci_lob_read_method)
+ PHP_FALIAS(eof, oci_lob_eof, arginfo_oci_lob_eof_method)
+ PHP_FALIAS(seek, oci_lob_seek, arginfo_oci_lob_seek_method)
+ PHP_FALIAS(write, oci_lob_write, arginfo_oci_lob_write_method)
+ PHP_FALIAS(append, oci_lob_append, arginfo_oci_lob_append_method)
+ PHP_FALIAS(size, oci_lob_size, arginfo_oci_lob_size_method)
+ PHP_FALIAS(writetofile, oci_lob_export, arginfo_oci_lob_export_method)
+ PHP_FALIAS(export, oci_lob_export, arginfo_oci_lob_export_method)
+ PHP_FALIAS(import, oci_lob_import, arginfo_oci_lob_import_method)
+ PHP_FALIAS(writetemporary, oci_lob_write_temporary, arginfo_oci_lob_write_temporary_method)
+ PHP_FALIAS(close, oci_lob_close, arginfo_oci_lob_close_method)
+ PHP_FALIAS(save, oci_lob_save, arginfo_oci_lob_save_method)
+ PHP_FALIAS(savefile, oci_lob_import, arginfo_oci_lob_import_method)
+ PHP_FALIAS(free, oci_free_descriptor, arginfo_oci_free_descriptor_method)
+ {NULL,NULL,NULL}
+};
+
+static
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5)
+/* This "if" allows PECL builds from this file to be portable to older PHP releases */
+const
+#endif
+zend_function_entry php_oci_coll_class_functions[] = {
+ PHP_FALIAS(append, oci_collection_append, arginfo_oci_collection_append_method)
+ PHP_FALIAS(getelem, oci_collection_element_get, arginfo_oci_collection_element_get_method)
+ PHP_FALIAS(assignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign_method)
+ PHP_FALIAS(assign, oci_collection_assign, arginfo_oci_collection_assign_method)
+ PHP_FALIAS(size, oci_collection_size, arginfo_oci_collection_size_method)
+ PHP_FALIAS(max, oci_collection_max, arginfo_oci_collection_max_method)
+ PHP_FALIAS(trim, oci_collection_trim, arginfo_oci_collection_trim_method)
+ PHP_FALIAS(free, oci_free_collection, arginfo_oci_collection_free_method)
+ {NULL,NULL,NULL}
+};
+
+zend_module_entry oci8_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "oci8", /* extension name */
+ php_oci_functions, /* extension function list */
+ PHP_MINIT(oci), /* extension-wide startup function */
+ PHP_MSHUTDOWN(oci), /* extension-wide shutdown function */
+ PHP_RINIT(oci), /* per-request startup function */
+ PHP_RSHUTDOWN(oci), /* per-request shutdown function */
+ PHP_MINFO(oci), /* information function */
+ PHP_OCI8_VERSION,
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
+ /* This check allows PECL builds from this file to be portable to older PHP releases */
+ PHP_MODULE_GLOBALS(oci), /* globals descriptor */
+ PHP_GINIT(oci), /* globals ctor */
+ PHP_GSHUTDOWN(oci), /* globals dtor */
+ NULL, /* post deactivate */
+ STANDARD_MODULE_PROPERTIES_EX
+#else
+ STANDARD_MODULE_PROPERTIES
+#endif
+};
+/* }}} */
+
+/* {{{ PHP_INI */
+PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY( "oci8.max_persistent", "-1", PHP_INI_SYSTEM, ONUPDATELONGFUNC, max_persistent, zend_oci_globals, oci_globals)
+ STD_PHP_INI_ENTRY( "oci8.persistent_timeout", "-1", PHP_INI_SYSTEM, ONUPDATELONGFUNC, persistent_timeout, zend_oci_globals, oci_globals)
+ STD_PHP_INI_ENTRY( "oci8.ping_interval", "60", PHP_INI_SYSTEM, ONUPDATELONGFUNC, ping_interval, zend_oci_globals, oci_globals)
+ STD_PHP_INI_BOOLEAN("oci8.privileged_connect", "0", PHP_INI_SYSTEM, OnUpdateBool, privileged_connect, zend_oci_globals, oci_globals)
+ STD_PHP_INI_ENTRY( "oci8.statement_cache_size", "20", PHP_INI_SYSTEM, ONUPDATELONGFUNC, statement_cache_size, zend_oci_globals, oci_globals)
+ STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, ONUPDATELONGFUNC, default_prefetch, zend_oci_globals, oci_globals)
+ STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics", "0", PHP_INI_SYSTEM, OnUpdateBool, old_oci_close_semantics,zend_oci_globals, oci_globals)
+ STD_PHP_INI_ENTRY( "oci8.connection_class", "", PHP_INI_ALL, OnUpdateString, connection_class, zend_oci_globals, oci_globals)
+ STD_PHP_INI_BOOLEAN("oci8.events", "0", PHP_INI_SYSTEM, OnUpdateBool, events, zend_oci_globals, oci_globals)
+PHP_INI_END()
+/* }}} */
+
+/* {{{ startup, shutdown and info functions
+*/
+
+/* {{{ php_oci_init_global_handles()
+ *
+ * Initialize global handles only when they are needed
+ */
+static void php_oci_init_global_handles(TSRMLS_D)
+{
+ sword errstatus;
+ sb4 ora_error_code = 0;
+ text tmp_buf[PHP_OCI_ERRBUF_LEN];
+
+ errstatus = OCIEnvNlsCreate(&OCI_G(env), PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, 0, 0);
+
+ if (errstatus == OCI_ERROR) {
+#ifdef HAVE_OCI_INSTANT_CLIENT
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
+#else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
+#endif
+ OCI_G(env) = NULL;
+ OCI_G(err) = NULL;
+ return;
+ }
+
+ errstatus = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
+
+ if (errstatus == OCI_SUCCESS) {
+#if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11)
+ /* This fixes PECL bug 15988 (sqlnet.ora not being read). The
+ * root cause was fixed in Oracle 10.2.0.4 but there is no
+ * compile time method to check for that precise patch level,
+ * nor can it be guaranteed that runtime will use the same
+ * patch level the code was compiled with. So, we do this
+ * code for all non 11g versions.
+ */
+ OCICPool *cpoolh;
+ ub4 cpoolmode = 0x80000000; /* Pass invalid mode to OCIConnectionPoolCreate */
+ PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **) &cpoolh, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0));
+ PHP_OCI_CALL(OCIConnectionPoolCreate, (OCI_G(env), OCI_G(err), cpoolh, NULL, 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0, cpoolmode));
+ PHP_OCI_CALL(OCIConnectionPoolDestroy, (cpoolh, OCI_G(err), OCI_DEFAULT));
+ PHP_OCI_CALL(OCIHandleFree, (cpoolh, OCI_HTYPE_CPOOL));
+#endif
+ } else {
+ OCIErrorGet(OCI_G(env), (ub4)1, NULL, &ora_error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
+
+ if (ora_error_code) {
+ int tmp_buf_len = strlen((char *)tmp_buf);
+
+ if (tmp_buf_len > 0 && tmp_buf[tmp_buf_len - 1] == '\n') {
+ tmp_buf[tmp_buf_len - 1] = '\0';
+ }
+
+ if (errstatus == OCI_SUCCESS_WITH_INFO) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_SUCCESS_WITH_INFO: %s", tmp_buf);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Initialization error: OCI_ERROR: %s", tmp_buf);
+
+ OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
+
+ OCI_G(env) = NULL;
+ OCI_G(err) = NULL;
+ }
+ }
+ }
+} /* }}} */
+
+/* {{{ php_oci_cleanup_global_handles()
+ *
+ * Free global handles (if they were initialized before)
+ */
+static void php_oci_cleanup_global_handles(TSRMLS_D)
+{
+ if (OCI_G(err)) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ERROR));
+ OCI_G(err) = NULL;
+ }
+
+ if (OCI_G(env)) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV));
+ OCI_G(env) = NULL;
+ }
+} /* }}} */
+
+/* {{{ PHP_GINIT_FUNCTION
+ *
+ * Zerofill globals during module init
+ */
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
+/* This check allows PECL builds from this file to be portable to older PHP releases */
+static PHP_GINIT_FUNCTION(oci)
+#else
+static void php_oci_init_globals(zend_oci_globals *oci_globals TSRMLS_DC)
+#endif
+{
+ memset(oci_globals, 0, sizeof(zend_oci_globals));
+}
+/* }}} */
+
+/* {{{ PHP_GSHUTDOWN_FUNCTION
+ *
+ * Called for thread shutdown in ZTS, after module shutdown for non-ZTS
+ */
+/* This check allows PECL builds from this file to be portable to older PHP releases */
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
+static PHP_GSHUTDOWN_FUNCTION(oci)
+#else
+static void php_oci_shutdown_globals(zend_oci_globals *oci_globals TSRMLS_DC)
+#endif
+{
+ php_oci_cleanup_global_handles(TSRMLS_C);
+}
+/* }}} */
+
+PHP_MINIT_FUNCTION(oci)
+{
+ zend_class_entry oci_lob_class_entry;
+ zend_class_entry oci_coll_class_entry;
+
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
+ /* This check allows PECL builds from this file to be portable to older PHP releases */
+ /* this is handled by new globals management code */
+#else
+ ZEND_INIT_MODULE_GLOBALS(oci, php_oci_init_globals, php_oci_shutdown_globals);
+#endif
+ REGISTER_INI_ENTRIES();
+
+ le_statement = zend_register_list_destructors_ex(php_oci_statement_list_dtor, NULL, "oci8 statement", module_number);
+ le_connection = zend_register_list_destructors_ex(php_oci_connection_list_dtor, NULL, "oci8 connection", module_number);
+ le_pconnection = zend_register_list_destructors_ex(php_oci_pconnection_list_np_dtor, php_oci_pconnection_list_dtor, "oci8 persistent connection", module_number);
+ le_psessionpool = zend_register_list_destructors_ex(NULL, php_oci_spool_list_dtor, "oci8 persistent session pool", module_number);
+ le_descriptor = zend_register_list_destructors_ex(php_oci_descriptor_list_dtor, NULL, "oci8 descriptor", module_number);
+ le_collection = zend_register_list_destructors_ex(php_oci_collection_list_dtor, NULL, "oci8 collection", module_number);
+
+ INIT_CLASS_ENTRY(oci_lob_class_entry, "OCI-Lob", php_oci_lob_class_functions);
+ INIT_CLASS_ENTRY(oci_coll_class_entry, "OCI-Collection", php_oci_coll_class_functions);
+
+ oci_lob_class_entry_ptr = zend_register_internal_class(&oci_lob_class_entry TSRMLS_CC);
+ oci_coll_class_entry_ptr = zend_register_internal_class(&oci_coll_class_entry TSRMLS_CC);
+
+/* thies@thieso.net 990203 i do not think that we will need all of them - just in here for completeness for now! */
+ REGISTER_LONG_CONSTANT("OCI_DEFAULT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_SYSOPER",OCI_SYSOPER, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_SYSDBA",OCI_SYSDBA, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_CRED_EXT",PHP_OCI_CRED_EXT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_DESCRIBE_ONLY",OCI_DESCRIBE_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_COMMIT_ON_SUCCESS",OCI_COMMIT_ON_SUCCESS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_NO_AUTO_COMMIT",OCI_DEFAULT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_EXACT_FETCH",OCI_EXACT_FETCH, CONST_CS | CONST_PERSISTENT);
+
+/* for $LOB->seek() */
+ REGISTER_LONG_CONSTANT("OCI_SEEK_SET",PHP_OCI_SEEK_SET, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_SEEK_CUR",PHP_OCI_SEEK_CUR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_SEEK_END",PHP_OCI_SEEK_END, CONST_CS | CONST_PERSISTENT);
+
+/* for $LOB->flush() */
+ REGISTER_LONG_CONSTANT("OCI_LOB_BUFFER_FREE",OCI_LOB_BUFFER_FREE, CONST_CS | CONST_PERSISTENT);
+
+/* for OCIBindByName (real "oci" names + short "php" names */
+ REGISTER_LONG_CONSTANT("SQLT_BFILEE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_RDD",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_RSET",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_AFC",SQLT_AFC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_CHR",SQLT_CHR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_VCS",SQLT_VCS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_AVC",SQLT_AVC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_STR",SQLT_STR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_LVC",SQLT_LVC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_FLT",SQLT_FLT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_UIN",SQLT_UIN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_LNG",SQLT_LNG, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_LBI",SQLT_LBI, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_ODT",SQLT_ODT, CONST_CS | CONST_PERSISTENT);
+#if defined(HAVE_OCI_INSTANT_CLIENT) || (defined(OCI_MAJOR_VERSION) && OCI_MAJOR_VERSION >= 10)
+ REGISTER_LONG_CONSTANT("SQLT_BDOUBLE",SQLT_BDOUBLE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_BFLOAT",SQLT_BFLOAT, CONST_CS | CONST_PERSISTENT);
+#endif
+
+ REGISTER_LONG_CONSTANT("OCI_B_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SQLT_NTY",SQLT_NTY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_STRING_CONSTANT("OCI_SYSDATE","SYSDATE", CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("OCI_B_BFILE",SQLT_BFILEE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_B_CFILEE",SQLT_CFILEE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_B_CLOB",SQLT_CLOB, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_B_BLOB",SQLT_BLOB, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_B_ROWID",SQLT_RDD, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_B_CURSOR",SQLT_RSET, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_B_BIN",SQLT_BIN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_B_INT",SQLT_INT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_B_NUM",SQLT_NUM, CONST_CS | CONST_PERSISTENT);
+
+/* for OCIFetchStatement */
+ REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_COLUMN", PHP_OCI_FETCHSTATEMENT_BY_COLUMN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_FETCHSTATEMENT_BY_ROW", PHP_OCI_FETCHSTATEMENT_BY_ROW, CONST_CS | CONST_PERSISTENT);
+
+/* for OCIFetchInto & OCIResult */
+ REGISTER_LONG_CONSTANT("OCI_ASSOC",PHP_OCI_ASSOC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_NUM",PHP_OCI_NUM, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_BOTH",PHP_OCI_BOTH, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_RETURN_NULLS",PHP_OCI_RETURN_NULLS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_RETURN_LOBS",PHP_OCI_RETURN_LOBS, CONST_CS | CONST_PERSISTENT);
+
+/* for OCINewDescriptor (real "oci" names + short "php" names */
+ REGISTER_LONG_CONSTANT("OCI_DTYPE_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_DTYPE_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_DTYPE_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("OCI_D_FILE",OCI_DTYPE_FILE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_D_LOB",OCI_DTYPE_LOB, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_D_ROWID",OCI_DTYPE_ROWID, CONST_CS | CONST_PERSISTENT);
+
+/* for OCIWriteTemporaryLob */
+ REGISTER_LONG_CONSTANT("OCI_TEMP_CLOB",OCI_TEMP_CLOB, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OCI_TEMP_BLOB",OCI_TEMP_BLOB, CONST_CS | CONST_PERSISTENT);
+
+ return SUCCESS;
+}
+
+PHP_RINIT_FUNCTION(oci)
+{
+ OCI_G(debug_mode) = 0; /* start "fresh" */
+ OCI_G(num_links) = OCI_G(num_persistent);
+ OCI_G(errcode) = 0;
+ OCI_G(edition) = NULL;
+
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(oci)
+{
+/* Work around PHP_GSHUTDOWN_FUNCTION not being called in older versions of PHP */
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) || (PHP_MAJOR_VERSION < 5)
+#ifndef ZTS
+ php_oci_cleanup_global_handles(TSRMLS_C);
+#endif
+#endif
+
+ OCI_G(shutdown) = 1;
+
+ UNREGISTER_INI_ENTRIES();
+
+ return SUCCESS;
+}
+
+PHP_RSHUTDOWN_FUNCTION(oci)
+{
+ /* Check persistent connections and do the necessary actions if needed. If persistent_helper is
+ * unable to process a pconnection because of a refcount, the processing would happen from
+ * np-destructor which is called when refcount goes to zero - php_oci_pconnection_list_np_dtor
+ */
+ zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
+
+ if (OCI_G(edition)) {
+ efree(OCI_G(edition));
+ }
+
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(oci)
+{
+ char buf[32];
+
+ php_info_print_table_start();
+ php_info_print_table_row(2, "OCI8 Support", "enabled");
+ php_info_print_table_row(2, "Version", PHP_OCI8_VERSION);
+ php_info_print_table_row(2, "Revision", "$Revision$");
+
+ snprintf(buf, sizeof(buf), "%ld", OCI_G(num_persistent));
+ php_info_print_table_row(2, "Active Persistent Connections", buf);
+ snprintf(buf, sizeof(buf), "%ld", OCI_G(num_links));
+ php_info_print_table_row(2, "Active Connections", buf);
+
+#if defined(OCI_MAJOR_VERSION) && defined(OCI_MINOR_VERSION)
+ snprintf(buf, sizeof(buf), "%d.%d", OCI_MAJOR_VERSION, OCI_MINOR_VERSION);
+#elif defined(PHP_OCI8_ORACLE_VERSION)
+ snprintf(buf, sizeof(buf), "%s", PHP_OCI8_ORACLE_VERSION);
+#else
+ snprintf(buf, sizeof(buf), "Unknown");
+#endif
+#if defined(HAVE_OCI_INSTANT_CLIENT)
+ php_info_print_table_row(2, "Oracle Instant Client Version", buf);
+#else
+ php_info_print_table_row(2, "Oracle Version", buf);
+#endif
+
+#if !defined(PHP_WIN32) && !defined(HAVE_OCI_INSTANT_CLIENT)
+#if defined(PHP_OCI8_DEF_DIR)
+ php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_OCI8_DEF_DIR);
+#endif
+#if defined(PHP_OCI8_DEF_SHARED_LIBADD)
+ php_info_print_table_row(2, "Libraries Used", PHP_OCI8_DEF_SHARED_LIBADD);
+#endif
+#endif
+
+ php_info_print_table_row(2, "Temporary Lob support", "enabled");
+ php_info_print_table_row(2, "Collections support", "enabled");
+ php_info_print_table_end();
+ DISPLAY_INI_ENTRIES();
+}
+/* }}} */
+
+/* list destructors {{{ */
+
+/* {{{ php_oci_connection_list_dtor()
+ *
+ * Non-persistent connection destructor
+ */
+static void php_oci_connection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
+{
+ php_oci_connection *connection = (php_oci_connection *)entry->ptr;
+
+ if (connection) {
+ php_oci_connection_close(connection TSRMLS_CC);
+ OCI_G(num_links)--;
+ }
+} /* }}} */
+
+/* {{{ php_oci_pconnection_list_dtor()
+ *
+ * Persistent connection destructor
+ */
+static void php_oci_pconnection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
+{
+ php_oci_connection *connection = (php_oci_connection *)entry->ptr;
+
+ if (connection) {
+ php_oci_connection_close(connection TSRMLS_CC);
+ OCI_G(num_persistent)--;
+ OCI_G(num_links)--;
+ }
+} /* }}} */
+
+/* {{{ php_oci_pconnection_list_np_dtor()
+ *
+ * Non-Persistent destructor for persistent connection - This gets invoked when
+ * the refcount of this goes to zero in the regular list
+ */
+static void php_oci_pconnection_list_np_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
+{
+ php_oci_connection *connection = (php_oci_connection *)entry->ptr;
+ zend_rsrc_list_entry *le;
+
+ /*
+ * We cannot get connection as NULL or as a stub in this function. This is the function that
+ * turns a pconnection to a stub
+ *
+ * If oci_password_change() changed the password of a persistent connection, close the
+ * connection and remove it from the persistent connection cache. This means subsequent scripts
+ * will be prevented from being able to present the old (now invalid) password to a usable
+ * connection to the database; they must use the new password.
+ *
+ * Check for conditions that warrant removal of the hash entry
+ */
+
+ if (!connection->is_open ||
+ connection->passwd_changed ||
+ (PG(connection_status) & PHP_CONNECTION_TIMEOUT) ||
+ OCI_G(in_call)) {
+
+ /* Remove the hash entry if present */
+ if ((zend_hash_find(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void **) &le)== SUCCESS) && (le->type == le_pconnection) && (le->ptr == connection)) {
+ zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
+ }
+ else {
+ php_oci_connection_close(connection TSRMLS_CC);
+ OCI_G(num_persistent)--;
+ }
+
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG L1: np_dtor cleaning up: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ }
+ }
+ else {
+ /*
+ * Release the connection to underlying pool. We do this unconditionally so that
+ * out-of-scope pconnects are now consistent with oci_close and out-of-scope new connect
+ * semantics. With the PECL OCI 1.3.x extensions, we release pconnections when oci_close
+ * takes the refcount to zero.
+ *
+ * If oci_old_close_semantics is set, we artifically bump up the refcount and decremented
+ * only at request shutdown.
+ */
+ php_oci_connection_release(connection TSRMLS_CC);
+
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG L1: np_dtor releasing: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ }
+ }
+} /* }}} */
+
+/* {{{ php_oci_statement_list_dtor()
+ *
+ * Statement destructor
+ */
+static void php_oci_statement_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
+{
+ php_oci_statement *statement = (php_oci_statement *)entry->ptr;
+ php_oci_statement_free(statement TSRMLS_CC);
+} /* }}} */
+
+/* {{{ php_oci_descriptor_list_dtor()
+ *
+ * Descriptor destructor
+ */
+static void php_oci_descriptor_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
+{
+ php_oci_descriptor *descriptor = (php_oci_descriptor *)entry->ptr;
+ php_oci_lob_free(descriptor TSRMLS_CC);
+} /* }}} */
+
+/* {{{ php_oci_collection_list_dtor()
+ *
+ * Collection destructor
+ */
+static void php_oci_collection_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
+{
+ php_oci_collection *collection = (php_oci_collection *)entry->ptr;
+ php_oci_collection_close(collection TSRMLS_CC);
+} /* }}} */
+
+/* }}} */
+
+/* Hash Destructors {{{ */
+
+/* {{{ php_oci_define_hash_dtor()
+ *
+ * Define hash destructor
+ */
+void php_oci_define_hash_dtor(void *data)
+{
+ php_oci_define *define = (php_oci_define *) data;
+
+ zval_ptr_dtor(&define->zval);
+
+ if (define->name) {
+ efree(define->name);
+ define->name = NULL;
+ }
+}
+/* }}} */
+
+/* {{{ php_oci_bind_hash_dtor()
+ *
+ * Bind hash destructor
+ */
+void php_oci_bind_hash_dtor(void *data)
+{
+ php_oci_bind *bind = (php_oci_bind *) data;
+
+ if (bind->array.elements) {
+ efree(bind->array.elements);
+ }
+
+ if (bind->array.element_lengths) {
+ efree(bind->array.element_lengths);
+ }
+
+ if (bind->array.indicators) {
+ efree(bind->array.indicators);
+ }
+
+ zval_ptr_dtor(&bind->zval);
+}
+/* }}} */
+
+/* {{{ php_oci_column_hash_dtor()
+ *
+ * Column hash destructor
+ */
+void php_oci_column_hash_dtor(void *data)
+{
+ php_oci_out_column *column = (php_oci_out_column *) data;
+ TSRMLS_FETCH();
+
+ if (column->stmtid) {
+ zend_list_delete(column->stmtid);
+ }
+
+ if (column->is_descr) {
+ zend_list_delete(column->descid);
+ }
+
+ if (column->data) {
+ efree(column->data);
+ }
+
+ if (column->name) {
+ efree(column->name);
+ }
+}
+/* }}} */
+
+/* {{{ php_oci_descriptor_flush_hash_dtor()
+ *
+ * Flush descriptors on commit
+ */
+void php_oci_descriptor_flush_hash_dtor(void *data)
+{
+ php_oci_descriptor *descriptor = *(php_oci_descriptor **)data;
+ TSRMLS_FETCH();
+
+ if (descriptor && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED && (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE)) {
+ php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
+ descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
+ }
+ data = NULL;
+}
+/* }}} */
+
+/* }}} */
+
+/* {{{ php_oci_connection_descriptors_free()
+ *
+ * Free descriptors for a connection
+ */
+void php_oci_connection_descriptors_free(php_oci_connection *connection TSRMLS_DC)
+{
+ zend_hash_destroy(connection->descriptors);
+ efree(connection->descriptors);
+ connection->descriptors = NULL;
+ connection->descriptor_count = 0;
+}
+/* }}} */
+
+
+/* {{{ php_oci_error()
+ *
+ * Fetch & print out error message if we get an error
+ * Returns an Oracle error number
+ */
+sb4 php_oci_error(OCIError *err_p, sword status TSRMLS_DC)
+{
+ text *errbuf = (text *)NULL;
+ sb4 errcode = 0;
+
+ switch (status) {
+ case OCI_SUCCESS:
+ break;
+ case OCI_SUCCESS_WITH_INFO:
+ errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
+ if (errbuf) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: %s", errbuf);
+ efree(errbuf);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SUCCESS_WITH_INFO: failed to fetch error message");
+ }
+ break;
+ case OCI_NEED_DATA:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NEED_DATA");
+ break;
+ case OCI_NO_DATA:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NO_DATA");
+ errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
+ if (errbuf) {
+ efree(errbuf);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_NO_DATA: failed to fetch error message");
+ }
+ break;
+ case OCI_ERROR:
+ errcode = php_oci_fetch_errmsg(err_p, &errbuf TSRMLS_CC);
+ if (errbuf) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf);
+ efree(errbuf);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to fetch error message");
+ }
+ break;
+ case OCI_INVALID_HANDLE:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_INVALID_HANDLE");
+ break;
+ case OCI_STILL_EXECUTING:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_STILL_EXECUTING");
+ break;
+ case OCI_CONTINUE:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CONTINUE");
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown OCI error code: %d", status);
+ break;
+ }
+ return errcode;
+}
+/* }}} */
+
+/* {{{ php_oci_fetch_errmsg()
+ *
+ * Fetch error message into the buffer from the error handle provided
+ */
+sb4 php_oci_fetch_errmsg(OCIError *error_handle, text **error_buf TSRMLS_DC)
+{
+ sb4 error_code = 0;
+ text err_buf[PHP_OCI_ERRBUF_LEN];
+
+ memset(err_buf, 0, sizeof(err_buf));
+ PHP_OCI_CALL(OCIErrorGet, (error_handle, (ub4)1, NULL, &error_code, err_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR));
+
+ if (error_code) {
+ int err_buf_len = strlen((char *)err_buf);
+
+ if (err_buf_len && err_buf[err_buf_len - 1] == '\n') {
+ err_buf[err_buf_len - 1] = '\0';
+ }
+ if (err_buf_len && error_buf) {
+ *error_buf = NULL;
+ *error_buf = (text *)estrndup((char *)err_buf, err_buf_len);
+ }
+ }
+ return error_code;
+} /* }}} */
+
+/* {{{ php_oci_fetch_sqltext_offset()
+ *
+ * Compute offset in the SQL statement
+ */
+int php_oci_fetch_sqltext_offset(php_oci_statement *statement, text **sqltext, ub2 *error_offset TSRMLS_DC)
+{
+ sword errstatus;
+
+ *sqltext = NULL;
+ *error_offset = 0;
+ PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *) sqltext, (ub4 *)0, OCI_ATTR_STATEMENT, statement->err));
+
+ if (errstatus != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(errstatus, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)error_offset, (ub4 *)0, OCI_ATTR_PARSE_ERROR_OFFSET, statement->err));
+
+ if (errstatus != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, errstatus TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_do_connect()
+ *
+ * Connect wrapper
+ */
+void php_oci_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent, int exclusive)
+{
+ php_oci_connection *connection;
+ char *username, *password;
+ char *dbname = NULL, *charset = NULL;
+ int username_len = 0, password_len = 0;
+ int dbname_len = 0, charset_len = 0;
+ long session_mode = OCI_DEFAULT;
+
+ /* if a fourth parameter is handed over, it is the charset identifier (but is only used in Oracle 9i+) */
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ssl", &username, &username_len, &password, &password_len, &dbname, &dbname_len, &charset, &charset_len, &session_mode) == FAILURE) {
+ return;
+ }
+
+ if (!charset_len) {
+ charset = NULL;
+ }
+
+ connection = php_oci_do_connect_ex(username, username_len, password, password_len, NULL, 0, dbname, dbname_len, charset, session_mode, persistent, exclusive TSRMLS_CC);
+
+ if (!connection) {
+ RETURN_FALSE;
+ }
+ RETURN_RESOURCE(connection->rsrc_id);
+
+} /* }}} */
+
+/* {{{ php_oci_do_connect_ex()
+ *
+ * The real connect function. Allocates all the resources needed, establishes the connection and
+ * returns the result handle (or NULL)
+ */
+php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC)
+{
+ zend_rsrc_list_entry *le;
+ zend_rsrc_list_entry new_le;
+ php_oci_connection *connection = NULL;
+ smart_str hashed_details = {0};
+ time_t timestamp;
+ php_oci_spool *session_pool = NULL;
+ zend_bool use_spool = 1; /* Default is to use client-side session pool */
+ zend_bool ping_done = 0;
+
+ ub2 charsetid = 0;
+ ub2 charsetid_nls_lang = 0;
+
+ if (session_mode & ~(OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid session mode specified (%ld)", session_mode);
+ return NULL;
+ }
+ if (session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) {
+ if ((session_mode & OCI_SYSOPER) && (session_mode & OCI_SYSDBA)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_SYSDBA and OCI_SYSOPER cannot be used together");
+ return NULL;
+ }
+ if (session_mode & PHP_OCI_CRED_EXT) {
+#ifdef PHP_WIN32
+ /* Disable external authentication on Windows as Impersonation is not yet handled.
+ * TODO: Re-enable this once OCI provides capability.
+ */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "External Authentication is not supported on Windows");
+ return NULL;
+#endif
+ if (username_len != 1 || username[0] != '/' || password_len != 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_CRED_EXT can only be used with a username of \"/\" and a NULL password");
+ return NULL;
+ }
+ }
+ if (session_mode & (OCI_SYSOPER | OCI_SYSDBA)) {
+ /* Increase security by not caching privileged oci_pconnect() connections. The
+ * connection becomes equivalent to oci_connect() or oci_new_connect().
+ */
+ persistent = 0;
+ if (!OCI_G(privileged_connect)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA");
+ return NULL;
+ }
+ /* Disable privileged connections in Safe Mode (N.b. safe mode has been removed in PHP
+ * 6 anyway)
+ */
+ if (PG(safe_mode)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Privileged connect is disabled in Safe Mode");
+ return NULL;
+ }
+ }
+ }
+
+ /* Initialize global handles if they weren't initialized before */
+ if (OCI_G(env) == NULL) {
+ php_oci_init_global_handles(TSRMLS_C);
+ if (OCI_G(env) == NULL) {
+ return NULL;
+ }
+ }
+
+ /* We cannot use the new session create logic (OCISessionGet from
+ * client-side session pool) when privileged connect or password
+ * change is attempted or OCI_CRED_EXT mode is specified.
+ * TODO: Re-enable this when OCI provides support.
+ */
+ if ((session_mode & (OCI_SYSOPER | OCI_SYSDBA | PHP_OCI_CRED_EXT)) || (new_password_len)) {
+ use_spool = 0;
+ }
+
+ smart_str_appendl_ex(&hashed_details, "oci8***", sizeof("oci8***") - 1, 0);
+ smart_str_appendl_ex(&hashed_details, username, username_len, 0);
+ smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
+
+ /* DRCP: connection_class is an attribute of a connection */
+ if (OCI_G(connection_class)){
+ smart_str_appendl_ex(&hashed_details, OCI_G(connection_class), strlen(OCI_G(connection_class)), 0);
+ }
+ smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
+
+ /* Add edition attribute to the hash */
+ if (OCI_G(edition)){
+ smart_str_appendl_ex(&hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
+ }
+ smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
+
+ if (password_len) {
+ ulong password_hash;
+ password_hash = zend_inline_hash_func(password, password_len);
+ smart_str_append_unsigned_ex(&hashed_details, password_hash, 0);
+ }
+ smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
+
+ if (dbname) {
+ smart_str_appendl_ex(&hashed_details, dbname, dbname_len, 0);
+ }
+ smart_str_appendl_ex(&hashed_details, "**", sizeof("**") - 1, 0);
+
+ if (charset && *charset) {
+ PHP_OCI_CALL_RETURN(charsetid, OCINlsCharSetNameToId, (OCI_G(env), (CONST oratext *)charset));
+ if (!charsetid) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid character set name: %s", charset);
+ } else {
+ smart_str_append_unsigned_ex(&hashed_details, charsetid, 0);
+ }
+ }
+
+ /* use NLS_LANG if no or invalid charset specified */
+ if (!charsetid) {
+ size_t rsize = 0;
+ sword result;
+
+ PHP_OCI_CALL_RETURN(result, OCINlsEnvironmentVariableGet, (&charsetid_nls_lang, 0, OCI_NLS_CHARSET_ID, 0, &rsize));
+ if (result != OCI_SUCCESS) {
+ charsetid_nls_lang = 0;
+ }
+ smart_str_append_unsigned_ex(&hashed_details, charsetid_nls_lang, 0);
+ }
+
+ timestamp = time(NULL);
+
+ smart_str_append_unsigned_ex(&hashed_details, session_mode, 0);
+ smart_str_0(&hashed_details);
+
+ /* make it lowercase */
+ php_strtolower(hashed_details.c, hashed_details.len);
+
+ if (!exclusive && !new_password) {
+ zend_bool found = 0;
+
+ if (persistent && zend_hash_find(&EG(persistent_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
+ found = 1;
+ /* found */
+ if (le->type == le_pconnection) {
+ connection = (php_oci_connection *)le->ptr;
+ }
+ } else if (!persistent && zend_hash_find(&EG(regular_list), hashed_details.c, hashed_details.len+1, (void **) &le) == SUCCESS) {
+ found = 1;
+ if (le->type == le_index_ptr) {
+ int type, link;
+ void *ptr;
+
+ link = (int) le->ptr;
+ ptr = zend_list_find(link,&type);
+ if (ptr && (type == le_connection)) {
+ connection = (php_oci_connection *)ptr;
+ }
+ }
+ }
+
+ /* Debug statements {{{ */
+ if (OCI_G(debug_mode)) {
+ if (connection && connection->is_stub) {
+ php_printf ("OCI8 DEBUG L1: Got a cached stub: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ } else if (connection) {
+ php_printf ("OCI8 DEBUG L1: Got a cached connection: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ } else {
+ php_printf ("OCI8 DEBUG L1: Got NO cached connection at (%s:%d) \n", __FILE__, __LINE__);
+ }
+ } /* }}} */
+
+ /* If we got a pconnection stub, then 'load'(OCISessionGet) the real connection from its
+ * private spool A connection is a stub if it is only a cached structure and the real
+ * connection is released to its underlying private session pool. We currently do not have
+ * stub support for non-persistent conns.
+ *
+ * TODO: put in negative code for non-persistent stubs
+ */
+ if (connection && connection->is_persistent && connection->is_stub) {
+ if (php_oci_create_session(connection, NULL, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
+ smart_str_free_ex(&hashed_details, 0);
+ zend_hash_del(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1);
+
+ return NULL;
+ }
+ /* We do the ping in php_oci_create_session, no need to ping again below */
+ ping_done = 1;
+ }
+
+ if (connection) {
+ if (connection->is_open) {
+ /* found an open connection. now ping it */
+ if (connection->is_persistent) {
+ int rsrc_type;
+
+ /* Check connection liveness in the following order:
+ * 1) always check OCI_ATTR_SERVER_STATUS
+ * 2) see if it's time to ping it
+ * 3) ping it if needed
+ */
+ if (php_oci_connection_status(connection TSRMLS_CC)) {
+ /* Only ping if:
+ *
+ * 1) next_ping > 0, which means that ping_interval is not -1 (aka "Off")
+ *
+ * 2) current_timestamp > next_ping, which means "it's time to check if it's
+ * still alive"
+ */
+ if (!ping_done && (*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp)) && !php_oci_connection_ping(connection TSRMLS_CC)) {
+ /* server died */
+ } else {
+ php_oci_connection *tmp;
+
+ /* okay, the connection is open and the server is still alive */
+ connection->used_this_request = 1;
+ tmp = (php_oci_connection *)zend_list_find(connection->rsrc_id, &rsrc_type);
+
+ if (tmp != NULL && rsrc_type == le_pconnection && strlen(tmp->hash_key) == hashed_details.len &&
+ memcmp(tmp->hash_key, hashed_details.c, hashed_details.len) == 0 && zend_list_addref(connection->rsrc_id) == SUCCESS) {
+ /* do nothing */
+ } else {
+ connection->rsrc_id = zend_list_insert(connection, le_pconnection);
+ /* Persistent connections: For old close semantics we artificially
+ * bump up the refcount to prevent the non-persistent destructor
+ * from getting called until request shutdown. The refcount is
+ * decremented in the persistent helper
+ */
+ if (OCI_G(old_oci_close_semantics)) {
+ zend_list_addref(connection->rsrc_id);
+ }
+ }
+ smart_str_free_ex(&hashed_details, 0);
+ return connection;
+ }
+ }
+ /* server died */
+ } else {
+ /* we do not ping non-persistent connections */
+ smart_str_free_ex(&hashed_details, 0);
+ zend_list_addref(connection->rsrc_id);
+ return connection;
+ }
+ } /* is_open is true? */
+
+ /* Server died - connection not usable. The is_open=true can also fall through to here,
+ * if ping fails
+ */
+ if (persistent){
+ int rsrc_type;
+
+ connection->is_open = 0;
+ connection->used_this_request = 1;
+
+ /* We have to do a hash_del but need to preserve the resource if there is a positive
+ * refcount. Set the data pointer in the list entry to NULL
+ */
+ if (connection == zend_list_find(connection->rsrc_id, &rsrc_type) && rsrc_type == le_pconnection) {
+ le->ptr = NULL;
+ }
+
+ zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
+ } else {
+ /* We only remove the hash entry. The resource and the list entry with its pointer
+ * to the resource are still intact
+ */
+ zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
+ }
+
+ connection = NULL;
+ } else if (found) {
+ /* found something, but it's not a connection, delete it */
+ if (persistent) {
+ zend_hash_del(&EG(persistent_list), hashed_details.c, hashed_details.len+1);
+ } else {
+ zend_hash_del(&EG(regular_list), hashed_details.c, hashed_details.len+1);
+ }
+ }
+ }
+
+ /* Check if we have reached max_persistent. If so, try to remove a few timed-out connections. As
+ * a last resort, return a non-persistent connection.
+ */
+ if (persistent) {
+ zend_bool alloc_non_persistent = 0;
+
+ if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
+ /* try to find an idle connection and kill it */
+ zend_hash_apply(&EG(persistent_list), (apply_func_t) php_oci_persistent_helper TSRMLS_CC);
+
+ if (OCI_G(max_persistent) != -1 && OCI_G(num_persistent) >= OCI_G(max_persistent)) {
+ /* all persistent connactions are in use, fallback to non-persistent connection creation */
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Too many open persistent connections (%ld)", OCI_G(num_persistent));
+ alloc_non_persistent = 1;
+ }
+ }
+
+ if (alloc_non_persistent) {
+ connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
+ connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
+ connection->is_persistent = 0;
+ } else {
+ connection = (php_oci_connection *) calloc(1, sizeof(php_oci_connection));
+ connection->hash_key = zend_strndup(hashed_details.c, hashed_details.len);
+ connection->is_persistent = 1;
+ }
+ } else {
+ connection = (php_oci_connection *) ecalloc(1, sizeof(php_oci_connection));
+ connection->hash_key = estrndup(hashed_details.c, hashed_details.len);
+ connection->is_persistent = 0;
+ }
+
+ /* {{{ Get the session pool that suits this connection request from the persistent list. This
+ * step is only for non-persistent connections as persistent connections have private session
+ * pools. Non-persistent conns use shared session pool to allow for optimizations such as
+ * caching the physical connection (for DRCP) even when the non-persistent php connection is
+ * destroyed.
+ *
+ * TODO: Unconditionally do this once OCI provides extended OCISessionGet capability
+ */
+ if (use_spool && !connection->is_persistent) {
+ if ((session_pool = php_oci_get_spool(username, username_len, password, password_len, dbname, dbname_len, charsetid ? charsetid:charsetid_nls_lang TSRMLS_CC))==NULL)
+ {
+ php_oci_connection_close(connection TSRMLS_CC);
+ smart_str_free_ex(&hashed_details, 0);
+ return NULL;
+ }
+ } /* }}} */
+
+ connection->idle_expiry = (OCI_G(persistent_timeout) > 0) ? (timestamp + OCI_G(persistent_timeout)) : 0;
+
+ /* Mark password as unchanged by PHP during the duration of the database session */
+ connection->passwd_changed = 0;
+
+ smart_str_free_ex(&hashed_details, 0);
+
+ if (charsetid) {
+ connection->charset = charsetid;
+ } else {
+ connection->charset = charsetid_nls_lang;
+ }
+
+ /* Old session creation semantics when session pool cannot be used Eg: privileged
+ * connect/password change
+ */
+ if (!use_spool) {
+ if (php_oci_old_create_session(connection, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
+ php_oci_connection_close(connection TSRMLS_CC);
+ return NULL;
+ }
+ } else {
+ /* create using the client-side session pool */
+ if (php_oci_create_session(connection, session_pool, dbname, dbname_len, username, username_len, password, password_len, new_password, new_password_len, session_mode TSRMLS_CC)) {
+ php_oci_connection_close(connection TSRMLS_CC);
+ return NULL;
+ }
+ }
+
+ /* Mark it as open */
+ connection->is_open = 1;
+
+ /* add to the appropriate hash */
+ if (connection->is_persistent) {
+ new_le.ptr = connection;
+ new_le.type = le_pconnection;
+ connection->used_this_request = 1;
+ connection->rsrc_id = zend_list_insert(connection, le_pconnection);
+
+ /* Persistent connections: For old close semantics we artificially bump up the refcount to
+ * prevent the non-persistent destructor from getting called until request shutdown. The
+ * refcount is decremented in the persistent helper
+ */
+ if (OCI_G(old_oci_close_semantics)) {
+ zend_list_addref(connection->rsrc_id);
+ }
+ zend_hash_update(&EG(persistent_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
+ OCI_G(num_persistent)++;
+ OCI_G(num_links)++;
+ } else if (!exclusive) {
+ connection->rsrc_id = zend_list_insert(connection, le_connection);
+ new_le.ptr = (void *)connection->rsrc_id;
+ new_le.type = le_index_ptr;
+ zend_hash_update(&EG(regular_list), connection->hash_key, strlen(connection->hash_key)+1, (void *)&new_le, sizeof(zend_rsrc_list_entry), NULL);
+ OCI_G(num_links)++;
+ } else {
+ connection->rsrc_id = zend_list_insert(connection, le_connection);
+ OCI_G(num_links)++;
+ }
+
+ /* Debug statements {{{ */
+ if (OCI_G(debug_mode)) {
+ if (connection->is_persistent) {
+ php_printf ("OCI8 DEBUG L1: New Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ } else {
+ php_printf ("OCI8 DEBUG L1: New Non-Persistent Connection address: (%p) at (%s:%d) \n", connection, __FILE__, __LINE__);
+ }
+ php_printf ("OCI8 DEBUG L1: num_persistent=(%ld), num_links=(%ld) at (%s:%d) \n", OCI_G(num_persistent), OCI_G(num_links), __FILE__, __LINE__);
+ } /* }}} */
+
+ return connection;
+}
+/* }}} */
+
+/* {{{ php_oci_connection_ping()
+ *
+ * Ping connection. Uses OCIPing() or OCIServerVersion() depending on the Oracle Client version
+ */
+static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC)
+{
+ /* Use OCIPing instead of OCIServerVersion. If OCIPing returns ORA-1010 (invalid OCI operation)
+ * such as from Pre-10.1 servers, the error is still from the server and we would have
+ * successfully performed a roundtrip and validated the connection. Use OCIServerVersion for
+ * Pre-10.2 clients
+ */
+#if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT));
+#else
+ char version[256];
+ /* use good old OCIServerVersion() */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX));
+#endif
+
+ if (OCI_G(errcode) == OCI_SUCCESS) {
+ return 1;
+ } else {
+ sb4 error_code = 0;
+ text tmp_buf[PHP_OCI_ERRBUF_LEN];
+
+ /* Treat ORA-1010 as a successful Ping */
+ OCIErrorGet(OCI_G(err), (ub4)1, NULL, &error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
+ if (error_code == 1010) {
+ return 1;
+ }
+ }
+
+ /* ignore errors here, just return failure
+ * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_oci_connection_status()
+ *
+ * Check connection status (pre-ping check)
+ */
+static int php_oci_connection_status(php_oci_connection *connection TSRMLS_DC)
+{
+ ub4 ss = 0;
+
+ /* get OCI_ATTR_SERVER_STATUS */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->server, OCI_HTYPE_SERVER, (dvoid *)&ss, (ub4 *)0, OCI_ATTR_SERVER_STATUS, OCI_G(err)));
+
+ if (OCI_G(errcode) == OCI_SUCCESS && ss == OCI_SERVER_NORMAL) {
+ return 1;
+ }
+
+ /* ignore errors here, just return failure
+ * php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC); */
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_oci_connection_rollback()
+ *
+ * Rollback connection
+ */
+int php_oci_connection_rollback(php_oci_connection *connection TSRMLS_DC)
+{
+ PHP_OCI_CALL_RETURN(connection->errcode, OCITransRollback, (connection->svc, connection->err, (ub4) 0));
+ connection->needs_commit = 0;
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_connection_commit()
+ *
+ * Commit connection
+ */
+int php_oci_connection_commit(php_oci_connection *connection TSRMLS_DC)
+{
+ PHP_OCI_CALL_RETURN(connection->errcode, OCITransCommit, (connection->svc, connection->err, (ub4) 0));
+ connection->needs_commit = 0;
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_connection_close()
+ *
+ * Close the connection and free all its resources
+ */
+static int php_oci_connection_close(php_oci_connection *connection TSRMLS_DC)
+{
+ int result = 0;
+ zend_bool in_call_save = OCI_G(in_call);
+
+ if (!connection->is_stub) {
+ /* Release resources associated with connection */
+ php_oci_connection_release(connection TSRMLS_CC);
+ }
+
+ if (!connection->using_spool && connection->svc) {
+ PHP_OCI_CALL(OCISessionEnd, (connection->svc, connection->err, connection->session, (ub4) 0));
+ }
+
+ if (connection->err) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->err, (ub4) OCI_HTYPE_ERROR));
+ }
+ if (connection->authinfo) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->authinfo, (ub4) OCI_HTYPE_AUTHINFO));
+ }
+
+ /* No Handlefrees for session pool connections */
+ if (!connection->using_spool) {
+ if (connection->session) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->session, OCI_HTYPE_SESSION));
+ }
+
+ if (connection->is_attached) {
+ PHP_OCI_CALL(OCIServerDetach, (connection->server, OCI_G(err), OCI_DEFAULT));
+ }
+
+ if (connection->svc) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
+ }
+
+ if (connection->server) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->server, (ub4) OCI_HTYPE_SERVER));
+ }
+
+ if (connection->env) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
+ }
+ } else if (connection->private_spool) {
+ /* Keep this as the last member to be freed, as there are dependencies
+ * (like env) on the session pool
+ */
+ php_oci_spool_close(connection->private_spool TSRMLS_CC);
+ }
+
+ if (connection->is_persistent) {
+ if (connection->hash_key) {
+ free(connection->hash_key);
+ }
+ free(connection);
+ } else {
+ if (connection->hash_key) {
+ efree(connection->hash_key);
+ }
+ efree(connection);
+ }
+ connection = NULL;
+ OCI_G(in_call) = in_call_save;
+ return result;
+} /* }}} */
+
+/* {{{ php_oci_connection_release()
+ *
+ * Release the connection's resources. This involves freeing descriptors and rolling back
+ * transactions, setting timeout-related parameters etc. For session-pool using connections, the
+ * underlying connection is released to its session pool.
+ */
+int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC)
+{
+ int result = 0;
+ zend_bool in_call_save = OCI_G(in_call);
+ time_t timestamp = time(NULL);
+
+ if (connection->is_stub) {
+ return 0;
+ }
+
+ if (connection->descriptors) {
+ php_oci_connection_descriptors_free(connection TSRMLS_CC);
+ }
+
+ if (connection->svc) {
+ /* rollback outstanding transactions */
+ if (connection->needs_commit) {
+ if (php_oci_connection_rollback(connection TSRMLS_CC)) {
+ /* rollback failed */
+ result = 1;
+ }
+ }
+ }
+
+ if (OCI_G(persistent_timeout) > 0) {
+ connection->idle_expiry = timestamp + OCI_G(persistent_timeout);
+ }
+
+ /* We may have half-cooked connections to clean up */
+ if (connection->next_pingp) {
+ if (OCI_G(ping_interval) >= 0) {
+ *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
+ } else {
+ /* ping_interval is -1 */
+ *(connection->next_pingp) = 0;
+ }
+ }
+
+ /* Release the session (stubs are filtered out at the beginning)*/
+ if (connection->using_spool) {
+ ub4 rlsMode = OCI_DEFAULT;
+
+ if (result) {
+ rlsMode |= OCI_SESSRLS_DROPSESS;
+ }
+
+ /* Sessions for non-persistent connections should be dropped. For 11 and above, the session
+ * pool has its own mechanism for doing so for purity NEW connections. We need to do so
+ * explicitly for 10.2 and earlier.
+ */
+#if (!(OCI_MAJOR_VERSION >= 11))
+ if (!connection->is_persistent) {
+ rlsMode |= OCI_SESSRLS_DROPSESS;
+ }
+#endif
+
+ if (connection->svc) {
+ PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,
+ 0, rlsMode));
+ }
+ /* It no longer has relation with the database session. However authinfo and env are
+ * cached
+ */
+ connection->svc = NULL;
+ connection->server = NULL;
+ connection->session = NULL;
+
+ connection->is_attached = connection->is_open = connection->needs_commit = connection->used_this_request = 0;
+ connection->is_stub = 1;
+
+ /* Cut the link between the connection structure and the time_t structure allocated within
+ * the OCI session
+ */
+ connection->next_pingp = NULL;
+ }
+
+ OCI_G(in_call) = in_call_save;
+ return result;
+} /* }}} */
+
+/* {{{ php_oci_password_change()
+ *
+ * Change password for the user with the username given
+ */
+int php_oci_password_change(php_oci_connection *connection, char *user, int user_len, char *pass_old, int pass_old_len, char *pass_new, int pass_new_len TSRMLS_DC)
+{
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIPasswordChange, (connection->svc, connection->err, (text *)user, user_len, (text *)pass_old, pass_old_len, (text *)pass_new, pass_new_len, OCI_DEFAULT));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ connection->passwd_changed = 1;
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_server_get_version()
+ *
+ * Get Oracle server version
+ */
+int php_oci_server_get_version(php_oci_connection *connection, char **version TSRMLS_DC)
+{
+ char version_buff[256];
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIServerVersion, (connection->svc, connection->err, (text *)version_buff, sizeof(version_buff), OCI_HTYPE_SVCCTX));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ *version = estrdup(version_buff);
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_column_to_zval()
+ *
+ * Convert php_oci_out_column struct into zval
+ */
+int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode TSRMLS_DC)
+{
+ php_oci_descriptor *descriptor;
+ ub4 lob_length;
+ int column_size;
+ char *lob_buffer;
+ int lob_fetch_status;
+
+ if (column->indicator == -1) { /* column is NULL */
+ ZVAL_NULL(value);
+ return 0;
+ }
+
+ if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
+ ZVAL_RESOURCE(value, column->stmtid);
+ zend_list_addref(column->stmtid);
+ } else if (column->is_descr) {
+
+ if (column->data_type != SQLT_RDD) {
+ int rsrc_type;
+
+ /* reset descriptor's length */
+ descriptor = (php_oci_descriptor *) zend_list_find(column->descid, &rsrc_type);
+
+ if (!descriptor || rsrc_type != le_descriptor) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find LOB descriptor #%d", column->descid);
+ return 1;
+ }
+
+ descriptor->lob_size = -1;
+ descriptor->lob_current_position = 0;
+ descriptor->buffering = 0;
+ }
+
+ if (column->data_type != SQLT_RDD && (mode & PHP_OCI_RETURN_LOBS)) {
+ /* PHP_OCI_RETURN_LOBS means that we want the content of the LOB back instead of the locator */
+
+ lob_fetch_status = php_oci_lob_read(descriptor, -1, 0, &lob_buffer, &lob_length TSRMLS_CC);
+ php_oci_temp_lob_close(descriptor TSRMLS_CC);
+ if (lob_fetch_status) {
+ ZVAL_FALSE(value);
+ return 1;
+ } else {
+ if (lob_length > 0) {
+ ZVAL_STRINGL(value, lob_buffer, lob_length, 0);
+ } else {
+ ZVAL_EMPTY_STRING(value);
+ }
+ return 0;
+ }
+ } else {
+ /* return the locator */
+ object_init_ex(value, oci_lob_class_entry_ptr);
+ add_property_resource(value, "descriptor", column->descid);
+ zend_list_addref(column->descid);
+ }
+ } else {
+ switch (column->retcode) {
+ case 0:
+ /* intact value */
+ if (column->piecewise) {
+ column_size = column->retlen4;
+ } else {
+ column_size = column->retlen;
+ }
+ break;
+
+ default:
+ ZVAL_FALSE(value);
+ return 0;
+ }
+
+ ZVAL_STRINGL(value, column->data, column_size, 1);
+ }
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_oci_fetch_row()
+ *
+ * Fetch the next row from the given statement
+ */
+void php_oci_fetch_row (INTERNAL_FUNCTION_PARAMETERS, int mode, int expected_args)
+{
+ zval *z_statement, *array;
+ php_oci_statement *statement;
+ php_oci_out_column *column;
+ ub4 nrows = 1;
+ int i;
+ long fetch_mode = 0;
+
+ if (expected_args > 2) {
+ /* only for ocifetchinto BC */
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|l", &z_statement, &array, &fetch_mode) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() == 2) {
+ fetch_mode = mode;
+ }
+ } else if (expected_args == 2) {
+ /* only for oci_fetch_array() */
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_statement, &fetch_mode) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() == 1) {
+ fetch_mode = mode;
+ }
+ } else {
+ /* for all oci_fetch_*() */
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
+ return;
+ }
+
+ fetch_mode = mode;
+ }
+
+ if (!(fetch_mode & PHP_OCI_NUM) && !(fetch_mode & PHP_OCI_ASSOC)) {
+ /* none of the modes present, use the default one */
+ if (mode & PHP_OCI_ASSOC) {
+ fetch_mode |= PHP_OCI_ASSOC;
+ }
+ if (mode & PHP_OCI_NUM) {
+ fetch_mode |= PHP_OCI_NUM;
+ }
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+
+ for (i = 0; i < statement->ncolumns; i++) {
+
+ column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+
+ if (column == NULL) {
+ continue;
+ }
+ if ((column->indicator == -1) && ((fetch_mode & PHP_OCI_RETURN_NULLS) == 0)) {
+ continue;
+ }
+
+ if (!(column->indicator == -1)) {
+ zval *element;
+
+ MAKE_STD_ZVAL(element);
+ php_oci_column_to_zval(column, element, fetch_mode TSRMLS_CC);
+
+ if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
+ add_index_zval(return_value, i, element);
+ }
+ if (fetch_mode & PHP_OCI_ASSOC) {
+ if (fetch_mode & PHP_OCI_NUM) {
+ Z_ADDREF_P(element);
+ }
+ add_assoc_zval(return_value, column->name, element);
+ }
+
+ } else {
+ if (fetch_mode & PHP_OCI_NUM || !(fetch_mode & PHP_OCI_ASSOC)) {
+ add_index_null(return_value, i);
+ }
+ if (fetch_mode & PHP_OCI_ASSOC) {
+ add_assoc_null(return_value, column->name);
+ }
+ }
+ }
+
+ if (expected_args > 2) {
+ /* Only for ocifetchinto BC. In all other cases we return array, not long */
+ REPLACE_ZVAL_VALUE(&array, return_value, 1); /* copy return_value to given reference */
+ zval_dtor(return_value);
+ RETURN_LONG(statement->ncolumns);
+ }
+}
+/* }}} */
+
+/* {{{ php_oci_persistent_helper()
+ *
+ * Helper function to close/rollback persistent connections at the end of request. A return value of
+ * 1 indicates that the connection is to be destroyed
+ */
+static int php_oci_persistent_helper(zend_rsrc_list_entry *le TSRMLS_DC)
+{
+ time_t timestamp;
+ php_oci_connection *connection;
+
+ timestamp = time(NULL);
+
+ /* Persistent connection stubs are also counted as they have private session pools */
+ if (le->type == le_pconnection) {
+ connection = (php_oci_connection *)le->ptr;
+
+ if (!connection->used_this_request && OCI_G(persistent_timeout) != -1) {
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG L1: persistent_helper processing for timeout: (%p stub=%d) at (%s:%d) \n", connection, connection->is_stub, __FILE__, __LINE__);
+ }
+ if (connection->idle_expiry < timestamp) {
+ /* connection has timed out */
+ return ZEND_HASH_APPLY_REMOVE;
+ }
+ }
+ }
+ return ZEND_HASH_APPLY_KEEP;
+} /* }}} */
+
+/* {{{ php_oci_create_spool()
+ *
+ * Create(alloc + Init) Session pool for the given dbname and charsetid
+ */
+static php_oci_spool *php_oci_create_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, char *hash_key, int hash_key_len, int charsetid TSRMLS_DC)
+{
+ php_oci_spool *session_pool = NULL;
+ zend_bool iserror = 0;
+ ub4 poolmode = OCI_DEFAULT; /* Mode to be passed to OCISessionPoolCreate */
+ OCIAuthInfo *spoolAuth = NULL;
+
+ /*Allocate sessionpool out of persistent memory */
+ session_pool = (php_oci_spool *) calloc(1, sizeof(php_oci_spool));
+
+ /* Populate key if passed */
+ if (hash_key_len) {
+ session_pool->spool_hash_key = zend_strndup(hash_key, hash_key_len);
+ }
+
+ /* Create the session pool's env */
+ if (!(session_pool->env = php_oci_create_env(charsetid TSRMLS_CC))) {
+ iserror = 1;
+ goto exit_create_spool;
+ }
+
+ /* Allocate the pool handle */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **) &session_pool->poolh, OCI_HTYPE_SPOOL, (size_t) 0, (dvoid **) 0));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ iserror = 1;
+ goto exit_create_spool;
+ }
+
+ /* Allocate the session pool error handle - This only for use in the destructor, as there is a
+ * generic bug which can free up the OCI_G(err) variable before destroying connections. We
+ * cannot use this for other roundtrip calls as there is no way the user can access this error
+ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, ((dvoid *) session_pool->env, (dvoid **)&(session_pool->err), (ub4) OCI_HTYPE_ERROR,(size_t) 0, (dvoid **) 0));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ iserror = 1;
+ goto exit_create_spool;
+ }
+
+/* Disable RLB as we mostly have single-connection pools */
+#if (OCI_MAJOR_VERSION > 10)
+ poolmode = OCI_SPC_NO_RLB | OCI_SPC_HOMOGENEOUS;
+#else
+ poolmode = OCI_SPC_HOMOGENEOUS;
+#endif
+
+#if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
+ /* Allocate auth handle for session pool {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (session_pool->env, (dvoid **)&(spoolAuth), OCI_HTYPE_AUTHINFO, 0, NULL));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ iserror = 1;
+ goto exit_create_spool;
+ } /* }}} */
+
+ /* Set the edition attribute on the auth handle {{{ */
+ if (OCI_G(edition)) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) OCI_G(edition), (ub4)(strlen(OCI_G(edition))), (ub4)OCI_ATTR_EDITION, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ iserror = 1;
+ goto exit_create_spool;
+ }
+ } /* }}} */
+
+ /* Set the driver name attribute on the auth handle {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ iserror = 1;
+ goto exit_create_spool;
+ } /* }}} */
+
+ /* Set the auth handle on the session pool {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) (session_pool->poolh),(ub4) OCI_HTYPE_SPOOL, (dvoid *) spoolAuth, (ub4)0, (ub4)OCI_ATTR_SPOOL_AUTH, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ iserror = 1;
+ goto exit_create_spool;
+ } /* }}} */
+#endif
+
+ /* Create the homogeneous session pool - We have different session pools for every different
+ * username, password, charset and dbname.
+ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionPoolCreate,(session_pool->env, OCI_G(err), session_pool->poolh, (OraText **)&session_pool->poolname, &session_pool->poolname_len, (OraText *)dbname, (ub4)dbname_len, 0, UB4MAXVAL, 1,(OraText *)username, (ub4)username_len, (OraText *)password,(ub4)password_len, poolmode));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ iserror = 1;
+ }
+
+exit_create_spool:
+ if (iserror && session_pool) {
+ php_oci_spool_close(session_pool TSRMLS_CC);
+ session_pool = NULL;
+ }
+
+ if (spoolAuth) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) spoolAuth, (ub4) OCI_HTYPE_AUTHINFO));
+ }
+
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG L1: create_spool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
+ }
+
+ return session_pool;
+} /* }}} */
+
+/* {{{ php_oci_get_spool()
+ *
+ * Get Session pool for the given dbname and charsetid from the persistent list. Function called for
+ * non-persistent connections.
+ */
+static php_oci_spool *php_oci_get_spool(char *username, int username_len, char *password, int password_len, char *dbname, int dbname_len, int charsetid TSRMLS_DC)
+{
+ smart_str spool_hashed_details = {0};
+ php_oci_spool *session_pool = NULL;
+ zend_rsrc_list_entry spool_le = {0};
+ zend_rsrc_list_entry *spool_out_le = NULL;
+ zend_bool iserror = 0;
+
+ /* Create the spool hash key {{{ */
+ smart_str_appendl_ex(&spool_hashed_details, "oci8spool***", sizeof("oci8spool***") - 1, 0);
+ smart_str_appendl_ex(&spool_hashed_details, username, username_len, 0);
+ smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
+ /* Add edition attribute to the hash */
+ if (OCI_G(edition)){
+ smart_str_appendl_ex(&spool_hashed_details, OCI_G(edition), strlen(OCI_G(edition)), 0);
+ }
+ smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
+ if (password_len) {
+ ulong password_hash;
+ password_hash = zend_inline_hash_func(password, password_len);
+ smart_str_append_unsigned_ex(&spool_hashed_details, password_hash, 0);
+ }
+ smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
+
+ if (dbname_len) {
+ smart_str_appendl_ex(&spool_hashed_details, dbname, dbname_len, 0);
+ }
+ smart_str_appendl_ex(&spool_hashed_details, "**", sizeof("**") - 1, 0);
+
+ smart_str_append_unsigned_ex(&spool_hashed_details, charsetid, 0);
+
+ /* Session Pool Hash Key : oci8spool***username**edition**hashedpassword**dbname**charset */
+
+ smart_str_0(&spool_hashed_details);
+ php_strtolower(spool_hashed_details.c, spool_hashed_details.len);
+ /* }}} */
+
+ if (zend_hash_find(&EG(persistent_list),spool_hashed_details.c, spool_hashed_details.len+1, (void **)&spool_out_le) == FAILURE) {
+
+ session_pool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, spool_hashed_details.c, spool_hashed_details.len, charsetid TSRMLS_CC);
+
+ if (session_pool == NULL) {
+ iserror = 1;
+ goto exit_get_spool;
+ }
+ spool_le.ptr = session_pool;
+ spool_le.type = le_psessionpool;
+ zend_list_insert(session_pool, le_psessionpool);
+ zend_hash_update(&EG(persistent_list), session_pool->spool_hash_key, strlen(session_pool->spool_hash_key)+1,(void *)&spool_le, sizeof(zend_rsrc_list_entry),NULL);
+ } else if (spool_out_le->type == le_psessionpool &&
+ strlen(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key) == spool_hashed_details.len &&
+ memcmp(((php_oci_spool *)(spool_out_le->ptr))->spool_hash_key, spool_hashed_details.c, spool_hashed_details.len) == 0) {
+ /* retrieve the cached session pool */
+ session_pool = (php_oci_spool *)(spool_out_le->ptr);
+ }
+
+exit_get_spool:
+ smart_str_free_ex(&spool_hashed_details, 0);
+ if (iserror && session_pool) {
+ php_oci_spool_close(session_pool TSRMLS_CC);
+ session_pool = NULL;
+ }
+
+ return session_pool;
+
+} /* }}} */
+
+/* {{{ php_oci_create_env()
+ *
+ * Create the OCI environment choosing the correct function for the OCI version
+ */
+static OCIEnv *php_oci_create_env(ub2 charsetid TSRMLS_DC)
+{
+ OCIEnv *retenv = NULL;
+
+ /* create an environment using the character set id */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIEnvNlsCreate, (&retenv, OCI_G(events) ? PHP_OCI_INIT_MODE | OCI_EVENTS : PHP_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, charsetid, charsetid));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+#ifdef HAVE_OCI_INSTANT_CLIENT
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that " PHP_OCI8_LIB_PATH_MSG " includes the directory with Oracle Instant Client libraries");
+#else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and " PHP_OCI8_LIB_PATH_MSG " are set and point to the right directories");
+#endif
+ return NULL;
+ }
+ return retenv;
+}/* }}} */
+
+/* {{{ php_oci_old_create_session()
+ *
+ * This function is to be deprecated in future in favour of OCISessionGet which is used in
+ * php_oci_do_connect_ex
+ */
+static int php_oci_old_create_session(php_oci_connection *connection, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
+{
+ ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
+
+ if (OCI_G(debug_mode)) {
+ php_printf ("OCI8 DEBUG: Bypassing client-side session pool for session create at (%s:%d) \n", __FILE__, __LINE__);
+ }
+
+ /* Create the OCI environment separate for each connection */
+ if (!(connection->env = php_oci_create_env(connection->charset TSRMLS_CC))) {
+ return 1;
+ }
+
+ /* Allocate our server handle {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->server), OCI_HTYPE_SERVER, 0, NULL));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ } /* }}} */
+
+ /* Attach to the server {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIServerAttach, (connection->server, OCI_G(err), (text *)dbname, dbname_len, (ub4) OCI_DEFAULT));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ } /* }}} */
+ connection->is_attached = 1;
+
+ /* Allocate our session handle {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->session), OCI_HTYPE_SESSION, 0, NULL));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ } /* }}} */
+
+ /* Allocate our private error-handle {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ } /* }}} */
+
+ /* Allocate our service-context {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->svc), OCI_HTYPE_SVCCTX, 0, NULL));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ } /* }}} */
+
+ /* Set the username {{{ */
+ if (username) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) username, (ub4) username_len, (ub4) OCI_ATTR_USERNAME, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+ }/* }}} */
+
+ /* Set the password {{{ */
+ if (password) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) password, (ub4) password_len, (ub4) OCI_ATTR_PASSWORD, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+ }/* }}} */
+
+ /* Set the edition attribute on the session handle {{{ */
+#if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
+ if (OCI_G(edition)) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(edition), (ub4) (strlen(OCI_G(edition))), (ub4) OCI_ATTR_EDITION, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+ }
+#endif /* }}} */
+
+ /* Set the driver name attribute on the session handle {{{ */
+#if (OCI_MAJOR_VERSION >= 11)
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) PHP_OCI8_DRIVER_NAME, (ub4) sizeof(PHP_OCI8_DRIVER_NAME)-1, (ub4) OCI_ATTR_DRIVER_NAME, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+#endif /* }}} */
+
+ /* Set the server handle in the service handle {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->server, 0, OCI_ATTR_SERVER, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ } /* }}} */
+
+ /* Set the authentication handle in the service handle {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, (connection->svc, OCI_HTYPE_SVCCTX, connection->session, 0, OCI_ATTR_SESSION, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ } /* }}} */
+
+ if (new_password) {
+ /* Try to change password if new one was provided {{{ */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIPasswordChange, (connection->svc, OCI_G(err), (text *)username, username_len, (text *)password, password_len, (text *)new_password, new_password_len, OCI_AUTH));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ } /* }}} */
+ } else {
+ /* start the session {{{ */
+ ub4 cred_type = OCI_CRED_RDBMS;
+
+ /* Extract the overloaded session_mode parameter into valid Oracle credential and session mode values */
+ if (session_mode & PHP_OCI_CRED_EXT) {
+ cred_type = OCI_CRED_EXT;
+ session_mode ^= PHP_OCI_CRED_EXT;
+ }
+
+ session_mode |= OCI_STMT_CACHE;
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCISessionBegin, (connection->svc, OCI_G(err), connection->session, (ub4) cred_type, (ub4) session_mode));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ /* OCISessionBegin returns OCI_SUCCESS_WITH_INFO when
+ * user's password has expired, but is still usable.
+ */
+ if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
+ return 1;
+ }
+ } /* }}} */
+ }
+
+ /* Brand new connection: Init and update the next_ping in the connection */
+ if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX, (ub4 *) &statement_cache_size, 0, (ub4) OCI_ATTR_STMTCACHESIZE, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+
+ /* Successfully created session */
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_create_session()
+ *
+ * Create session using client-side session pool - new norm
+ */
+static int php_oci_create_session(php_oci_connection *connection, php_oci_spool *session_pool, char *dbname, int dbname_len, char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, int session_mode TSRMLS_DC)
+{
+ php_oci_spool *actual_spool = NULL;
+#if (OCI_MAJOR_VERSION > 10)
+ ub4 purity = -2; /* Illegal value to initialize */
+#endif
+ time_t timestamp = time(NULL);
+ ub4 statement_cache_size = (OCI_G(statement_cache_size) > 0) ? OCI_G(statement_cache_size) : 0;
+
+ /* Persistent connections have private session pools */
+ if (connection->is_persistent && !connection->private_spool &&
+ !(connection->private_spool = php_oci_create_spool(username, username_len, password, password_len, dbname, dbname_len, NULL, 0, connection->charset TSRMLS_CC))) {
+ return 1;
+ }
+ actual_spool = (connection->is_persistent) ? (connection->private_spool) : (session_pool);
+
+ connection->env = actual_spool->env;
+
+ /* Do this upfront so that connection close on an error would know that this is a session pool
+ * connection. Failure to do this would result in crashes in error scenarios
+ */
+ if (!connection->using_spool) {
+ connection->using_spool = 1;
+ }
+
+ if (OCI_G(debug_mode)) {
+ if (session_pool) {
+ php_printf ("OCI8 DEBUG L1: using shared pool: (%p) at (%s:%d) \n", session_pool, __FILE__, __LINE__);
+ } else {
+ php_printf ("OCI8 DEBUG L1: using private pool: (%p) at (%s:%d) \n", connection->private_spool, __FILE__, __LINE__);
+ }
+ }
+
+ /* The passed in "connection" can be a cached stub from plist or freshly created. In the former
+ * case, we do not have to allocate any handles
+ */
+
+ if (!connection->err) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->err), OCI_HTYPE_ERROR, 0, NULL));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+ }
+
+ /* {{{ Allocate and initialize the connection-private authinfo handle if not allocated yet */
+ if (!connection->authinfo) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIHandleAlloc, (connection->env, (dvoid **)&(connection->authinfo), OCI_HTYPE_AUTHINFO, 0, NULL));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+
+ /* Set the Connection class and purity if OCI client version >= 11g */
+#if (OCI_MAJOR_VERSION > 10)
+ PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_SESSION, (dvoid *) OCI_G(connection_class), (ub4)(strlen(OCI_G(connection_class))), (ub4)OCI_ATTR_CONNECTION_CLASS, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+
+ if (connection->is_persistent)
+ purity = OCI_ATTR_PURITY_SELF;
+ else
+ purity = OCI_ATTR_PURITY_NEW;
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode),OCIAttrSet, ((dvoid *) connection->authinfo,(ub4) OCI_HTYPE_AUTHINFO, (dvoid *) &purity, (ub4)0, (ub4)OCI_ATTR_PURITY, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+#endif
+ } /* }}} */
+
+ /* Debug statements {{{ */
+ if (OCI_G(debug_mode)) {
+ ub4 numfree = 0, numbusy = 0, numopen = 0;
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numopen, (ub4 *)0, OCI_ATTR_SPOOL_OPEN_COUNT, OCI_G(err)));
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)actual_spool->poolh, OCI_HTYPE_SPOOL, (dvoid *)&numbusy, (ub4 *)0, OCI_ATTR_SPOOL_BUSY_COUNT, OCI_G(err)));
+ numfree = numopen - numbusy; /* number of free connections in the pool */
+ php_printf ("OCI8 DEBUG L1: (numopen=%d)(numbusy=%d) at (%s:%d) \n", numopen, numbusy, __FILE__, __LINE__);
+ } /* }}} */
+
+ /* Ping loop: Ping and loop till we get a good connection. When a database instance goes
+ * down, it can leave several bad connections that need to be flushed out before getting a
+ * good one. In non-RAC, we always get a brand new connection at the end of the loop and in
+ * RAC, we can get a good connection from a different instance before flushing out all bad
+ * ones. We do not need to ping brand new connections.
+ */
+ do {
+ /* Continue to use the global error handle as the connection is closed when an error occurs */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode),OCISessionGet, (connection->env, OCI_G(err), &(connection->svc), (OCIAuthInfo *)connection->authinfo, (OraText *)actual_spool->poolname, (ub4)actual_spool->poolname_len, NULL, 0, NULL, NULL, NULL, OCI_SESSGET_SPOOL));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+
+ /* Session creation returns OCI_SUCCESS_WITH_INFO when user's password has expired, but
+ * is still usable.
+ */
+
+ if (OCI_G(errcode) != OCI_SUCCESS_WITH_INFO) {
+ return 1;
+ }
+ }
+
+ /* {{{ Populate the session and server fields of the connection */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->server), (ub4 *)0, OCI_ATTR_SERVER, OCI_G(err)));
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrGet, ((dvoid *)connection->svc, OCI_HTYPE_SVCCTX, (dvoid *)&(connection->session), (ub4 *)0, OCI_ATTR_SESSION, OCI_G(err))); /* }}} */
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, OCI_G(err), (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&(connection->next_pingp)));
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+
+ if (!(connection->next_pingp)){
+ /* This is a brand new connection, we need not ping, but have to initialize ping */
+ if (php_oci_ping_init(connection, OCI_G(err) TSRMLS_CC) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+ } else if ((*(connection->next_pingp) > 0) && (timestamp >= *(connection->next_pingp))) {
+ if (php_oci_connection_ping(connection TSRMLS_CC)) {
+ /* Got a good connection - update next_ping and get out of ping loop */
+ *(connection->next_pingp) = timestamp + OCI_G(ping_interval);
+ } else {
+ /* Bad connection - remove from pool */
+ PHP_OCI_CALL(OCISessionRelease, (connection->svc, connection->err, NULL,0, (ub4) OCI_SESSRLS_DROPSESS));
+ connection->svc = NULL;
+ connection->server = NULL;
+ connection->session = NULL;
+ }
+ } /* If ping applicable */
+ } while (!(connection->svc));
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX, (ub4 *) &statement_cache_size, 0, (ub4) OCI_ATTR_STMTCACHESIZE, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ return 1;
+ }
+
+ /* Session is now taken from the session pool and attached and open */
+ connection->is_stub = 0;
+ connection->is_attached = connection->is_open = 1;
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_spool_list_dtor()
+ *
+ * Session pool destructor function
+ */
+static void php_oci_spool_list_dtor(zend_rsrc_list_entry *entry TSRMLS_DC)
+{
+ php_oci_spool *session_pool = (php_oci_spool *)entry->ptr;
+
+ if (session_pool) {
+ php_oci_spool_close(session_pool TSRMLS_CC);
+ }
+
+ return;
+} /* }}} */
+
+/* {{{ php_oci_spool_close()
+ *
+ * Destroys the OCI Session Pool
+ */
+static void php_oci_spool_close(php_oci_spool *session_pool TSRMLS_DC)
+{
+ if (session_pool->poolname_len) {
+ PHP_OCI_CALL(OCISessionPoolDestroy, ((dvoid *) session_pool->poolh,
+ (dvoid *) session_pool->err, OCI_SPD_FORCE));
+ }
+
+ if (session_pool->poolh) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->poolh, OCI_HTYPE_SPOOL));
+ }
+
+ if (session_pool->err) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->err, OCI_HTYPE_ERROR));
+ }
+
+ if (session_pool->env) {
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) session_pool->env, OCI_HTYPE_ENV));
+ }
+
+ if (session_pool->spool_hash_key) {
+ free(session_pool->spool_hash_key);
+ }
+
+ free(session_pool);
+} /* }}} */
+
+/* {{{ php_oci_ping_init()
+ *
+ * Initializes the next_ping time as a context value in the connection. We now use
+ * OCIContext{Get,Set}Value to store the next_ping because we need to support ping for
+ * non-persistent DRCP connections
+ */
+static sword php_oci_ping_init(php_oci_connection *connection, OCIError *errh TSRMLS_DC)
+{
+ time_t *next_pingp = NULL;
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextGetValue, (connection->session, errh, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), (void **)&next_pingp));
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ return OCI_G(errcode);
+ }
+
+ /* This must be a brand-new connection. Allocate memory for the ping */
+ if (!next_pingp) {
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIMemoryAlloc, (connection->session, errh, (void **)&next_pingp, OCI_DURATION_SESSION, sizeof(time_t), OCI_MEMORY_CLEARED));
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ return OCI_G(errcode);
+ }
+ }
+
+ if (OCI_G(ping_interval) >= 0) {
+ time_t timestamp = time(NULL);
+ *next_pingp = timestamp + OCI_G(ping_interval);
+ } else {
+ *next_pingp = 0;
+ }
+
+ /* Set the new ping value into the connection */
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIContextSetValue, (connection->session, errh, OCI_DURATION_SESSION, (ub1 *)"NEXT_PING", (ub1)sizeof("NEXT_PING"), next_pingp));
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ OCIMemoryFree(connection->session, errh, next_pingp);
+ return OCI_G(errcode);
+ }
+
+ /* Cache the pointer so we do not have to do OCIContextGetValue repeatedly */
+ connection->next_pingp = next_pingp;
+
+ return OCI_SUCCESS;
+} /* }}} */
+
+#endif /* HAVE_OCI8 */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/oci8.dsp b/oci8.dsp
new file mode 100644
index 0000000000..f0b27fa824
--- /dev/null
+++ b/oci8.dsp
@@ -0,0 +1,133 @@
+# Microsoft Developer Studio Project File - Name="oci8" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=oci8 - Win32 Release_TS
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "oci8.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "oci8.mak" CFG="oci8 - Win32 Release_TS"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "oci8 - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "oci8 - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "oci8 - Win32 Release_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_TS"
+# PROP BASE Intermediate_Dir "Release_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS"
+# PROP Intermediate_Dir "Release_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D ZTS=1 /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\\" /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "..\..\..\php_build\include\instantclient" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_OCI8=1 /D HAVE_OCI8_TEMP_LOB=1 /D HAVE_OCI8_ATTR_STATEMENT=1 /D COMPILE_DL_OCI8=1 /D PHP_OCI8_HAVE_COLLECTIONS=1 /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /machine:I386
+# ADD LINK32 php4ts.lib oci.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_oci8.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\..\php_build\lib\instantclient" /libpath:"..\..\Release_TS_Inline"
+
+!ELSEIF "$(CFG)" == "oci8 - Win32 Debug_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Debug_TS"
+# PROP BASE Intermediate_Dir "Debug_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug_TS"
+# PROP Intermediate_Dir "Debug_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D ZTS=1 /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\\" /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "..\..\..\php_build\include\instantclient" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FTP_EXPORTS" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_OCI8=1 /D HAVE_OCI8_TEMP_LOB=1 /D HAVE_OCI8_ATTR_STATEMENT=1 /D COMPILE_DL_OCI8=1 /D PHP_OCI8_HAVE_COLLECTIONS=1 /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /machine:I386
+# ADD LINK32 php4ts_debug.lib oci.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Debug_TS/php_oci8.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\lib\instantclient"
+
+!ENDIF
+
+# Begin Target
+
+# Name "oci8 - Win32 Release_TS"
+# Name "oci8 - Win32 Debug_TS"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\oci8.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\oci8_collection.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\oci8_interface.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\oci8_lob.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\oci8_statement.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\php_oci8.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_oci8_int.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/oci8_collection.c b/oci8_collection.c
new file mode 100644
index 0000000000..991977f092
--- /dev/null
+++ b/oci8_collection.c
@@ -0,0 +1,793 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@php.net> |
+ | Thies C. Arntzen <thies@thieso.net> |
+ | |
+ | Collection support by Andy Sautins <asautins@veripost.net> |
+ | Temporary LOB support by David Benson <dbenson@mancala.com> |
+ | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
+ | |
+ | Redesigned by: Antony Dovgal <antony@zend.com> |
+ | Andi Gutmans <andi@zend.com> |
+ | Wez Furlong <wez@omniti.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "ext/standard/info.h"
+#include "php_ini.h"
+
+#if HAVE_OCI8
+
+#include "php_oci8.h"
+#include "php_oci8_int.h"
+
+/* {{{ php_oci_collection_create()
+ Create and return connection handle */
+php_oci_collection * php_oci_collection_create(php_oci_connection *connection, char *tdo, int tdo_len, char *schema, int schema_len TSRMLS_DC)
+{
+ dvoid *dschp1 = NULL;
+ dvoid *parmp1;
+ dvoid *parmp2;
+ php_oci_collection *collection;
+
+ collection = emalloc(sizeof(php_oci_collection));
+
+ collection->connection = connection;
+ collection->collection = NULL;
+ zend_list_addref(collection->connection->rsrc_id);
+
+ /* get type handle by name */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCITypeByName,
+ (
+ connection->env,
+ connection->err,
+ connection->svc,
+ (text *) schema,
+ (ub4) schema_len,
+ (text *) tdo,
+ (ub4) tdo_len,
+ (CONST text *) 0,
+ (ub4) 0,
+ OCI_DURATION_SESSION,
+ OCI_TYPEGET_ALL,
+ &(collection->tdo)
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ /* allocate describe handle */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIHandleAlloc, (connection->env, (dvoid **) &dschp1, (ub4) OCI_HTYPE_DESCRIBE, (size_t) 0, (dvoid **) 0));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ /* describe TDO */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDescribeAny,
+ (
+ connection->svc,
+ connection->err,
+ (dvoid *) collection->tdo,
+ (ub4) 0,
+ OCI_OTYPE_PTR,
+ (ub1) OCI_DEFAULT,
+ (ub1) OCI_PTYPE_TYPE,
+ dschp1
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ /* get first parameter handle */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet, ((dvoid *) dschp1, (ub4) OCI_HTYPE_DESCRIBE, (dvoid *)&parmp1, (ub4 *)0, (ub4)OCI_ATTR_PARAM, connection->err));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ /* get the collection type code of the attribute */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
+ (
+ (dvoid*) parmp1,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid*) &(collection->coll_typecode),
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_COLLECTION_TYPECODE,
+ connection->err
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ switch(collection->coll_typecode) {
+ case OCI_TYPECODE_TABLE:
+ case OCI_TYPECODE_VARRAY:
+ /* get collection element handle */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
+ (
+ (dvoid*) parmp1,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid*) &parmp2,
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_COLLECTION_ELEMENT,
+ connection->err
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ /* get REF of the TDO for the type */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
+ (
+ (dvoid*) parmp2,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid*) &(collection->elem_ref),
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_REF_TDO,
+ connection->err
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ /* get the TDO (only header) */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCITypeByRef,
+ (
+ connection->env,
+ connection->err,
+ collection->elem_ref,
+ OCI_DURATION_SESSION,
+ OCI_TYPEGET_HEADER,
+ &(collection->element_type)
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ /* get typecode */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIAttrGet,
+ (
+ (dvoid*) parmp2,
+ (ub4) OCI_DTYPE_PARAM,
+ (dvoid*) &(collection->element_typecode),
+ (ub4 *) 0,
+ (ub4) OCI_ATTR_TYPECODE,
+ connection->err
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+ break;
+ /* we only support VARRAYs and TABLEs */
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown collection type %d", collection->coll_typecode);
+ break;
+ }
+
+ /* Create object to hold return table */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIObjectNew,
+ (
+ connection->env,
+ connection->err,
+ connection->svc,
+ OCI_TYPECODE_TABLE,
+ collection->tdo,
+ (dvoid *)0,
+ OCI_DURATION_DEFAULT,
+ TRUE,
+ (dvoid **) &(collection->collection)
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ goto CLEANUP;
+ }
+
+ /* free the describe handle (Bug #44113) */
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE));
+ PHP_OCI_REGISTER_RESOURCE(collection, le_collection);
+ return collection;
+
+CLEANUP:
+
+ if (dschp1) {
+ /* free the describe handle (Bug #44113) */
+ PHP_OCI_CALL(OCIHandleFree, ((dvoid *) dschp1, OCI_HTYPE_DESCRIBE));
+ }
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ php_oci_collection_close(collection TSRMLS_CC);
+ return NULL;
+} /* }}} */
+
+/* {{{ php_oci_collection_size()
+ Return size of the collection */
+int php_oci_collection_size(php_oci_collection *collection, sb4 *size TSRMLS_DC)
+{
+ php_oci_connection *connection = collection->connection;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollSize, (connection->env, connection->err, collection->collection, (sb4 *)size));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_max()
+ Return max number of elements in the collection */
+int php_oci_collection_max(php_oci_collection *collection, long *max TSRMLS_DC)
+{
+ php_oci_connection *connection = collection->connection;
+
+ PHP_OCI_CALL_RETURN(*max, OCICollMax, (connection->env, collection->collection));
+
+ /* error handling is not necessary here? */
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_trim()
+ Trim collection to the given number of elements */
+int php_oci_collection_trim(php_oci_collection *collection, long trim_size TSRMLS_DC)
+{
+ php_oci_connection *connection = collection->connection;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollTrim, (connection->env, connection->err, trim_size, collection->collection));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_append_null()
+ Append NULL element to the end of the collection */
+int php_oci_collection_append_null(php_oci_collection *collection TSRMLS_DC)
+{
+ OCIInd null_index = OCI_IND_NULL;
+ php_oci_connection *connection = collection->connection;
+
+ /* append NULL element */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend, (connection->env, connection->err, (dvoid *)0, &null_index, collection->collection));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_append_date()
+ Append DATE element to the end of the collection (use "DD-MON-YY" format) */
+int php_oci_collection_append_date(php_oci_collection *collection, char *date, int date_len TSRMLS_DC)
+{
+ OCIInd new_index = OCI_IND_NOTNULL;
+ OCIDate oci_date;
+ php_oci_connection *connection = collection->connection;
+
+ /* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ /* failed to convert string to date */
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
+ (
+ connection->env,
+ connection->err,
+ (dvoid *) &oci_date,
+ (dvoid *) &new_index,
+ (OCIColl *) collection->collection
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_append_number()
+ Append NUMBER to the end of the collection */
+int php_oci_collection_append_number(php_oci_collection *collection, char *number, int number_len TSRMLS_DC)
+{
+ OCIInd new_index = OCI_IND_NOTNULL;
+ double element_double;
+ OCINumber oci_number;
+ php_oci_connection *connection = collection->connection;
+
+#if (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10)
+ /* minimum PHP version ext/oci8/config.m4 accepts is 4.3.9 */
+ element_double = strtod(number, NULL);
+#else
+ /* zend_strtod was introduced in PHP 4.3.10 */
+ element_double = zend_strtod(number, NULL);
+#endif
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
+ (
+ connection->env,
+ connection->err,
+ (dvoid *) &oci_number,
+ (dvoid *) &new_index,
+ (OCIColl *) collection->collection
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_append_string()
+ Append STRING to the end of the collection */
+int php_oci_collection_append_string(php_oci_collection *collection, char *element, int element_len TSRMLS_DC)
+{
+ OCIInd new_index = OCI_IND_NOTNULL;
+ OCIString *ocistr = (OCIString *)0;
+ php_oci_connection *connection = collection->connection;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAppend,
+ (
+ connection->env,
+ connection->err,
+ (dvoid *) ocistr,
+ (dvoid *) &new_index,
+ (OCIColl *) collection->collection
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_append()
+ Append wrapper. Appends any supported element to the end of the collection */
+int php_oci_collection_append(php_oci_collection *collection, char *element, int element_len TSRMLS_DC)
+{
+ if (element_len == 0) {
+ return php_oci_collection_append_null(collection TSRMLS_CC);
+ }
+
+ switch(collection->element_typecode) {
+ case OCI_TYPECODE_DATE:
+ return php_oci_collection_append_date(collection, element, element_len TSRMLS_CC);
+ break;
+
+ case OCI_TYPECODE_VARCHAR2 :
+ return php_oci_collection_append_string(collection, element, element_len TSRMLS_CC);
+ break;
+
+ case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
+ case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
+ case OCI_TYPECODE_REAL : /* REAL */
+ case OCI_TYPECODE_DOUBLE : /* DOUBLE */
+ case OCI_TYPECODE_INTEGER : /* INT */
+ case OCI_TYPECODE_SIGNED16 : /* SHORT */
+ case OCI_TYPECODE_SIGNED32 : /* LONG */
+ case OCI_TYPECODE_DECIMAL : /* DECIMAL */
+ case OCI_TYPECODE_FLOAT : /* FLOAT */
+ case OCI_TYPECODE_NUMBER : /* NUMBER */
+ case OCI_TYPECODE_SMALLINT : /* SMALLINT */
+ return php_oci_collection_append_number(collection, element, element_len TSRMLS_CC);
+ break;
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
+ return 1;
+ break;
+ }
+ /* never reached */
+ return 1;
+} /* }}} */
+
+/* {{{ php_oci_collection_element_get()
+ Get the element with the given index */
+int php_oci_collection_element_get(php_oci_collection *collection, long index, zval **result_element TSRMLS_DC)
+{
+ php_oci_connection *connection = collection->connection;
+ dvoid *element;
+ OCIInd *element_index;
+ boolean exists;
+ oratext buff[1024];
+ ub4 buff_len = 1024;
+
+ MAKE_STD_ZVAL(*result_element);
+ ZVAL_NULL(*result_element);
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollGetElem,
+ (
+ connection->env,
+ connection->err,
+ collection->collection,
+ (ub4)index,
+ &exists,
+ &element,
+ (dvoid **)&element_index
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ FREE_ZVAL(*result_element);
+ return 1;
+ }
+
+ if (exists == 0) {
+ /* element doesn't exist */
+ FREE_ZVAL(*result_element);
+ return 1;
+ }
+
+ if (*element_index == OCI_IND_NULL) {
+ /* this is not an error, we're returning NULL here */
+ return 0;
+ }
+
+ switch (collection->element_typecode) {
+ case OCI_TYPECODE_DATE:
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, element, 0, 0, 0, 0, &buff_len, buff));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ FREE_ZVAL(*result_element);
+ return 1;
+ }
+
+ ZVAL_STRINGL(*result_element, (char *)buff, buff_len, 1);
+ Z_STRVAL_P(*result_element)[buff_len] = '\0';
+
+ return 0;
+ break;
+
+ case OCI_TYPECODE_VARCHAR2:
+ {
+ OCIString *oci_string = *(OCIString **)element;
+ text *str;
+
+ PHP_OCI_CALL_RETURN(str, OCIStringPtr, (connection->env, oci_string));
+
+ if (str) {
+ ZVAL_STRING(*result_element, (char *)str, 1);
+ }
+ return 0;
+ }
+ break;
+
+ case OCI_TYPECODE_UNSIGNED16: /* UNSIGNED SHORT */
+ case OCI_TYPECODE_UNSIGNED32: /* UNSIGNED LONG */
+ case OCI_TYPECODE_REAL: /* REAL */
+ case OCI_TYPECODE_DOUBLE: /* DOUBLE */
+ case OCI_TYPECODE_INTEGER: /* INT */
+ case OCI_TYPECODE_SIGNED16: /* SHORT */
+ case OCI_TYPECODE_SIGNED32: /* LONG */
+ case OCI_TYPECODE_DECIMAL: /* DECIMAL */
+ case OCI_TYPECODE_FLOAT: /* FLOAT */
+ case OCI_TYPECODE_NUMBER: /* NUMBER */
+ case OCI_TYPECODE_SMALLINT: /* SMALLINT */
+ {
+ double double_number;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCINumberToReal, (connection->err, (CONST OCINumber *) element, (uword) sizeof(double), (dvoid *) &double_number));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ FREE_ZVAL(*result_element);
+ return 1;
+ }
+
+ ZVAL_DOUBLE(*result_element, double_number);
+
+ return 0;
+ }
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
+ FREE_ZVAL(*result_element);
+ return 1;
+ break;
+ }
+ /* never reached */
+ return 1;
+} /* }}} */
+
+/* {{{ php_oci_collection_element_set_null()
+ Set the element with the given index to NULL */
+int php_oci_collection_element_set_null(php_oci_collection *collection, long index TSRMLS_DC)
+{
+ OCIInd null_index = OCI_IND_NULL;
+ php_oci_connection *connection = collection->connection;
+
+ /* set NULL element */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem, (connection->env, connection->err, (ub4) index, (dvoid *)"", &null_index, collection->collection));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_element_set_date()
+ Change element's value to the given DATE */
+int php_oci_collection_element_set_date(php_oci_collection *collection, long index, char *date, int date_len TSRMLS_DC)
+{
+ OCIInd new_index = OCI_IND_NOTNULL;
+ OCIDate oci_date;
+ php_oci_connection *connection = collection->connection;
+
+ /* format and language are NULLs, so format is "DD-MON-YY" and language is the default language of the session */
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)date, date_len, NULL, 0, NULL, 0, &oci_date));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ /* failed to convert string to date */
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
+ (
+ connection->env,
+ connection->err,
+ (ub4)index,
+ (dvoid *) &oci_date,
+ (dvoid *) &new_index,
+ (OCIColl *) collection->collection
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_element_set_number()
+ Change element's value to the given NUMBER */
+int php_oci_collection_element_set_number(php_oci_collection *collection, long index, char *number, int number_len TSRMLS_DC)
+{
+ OCIInd new_index = OCI_IND_NOTNULL;
+ double element_double;
+ OCINumber oci_number;
+ php_oci_connection *connection = collection->connection;
+
+#if (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10)
+ /* minimum PHP version ext/oci8/config.m4 accepts is 4.3.9 */
+ element_double = strtod(number, NULL);
+#else
+ /* zend_strtod was introduced in PHP 4.3.10 */
+ element_double = zend_strtod(number, NULL);
+#endif
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCINumberFromReal, (connection->err, &element_double, sizeof(double), &oci_number));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
+ (
+ connection->env,
+ connection->err,
+ (ub4) index,
+ (dvoid *) &oci_number,
+ (dvoid *) &new_index,
+ (OCIColl *) collection->collection
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_element_set_string()
+ Change element's value to the given string */
+int php_oci_collection_element_set_string(php_oci_collection *collection, long index, char *element, int element_len TSRMLS_DC)
+{
+ OCIInd new_index = OCI_IND_NOTNULL;
+ OCIString *ocistr = (OCIString *)0;
+ php_oci_connection *connection = collection->connection;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIStringAssignText, (connection->env, connection->err, (CONST oratext *)element, element_len, &ocistr));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssignElem,
+ (
+ connection->env,
+ connection->err,
+ (ub4)index,
+ (dvoid *) ocistr,
+ (dvoid *) &new_index,
+ (OCIColl *) collection->collection
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_element_set()
+ Collection element setter */
+int php_oci_collection_element_set(php_oci_collection *collection, long index, char *value, int value_len TSRMLS_DC)
+{
+ if (value_len == 0) {
+ return php_oci_collection_element_set_null(collection, index TSRMLS_CC);
+ }
+
+ switch(collection->element_typecode) {
+ case OCI_TYPECODE_DATE:
+ return php_oci_collection_element_set_date(collection, index, value, value_len TSRMLS_CC);
+ break;
+
+ case OCI_TYPECODE_VARCHAR2 :
+ return php_oci_collection_element_set_string(collection, index, value, value_len TSRMLS_CC);
+ break;
+
+ case OCI_TYPECODE_UNSIGNED16 : /* UNSIGNED SHORT */
+ case OCI_TYPECODE_UNSIGNED32 : /* UNSIGNED LONG */
+ case OCI_TYPECODE_REAL : /* REAL */
+ case OCI_TYPECODE_DOUBLE : /* DOUBLE */
+ case OCI_TYPECODE_INTEGER : /* INT */
+ case OCI_TYPECODE_SIGNED16 : /* SHORT */
+ case OCI_TYPECODE_SIGNED32 : /* LONG */
+ case OCI_TYPECODE_DECIMAL : /* DECIMAL */
+ case OCI_TYPECODE_FLOAT : /* FLOAT */
+ case OCI_TYPECODE_NUMBER : /* NUMBER */
+ case OCI_TYPECODE_SMALLINT : /* SMALLINT */
+ return php_oci_collection_element_set_number(collection, index, value, value_len TSRMLS_CC);
+ break;
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or unsupported type of element: %d", collection->element_typecode);
+ return 1;
+ break;
+ }
+ /* never reached */
+ return 1;
+} /* }}} */
+
+/* {{{ php_oci_collection_assign()
+ Assigns a value to the collection from another collection */
+int php_oci_collection_assign(php_oci_collection *collection_dest, php_oci_collection *collection_from TSRMLS_DC)
+{
+ php_oci_connection *connection = collection_dest->connection;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCICollAssign, (connection->env, connection->err, collection_from->collection, collection_dest->collection));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_collection_close()
+ Destroy collection and all associated resources */
+void php_oci_collection_close(php_oci_collection *collection TSRMLS_DC)
+{
+ php_oci_connection *connection = collection->connection;
+
+ if (collection->collection) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIObjectFree, (connection->env, connection->err, (dvoid *)collection->collection, (ub2)OCI_OBJECTFREE_FORCE));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ }
+ }
+
+ zend_list_delete(collection->connection->rsrc_id);
+
+ efree(collection);
+ return;
+} /* }}} */
+
+#endif /* HAVE_OCI8 */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/oci8_interface.c b/oci8_interface.c
new file mode 100644
index 0000000000..b12c8dc3bc
--- /dev/null
+++ b/oci8_interface.c
@@ -0,0 +1,2355 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@php.net> |
+ | Thies C. Arntzen <thies@thieso.net> |
+ | |
+ | Collection support by Andy Sautins <asautins@veripost.net> |
+ | Temporary LOB support by David Benson <dbenson@mancala.com> |
+ | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
+ | |
+ | Redesigned by: Antony Dovgal <antony@zend.com> |
+ | Andi Gutmans <andi@zend.com> |
+ | Wez Furlong <wez@omniti.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "ext/standard/info.h"
+#include "php_ini.h"
+
+#if HAVE_OCI8
+
+#include "php_oci8.h"
+#include "php_oci8_int.h"
+
+#ifndef OCI_STMT_CALL
+#define OCI_STMT_CALL 10
+#endif
+
+/* {{{ proto bool oci_define_by_name(resource stmt, string name, mixed &var [, int type])
+ Define a PHP variable to an Oracle column by name */
+/* if you want to define a LOB/CLOB etc make sure you allocate it via OCINewDescriptor BEFORE defining!!! */
+PHP_FUNCTION(oci_define_by_name)
+{
+ zval *stmt, *var;
+ char *name;
+ int name_len;
+ long type = 0;
+ php_oci_statement *statement;
+ php_oci_define *define, *tmp_define;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz/|l", &stmt, &name, &name_len, &var, &type) == FAILURE) {
+ return;
+ }
+
+ if (!name_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column name cannot be empty");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(stmt, statement);
+
+ if (statement->defines == NULL) {
+ ALLOC_HASHTABLE(statement->defines);
+ zend_hash_init(statement->defines, 13, NULL, php_oci_define_hash_dtor, 0);
+ }
+
+ define = ecalloc(1,sizeof(php_oci_define));
+
+ if (zend_hash_add(statement->defines, name, name_len, define, sizeof(php_oci_define), (void **)&tmp_define) == SUCCESS) {
+ efree(define);
+ define = tmp_define;
+ } else {
+ efree(define);
+ RETURN_FALSE;
+ }
+
+ define->name = (text*) estrndup(name, name_len);
+ define->name_len = name_len;
+ define->type = type;
+ define->zval = var;
+ zval_add_ref(&var);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_bind_by_name(resource stmt, string name, mixed &var, [, int maxlength [, int type]])
+ Bind a PHP variable to an Oracle placeholder by name */
+/* if you want to bind a LOB/CLOB etc make sure you allocate it via OCINewDescriptor BEFORE binding!!! */
+PHP_FUNCTION(oci_bind_by_name)
+{
+ ub2 bind_type = SQLT_CHR; /* unterminated string */
+ int name_len;
+ long maxlen = -1, type = 0;
+ char *name;
+ zval *z_statement;
+ zval *bind_var = NULL;
+ php_oci_statement *statement;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz/|ll", &z_statement, &name, &name_len, &bind_var, &maxlen, &type) == FAILURE) {
+ return;
+ }
+
+ if (type) {
+ bind_type = (ub2) type;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (php_oci_bind_by_name(statement, name, name_len, bind_var, maxlen, bind_type TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_bind_array_by_name(resource stmt, string name, array &var, int max_table_length [, int max_item_length [, int type ]])
+ Bind a PHP array to an Oracle PL/SQL type by name */
+PHP_FUNCTION(oci_bind_array_by_name)
+{
+ int name_len;
+ long max_item_len = -1;
+ long max_array_len = 0;
+ long type = SQLT_AFC;
+ char *name;
+ zval *z_statement;
+ zval *bind_var = NULL;
+ php_oci_statement *statement;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz/l|ll", &z_statement, &name, &name_len, &bind_var, &max_array_len, &max_item_len, &type) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (ZEND_NUM_ARGS() == 5 && max_item_len <= 0) {
+ max_item_len = -1;
+ }
+
+ if (max_array_len <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum array length must be greater than zero");
+ RETURN_FALSE;
+ }
+
+ if (php_oci_bind_array_by_name(statement, name, name_len, bind_var, max_array_len, max_item_len, type TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_free_descriptor()
+ Deletes large object description */
+PHP_FUNCTION(oci_free_descriptor)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ zend_list_delete(descriptor->id);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_save( string data [, int offset ])
+ Saves a large object */
+PHP_FUNCTION(oci_lob_save)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ char *data;
+ int data_len;
+ long offset = 0;
+ ub4 bytes_written;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &offset) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &z_descriptor, oci_lob_class_entry_ptr, &data, &data_len, &offset) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (offset < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset parameter must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+
+ if (php_oci_lob_write(descriptor, offset, data, data_len, &bytes_written TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_import( string filename )
+ Loads file into a LOB */
+PHP_FUNCTION(oci_lob_import)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ char *filename;
+ int filename_len;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_import(descriptor, filename TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string oci_lob_load()
+ Loads a large object */
+PHP_FUNCTION(oci_lob_load)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ char *buffer = NULL;
+ ub4 buffer_len;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_read(descriptor, -1, 0, &buffer, &buffer_len TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ if (buffer_len > 0) {
+ RETURN_STRINGL(buffer, buffer_len, 0);
+ }
+ else {
+ RETURN_EMPTY_STRING();
+ }
+}
+/* }}} */
+
+/* {{{ proto string oci_lob_read( int length )
+ Reads particular part of a large object */
+PHP_FUNCTION(oci_lob_read)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ long length;
+ char *buffer;
+ ub4 buffer_len;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &z_descriptor, oci_lob_class_entry_ptr, &length) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (length <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
+ RETURN_FALSE;
+ }
+
+ if (php_oci_lob_read(descriptor, length, descriptor->lob_current_position, &buffer, &buffer_len TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ if (buffer_len > 0) {
+ RETURN_STRINGL(buffer, buffer_len, 0);
+ }
+ else {
+ RETURN_EMPTY_STRING();
+ }
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_eof()
+ Checks if EOF is reached */
+PHP_FUNCTION(oci_lob_eof)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ ub4 lob_length;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (!php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC) && lob_length >= 0) {
+ if (lob_length == descriptor->lob_current_position) {
+ RETURN_TRUE;
+ }
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto int oci_lob_tell()
+ Tells LOB pointer position */
+PHP_FUNCTION(oci_lob_tell)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ RETURN_LONG(descriptor->lob_current_position);
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_rewind()
+ Rewind pointer of a LOB */
+PHP_FUNCTION(oci_lob_rewind)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ descriptor->lob_current_position = 0;
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_seek( int offset [, int whence ])
+ Moves the pointer of a LOB */
+PHP_FUNCTION(oci_lob_seek)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ long offset, whence = PHP_OCI_SEEK_SET;
+ ub4 lob_length;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &offset, &whence) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|l", &z_descriptor, oci_lob_class_entry_ptr, &offset, &whence) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ switch(whence) {
+ case PHP_OCI_SEEK_CUR:
+ descriptor->lob_current_position += offset;
+ break;
+ case PHP_OCI_SEEK_END:
+ if ((descriptor->lob_size + offset) >= 0) {
+ descriptor->lob_current_position = descriptor->lob_size + offset;
+ }
+ else {
+ descriptor->lob_current_position = 0;
+ }
+ break;
+ case PHP_OCI_SEEK_SET:
+ default:
+ descriptor->lob_current_position = (offset > 0) ? offset : 0;
+ break;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int oci_lob_size()
+ Returns size of a large object */
+PHP_FUNCTION(oci_lob_size)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ ub4 lob_length;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(lob_length);
+}
+/* }}} */
+
+/* {{{ proto int oci_lob_write( string string [, int length ])
+ Writes data to current position of a LOB */
+PHP_FUNCTION(oci_lob_write)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ int data_len;
+ long write_len = 0;
+ ub4 bytes_written;
+ char *data;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &write_len) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() == 2) {
+ data_len = MIN(data_len, write_len);
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &z_descriptor, oci_lob_class_entry_ptr, &data, &data_len, &write_len) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() == 3) {
+ data_len = MIN(data_len, write_len);
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (data_len <= 0) {
+ RETURN_LONG(0);
+ }
+
+ if (php_oci_lob_write(descriptor, descriptor->lob_current_position, data, data_len, &bytes_written TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(bytes_written);
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_append( object lob )
+ Appends data from a LOB to another LOB */
+PHP_FUNCTION(oci_lob_append)
+{
+ zval **tmp_dest, **tmp_from, *z_descriptor_dest = getThis(), *z_descriptor_from;
+ php_oci_descriptor *descriptor_dest, *descriptor_from;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor_from, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &z_descriptor_dest, oci_lob_class_entry_ptr, &z_descriptor_from, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor_dest), "descriptor", sizeof("descriptor"), (void **)&tmp_dest) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The first argument should be valid descriptor object");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor_from), "descriptor", sizeof("descriptor"), (void **)&tmp_from) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The second argument should be valid descriptor object");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_dest, descriptor_dest);
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_from, descriptor_from);
+
+ if (php_oci_lob_append(descriptor_dest, descriptor_from TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ /* XXX should we increase lob_size here ? */
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_truncate( [ int length ])
+ Truncates a LOB */
+PHP_FUNCTION(oci_lob_truncate)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ long trim_length = 0;
+ ub4 ub_trim_length;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &trim_length) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &z_descriptor, oci_lob_class_entry_ptr, &trim_length) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ if (trim_length < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length must be greater than or equal to zero");
+ RETURN_FALSE;
+ }
+
+ ub_trim_length = (ub4) trim_length;
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_truncate(descriptor, ub_trim_length TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int oci_lob_erase( [ int offset [, int length ] ] )
+ Erases a specified portion of the internal LOB, starting at a specified offset */
+PHP_FUNCTION(oci_lob_erase)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ ub4 bytes_erased;
+ long offset = -1, length = -1;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &offset, &length) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() > 0 && offset < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+
+ if (ZEND_NUM_ARGS() > 1 && length < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|ll", &z_descriptor, oci_lob_class_entry_ptr, &offset, &length) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() > 1 && offset < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+
+ if (ZEND_NUM_ARGS() > 2 && length < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_erase(descriptor, offset, length, &bytes_erased TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(bytes_erased);
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_flush( [ int flag ] )
+ Flushes the LOB buffer */
+PHP_FUNCTION(oci_lob_flush)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ long flush_flag = 0;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flush_flag) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &z_descriptor, oci_lob_class_entry_ptr, &flush_flag) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (descriptor->buffering == PHP_OCI_LOB_BUFFER_DISABLED) {
+ /* buffering wasn't enabled, there is nothing to flush */
+ RETURN_FALSE;
+ }
+
+ if (php_oci_lob_flush(descriptor, flush_flag TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ocisetbufferinglob( boolean flag )
+ Enables/disables buffering for a LOB */
+PHP_FUNCTION(ocisetbufferinglob)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ zend_bool flag;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &flag) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ob", &z_descriptor, oci_lob_class_entry_ptr, &flag) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_set_buffering(descriptor, flag TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ocigetbufferinglob()
+ Returns current state of buffering for a LOB */
+PHP_FUNCTION(ocigetbufferinglob)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
+ RETURN_TRUE;
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_copy( object lob_to, object lob_from [, int length ] )
+ Copies data from a LOB to another LOB */
+PHP_FUNCTION(oci_lob_copy)
+{
+ zval **tmp_dest, **tmp_from, *z_descriptor_dest, *z_descriptor_from;
+ php_oci_descriptor *descriptor_dest, *descriptor_from;
+ long length = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO|l", &z_descriptor_dest, oci_lob_class_entry_ptr, &z_descriptor_from, oci_lob_class_entry_ptr, &length) == FAILURE) {
+ return;
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor_dest), "descriptor", sizeof("descriptor"), (void **)&tmp_dest) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The first argument should be valid descriptor object");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor_from), "descriptor", sizeof("descriptor"), (void **)&tmp_from) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The second argument should be valid descriptor object");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_dest, descriptor_dest);
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_from, descriptor_from);
+
+ if (ZEND_NUM_ARGS() == 3 && length < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
+ RETURN_FALSE;
+ }
+
+ if (ZEND_NUM_ARGS() == 2) {
+ /* indicate that we want to copy from the current position to the end of the LOB */
+ length = -1;
+ }
+
+ if (php_oci_lob_copy(descriptor_dest, descriptor_from, length TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_is_equal( object lob1, object lob2 )
+ Tests to see if two LOB/FILE locators are equal */
+PHP_FUNCTION(oci_lob_is_equal)
+{
+ zval **tmp_first, **tmp_second, *z_descriptor_first, *z_descriptor_second;
+ php_oci_descriptor *descriptor_first, *descriptor_second;
+ boolean is_equal;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &z_descriptor_first, oci_lob_class_entry_ptr, &z_descriptor_second, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor_first), "descriptor", sizeof("descriptor"), (void **)&tmp_first) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The first argument should be valid descriptor object");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor_second), "descriptor", sizeof("descriptor"), (void **)&tmp_second) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property. The second argument should be valid descriptor object");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_first, descriptor_first);
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp_second, descriptor_second);
+
+ if (php_oci_lob_is_equal(descriptor_first, descriptor_second, &is_equal TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ if (is_equal == TRUE) {
+ RETURN_TRUE;
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_export([string filename [, int start [, int length]]])
+ Writes a large object into a file */
+PHP_FUNCTION(oci_lob_export)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ char *filename;
+ char *buffer;
+ int filename_len;
+ long start = -1, length = -1, block_length;
+ php_stream *stream;
+ ub4 lob_length;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &filename, &filename_len, &start, &length) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() > 1 && start < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Start parameter must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+ if (ZEND_NUM_ARGS() > 2 && length < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|ll", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len, &start, &length) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() > 2 && start < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Start parameter must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+ if (ZEND_NUM_ARGS() > 3 && length < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than or equal to 0");
+ RETURN_FALSE;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ if (start == -1) {
+ start = 0;
+ }
+
+ if (length == -1) {
+ length = lob_length - descriptor->lob_current_position;
+ }
+
+ if (length == 0) {
+ /* nothing to write, fail silently */
+ RETURN_FALSE;
+ }
+
+ if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
+ RETURN_FALSE;
+ }
+
+ if (php_check_open_basedir(filename TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ stream = php_stream_open_wrapper_ex(filename, "w", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL);
+
+ block_length = PHP_OCI_LOB_BUFFER_SIZE;
+ if (block_length > length) {
+ block_length = length;
+ }
+
+ while(length > 0) {
+ ub4 tmp_bytes_read = 0;
+ if (php_oci_lob_read(descriptor, block_length, start, &buffer, &tmp_bytes_read TSRMLS_CC)) {
+ php_stream_close(stream);
+ RETURN_FALSE;
+ }
+ if (tmp_bytes_read && !php_stream_write(stream, buffer, tmp_bytes_read)) {
+ php_stream_close(stream);
+ efree(buffer);
+ RETURN_FALSE;
+ }
+ if (buffer) {
+ efree(buffer);
+ }
+
+ length -= tmp_bytes_read;
+ descriptor->lob_current_position += tmp_bytes_read;
+ start += tmp_bytes_read;
+
+ if (block_length > length) {
+ block_length = length;
+ }
+ }
+
+ php_stream_close(stream);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_write_temporary(string var [, int lob_type])
+ Writes temporary blob */
+PHP_FUNCTION(oci_lob_write_temporary)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+ char *data;
+ int data_len;
+ long type = OCI_TEMP_CLOB;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &type) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os|l", &z_descriptor, oci_lob_class_entry_ptr, &data, &data_len, &type) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_write_tmp(descriptor, type, data, data_len TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_lob_close()
+ Closes lob descriptor */
+PHP_FUNCTION(oci_lob_close)
+{
+ zval **tmp, *z_descriptor = getThis();
+ php_oci_descriptor *descriptor;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_descriptor, oci_lob_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR(*tmp, descriptor);
+
+ if (php_oci_lob_close(descriptor TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto object oci_new_descriptor(resource connection [, int type])
+ Initialize a new empty descriptor LOB/FILE (LOB is default) */
+PHP_FUNCTION(oci_new_descriptor)
+{
+ zval *z_connection;
+ php_oci_connection *connection;
+ php_oci_descriptor *descriptor;
+ long type = OCI_DTYPE_LOB;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_connection, &type) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ /* php_oci_lob_create() checks type */
+ descriptor = php_oci_lob_create(connection, type TSRMLS_CC);
+
+ if (!descriptor) {
+ RETURN_NULL();
+ }
+
+ object_init_ex(return_value, oci_lob_class_entry_ptr);
+ add_property_resource(return_value, "descriptor", descriptor->id);
+}
+/* }}} */
+
+/* {{{ proto bool oci_rollback(resource connection)
+ Rollback the current context */
+PHP_FUNCTION(oci_rollback)
+{
+ zval *z_connection;
+ php_oci_connection *connection;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ if (connection->descriptors) {
+ php_oci_connection_descriptors_free(connection TSRMLS_CC);
+ }
+
+ if (php_oci_connection_rollback(connection TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_commit(resource connection)
+ Commit the current context */
+PHP_FUNCTION(oci_commit)
+{
+ zval *z_connection;
+ php_oci_connection *connection;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ if (connection->descriptors) {
+ php_oci_connection_descriptors_free(connection TSRMLS_CC);
+ }
+
+ if (php_oci_connection_commit(connection TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string oci_field_name(resource stmt, int col)
+ Tell the name of a column */
+PHP_FUNCTION(oci_field_name)
+{
+ php_oci_out_column *column;
+
+ if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
+ RETURN_STRINGL(column->name, column->name_len, 1);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto int oci_field_size(resource stmt, int col)
+ Tell the maximum data size of a column */
+PHP_FUNCTION(oci_field_size)
+{
+ php_oci_out_column *column;
+
+ if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
+ /* Handle data type of LONG */
+ if (column->data_type == SQLT_LNG){
+ RETURN_LONG(column->storage_size4);
+ }
+ RETURN_LONG(column->data_size);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto int oci_field_scale(resource stmt, int col)
+ Tell the scale of a column */
+PHP_FUNCTION(oci_field_scale)
+{
+ php_oci_out_column *column;
+
+ if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
+ RETURN_LONG(column->scale);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto int oci_field_precision(resource stmt, int col)
+ Tell the precision of a column */
+PHP_FUNCTION(oci_field_precision)
+{
+ php_oci_out_column *column;
+
+ if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
+ RETURN_LONG(column->precision);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto mixed oci_field_type(resource stmt, int col)
+ Tell the data type of a column */
+PHP_FUNCTION(oci_field_type)
+{
+ php_oci_out_column *column;
+
+ column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+
+ if (!column) {
+ RETURN_FALSE;
+ }
+
+ switch (column->data_type) {
+#ifdef SQLT_TIMESTAMP
+ case SQLT_TIMESTAMP:
+ RETVAL_STRING("TIMESTAMP",1);
+ break;
+#endif
+#ifdef SQLT_TIMESTAMP_TZ
+ case SQLT_TIMESTAMP_TZ:
+ RETVAL_STRING("TIMESTAMP WITH TIMEZONE",1);
+ break;
+#endif
+#ifdef SQLT_TIMESTAMP_LTZ
+ case SQLT_TIMESTAMP_LTZ:
+ RETVAL_STRING("TIMESTAMP WITH LOCAL TIMEZONE",1);
+ break;
+#endif
+#ifdef SQLT_INTERVAL_YM
+ case SQLT_INTERVAL_YM:
+ RETVAL_STRING("INTERVAL YEAR TO MONTH",1);
+ break;
+#endif
+#ifdef SQLT_INTERVAL_DS
+ case SQLT_INTERVAL_DS:
+ RETVAL_STRING("INTERVAL DAY TO SECOND",1);
+ break;
+#endif
+ case SQLT_DAT:
+ RETVAL_STRING("DATE",1);
+ break;
+ case SQLT_NUM:
+ RETVAL_STRING("NUMBER",1);
+ break;
+ case SQLT_LNG:
+ RETVAL_STRING("LONG",1);
+ break;
+ case SQLT_BIN:
+ RETVAL_STRING("RAW",1);
+ break;
+ case SQLT_LBI:
+ RETVAL_STRING("LONG RAW",1);
+ break;
+ case SQLT_CHR:
+ RETVAL_STRING("VARCHAR2",1);
+ break;
+ case SQLT_RSET:
+ RETVAL_STRING("REFCURSOR",1);
+ break;
+ case SQLT_AFC:
+ RETVAL_STRING("CHAR",1);
+ break;
+ case SQLT_BLOB:
+ RETVAL_STRING("BLOB",1);
+ break;
+ case SQLT_CLOB:
+ RETVAL_STRING("CLOB",1);
+ break;
+ case SQLT_BFILE:
+ RETVAL_STRING("BFILE",1);
+ break;
+ case SQLT_RDD:
+ RETVAL_STRING("ROWID",1);
+ break;
+ default:
+ RETVAL_LONG(column->data_type);
+ }
+}
+/* }}} */
+
+/* {{{ proto int oci_field_type_raw(resource stmt, int col)
+ Tell the raw oracle data type of a column */
+PHP_FUNCTION(oci_field_type_raw)
+{
+ php_oci_out_column *column;
+
+ column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+ if (column) {
+ RETURN_LONG(column->data_type);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_field_is_null(resource stmt, int col)
+ Tell whether a column is NULL */
+PHP_FUNCTION(oci_field_is_null)
+{
+ php_oci_out_column *column;
+
+ if ( ( column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0) ) ) {
+ if (column->indicator == -1) {
+ RETURN_TRUE;
+ }
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto void oci_internal_debug(int onoff)
+ Toggle internal debugging output for the OCI extension */
+PHP_FUNCTION(oci_internal_debug)
+{
+ zend_bool on_off;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &on_off) == FAILURE) {
+ return;
+ }
+ OCI_G(debug_mode) = on_off;
+}
+/* }}} */
+
+/* {{{ proto bool oci_execute(resource stmt [, int mode])
+ Execute a parsed statement */
+PHP_FUNCTION(oci_execute)
+{
+ zval *z_statement;
+ php_oci_statement *statement;
+ long mode = OCI_COMMIT_ON_SUCCESS;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &z_statement, &mode) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (php_oci_statement_execute(statement, mode TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_cancel(resource stmt)
+ Cancel reading from a cursor */
+PHP_FUNCTION(oci_cancel)
+{
+ zval *z_statement;
+ php_oci_statement *statement;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (php_oci_statement_cancel(statement TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_fetch(resource stmt)
+ Prepare a new row of data for reading */
+PHP_FUNCTION(oci_fetch)
+{
+ zval *z_statement;
+ php_oci_statement *statement;
+ ub4 nrows = 1; /* only one row at a time is supported for now */
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ocifetchinto(resource stmt, array &output [, int mode])
+ Fetch a row of result data into an array */
+PHP_FUNCTION(ocifetchinto)
+{
+ php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_NUM, 3);
+}
+/* }}} */
+
+/* {{{ proto int oci_fetch_all(resource stmt, array &output[, int skip[, int maxrows[, int flags]]])
+ Fetch all rows of result data into an array */
+PHP_FUNCTION(oci_fetch_all)
+{
+ zval *z_statement, *array, *element, *tmp;
+ php_oci_statement *statement;
+ php_oci_out_column **columns;
+ zval ***outarrs;
+ ub4 nrows = 1;
+ int i;
+ long rows = 0, flags = 0, skip = 0, maxrows = -1;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz/|lll", &z_statement, &array, &skip, &maxrows, &flags) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ zval_dtor(array);
+ array_init(array);
+
+ while (skip--) {
+ if (php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
+ RETURN_LONG(0);
+ }
+ }
+
+ if (flags & PHP_OCI_FETCHSTATEMENT_BY_ROW) {
+ columns = safe_emalloc(statement->ncolumns, sizeof(php_oci_out_column *), 0);
+
+ for (i = 0; i < statement->ncolumns; i++) {
+ columns[ i ] = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+ }
+
+ while (!php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
+ zval *row;
+
+ MAKE_STD_ZVAL(row);
+ array_init(row);
+
+ for (i = 0; i < statement->ncolumns; i++) {
+ MAKE_STD_ZVAL(element);
+ php_oci_column_to_zval(columns[ i ], element, PHP_OCI_RETURN_LOBS TSRMLS_CC);
+
+ if (flags & PHP_OCI_NUM) {
+ zend_hash_next_index_insert(Z_ARRVAL_P(row), &element, sizeof(zval*), NULL);
+ } else { /* default to ASSOC */
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
+ /* zend_symtable_update is only available in 5.2+ */
+ zend_symtable_update(Z_ARRVAL_P(row), columns[ i ]->name, columns[ i ]->name_len+1, &element, sizeof(zval*), NULL);
+#else
+ /* This code path means Bug #45458 will remain broken when OCI8 is built with PHP 4 */
+ zend_hash_update(Z_ARRVAL_P(row), columns[ i ]->name, columns[ i ]->name_len+1, &element, sizeof(zval*), NULL);
+#endif
+ }
+ }
+
+ zend_hash_next_index_insert(Z_ARRVAL_P(array), &row, sizeof(zval*), NULL);
+ rows++;
+
+ if (maxrows != -1 && rows == maxrows) {
+ php_oci_statement_cancel(statement TSRMLS_CC);
+ break;
+ }
+ }
+ efree(columns);
+
+ } else { /* default to BY_COLUMN */
+ columns = safe_emalloc(statement->ncolumns, sizeof(php_oci_out_column *), 0);
+ outarrs = safe_emalloc(statement->ncolumns, sizeof(zval*), 0);
+
+ if (flags & PHP_OCI_NUM) {
+ for (i = 0; i < statement->ncolumns; i++) {
+ columns[ i ] = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+
+ MAKE_STD_ZVAL(tmp);
+ array_init(tmp);
+ zend_hash_next_index_insert(Z_ARRVAL_P(array), &tmp, sizeof(zval*), (void **) &(outarrs[ i ]));
+ }
+ } else { /* default to ASSOC */
+ for (i = 0; i < statement->ncolumns; i++) {
+ columns[ i ] = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+
+ MAKE_STD_ZVAL(tmp);
+ array_init(tmp);
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
+ /* zend_symtable_update is only available in 5.2+ */
+ zend_symtable_update(Z_ARRVAL_P(array), columns[ i ]->name, columns[ i ]->name_len+1, (void *) &tmp, sizeof(zval*), (void **) &(outarrs[ i ]));
+#else
+ /* This code path means Bug #45458 will remain broken when OCI8 is built with PHP 4 */
+ zend_hash_update(Z_ARRVAL_P(array), columns[ i ]->name, columns[ i ]->name_len+1, (void *) &tmp, sizeof(zval*), (void **) &(outarrs[ i ]));
+#endif
+ }
+ }
+
+ while (!php_oci_statement_fetch(statement, nrows TSRMLS_CC)) {
+ for (i = 0; i < statement->ncolumns; i++) {
+ MAKE_STD_ZVAL(element);
+ php_oci_column_to_zval(columns[ i ], element, PHP_OCI_RETURN_LOBS TSRMLS_CC);
+ zend_hash_index_update((*(outarrs[ i ]))->value.ht, rows, (void *)&element, sizeof(zval*), NULL);
+ }
+
+ rows++;
+
+ if (maxrows != -1 && rows == maxrows) {
+ php_oci_statement_cancel(statement TSRMLS_CC);
+ break;
+ }
+ }
+
+ efree(columns);
+ efree(outarrs);
+ }
+
+ RETURN_LONG(rows);
+}
+/* }}} */
+
+/* {{{ proto object oci_fetch_object( resource stmt )
+ Fetch a result row as an object */
+PHP_FUNCTION(oci_fetch_object)
+{
+ php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_ASSOC | PHP_OCI_RETURN_NULLS, 2);
+
+ if (Z_TYPE_P(return_value) == IS_ARRAY) {
+ object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
+ }
+}
+/* }}} */
+
+/* {{{ proto array oci_fetch_row( resource stmt )
+ Fetch a result row as an enumerated array */
+PHP_FUNCTION(oci_fetch_row)
+{
+ php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_NUM | PHP_OCI_RETURN_NULLS, 1);
+}
+/* }}} */
+
+/* {{{ proto array oci_fetch_assoc( resource stmt )
+ Fetch a result row as an associative array */
+PHP_FUNCTION(oci_fetch_assoc)
+{
+ php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_ASSOC | PHP_OCI_RETURN_NULLS, 1);
+}
+/* }}} */
+
+/* {{{ proto array oci_fetch_array( resource stmt [, int mode ])
+ Fetch a result row as an array */
+PHP_FUNCTION(oci_fetch_array)
+{
+ php_oci_fetch_row(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_OCI_BOTH | PHP_OCI_RETURN_NULLS, 2);
+}
+/* }}} */
+
+/* {{{ proto bool oci_free_statement(resource stmt)
+ Free all resources associated with a statement */
+PHP_FUNCTION(oci_free_statement)
+{
+ zval *z_statement;
+ php_oci_statement *statement;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ zend_list_delete(statement->id);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_close(resource connection)
+ Disconnect from database */
+PHP_FUNCTION(oci_close)
+{
+ /* oci_close for pconnect (if old_oci_close_semantics not set) would
+ * release the connection back to the client-side session pool (and to the
+ * server-side pool if Database Resident Connection Pool is being used).
+ * Subsequent pconnects in the same script are not guaranteed to get the
+ * same database session.
+ */
+
+ zval *z_connection;
+ php_oci_connection *connection;
+
+ if (OCI_G(old_oci_close_semantics)) {
+ /* do nothing to keep BC */
+ return;
+ }
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+ zend_list_delete(connection->rsrc_id);
+
+ ZVAL_NULL(z_connection);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto resource oci_new_connect(string user, string pass [, string db])
+ Connect to an Oracle database and log on. Returns a new session. */
+PHP_FUNCTION(oci_new_connect)
+{
+ php_oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
+}
+/* }}} */
+
+/* {{{ proto resource oci_connect(string user, string pass [, string db [, string charset [, int session_mode ]])
+ Connect to an Oracle database and log on. Returns a new session. */
+PHP_FUNCTION(oci_connect)
+{
+ php_oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
+}
+/* }}} */
+
+/* {{{ proto resource oci_pconnect(string user, string pass [, string db [, string charset ]])
+ Connect to an Oracle database using a persistent connection and log on. Returns a new session. */
+PHP_FUNCTION(oci_pconnect)
+{
+ php_oci_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
+}
+/* }}} */
+
+/* {{{ proto array oci_error([resource stmt|connection|global])
+ Return the last error of stmt|connection|global. If no error happened returns false. */
+PHP_FUNCTION(oci_error)
+{
+ zval *arg = NULL;
+ php_oci_statement *statement;
+ php_oci_connection *connection;
+ text *errbuf;
+ sb4 errcode = 0;
+ sword error = OCI_SUCCESS;
+ dvoid *errh = NULL;
+ ub2 error_offset = 0;
+ text *sqltext = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &arg) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_NUM_ARGS() > 0) {
+ statement = (php_oci_statement *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_statement);
+
+ if (statement) {
+ errh = statement->err;
+ error = statement->errcode;
+
+ if (php_oci_fetch_sqltext_offset(statement, &sqltext, &error_offset TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ goto go_out;
+ }
+
+ connection = (php_oci_connection *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_connection);
+ if (connection) {
+ errh = connection->err;
+ error = connection->errcode;
+ goto go_out;
+ }
+
+ connection = (php_oci_connection *) zend_fetch_resource(&arg TSRMLS_CC, -1, NULL, NULL, 1, le_pconnection);
+ if (connection) {
+ errh = connection->err;
+ error = connection->errcode;
+ goto go_out;
+ }
+ } else {
+ errh = OCI_G(err);
+ error = OCI_G(errcode);
+ }
+
+go_out:
+ if (error == OCI_SUCCESS) { /* no error set in the handle */
+ RETURN_FALSE;
+ }
+
+ if (!errh) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Oci_error: unable to find error handle");
+ RETURN_FALSE;
+ }
+
+ errcode = php_oci_fetch_errmsg(errh, &errbuf TSRMLS_CC);
+
+ if (errcode) {
+ array_init(return_value);
+ add_assoc_long(return_value, "code", errcode);
+ add_assoc_string(return_value, "message", (char*) errbuf, 0);
+ add_assoc_long(return_value, "offset", error_offset);
+ add_assoc_string(return_value, "sqltext", sqltext ? (char *) sqltext : "", 1);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto int oci_num_fields(resource stmt)
+ Return the number of result columns in a statement */
+PHP_FUNCTION(oci_num_fields)
+{
+ zval *z_statement;
+ php_oci_statement *statement;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ RETURN_LONG(statement->ncolumns);
+}
+/* }}} */
+
+/* {{{ proto resource oci_parse(resource connection, string query)
+ Parse a query and return a statement */
+PHP_FUNCTION(oci_parse)
+{
+ zval *z_connection;
+ php_oci_connection *connection;
+ php_oci_statement *statement;
+ char *query;
+ int query_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &query, &query_len) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ statement = php_oci_statement_create(connection, query, query_len TSRMLS_CC);
+
+ if (statement) {
+ RETURN_RESOURCE(statement->id);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_set_prefetch(resource stmt, int prefetch_rows)
+ Sets the number of rows to be prefetched on execute to prefetch_rows for stmt */
+PHP_FUNCTION(oci_set_prefetch)
+{
+ zval *z_statement;
+ php_oci_statement *statement;
+ long size;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &z_statement, &size) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (php_oci_statement_set_prefetch(statement, size TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_set_client_identifier(resource connection, string value)
+ Sets the client identifier attribute on the connection */
+PHP_FUNCTION(oci_set_client_identifier)
+{
+ zval *z_connection;
+ php_oci_connection *connection;
+ char *client_id;
+ long client_id_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &client_id, &client_id_len) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) client_id, (ub4) client_id_len, (ub4) OCI_ATTR_CLIENT_IDENTIFIER, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_set_edition(string value)
+ Sets the edition attribute for all subsequent connections created */
+PHP_FUNCTION(oci_set_edition)
+{
+#if ((OCI_MAJOR_VERSION > 11) || ((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION >= 2)))
+ char *edition;
+ long edition_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &edition, &edition_len) == FAILURE) {
+ return;
+ }
+
+ if (OCI_G(edition)) {
+ efree(OCI_G(edition));
+ OCI_G(edition) = NULL;
+ }
+
+ if (edition) {
+ OCI_G(edition) = (char *)safe_emalloc(edition_len+1, sizeof(text), 0);
+ memcpy(OCI_G(edition), edition, edition_len);
+ OCI_G(edition)[edition_len] = '\0';
+ }
+
+ RETURN_TRUE;
+#else
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
+ RETURN_FALSE;
+#endif
+}
+/* }}} */
+
+/* {{{ proto bool oci_set_module_name(resource connection, string value)
+ Sets the module attribute on the connection */
+PHP_FUNCTION(oci_set_module_name)
+{
+#if (OCI_MAJOR_VERSION >= 10)
+ zval *z_connection;
+ php_oci_connection *connection;
+ char *module;
+ long module_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &module, &module_len) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) module, (ub4) module_len, (ub4) OCI_ATTR_MODULE, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+#else
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
+ RETURN_FALSE;
+#endif
+}
+/* }}} */
+
+/* {{{ proto bool oci_set_action(resource connection, string value)
+ Sets the action attribute on the connection */
+PHP_FUNCTION(oci_set_action)
+{
+#if (OCI_MAJOR_VERSION >= 10)
+ zval *z_connection;
+ php_oci_connection *connection;
+ char *action;
+ long action_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &action, &action_len) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) action, (ub4) action_len, (ub4) OCI_ATTR_ACTION, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+#else
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
+ RETURN_FALSE;
+#endif
+}
+/* }}} */
+
+/* {{{ proto bool oci_set_client_info(resource connection, string value)
+ Sets the client info attribute on the connection */
+PHP_FUNCTION(oci_set_client_info)
+{
+#if (OCI_MAJOR_VERSION >= 10)
+ zval *z_connection;
+ php_oci_connection *connection;
+ char *client_info;
+ long client_info_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_connection, &client_info, &client_info_len) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIAttrSet, ((dvoid *) connection->session, (ub4) OCI_HTYPE_SESSION, (dvoid *) client_info, (ub4) client_info_len, (ub4) OCI_ATTR_CLIENT_INFO, OCI_G(err)));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+#else
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unsupported attribute type");
+ RETURN_FALSE;
+#endif
+}
+/* }}} */
+
+/* {{{ proto bool oci_password_change(resource connection, string username, string old_password, string new_password)
+ Changes the password of an account */
+PHP_FUNCTION(oci_password_change)
+{
+ zval *z_connection;
+ char *user, *pass_old, *pass_new, *dbname;
+ int user_len, pass_old_len, pass_new_len, dbname_len;
+ php_oci_connection *connection;
+
+ /* Disable in Safe Mode */
+ if (PG(safe_mode)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "is disabled in Safe Mode");
+ RETURN_FALSE;
+ }
+
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &z_connection, &user, &user_len, &pass_old, &pass_old_len, &pass_new, &pass_new_len) == SUCCESS) {
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ if (!user_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "username cannot be empty");
+ RETURN_FALSE;
+ }
+ if (!pass_old_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "old password cannot be empty");
+ RETURN_FALSE;
+ }
+ if (!pass_new_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "new password cannot be empty");
+ RETURN_FALSE;
+ }
+
+ if (php_oci_password_change(connection, user, user_len, pass_old, pass_old_len, pass_new, pass_new_len TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+ } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ssss", &dbname, &dbname_len, &user, &user_len, &pass_old, &pass_old_len, &pass_new, &pass_new_len) == SUCCESS) {
+
+ if (!user_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "username cannot be empty");
+ RETURN_FALSE;
+ }
+ if (!pass_old_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "old password cannot be empty");
+ RETURN_FALSE;
+ }
+ if (!pass_new_len) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "new password cannot be empty");
+ RETURN_FALSE;
+ }
+
+ connection = php_oci_do_connect_ex(user, user_len, pass_old, pass_old_len, pass_new, pass_new_len, dbname, dbname_len, NULL, OCI_DEFAULT, 0, 0 TSRMLS_CC);
+ if (!connection) {
+ RETURN_FALSE;
+ }
+ RETURN_RESOURCE(connection->rsrc_id);
+ }
+ WRONG_PARAM_COUNT;
+}
+/* }}} */
+
+/* {{{ proto resource oci_new_cursor(resource connection)
+ Return a new cursor (Statement-Handle) - use this to bind ref-cursors! */
+PHP_FUNCTION(oci_new_cursor)
+{
+ zval *z_connection;
+ php_oci_connection *connection;
+ php_oci_statement *statement;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ statement = php_oci_statement_create(connection, NULL, 0 TSRMLS_CC);
+
+ if (statement) {
+ RETURN_RESOURCE(statement->id);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto string oci_result(resource stmt, mixed column)
+ Return a single column of result data */
+PHP_FUNCTION(oci_result)
+{
+ php_oci_out_column *column;
+
+ column = php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+ if(column) {
+ php_oci_column_to_zval(column, return_value, 0 TSRMLS_CC);
+ }
+ else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string oci_server_version(resource connection)
+ Return a string containing server version information */
+PHP_FUNCTION(oci_server_version)
+{
+ zval *z_connection;
+ php_oci_connection *connection;
+ char *version = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_connection) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ if (php_oci_server_get_version(connection, &version TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ RETURN_STRING(version, 0);
+}
+/* }}} */
+
+/* {{{ proto string oci_statement_type(resource stmt)
+ Return the query type of an OCI statement */
+PHP_FUNCTION(oci_statement_type)
+{
+ zval *z_statement;
+ php_oci_statement *statement;
+ ub2 type;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (php_oci_statement_get_type(statement, &type TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ switch (type) {
+ case OCI_STMT_SELECT:
+ RETVAL_STRING("SELECT",1);
+ break;
+ case OCI_STMT_UPDATE:
+ RETVAL_STRING("UPDATE",1);
+ break;
+ case OCI_STMT_DELETE:
+ RETVAL_STRING("DELETE",1);
+ break;
+ case OCI_STMT_INSERT:
+ RETVAL_STRING("INSERT",1);
+ break;
+ case OCI_STMT_CREATE:
+ RETVAL_STRING("CREATE",1);
+ break;
+ case OCI_STMT_DROP:
+ RETVAL_STRING("DROP",1);
+ break;
+ case OCI_STMT_ALTER:
+ RETVAL_STRING("ALTER",1);
+ break;
+ case OCI_STMT_BEGIN:
+ RETVAL_STRING("BEGIN",1);
+ break;
+ case OCI_STMT_DECLARE:
+ RETVAL_STRING("DECLARE",1);
+ break;
+ case OCI_STMT_CALL:
+ RETVAL_STRING("CALL",1);
+ break;
+ default:
+ RETVAL_STRING("UNKNOWN",1);
+ }
+}
+/* }}} */
+
+/* {{{ proto int oci_num_rows(resource stmt)
+ Return the row count of an OCI statement */
+PHP_FUNCTION(oci_num_rows)
+{
+ zval *z_statement;
+ php_oci_statement *statement;
+ ub4 rowcount;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_statement) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
+
+ if (php_oci_statement_get_numrows(statement, &rowcount TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(rowcount);
+}
+/* }}} */
+
+/* {{{ proto bool oci_free_collection()
+ Deletes collection object*/
+PHP_FUNCTION(oci_free_collection)
+{
+ zval **tmp, *z_collection = getThis();
+ php_oci_collection *collection;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
+
+ zend_list_delete(collection->id);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_collection_append(string value)
+ Append an object to the collection */
+PHP_FUNCTION(oci_collection_append)
+{
+ zval **tmp, *z_collection = getThis();
+ php_oci_collection *collection;
+ char *value;
+ int value_len;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Os", &z_collection, oci_coll_class_entry_ptr, &value, &value_len) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
+
+ if (php_oci_collection_append(collection, value, value_len TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string oci_collection_element_get(int ndx)
+ Retrieve the value at collection index ndx */
+PHP_FUNCTION(oci_collection_element_get)
+{
+ zval **tmp, *z_collection = getThis();
+ php_oci_collection *collection;
+ long element_index;
+ zval *value;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &element_index) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &z_collection, oci_coll_class_entry_ptr, &element_index) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
+
+ if (php_oci_collection_element_get(collection, element_index, &value TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ *return_value = *value;
+ zval_copy_ctor(return_value);
+ zval_ptr_dtor(&value);
+}
+/* }}} */
+
+/* {{{ proto bool oci_collection_assign(object from)
+ Assign a collection from another existing collection */
+PHP_FUNCTION(oci_collection_assign)
+{
+ zval **tmp_dest, **tmp_from, *z_collection_dest = getThis(), *z_collection_from;
+ php_oci_collection *collection_dest, *collection_from;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_collection_from, oci_coll_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &z_collection_dest, oci_coll_class_entry_ptr, &z_collection_from, oci_coll_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection_dest), "collection", sizeof("collection"), (void **)&tmp_dest) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property. The first argument should be valid collection object");
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection_from), "collection", sizeof("collection"), (void **)&tmp_from) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property. The second argument should be valid collection object");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp_dest, collection_dest);
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp_from, collection_from);
+
+ if (php_oci_collection_assign(collection_dest, collection_from TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool oci_collection_element_assign(int index, string val)
+ Assign element val to collection at index ndx */
+PHP_FUNCTION(oci_collection_element_assign)
+{
+ zval **tmp, *z_collection = getThis();
+ php_oci_collection *collection;
+ int value_len;
+ long element_index;
+ char *value;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &element_index, &value, &value_len) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ols", &z_collection, oci_coll_class_entry_ptr, &element_index, &value, &value_len) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
+
+ if (php_oci_collection_element_set(collection, element_index, value, value_len TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int oci_collection_size()
+ Return the size of a collection */
+PHP_FUNCTION(oci_collection_size)
+{
+ zval **tmp, *z_collection = getThis();
+ php_oci_collection *collection;
+ sb4 size = 0;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
+
+ if (php_oci_collection_size(collection, &size TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(size);
+}
+/* }}} */
+
+/* {{{ proto int oci_collection_max()
+ Return the max value of a collection. For a varray this is the maximum length of the array */
+PHP_FUNCTION(oci_collection_max)
+{
+ zval **tmp, *z_collection = getThis();
+ php_oci_collection *collection;
+ long max;
+
+ if (!getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_collection, oci_coll_class_entry_ptr) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
+
+ if (php_oci_collection_max(collection, &max TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(max);
+}
+/* }}} */
+
+/* {{{ proto bool oci_collection_trim(int num)
+ Trim num elements from the end of a collection */
+PHP_FUNCTION(oci_collection_trim)
+{
+ zval **tmp, *z_collection = getThis();
+ php_oci_collection *collection;
+ long trim_size;
+
+ if (getThis()) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &trim_size) == FAILURE) {
+ return;
+ }
+ }
+ else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &z_collection, oci_coll_class_entry_ptr, &trim_size) == FAILURE) {
+ return;
+ }
+ }
+
+ if (zend_hash_find(Z_OBJPROP_P(z_collection), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
+ RETURN_FALSE;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION(*tmp, collection);
+
+ if (php_oci_collection_trim(collection, trim_size TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto object oci_new_collection(resource connection, string tdo [, string schema])
+ Initialize a new collection */
+PHP_FUNCTION(oci_new_collection)
+{
+ zval *z_connection;
+ php_oci_connection *connection;
+ php_oci_collection *collection;
+ char *tdo, *schema = NULL;
+ int tdo_len, schema_len = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|s", &z_connection, &tdo, &tdo_len, &schema, &schema_len) == FAILURE) {
+ return;
+ }
+
+ PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
+
+ if ( (collection = php_oci_collection_create(connection, tdo, tdo_len, schema, schema_len TSRMLS_CC)) ) {
+ object_init_ex(return_value, oci_coll_class_entry_ptr);
+ add_property_resource(return_value, "collection", collection->id);
+ }
+ else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+#endif /* HAVE_OCI8 */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/oci8_lob.c b/oci8_lob.c
new file mode 100644
index 0000000000..2b87dbb3d2
--- /dev/null
+++ b/oci8_lob.c
@@ -0,0 +1,953 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@php.net> |
+ | Thies C. Arntzen <thies@thieso.net> |
+ | |
+ | Collection support by Andy Sautins <asautins@veripost.net> |
+ | Temporary LOB support by David Benson <dbenson@mancala.com> |
+ | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
+ | |
+ | Redesigned by: Antony Dovgal <antony@zend.com> |
+ | Andi Gutmans <andi@zend.com> |
+ | Wez Furlong <wez@omniti.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "ext/standard/info.h"
+#include "php_ini.h"
+
+#if HAVE_OCI8
+
+#include "php_oci8.h"
+#include "php_oci8_int.h"
+
+/* for import/export functions */
+#include <fcntl.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* {{{ php_oci_lob_create()
+ Create LOB descriptor and allocate all the resources needed */
+php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long type TSRMLS_DC)
+{
+ php_oci_descriptor *descriptor;
+
+ switch (type) {
+ case OCI_DTYPE_FILE:
+ case OCI_DTYPE_LOB:
+ case OCI_DTYPE_ROWID:
+ /* these three are allowed */
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown descriptor type %ld", type);
+ return NULL;
+ break;
+ }
+
+ descriptor = ecalloc(1, sizeof(php_oci_descriptor));
+ descriptor->type = type;
+ descriptor->connection = connection;
+ zend_list_addref(descriptor->connection->rsrc_id);
+
+ PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0));
+
+ if (OCI_G(errcode) != OCI_SUCCESS) {
+ OCI_G(errcode) = php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, OCI_G(errcode));
+ efree(descriptor);
+ return NULL;
+ }
+
+ PHP_OCI_REGISTER_RESOURCE(descriptor, le_descriptor);
+
+ descriptor->lob_current_position = 0;
+ descriptor->lob_size = -1; /* we should set it to -1 to know, that it's just not initialized */
+ descriptor->buffering = PHP_OCI_LOB_BUFFER_DISABLED; /* buffering is off by default */
+ descriptor->charset_form = SQLCS_IMPLICIT; /* default value */
+ descriptor->charset_id = connection->charset;
+ descriptor->is_open = 0;
+
+ if (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE) {
+ /* add Lobs & Files to hash. we'll flush them at the end */
+ if (!connection->descriptors) {
+ ALLOC_HASHTABLE(connection->descriptors);
+ zend_hash_init(connection->descriptors, 0, NULL, php_oci_descriptor_flush_hash_dtor, 0);
+ connection->descriptor_count = 0;
+ }
+
+ descriptor->index = (connection->descriptor_count)++;
+ if (connection->descriptor_count == LONG_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal descriptor counter has reached limit");
+ php_oci_connection_descriptors_free(connection TSRMLS_CC);
+ return NULL;
+ }
+
+ zend_hash_index_update(connection->descriptors,descriptor->index,&descriptor,sizeof(php_oci_descriptor *),NULL);
+ }
+ return descriptor;
+
+} /* }}} */
+
+/* {{{ php_oci_lob_get_length()
+ Get length of the LOB. The length is cached so we don't need to ask Oracle every time */
+int php_oci_lob_get_length (php_oci_descriptor *descriptor, ub4 *length TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+
+ *length = 0;
+
+ if (descriptor->lob_size >= 0) {
+ *length = descriptor->lob_size;
+ return 0;
+ } else {
+ if (descriptor->type == OCI_DTYPE_FILE) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY));
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobGetLength, (connection->svc, connection->err, descriptor->descriptor, (ub4 *)length));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ descriptor->lob_size = *length;
+
+ if (descriptor->type == OCI_DTYPE_FILE) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ }
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_callback()
+ Append LOB portion to a memory buffer */
+#if defined(HAVE_OCI_LOB_READ2)
+sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, oraub8 len, ub1 piece, dvoid **changed_bufpp, oraub8 *changed_lenp)
+#else
+sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, ub4 len, ub1 piece)
+#endif
+{
+ ub4 lenp = (ub4) len;
+ php_oci_lob_ctx *ctx = (php_oci_lob_ctx *)ctxp;
+
+ switch (piece)
+ {
+ case OCI_LAST_PIECE:
+ if ((*(ctx->lob_len) + lenp) > (ctx->alloc_len)) {
+ /* this should not happen ever */
+ *(ctx->lob_data) = NULL;
+ *(ctx->lob_len) = 0;
+ return OCI_ERROR;
+ }
+ memcpy(*(ctx->lob_data) + *(ctx->lob_len), bufxp, (size_t) lenp);
+ *(ctx->lob_len) += lenp;
+ *(*(ctx->lob_data) + *(ctx->lob_len)) = 0x00;
+ return OCI_CONTINUE;
+
+ case OCI_FIRST_PIECE:
+ case OCI_NEXT_PIECE:
+ if ((*(ctx->lob_len) + lenp) > ctx->alloc_len) {
+ /* this should not happen ever */
+ *(ctx->lob_data) = NULL;
+ *(ctx->lob_len) = 0;
+ return OCI_ERROR;
+ }
+ memcpy(*(ctx->lob_data) + *(ctx->lob_len), bufxp, (size_t) lenp);
+ *(ctx->lob_len) += lenp;
+ return OCI_CONTINUE;
+
+ default: {
+ TSRMLS_FETCH();
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected LOB piece id received (value:%d)", piece);
+ *(ctx->lob_data) = NULL;
+ *(ctx->lob_len) = 0;
+ return OCI_ERROR;
+ }
+ }
+}
+/* }}} */
+
+/* {{{ php_oci_lob_calculate_buffer() */
+static inline int php_oci_lob_calculate_buffer(php_oci_descriptor *descriptor, long read_length TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+ ub4 chunk_size;
+
+ if (descriptor->type == OCI_DTYPE_FILE) {
+ return read_length;
+ }
+
+ if (!descriptor->chunk_size) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobGetChunkSize, (connection->svc, connection->err, descriptor->descriptor, &chunk_size));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return read_length; /* we have to return original length here */
+ }
+ descriptor->chunk_size = chunk_size;
+ }
+
+ if ((read_length % descriptor->chunk_size) != 0) {
+ return descriptor->chunk_size * ((read_length / descriptor->chunk_size) + 1);
+ }
+ return read_length;
+}
+/* }}} */
+
+/* {{{ php_oci_lob_read()
+ Read specified portion of the LOB into the buffer */
+int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long initial_offset, char **data, ub4 *data_len TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+ ub4 length = 0;
+ int buffer_size = PHP_OCI_LOB_BUFFER_SIZE;
+ php_oci_lob_ctx ctx;
+ ub1 *bufp;
+#if defined(HAVE_OCI_LOB_READ2)
+ oraub8 bytes_read, offset = 0;
+ oraub8 requested_len = read_length; /* this is by default */
+ oraub8 chars_read = 0;
+#else
+ int bytes_read, offset = 0;
+ int requested_len = read_length; /* this is by default */
+#endif
+ int is_clob = 0;
+ sb4 bytes_per_char = 1;
+
+ *data_len = 0;
+ *data = NULL;
+
+ ctx.lob_len = data_len;
+ ctx.lob_data = data;
+ ctx.alloc_len = 0;
+
+ if (php_oci_lob_get_length(descriptor, &length TSRMLS_CC)) {
+ return 1;
+ }
+
+ if (length <= 0) {
+ return 0;
+ }
+
+ if (initial_offset > length) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be less than size of the LOB");
+ return 1;
+ }
+
+ if (read_length == -1) {
+ requested_len = length;
+ }
+
+ if (requested_len > (length - initial_offset)) {
+ requested_len = length - initial_offset;
+ }
+
+ if (requested_len <= 0) {
+ return 0;
+ }
+
+ offset = initial_offset;
+
+ if (descriptor->type == OCI_DTYPE_FILE) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ } else {
+ ub2 charset_id = 0;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobCharSetId, (connection->env, connection->err, descriptor->descriptor, &charset_id));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ if (charset_id > 0) { /* charset_id is always > 0 for [N]CLOBs */
+ is_clob = 1;
+ }
+ }
+
+ if (is_clob) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCINlsNumericInfoGet, (connection->env, connection->err, &bytes_per_char, OCI_NLS_CHARSET_MAXBYTESZ));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ } else {
+ /* BLOBs don't have encoding, so bytes_per_char == 1 */
+ }
+
+ ctx.alloc_len = (requested_len + 1) * bytes_per_char;
+ *data = ecalloc(bytes_per_char, requested_len + 1);
+
+#ifdef HAVE_OCI_LOB_READ2
+ if (is_clob) {
+ chars_read = requested_len;
+ bytes_read = 0;
+ } else {
+ chars_read = 0;
+ bytes_read = requested_len;
+ }
+
+ buffer_size = (requested_len < buffer_size ) ? requested_len : buffer_size; /* optimize buffer size */
+ buffer_size = php_oci_lob_calculate_buffer(descriptor, buffer_size TSRMLS_CC); /* use chunk size */
+
+ bufp = (ub1 *) ecalloc(1, buffer_size);
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobRead2,
+ (
+ connection->svc,
+ connection->err,
+ descriptor->descriptor,
+ (oraub8 *)&bytes_read, /* IN/OUT bytes toread/read */
+ (oraub8 *)&chars_read, /* IN/OUT chars toread/read */
+ (oraub8) offset + 1, /* offset (starts with 1) */
+ (dvoid *) bufp,
+ (oraub8) buffer_size, /* size of buffer */
+ OCI_FIRST_PIECE,
+ (dvoid *)&ctx,
+ (OCICallbackLobRead2) php_oci_lob_callback, /* callback... */
+ (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */
+ (ub1) descriptor->charset_form /* The character set form of the buffer data. */
+ )
+ );
+
+ efree(bufp);
+
+ if (is_clob) {
+ offset = descriptor->lob_current_position + chars_read;
+ } else {
+ offset = descriptor->lob_current_position + bytes_read;
+ }
+
+#else
+
+ bytes_read = requested_len;
+ buffer_size = (requested_len < buffer_size ) ? requested_len : buffer_size; /* optimize buffer size */
+ buffer_size = php_oci_lob_calculate_buffer(descriptor, buffer_size TSRMLS_CC); /* use chunk size */
+
+ bufp = (ub1 *) ecalloc(1, buffer_size);
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobRead,
+ (
+ connection->svc,
+ connection->err,
+ descriptor->descriptor,
+ &bytes_read, /* IN/OUT bytes toread/read */
+ offset + 1, /* offset (starts with 1) */
+ (dvoid *) bufp,
+ (ub4) buffer_size, /* size of buffer */
+ (dvoid *)&ctx,
+ (OCICallbackLobRead) php_oci_lob_callback, /* callback... */
+ (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */
+ (ub1) descriptor->charset_form /* The character set form of the buffer data. */
+ )
+ );
+
+ efree(bufp);
+ offset = descriptor->lob_current_position + bytes_read;
+
+#endif
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ if (*data) {
+ efree(*data);
+ *data = NULL;
+ }
+ *data_len = 0;
+ return 1;
+ }
+
+ descriptor->lob_current_position = (int)offset;
+
+ if (descriptor->type == OCI_DTYPE_FILE) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ if (*data) {
+ efree(*data);
+ *data = NULL;
+ }
+ *data_len = 0;
+ return 1;
+ }
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_write()
+ Write data to the LOB */
+int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, int data_len, ub4 *bytes_written TSRMLS_DC)
+{
+ OCILobLocator *lob = (OCILobLocator *) descriptor->descriptor;
+ php_oci_connection *connection = (php_oci_connection *) descriptor->connection;
+ ub4 lob_length;
+
+ *bytes_written = 0;
+ if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
+ return 1;
+ }
+
+ if (!data || data_len <= 0) {
+ return 0;
+ }
+
+ if (offset < 0) {
+ offset = 0;
+ }
+
+ if (offset > descriptor->lob_current_position) {
+ offset = descriptor->lob_current_position;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobWrite,
+ (
+ connection->svc,
+ connection->err,
+ lob,
+ (ub4 *)&data_len,
+ (ub4) offset + 1,
+ (dvoid *) data,
+ (ub4) data_len,
+ OCI_ONE_PIECE,
+ (dvoid *)0,
+ (OCICallbackLobWrite) 0,
+ (ub2) descriptor->charset_id,
+ (ub1) descriptor->charset_form
+ )
+ );
+
+ if (connection->errcode) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ *bytes_written = 0;
+ return 1;
+ }
+ *bytes_written = data_len;
+ descriptor->lob_current_position += data_len;
+
+ if (descriptor->lob_current_position > descriptor->lob_size) {
+ descriptor->lob_size = descriptor->lob_current_position;
+ }
+
+ /* marking buffer as used */
+ if (descriptor->buffering == PHP_OCI_LOB_BUFFER_ENABLED) {
+ descriptor->buffering = PHP_OCI_LOB_BUFFER_USED;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_set_buffering()
+ Turn buffering off/onn for this particular LOB */
+int php_oci_lob_set_buffering (php_oci_descriptor *descriptor, int on_off TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+
+ if (!on_off && descriptor->buffering == PHP_OCI_LOB_BUFFER_DISABLED) {
+ /* disabling when it's already off */
+ return 0;
+ }
+
+ if (on_off && descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
+ /* enabling when it's already on */
+ return 0;
+ }
+
+ if (on_off) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobEnableBuffering, (connection->svc, connection->err, descriptor->descriptor));
+ } else {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobDisableBuffering, (connection->svc, connection->err, descriptor->descriptor));
+ }
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ descriptor->buffering = on_off ? PHP_OCI_LOB_BUFFER_ENABLED : PHP_OCI_LOB_BUFFER_DISABLED;
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_get_buffering()
+ Return current buffering state for the LOB */
+int php_oci_lob_get_buffering (php_oci_descriptor *descriptor)
+{
+ if (descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
+ return 1;
+ } else {
+ return 0;
+ }
+} /* }}} */
+
+/* {{{ php_oci_lob_copy()
+ Copy one LOB (or its part) to another one */
+int php_oci_lob_copy (php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from, long length TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor_dest->connection;
+ ub4 length_dest, length_from, copy_len;
+
+ if (php_oci_lob_get_length(descriptor_dest, &length_dest TSRMLS_CC)) {
+ return 1;
+ }
+
+ if (php_oci_lob_get_length(descriptor_from, &length_from TSRMLS_CC)) {
+ return 1;
+ }
+
+ if (length == -1) {
+ copy_len = length_from - descriptor_from->lob_current_position;
+ } else {
+ copy_len = length;
+ }
+
+ if ((int)copy_len <= 0) {
+ /* silently fail, there is nothing to copy */
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobCopy,
+ (
+ connection->svc,
+ connection->err,
+ descriptor_dest->descriptor,
+ descriptor_from->descriptor,
+ copy_len,
+ descriptor_dest->lob_current_position+1,
+ descriptor_from->lob_current_position+1
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_close()
+ Close LOB */
+int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+
+ if (descriptor->is_open) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobClose, (connection->svc, connection->err, descriptor->descriptor));
+ }
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ if (php_oci_temp_lob_close(descriptor TSRMLS_CC)) {
+ return 1;
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_temp_lob_close()
+ Close Temporary LOB */
+int php_oci_temp_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+ int is_temporary;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsTemporary, (connection->env,connection->err, descriptor->descriptor, &is_temporary));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ if (is_temporary) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobFreeTemporary, (connection->svc, connection->err, descriptor->descriptor));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ }
+ return 0;
+} /* }}} */
+
+
+/* {{{ php_oci_lob_flush()
+ Flush buffers for the LOB (only if they have been used) */
+int php_oci_lob_flush(php_oci_descriptor *descriptor, long flush_flag TSRMLS_DC)
+{
+ OCILobLocator *lob = descriptor->descriptor;
+ php_oci_connection *connection = descriptor->connection;
+
+ if (!lob) {
+ return 1;
+ }
+
+ switch (flush_flag) {
+ case 0:
+ case OCI_LOB_BUFFER_FREE:
+ /* only these two are allowed */
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid flag value: %ld", flush_flag);
+ return 1;
+ break;
+ }
+
+ /* do not really flush buffer, but report success
+ * to suppress OCI error when flushing not used buffer
+ * */
+ if (descriptor->buffering != PHP_OCI_LOB_BUFFER_USED) {
+ return 0;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobFlushBuffer, (connection->svc, connection->err, lob, flush_flag));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ /* marking buffer as enabled and not used */
+ descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_free()
+ Close LOB descriptor and free associated resources */
+void php_oci_lob_free (php_oci_descriptor *descriptor TSRMLS_DC)
+{
+ if (!descriptor || !descriptor->connection) {
+ return;
+ }
+
+ if (descriptor->connection->descriptors) {
+ /* delete descriptor from the hash */
+ zend_hash_index_del(descriptor->connection->descriptors, descriptor->index);
+ if (zend_hash_num_elements(descriptor->connection->descriptors) == 0) {
+ descriptor->connection->descriptor_count = 0;
+ } else {
+ if (descriptor->index + 1 == descriptor->connection->descriptor_count) {
+ /* If the descriptor being freed is the end-most one
+ * allocated, then the descriptor_count is reduced so
+ * a future descriptor can reuse the hash table index.
+ * This can prevent the hash index range increasing in
+ * the common case that each descriptor is
+ * allocated/used/freed before another descriptor is
+ * needed. However it is possible that a script frees
+ * descriptors in arbitrary order which would prevent
+ * descriptor_count ever being reduced to zero until
+ * zend_hash_num_elements() returns 0.
+ */
+ descriptor->connection->descriptor_count--;
+ }
+ }
+ }
+
+ /* flushing Lobs & Files with buffering enabled */
+ if ((descriptor->type == OCI_DTYPE_FILE || descriptor->type == OCI_DTYPE_LOB) && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED) {
+ php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
+ }
+
+ if (descriptor->type == OCI_DTYPE_LOB) {
+ php_oci_temp_lob_close(descriptor TSRMLS_CC);
+ }
+
+ PHP_OCI_CALL(OCIDescriptorFree, (descriptor->descriptor, descriptor->type));
+
+ zend_list_delete(descriptor->connection->rsrc_id);
+ efree(descriptor);
+} /* }}} */
+
+/* {{{ php_oci_lob_import()
+ Import LOB contents from the given file */
+int php_oci_lob_import (php_oci_descriptor *descriptor, char *filename TSRMLS_DC)
+{
+ int fp;
+ ub4 loblen;
+ OCILobLocator *lob = (OCILobLocator *)descriptor->descriptor;
+ php_oci_connection *connection = descriptor->connection;
+ char buf[8192];
+ ub4 offset = 1;
+
+ if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)) {
+ return 1;
+ }
+
+ if ((fp = VCWD_OPEN(filename, O_RDONLY|O_BINARY)) == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't open file %s", filename);
+ return 1;
+ }
+
+ while ((loblen = read(fp, &buf, sizeof(buf))) > 0) {
+ PHP_OCI_CALL_RETURN(connection->errcode,
+ OCILobWrite,
+ (
+ connection->svc,
+ connection->err,
+ lob,
+ &loblen,
+ offset,
+ (dvoid *) &buf,
+ loblen,
+ OCI_ONE_PIECE,
+ (dvoid *)0,
+ (OCICallbackLobWrite) 0,
+ (ub2) descriptor->charset_id,
+ (ub1) descriptor->charset_form
+ )
+ );
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ close(fp);
+ return 1;
+ }
+ offset += loblen;
+ }
+ close(fp);
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_append()
+ Append data to the end of the LOB */
+int php_oci_lob_append (php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor_dest->connection;
+ OCILobLocator *lob_dest = descriptor_dest->descriptor;
+ OCILobLocator *lob_from = descriptor_from->descriptor;
+ ub4 dest_len, from_len;
+
+ if (php_oci_lob_get_length(descriptor_dest, &dest_len TSRMLS_CC)) {
+ return 1;
+ }
+
+ if (php_oci_lob_get_length(descriptor_from, &from_len TSRMLS_CC)) {
+ return 1;
+ }
+
+ if (from_len <= 0) {
+ return 0;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobAppend, (connection->svc, connection->err, lob_dest, lob_from));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_truncate()
+ Truncate LOB to the given length */
+int php_oci_lob_truncate (php_oci_descriptor *descriptor, long new_lob_length TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+ OCILobLocator *lob = descriptor->descriptor;
+ ub4 lob_length;
+
+ if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
+ return 1;
+ }
+
+ if (lob_length <= 0) {
+ return 0;
+ }
+
+ if (new_lob_length < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size must be greater than or equal to 0");
+ return 1;
+ }
+
+ if (new_lob_length > lob_length) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size must be less than or equal to the current LOB size");
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobTrim, (connection->svc, connection->err, lob, new_lob_length));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ descriptor->lob_size = new_lob_length;
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_erase()
+ Erase (or fill with whitespaces, depending on LOB type) the LOB (or its part) */
+int php_oci_lob_erase (php_oci_descriptor *descriptor, long offset, ub4 length, ub4 *bytes_erased TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+ OCILobLocator *lob = descriptor->descriptor;
+ ub4 lob_length;
+
+ *bytes_erased = 0;
+
+ if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
+ return 1;
+ }
+
+ if (offset == -1) {
+ offset = descriptor->lob_current_position;
+ }
+
+ if (length == -1) {
+ length = lob_length;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobErase, (connection->svc, connection->err, lob, (ub4 *)&length, offset+1));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ *bytes_erased = length;
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_is_equal()
+ Compare two LOB descriptors and figure out if they are pointing to the same LOB */
+int php_oci_lob_is_equal (php_oci_descriptor *descriptor_first, php_oci_descriptor *descriptor_second, boolean *result TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor_first->connection;
+ OCILobLocator *first_lob = descriptor_first->descriptor;
+ OCILobLocator *second_lob = descriptor_second->descriptor;
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsEqual, (connection->env, first_lob, second_lob, result));
+
+ if (connection->errcode) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_lob_write_tmp()
+ Create temporary LOB and write data to it */
+int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, ub1 type, char *data, int data_len TSRMLS_DC)
+{
+ php_oci_connection *connection = descriptor->connection;
+ OCILobLocator *lob = descriptor->descriptor;
+ ub4 bytes_written = 0;
+
+ switch (type) {
+ case OCI_TEMP_BLOB:
+ case OCI_TEMP_CLOB:
+ /* only these two are allowed */
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid temporary lob type: %d", type);
+ return 1;
+ break;
+ }
+
+ if (data_len < 0) {
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobCreateTemporary,
+ (
+ connection->svc,
+ connection->err,
+ lob,
+ OCI_DEFAULT,
+ OCI_DEFAULT,
+ type,
+ OCI_ATTR_NOCACHE,
+ OCI_DURATION_SESSION
+ )
+ );
+
+ if (connection->errcode) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(connection->errcode, OCILobOpen, (connection->svc, connection->err, lob, OCI_LOB_READWRITE));
+
+ if (connection->errcode) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return 1;
+ }
+
+ descriptor->is_open = 1;
+
+ return php_oci_lob_write(descriptor, 0, data, data_len, &bytes_written TSRMLS_CC);
+} /* }}} */
+
+#endif /* HAVE_OCI8 */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/oci8_statement.c b/oci8_statement.c
new file mode 100644
index 0000000000..b5ea74a656
--- /dev/null
+++ b/oci8_statement.c
@@ -0,0 +1,1722 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@php.net> |
+ | Thies C. Arntzen <thies@thieso.net> |
+ | |
+ | Collection support by Andy Sautins <asautins@veripost.net> |
+ | Temporary LOB support by David Benson <dbenson@mancala.com> |
+ | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
+ | |
+ | Redesigned by: Antony Dovgal <antony@zend.com> |
+ | Andi Gutmans <andi@zend.com> |
+ | Wez Furlong <wez@omniti.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "ext/standard/info.h"
+#include "php_ini.h"
+
+#if HAVE_OCI8
+
+#include "php_oci8.h"
+#include "php_oci8_int.h"
+
+/* {{{ php_oci_statement_create()
+ Create statemend handle and allocate necessary resources */
+php_oci_statement *php_oci_statement_create (php_oci_connection *connection, char *query, int query_len TSRMLS_DC)
+{
+ php_oci_statement *statement;
+
+ statement = ecalloc(1,sizeof(php_oci_statement));
+
+ if (!query_len) {
+ /* do not allocate stmt handle for refcursors, we'll get it from OCIStmtPrepare2() */
+ PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->stmt), OCI_HTYPE_STMT, 0, NULL));
+ }
+
+ PHP_OCI_CALL(OCIHandleAlloc, (connection->env, (dvoid **)&(statement->err), OCI_HTYPE_ERROR, 0, NULL));
+
+ if (query_len > 0) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIStmtPrepare2,
+ (
+ connection->svc,
+ &(statement->stmt),
+ connection->err,
+ (text *)query,
+ query_len,
+ NULL,
+ 0,
+ OCI_NTV_SYNTAX,
+ OCI_DEFAULT
+ )
+ );
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+
+ PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
+ PHP_OCI_CALL(OCIHandleFree,(statement->err, OCI_HTYPE_ERROR));
+
+ efree(statement);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return NULL;
+ }
+ }
+
+ if (query && query_len) {
+ statement->last_query = estrndup(query, query_len);
+ statement->last_query_len = query_len;
+ }
+ else {
+ statement->last_query = NULL;
+ statement->last_query_len = 0;
+ }
+
+ statement->connection = connection;
+ statement->has_data = 0;
+ statement->has_descr = 0;
+ statement->parent_stmtid = 0;
+ zend_list_addref(statement->connection->rsrc_id);
+
+ if (OCI_G(default_prefetch) >= 0) {
+ php_oci_statement_set_prefetch(statement, OCI_G(default_prefetch) TSRMLS_CC);
+ }
+
+ PHP_OCI_REGISTER_RESOURCE(statement, le_statement);
+
+ OCI_G(num_statements)++;
+
+ return statement;
+}
+/* }}} */
+
+/* {{{ php_oci_statement_set_prefetch()
+ Set prefetch buffer size for the statement (we're assuming that one row is ~1K sized) */
+int php_oci_statement_set_prefetch(php_oci_statement *statement, long size TSRMLS_DC)
+{
+ ub4 prefetch = size;
+
+ if (size < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows to be prefetched has to be greater than or equal to 0");
+ return 1;
+ }
+
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrSet, (statement->stmt, OCI_HTYPE_STMT, &prefetch, 0, OCI_ATTR_PREFETCH_ROWS, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_oci_cleanup_pre_fetch()
+ Helper function to cleanup ref-cursors and descriptors from the previous row */
+int php_oci_cleanup_pre_fetch(void *data TSRMLS_DC)
+{
+ php_oci_out_column *outcol = data;
+
+ if (!outcol->is_descr && !outcol->is_cursor)
+ return ZEND_HASH_APPLY_KEEP;
+
+ switch(outcol->data_type) {
+ case SQLT_CLOB:
+ case SQLT_BLOB:
+ case SQLT_RDD:
+ case SQLT_BFILE:
+ if (outcol->descid) {
+ zend_list_delete(outcol->descid);
+ outcol->descid = 0;
+ }
+ break;
+ case SQLT_RSET:
+ if (outcol->stmtid) {
+ zend_list_delete(outcol->stmtid);
+ outcol->stmtid = 0;
+ outcol->nested_statement = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ return ZEND_HASH_APPLY_KEEP;
+
+} /* }}} */
+
+
+/* {{{ php_oci_statement_fetch()
+ Fetch a row from the statement */
+int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC)
+{
+ int i;
+ void *handlepp;
+ ub4 typep, iterp, idxp;
+ ub1 in_outp, piecep;
+ zend_bool piecewisecols = 0;
+
+ php_oci_out_column *column;
+
+ if (statement->has_descr && statement->columns) {
+ zend_hash_apply(statement->columns, (apply_func_t) php_oci_cleanup_pre_fetch TSRMLS_CC);
+ }
+
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
+
+ if ( statement->errcode == OCI_NO_DATA || nrows == 0 ) {
+ if (statement->last_query == NULL) {
+ /* reset define-list for refcursors */
+ if (statement->columns) {
+ zend_hash_destroy(statement->columns);
+ efree(statement->columns);
+ statement->columns = NULL;
+ statement->ncolumns = 0;
+ }
+ statement->executed = 0;
+ }
+
+ statement->errcode = 0; /* OCI_NO_DATA is NO error for us!!! */
+ statement->has_data = 0;
+
+ if (nrows == 0) {
+ /* this is exactly what we requested */
+ return 0;
+ }
+ return 1;
+ }
+
+ /* reset length for all piecewise columns */
+ for (i = 0; i < statement->ncolumns; i++) {
+ column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+ if (column->piecewise) {
+ column->retlen4 = 0;
+ piecewisecols = 1;
+ }
+ }
+
+ while (statement->errcode == OCI_NEED_DATA) {
+ if (piecewisecols) {
+ PHP_OCI_CALL_RETURN(statement->errcode,
+ OCIStmtGetPieceInfo,
+ (
+ statement->stmt,
+ statement->err,
+ &handlepp,
+ &typep,
+ &in_outp,
+ &iterp,
+ &idxp,
+ &piecep
+ )
+ );
+
+ /* scan through our columns for a piecewise column with a matching handle */
+ for (i = 0; i < statement->ncolumns; i++) {
+ column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+ if (column->piecewise && handlepp == column->oci_define) {
+ if (!column->data) {
+ column->data = (text *) ecalloc(1, PHP_OCI_PIECE_SIZE + 1);
+ } else {
+ column->data = erealloc(column->data, column->retlen4 + PHP_OCI_PIECE_SIZE + 1);
+ }
+ column->cb_retlen = PHP_OCI_PIECE_SIZE;
+
+ /* and instruct fetch to fetch waiting piece into our buffer */
+ PHP_OCI_CALL(OCIStmtSetPieceInfo,
+ (
+ (void *) column->oci_define,
+ OCI_HTYPE_DEFINE,
+ statement->err,
+ ((char*)column->data) + column->retlen4,
+ &(column->cb_retlen),
+ piecep,
+ &column->indicator,
+ &column->retcode
+ )
+ );
+ }
+ }
+ }
+
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
+
+ if (piecewisecols) {
+ for (i = 0; i < statement->ncolumns; i++) {
+ column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+ if (column && column->piecewise && handlepp == column->oci_define) {
+ column->retlen4 += column->cb_retlen;
+ }
+ }
+ }
+ }
+
+ if (statement->errcode == OCI_SUCCESS_WITH_INFO || statement->errcode == OCI_SUCCESS) {
+ statement->has_data = 1;
+
+ /* do the stuff needed for OCIDefineByName */
+ for (i = 0; i < statement->ncolumns; i++) {
+ column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+ if (column == NULL) {
+ continue;
+ }
+
+ if (!column->define) {
+ continue;
+ }
+
+ zval_dtor(column->define->zval);
+ php_oci_column_to_zval(column, column->define->zval, 0 TSRMLS_CC);
+ }
+
+ return 0;
+ }
+
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+
+ statement->has_data = 0;
+
+ return 1;
+}
+/* }}} */
+
+/* {{{ php_oci_statement_get_column()
+ Get column from the result set */
+php_oci_out_column *php_oci_statement_get_column(php_oci_statement *statement, long column_index, char *column_name, int column_name_len TSRMLS_DC)
+{
+ php_oci_out_column *column = NULL;
+ int i;
+
+ if (statement->columns == NULL) { /* we release the columns at the end of a fetch */
+ return NULL;
+ }
+
+ if (column_name) {
+ for (i = 0; i < statement->ncolumns; i++) {
+ column = php_oci_statement_get_column(statement, i + 1, NULL, 0 TSRMLS_CC);
+ if (column == NULL) {
+ continue;
+ } else if (((int) column->name_len == column_name_len) && (!strncmp(column->name, column_name, column_name_len))) {
+ return column;
+ }
+ }
+ } else if (column_index != -1) {
+ if (zend_hash_index_find(statement->columns, column_index, (void **)&column) == FAILURE) {
+ return NULL;
+ }
+ return column;
+ }
+
+ return NULL;
+}
+/* }}} */
+
+/* php_oci_define_callback() {{{ */
+sb4 php_oci_define_callback(dvoid *ctx, OCIDefine *define, ub4 iter, dvoid **bufpp, ub4 **alenpp, ub1 *piecep, dvoid **indpp, ub2 **rcpp)
+{
+ php_oci_out_column *outcol = (php_oci_out_column *)ctx;
+ TSRMLS_FETCH();
+
+ if (!outcol) {
+
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid context pointer value");
+ return OCI_ERROR;
+ }
+
+ switch(outcol->data_type) {
+ case SQLT_RSET: {
+ php_oci_statement *nested_stmt;
+
+ nested_stmt = php_oci_statement_create(outcol->statement->connection, NULL, 0 TSRMLS_CC);
+ if (!nested_stmt) {
+ return OCI_ERROR;
+ }
+ nested_stmt->parent_stmtid = outcol->statement->id;
+ zend_list_addref(outcol->statement->id);
+ outcol->nested_statement = nested_stmt;
+ outcol->stmtid = nested_stmt->id;
+
+ *bufpp = nested_stmt->stmt;
+ *alenpp = &(outcol->retlen4);
+ *piecep = OCI_ONE_PIECE;
+ *indpp = &(outcol->indicator);
+ *rcpp = &(outcol->retcode);
+ return OCI_CONTINUE;
+ }
+ break;
+ case SQLT_RDD:
+ case SQLT_BLOB:
+ case SQLT_CLOB:
+ case SQLT_BFILE: {
+ php_oci_descriptor *descr;
+ int dtype;
+
+ if (outcol->data_type == SQLT_BFILE) {
+ dtype = OCI_DTYPE_FILE;
+ } else if (outcol->data_type == SQLT_RDD ) {
+ dtype = OCI_DTYPE_ROWID;
+ } else {
+ dtype = OCI_DTYPE_LOB;
+ }
+
+ descr = php_oci_lob_create(outcol->statement->connection, dtype TSRMLS_CC);
+ if (!descr) {
+ return OCI_ERROR;
+ }
+ outcol->descid = descr->id;
+ descr->charset_form = outcol->charset_form;
+
+ *bufpp = descr->descriptor;
+ *alenpp = &(outcol->retlen4);
+ *piecep = OCI_ONE_PIECE;
+ *indpp = &(outcol->indicator);
+ *rcpp = &(outcol->retcode);
+
+ return OCI_CONTINUE;
+ }
+ break;
+ }
+ return OCI_ERROR;
+}
+/* }}} */
+
+/* {{{ php_oci_statement_execute()
+ Execute statement */
+int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
+{
+ php_oci_out_column *outcol;
+ php_oci_out_column column;
+ OCIParam *param = NULL;
+ text *colname;
+ ub4 counter;
+ ub2 define_type;
+ ub4 iters;
+ ub4 colcount;
+ ub2 dynamic;
+ dvoid *buf;
+
+ switch (mode) {
+ case OCI_COMMIT_ON_SUCCESS:
+ case OCI_DESCRIBE_ONLY:
+ case OCI_DEFAULT:
+ /* only these are allowed */
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid execute mode given: %d", mode);
+ return 1;
+ break;
+ }
+
+ if (!statement->stmttype) {
+ /* get statement type */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement->stmttype, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+ }
+
+ if (statement->stmttype == OCI_STMT_SELECT) {
+ iters = 0;
+ } else {
+ iters = 1;
+ }
+
+ if (statement->last_query) {
+ /* if we execute refcursors we don't have a query and
+ we don't want to execute!!! */
+
+ if (statement->binds) {
+ int result = 0;
+ zend_hash_apply_with_argument(statement->binds, (apply_func_arg_t) php_oci_bind_pre_exec, (void *)&result TSRMLS_CC);
+ if (result) {
+ return 1;
+ }
+ }
+
+ /* execute statement */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtExecute, (statement->connection->svc, statement->stmt, statement->err, iters, 0, NULL, NULL, mode));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ if (statement->binds) {
+ zend_hash_apply(statement->binds, (apply_func_t) php_oci_bind_post_exec TSRMLS_CC);
+ }
+
+ if (mode & OCI_COMMIT_ON_SUCCESS) {
+ statement->connection->needs_commit = 0;
+ } else {
+ statement->connection->needs_commit = 1;
+ }
+ }
+
+ if (statement->stmttype == OCI_STMT_SELECT && statement->executed == 0) {
+ /* we only need to do the define step is this very statement is executed the first time! */
+ statement->executed = 1;
+
+ ALLOC_HASHTABLE(statement->columns);
+ zend_hash_init(statement->columns, 13, NULL, php_oci_column_hash_dtor, 0);
+
+ counter = 1;
+
+ /* get number of columns */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (dvoid *)&colcount, (ub4 *)0, OCI_ATTR_PARAM_COUNT, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ statement->ncolumns = colcount;
+
+ for (counter = 1; counter <= colcount; counter++) {
+ memset(&column,0,sizeof(php_oci_out_column));
+
+ if (zend_hash_index_update(statement->columns, counter, &column, sizeof(php_oci_out_column), (void**) &outcol) == FAILURE) {
+ efree(statement->columns);
+ /* out of memory */
+ return 1;
+ }
+
+ /* get column */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIParamGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, statement->err, (dvoid**)&param, counter));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ /* get column datatype */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_type, (ub4 *)0, OCI_ATTR_DATA_TYPE, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ /* get character set form */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_form, (ub4 *)0, OCI_ATTR_CHARSET_FORM, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ /* get character set id */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->charset_id, (ub4 *)0, OCI_ATTR_CHARSET_ID, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ /* get size of the column */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->data_size, (dvoid *)0, OCI_ATTR_DATA_SIZE, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ outcol->storage_size4 = outcol->data_size;
+ outcol->retlen = outcol->data_size;
+
+ /* get scale of the column */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->scale, (dvoid *)0, OCI_ATTR_SCALE, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ /* get precision of the column */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&outcol->precision, (dvoid *)0, OCI_ATTR_PRECISION, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ /* get name of the column */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)param, OCI_DTYPE_PARAM, (dvoid **)&colname, (ub4 *)&outcol->name_len, (ub4)OCI_ATTR_NAME, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+ PHP_OCI_CALL(OCIDescriptorFree, (param, OCI_DTYPE_PARAM));
+
+ outcol->name = estrndup((char*) colname, outcol->name_len);
+
+ /* find a user-setted define */
+ if (statement->defines) {
+ if (zend_hash_find(statement->defines,outcol->name,outcol->name_len,(void **) &outcol->define) == SUCCESS) {
+ if (outcol->define->type) {
+ outcol->data_type = outcol->define->type;
+ }
+ }
+ }
+
+ buf = 0;
+ switch (outcol->data_type) {
+ case SQLT_RSET:
+ outcol->statement = statement; /* parent handle */
+
+ define_type = SQLT_RSET;
+ outcol->is_cursor = 1;
+ outcol->statement->has_descr = 1;
+ outcol->storage_size4 = -1;
+ outcol->retlen = -1;
+ dynamic = OCI_DYNAMIC_FETCH;
+ break;
+
+ case SQLT_RDD: /* ROWID */
+ case SQLT_BLOB: /* binary LOB */
+ case SQLT_CLOB: /* character LOB */
+ case SQLT_BFILE: /* binary file LOB */
+ outcol->statement = statement; /* parent handle */
+
+ define_type = outcol->data_type;
+ outcol->is_descr = 1;
+ outcol->statement->has_descr = 1;
+ outcol->storage_size4 = -1;
+ dynamic = OCI_DYNAMIC_FETCH;
+ break;
+
+ case SQLT_LNG:
+ case SQLT_LBI:
+ if (outcol->data_type == SQLT_LBI) {
+ define_type = SQLT_BIN;
+ } else {
+ define_type = SQLT_CHR;
+ }
+ outcol->storage_size4 = PHP_OCI_MAX_DATA_SIZE;
+ outcol->piecewise = 1;
+ dynamic = OCI_DYNAMIC_FETCH;
+ break;
+
+ case SQLT_BIN:
+ default:
+ define_type = SQLT_CHR;
+ if (outcol->data_type == SQLT_BIN) {
+ define_type = SQLT_BIN;
+ }
+ if ((outcol->data_type == SQLT_DAT) || (outcol->data_type == SQLT_NUM)
+#ifdef SQLT_TIMESTAMP
+ || (outcol->data_type == SQLT_TIMESTAMP)
+#endif
+#ifdef SQLT_TIMESTAMP_TZ
+ || (outcol->data_type == SQLT_TIMESTAMP_TZ)
+#endif
+#ifdef SQLT_TIMESTAMP_LTZ
+ || (outcol->data_type == SQLT_TIMESTAMP_LTZ)
+#endif
+#ifdef SQLT_INTERVAL_YM
+ || (outcol->data_type == SQLT_INTERVAL_YM)
+#endif
+#ifdef SQLT_INTERVAL_DS
+ || (outcol->data_type == SQLT_INTERVAL_DS)
+#endif
+ ) {
+ outcol->storage_size4 = 512; /* XXX this should fit "most" NLS date-formats and Numbers */
+#if defined(SQLT_IBFLOAT) && defined(SQLT_IBDOUBLE)
+ } else if (outcol->data_type == SQLT_IBFLOAT || outcol->data_type == SQLT_IBDOUBLE) {
+ outcol->storage_size4 = 1024;
+#endif
+ } else {
+ outcol->storage_size4++; /* add one for string terminator */
+ }
+
+ outcol->storage_size4 *= 3;
+
+ dynamic = OCI_DEFAULT;
+ buf = outcol->data = (text *) safe_emalloc(1, outcol->storage_size4, 0);
+ memset(buf, 0, outcol->storage_size4);
+ break;
+ }
+
+ if (dynamic == OCI_DYNAMIC_FETCH) {
+ PHP_OCI_CALL_RETURN(statement->errcode,
+ OCIDefineByPos,
+ (
+ statement->stmt, /* IN/OUT handle to the requested SQL query */
+ (OCIDefine **)&outcol->oci_define, /* IN/OUT pointer to a pointer to a define handle */
+ statement->err, /* IN/OUT An error handle */
+ counter, /* IN position in the select list */
+ (dvoid *)NULL, /* IN/OUT pointer to a buffer */
+ outcol->storage_size4, /* IN The size of each valuep buffer in bytes */
+ define_type, /* IN The data type */
+ (dvoid *)&outcol->indicator, /* IN pointer to an indicator variable or arr */
+ (ub2 *)NULL, /* IN/OUT Pointer to array of length of data fetched */
+ (ub2 *)NULL, /* OUT Pointer to array of column-level return codes */
+ OCI_DYNAMIC_FETCH /* IN mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
+ )
+ );
+
+ } else {
+ PHP_OCI_CALL_RETURN(statement->errcode,
+ OCIDefineByPos,
+ (
+ statement->stmt, /* IN/OUT handle to the requested SQL query */
+ (OCIDefine **)&outcol->oci_define, /* IN/OUT pointer to a pointer to a define handle */
+ statement->err, /* IN/OUT An error handle */
+ counter, /* IN position in the select list */
+ (dvoid *)buf, /* IN/OUT pointer to a buffer */
+ outcol->storage_size4, /* IN The size of each valuep buffer in bytes */
+ define_type, /* IN The data type */
+ (dvoid *)&outcol->indicator, /* IN pointer to an indicator variable or arr */
+ (ub2 *)&outcol->retlen, /* IN/OUT Pointer to array of length of data fetched */
+ (ub2 *)&outcol->retcode, /* OUT Pointer to array of column-level return codes */
+ OCI_DEFAULT /* IN mode (OCI_DEFAULT, OCI_DYNAMIC_FETCH) */
+ )
+ );
+
+ }
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 0;
+ }
+
+ /* additional OCIDefineDynamic() call */
+ switch (outcol->data_type) {
+ case SQLT_RSET:
+ case SQLT_RDD:
+ case SQLT_BLOB:
+ case SQLT_CLOB:
+ case SQLT_BFILE:
+ PHP_OCI_CALL_RETURN(statement->errcode,
+ OCIDefineDynamic,
+ (
+ outcol->oci_define,
+ statement->err,
+ (dvoid *)outcol,
+ php_oci_define_callback
+ )
+ );
+
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_oci_statement_cancel()
+ Cancel statement */
+int php_oci_statement_cancel(php_oci_statement *statement TSRMLS_DC)
+{
+
+ return php_oci_statement_fetch(statement, 0 TSRMLS_CC);
+
+} /* }}} */
+
+/* {{{ php_oci_statement_free()
+ Destroy statement handle and free associated resources */
+void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC)
+{
+ if (statement->stmt) {
+ if (statement->last_query_len) { /* FIXME: magical */
+ PHP_OCI_CALL(OCIStmtRelease, (statement->stmt, statement->err, NULL, 0, statement->errcode ? OCI_STRLS_CACHE_DELETE : OCI_DEFAULT));
+ } else {
+ PHP_OCI_CALL(OCIHandleFree, (statement->stmt, OCI_HTYPE_STMT));
+ }
+ statement->stmt = 0;
+ }
+
+ if (statement->err) {
+ PHP_OCI_CALL(OCIHandleFree, (statement->err, OCI_HTYPE_ERROR));
+ statement->err = 0;
+ }
+
+ if (statement->last_query) {
+ efree(statement->last_query);
+ }
+
+ if (statement->columns) {
+ zend_hash_destroy(statement->columns);
+ efree(statement->columns);
+ }
+
+ if (statement->binds) {
+ zend_hash_destroy(statement->binds);
+ efree(statement->binds);
+ }
+
+ if (statement->defines) {
+ zend_hash_destroy(statement->defines);
+ efree(statement->defines);
+ }
+
+ if (statement->parent_stmtid) {
+ zend_list_delete(statement->parent_stmtid);
+ }
+
+ zend_list_delete(statement->connection->rsrc_id);
+ efree(statement);
+
+ OCI_G(num_statements)--;
+} /* }}} */
+
+/* {{{ php_oci_bind_pre_exec()
+ Helper function */
+int php_oci_bind_pre_exec(void *data, void *result TSRMLS_DC)
+{
+ php_oci_bind *bind = (php_oci_bind *) data;
+
+ *(int *)result = 0;
+
+ if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
+ /* These checks are currently valid for oci_bind_by_name, not
+ * oci_bind_array_by_name. Also bind->type and
+ * bind->indicator are not used for oci_bind_array_by_name.
+ */
+ return 0;
+ }
+ switch (bind->type) {
+ case SQLT_NTY:
+ case SQLT_BFILEE:
+ case SQLT_CFILEE:
+ case SQLT_CLOB:
+ case SQLT_BLOB:
+ case SQLT_RDD:
+ if (Z_TYPE_P(bind->zval) != IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ *(int *)result = 1;
+ }
+ break;
+
+ case SQLT_INT:
+ case SQLT_NUM:
+ if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ *(int *)result = 1;
+ }
+ break;
+
+ case SQLT_LBI:
+ case SQLT_BIN:
+ case SQLT_LNG:
+ case SQLT_AFC:
+ case SQLT_CHR:
+ if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ *(int *)result = 1;
+ }
+ break;
+
+ case SQLT_RSET:
+ if (Z_TYPE_P(bind->zval) != IS_RESOURCE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ *(int *)result = 1;
+ }
+ break;
+ }
+
+ /* reset all bind stuff to a normal state..-. */
+ bind->indicator = 0;
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_oci_bind_post_exec()
+ Helper function */
+int php_oci_bind_post_exec(void *data TSRMLS_DC)
+{
+ php_oci_bind *bind = (php_oci_bind *) data;
+ php_oci_connection *connection = bind->parent_statement->connection;
+
+ if (bind->indicator == -1) { /* NULL */
+ zval *val = bind->zval;
+ if (Z_TYPE_P(val) == IS_STRING) {
+ *Z_STRVAL_P(val) = '\0'; /* XXX avoid warning in debug mode */
+ }
+ zval_dtor(val);
+ ZVAL_NULL(val);
+ } else if (Z_TYPE_P(bind->zval) == IS_STRING
+ && Z_STRLEN_P(bind->zval) > 0
+ && Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] != '\0') {
+ /* The post- PHP 5.3 feature for "interned" strings disallows
+ * their reallocation but (i) any IN binds either interned or
+ * not should already be null terminated and (ii) for OUT
+ * binds, php_oci_bind_out_callback() should have allocated a
+ * new string that can be realloced.
+ */
+ Z_STRVAL_P(bind->zval) = erealloc(Z_STRVAL_P(bind->zval), Z_STRLEN_P(bind->zval)+1);
+ Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] = '\0';
+ } else if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
+ int i;
+ zval **entry;
+ HashTable *hash = HASH_OF(bind->zval);
+
+ zend_hash_internal_pointer_reset(hash);
+
+ switch (bind->array.type) {
+ case SQLT_NUM:
+ case SQLT_INT:
+ case SQLT_LNG:
+ for (i = 0; i < bind->array.current_length; i++) {
+ if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ zval_dtor(*entry);
+ ZVAL_LONG(*entry, ((ub4 *)(bind->array.elements))[i]);
+ zend_hash_move_forward(hash);
+ } else {
+ add_next_index_long(bind->zval, ((ub4 *)(bind->array.elements))[i]);
+ }
+ }
+ break;
+ case SQLT_FLT:
+ for (i = 0; i < bind->array.current_length; i++) {
+ if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ zval_dtor(*entry);
+ ZVAL_DOUBLE(*entry, ((double *)(bind->array.elements))[i]);
+ zend_hash_move_forward(hash);
+ } else {
+ add_next_index_double(bind->zval, ((double *)(bind->array.elements))[i]);
+ }
+ }
+ break;
+ case SQLT_ODT:
+ for (i = 0; i < bind->array.current_length; i++) {
+ oratext buff[1024];
+ ub4 buff_len = 1024;
+
+ memset((void*)buff,0,sizeof(buff));
+
+ if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
+ zval_dtor(*entry);
+
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ ZVAL_NULL(*entry);
+ } else {
+ ZVAL_STRINGL(*entry, (char *)buff, buff_len, 1);
+ }
+ zend_hash_move_forward(hash);
+ } else {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
+ if (connection->errcode != OCI_SUCCESS) {
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ add_next_index_null(bind->zval);
+ } else {
+ add_next_index_stringl(bind->zval, (char *)buff, buff_len, 1);
+ }
+ }
+ }
+ break;
+
+ case SQLT_AFC:
+ case SQLT_CHR:
+ case SQLT_VCS:
+ case SQLT_AVC:
+ case SQLT_STR:
+ case SQLT_LVC:
+ for (i = 0; i < bind->array.current_length; i++) {
+ /* int curr_element_length = strlen(((text *)bind->array.elements)+i*bind->array.max_length); */
+ int curr_element_length = bind->array.element_lengths[i];
+ if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ zval_dtor(*entry);
+ ZVAL_STRINGL(*entry, (char *)(((text *)bind->array.elements)+i*bind->array.max_length), curr_element_length, 1);
+ zend_hash_move_forward(hash);
+ } else {
+ add_next_index_stringl(bind->zval, (char *)(((text *)bind->array.elements)+i*bind->array.max_length), curr_element_length, 1);
+ }
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ php_oci_bind_by_name()
+ Bind zval to the given placeholder */
+int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long maxlength, ub2 type TSRMLS_DC)
+{
+ php_oci_collection *bind_collection = NULL;
+ php_oci_descriptor *bind_descriptor = NULL;
+ php_oci_statement *bind_statement = NULL;
+ dvoid *oci_desc = NULL;
+ /* dvoid *php_oci_collection = NULL; */
+ OCIStmt *oci_stmt = NULL;
+ dvoid *bind_data = NULL;
+ php_oci_bind bind, *old_bind, *bindp;
+ int mode = OCI_DATA_AT_EXEC;
+ sb4 value_sz = -1;
+
+ switch (type) {
+ case SQLT_NTY:
+ {
+ zval **tmp;
+
+ if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "collection", sizeof("collection"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find collection property");
+ return 1;
+ }
+
+ PHP_OCI_ZVAL_TO_COLLECTION_EX(*tmp, bind_collection);
+ value_sz = sizeof(void*);
+ mode = OCI_DEFAULT;
+
+ if (!bind_collection->collection) {
+ return 1;
+ }
+ }
+ break;
+ case SQLT_BFILEE:
+ case SQLT_CFILEE:
+ case SQLT_CLOB:
+ case SQLT_BLOB:
+ case SQLT_RDD:
+ {
+ zval **tmp;
+
+ if (Z_TYPE_P(var) != IS_OBJECT || zend_hash_find(Z_OBJPROP_P(var), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find descriptor property");
+ return 1;
+ }
+
+ PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, bind_descriptor);
+
+ value_sz = sizeof(void*);
+
+ oci_desc = bind_descriptor->descriptor;
+
+ if (!oci_desc) {
+ return 1;
+ }
+ }
+ break;
+
+ case SQLT_INT:
+ case SQLT_NUM:
+ if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ return 1;
+ }
+ convert_to_long(var);
+ bind_data = (ub4 *)&Z_LVAL_P(var);
+ value_sz = sizeof(ub4);
+ mode = OCI_DEFAULT;
+ break;
+
+ case SQLT_LBI:
+ case SQLT_BIN:
+ case SQLT_LNG:
+ case SQLT_AFC:
+ case SQLT_CHR: /* SQLT_CHR is the default value when type was not specified */
+ if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ return 1;
+ }
+ if (Z_TYPE_P(var) != IS_NULL) {
+ convert_to_string(var);
+ }
+ if (maxlength == -1) {
+ value_sz = (Z_TYPE_P(var) == IS_STRING) ? Z_STRLEN_P(var) : 0;
+ } else {
+ value_sz = maxlength;
+ }
+ break;
+
+ case SQLT_RSET:
+ if (Z_TYPE_P(var) != IS_RESOURCE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ return 1;
+ }
+ PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement);
+ value_sz = sizeof(void*);
+
+ oci_stmt = bind_statement->stmt;
+
+ if (!oci_stmt) {
+ return 1;
+ }
+ break;
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %d", (int)type);
+ return 1;
+ break;
+ }
+
+ if (value_sz == 0) {
+ value_sz = 1;
+ }
+
+ if (!statement->binds) {
+ ALLOC_HASHTABLE(statement->binds);
+ zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
+ }
+
+ memset((void*)&bind,0,sizeof(php_oci_bind));
+ if (zend_hash_find(statement->binds, name, name_len + 1, (void **)&old_bind) == SUCCESS) {
+ bindp = old_bind;
+ if (bindp->zval) {
+ zval_ptr_dtor(&bindp->zval);
+ }
+ } else {
+ zend_hash_update(statement->binds, name, name_len + 1, &bind, sizeof(php_oci_bind), (void **)&bindp);
+ }
+
+ bindp->descriptor = oci_desc;
+ bindp->statement = oci_stmt;
+ bindp->parent_statement = statement;
+ bindp->zval = var;
+ bindp->type = type;
+ zval_add_ref(&var);
+
+ PHP_OCI_CALL_RETURN(statement->errcode,
+ OCIBindByName,
+ (
+ statement->stmt, /* statement handle */
+ (OCIBind **)&bindp->bind, /* bind hdl (will alloc) */
+ statement->err, /* error handle */
+ (text*) name, /* placeholder name */
+ name_len, /* placeholder length */
+ (dvoid *)bind_data, /* in/out data */
+ value_sz, /* PHP_OCI_MAX_DATA_SIZE, */ /* max size of input/output data */
+ type, /* in/out data type */
+ (dvoid *)&bindp->indicator, /* indicator (ignored) */
+ (ub2 *)0, /* size array (ignored) */
+ (ub2 *)&bindp->retcode, /* return code (ignored) */
+ (ub4)0, /* maxarr_len (PL/SQL only?) */
+ (ub4 *)0, /* actual array size (PL/SQL only?) */
+ mode /* mode */
+ )
+ );
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ if (mode == OCI_DATA_AT_EXEC) {
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIBindDynamic,
+ (
+ bindp->bind,
+ statement->err,
+ (dvoid *)bindp,
+ php_oci_bind_in_callback,
+ (dvoid *)bindp,
+ php_oci_bind_out_callback
+ )
+ );
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+ }
+
+ if (type == SQLT_NTY) {
+ /* Bind object */
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIBindObject,
+ (
+ bindp->bind,
+ statement->err,
+ bind_collection->tdo,
+ (dvoid **) &(bind_collection->collection),
+ (ub4 *) 0,
+ (dvoid **) 0,
+ (ub4 *) 0
+ )
+ );
+
+ if (statement->errcode) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+ }
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_bind_in_callback()
+ Callback used when binding LOBs and VARCHARs */
+sb4 php_oci_bind_in_callback(
+ dvoid *ictxp, /* context pointer */
+ OCIBind *bindp, /* bind handle */
+ ub4 iter, /* 0-based execute iteration value */
+ ub4 index, /* index of current array for PL/SQL or row index for SQL */
+ dvoid **bufpp, /* pointer to data */
+ ub4 *alenp, /* size after value/piece has been read */
+ ub1 *piecep, /* which piece */
+ dvoid **indpp) /* indicator value */
+{
+ php_oci_bind *phpbind;
+ zval *val;
+ TSRMLS_FETCH();
+
+ if (!(phpbind=(php_oci_bind *)ictxp) || !(val = phpbind->zval)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
+ return OCI_ERROR;
+ }
+
+ if (ZVAL_IS_NULL(val)) {
+ /* we're going to insert a NULL column */
+ phpbind->indicator = -1;
+ *bufpp = 0;
+ *alenp = -1;
+ *indpp = (dvoid *)&phpbind->indicator;
+ } else if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
+ /* "normal string bind */
+ convert_to_string(val);
+
+ *bufpp = Z_STRVAL_P(val);
+ *alenp = Z_STRLEN_P(val);
+ *indpp = (dvoid *)&phpbind->indicator;
+ } else if (phpbind->statement != 0) {
+ /* RSET */
+ *bufpp = phpbind->statement;
+ *alenp = -1; /* seems to be allright */
+ *indpp = (dvoid *)&phpbind->indicator;
+ } else {
+ /* descriptor bind */
+ *bufpp = phpbind->descriptor;
+ *alenp = -1; /* seems to be allright */
+ *indpp = (dvoid *)&phpbind->indicator;
+ }
+
+ *piecep = OCI_ONE_PIECE; /* pass all data in one go */
+
+ return OCI_CONTINUE;
+}/* }}} */
+
+/* {{{ php_oci_bind_out_callback()
+ Callback used when binding LOBs and VARCHARs */
+sb4 php_oci_bind_out_callback(
+ dvoid *octxp, /* context pointer */
+ OCIBind *bindp, /* bind handle */
+ ub4 iter, /* 0-based execute iteration value */
+ ub4 index, /* index of current array for PL/SQL or row index for SQL */
+ dvoid **bufpp, /* pointer to data */
+ ub4 **alenpp, /* size after value/piece has been read */
+ ub1 *piecep, /* which piece */
+ dvoid **indpp, /* indicator value */
+ ub2 **rcodepp) /* return code */
+{
+ php_oci_bind *phpbind;
+ zval *val;
+ sb4 retval = OCI_ERROR;
+ TSRMLS_FETCH();
+
+ if (!(phpbind=(php_oci_bind *)octxp) || !(val = phpbind->zval)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid phpbind pointer value");
+ return retval;
+ }
+
+ if (Z_TYPE_P(val) == IS_RESOURCE) {
+ /* Processing for ref-cursor out binds */
+ if (phpbind->statement != NULL) {
+ *bufpp = phpbind->statement;
+ *alenpp = &phpbind->dummy_len;
+ *piecep = OCI_ONE_PIECE;
+ *rcodepp = &phpbind->retcode;
+ *indpp = &phpbind->indicator;
+ }
+ retval = OCI_CONTINUE;
+ } else if (Z_TYPE_P(val) == IS_OBJECT) {
+ zval **tmp;
+ php_oci_descriptor *desc;
+
+ if (!phpbind->descriptor) {
+ return OCI_ERROR;
+ }
+
+ /* Do not use the cached lob size if the descriptor is an
+ * out-bind as the contents would have been changed for in/out
+ * binds (Bug #46994).
+ */
+ if (zend_hash_find(Z_OBJPROP_P(val), "descriptor", sizeof("descriptor"), (void **)&tmp) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find object outbind descriptor property");
+ return OCI_ERROR;
+ }
+ PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(*tmp, desc);
+ desc->lob_size = -1; /* force OCI8 to update cached size */
+
+ *alenpp = &phpbind->dummy_len;
+ *bufpp = phpbind->descriptor;
+ *piecep = OCI_ONE_PIECE;
+ *rcodepp = &phpbind->retcode;
+ *indpp = &phpbind->indicator;
+ retval = OCI_CONTINUE;
+ } else {
+ convert_to_string(val);
+ zval_dtor(val);
+
+ Z_STRLEN_P(val) = PHP_OCI_PIECE_SIZE; /* 64K-1 is max XXX */
+ Z_STRVAL_P(val) = ecalloc(1, Z_STRLEN_P(phpbind->zval) + 1);
+
+ /* XXX we assume that zend-zval len has 4 bytes */
+ *alenpp = (ub4*) &Z_STRLEN_P(phpbind->zval);
+ *bufpp = Z_STRVAL_P(phpbind->zval);
+ *piecep = OCI_ONE_PIECE;
+ *rcodepp = &phpbind->retcode;
+ *indpp = &phpbind->indicator;
+ retval = OCI_CONTINUE;
+ }
+
+ return retval;
+}
+/* }}} */
+
+/* {{{ php_oci_statement_get_column_helper()
+ Helper function to get column by name and index */
+php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS, int need_data)
+{
+ zval *z_statement, *column_index;
+ php_oci_statement *statement;
+ php_oci_out_column *column;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_statement, &column_index) == FAILURE) {
+ return NULL;
+ }
+
+ statement = (php_oci_statement *) zend_fetch_resource(&z_statement TSRMLS_CC, -1, "oci8 statement", NULL, 1, le_statement);
+
+ if (!statement) {
+ return NULL;
+ }
+
+ if (need_data && !statement->has_data) {
+ return NULL;
+ }
+
+ if (Z_TYPE_P(column_index) == IS_STRING) {
+ column = php_oci_statement_get_column(statement, -1, Z_STRVAL_P(column_index), Z_STRLEN_P(column_index) TSRMLS_CC);
+ if (!column) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column name \"%s\"", Z_STRVAL_P(column_index));
+ return NULL;
+ }
+ } else {
+ zval tmp;
+ /* NB: for PHP4 compat only, it should be using 'Z' instead */
+ tmp = *column_index;
+ zval_copy_ctor(&tmp);
+ convert_to_long(&tmp);
+ column = php_oci_statement_get_column(statement, Z_LVAL(tmp), NULL, 0 TSRMLS_CC);
+ if (!column) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column index \"%ld\"", Z_LVAL(tmp));
+ zval_dtor(&tmp);
+ return NULL;
+ }
+ zval_dtor(&tmp);
+ }
+ return column;
+} /* }}} */
+
+/* {{{ php_oci_statement_get_type()
+ Return type of the statement */
+int php_oci_statement_get_type(php_oci_statement *statement, ub2 *type TSRMLS_DC)
+{
+ ub2 statement_type;
+
+ *type = 0;
+
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub2 *)&statement_type, (ub4 *)0, OCI_ATTR_STMT_TYPE, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ *type = statement_type;
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_statement_get_numrows()
+ Get the number of rows fetched to the clientside (NOT the number of rows in the result set) */
+int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSRMLS_DC)
+{
+ ub4 statement_numrows;
+
+ *numrows = 0;
+
+ PHP_OCI_CALL_RETURN(statement->errcode, OCIAttrGet, ((dvoid *)statement->stmt, OCI_HTYPE_STMT, (ub4 *)&statement_numrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, statement->err));
+
+ if (statement->errcode != OCI_SUCCESS) {
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+
+ *numrows = statement_numrows;
+
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_by_name()
+ Bind arrays to PL/SQL types */
+int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long max_table_length, long maxlength, long type TSRMLS_DC)
+{
+ php_oci_bind *bind, *bindp;
+
+ convert_to_array(var);
+
+ if (maxlength < -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid max length value (%ld)", maxlength);
+ return 1;
+ }
+
+ switch(type) {
+ case SQLT_NUM:
+ case SQLT_INT:
+ case SQLT_LNG:
+ bind = php_oci_bind_array_helper_number(var, max_table_length TSRMLS_CC);
+ break;
+
+ case SQLT_FLT:
+ bind = php_oci_bind_array_helper_double(var, max_table_length TSRMLS_CC);
+ break;
+
+ case SQLT_AFC:
+ case SQLT_CHR:
+ case SQLT_VCS:
+ case SQLT_AVC:
+ case SQLT_STR:
+ case SQLT_LVC:
+ if (maxlength == -1 && zend_hash_num_elements(Z_ARRVAL_P(var)) == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must provide max length value for empty arrays");
+ return 1;
+ }
+ bind = php_oci_bind_array_helper_string(var, max_table_length, maxlength TSRMLS_CC);
+ break;
+ case SQLT_ODT:
+ bind = php_oci_bind_array_helper_date(var, max_table_length, statement->connection TSRMLS_CC);
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or unsupported datatype given: %ld", type);
+ return 1;
+ break;
+ }
+
+ if (bind == NULL) {
+ /* failed to generate bind struct */
+ return 1;
+ }
+
+ if (!statement->binds) {
+ ALLOC_HASHTABLE(statement->binds);
+ zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
+ }
+
+ zend_hash_update(statement->binds, name, name_len + 1, bind, sizeof(php_oci_bind), (void **)&bindp);
+
+ bindp->descriptor = NULL;
+ bindp->statement = NULL;
+ bindp->parent_statement = statement;
+ bindp->bind = NULL;
+ bindp->zval = var;
+ bindp->array.type = type;
+ bindp->indicator = 0; /* not used for array binds */
+ bindp->type = 0; /* not used for array binds */
+
+ zval_add_ref(&var);
+
+ PHP_OCI_CALL_RETURN(statement->errcode,
+ OCIBindByName,
+ (
+ statement->stmt,
+ (OCIBind **)&bindp->bind,
+ statement->err,
+ (text *)name,
+ name_len,
+ (dvoid *) bindp->array.elements,
+ (sb4) bind->array.max_length,
+ type,
+ (dvoid *)bindp->array.indicators,
+ (ub2 *)bind->array.element_lengths,
+ (ub2 *)0, /* bindp->array.retcodes, */
+ (ub4) max_table_length,
+ (ub4 *) &(bindp->array.current_length),
+ (ub4) OCI_DEFAULT
+ )
+ );
+
+
+ if (statement->errcode != OCI_SUCCESS) {
+ efree(bind);
+ statement->errcode = php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+ efree(bind);
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_helper_string()
+ Bind arrays to PL/SQL types */
+php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, long maxlength TSRMLS_DC)
+{
+ php_oci_bind *bind;
+ ub4 i;
+ HashTable *hash;
+ zval **entry;
+
+ hash = HASH_OF(var);
+
+ if (maxlength == -1) {
+ zend_hash_internal_pointer_reset(hash);
+ while (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
+ convert_to_string_ex(entry);
+ if (Z_STRLEN_PP(entry) > maxlength) {
+ maxlength = Z_STRLEN_PP(entry) + 1;
+ }
+ zend_hash_move_forward(hash);
+ }
+ }
+
+ bind = emalloc(sizeof(php_oci_bind));
+ bind->array.elements = (text *)safe_emalloc(max_table_length * (maxlength + 1), sizeof(text), 0);
+ memset(bind->array.elements, 0, max_table_length * (maxlength + 1) * sizeof(text));
+ bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
+ bind->array.old_length = bind->array.current_length;
+ bind->array.max_length = maxlength;
+ bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
+ memset(bind->array.element_lengths, 0, max_table_length*sizeof(ub2));
+ bind->array.indicators = safe_emalloc(max_table_length, sizeof(sb2), 0);
+ memset(bind->array.indicators, 0, max_table_length*sizeof(sb2));
+
+ zend_hash_internal_pointer_reset(hash);
+
+ for (i = 0; i < bind->array.current_length; i++) {
+ if (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
+ convert_to_string_ex(entry);
+ bind->array.element_lengths[i] = Z_STRLEN_PP(entry);
+ if (Z_STRLEN_PP(entry) == 0) {
+ bind->array.indicators[i] = -1;
+ }
+ zend_hash_move_forward(hash);
+ } else {
+ break;
+ }
+ }
+
+ zend_hash_internal_pointer_reset(hash);
+ for (i = 0; i < max_table_length; i++) {
+ if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ int element_length;
+
+ convert_to_string_ex(entry);
+ element_length = (maxlength > Z_STRLEN_PP(entry)) ? Z_STRLEN_PP(entry) : maxlength;
+
+ memcpy((text *)bind->array.elements + i*maxlength, Z_STRVAL_PP(entry), element_length);
+ ((text *)bind->array.elements)[i*maxlength + element_length] = '\0';
+
+ zend_hash_move_forward(hash);
+ } else {
+ ((text *)bind->array.elements)[i*maxlength] = '\0';
+ }
+ }
+ zend_hash_internal_pointer_reset(hash);
+
+ return bind;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_helper_number()
+ Bind arrays to PL/SQL types */
+php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length TSRMLS_DC)
+{
+ php_oci_bind *bind;
+ ub4 i;
+ HashTable *hash;
+ zval **entry;
+
+ hash = HASH_OF(var);
+
+ bind = emalloc(sizeof(php_oci_bind));
+ bind->array.elements = (ub4 *)safe_emalloc(max_table_length, sizeof(ub4), 0);
+ bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
+ bind->array.old_length = bind->array.current_length;
+ bind->array.max_length = sizeof(ub4);
+ bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
+ memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
+ bind->array.indicators = NULL;
+
+ zend_hash_internal_pointer_reset(hash);
+ for (i = 0; i < max_table_length; i++) {
+ if (i < bind->array.current_length) {
+ bind->array.element_lengths[i] = sizeof(ub4);
+ }
+ if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ convert_to_long_ex(entry);
+ ((ub4 *)bind->array.elements)[i] = (ub4) Z_LVAL_PP(entry);
+ zend_hash_move_forward(hash);
+ } else {
+ ((ub4 *)bind->array.elements)[i] = 0;
+ }
+ }
+ zend_hash_internal_pointer_reset(hash);
+
+ return bind;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_helper_double()
+ Bind arrays to PL/SQL types */
+php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length TSRMLS_DC)
+{
+ php_oci_bind *bind;
+ ub4 i;
+ HashTable *hash;
+ zval **entry;
+
+ hash = HASH_OF(var);
+
+ bind = emalloc(sizeof(php_oci_bind));
+ bind->array.elements = (double *)safe_emalloc(max_table_length, sizeof(double), 0);
+ bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
+ bind->array.old_length = bind->array.current_length;
+ bind->array.max_length = sizeof(double);
+ bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
+ memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
+ bind->array.indicators = NULL;
+
+ zend_hash_internal_pointer_reset(hash);
+ for (i = 0; i < max_table_length; i++) {
+ if (i < bind->array.current_length) {
+ bind->array.element_lengths[i] = sizeof(double);
+ }
+ if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ convert_to_double_ex(entry);
+ ((double *)bind->array.elements)[i] = (double) Z_DVAL_PP(entry);
+ zend_hash_move_forward(hash);
+ } else {
+ ((double *)bind->array.elements)[i] = 0;
+ }
+ }
+ zend_hash_internal_pointer_reset(hash);
+
+ return bind;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_helper_date()
+ Bind arrays to PL/SQL types */
+php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, php_oci_connection *connection TSRMLS_DC)
+{
+ php_oci_bind *bind;
+ ub4 i;
+ HashTable *hash;
+ zval **entry;
+
+ hash = HASH_OF(var);
+
+ bind = emalloc(sizeof(php_oci_bind));
+ bind->array.elements = (OCIDate *)safe_emalloc(max_table_length, sizeof(OCIDate), 0);
+ bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
+ bind->array.old_length = bind->array.current_length;
+ bind->array.max_length = sizeof(OCIDate);
+ bind->array.element_lengths = safe_emalloc(max_table_length, sizeof(ub2), 0);
+ memset(bind->array.element_lengths, 0, max_table_length * sizeof(ub2));
+ bind->array.indicators = NULL;
+
+ zend_hash_internal_pointer_reset(hash);
+ for (i = 0; i < max_table_length; i++) {
+ OCIDate oci_date;
+ if (i < bind->array.current_length) {
+ bind->array.element_lengths[i] = sizeof(OCIDate);
+ }
+ if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+
+ convert_to_string_ex(entry);
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), NULL, 0, NULL, 0, &oci_date));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ /* failed to convert string to date */
+ efree(bind->array.element_lengths);
+ efree(bind->array.elements);
+ efree(bind);
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return NULL;
+ }
+
+ ((OCIDate *)bind->array.elements)[i] = oci_date;
+ zend_hash_move_forward(hash);
+ } else {
+ PHP_OCI_CALL_RETURN(connection->errcode, OCIDateFromText, (connection->err, (CONST text *)"01-JAN-00", sizeof("01-JAN-00")-1, NULL, 0, NULL, 0, &oci_date));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ /* failed to convert string to date */
+ efree(bind->array.element_lengths);
+ efree(bind->array.elements);
+ efree(bind);
+ connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
+ return NULL;
+ }
+
+ ((OCIDate *)bind->array.elements)[i] = oci_date;
+ }
+ }
+ zend_hash_internal_pointer_reset(hash);
+
+ return bind;
+} /* }}} */
+
+#endif /* HAVE_OCI8 */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/php_oci8.h b/php_oci8.h
new file mode 100644
index 0000000000..9bf589d660
--- /dev/null
+++ b/php_oci8.h
@@ -0,0 +1,74 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@php.net> |
+ | Thies C. Arntzen <thies@thieso.net> |
+ | |
+ | Collection support by Andy Sautins <asautins@veripost.net> |
+ | Temporary LOB support by David Benson <dbenson@mancala.com> |
+ | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
+ | |
+ | Redesigned by: Antony Dovgal <antony@zend.com> |
+ | Andi Gutmans <andi@zend.com> |
+ | Wez Furlong <wez@omniti.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#if HAVE_OCI8
+# ifndef PHP_OCI8_H
+# define PHP_OCI8_H
+
+#ifdef ZTS
+# include "TSRM.h"
+#endif
+
+
+/*
+ * The version of the OCI8 extension.
+ */
+#ifdef PHP_OCI8_VERSION
+/* The definition of PHP_OCI8_VERSION changed in PHP 5.3 and building
+ * this code with PHP 5.2 and earlier (e.g. when using OCI8 from PECL)
+ * will conflict.
+ */
+#undef PHP_OCI8_VERSION
+#endif
+#define PHP_OCI8_VERSION "1.4.3"
+
+extern zend_module_entry oci8_module_entry;
+#define phpext_oci8_ptr &oci8_module_entry
+#define phpext_oci8_11g_ptr &oci8_module_entry
+
+
+PHP_MINIT_FUNCTION(oci);
+PHP_RINIT_FUNCTION(oci);
+PHP_MSHUTDOWN_FUNCTION(oci);
+PHP_RSHUTDOWN_FUNCTION(oci);
+PHP_MINFO_FUNCTION(oci);
+
+# endif /* !PHP_OCI8_H */
+#else /* !HAVE_OCI8 */
+
+# define oci8_module_ptr NULL
+
+#endif /* HAVE_OCI8 */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/php_oci8_int.h b/php_oci8_int.h
new file mode 100644
index 0000000000..c1f8cb8b03
--- /dev/null
+++ b/php_oci8_int.h
@@ -0,0 +1,518 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2010 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@php.net> |
+ | Thies C. Arntzen <thies@thieso.net> |
+ | |
+ | Collection support by Andy Sautins <asautins@veripost.net> |
+ | Temporary LOB support by David Benson <dbenson@mancala.com> |
+ | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
+ | |
+ | Redesigned by: Antony Dovgal <antony@zend.com> |
+ | Andi Gutmans <andi@zend.com> |
+ | Wez Furlong <wez@omniti.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#if HAVE_OCI8
+# ifndef PHP_OCI8_INT_H
+# define PHP_OCI8_INT_H
+
+/* misc defines {{{ */
+# if (defined(__osf__) && defined(__alpha))
+# ifndef A_OSF
+# define A_OSF
+# endif
+# ifndef OSF1
+# define OSF1
+# endif
+# ifndef _INTRINSICS
+# define _INTRINSICS
+# endif
+# endif /* osf alpha */
+
+#if defined(min)
+#undef min
+#endif
+#if defined(max)
+#undef max
+#endif
+/* }}} */
+
+#include "ext/standard/php_string.h"
+#include <oci.h>
+
+extern int le_connection;
+extern int le_pconnection;
+extern int le_statement;
+extern int le_descriptor;
+extern int le_collection;
+extern int le_server;
+extern int le_session;
+
+extern zend_class_entry *oci_lob_class_entry_ptr;
+extern zend_class_entry *oci_coll_class_entry_ptr;
+
+/* constants {{{ */
+#define PHP_OCI_SEEK_SET 0
+#define PHP_OCI_SEEK_CUR 1
+#define PHP_OCI_SEEK_END 2
+
+#define PHP_OCI_MAX_NAME_LEN 64
+#define PHP_OCI_MAX_DATA_SIZE INT_MAX
+#define PHP_OCI_PIECE_SIZE ((64*1024)-1)
+#define PHP_OCI_LOB_BUFFER_SIZE 1048576l /* 1Mb seems to be the most reasonable buffer size for LOB reading */
+
+#define PHP_OCI_ASSOC (1<<0)
+#define PHP_OCI_NUM (1<<1)
+#define PHP_OCI_BOTH (PHP_OCI_ASSOC|PHP_OCI_NUM)
+
+#define PHP_OCI_RETURN_NULLS (1<<2)
+#define PHP_OCI_RETURN_LOBS (1<<3)
+
+#define PHP_OCI_FETCHSTATEMENT_BY_COLUMN (1<<4)
+#define PHP_OCI_FETCHSTATEMENT_BY_ROW (1<<5)
+#define PHP_OCI_FETCHSTATEMENT_BY (PHP_OCI_FETCHSTATEMENT_BY_COLUMN | PHP_OCI_FETCHSTATEMENT_BY_ROW)
+
+#define PHP_OCI_LOB_BUFFER_DISABLED 0
+#define PHP_OCI_LOB_BUFFER_ENABLED 1
+#define PHP_OCI_LOB_BUFFER_USED 2
+
+/* The mode parameter for oci_connect() is overloaded and accepts both
+ * privilege and external authentication flags OR'd together.
+ * PHP_OCI_CRED_EXT must be distinct from the OCI_xxx privilege
+ * values.
+ */
+#define PHP_OCI_CRED_EXT (1<<31)
+#if ((PHP_OCI_CRED_EXT == OCI_DEFAULT) || (PHP_OCI_CRED_EXT & (OCI_SYSOPER | OCI_SYSDBA)))
+#error Invalid value for PHP_OCI_CRED_EXT
+#endif
+
+/*
+ * Name passed to Oracle for tracing. Note some DB views only show
+ * the first nine characters of the driver name.
+ */
+#define PHP_OCI8_DRIVER_NAME "PHP OCI8 " PHP_OCI8_VERSION
+
+/* }}} */
+
+typedef struct { /* php_oci_spool {{{ */
+ OCIEnv *env; /*env of this session pool */
+ OCIError *err; /* pool's error handle */
+ OCISPool *poolh; /* pool handle */
+ void *poolname; /* session pool name */
+ unsigned int poolname_len; /* length of session pool name */
+ char *spool_hash_key; /* Hash key for session pool in plist */
+} php_oci_spool; /* }}} */
+
+typedef struct { /* php_oci_connection {{{ */
+ OCIEnv *env; /* private env handle */
+ ub2 charset; /* charset ID */
+ OCIServer *server; /* private server handle */
+ OCISvcCtx *svc; /* private service context handle */
+ OCISession *session; /* private session handle */
+ OCIAuthInfo *authinfo; /* Cached authinfo handle for OCISessionGet */
+ OCIError *err; /* private error handle */
+ php_oci_spool *private_spool; /* private session pool (for persistent) */
+ sword errcode; /* last errcode */
+
+ HashTable *descriptors; /* descriptors hash, used to flush all the LOBs using this connection on commit */
+ ulong descriptor_count; /* used to index the descriptors hash table. Not an accurate count */
+ unsigned is_open:1; /* hels to determine if the connection is dead or not */
+ unsigned is_attached:1; /* hels to determine if we should detach from the server when closing/freeing the connection */
+ unsigned is_persistent:1; /* self-descriptive */
+ unsigned used_this_request:1; /* helps to determine if we should reset connection's next ping time and check its timeout */
+ unsigned needs_commit:1; /* helps to determine if we should rollback this connection on close/shutdown */
+ unsigned passwd_changed:1; /* helps determine if a persistent connection hash should be invalidated after a password change */
+ unsigned is_stub:1; /* flag to keep track whether the connection structure has a real OCI connection associated */
+ unsigned using_spool:1; /* Is this connection from session pool? */
+ int rsrc_id; /* resource ID */
+ time_t idle_expiry; /* time when the connection will be considered as expired */
+ time_t *next_pingp; /* (pointer to) time of the next ping */
+ char *hash_key; /* hashed details of the connection */
+} php_oci_connection; /* }}} */
+
+typedef struct { /* php_oci_descriptor {{{ */
+ int id;
+ ulong index; /* descriptors hash table index */
+ php_oci_connection *connection; /* parent connection handle */
+ dvoid *descriptor; /* OCI descriptor handle */
+ ub4 type; /* descriptor type (FILE/LOB) */
+ int lob_current_position; /* LOB internal pointer */
+ int lob_size; /* cached LOB size. -1 = Lob wasn't initialized yet */
+ int buffering; /* cached buffering flag. 0 - off, 1 - on, 2 - on and buffer was used */
+ ub4 chunk_size; /* chunk size of the LOB. 0 - unknown */
+ ub1 charset_form; /* charset form, required for NCLOBs */
+ ub2 charset_id; /* charset ID */
+ unsigned is_open:1; /* helps to determine if lob is open or not */
+} php_oci_descriptor; /* }}} */
+
+typedef struct { /* php_oci_lob_ctx {{{ */
+ char **lob_data; /* address of pointer to LOB data */
+ ub4 *lob_len; /* address of LOB length variable (bytes) */
+ ub4 alloc_len;
+} php_oci_lob_ctx; /* }}} */
+
+typedef struct { /* php_oci_collection {{{ */
+ int id;
+ php_oci_connection *connection; /* parent connection handle */
+ OCIType *tdo; /* collection's type handle */
+ OCITypeCode coll_typecode; /* collection's typecode handle */
+ OCIRef *elem_ref; /* element's reference handle */
+ OCIType *element_type; /* element's type handle */
+ OCITypeCode element_typecode; /* element's typecode handle */
+ OCIColl *collection; /* collection handle */
+} php_oci_collection; /* }}} */
+
+typedef struct { /* php_oci_define {{{ */
+ zval *zval; /* zval used in define */
+ text *name; /* placeholder's name */
+ ub4 name_len; /* placeholder's name length */
+ ub4 type; /* define type */
+} php_oci_define; /* }}} */
+
+typedef struct { /* php_oci_statement {{{ */
+ int id;
+ int parent_stmtid; /* parent statement id */
+ php_oci_connection *connection; /* parent connection handle */
+ sword errcode; /* last errcode*/
+ OCIError *err; /* private error handle */
+ OCIStmt *stmt; /* statement handle */
+ char *last_query; /* last query issued. also used to determine if this is a statement or a refcursor recieved from Oracle */
+ long last_query_len; /* last query length */
+ HashTable *columns; /* hash containing all the result columns */
+ HashTable *binds; /* binds hash */
+ HashTable *defines; /* defines hash */
+ int ncolumns; /* number of columns in the result */
+ unsigned executed:1; /* statement executed flag */
+ unsigned has_data:1; /* statement has more data flag */
+ unsigned has_descr:1; /* statement has at least one descriptor or cursor column */
+ ub2 stmttype; /* statement type */
+} php_oci_statement; /* }}} */
+
+typedef struct { /* php_oci_bind {{{ */
+ OCIBind *bind; /* bind handle */
+ zval *zval; /* value */
+ dvoid *descriptor; /* used for binding of LOBS etc */
+ OCIStmt *statement; /* used for binding REFCURSORs */
+ php_oci_statement *parent_statement; /* pointer to the parent statement */
+ ub2 type; /* bind type */
+ struct {
+ void *elements;
+ sb2 *indicators;
+ ub2 *element_lengths;
+ ub4 current_length;
+ ub4 old_length;
+ ub4 max_length;
+ long type;
+ } array;
+ sb2 indicator; /* -1 means NULL */
+ ub2 retcode;
+ ub4 dummy_len; /* a dummy var to store alenpp value in bind OUT callback */
+} php_oci_bind; /* }}} */
+
+typedef struct { /* php_oci_out_column {{{ */
+ php_oci_statement *statement; /* statement handle. used when fetching REFCURSORS */
+ php_oci_statement *nested_statement; /* statement handle. used when fetching REFCURSORS */
+ OCIDefine *oci_define; /* define handle */
+ char *name; /* column name */
+ ub4 name_len; /* column name length */
+ ub2 data_type; /* column data type */
+ ub2 data_size; /* data size */
+ ub4 storage_size4; /* size used when allocating buffers */
+ sb2 indicator;
+ ub2 retcode; /* code returned when fetching this particular column */
+ ub2 retlen;
+ ub4 retlen4;
+ ub2 is_descr; /* column contains a descriptor */
+ ub2 is_cursor; /* column contains a cursor */
+ int stmtid; /* statement id for cursors */
+ int descid; /* descriptor id for descriptors */
+ void *data;
+ php_oci_define *define; /* define handle */
+ int piecewise; /* column is fetched piece-by-piece */
+ ub4 cb_retlen;
+ sb1 scale; /* column scale */
+ sb2 precision; /* column precision */
+ ub1 charset_form; /* charset form, required for NCLOBs */
+ ub2 charset_id; /* charset ID */
+} php_oci_out_column; /* }}} */
+
+/* {{{ macros */
+
+#define PHP_OCI_CALL(func, params) \
+ do { \
+ if (OCI_G(debug_mode)) { \
+ php_printf ("OCI8 DEBUG: " #func " at (%s:%d) \n", __FILE__, __LINE__); \
+ } \
+ OCI_G(in_call) = 1; \
+ func params; \
+ OCI_G(in_call) = 0; \
+ } while (0)
+
+#define PHP_OCI_CALL_RETURN(__retval, func, params) \
+ do { \
+ if (OCI_G(debug_mode)) { \
+ php_printf ("OCI8 DEBUG: " #func " at (%s:%d) \n", __FILE__, __LINE__); \
+ } \
+ OCI_G(in_call) = 1; \
+ __retval = func params; \
+ OCI_G(in_call) = 0; \
+ } while (0)
+
+/* Check for errors that indicate the connection to the DB is no
+ * longer valid. If it isn't, then the PHP connection is marked to be
+ * reopened by the next PHP OCI8 connect command. This is most useful
+ * for persistent connections. The error number list is not
+ * exclusive. The error number comparisons and the
+ * OCI_ATTR_SERVER_STATUS check are done for maximum cross-version
+ * compatibility. In the far future, only the attribute check will be
+ * needed.
+ */
+#define PHP_OCI_HANDLE_ERROR(connection, errcode) \
+ do { \
+ switch (errcode) { \
+ case 1013: \
+ zend_bailout(); \
+ break; \
+ case 22: \
+ case 378: \
+ case 602: \
+ case 603: \
+ case 604: \
+ case 609: \
+ case 1012: \
+ case 1033: \
+ case 1041: \
+ case 1043: \
+ case 1089: \
+ case 1090: \
+ case 1092: \
+ case 3113: \
+ case 3114: \
+ case 3122: \
+ case 3135: \
+ case 12153: \
+ case 27146: \
+ case 28511: \
+ (connection)->is_open = 0; \
+ break; \
+ default: \
+ { \
+ ub4 serverStatus = OCI_SERVER_NORMAL; \
+ PHP_OCI_CALL(OCIAttrGet, ((dvoid *)(connection)->server, OCI_HTYPE_SERVER, (dvoid *)&serverStatus, \
+ (ub4 *)0, OCI_ATTR_SERVER_STATUS, (connection)->err)); \
+ if (serverStatus != OCI_SERVER_NORMAL) { \
+ (connection)->is_open = 0; \
+ } \
+ } \
+ break; \
+ } \
+ } while (0)
+
+#define PHP_OCI_REGISTER_RESOURCE(resource, le_resource) \
+ do { \
+ resource->id = ZEND_REGISTER_RESOURCE(NULL, resource, le_resource); \
+ } while (0)
+
+#define PHP_OCI_ZVAL_TO_CONNECTION(zval, connection) \
+ ZEND_FETCH_RESOURCE2(connection, php_oci_connection *, &zval, -1, "oci8 connection", le_connection, le_pconnection)
+
+#define PHP_OCI_ZVAL_TO_STATEMENT(zval, statement) \
+ ZEND_FETCH_RESOURCE(statement, php_oci_statement *, &zval, -1, "oci8 statement", le_statement)
+
+#define PHP_OCI_ZVAL_TO_DESCRIPTOR(zval, descriptor) \
+ ZEND_FETCH_RESOURCE(descriptor, php_oci_descriptor *, &zval, -1, "oci8 descriptor", le_descriptor)
+
+#define PHP_OCI_ZVAL_TO_COLLECTION(zval, collection) \
+ ZEND_FETCH_RESOURCE(collection, php_oci_collection *, &zval, -1, "oci8 collection", le_collection)
+
+#define PHP_OCI_FETCH_RESOURCE_EX(zval, var, type, name, resource_type) \
+ do { \
+ var = (type) zend_fetch_resource(&zval TSRMLS_CC, -1, name, NULL, 1, resource_type); \
+ if (!var) { \
+ return 1; \
+ } \
+ } while (0)
+
+#define PHP_OCI_ZVAL_TO_CONNECTION_EX(zval, connection) \
+ PHP_OCI_FETCH_RESOURCE_EX(zval, connection, php_oci_connection *, "oci8 connection", le_connection)
+
+#define PHP_OCI_ZVAL_TO_STATEMENT_EX(zval, statement) \
+ PHP_OCI_FETCH_RESOURCE_EX(zval, statement, php_oci_statement *, "oci8 statement", le_statement)
+
+#define PHP_OCI_ZVAL_TO_DESCRIPTOR_EX(zval, descriptor) \
+ PHP_OCI_FETCH_RESOURCE_EX(zval, descriptor, php_oci_descriptor *, "oci8 descriptor", le_descriptor)
+
+#define PHP_OCI_ZVAL_TO_COLLECTION_EX(zval, collection) \
+ PHP_OCI_FETCH_RESOURCE_EX(zval, collection, php_oci_collection *, "oci8 collection", le_collection)
+
+/* }}} */
+
+/* PROTOS */
+
+/* main prototypes {{{ */
+
+void php_oci_column_hash_dtor (void *data);
+void php_oci_define_hash_dtor (void *data);
+void php_oci_bind_hash_dtor (void *data);
+void php_oci_descriptor_flush_hash_dtor (void *data);
+
+void php_oci_connection_descriptors_free(php_oci_connection *connection TSRMLS_DC);
+
+sb4 php_oci_error (OCIError *, sword TSRMLS_DC);
+sb4 php_oci_fetch_errmsg(OCIError *, text ** TSRMLS_DC);
+int php_oci_fetch_sqltext_offset(php_oci_statement *, text **, ub2 * TSRMLS_DC);
+
+void php_oci_do_connect (INTERNAL_FUNCTION_PARAMETERS, int , int);
+php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char *password, int password_len, char *new_password, int new_password_len, char *dbname, int dbname_len, char *charset, long session_mode, int persistent, int exclusive TSRMLS_DC);
+
+int php_oci_connection_rollback(php_oci_connection * TSRMLS_DC);
+int php_oci_connection_commit(php_oci_connection * TSRMLS_DC);
+int php_oci_connection_release(php_oci_connection *connection TSRMLS_DC);
+
+int php_oci_password_change(php_oci_connection *, char *, int, char *, int, char *, int TSRMLS_DC);
+int php_oci_server_get_version(php_oci_connection *, char ** TSRMLS_DC);
+
+void php_oci_fetch_row(INTERNAL_FUNCTION_PARAMETERS, int, int);
+int php_oci_column_to_zval(php_oci_out_column *, zval *, int TSRMLS_DC);
+
+/* }}} */
+
+/* lob related prototypes {{{ */
+
+php_oci_descriptor * php_oci_lob_create (php_oci_connection *, long TSRMLS_DC);
+int php_oci_lob_get_length (php_oci_descriptor *, ub4 * TSRMLS_DC);
+int php_oci_lob_read (php_oci_descriptor *, long, long, char **, ub4 * TSRMLS_DC);
+int php_oci_lob_write (php_oci_descriptor *, ub4, char *, int, ub4 * TSRMLS_DC);
+int php_oci_lob_flush (php_oci_descriptor *, long TSRMLS_DC);
+int php_oci_lob_set_buffering (php_oci_descriptor *, int TSRMLS_DC);
+int php_oci_lob_get_buffering (php_oci_descriptor *);
+int php_oci_lob_copy (php_oci_descriptor *, php_oci_descriptor *, long TSRMLS_DC);
+int php_oci_lob_close (php_oci_descriptor * TSRMLS_DC);
+int php_oci_temp_lob_close (php_oci_descriptor * TSRMLS_DC);
+int php_oci_lob_write_tmp (php_oci_descriptor *, ub1, char *, int TSRMLS_DC);
+void php_oci_lob_free(php_oci_descriptor * TSRMLS_DC);
+int php_oci_lob_import(php_oci_descriptor *descriptor, char * TSRMLS_DC);
+int php_oci_lob_append (php_oci_descriptor *, php_oci_descriptor * TSRMLS_DC);
+int php_oci_lob_truncate (php_oci_descriptor *, long TSRMLS_DC);
+int php_oci_lob_erase (php_oci_descriptor *, long, ub4, ub4 * TSRMLS_DC);
+int php_oci_lob_is_equal (php_oci_descriptor *, php_oci_descriptor *, boolean * TSRMLS_DC);
+#if defined(HAVE_OCI_LOB_READ2)
+sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, oraub8 len, ub1 piece, dvoid **changed_bufpp, oraub8 *changed_lenp);
+#else
+sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, ub4 len, ub1 piece);
+#endif
+/* }}} */
+
+/* collection related prototypes {{{ */
+
+php_oci_collection * php_oci_collection_create(php_oci_connection *, char *, int, char *, int TSRMLS_DC);
+int php_oci_collection_size(php_oci_collection *, sb4 * TSRMLS_DC);
+int php_oci_collection_max(php_oci_collection *, long * TSRMLS_DC);
+int php_oci_collection_trim(php_oci_collection *, long TSRMLS_DC);
+int php_oci_collection_append(php_oci_collection *, char *, int TSRMLS_DC);
+int php_oci_collection_element_get(php_oci_collection *, long, zval** TSRMLS_DC);
+int php_oci_collection_element_set(php_oci_collection *, long, char *, int TSRMLS_DC);
+int php_oci_collection_element_set_null(php_oci_collection *, long TSRMLS_DC);
+int php_oci_collection_element_set_date(php_oci_collection *, long, char *, int TSRMLS_DC);
+int php_oci_collection_element_set_number(php_oci_collection *, long, char *, int TSRMLS_DC);
+int php_oci_collection_element_set_string(php_oci_collection *, long, char *, int TSRMLS_DC);
+int php_oci_collection_assign(php_oci_collection *, php_oci_collection * TSRMLS_DC);
+void php_oci_collection_close(php_oci_collection * TSRMLS_DC);
+int php_oci_collection_append_null(php_oci_collection * TSRMLS_DC);
+int php_oci_collection_append_date(php_oci_collection *, char *, int TSRMLS_DC);
+int php_oci_collection_append_number(php_oci_collection *, char *, int TSRMLS_DC);
+int php_oci_collection_append_string(php_oci_collection *, char *, int TSRMLS_DC);
+
+
+/* }}} */
+
+/* statement related prototypes {{{ */
+
+php_oci_statement * php_oci_statement_create (php_oci_connection *, char *, int TSRMLS_DC);
+int php_oci_statement_set_prefetch (php_oci_statement *, long TSRMLS_DC);
+int php_oci_statement_fetch (php_oci_statement *, ub4 TSRMLS_DC);
+php_oci_out_column * php_oci_statement_get_column (php_oci_statement *, long, char *, int TSRMLS_DC);
+int php_oci_statement_execute (php_oci_statement *, ub4 TSRMLS_DC);
+int php_oci_statement_cancel (php_oci_statement * TSRMLS_DC);
+void php_oci_statement_free (php_oci_statement * TSRMLS_DC);
+int php_oci_bind_pre_exec(void *data, void *result TSRMLS_DC);
+int php_oci_bind_post_exec(void *data TSRMLS_DC);
+int php_oci_bind_by_name(php_oci_statement *, char *, int, zval*, long, ub2 TSRMLS_DC);
+sb4 php_oci_bind_in_callback(dvoid *, OCIBind *, ub4, ub4, dvoid **, ub4 *, ub1 *, dvoid **);
+sb4 php_oci_bind_out_callback(dvoid *, OCIBind *, ub4, ub4, dvoid **, ub4 **, ub1 *, dvoid **, ub2 **);
+php_oci_out_column *php_oci_statement_get_column_helper(INTERNAL_FUNCTION_PARAMETERS, int need_data);
+int php_oci_cleanup_pre_fetch(void *data TSRMLS_DC);
+
+int php_oci_statement_get_type(php_oci_statement *, ub2 * TSRMLS_DC);
+int php_oci_statement_get_numrows(php_oci_statement *, ub4 * TSRMLS_DC);
+int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long max_table_length, long maxlength, long type TSRMLS_DC);
+php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length TSRMLS_DC);
+php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length TSRMLS_DC);
+php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, long maxlength TSRMLS_DC);
+php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, php_oci_connection *connection TSRMLS_DC);
+
+/* }}} */
+
+ZEND_BEGIN_MODULE_GLOBALS(oci) /* {{{ */
+ sword errcode; /* global last error code (used when connect fails, for example) */
+ OCIError *err; /* global error handle */
+
+ zend_bool debug_mode; /* debug mode flag */
+
+ long max_persistent; /* maximum number of persistent connections per process */
+ long num_persistent; /* number of existing persistent connections */
+ long num_links; /* non-persistent + persistent connections */
+ long num_statements; /* number of statements open */
+ long ping_interval; /* time interval between pings */
+ long persistent_timeout; /* time period after which idle persistent connection is considered expired */
+ long statement_cache_size; /* statement cache size. used with 9i+ clients only*/
+ long default_prefetch; /* default prefetch setting */
+ zend_bool privileged_connect; /* privileged connect flag (On/Off) */
+ zend_bool old_oci_close_semantics; /* old_oci_close_semantics flag (to determine the way oci_close() should behave) */
+
+ int shutdown; /* in shutdown flag */
+
+ OCIEnv *env; /* global environment handle */
+
+ zend_bool in_call;
+ char *connection_class;
+ zend_bool events;
+ char *edition;
+ZEND_END_MODULE_GLOBALS(oci) /* }}} */
+
+#ifdef ZTS
+#define OCI_G(v) TSRMG(oci_globals_id, zend_oci_globals *, v)
+#else
+#define OCI_G(v) (oci_globals.v)
+#endif
+
+ZEND_EXTERN_MODULE_GLOBALS(oci)
+
+# endif /* !PHP_OCI8_INT_H */
+#else /* !HAVE_OCI8 */
+
+# define oci8_module_ptr NULL
+
+#endif /* HAVE_OCI8 */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/tests/array_bind_001.phpt b/tests/array_bind_001.phpt
new file mode 100644
index 0000000000..1310325ad4
--- /dev/null
+++ b/tests/array_bind_001.phpt
@@ -0,0 +1,69 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 1
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name DATE)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF DATE INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = "";
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, SQLT_ODT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_bind_array_by_name(): OCI-21560: argument 3 is null, invalid, or out of range in %s on line %d
+
+Warning: oci_execute(): ORA-01008: not all variables bound in %s on line %d
+array(1) {
+ [0]=>
+ string(0) ""
+}
+Done
diff --git a/tests/array_bind_002.phpt b/tests/array_bind_002.phpt
new file mode 100644
index 0000000000..4c76df42f9
--- /dev/null
+++ b/tests/array_bind_002.phpt
@@ -0,0 +1,77 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 2
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name DATE)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF DATE INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array("06-DEC-05","10-DEC-80","21-AUG-91","26-OCT-17","05-NOV-05");
+
+oci_bind_array_by_name($statement, ":c1", $array, 0, 0, SQLT_ODT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_bind_array_by_name(): Maximum array length must be greater than zero in %s on line %d
+
+Warning: oci_execute(): ORA-01008: not all variables bound in %s on line %d
+array(5) {
+ [0]=>
+ string(9) "06-DEC-05"
+ [1]=>
+ string(9) "10-DEC-80"
+ [2]=>
+ string(9) "21-AUG-91"
+ [3]=>
+ string(9) "26-OCT-17"
+ [4]=>
+ string(9) "05-NOV-05"
+}
+Done
diff --git a/tests/array_bind_003.phpt b/tests/array_bind_003.phpt
new file mode 100644
index 0000000000..497e46e496
--- /dev/null
+++ b/tests/array_bind_003.phpt
@@ -0,0 +1,73 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 3
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name DATE)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF DATE INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array("06-DEC-05","10-DEC-80","21-AUG-91","26-OCT-17");
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, SQLT_ODT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_execute(): OCI_NO_DATA in %s on line %d
+array(4) {
+ [0]=>
+ string(9) "06-DEC-05"
+ [1]=>
+ string(9) "10-DEC-80"
+ [2]=>
+ string(9) "21-AUG-91"
+ [3]=>
+ string(9) "26-OCT-17"
+}
+Done
diff --git a/tests/array_bind_004.phpt b/tests/array_bind_004.phpt
new file mode 100644
index 0000000000..1ddf85149b
--- /dev/null
+++ b/tests/array_bind_004.phpt
@@ -0,0 +1,65 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 4
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name DATE)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF DATE INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array();
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, SQLT_ODT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_execute(): OCI_NO_DATA in %s on line %d
+array(0) {
+}
+Done
diff --git a/tests/array_bind_005.phpt b/tests/array_bind_005.phpt
new file mode 100644
index 0000000000..58dadc20ca
--- /dev/null
+++ b/tests/array_bind_005.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 5
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name VARCHAR(20))";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array("", "", "", "", "");
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 20, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+array(5) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(0) ""
+ [2]=>
+ string(0) ""
+ [3]=>
+ string(0) ""
+ [4]=>
+ string(0) ""
+}
+Done
diff --git a/tests/array_bind_006.phpt b/tests/array_bind_006.phpt
new file mode 100644
index 0000000000..e229dd8722
--- /dev/null
+++ b/tests/array_bind_006.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name(), SQLT_CHR and default max_length
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name VARCHAR(20))";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = array("one", "two", "three", "four", "five");
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, -1, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ string(4) "five"
+ [1]=>
+ string(4) "four"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(3) "two"
+ [4]=>
+ string(3) "one"
+}
+Done
diff --git a/tests/array_bind_007.phpt b/tests/array_bind_007.phpt
new file mode 100644
index 0000000000..10c92a8e7d
--- /dev/null
+++ b/tests/array_bind_007.phpt
@@ -0,0 +1,77 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 7
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name NUMBER)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array(1,2,3,4,5);
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, -1);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_bind_array_by_name(): Unknown or unsupported datatype given: -1 in %s on line %d
+
+Warning: oci_execute(): ORA-01008: not all variables bound in %s on line %d
+array(5) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+ [3]=>
+ int(4)
+ [4]=>
+ int(5)
+}
+Done
diff --git a/tests/array_bind_008.phpt b/tests/array_bind_008.phpt
new file mode 100644
index 0000000000..c44304c11c
--- /dev/null
+++ b/tests/array_bind_008.phpt
@@ -0,0 +1,78 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 8
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name NUMBER)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array(1,2,3,4,5);
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_execute(): ORA-06550: line %d, column %d:
+PLS-00418: array bind type must match PL/SQL table row type
+ORA-06550: line %d, column %d:
+PL/SQL: Statement ignored in %s on line %d
+array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "2"
+ [2]=>
+ string(1) "3"
+ [3]=>
+ string(1) "4"
+ [4]=>
+ string(1) "5"
+}
+Done
diff --git a/tests/array_bind_009.phpt b/tests/array_bind_009.phpt
new file mode 100644
index 0000000000..8e83b0982c
--- /dev/null
+++ b/tests/array_bind_009.phpt
@@ -0,0 +1,17 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 9
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+var_dump(oci_bind_array_by_name($c, ":c1", $array, 5, 5, SQLT_CHR));
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_bind_array_by_name(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+Done
diff --git a/tests/array_bind_010.phpt b/tests/array_bind_010.phpt
new file mode 100644
index 0000000000..a77ed913ea
--- /dev/null
+++ b/tests/array_bind_010.phpt
@@ -0,0 +1,36 @@
+--TEST--
+oci_bind_array_by_name() and invalid values 8
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$statement = oci_parse($c, 'SELECT user FROM v$session');
+
+$array = Array(1,2,3,4,5);
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_bind_array_by_name(): ORA-01036: illegal variable name/number in %s on line %d
+array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "2"
+ [2]=>
+ string(1) "3"
+ [3]=>
+ string(1) "4"
+ [4]=>
+ string(1) "5"
+}
+Done
diff --git a/tests/array_bind_011.phpt b/tests/array_bind_011.phpt
new file mode 100644
index 0000000000..e8e00a8091
--- /dev/null
+++ b/tests/array_bind_011.phpt
@@ -0,0 +1,67 @@
+--TEST--
+oci_bind_array_by_name(), SQLT_CHR, default max_length and empty array
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name VARCHAR(20))";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = array();
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, -1, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_bind_array_by_name(): You must provide max length value for empty arrays in %s on line %d
+
+Warning: oci_execute(): ORA-01008: not all variables bound in %s on line %d
+array(0) {
+}
+Done
diff --git a/tests/array_bind_012.phpt b/tests/array_bind_012.phpt
new file mode 100644
index 0000000000..2208f0b3b9
--- /dev/null
+++ b/tests/array_bind_012.phpt
@@ -0,0 +1,26 @@
+--TEST--
+oci_bind_array_by_name(), SQLT_CHR, default max_length and empty array
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$statement = oci_parse($c, 'SELECT user FROM v$session');
+
+$array = array();
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, -10, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_bind_array_by_name(): Invalid max length value (-10) in %s on line %d
+array(0) {
+}
+Done
diff --git a/tests/array_bind_013.phpt b/tests/array_bind_013.phpt
new file mode 100644
index 0000000000..4da9d8bbed
--- /dev/null
+++ b/tests/array_bind_013.phpt
@@ -0,0 +1,39 @@
+--TEST--
+oci_bind_array_by_name(), SQLT_CHR, default max_length and empty array
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$statement = oci_parse($c, 'SELECT user FROM v$session');
+
+$array = array();
+
+var_dump(oci_bind_array_by_name($statement, ":c1", $array, 5, -10, SQLT_CHR, -10));
+var_dump(oci_bind_array_by_name($statement, ":c1", $array, 5, -10));
+var_dump(oci_bind_array_by_name($statement, ":c1", $array, 5, -1));
+var_dump(oci_bind_array_by_name($statement, ":c1", $array, 5, 0));
+
+@oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_bind_array_by_name() expects at most 6 parameters, 7 given in %s on line %d
+NULL
+
+Warning: oci_bind_array_by_name(): You must provide max length value for empty arrays in %s on line %d
+bool(false)
+
+Warning: oci_bind_array_by_name(): You must provide max length value for empty arrays in %s on line %d
+bool(false)
+
+Warning: oci_bind_array_by_name(): You must provide max length value for empty arrays in %s on line %d
+bool(false)
+array(0) {
+}
+Done
diff --git a/tests/array_bind_014.phpt b/tests/array_bind_014.phpt
new file mode 100644
index 0000000000..bd9fdf1335
--- /dev/null
+++ b/tests/array_bind_014.phpt
@@ -0,0 +1,73 @@
+--TEST--
+oci_bind_array_by_name() and NUMBERs
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name NUMBER)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+for ($i = 1; $i < 6; $i++) {
+ $statement = oci_parse($c, "INSERT INTO bind_test VALUES (".$i.")");
+ oci_execute($statement);
+}
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+$array = Array();
+oci_bind_array_by_name($statement, ":c1", $array, 5, -1, SQLT_INT);
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+array(5) {
+ [0]=>
+ int(5)
+ [1]=>
+ int(4)
+ [2]=>
+ int(3)
+ [3]=>
+ int(2)
+ [4]=>
+ int(1)
+}
+Done
diff --git a/tests/array_bind_date.phpt b/tests/array_bind_date.phpt
new file mode 100644
index 0000000000..63da558f91
--- /dev/null
+++ b/tests/array_bind_date.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and SQLT_ODT
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name DATE)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF DATE INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array("06-DEC-05","10-DEC-80","21-AUG-91","26-OCT-17","05-NOV-05");
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, SQLT_ODT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ string(9) "05-NOV-05"
+ [1]=>
+ string(9) "26-OCT-17"
+ [2]=>
+ string(9) "21-AUG-91"
+ [3]=>
+ string(9) "10-DEC-80"
+ [4]=>
+ string(9) "06-DEC-05"
+}
+Done
diff --git a/tests/array_bind_date1.phpt b/tests/array_bind_date1.phpt
new file mode 100644
index 0000000000..ebf767570b
--- /dev/null
+++ b/tests/array_bind_date1.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and SQLT_ODT
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name DATE)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF DATE INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array("06-DEC-05","10-DEC-80","21-AUG-91","26-OCT-17","05-NOV-05");
+
+oci_bind_array_by_name($statement, ":c1", $array, 10, 5, SQLT_ODT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ string(9) "05-NOV-05"
+ [1]=>
+ string(9) "26-OCT-17"
+ [2]=>
+ string(9) "21-AUG-91"
+ [3]=>
+ string(9) "10-DEC-80"
+ [4]=>
+ string(9) "06-DEC-05"
+}
+Done
diff --git a/tests/array_bind_float.phpt b/tests/array_bind_float.phpt
new file mode 100644
index 0000000000..1aafb24317
--- /dev/null
+++ b/tests/array_bind_float.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and SQLT_FLT
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name FLOAT)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF FLOAT INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array(1.243,2.5658,3.4234,4.2123,5.9999);
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, SQLT_FLT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ float(5.9999)
+ [1]=>
+ float(4.2123)
+ [2]=>
+ float(3.4234)
+ [3]=>
+ float(2.5658)
+ [4]=>
+ float(1.243)
+}
+Done
diff --git a/tests/array_bind_float1.phpt b/tests/array_bind_float1.phpt
new file mode 100644
index 0000000000..ead85890fa
--- /dev/null
+++ b/tests/array_bind_float1.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and SQLT_FLT
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name FLOAT)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF FLOAT INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array(1.243,2.5658,3.4234,4.2123,5.9999);
+
+oci_bind_array_by_name($statement, ":c1", $array, 10, 5, SQLT_FLT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ float(5.9999)
+ [1]=>
+ float(4.2123)
+ [2]=>
+ float(3.4234)
+ [3]=>
+ float(2.5658)
+ [4]=>
+ float(1.243)
+}
+Done
diff --git a/tests/array_bind_int.phpt b/tests/array_bind_int.phpt
new file mode 100644
index 0000000000..3c8bfd4f57
--- /dev/null
+++ b/tests/array_bind_int.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and SQLT_INT
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name NUMBER)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array(1,2,3,4,5);
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 5, SQLT_NUM);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ int(5)
+ [1]=>
+ int(4)
+ [2]=>
+ int(3)
+ [3]=>
+ int(2)
+ [4]=>
+ int(1)
+}
+Done
diff --git a/tests/array_bind_int1.phpt b/tests/array_bind_int1.phpt
new file mode 100644
index 0000000000..5e06de876b
--- /dev/null
+++ b/tests/array_bind_int1.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and SQLT_INT
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name NUMBER)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array(1,2,3,4,5);
+
+oci_bind_array_by_name($statement, ":c1", $array, 10, 5, SQLT_INT);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ int(5)
+ [1]=>
+ int(4)
+ [2]=>
+ int(3)
+ [3]=>
+ int(2)
+ [4]=>
+ int(1)
+}
+Done
diff --git a/tests/array_bind_str.phpt b/tests/array_bind_str.phpt
new file mode 100644
index 0000000000..c8e1e0cdb5
--- /dev/null
+++ b/tests/array_bind_str.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and SQLT_AVC
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name VARCHAR(20))";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array("one", "two", "three", "four", "five");
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 20, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ string(4) "five"
+ [1]=>
+ string(4) "four"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(3) "two"
+ [4]=>
+ string(3) "one"
+}
+Done
diff --git a/tests/array_bind_str1.phpt b/tests/array_bind_str1.phpt
new file mode 100644
index 0000000000..af4dbfe220
--- /dev/null
+++ b/tests/array_bind_str1.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci_bind_array_by_name() and SQLT_AVC
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name VARCHAR(20))";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+
+$array = Array("one", "two", "three", "four", "five");
+
+oci_bind_array_by_name($statement, ":c1", $array, 10, 20, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ string(4) "five"
+ [1]=>
+ string(4) "four"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(3) "two"
+ [4]=>
+ string(3) "one"
+}
+Done
diff --git a/tests/b47243_1.phpt b/tests/b47243_1.phpt
new file mode 100644
index 0000000000..9f04f302cb
--- /dev/null
+++ b/tests/b47243_1.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #47243 (Crash on exit with ZTS mode)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Run Test
+
+$s = oci_parse($c, "select cursor(select dummy from dual) from dual");
+oci_execute($s);
+oci_fetch_all($s, $r);
+
+// No explicit free or close
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+===DONE===
diff --git a/tests/b47243_2.phpt b/tests/b47243_2.phpt
new file mode 100644
index 0000000000..08f5f528c3
--- /dev/null
+++ b/tests/b47243_2.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #47243 (Crash on exit with ZTS mode)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Run Test
+
+$s = oci_parse($c, "select cursor(select dummy from dual) from dual");
+oci_execute($s);
+oci_fetch_all($s, $r);
+
+oci_free_statement($s);
+// no explicit close
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+===DONE===
diff --git a/tests/b47243_3.phpt b/tests/b47243_3.phpt
new file mode 100644
index 0000000000..0decb34872
--- /dev/null
+++ b/tests/b47243_3.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #47243 (Crash on exit with ZTS mode)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Run Test
+
+$s = oci_parse($c, "select cursor(select dummy from dual) from dual");
+oci_execute($s);
+oci_fetch_all($s, $r);
+
+// With explicit free and close
+oci_free_statement($s);
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+===DONE===
diff --git a/tests/bind_char_1.phpt b/tests/bind_char_1.phpt
new file mode 100644
index 0000000000..71cccbfc50
--- /dev/null
+++ b/tests/bind_char_1.phpt
@@ -0,0 +1,306 @@
+--TEST--
+SELECT oci_bind_by_name with SQLT_AFC aka CHAR
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[01]\.2\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 10gR2 or 11gR2 databases");
+}
+?>
+--FILE--
+<?php
+
+// Note: expected output is valid for 32bit clients to 32bit 10gR2 XE or 11.2.0.1 64bit DBs.
+// It will diff on the undefined cases with a 32bit 11.2.0.1 DB
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table bind_char_tab",
+ "create table bind_char_tab (id number, c1 char(10), c2 varchar2(10))",
+ "insert into bind_char_tab values (1, 'abc', NULL)",
+ "insert into bind_char_tab values (2, NULL, 'abc')",
+ "insert into bind_char_tab values (3, NULL, 'abc ')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+echo "*** Non-null Data Tests against CHAR***\n";
+
+$bv1 = 'abc';
+
+echo "Test 1.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c1 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "\n\n*** NULL data tests against CHAR ***\n";
+
+$bv1 = null;
+
+echo "Test 2.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c1 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+
+echo "\n\n*** Non-null Data Tests against VARCHAR2***\n";
+
+$bv1 = 'abc';
+
+echo "Test 3.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c2 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+
+echo "\n\n*** NULL data tests against VARCHAR2 ***\n";
+
+$bv1 = null;
+
+echo "Test 4.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c2 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+
+
+function do_e_q($s)
+{
+ echo " Querying:\n";
+
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ echo " Oci_execute error ORA-".$m['code']." Exiting Query\n";
+ return;
+ }
+ while ($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) {
+ foreach ($row as $item) {
+ echo " :" . $item . ":\n";
+ }
+ }
+}
+
+// Cleanup
+$stmtarray = array(
+ "drop table bind_char_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+*** Non-null Data Tests against CHAR***
+Test 1.1: Type: default. Length: default
+ Querying:
+Test 1.2: Type: AFC. Length: default
+ Querying:
+ :1:
+ :abc :
+ ::
+Test 1.3: Type: AFC: Length: 0
+ Querying:
+ :1:
+ :abc :
+ ::
+Test 1.4: Type: AFC: Length: strlen
+ Querying:
+ :1:
+ :abc :
+ ::
+Test 1.5: Type: AFC. Length: strlen-1
+ Querying:
+ :1:
+ :abc :
+ ::
+Test 1.6: Type: AFC. Length: strlen+1
+ Querying:
+ :1:
+ :abc :
+ ::
+
+
+*** NULL data tests against CHAR ***
+Test 2.1: Type: default. Length: default
+ Querying:
+Test 2.2: Type: AFC. Length: default
+ Querying:
+Test 2.3: Type: AFC: Length: 0
+ Querying:
+Test 2.4: Type: AFC: Length: strlen
+ Querying:
+Test 2.5: Type: AFC. Length: strlen-1
+ Querying:
+Test 2.6: Type: AFC. Length: strlen+1
+ Querying:
+
+
+*** Non-null Data Tests against VARCHAR2***
+Test 3.1: Type: default. Length: default
+ Querying:
+ :2:
+ ::
+ :abc:
+Test 3.2: Type: AFC. Length: default
+ Querying:
+ :2:
+ ::
+ :abc:
+Test 3.3: Type: AFC: Length: 0
+ Querying:
+ :2:
+ ::
+ :abc:
+Test 3.4: Type: AFC: Length: strlen
+ Querying:
+ :2:
+ ::
+ :abc:
+Test 3.5: Type: AFC. Length: strlen-1
+ Querying:
+ :2:
+ ::
+ :abc:
+Test 3.6: Type: AFC. Length: strlen+1
+ Querying:
+ :2:
+ ::
+ :abc:
+
+
+*** NULL data tests against VARCHAR2 ***
+Test 4.1: Type: default. Length: default
+ Querying:
+Test 4.2: Type: AFC. Length: default
+ Querying:
+Test 4.3: Type: AFC: Length: 0
+ Querying:
+Test 4.4: Type: AFC: Length: strlen
+ Querying:
+Test 4.5: Type: AFC. Length: strlen-1
+ Querying:
+Test 4.6: Type: AFC. Length: strlen+1
+ Querying:
+Done
diff --git a/tests/bind_char_1_11gR1.phpt b/tests/bind_char_1_11gR1.phpt
new file mode 100644
index 0000000000..60b7142ff1
--- /dev/null
+++ b/tests/bind_char_1_11gR1.phpt
@@ -0,0 +1,297 @@
+--TEST--
+SELECT oci_bind_by_name with SQLT_AFC aka CHAR
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 11\.1\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 11gR1 database");
+}
+?>
+--FILE--
+<?php
+
+// Output is for 32 bit client to 64bit 11.1.0.6
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table bind_char_tab",
+ "create table bind_char_tab (id number, c1 char(10), c2 varchar2(10))",
+ "insert into bind_char_tab values (1, 'abc', NULL)",
+ "insert into bind_char_tab values (2, NULL, 'abc')",
+ "insert into bind_char_tab values (3, NULL, 'abc ')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+echo "*** Non-null Data Tests against CHAR***\n";
+
+$bv1 = 'abc';
+
+echo "Test 1.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c1 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "\n\n*** NULL data tests against CHAR ***\n";
+
+$bv1 = null;
+
+echo "Test 2.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c1 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 2.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+
+echo "\n\n*** Non-null Data Tests against VARCHAR2***\n";
+
+$bv1 = 'abc';
+
+echo "Test 3.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c2 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 3.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+
+echo "\n\n*** NULL data tests against VARCHAR2 ***\n";
+
+$bv1 = null;
+
+echo "Test 4.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c2 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 4.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+
+
+function do_e_q($s)
+{
+ echo " Querying:\n";
+
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ echo " Oci_execute error ORA-".$m['code']." Exiting Query\n";
+ return;
+ }
+ while ($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) {
+ foreach ($row as $item) {
+ echo " :" . $item . ":\n";
+ }
+ }
+}
+
+// Cleanup
+$stmtarray = array(
+ "drop table bind_char_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+*** Non-null Data Tests against CHAR***
+Test 1.1: Type: default. Length: default
+ Querying:
+Test 1.2: Type: AFC. Length: default
+ Querying:
+ :1:
+ :abc :
+ ::
+Test 1.3: Type: AFC: Length: 0
+ Querying:
+ Oci_execute error ORA-1460 Exiting Query
+Test 1.4: Type: AFC: Length: strlen
+ Querying:
+ :1:
+ :abc :
+ ::
+Test 1.5: Type: AFC. Length: strlen-1
+ Querying:
+ Oci_execute error ORA-1460 Exiting Query
+Test 1.6: Type: AFC. Length: strlen+1
+ Querying:
+ :1:
+ :abc :
+ ::
+
+
+*** NULL data tests against CHAR ***
+Test 2.1: Type: default. Length: default
+ Querying:
+Test 2.2: Type: AFC. Length: default
+ Querying:
+Test 2.3: Type: AFC: Length: 0
+ Querying:
+Test 2.4: Type: AFC: Length: strlen
+ Querying:
+Test 2.5: Type: AFC. Length: strlen-1
+ Querying:
+Test 2.6: Type: AFC. Length: strlen+1
+ Querying:
+
+
+*** Non-null Data Tests against VARCHAR2***
+Test 3.1: Type: default. Length: default
+ Querying:
+ :2:
+ ::
+ :abc:
+Test 3.2: Type: AFC. Length: default
+ Querying:
+ :2:
+ ::
+ :abc:
+Test 3.3: Type: AFC: Length: 0
+ Querying:
+ Oci_execute error ORA-1460 Exiting Query
+Test 3.4: Type: AFC: Length: strlen
+ Querying:
+ :2:
+ ::
+ :abc:
+Test 3.5: Type: AFC. Length: strlen-1
+ Querying:
+ Oci_execute error ORA-1460 Exiting Query
+Test 3.6: Type: AFC. Length: strlen+1
+ Querying:
+ :2:
+ ::
+ :abc:
+
+
+*** NULL data tests against VARCHAR2 ***
+Test 4.1: Type: default. Length: default
+ Querying:
+Test 4.2: Type: AFC. Length: default
+ Querying:
+Test 4.3: Type: AFC: Length: 0
+ Querying:
+Test 4.4: Type: AFC: Length: strlen
+ Querying:
+Test 4.5: Type: AFC. Length: strlen-1
+ Querying:
+Test 4.6: Type: AFC. Length: strlen+1
+ Querying:
+Done
diff --git a/tests/bind_char_2.phpt b/tests/bind_char_2.phpt
new file mode 100644
index 0000000000..6c7dbafcc5
--- /dev/null
+++ b/tests/bind_char_2.phpt
@@ -0,0 +1,127 @@
+--TEST--
+SELECT oci_bind_by_name with SQLT_AFC aka CHAR and dates
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[01]\.2\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 10gR2 or 11gR2 databases");
+}
+?>
+--FILE--
+<?php
+
+// Note: expected output is valid for 32bit clients to 32bit 10gR2 XE or 11.2.0.1 64bit DBs.
+// It will diff on the undefined cases with a 32bit 11.2.0.1 DB
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "alter session set nls_date_format='YYYY-MM-DD'",
+ "drop table bind_char_tab",
+ "create table bind_char_tab (id number, c1 date)",
+ "insert into bind_char_tab values (1, '2008-04-20')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+$bv1 = '2008-04-20';
+
+echo "Test 1.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c1 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+
+function do_e_q($s)
+{
+ echo " Querying:\n";
+
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ echo " Oci_execute error ORA-".$m['code']." Exiting Query\n";
+ return;
+ }
+ while ($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) {
+ foreach ($row as $item) {
+ echo " :" . $item . ":\n";
+ }
+ }
+}
+
+// Cleanup
+$stmtarray = array(
+ "drop table bind_char_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Test 1.1: Type: default. Length: default
+ Querying:
+ :1:
+ :2008-04-20:
+Test 1.2: Type: AFC. Length: default
+ Querying:
+ :1:
+ :2008-04-20:
+Test 1.3: Type: AFC: Length: 0
+ Querying:
+ Oci_execute error ORA-1460 Exiting Query
+Test 1.4: Type: AFC: Length: strlen
+ Querying:
+ :1:
+ :2008-04-20:
+Test 1.5: Type: AFC. Length: strlen-1
+ Querying:
+ :1:
+ :2008-04-20:
+Test 1.6: Type: AFC. Length: strlen+1
+ Querying:
+ :1:
+ :2008-04-20:
+Done
diff --git a/tests/bind_char_2_11gR1.phpt b/tests/bind_char_2_11gR1.phpt
new file mode 100644
index 0000000000..68a872fc46
--- /dev/null
+++ b/tests/bind_char_2_11gR1.phpt
@@ -0,0 +1,123 @@
+--TEST--
+SELECT oci_bind_by_name with SQLT_AFC aka CHAR and dates
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 11\.1\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 11gR1 database");
+}
+?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "alter session set nls_date_format='YYYY-MM-DD'",
+ "drop table bind_char_tab",
+ "create table bind_char_tab (id number, c1 date)",
+ "insert into bind_char_tab values (1, '2008-04-20')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+$bv1 = '2008-04-20';
+
+echo "Test 1.1: Type: default. Length: default\n";
+$s = oci_parse($c, "select * from bind_char_tab where c1 = :bv");
+$r = oci_bind_by_name($s, ":bv", $bv1);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.2: Type: AFC. Length: default\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, -1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.3: Type: AFC: Length: 0\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, 0, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.4: Type: AFC: Length: strlen\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.5: Type: AFC. Length: strlen-1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+echo "Test 1.6: Type: AFC. Length: strlen+1\n";
+$r = oci_bind_by_name($s, ":bv", $bv1, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e_q($s);
+
+
+function do_e_q($s)
+{
+ echo " Querying:\n";
+
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ echo " Oci_execute error ORA-".$m['code']." Exiting Query\n";
+ return;
+ }
+ while ($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) {
+ foreach ($row as $item) {
+ echo " :" . $item . ":\n";
+ }
+ }
+}
+
+// Cleanup
+$stmtarray = array(
+ "drop table bind_char_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Test 1.1: Type: default. Length: default
+ Querying:
+ :1:
+ :2008-04-20:
+Test 1.2: Type: AFC. Length: default
+ Querying:
+ :1:
+ :2008-04-20:
+Test 1.3: Type: AFC: Length: 0
+ Querying:
+ Oci_execute error ORA-1460 Exiting Query
+Test 1.4: Type: AFC: Length: strlen
+ Querying:
+ :1:
+ :2008-04-20:
+Test 1.5: Type: AFC. Length: strlen-1
+ Querying:
+ Oci_execute error ORA-1460 Exiting Query
+Test 1.6: Type: AFC. Length: strlen+1
+ Querying:
+ :1:
+ :2008-04-20:
+Done
diff --git a/tests/bind_char_3.phpt b/tests/bind_char_3.phpt
new file mode 100644
index 0000000000..8d4e95f6bf
--- /dev/null
+++ b/tests/bind_char_3.phpt
@@ -0,0 +1,345 @@
+--TEST--
+PL/SQL oci_bind_by_name with SQLT_AFC aka CHAR to CHAR parameter
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[01]\.2\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 10gR2 11gR2 databases");
+}
+?>
+--FILE--
+<?php
+
+// Note: expected output is valid for 32bit clients to 32bit 10gR2 XE or 11.2.0.1 64bit DBs.
+// It will diff on the undefined cases with a 32bit 11.2.0.1 DB
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace function bind_char_3_fn(p1 char) return char as begin return p1; end;",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+echo "Test 1.1 In Length: default. In Type: default. Out Length: default. Out Type: default\n";
+
+$s = oci_parse($c, "begin :bv2 := bind_char_3_fn(:bv1); end;");
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+echo "Test 1.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 1.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.5 In Length: strlen. In Type: AFC. Out Length: strlen(input). Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.6 In Length: strlen. In Type: AFC. Out Length: strlen(input)-1. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.7 In Length: strlen. In Type: AFC. Out Length: strlen(input)+1. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "\n\nTests with ''\n\n";
+
+echo "Test 2.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 2.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.6 In Length: 0. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, 0, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.7 In Length: 1. In Type: AFC. Out Length: 1. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, 1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "\n\nTests with NULL\n";
+
+echo "Test 3.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 3.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 3.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.6 In Length: -1. In Type: AFC. Out Length: 1. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+function do_e($s)
+{
+ echo " Executing:\n";
+
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ echo " Oci_execute error ORA-".$m['code']."\n";
+ return;
+ }
+}
+
+// Cleanup
+
+//require(dirname(__FILE__).'/drop_table.inc');
+
+$stmtarray = array(
+ "drop function bind_char_3_fn"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1.1 In Length: default. In Type: default. Out Length: default. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(30) "abc "
+Test 1.5 In Length: strlen. In Type: AFC. Out Length: strlen(input). Out Type: AFC
+ Executing:
+string(3) "abc"
+string(9) "abc "
+Test 1.6 In Length: strlen. In Type: AFC. Out Length: strlen(input)-1. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(6) "abc "
+Test 1.7 In Length: strlen. In Type: AFC. Out Length: strlen(input)+1. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(12) "abc "
+
+
+Tests with ''
+
+Test 2.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+string(0) ""
+NULL
+Test 2.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+string(0) ""
+NULL
+Test 2.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.6 In Length: 0. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.7 In Length: 1. In Type: AFC. Out Length: 1. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+
+
+Tests with NULL
+Test 3.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+NULL
+NULL
+Test 3.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+NULL
+NULL
+Test 3.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.6 In Length: -1. In Type: AFC. Out Length: 1. Out Type: AFC
+ Executing:
+NULL
+NULL
+Done
diff --git a/tests/bind_char_3_11gR1.phpt b/tests/bind_char_3_11gR1.phpt
new file mode 100644
index 0000000000..aaa5371195
--- /dev/null
+++ b/tests/bind_char_3_11gR1.phpt
@@ -0,0 +1,344 @@
+--TEST--
+PL/SQL oci_bind_by_name with SQLT_AFC aka CHAR to CHAR parameter
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 11\.1\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 11gR1 database");
+}
+?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace function bind_char_3_fn(p1 char) return char as begin return p1; end;",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+echo "Test 1.1 In Length: default. In Type: default. Out Length: default. Out Type: default\n";
+
+$s = oci_parse($c, "begin :bv2 := bind_char_3_fn(:bv1); end;");
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+echo "Test 1.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 1.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.5 In Length: strlen. In Type: AFC. Out Length: strlen(input). Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.6 In Length: strlen. In Type: AFC. Out Length: strlen(input)-1. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.7 In Length: strlen. In Type: AFC. Out Length: strlen(input)+1. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "\n\nTests with ''\n\n";
+
+echo "Test 2.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 2.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.6 In Length: 0. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, 0, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.7 In Length: 1. In Type: AFC. Out Length: 1. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, 1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "\n\nTests with NULL\n";
+
+echo "Test 3.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 3.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 3.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.6 In Length: -1. In Type: AFC. Out Length: 1. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+function do_e($s)
+{
+ echo " Executing:\n";
+
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ echo " Oci_execute error ORA-".$m['code']."\n";
+ return;
+ }
+}
+
+// Cleanup
+
+//require(dirname(__FILE__).'/drop_table.inc');
+
+$stmtarray = array(
+ "drop function bind_char_3_fn"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1.1 In Length: default. In Type: default. Out Length: default. Out Type: default
+ Executing:
+ Oci_execute error ORA-6502
+string(3) "abc"
+NULL
+Test 1.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(10) "abc "
+Test 1.5 In Length: strlen. In Type: AFC. Out Length: strlen(input). Out Type: AFC
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.6 In Length: strlen. In Type: AFC. Out Length: strlen(input)-1. Out Type: AFC
+ Executing:
+ Oci_execute error ORA-6502
+string(3) "abc"
+string(3) "abc"
+Test 1.7 In Length: strlen. In Type: AFC. Out Length: strlen(input)+1. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(4) "abc "
+
+
+Tests with ''
+
+Test 2.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+string(0) ""
+NULL
+Test 2.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+string(0) ""
+NULL
+Test 2.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.6 In Length: 0. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.7 In Length: 1. In Type: AFC. Out Length: 1. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+
+
+Tests with NULL
+Test 3.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+NULL
+NULL
+Test 3.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+NULL
+NULL
+Test 3.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.6 In Length: -1. In Type: AFC. Out Length: 1. Out Type: AFC
+ Executing:
+NULL
+NULL
+Done
diff --git a/tests/bind_char_4.phpt b/tests/bind_char_4.phpt
new file mode 100644
index 0000000000..40221b266f
--- /dev/null
+++ b/tests/bind_char_4.phpt
@@ -0,0 +1,347 @@
+--TEST--
+PL/SQL oci_bind_by_name with SQLT_AFC aka CHAR to VARCHAR2 parameter
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[01]\.2\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 10gR2 or 11gR2 databases");
+}
+?>
+--FILE--
+<?php
+
+// Note: expected output is valid for 32bit clients to 32bit 10gR2 XE or 11.2.0.1 64bit DBs.
+// It will diff on the undefined cases with a 32bit 11.2.0.1 DB
+
+// Same test as bind_char_3 but the PL/SQL function uses VARCHAR2 instead of CHAR
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace function bind_char_3_fn(p1 varchar2) return varchar2 as begin return p1; end;",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+echo "Test 1.1 In Length: default. In Type: default. Out Length: default. Out Type: default\n";
+
+$s = oci_parse($c, "begin :bv2 := bind_char_3_fn(:bv1); end;");
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+echo "Test 1.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 1.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.5 In Length: strlen. In Type: AFC. Out Length: strlen(input). Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.6 In Length: strlen. In Type: AFC. Out Length: strlen(input)-1. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.7 In Length: strlen. In Type: AFC. Out Length: strlen(input)+1. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "\n\nTests with ''\n\n";
+
+echo "Test 2.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 2.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.6 In Length: 0. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, 0, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.7 In Length: 1. In Type: AFC. Out Length: 1. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, 1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "\n\nTests with NULL\n";
+
+echo "Test 3.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 3.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 3.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.6 In Length: -1. In Type: AFC. Out Length: 1. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+function do_e($s)
+{
+ echo " Executing:\n";
+
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ echo " Oci_execute error ORA-".$m['code']."\n";
+ return;
+ }
+}
+
+// Cleanup
+
+//require(dirname(__FILE__).'/drop_table.inc');
+
+$stmtarray = array(
+ "drop function bind_char_3_fn"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1.1 In Length: default. In Type: default. Out Length: default. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(30) "abc "
+Test 1.5 In Length: strlen. In Type: AFC. Out Length: strlen(input). Out Type: AFC
+ Executing:
+string(3) "abc"
+string(9) "abc "
+Test 1.6 In Length: strlen. In Type: AFC. Out Length: strlen(input)-1. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(6) "abc "
+Test 1.7 In Length: strlen. In Type: AFC. Out Length: strlen(input)+1. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(12) "abc "
+
+
+Tests with ''
+
+Test 2.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+string(0) ""
+NULL
+Test 2.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+string(0) ""
+NULL
+Test 2.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.6 In Length: 0. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.7 In Length: 1. In Type: AFC. Out Length: 1. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+
+
+Tests with NULL
+Test 3.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+NULL
+NULL
+Test 3.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+NULL
+NULL
+Test 3.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.6 In Length: -1. In Type: AFC. Out Length: 1. Out Type: AFC
+ Executing:
+NULL
+NULL
+Done
diff --git a/tests/bind_char_4_11gR1.phpt b/tests/bind_char_4_11gR1.phpt
new file mode 100644
index 0000000000..c4f7968e14
--- /dev/null
+++ b/tests/bind_char_4_11gR1.phpt
@@ -0,0 +1,346 @@
+--TEST--
+PL/SQL oci_bind_by_name with SQLT_AFC aka CHAR to VARCHAR2 parameter
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 11\.1\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 11gR1 database");
+}
+?>
+--FILE--
+<?php
+
+// Same test as bind_char_3 but the PL/SQL function uses VARCHAR2 instead of CHAR
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace function bind_char_3_fn(p1 varchar2) return varchar2 as begin return p1; end;",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+echo "Test 1.1 In Length: default. In Type: default. Out Length: default. Out Type: default\n";
+
+$s = oci_parse($c, "begin :bv2 := bind_char_3_fn(:bv1); end;");
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+echo "Test 1.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 1.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.5 In Length: strlen. In Type: AFC. Out Length: strlen(input). Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1), SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.6 In Length: strlen. In Type: AFC. Out Length: strlen(input)-1. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1)-1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 1.7 In Length: strlen. In Type: AFC. Out Length: strlen(input)+1. Out Type: AFC\n";
+
+$bv1 = 'abc';
+$r = oci_bind_by_name($s, ':bv1', $bv1, strlen($bv1), SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, strlen($bv1)+1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "\n\nTests with ''\n\n";
+
+echo "Test 2.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 2.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.6 In Length: 0. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, 0, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 2.7 In Length: 1. In Type: AFC. Out Length: 1. Out Type: AFC\n";
+
+$bv1 = '';
+$r = oci_bind_by_name($s, ':bv1', $bv1, 1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "\n\nTests with NULL\n";
+
+echo "Test 3.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 3.2 In Length: default. In Type: default. Out Length: 10. Out Type: default\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 10, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+echo "Test 3.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 0, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+
+echo "Test 3.6 In Length: -1. In Type: AFC. Out Length: 1. Out Type: AFC\n";
+
+$bv1 = null;
+$r = oci_bind_by_name($s, ':bv1', $bv1, -1, SQLT_AFC) && oci_bind_by_name($s, ':bv2', $bv2, 1, SQLT_AFC);
+if ($r)
+ do_e($s);
+var_dump($bv1, $bv2);
+
+
+function do_e($s)
+{
+ echo " Executing:\n";
+
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ echo " Oci_execute error ORA-".$m['code']."\n";
+ return;
+ }
+}
+
+// Cleanup
+
+//require(dirname(__FILE__).'/drop_table.inc');
+
+$stmtarray = array(
+ "drop function bind_char_3_fn"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1.1 In Length: default. In Type: default. Out Length: default. Out Type: default
+ Executing:
+ Oci_execute error ORA-6502
+string(3) "abc"
+NULL
+Test 1.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(10) "abc "
+Test 1.5 In Length: strlen. In Type: AFC. Out Length: strlen(input). Out Type: AFC
+ Executing:
+string(3) "abc"
+string(3) "abc"
+Test 1.6 In Length: strlen. In Type: AFC. Out Length: strlen(input)-1. Out Type: AFC
+ Executing:
+ Oci_execute error ORA-6502
+string(3) "abc"
+string(3) "abc"
+Test 1.7 In Length: strlen. In Type: AFC. Out Length: strlen(input)+1. Out Type: AFC
+ Executing:
+string(3) "abc"
+string(4) "abc "
+
+
+Tests with ''
+
+Test 2.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+string(0) ""
+NULL
+Test 2.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+string(0) ""
+NULL
+Test 2.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.6 In Length: 0. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+Test 2.7 In Length: 1. In Type: AFC. Out Length: 1. Out Type: AFC
+ Executing:
+string(0) ""
+NULL
+
+
+Tests with NULL
+Test 3.1 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.2 In Length: default. In Type: default. Out Length: 10. Out Type: default
+ Executing:
+NULL
+NULL
+Test 3.3 In Length: -1. In Type: AFC. Out Length: 10. Out Type: default
+ Executing:
+NULL
+NULL
+Test 3.4 In Length: -1. In Type: AFC. Out Length: 10. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.5 In Length: -1. In Type: AFC. Out Length: 0. Out Type: AFC
+ Executing:
+NULL
+NULL
+Test 3.6 In Length: -1. In Type: AFC. Out Length: 1. Out Type: AFC
+ Executing:
+NULL
+NULL
+Done
diff --git a/tests/bind_empty.phpt b/tests/bind_empty.phpt
new file mode 100644
index 0000000000..4c6c07e3c0
--- /dev/null
+++ b/tests/bind_empty.phpt
@@ -0,0 +1,127 @@
+--TEST--
+binding empty values
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table bind_empty_tab";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_empty_tab(name VARCHAR(10))";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+
+echo "Test 1\n";
+
+$name = null;
+$stmt = oci_parse($c, "UPDATE bind_empty_tab SET name=:name");
+oci_bind_by_name($stmt, ":name", $name);
+
+var_dump(oci_execute($stmt));
+
+echo "Test 2\n";
+
+$name = "";
+$stmt = oci_parse($c, "UPDATE bind_empty_tab SET name=:name");
+oci_bind_by_name($stmt, ":name", $name);
+
+var_dump(oci_execute($stmt));
+
+echo "Test 3\n";
+
+$stmt = oci_parse($c, "INSERT INTO bind_empty_tab (NAME) VALUES ('abc')");
+$res = oci_execute($stmt);
+
+$stmt = oci_parse($c, "INSERT INTO bind_empty_tab (NAME) VALUES ('def')");
+$res = oci_execute($stmt);
+
+$name = null;
+$stmt = oci_parse($c, "UPDATE bind_empty_tab SET name=:name WHERE NAME = 'abc'");
+oci_bind_by_name($stmt, ":name", $name);
+
+var_dump(oci_execute($stmt));
+
+$stid = oci_parse($c, "select * from bind_empty_tab order by 1");
+oci_execute($stid);
+oci_fetch_all($stid, $res);
+var_dump($res);
+
+echo "Test 4\n";
+
+$name = "";
+$stmt = oci_parse($c, "UPDATE bind_empty_tab SET name=:name WHERE NAME = 'def'");
+oci_bind_by_name($stmt, ":name", $name);
+
+var_dump(oci_execute($stmt));
+
+$stid = oci_parse($c, "select * from bind_empty_tab order by 1");
+oci_execute($stid);
+oci_fetch_all($stid, $res);
+var_dump($res);
+
+echo "Test 5\n";
+
+$av = $bv = 'old';
+$s = oci_parse($c, "begin :bv := null; end; ");
+oci_bind_by_name($s, ":bv", $bv);
+oci_execute($s);
+var_dump($av);
+var_dump($bv);
+
+echo "Test 6\n";
+
+$av = $bv = null;
+$s = oci_parse($c, "begin :bv := null; end; ");
+oci_bind_by_name($s, ":bv", $bv);
+oci_execute($s);
+var_dump($av);
+var_dump($bv);
+
+// Clean up
+
+$drop = "DROP table bind_empty_tab";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+bool(true)
+Test 2
+bool(true)
+Test 3
+bool(true)
+array(1) {
+ ["NAME"]=>
+ array(2) {
+ [0]=>
+ string(3) "def"
+ [1]=>
+ NULL
+ }
+}
+Test 4
+bool(true)
+array(1) {
+ ["NAME"]=>
+ array(2) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ }
+}
+Test 5
+string(3) "old"
+NULL
+Test 6
+NULL
+NULL
+===DONE===
diff --git a/tests/bind_long.phpt b/tests/bind_long.phpt
new file mode 100644
index 0000000000..ba6bd4d044
--- /dev/null
+++ b/tests/bind_long.phpt
@@ -0,0 +1,41 @@
+--TEST--
+bind LONG field
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+$stmt = oci_parse($c, "drop table phptestlng");
+@oci_execute($stmt);
+
+$stmt = oci_parse($c, "create table phptestlng( id number(10), filetxt long)");
+oci_execute($stmt);
+
+$stmt = oci_parse ($c, "insert into phptestlng (id, filetxt) values (:id, :filetxt)");
+$i=1;
+$filetxt = file_get_contents( dirname(__FILE__)."/test.txt");
+
+oci_bind_by_name( $stmt, ":id", $i, -1);
+oci_bind_by_name( $stmt, ":filetxt", $filetxt, -1, SQLT_LNG);
+oci_execute($stmt, OCI_DEFAULT);
+oci_commit($c);
+
+$stmt = oci_parse($c, "SELECT filetxt FROM phptestlng");
+oci_execute($stmt);
+
+$row = oci_fetch_row($stmt);
+var_dump(md5($row[0]));
+var_dump(strlen($row[0]));
+
+$stmt = oci_parse($c, "drop table phptestlng");
+oci_execute($stmt);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+string(32) "5c7c34abf7ea51936785062dbfcaeddc"
+int(394)
+Done
diff --git a/tests/bind_long_raw.phpt b/tests/bind_long_raw.phpt
new file mode 100644
index 0000000000..2a9962eace
--- /dev/null
+++ b/tests/bind_long_raw.phpt
@@ -0,0 +1,38 @@
+--TEST--
+bind LONG RAW field
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$stmt = oci_parse($c, "create table phptestlngraw( id number(10), fileimage long raw)");
+oci_execute($stmt);
+
+$stmt = oci_parse ($c, "insert into phptestlngraw (id, fileimage) values (:id, :fileimage)");
+$i=1;
+$fileimage = file_get_contents( dirname(__FILE__)."/test.gif");
+
+oci_bind_by_name( $stmt, ":id", $i, -1);
+oci_bind_by_name( $stmt, ":fileimage", $fileimage, -1, SQLT_LBI);
+oci_execute($stmt, OCI_DEFAULT);
+oci_commit($c);
+
+$stmt = oci_parse($c, "SELECT fileimage FROM phptestlngraw");
+oci_execute($stmt);
+
+$row = oci_fetch_row($stmt);
+var_dump(md5($row[0]));
+var_dump(strlen($row[0]));
+
+$stmt = oci_parse($c, "drop table phptestlngraw");
+oci_execute($stmt);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+string(32) "614fcbba1effb7caa27ef0ef25c27fcf"
+int(2523)
+Done
diff --git a/tests/bind_raw.phpt b/tests/bind_raw.phpt
new file mode 100644
index 0000000000..c9087e552b
--- /dev/null
+++ b/tests/bind_raw.phpt
@@ -0,0 +1,39 @@
+--TEST--
+bind RAW field
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$stmt = oci_parse($c, "create table phptestrawtable( id number(10), fileimage raw(1000))");
+oci_execute($stmt);
+
+$stmt = oci_parse ($c, "insert into phptestrawtable (id, fileimage) values (:id, :fileimage)");
+$i=1;
+$fileimage = file_get_contents( dirname(__FILE__)."/test.gif");
+$fileimage = substr($fileimage, 0, 300);
+
+oci_bind_by_name( $stmt, ":id", $i, -1);
+oci_bind_by_name( $stmt, ":fileimage", $fileimage, -1, SQLT_BIN);
+oci_execute($stmt, OCI_DEFAULT);
+oci_commit($c);
+
+$stmt = oci_parse($c, "SELECT fileimage FROM phptestrawtable");
+oci_execute($stmt);
+
+$row = oci_fetch_row($stmt);
+var_dump(md5($row[0]));
+var_dump(strlen($row[0]));
+
+$stmt = oci_parse($c, "drop table phptestrawtable");
+oci_execute($stmt);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+string(32) "88b274d7a257ac6f70435b83abd4e26e"
+int(300)
+Done
diff --git a/tests/bind_rowid.phpt b/tests/bind_rowid.phpt
new file mode 100644
index 0000000000..f15d8f8bbb
--- /dev/null
+++ b/tests/bind_rowid.phpt
@@ -0,0 +1,86 @@
+--TEST--
+Test ROWID bind
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+function do_query($c)
+{
+ $s = oci_parse($c, 'select address from rid_tab order by id');
+ $id = 1;
+ oci_execute($s, OCI_DEFAULT);
+ while ($row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS)) {
+ var_dump($row);
+ }
+}
+
+$stmts = array(
+ "drop table rid_tab",
+ "create table rid_tab (id number, address varchar2(40))",
+ "insert into rid_tab (id, address) values (1, 'original text #1')",
+ "insert into rid_tab (id, address) values (2, 'original text #2')"
+);
+
+foreach ($stmts as $q) {
+ $s = oci_parse($c, $q);
+ @oci_execute($s);
+}
+
+echo "Initial Data\n";
+do_query($c);
+
+$s = oci_parse($c, 'select rowid, address from rid_tab where id = :l_bv for update');
+$id = 1;
+oci_bind_by_name($s, ':l_bv', $id);
+oci_execute($s, OCI_DEFAULT);
+$row = oci_fetch_array($s, OCI_ASSOC+OCI_RETURN_NULLS);
+
+$rid = $row['ROWID'];
+$addr = $row['ADDRESS'];
+
+$addr = 'Some new text';
+
+// Save changes
+$s = oci_parse($c,'update rid_tab set address = :a_bv where rowid = :r_bv');
+oci_bind_by_name($s, ':r_bv', $rid, -1, OCI_B_ROWID);
+oci_bind_by_name($s, ':a_bv', $addr);
+oci_execute($s);
+
+echo "Verify Change\n";
+do_query($c);
+
+// Cleanup
+
+$stmts = array("drop table rid_tab");
+
+foreach ($stmts as $q) {
+ $s = oci_parse($c, $q);
+ @oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Initial Data
+array(1) {
+ ["ADDRESS"]=>
+ string(16) "original text #1"
+}
+array(1) {
+ ["ADDRESS"]=>
+ string(16) "original text #2"
+}
+Verify Change
+array(1) {
+ ["ADDRESS"]=>
+ string(13) "Some new text"
+}
+array(1) {
+ ["ADDRESS"]=>
+ string(16) "original text #2"
+}
+Done
diff --git a/tests/bug26133.phpt b/tests/bug26133.phpt
new file mode 100644
index 0000000000..2463e70c76
--- /dev/null
+++ b/tests/bug26133.phpt
@@ -0,0 +1,62 @@
+--TEST--
+Bug #26133 (ocifreedesc() segfault)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialize
+
+$stmtarray = array(
+ "drop table bug26133_tab",
+ "create table bug26133_tab (id number, value number)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+$ora_sql = "INSERT INTO bug26133_tab (id, value) VALUES ('1','1') RETURNING ROWID INTO :v_rowid ";
+
+$statement = OCIParse($c,$ora_sql);
+$rowid = OCINewDescriptor($c,OCI_D_ROWID);
+OCIBindByName($statement,":v_rowid", $rowid,-1,OCI_B_ROWID);
+if (OCIExecute($statement)) {
+ OCICommit($c);
+}
+OCIFreeStatement($statement);
+$rowid->free();
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table bug26133_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+Done
diff --git a/tests/bug27303_1.phpt b/tests/bug27303_1.phpt
new file mode 100644
index 0000000000..82c2d6f506
--- /dev/null
+++ b/tests/bug27303_1.phpt
@@ -0,0 +1,261 @@
+--TEST--
+Bug #27303 (OCIBindByName binds numeric PHP values as characters)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[01]\.2\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 19gR2 or 11gR2 databases");
+}
+?>
+--FILE--
+<?php
+
+// Note: expected output is valid for 32bit clients to 32bit 10gR2 XE or 11.2.0.1 64bit DBs.
+// It will diff with a 32bit 11.2.0.1 DB
+
+require dirname(__FILE__).'/connect.inc';
+
+$create_st = array();
+$create_st[] = "drop sequence myseq";
+$create_st[] = "drop table mytab";
+$create_st[] = "create sequence myseq";
+$create_st[] = "create table mytab (mydata varchar2(20), seqcol number)";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ @oci_execute($stmt);
+}
+
+define('MYLIMIT', 200);
+
+$stmt = "insert into mytab (mydata, seqcol) values ('Some data', myseq.nextval) returning seqcol into :mybv";
+
+$stid = OCIParse($c, $stmt);
+if (!$stid) { echo "Parse error"; die; }
+
+$r = OCIBindByName($stid, ':MYBV', $mybv);
+if (!$r) { echo "Bind error"; die; }
+
+for ($i = 1; $i < MYLIMIT; $i++) {
+ $r = OCIExecute($stid, OCI_DEFAULT);
+ if (!$r) { echo "Execute error"; die; }
+ var_dump($mybv);
+}
+
+OCICommit($c);
+
+$drop_st = array();
+$drop_st[] = "drop sequence myseq";
+$drop_st[] = "drop table mytab";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+string(1) "1"
+string(1) "2"
+string(1) "3"
+string(1) "4"
+string(1) "5"
+string(1) "6"
+string(1) "7"
+string(1) "8"
+string(1) "9"
+string(2) "10"
+string(2) "11"
+string(2) "12"
+string(2) "13"
+string(2) "14"
+string(2) "15"
+string(2) "16"
+string(2) "17"
+string(2) "18"
+string(2) "19"
+string(2) "20"
+string(2) "21"
+string(2) "22"
+string(2) "23"
+string(2) "24"
+string(2) "25"
+string(2) "26"
+string(2) "27"
+string(2) "28"
+string(2) "29"
+string(2) "30"
+string(2) "31"
+string(2) "32"
+string(2) "33"
+string(2) "34"
+string(2) "35"
+string(2) "36"
+string(2) "37"
+string(2) "38"
+string(2) "39"
+string(2) "40"
+string(2) "41"
+string(2) "42"
+string(2) "43"
+string(2) "44"
+string(2) "45"
+string(2) "46"
+string(2) "47"
+string(2) "48"
+string(2) "49"
+string(2) "50"
+string(2) "51"
+string(2) "52"
+string(2) "53"
+string(2) "54"
+string(2) "55"
+string(2) "56"
+string(2) "57"
+string(2) "58"
+string(2) "59"
+string(2) "60"
+string(2) "61"
+string(2) "62"
+string(2) "63"
+string(2) "64"
+string(2) "65"
+string(2) "66"
+string(2) "67"
+string(2) "68"
+string(2) "69"
+string(2) "70"
+string(2) "71"
+string(2) "72"
+string(2) "73"
+string(2) "74"
+string(2) "75"
+string(2) "76"
+string(2) "77"
+string(2) "78"
+string(2) "79"
+string(2) "80"
+string(2) "81"
+string(2) "82"
+string(2) "83"
+string(2) "84"
+string(2) "85"
+string(2) "86"
+string(2) "87"
+string(2) "88"
+string(2) "89"
+string(2) "90"
+string(2) "91"
+string(2) "92"
+string(2) "93"
+string(2) "94"
+string(2) "95"
+string(2) "96"
+string(2) "97"
+string(2) "98"
+string(2) "99"
+string(3) "100"
+string(3) "101"
+string(3) "102"
+string(3) "103"
+string(3) "104"
+string(3) "105"
+string(3) "106"
+string(3) "107"
+string(3) "108"
+string(3) "109"
+string(3) "110"
+string(3) "111"
+string(3) "112"
+string(3) "113"
+string(3) "114"
+string(3) "115"
+string(3) "116"
+string(3) "117"
+string(3) "118"
+string(3) "119"
+string(3) "120"
+string(3) "121"
+string(3) "122"
+string(3) "123"
+string(3) "124"
+string(3) "125"
+string(3) "126"
+string(3) "127"
+string(3) "128"
+string(3) "129"
+string(3) "130"
+string(3) "131"
+string(3) "132"
+string(3) "133"
+string(3) "134"
+string(3) "135"
+string(3) "136"
+string(3) "137"
+string(3) "138"
+string(3) "139"
+string(3) "140"
+string(3) "141"
+string(3) "142"
+string(3) "143"
+string(3) "144"
+string(3) "145"
+string(3) "146"
+string(3) "147"
+string(3) "148"
+string(3) "149"
+string(3) "150"
+string(3) "151"
+string(3) "152"
+string(3) "153"
+string(3) "154"
+string(3) "155"
+string(3) "156"
+string(3) "157"
+string(3) "158"
+string(3) "159"
+string(3) "160"
+string(3) "161"
+string(3) "162"
+string(3) "163"
+string(3) "164"
+string(3) "165"
+string(3) "166"
+string(3) "167"
+string(3) "168"
+string(3) "169"
+string(3) "170"
+string(3) "171"
+string(3) "172"
+string(3) "173"
+string(3) "174"
+string(3) "175"
+string(3) "176"
+string(3) "177"
+string(3) "178"
+string(3) "179"
+string(3) "180"
+string(3) "181"
+string(3) "182"
+string(3) "183"
+string(3) "184"
+string(3) "185"
+string(3) "186"
+string(3) "187"
+string(3) "188"
+string(3) "189"
+string(3) "190"
+string(3) "191"
+string(3) "192"
+string(3) "193"
+string(3) "194"
+string(3) "195"
+string(3) "196"
+string(3) "197"
+string(3) "198"
+string(3) "199"
+Done \ No newline at end of file
diff --git a/tests/bug27303_1_11gR1.phpt b/tests/bug27303_1_11gR1.phpt
new file mode 100644
index 0000000000..fe5c17c3ee
--- /dev/null
+++ b/tests/bug27303_1_11gR1.phpt
@@ -0,0 +1,258 @@
+--TEST--
+Bug #27303 (OCIBindByName binds numeric PHP values as characters)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 11\.1\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 11gR1 database");
+}
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$create_st = array();
+$create_st[] = "drop sequence myseq";
+$create_st[] = "drop table mytab";
+$create_st[] = "create sequence myseq";
+$create_st[] = "create table mytab (mydata varchar2(20), seqcol number)";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ @oci_execute($stmt);
+}
+
+define('MYLIMIT', 200);
+
+$stmt = "insert into mytab (mydata, seqcol) values ('Some data', myseq.nextval) returning seqcol into :mybv";
+
+$stid = OCIParse($c, $stmt);
+if (!$stid) { echo "Parse error"; die; }
+
+$r = OCIBindByName($stid, ':MYBV', $mybv);
+if (!$r) { echo "Bind error"; die; }
+
+for ($i = 1; $i < MYLIMIT; $i++) {
+ $r = OCIExecute($stid, OCI_DEFAULT);
+ if (!$r) { echo "Execute error"; die; }
+ var_dump($mybv);
+}
+
+OCICommit($c);
+
+$drop_st = array();
+$drop_st[] = "drop sequence myseq";
+$drop_st[] = "drop table mytab";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+string(1) "1"
+string(1) "2"
+string(1) "3"
+string(1) "4"
+string(1) "5"
+string(1) "6"
+string(1) "7"
+string(1) "8"
+string(1) "9"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+Done
diff --git a/tests/bug27303_2.phpt b/tests/bug27303_2.phpt
new file mode 100644
index 0000000000..44b9ce6c61
--- /dev/null
+++ b/tests/bug27303_2.phpt
@@ -0,0 +1,263 @@
+--TEST--
+Bug #27303 (OCIBindByName binds numeric PHP values as characters)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[01]\.2\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 10gR2 or 11gR2 database");
+}
+?>
+--FILE--
+<?php
+
+// Note: expected output is valid for 32bit clients to 32bit 10gR2 XE or 11.2.0.1 64bit DBs.
+// It will diff with a 32bit 11.2.0.1 DB
+
+require dirname(__FILE__).'/connect.inc';
+
+$create_st = array();
+$create_st[] = "drop sequence myseq";
+$create_st[] = "drop table mytab";
+$create_st[] = "create sequence myseq";
+$create_st[] = "create table mytab (mydata varchar2(20), seqcol number)";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+define('MYLIMIT', 200);
+define('INITMYBV', 11);
+
+$stmt = "insert into mytab (mydata, seqcol) values ('Some data', myseq.nextval) returning seqcol into :mybv";
+
+$stid = OCIParse($c, $stmt);
+if (!$stid) { echo "Parse error"; die; }
+
+$mybv = INITMYBV;
+$r = OCIBindByName($stid, ':MYBV', $mybv);
+if (!$r) { echo "Bind error"; die; }
+
+for ($i = 1; $i < MYLIMIT; $i++) {
+ $r = OCIExecute($stid, OCI_DEFAULT);
+ if (!$r) { echo "Execute error"; die; }
+ var_dump($mybv);
+}
+
+OCICommit($c);
+
+$drop_st = array();
+$drop_st[] = "drop sequence myseq";
+$drop_st[] = "drop table mytab";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+string(1) "1"
+string(1) "2"
+string(1) "3"
+string(1) "4"
+string(1) "5"
+string(1) "6"
+string(1) "7"
+string(1) "8"
+string(1) "9"
+string(2) "10"
+string(2) "11"
+string(2) "12"
+string(2) "13"
+string(2) "14"
+string(2) "15"
+string(2) "16"
+string(2) "17"
+string(2) "18"
+string(2) "19"
+string(2) "20"
+string(2) "21"
+string(2) "22"
+string(2) "23"
+string(2) "24"
+string(2) "25"
+string(2) "26"
+string(2) "27"
+string(2) "28"
+string(2) "29"
+string(2) "30"
+string(2) "31"
+string(2) "32"
+string(2) "33"
+string(2) "34"
+string(2) "35"
+string(2) "36"
+string(2) "37"
+string(2) "38"
+string(2) "39"
+string(2) "40"
+string(2) "41"
+string(2) "42"
+string(2) "43"
+string(2) "44"
+string(2) "45"
+string(2) "46"
+string(2) "47"
+string(2) "48"
+string(2) "49"
+string(2) "50"
+string(2) "51"
+string(2) "52"
+string(2) "53"
+string(2) "54"
+string(2) "55"
+string(2) "56"
+string(2) "57"
+string(2) "58"
+string(2) "59"
+string(2) "60"
+string(2) "61"
+string(2) "62"
+string(2) "63"
+string(2) "64"
+string(2) "65"
+string(2) "66"
+string(2) "67"
+string(2) "68"
+string(2) "69"
+string(2) "70"
+string(2) "71"
+string(2) "72"
+string(2) "73"
+string(2) "74"
+string(2) "75"
+string(2) "76"
+string(2) "77"
+string(2) "78"
+string(2) "79"
+string(2) "80"
+string(2) "81"
+string(2) "82"
+string(2) "83"
+string(2) "84"
+string(2) "85"
+string(2) "86"
+string(2) "87"
+string(2) "88"
+string(2) "89"
+string(2) "90"
+string(2) "91"
+string(2) "92"
+string(2) "93"
+string(2) "94"
+string(2) "95"
+string(2) "96"
+string(2) "97"
+string(2) "98"
+string(2) "99"
+string(3) "100"
+string(3) "101"
+string(3) "102"
+string(3) "103"
+string(3) "104"
+string(3) "105"
+string(3) "106"
+string(3) "107"
+string(3) "108"
+string(3) "109"
+string(3) "110"
+string(3) "111"
+string(3) "112"
+string(3) "113"
+string(3) "114"
+string(3) "115"
+string(3) "116"
+string(3) "117"
+string(3) "118"
+string(3) "119"
+string(3) "120"
+string(3) "121"
+string(3) "122"
+string(3) "123"
+string(3) "124"
+string(3) "125"
+string(3) "126"
+string(3) "127"
+string(3) "128"
+string(3) "129"
+string(3) "130"
+string(3) "131"
+string(3) "132"
+string(3) "133"
+string(3) "134"
+string(3) "135"
+string(3) "136"
+string(3) "137"
+string(3) "138"
+string(3) "139"
+string(3) "140"
+string(3) "141"
+string(3) "142"
+string(3) "143"
+string(3) "144"
+string(3) "145"
+string(3) "146"
+string(3) "147"
+string(3) "148"
+string(3) "149"
+string(3) "150"
+string(3) "151"
+string(3) "152"
+string(3) "153"
+string(3) "154"
+string(3) "155"
+string(3) "156"
+string(3) "157"
+string(3) "158"
+string(3) "159"
+string(3) "160"
+string(3) "161"
+string(3) "162"
+string(3) "163"
+string(3) "164"
+string(3) "165"
+string(3) "166"
+string(3) "167"
+string(3) "168"
+string(3) "169"
+string(3) "170"
+string(3) "171"
+string(3) "172"
+string(3) "173"
+string(3) "174"
+string(3) "175"
+string(3) "176"
+string(3) "177"
+string(3) "178"
+string(3) "179"
+string(3) "180"
+string(3) "181"
+string(3) "182"
+string(3) "183"
+string(3) "184"
+string(3) "185"
+string(3) "186"
+string(3) "187"
+string(3) "188"
+string(3) "189"
+string(3) "190"
+string(3) "191"
+string(3) "192"
+string(3) "193"
+string(3) "194"
+string(3) "195"
+string(3) "196"
+string(3) "197"
+string(3) "198"
+string(3) "199"
+Done \ No newline at end of file
diff --git a/tests/bug27303_2_11gR1.phpt b/tests/bug27303_2_11gR1.phpt
new file mode 100644
index 0000000000..e1daef0537
--- /dev/null
+++ b/tests/bug27303_2_11gR1.phpt
@@ -0,0 +1,260 @@
+--TEST--
+Bug #27303 (OCIBindByName binds numeric PHP values as characters)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 11\.1\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 11gR1 database");
+}
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$create_st = array();
+$create_st[] = "drop sequence myseq";
+$create_st[] = "drop table mytab";
+$create_st[] = "create sequence myseq";
+$create_st[] = "create table mytab (mydata varchar2(20), seqcol number)";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+define('MYLIMIT', 200);
+define('INITMYBV', 11);
+
+$stmt = "insert into mytab (mydata, seqcol) values ('Some data', myseq.nextval) returning seqcol into :mybv";
+
+$stid = OCIParse($c, $stmt);
+if (!$stid) { echo "Parse error"; die; }
+
+$mybv = INITMYBV;
+$r = OCIBindByName($stid, ':MYBV', $mybv);
+if (!$r) { echo "Bind error"; die; }
+
+for ($i = 1; $i < MYLIMIT; $i++) {
+ $r = OCIExecute($stid, OCI_DEFAULT);
+ if (!$r) { echo "Execute error"; die; }
+ var_dump($mybv);
+}
+
+OCICommit($c);
+
+$drop_st = array();
+$drop_st[] = "drop sequence myseq";
+$drop_st[] = "drop table mytab";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+string(1) "1"
+string(1) "2"
+string(1) "3"
+string(1) "4"
+string(1) "5"
+string(1) "6"
+string(1) "7"
+string(1) "8"
+string(1) "9"
+string(2) "10"
+string(2) "11"
+string(2) "12"
+string(2) "13"
+string(2) "14"
+string(2) "15"
+string(2) "16"
+string(2) "17"
+string(2) "18"
+string(2) "19"
+string(2) "20"
+string(2) "21"
+string(2) "22"
+string(2) "23"
+string(2) "24"
+string(2) "25"
+string(2) "26"
+string(2) "27"
+string(2) "28"
+string(2) "29"
+string(2) "30"
+string(2) "31"
+string(2) "32"
+string(2) "33"
+string(2) "34"
+string(2) "35"
+string(2) "36"
+string(2) "37"
+string(2) "38"
+string(2) "39"
+string(2) "40"
+string(2) "41"
+string(2) "42"
+string(2) "43"
+string(2) "44"
+string(2) "45"
+string(2) "46"
+string(2) "47"
+string(2) "48"
+string(2) "49"
+string(2) "50"
+string(2) "51"
+string(2) "52"
+string(2) "53"
+string(2) "54"
+string(2) "55"
+string(2) "56"
+string(2) "57"
+string(2) "58"
+string(2) "59"
+string(2) "60"
+string(2) "61"
+string(2) "62"
+string(2) "63"
+string(2) "64"
+string(2) "65"
+string(2) "66"
+string(2) "67"
+string(2) "68"
+string(2) "69"
+string(2) "70"
+string(2) "71"
+string(2) "72"
+string(2) "73"
+string(2) "74"
+string(2) "75"
+string(2) "76"
+string(2) "77"
+string(2) "78"
+string(2) "79"
+string(2) "80"
+string(2) "81"
+string(2) "82"
+string(2) "83"
+string(2) "84"
+string(2) "85"
+string(2) "86"
+string(2) "87"
+string(2) "88"
+string(2) "89"
+string(2) "90"
+string(2) "91"
+string(2) "92"
+string(2) "93"
+string(2) "94"
+string(2) "95"
+string(2) "96"
+string(2) "97"
+string(2) "98"
+string(2) "99"
+string(2) "10"
+string(2) "10"
+string(2) "10"
+string(2) "10"
+string(2) "10"
+string(2) "10"
+string(2) "10"
+string(2) "10"
+string(2) "10"
+string(2) "10"
+string(2) "11"
+string(2) "11"
+string(2) "11"
+string(2) "11"
+string(2) "11"
+string(2) "11"
+string(2) "11"
+string(2) "11"
+string(2) "11"
+string(2) "11"
+string(2) "12"
+string(2) "12"
+string(2) "12"
+string(2) "12"
+string(2) "12"
+string(2) "12"
+string(2) "12"
+string(2) "12"
+string(2) "12"
+string(2) "12"
+string(2) "13"
+string(2) "13"
+string(2) "13"
+string(2) "13"
+string(2) "13"
+string(2) "13"
+string(2) "13"
+string(2) "13"
+string(2) "13"
+string(2) "13"
+string(2) "14"
+string(2) "14"
+string(2) "14"
+string(2) "14"
+string(2) "14"
+string(2) "14"
+string(2) "14"
+string(2) "14"
+string(2) "14"
+string(2) "14"
+string(2) "15"
+string(2) "15"
+string(2) "15"
+string(2) "15"
+string(2) "15"
+string(2) "15"
+string(2) "15"
+string(2) "15"
+string(2) "15"
+string(2) "15"
+string(2) "16"
+string(2) "16"
+string(2) "16"
+string(2) "16"
+string(2) "16"
+string(2) "16"
+string(2) "16"
+string(2) "16"
+string(2) "16"
+string(2) "16"
+string(2) "17"
+string(2) "17"
+string(2) "17"
+string(2) "17"
+string(2) "17"
+string(2) "17"
+string(2) "17"
+string(2) "17"
+string(2) "17"
+string(2) "17"
+string(2) "18"
+string(2) "18"
+string(2) "18"
+string(2) "18"
+string(2) "18"
+string(2) "18"
+string(2) "18"
+string(2) "18"
+string(2) "18"
+string(2) "18"
+string(2) "19"
+string(2) "19"
+string(2) "19"
+string(2) "19"
+string(2) "19"
+string(2) "19"
+string(2) "19"
+string(2) "19"
+string(2) "19"
+string(2) "19"
+Done
diff --git a/tests/bug27303_3.phpt b/tests/bug27303_3.phpt
new file mode 100644
index 0000000000..6395388471
--- /dev/null
+++ b/tests/bug27303_3.phpt
@@ -0,0 +1,252 @@
+--TEST--
+Bug #27303 (OCIBindByName binds numeric PHP values as characters)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$create_st = array();
+$create_st[] = "drop sequence myseq";
+$create_st[] = "drop table mytab";
+$create_st[] = "create sequence myseq";
+$create_st[] = "create table mytab (mydata varchar2(20), seqcol number)";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ @oci_execute($stmt);
+}
+
+define('MYLIMIT', 200);
+define('INITMYBV', 11);
+
+$stmt = "insert into mytab (mydata, seqcol) values ('Some data', myseq.nextval) returning seqcol into :mybv";
+
+$stid = OCIParse($c, $stmt);
+if (!$stid) { echo "Parse error"; die; }
+
+$mybv = INITMYBV;
+$r = OCIBindByName($stid, ':MYBV', $mybv, 5, SQLT_INT);
+if (!$r) { echo "Bind error"; die; }
+
+for ($i = 1; $i < MYLIMIT; $i++) {
+ $r = OCIExecute($stid, OCI_DEFAULT);
+ if (!$r) { echo "Execute error"; die; }
+ var_dump($mybv);
+}
+
+OCICommit($c);
+
+$drop_st = array();
+$drop_st[] = "drop sequence myseq";
+$drop_st[] = "drop table mytab";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+echo "Done\n";
+?>
+--EXPECTF--
+int(1)
+int(2)
+int(3)
+int(4)
+int(5)
+int(6)
+int(7)
+int(8)
+int(9)
+int(10)
+int(11)
+int(12)
+int(13)
+int(14)
+int(15)
+int(16)
+int(17)
+int(18)
+int(19)
+int(20)
+int(21)
+int(22)
+int(23)
+int(24)
+int(25)
+int(26)
+int(27)
+int(28)
+int(29)
+int(30)
+int(31)
+int(32)
+int(33)
+int(34)
+int(35)
+int(36)
+int(37)
+int(38)
+int(39)
+int(40)
+int(41)
+int(42)
+int(43)
+int(44)
+int(45)
+int(46)
+int(47)
+int(48)
+int(49)
+int(50)
+int(51)
+int(52)
+int(53)
+int(54)
+int(55)
+int(56)
+int(57)
+int(58)
+int(59)
+int(60)
+int(61)
+int(62)
+int(63)
+int(64)
+int(65)
+int(66)
+int(67)
+int(68)
+int(69)
+int(70)
+int(71)
+int(72)
+int(73)
+int(74)
+int(75)
+int(76)
+int(77)
+int(78)
+int(79)
+int(80)
+int(81)
+int(82)
+int(83)
+int(84)
+int(85)
+int(86)
+int(87)
+int(88)
+int(89)
+int(90)
+int(91)
+int(92)
+int(93)
+int(94)
+int(95)
+int(96)
+int(97)
+int(98)
+int(99)
+int(100)
+int(101)
+int(102)
+int(103)
+int(104)
+int(105)
+int(106)
+int(107)
+int(108)
+int(109)
+int(110)
+int(111)
+int(112)
+int(113)
+int(114)
+int(115)
+int(116)
+int(117)
+int(118)
+int(119)
+int(120)
+int(121)
+int(122)
+int(123)
+int(124)
+int(125)
+int(126)
+int(127)
+int(128)
+int(129)
+int(130)
+int(131)
+int(132)
+int(133)
+int(134)
+int(135)
+int(136)
+int(137)
+int(138)
+int(139)
+int(140)
+int(141)
+int(142)
+int(143)
+int(144)
+int(145)
+int(146)
+int(147)
+int(148)
+int(149)
+int(150)
+int(151)
+int(152)
+int(153)
+int(154)
+int(155)
+int(156)
+int(157)
+int(158)
+int(159)
+int(160)
+int(161)
+int(162)
+int(163)
+int(164)
+int(165)
+int(166)
+int(167)
+int(168)
+int(169)
+int(170)
+int(171)
+int(172)
+int(173)
+int(174)
+int(175)
+int(176)
+int(177)
+int(178)
+int(179)
+int(180)
+int(181)
+int(182)
+int(183)
+int(184)
+int(185)
+int(186)
+int(187)
+int(188)
+int(189)
+int(190)
+int(191)
+int(192)
+int(193)
+int(194)
+int(195)
+int(196)
+int(197)
+int(198)
+int(199)
+Done
diff --git a/tests/bug27303_4.phpt b/tests/bug27303_4.phpt
new file mode 100644
index 0000000000..3c35c65b77
--- /dev/null
+++ b/tests/bug27303_4.phpt
@@ -0,0 +1,261 @@
+--TEST--
+Bug #27303 (OCIBindByName binds numeric PHP values as characters)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[01]\.2\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 10gR2 or 11gR2 databases");
+}
+?>
+--FILE--
+<?php
+
+// Note: expected output is valid for 32bit clients to 32bit 10gR2 XE or 11.2.0.1 64bit DBs.
+// It will diff with a 32bit 11.2.0.1 DB
+
+require dirname(__FILE__).'/connect.inc';
+
+$create_st = array();
+$create_st[] = "drop sequence myseq";
+$create_st[] = "drop table mytab";
+$create_st[] = "create sequence myseq";
+$create_st[] = "create table mytab (mydata varchar2(20), seqcol number)";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+define('MYLIMIT', 200);
+
+$stmt = "insert into mytab (mydata, seqcol) values ('Some data', myseq.nextval) returning seqcol into :mybv";
+
+$stid = OCIParse($c, $stmt);
+if (!$stid) { echo "Parse error"; die; }
+
+$r = OCIBindByName($stid, ':MYBV', $mybv, 0 );
+if (!$r) { echo "Bind error"; die; }
+
+for ($i = 1; $i < MYLIMIT; $i++) {
+ $r = OCIExecute($stid, OCI_DEFAULT);
+ if (!$r) { echo "Execute error"; die; }
+ var_dump($mybv);
+}
+
+OCICommit($c);
+
+$drop_st = array();
+$drop_st[] = "drop sequence myseq";
+$drop_st[] = "drop table mytab";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+string(1) "1"
+string(1) "2"
+string(1) "3"
+string(1) "4"
+string(1) "5"
+string(1) "6"
+string(1) "7"
+string(1) "8"
+string(1) "9"
+string(2) "10"
+string(2) "11"
+string(2) "12"
+string(2) "13"
+string(2) "14"
+string(2) "15"
+string(2) "16"
+string(2) "17"
+string(2) "18"
+string(2) "19"
+string(2) "20"
+string(2) "21"
+string(2) "22"
+string(2) "23"
+string(2) "24"
+string(2) "25"
+string(2) "26"
+string(2) "27"
+string(2) "28"
+string(2) "29"
+string(2) "30"
+string(2) "31"
+string(2) "32"
+string(2) "33"
+string(2) "34"
+string(2) "35"
+string(2) "36"
+string(2) "37"
+string(2) "38"
+string(2) "39"
+string(2) "40"
+string(2) "41"
+string(2) "42"
+string(2) "43"
+string(2) "44"
+string(2) "45"
+string(2) "46"
+string(2) "47"
+string(2) "48"
+string(2) "49"
+string(2) "50"
+string(2) "51"
+string(2) "52"
+string(2) "53"
+string(2) "54"
+string(2) "55"
+string(2) "56"
+string(2) "57"
+string(2) "58"
+string(2) "59"
+string(2) "60"
+string(2) "61"
+string(2) "62"
+string(2) "63"
+string(2) "64"
+string(2) "65"
+string(2) "66"
+string(2) "67"
+string(2) "68"
+string(2) "69"
+string(2) "70"
+string(2) "71"
+string(2) "72"
+string(2) "73"
+string(2) "74"
+string(2) "75"
+string(2) "76"
+string(2) "77"
+string(2) "78"
+string(2) "79"
+string(2) "80"
+string(2) "81"
+string(2) "82"
+string(2) "83"
+string(2) "84"
+string(2) "85"
+string(2) "86"
+string(2) "87"
+string(2) "88"
+string(2) "89"
+string(2) "90"
+string(2) "91"
+string(2) "92"
+string(2) "93"
+string(2) "94"
+string(2) "95"
+string(2) "96"
+string(2) "97"
+string(2) "98"
+string(2) "99"
+string(3) "100"
+string(3) "101"
+string(3) "102"
+string(3) "103"
+string(3) "104"
+string(3) "105"
+string(3) "106"
+string(3) "107"
+string(3) "108"
+string(3) "109"
+string(3) "110"
+string(3) "111"
+string(3) "112"
+string(3) "113"
+string(3) "114"
+string(3) "115"
+string(3) "116"
+string(3) "117"
+string(3) "118"
+string(3) "119"
+string(3) "120"
+string(3) "121"
+string(3) "122"
+string(3) "123"
+string(3) "124"
+string(3) "125"
+string(3) "126"
+string(3) "127"
+string(3) "128"
+string(3) "129"
+string(3) "130"
+string(3) "131"
+string(3) "132"
+string(3) "133"
+string(3) "134"
+string(3) "135"
+string(3) "136"
+string(3) "137"
+string(3) "138"
+string(3) "139"
+string(3) "140"
+string(3) "141"
+string(3) "142"
+string(3) "143"
+string(3) "144"
+string(3) "145"
+string(3) "146"
+string(3) "147"
+string(3) "148"
+string(3) "149"
+string(3) "150"
+string(3) "151"
+string(3) "152"
+string(3) "153"
+string(3) "154"
+string(3) "155"
+string(3) "156"
+string(3) "157"
+string(3) "158"
+string(3) "159"
+string(3) "160"
+string(3) "161"
+string(3) "162"
+string(3) "163"
+string(3) "164"
+string(3) "165"
+string(3) "166"
+string(3) "167"
+string(3) "168"
+string(3) "169"
+string(3) "170"
+string(3) "171"
+string(3) "172"
+string(3) "173"
+string(3) "174"
+string(3) "175"
+string(3) "176"
+string(3) "177"
+string(3) "178"
+string(3) "179"
+string(3) "180"
+string(3) "181"
+string(3) "182"
+string(3) "183"
+string(3) "184"
+string(3) "185"
+string(3) "186"
+string(3) "187"
+string(3) "188"
+string(3) "189"
+string(3) "190"
+string(3) "191"
+string(3) "192"
+string(3) "193"
+string(3) "194"
+string(3) "195"
+string(3) "196"
+string(3) "197"
+string(3) "198"
+string(3) "199"
+Done
diff --git a/tests/bug27303_4_11gR1.phpt b/tests/bug27303_4_11gR1.phpt
new file mode 100644
index 0000000000..0c88360be2
--- /dev/null
+++ b/tests/bug27303_4_11gR1.phpt
@@ -0,0 +1,258 @@
+--TEST--
+Bug #27303 (OCIBindByName binds numeric PHP values as characters)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 11\.1\./', $sv, $matches);
+if ($sv !== 1) {
+ die ("skip expected output only valid when using Oracle 11gR1 database");
+}
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$create_st = array();
+$create_st[] = "drop sequence myseq";
+$create_st[] = "drop table mytab";
+$create_st[] = "create sequence myseq";
+$create_st[] = "create table mytab (mydata varchar2(20), seqcol number)";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+define('MYLIMIT', 200);
+
+$stmt = "insert into mytab (mydata, seqcol) values ('Some data', myseq.nextval) returning seqcol into :mybv";
+
+$stid = OCIParse($c, $stmt);
+if (!$stid) { echo "Parse error"; die; }
+
+$r = OCIBindByName($stid, ':MYBV', $mybv, 0 );
+if (!$r) { echo "Bind error"; die; }
+
+for ($i = 1; $i < MYLIMIT; $i++) {
+ $r = OCIExecute($stid, OCI_DEFAULT);
+ if (!$r) { echo "Execute error"; die; }
+ var_dump($mybv);
+}
+
+OCICommit($c);
+
+$drop_st = array();
+$drop_st[] = "drop sequence myseq";
+$drop_st[] = "drop table mytab";
+
+foreach ($create_st as $statement) {
+ $stmt = oci_parse($c, $statement);
+ oci_execute($stmt);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+string(1) "1"
+string(1) "2"
+string(1) "3"
+string(1) "4"
+string(1) "5"
+string(1) "6"
+string(1) "7"
+string(1) "8"
+string(1) "9"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "2"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "3"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "4"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "5"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "6"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "7"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "8"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "9"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+Done
diff --git a/tests/bug32325.phpt b/tests/bug32325.phpt
new file mode 100644
index 0000000000..257c6977b8
--- /dev/null
+++ b/tests/bug32325.phpt
@@ -0,0 +1,63 @@
+--TEST--
+Bug #32325 (Cannot retrieve collection using OCI8)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialize
+
+$stmtarray = array(
+ "create or replace type bug32325_t as table of number"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run test
+
+$collection = oci_new_collection($c, "BUG32325_T");
+
+$sql = "begin
+ select bug32325_t(1,2,3,4) into :list from dual;
+ end;";
+
+$stmt = oci_parse($c, $sql);
+
+oci_bind_by_name($stmt, ":list", $collection, -1, OCI_B_NTY);
+oci_execute($stmt);
+
+var_dump($collection->size());
+var_dump($collection->getelem(1));
+var_dump($collection->getelem(2));
+
+// Cleanup
+
+$stmtarray = array(
+ "drop type bug32325_t"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+int(4)
+float(2)
+float(3)
+Done
diff --git a/tests/bug35973.phpt b/tests/bug35973.phpt
new file mode 100644
index 0000000000..81e1e58ba2
--- /dev/null
+++ b/tests/bug35973.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Bug #35973 (Error ORA-24806 occurs when trying to fetch a NCLOB field)
+--SKIPIF--
+<?php if (!extension_loaded("oci8")) print "skip"; ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$s1 = oci_parse($c, "drop table test_nclob");
+@oci_execute($s1);
+
+$s2 = oci_parse($c, "create table test_nclob (nc NCLOB)");
+oci_execute($s2);
+
+$s3 = oci_parse($c, "insert into test_nclob (nc) values ('12345data')");
+oci_execute($s3);
+
+$s3 = oci_parse($c, "select * from test_nclob");
+oci_execute($s3);
+
+var_dump($data = oci_fetch_assoc($s3));
+$d = $data['NC'];
+
+var_dump($d->read(5));
+var_dump($d->read(4));
+
+$s1 = oci_parse($c, "drop table test_nclob");
+@oci_execute($s1);
+
+echo "Done\n";
+?>
+--EXPECTF--
+array(1) {
+ ["NC"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(%d) "%s5"
+string(%d) "%sa"
+Done
diff --git a/tests/bug36010.phpt b/tests/bug36010.phpt
new file mode 100644
index 0000000000..d451f3f2f4
--- /dev/null
+++ b/tests/bug36010.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #36010 (Crash when executing SQL statment with lob parameter twice)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+function f($conn)
+{
+ $sql = "begin :p_clob := 'lob string'; end;";
+ $stid = oci_parse($conn, $sql);
+ $clob = oci_new_descriptor($conn, OCI_D_LOB);
+ oci_bind_by_name($stid, ":p_clob", $clob, -1, OCI_B_CLOB);
+ $r = oci_execute($stid, OCI_DEFAULT);
+}
+
+f($c);
+f($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Done
diff --git a/tests/bug36096.phpt b/tests/bug36096.phpt
new file mode 100644
index 0000000000..44b3a6ddca
--- /dev/null
+++ b/tests/bug36096.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #36096 (oci_result() returns garbage after oci_fetch() failed)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$sql = "SELECT 'ABC' FROM DUAL WHERE 1<>1";
+$stmt = oci_parse($c, $sql);
+
+if(oci_execute($stmt, OCI_COMMIT_ON_SUCCESS)){
+ var_dump(oci_fetch($stmt));
+ var_dump(oci_result($stmt, 1));
+ var_dump(oci_field_name($stmt, 1));
+ var_dump(oci_field_type($stmt, 1));
+}
+
+echo "Done\n";
+
+?>
+--EXPECT--
+bool(false)
+bool(false)
+string(5) "'ABC'"
+string(4) "CHAR"
+Done
diff --git a/tests/bug36403.phpt b/tests/bug36403.phpt
new file mode 100644
index 0000000000..68c5f7b0a1
--- /dev/null
+++ b/tests/bug36403.phpt
@@ -0,0 +1,76 @@
+--TEST--
+Bug #36403 (oci_execute no longer supports OCI_DESCRIBE_ONLY)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table bug36403_tab",
+ "create table bug36403_tab (c1 number, col2 number, column3 number, col4 number)"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+$s = oci_parse($c, "select * from bug36403_tab");
+oci_execute($s, OCI_DESCRIBE_ONLY);
+for ($i = oci_num_fields($s); $i > 0; $i--) {
+ echo oci_field_name($s, $i) . "\n";
+}
+
+echo "Test 2\n";
+
+// Should generate an error: ORA-24338: statement handle not executed
+// since the statement handle was only described and not executed
+$row = oci_fetch_array($s);
+
+// Clean up
+
+//require(dirname(__FILE__).'/drop_table.inc');
+
+$stmtarray = array(
+ "drop table bug36403_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+COL4
+COLUMN3
+COL2
+C1
+Test 2
+
+Warning: oci_fetch_array(): ORA-24338: %sbug36403.php on line %d
+===DONE===
diff --git a/tests/bug37220.phpt b/tests/bug37220.phpt
new file mode 100644
index 0000000000..6743165b70
--- /dev/null
+++ b/tests/bug37220.phpt
@@ -0,0 +1,68 @@
+--TEST--
+Bug #37220 (LOB Type mismatch when using windows & oci8.dll)
+--SKIPIF--
+<?php if (!extension_loaded("oci8")) print "skip"; ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Initialization
+
+$stmtarray = array(
+ "create table bug37220_tab( mycolumn xmltype not null)",
+ "insert into bug37220_tab values(xmltype('<THETAG myID=\"1234\"></THETAG>'))"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Now let's update the row where myId = 1234 and change the tag
+// 'THETAG' to 'MYTAG' (mycolumn is an XMLTYPE datatype and
+// bug37220_tab a normal Oracle table)
+
+$query = "UPDATE bug37220_tab
+ SET bug37220_tab.mycolumn = updateXML(bug37220_tab.mycolumn,'/THETAG',xmltype.createXML(:data))
+ WHERE existsNode(bug37220_tab.mycolumn,'/THETAG[@myID=\"1234\"]') = 1";
+$stmt = oci_parse ($c, $query);
+$clob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($stmt, ':data', $clob, -1, OCI_B_CLOB);
+$clob->writetemporary("<MYTAG/>", OCI_TEMP_CLOB);
+$success = oci_execute($stmt, OCI_COMMIT_ON_SUCCESS);
+oci_free_statement($stmt);
+$clob->close();
+
+// Query back the change
+
+$query = "select * from bug37220_tab";
+$stmt = oci_parse ($c, $query);
+
+oci_execute($stmt);
+
+while ($row = oci_fetch_array($stmt, OCI_ASSOC+OCI_RETURN_NULLS)) {
+ foreach ($row as $item) {
+ echo $item."\n";
+ }
+ echo "\n";
+}
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table bug37220_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECT--
+<MYTAG/>
+
+Done
diff --git a/tests/bug37581.phpt b/tests/bug37581.phpt
new file mode 100644
index 0000000000..ec86c51959
--- /dev/null
+++ b/tests/bug37581.phpt
@@ -0,0 +1,69 @@
+--TEST--
+Bug #37581 (oci_bind_array_by_name clobbers input array when using SQLT_AFC, AVC)
+--SKIPIF--
+<?php if (!extension_loaded("oci8")) print "skip"; ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$p1 = "create or replace package ARRAYBINDPKG1 as
+type str_array is table of char(2) index by binary_integer;
+procedure array_bind(in_str in str_array, out_str out string);
+end ARRAYBINDPKG1;";
+
+$p2 = "create or replace package body ARRAYBINDPKG1 as
+ procedure array_bind(in_str in str_array, out_str out string) is
+ begin
+ for i in 1 .. in_str.count loop
+ out_str := in_str(i);
+ end loop;
+ end array_bind;
+end ARRAYBINDPKG1;";
+
+$s1 = oci_parse($c, $p1);
+$s2 = oci_parse($c, $p2);
+oci_execute($s1);
+oci_execute($s2);
+
+
+$stmt = oci_parse($c,'begin ARRAYBINDPKG1.array_bind(:in_arr, :out_str); end;');
+$strings = array('A','B','C','D','E');
+
+oci_bind_array_by_name($stmt,':in_arr',$strings,5,1,SQLT_AFC);
+oci_bind_by_name($stmt,':out_str',$result,10);
+
+oci_execute($stmt);
+var_dump($strings);
+
+oci_execute($stmt);
+var_dump($strings);
+
+echo "Done\n";
+?>
+--EXPECTF--
+array(5) {
+ [0]=>
+ string(1) "A"
+ [1]=>
+ string(1) "B"
+ [2]=>
+ string(1) "C"
+ [3]=>
+ string(1) "D"
+ [4]=>
+ string(1) "E"
+}
+array(5) {
+ [0]=>
+ string(1) "A"
+ [1]=>
+ string(1) "B"
+ [2]=>
+ string(1) "C"
+ [3]=>
+ string(1) "D"
+ [4]=>
+ string(1) "E"
+}
+Done
diff --git a/tests/bug38161.phpt b/tests/bug38161.phpt
new file mode 100644
index 0000000000..e0fbba816a
--- /dev/null
+++ b/tests/bug38161.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #38161 (oci_bind_by_name() returns garbage when Oracle didn't set the variable)
+--SKIPIF--
+<?php if (!extension_loaded("oci8")) print "skip"; ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$query = "begin if false then :bv := 1; end if; end;";
+$stid = oci_parse($c, $query);
+oci_bind_by_name($stid, ":bv", $bv, 22);
+oci_execute($stid, OCI_DEFAULT);
+
+var_dump($bv);
+unset($bv);
+
+$query = "begin if false then :bv := 1; end if; end;";
+$stid = oci_parse($c, $query);
+oci_bind_by_name($stid, ":bv", $bv, 22, SQLT_INT);
+oci_execute($stid, OCI_DEFAULT);
+
+var_dump($bv);
+
+echo "Done\n";
+?>
+--EXPECTF--
+NULL
+int(0)
+Done
diff --git a/tests/bug38173.phpt b/tests/bug38173.phpt
new file mode 100644
index 0000000000..b92df9e39e
--- /dev/null
+++ b/tests/bug38173.phpt
@@ -0,0 +1,79 @@
+--TEST--
+Bug #38173 (Freeing nested cursors causes OCI8 to segfault)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$create_1 = "CREATE TABLE t1 (id INTEGER)";
+$create_2 = "CREATE TABLE t2 (id INTEGER)";
+$drop_1 = "DROP TABLE t1";
+$drop_2 = "DROP TABLE t2";
+
+$s1 = oci_parse($c, $drop_1);
+$s2 = oci_parse($c, $drop_2);
+@oci_execute($s1);
+@oci_execute($s2);
+
+$s1 = oci_parse($c, $create_1);
+$s2 = oci_parse($c, $create_2);
+oci_execute($s1);
+oci_execute($s2);
+
+for($i=0; $i < 5; $i++) {
+ $insert = "INSERT INTO t1 VALUES(".$i.")";
+ $s = oci_parse($c, $insert);
+ oci_execute($s);
+}
+
+for($i=0; $i < 5; $i++) {
+ $insert = "INSERT INTO t2 VALUES(".$i.")";
+ $s = oci_parse($c, $insert);
+ oci_execute($s);
+}
+
+$query ="
+SELECT
+ t1.*,
+ CURSOR( SELECT * FROM t2 ) as cursor
+FROM
+ t1
+";
+
+$sth = oci_parse($c, $query);
+oci_execute($sth);
+
+// dies on oci_free_statement on 2nd pass through loop
+while ( $row = oci_fetch_assoc($sth) ) {
+ print "Got row!\n";
+ var_dump(oci_execute($row['CURSOR']));
+ var_dump(oci_free_statement($row['CURSOR']));
+}
+
+$s1 = oci_parse($c, $drop_1);
+$s2 = oci_parse($c, $drop_2);
+@oci_execute($s1);
+@oci_execute($s2);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Got row!
+bool(true)
+bool(true)
+Got row!
+bool(true)
+bool(true)
+Got row!
+bool(true)
+bool(true)
+Got row!
+bool(true)
+bool(true)
+Got row!
+bool(true)
+bool(true)
+Done
diff --git a/tests/bug40078.phpt b/tests/bug40078.phpt
new file mode 100644
index 0000000000..4a234e176d
--- /dev/null
+++ b/tests/bug40078.phpt
@@ -0,0 +1,55 @@
+--TEST--
+Bug #40078 (ORA-01405 when fetching NULL values using oci_bind_array_by_name())
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
+ PROCEDURE nullbind(c1 OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ PROCEDURE nullbind(c1 OUT ARRTYPE) IS
+ BEGIN
+ c1(1) := 'one';
+ c1(2) := 'two';
+ c1(3) := '';
+ c1(4) := 'four';
+ c1(5) := 'five';
+ END nullbind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.nullbind(:c1); END;");
+
+oci_bind_array_by_name($statement, ":c1", $array, 5, 20, SQLT_CHR);
+
+oci_execute($statement);
+
+var_dump($array);
+
+echo "Done\n";
+?>
+--EXPECTF--
+array(5) {
+ [0]=>
+ string(3) "one"
+ [1]=>
+ string(3) "two"
+ [2]=>
+ string(0) ""
+ [3]=>
+ string(4) "four"
+ [4]=>
+ string(4) "five"
+}
+Done
diff --git a/tests/bug40415.phpt b/tests/bug40415.phpt
new file mode 100644
index 0000000000..1ebc249d38
--- /dev/null
+++ b/tests/bug40415.phpt
@@ -0,0 +1,200 @@
+--TEST--
+Bug #40415 (Using oci_fetchall with nested cursors)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+// Setup
+
+$create_1 = "CREATE TABLE t1 (id1 INTEGER)";
+$create_2 = "CREATE TABLE t2 (id2 INTEGER)";
+$drop_1 = "DROP TABLE t1";
+$drop_2 = "DROP TABLE t2";
+
+$s1 = oci_parse($c, $drop_1);
+$s2 = oci_parse($c, $drop_2);
+@oci_execute($s1);
+@oci_execute($s2);
+
+$s1 = oci_parse($c, $create_1);
+$s2 = oci_parse($c, $create_2);
+oci_execute($s1);
+oci_execute($s2);
+
+for($i=1; $i < 4; $i++) {
+ $insert = "INSERT INTO t1 VALUES(1".$i.")";
+ $s = oci_parse($c, $insert);
+ oci_execute($s);
+}
+
+for($i=1; $i < 4; $i++) {
+ $insert = "INSERT INTO t2 VALUES(2".$i.")";
+ $s = oci_parse($c, $insert);
+ oci_execute($s);
+}
+
+
+function do_assoc($c)
+{
+ $query = "SELECT t1.*, CURSOR( SELECT * FROM t2 ) AS CURSOR FROM t1";
+
+ $stmt = oci_parse($c, $query);
+ oci_execute($stmt);
+
+ while ($row = oci_fetch_assoc($stmt)) {
+ print "Got row \"".$row['ID1']."\". Now getting nested cursor:\n";
+ var_dump(oci_execute($row['CURSOR']));
+ while ($row_n = oci_fetch_assoc($row['CURSOR']) ) {
+ var_dump($row_n);
+ }
+ }
+}
+
+function do_all($c)
+{
+ $query = "SELECT t1.*, CURSOR( SELECT * FROM t2 ) AS CURSOR FROM t1";
+
+ $stmt = oci_parse($c, $query);
+ oci_execute($stmt);
+
+ $rc1 = oci_fetch_all($stmt, $res);
+
+ echo "Rows returned $rc1\n";
+
+ var_dump($res);
+
+ foreach ($res['CURSOR'] as $cv) {
+ echo "Getting nested cursor\n";
+ var_dump(oci_execute($cv));
+ $rc2 = oci_fetch_all($cv, $res2);
+ var_dump($res2);
+ }
+}
+
+
+
+echo "Test 1: Associate fetch of nested cursor\n";
+do_assoc($c);
+
+echo "\nTest 2: fetchall of nested cursor\n";
+do_all($c);
+
+
+// Cleanup
+$s1 = oci_parse($c, $drop_1);
+$s2 = oci_parse($c, $drop_2);
+@oci_execute($s1);
+@oci_execute($s2);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Test 1: Associate fetch of nested cursor
+Got row "11". Now getting nested cursor:
+bool(true)
+array(1) {
+ ["ID2"]=>
+ string(2) "21"
+}
+array(1) {
+ ["ID2"]=>
+ string(2) "22"
+}
+array(1) {
+ ["ID2"]=>
+ string(2) "23"
+}
+Got row "12". Now getting nested cursor:
+bool(true)
+array(1) {
+ ["ID2"]=>
+ string(2) "21"
+}
+array(1) {
+ ["ID2"]=>
+ string(2) "22"
+}
+array(1) {
+ ["ID2"]=>
+ string(2) "23"
+}
+Got row "13". Now getting nested cursor:
+bool(true)
+array(1) {
+ ["ID2"]=>
+ string(2) "21"
+}
+array(1) {
+ ["ID2"]=>
+ string(2) "22"
+}
+array(1) {
+ ["ID2"]=>
+ string(2) "23"
+}
+
+Test 2: fetchall of nested cursor
+Rows returned 3
+array(2) {
+ ["ID1"]=>
+ array(3) {
+ [0]=>
+ string(2) "11"
+ [1]=>
+ string(2) "12"
+ [2]=>
+ string(2) "13"
+ }
+ ["CURSOR"]=>
+ array(3) {
+ [0]=>
+ resource(%d) of type (oci8 statement)
+ [1]=>
+ resource(%d) of type (oci8 statement)
+ [2]=>
+ resource(%d) of type (oci8 statement)
+ }
+}
+Getting nested cursor
+bool(true)
+array(1) {
+ ["ID2"]=>
+ array(3) {
+ [0]=>
+ string(2) "21"
+ [1]=>
+ string(2) "22"
+ [2]=>
+ string(2) "23"
+ }
+}
+Getting nested cursor
+bool(true)
+array(1) {
+ ["ID2"]=>
+ array(3) {
+ [0]=>
+ string(2) "21"
+ [1]=>
+ string(2) "22"
+ [2]=>
+ string(2) "23"
+ }
+}
+Getting nested cursor
+bool(true)
+array(1) {
+ ["ID2"]=>
+ array(3) {
+ [0]=>
+ string(2) "21"
+ [1]=>
+ string(2) "22"
+ [2]=>
+ string(2) "23"
+ }
+}
+Done
diff --git a/tests/bug41069.phpt b/tests/bug41069.phpt
new file mode 100644
index 0000000000..b3a1b9969c
--- /dev/null
+++ b/tests/bug41069.phpt
@@ -0,0 +1,275 @@
+--TEST--
+Bug #41069 (Oracle crash with certain data over a DB-link when prefetch memory limit used - Oracle bug 6039623)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__).'/details.inc');
+if (empty($dbase)) die ("skip requires network connection alias for DB link loopback");
+if ($test_drcp) die("skip DRCP does not support shared database links");
+?>
+--INI--
+oci8.default_prefetch=5
+--FILE--
+ <?php
+
+ require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "alter session set nls_date_format = 'MM/DD/YYYY'",
+
+ "drop database link bug41069_dblink",
+
+ "drop table bug41069_tab",
+
+ "create shared database link bug41069_dblink authenticated by $user identified by $password using '$dbase'",
+
+ "create table bug41069_tab
+ (
+ c1 number(20),
+ c2 varchar2(60 byte),
+ c3 varchar2(1000 byte),
+ c4 varchar2(255 byte),
+ c5 varchar2(2 byte),
+ c6 varchar2(1 byte),
+ c7 varchar2(255 byte),
+ c8 varchar2(50 byte),
+ c9 date,
+ c10 date,
+ c12 number(20),
+ c13 varchar2(20 byte),
+ c15 varchar2(50 byte)
+ )",
+
+ "insert into bug41069_tab (c1, c2, c5, c6, c9, c10, c12, c15) values
+ (111, 'aaaaaaa', 'b', 'c', '01/17/2008', '01/07/2017', 2222, 'zzzzzzzzzz')",
+
+ "insert into bug41069_tab (c1, c2, c3, c4, c5, c6, c7, c9, c10, c12, c13, c15) values
+ (112, 'aaaaaaa', 'bbbbbbbb', 'ccccccc', 'd', 'e', 'rrrrrrr', '04/16/2007', '04/16/2007', 2223, 'xxxxxxxx', 'zzzzzzzz')",
+
+ "insert into bug41069_tab (c1, c2, c3, c4, c5, c6, c7, c9, c10, c12, c15) values
+ (113, 'aaaaaaa', 'bbbbbbbbbb', 'cccccc', 'e', 'f', 'dddd', '12/04/2006', '12/04/2006', 2224, 'zzzzzzz')"
+ );
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+
+// Run Tests
+
+echo "Test 1: non-DB link case that always worked\n";
+$stid = oci_parse($c, 'select * from bug41069_tab order by c1');
+oci_execute($stid, OCI_DEFAULT);
+oci_fetch_all($stid, $results, 0, -1, OCI_ASSOC+OCI_FETCHSTATEMENT_BY_ROW);
+var_dump($results);
+
+echo "Test 2: Should not crash\n";
+$stid = oci_parse($c, 'select * from bug41069_tab@bug41069_dblink order by c1');
+oci_execute($stid, OCI_DEFAULT);
+oci_fetch_all($stid, $results, 0, -1, OCI_ASSOC+OCI_FETCHSTATEMENT_BY_ROW);
+var_dump($results);
+
+// Cleanup
+
+$c = oci_new_connect($user, $password, $dbase);
+
+$stmtarray = array(
+ "drop database link bug41069_dblink",
+ "drop table bug41069_tab"
+ );
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Test 1: non-DB link case that always worked
+array(3) {
+ [0]=>
+ array(13) {
+ ["C1"]=>
+ string(3) "111"
+ ["C2"]=>
+ string(7) "aaaaaaa"
+ ["C3"]=>
+ NULL
+ ["C4"]=>
+ NULL
+ ["C5"]=>
+ string(1) "b"
+ ["C6"]=>
+ string(1) "c"
+ ["C7"]=>
+ NULL
+ ["C8"]=>
+ NULL
+ ["C9"]=>
+ string(10) "01/17/2008"
+ ["C10"]=>
+ string(10) "01/07/2017"
+ ["C12"]=>
+ string(4) "2222"
+ ["C13"]=>
+ NULL
+ ["C15"]=>
+ string(10) "zzzzzzzzzz"
+ }
+ [1]=>
+ array(13) {
+ ["C1"]=>
+ string(3) "112"
+ ["C2"]=>
+ string(7) "aaaaaaa"
+ ["C3"]=>
+ string(8) "bbbbbbbb"
+ ["C4"]=>
+ string(7) "ccccccc"
+ ["C5"]=>
+ string(1) "d"
+ ["C6"]=>
+ string(1) "e"
+ ["C7"]=>
+ string(7) "rrrrrrr"
+ ["C8"]=>
+ NULL
+ ["C9"]=>
+ string(10) "04/16/2007"
+ ["C10"]=>
+ string(10) "04/16/2007"
+ ["C12"]=>
+ string(4) "2223"
+ ["C13"]=>
+ string(8) "xxxxxxxx"
+ ["C15"]=>
+ string(8) "zzzzzzzz"
+ }
+ [2]=>
+ array(13) {
+ ["C1"]=>
+ string(3) "113"
+ ["C2"]=>
+ string(7) "aaaaaaa"
+ ["C3"]=>
+ string(10) "bbbbbbbbbb"
+ ["C4"]=>
+ string(6) "cccccc"
+ ["C5"]=>
+ string(1) "e"
+ ["C6"]=>
+ string(1) "f"
+ ["C7"]=>
+ string(4) "dddd"
+ ["C8"]=>
+ NULL
+ ["C9"]=>
+ string(10) "12/04/2006"
+ ["C10"]=>
+ string(10) "12/04/2006"
+ ["C12"]=>
+ string(4) "2224"
+ ["C13"]=>
+ NULL
+ ["C15"]=>
+ string(7) "zzzzzzz"
+ }
+}
+Test 2: Should not crash
+array(3) {
+ [0]=>
+ array(13) {
+ ["C1"]=>
+ string(3) "111"
+ ["C2"]=>
+ string(7) "aaaaaaa"
+ ["C3"]=>
+ NULL
+ ["C4"]=>
+ NULL
+ ["C5"]=>
+ string(1) "b"
+ ["C6"]=>
+ string(1) "c"
+ ["C7"]=>
+ NULL
+ ["C8"]=>
+ NULL
+ ["C9"]=>
+ string(10) "01/17/2008"
+ ["C10"]=>
+ string(10) "01/07/2017"
+ ["C12"]=>
+ string(4) "2222"
+ ["C13"]=>
+ NULL
+ ["C15"]=>
+ string(10) "zzzzzzzzzz"
+ }
+ [1]=>
+ array(13) {
+ ["C1"]=>
+ string(3) "112"
+ ["C2"]=>
+ string(7) "aaaaaaa"
+ ["C3"]=>
+ string(8) "bbbbbbbb"
+ ["C4"]=>
+ string(7) "ccccccc"
+ ["C5"]=>
+ string(1) "d"
+ ["C6"]=>
+ string(1) "e"
+ ["C7"]=>
+ string(7) "rrrrrrr"
+ ["C8"]=>
+ NULL
+ ["C9"]=>
+ string(10) "04/16/2007"
+ ["C10"]=>
+ string(10) "04/16/2007"
+ ["C12"]=>
+ string(4) "2223"
+ ["C13"]=>
+ string(8) "xxxxxxxx"
+ ["C15"]=>
+ string(8) "zzzzzzzz"
+ }
+ [2]=>
+ array(13) {
+ ["C1"]=>
+ string(3) "113"
+ ["C2"]=>
+ string(7) "aaaaaaa"
+ ["C3"]=>
+ string(10) "bbbbbbbbbb"
+ ["C4"]=>
+ string(6) "cccccc"
+ ["C5"]=>
+ string(1) "e"
+ ["C6"]=>
+ string(1) "f"
+ ["C7"]=>
+ string(4) "dddd"
+ ["C8"]=>
+ NULL
+ ["C9"]=>
+ string(10) "12/04/2006"
+ ["C10"]=>
+ string(10) "12/04/2006"
+ ["C12"]=>
+ string(4) "2224"
+ ["C13"]=>
+ NULL
+ ["C15"]=>
+ string(7) "zzzzzzz"
+ }
+}
+Done
diff --git a/tests/bug42134.phpt b/tests/bug42134.phpt
new file mode 100644
index 0000000000..2b0e3707d6
--- /dev/null
+++ b/tests/bug42134.phpt
@@ -0,0 +1,100 @@
+--TEST--
+Bug #42134 (Collection error for invalid collection name)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Test collection creation error for normal connection
+
+if (!empty($dbase)) {
+ $c = oci_connect($user,$password,$dbase);
+}
+else {
+ $c = oci_connect($user,$password);
+}
+
+$collection = oci_new_collection($c, "ABC");
+if (!$collection) {
+ echo "Normal connection: New Collection error\n";
+ $m = oci_error($c);
+ var_dump($m);
+}
+
+// Test collection creation error for new connection
+
+if (!empty($dbase)) {
+ $c = oci_new_connect($user,$password,$dbase);
+}
+else {
+ $c = oci_new_connect($user,$password);
+}
+
+$collection = oci_new_collection($c, "DEF");
+if (!$collection) {
+ echo "New connection: New Collection error\n";
+ $m = oci_error($c);
+ var_dump($m);
+}
+
+// Test collection creation error for persistent connection
+
+if (!empty($dbase)) {
+ $c = oci_pconnect($user,$password,$dbase);
+}
+else {
+ $c = oci_pconnect($user,$password);
+}
+
+$collection = oci_new_collection($c, "GHI");
+if (!$collection) {
+ echo "Persistent connection: New Collection error\n";
+ $m = oci_error($c);
+ var_dump($m);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: oci_new_collection(): OCI-22303: type ""."ABC" not found in %s on line %d
+Normal connection: New Collection error
+array(4) {
+ ["code"]=>
+ int(22303)
+ ["message"]=>
+ string(34) "OCI-22303: type ""."ABC" not found"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+
+Warning: oci_new_collection(): OCI-22303: type ""."DEF" not found in %s on line %d
+New connection: New Collection error
+array(4) {
+ ["code"]=>
+ int(22303)
+ ["message"]=>
+ string(34) "OCI-22303: type ""."DEF" not found"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+
+Warning: oci_new_collection(): OCI-22303: type ""."GHI" not found in %s on line %d
+Persistent connection: New Collection error
+array(4) {
+ ["code"]=>
+ int(22303)
+ ["message"]=>
+ string(34) "OCI-22303: type ""."GHI" not found"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+Done
diff --git a/tests/bug42173.phpt b/tests/bug42173.phpt
new file mode 100644
index 0000000000..501ed75cd0
--- /dev/null
+++ b/tests/bug42173.phpt
@@ -0,0 +1,168 @@
+--TEST--
+Bug #42173 (TIMESTAMP and INTERVAL query and field functions)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+$stmts = array(
+
+"drop table ts_test",
+
+"create table ts_test (
+c1 TIMESTAMP,
+c2 TIMESTAMP (5),
+c3 TIMESTAMP WITH TIME ZONE,
+c4 TIMESTAMP (2) WITH TIME ZONE,
+c5 TIMESTAMP WITH LOCAL TIME ZONE,
+c6 INTERVAL YEAR TO MONTH,
+c7 INTERVAL YEAR(2) TO MONTH,
+c8 INTERVAL DAY TO SECOND,
+c9 INTERVAL DAY(2) TO SECOND(3)
+)",
+
+"insert into ts_test values (
+timestamp'1999-01-03 10:00:00.123',
+timestamp'1999-01-04 10:00:00.123456',
+timestamp'1999-01-05 10:00:00.123456+1:0',
+timestamp'1999-01-06 10:00:00.123456-1:0',
+timestamp'1999-01-06 10:00:00.123456-1:0',
+interval'1-2' year to month,
+interval'10-4' year to month,
+interval'1 2:20:20.123' day to second,
+interval'1 2:20:20.12345' day to second)");
+
+foreach ($stmts as $sql) {
+ $s = oci_parse($c, $sql);
+ $r = @oci_execute($s);
+}
+
+$s = oci_parse($c, "select * from ts_test");
+$r = oci_execute($s);
+$row = oci_fetch_array($s, OCI_ASSOC);
+var_dump($row);
+
+foreach ($row as $name => $field) {
+ echo "\nColumn $name\n";
+ var_dump(oci_field_is_null($s, $name));
+ var_dump(oci_field_name($s, $name));
+ var_dump(oci_field_type($s, $name));
+ var_dump(oci_field_type_raw($s, $name));
+ var_dump(oci_field_scale($s, $name));
+ var_dump(oci_field_precision($s, $name));
+ var_dump(oci_field_size($s, $name));
+}
+
+// Cleanup
+
+$s = oci_parse($c, "drop table ts_test");
+$r = @oci_execute($s);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+array(9) {
+ ["C1"]=>
+ string(28) "03-JAN-99 10.00.00.123000 AM"
+ ["C2"]=>
+ string(27) "04-JAN-99 10.00.00.12346 AM"
+ ["C3"]=>
+ string(35) "05-JAN-99 10.00.00.123456 AM +01:00"
+ ["C4"]=>
+ string(31) "06-JAN-99 10.00.00.12 AM -01:00"
+ ["C5"]=>
+ string(28) "%s"
+ ["C6"]=>
+ string(6) "+01-02"
+ ["C7"]=>
+ string(6) "+10-04"
+ ["C8"]=>
+ string(19) "+01 02:20:20.123000"
+ ["C9"]=>
+ string(16) "+01 02:20:20.123"
+}
+
+Column C1
+bool(false)
+string(2) "C1"
+string(9) "TIMESTAMP"
+int(187)
+int(6)
+int(0)
+int(11)
+
+Column C2
+bool(false)
+string(2) "C2"
+string(9) "TIMESTAMP"
+int(187)
+int(5)
+int(0)
+int(11)
+
+Column C3
+bool(false)
+string(2) "C3"
+string(23) "TIMESTAMP WITH TIMEZONE"
+int(188)
+int(6)
+int(0)
+int(13)
+
+Column C4
+bool(false)
+string(2) "C4"
+string(23) "TIMESTAMP WITH TIMEZONE"
+int(188)
+int(2)
+int(0)
+int(13)
+
+Column C5
+bool(false)
+string(2) "C5"
+string(29) "TIMESTAMP WITH LOCAL TIMEZONE"
+int(232)
+int(6)
+int(0)
+int(11)
+
+Column C6
+bool(false)
+string(2) "C6"
+string(22) "INTERVAL YEAR TO MONTH"
+int(189)
+int(0)
+int(2)
+int(5)
+
+Column C7
+bool(false)
+string(2) "C7"
+string(22) "INTERVAL YEAR TO MONTH"
+int(189)
+int(0)
+int(2)
+int(5)
+
+Column C8
+bool(false)
+string(2) "C8"
+string(22) "INTERVAL DAY TO SECOND"
+int(190)
+int(6)
+int(2)
+int(11)
+
+Column C9
+bool(false)
+string(2) "C9"
+string(22) "INTERVAL DAY TO SECOND"
+int(190)
+int(3)
+int(2)
+int(11)
+Done
diff --git a/tests/bug42496_1.phpt b/tests/bug42496_1.phpt
new file mode 100644
index 0000000000..4d7e2c5852
--- /dev/null
+++ b/tests/bug42496_1.phpt
@@ -0,0 +1,61 @@
+--TEST--
+Bug #42496 (LOB fetch leaks cursors, eventually failing with ORA-1000 maximum open cursors reached)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Initialization
+
+$stmtarray = array(
+ "DROP table bug42496_tab",
+ "CREATE table bug42496_tab(c1 CLOB, c2 CLOB)",
+ "INSERT INTO bug42496_tab VALUES('test1', 'test1')",
+ "INSERT INTO bug42496_tab VALUES('test2', 'test2')",
+ "INSERT INTO bug42496_tab VALUES('test3', 'test3')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+for ($i = 0; $i < 15000; $i++) {
+ $s = oci_parse($c, "SELECT * from bug42496_tab");
+ oci_define_by_name($s, "C1", $col1);
+ oci_define_by_name($s, "C2", $col2);
+ if (oci_execute($s)) {
+ $arr = array();
+ while ($arr = oci_fetch_assoc($s)) {
+ $arr['C1']->free();
+ $arr['C2']->free();
+ }
+ }
+ oci_free_statement($s);
+}
+
+echo "Done\n";
+
+// Cleanup
+
+$stmtarray = array(
+ "DROP table bug42496_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+--EXPECTF--
+Test 1
+Done
diff --git a/tests/bug42496_2.phpt b/tests/bug42496_2.phpt
new file mode 100644
index 0000000000..e2800bbd8a
--- /dev/null
+++ b/tests/bug42496_2.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Bug #42496 (LOB fetch leaks cursors, eventually failing with ORA-1000 maximum open cursors reached)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Initialization
+
+$stmtarray = array(
+ "DROP table bug42496_tab",
+ "CREATE table bug42496_tab(c1 CLOB, c2 CLOB)",
+ "INSERT INTO bug42496_tab VALUES('test1', 'test1')",
+ "INSERT INTO bug42496_tab VALUES('test2', 'test2')",
+ "INSERT INTO bug42496_tab VALUES('test3', 'test3')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+echo "Test 2\n";
+
+for ($i = 0; $i < 15000; $i++) {
+ $s = oci_parse($c, "SELECT * from bug42496_tab");
+ if (oci_execute($s)) {
+ $arr = array();
+ while ($arr = oci_fetch_assoc($s)) {
+ $arr['C1']->free();
+ $arr['C2']->free();
+ }
+ }
+ oci_free_statement($s);
+}
+
+echo "Done\n";
+
+// Cleanup
+
+$stmtarray = array(
+ "DROP table bug42496_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+--EXPECTF--
+Test 2
+Done
diff --git a/tests/bug42841.phpt b/tests/bug42841.phpt
new file mode 100644
index 0000000000..921c8149dd
--- /dev/null
+++ b/tests/bug42841.phpt
@@ -0,0 +1,187 @@
+--TEST--
+Bug #42841 (REF CURSOR and oci_new_cursor PHP crash)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.statement_cache_size=20
+--FILE--
+<?php
+
+require dirname(__FILE__).'/details.inc';
+
+// note a oci_new_connect() occurs lower in the script
+$c = oci_connect($user, $password, $dbase);
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace procedure bug42841_proc(out_1 out sys_refcursor) is
+ begin
+ open out_1 for select 11 from dual union all select 12 from dual union all select 13 from dual;
+ end bug42841_proc;",
+
+ "create or replace package bug43449_pkg is
+ type cursortype is ref Cursor;
+ function testcursor return cursortype;
+ end bug43449_pkg;",
+
+ "create or replace package body bug43449_pkg is
+ function testcursor return cursortype is
+ retCursor cursorType;
+ begin
+ Open retCursor For 'select * from dual';
+ return retCursor;
+ end;
+ end bug43449_pkg;"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Main code
+
+function do_bug42841($c)
+{
+ echo "First attempt\n";
+
+ $sql = "BEGIN bug42841_proc(:cursor); END;";
+ $stmt = oci_parse($c, $sql);
+ $cursor = oci_new_cursor($c);
+ oci_bind_by_name($stmt, ":cursor", $cursor, -1, OCI_B_CURSOR);
+
+ oci_execute($stmt, OCI_DEFAULT);
+ oci_execute($cursor);
+
+ while($row = oci_fetch_array($cursor, OCI_ASSOC + OCI_RETURN_LOBS)) {
+ $data1[] = $row;
+ }
+
+ oci_free_statement($stmt);
+ oci_free_statement($cursor);
+ var_dump($data1);
+
+ echo "Second attempt\n";
+
+ $sql = "BEGIN bug42841_proc(:cursor); END;";
+ $stmt = oci_parse($c, $sql);
+ $cursor = oci_new_cursor($c);
+ oci_bind_by_name($stmt, ":cursor", $cursor, -1, OCI_B_CURSOR);
+
+ oci_execute($stmt, OCI_DEFAULT);
+ oci_execute($cursor);
+
+ while($row = oci_fetch_array($cursor, OCI_ASSOC + OCI_RETURN_LOBS)) {
+ $data2[] = $row;
+ }
+
+ oci_free_statement($stmt);
+ oci_free_statement($cursor);
+ var_dump($data2);
+}
+
+function do_bug43449($c)
+{
+
+ for ($i = 0; $i < 2; $i++) {
+ var_dump(bug43449_getCur($c));
+ }
+}
+
+function bug43449_getCur($c)
+{
+ $cur = oci_new_cursor($c);
+ $stmt = oci_parse($c, 'begin :cur := bug43449_pkg.testcursor; end;');
+ oci_bind_by_name($stmt, ':cur', $cur, -1, OCI_B_CURSOR);
+ oci_execute($stmt, OCI_DEFAULT);
+ oci_execute($cur, OCI_DEFAULT);
+
+ $ret = array();
+
+ while (ocifetchinto($cur, $row, OCI_ASSOC)) {
+ $ret[] = $row;
+ }
+
+ oci_free_statement($cur);
+ oci_free_statement($stmt);
+ return $ret;
+}
+
+echo "Test bug 42841: Procedure with OUT cursor parameter\n";
+do_bug42841($c);
+
+$c = oci_new_connect($user, $password, $dbase);
+
+echo "Test bug 43449: Cursor as function result\n";
+do_bug43449($c);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop procedure bug42841_proc",
+ "drop package bug43449_pkg"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Test bug 42841: Procedure with OUT cursor parameter
+First attempt
+array(3) {
+ [0]=>
+ array(1) {
+ [11]=>
+ string(2) "11"
+ }
+ [1]=>
+ array(1) {
+ [11]=>
+ string(2) "12"
+ }
+ [2]=>
+ array(1) {
+ [11]=>
+ string(2) "13"
+ }
+}
+Second attempt
+array(3) {
+ [0]=>
+ array(1) {
+ [11]=>
+ string(2) "11"
+ }
+ [1]=>
+ array(1) {
+ [11]=>
+ string(2) "12"
+ }
+ [2]=>
+ array(1) {
+ [11]=>
+ string(2) "13"
+ }
+}
+Test bug 43449: Cursor as function result
+array(1) {
+ [0]=>
+ array(1) {
+ ["DUMMY"]=>
+ string(1) "X"
+ }
+}
+array(1) {
+ [0]=>
+ array(1) {
+ ["DUMMY"]=>
+ string(1) "X"
+ }
+}
+Done
diff --git a/tests/bug43492.phpt b/tests/bug43492.phpt
new file mode 100644
index 0000000000..d28aabfced
--- /dev/null
+++ b/tests/bug43492.phpt
@@ -0,0 +1,378 @@
+--TEST--
+Bug #43492 (Nested cursor leaks)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$stmtarray = array(
+ "DROP table bug43492_tab",
+ "CREATE TABLE bug43492_tab(col1 VARCHAR2(1))",
+ "INSERT INTO bug43492_tab VALUES ('A')",
+ "INSERT INTO bug43492_tab VALUES ('B')",
+ "INSERT INTO bug43492_tab VALUES ('C')",
+ "INSERT INTO bug43492_tab VALUES ('D')",
+ "INSERT INTO bug43492_tab VALUES ('E')",
+ "INSERT INTO bug43492_tab VALUES ('F')",
+ "INSERT INTO bug43492_tab VALUES ('G')",
+ "INSERT INTO bug43492_tab VALUES ('H')",
+ "INSERT INTO bug43492_tab VALUES ('I')",
+ "INSERT INTO bug43492_tab VALUES ('J')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+/*
+
+While fetching data from a ref cursor, the parent statement needs to
+be around. Also when the parent statement goes out of scope, it is
+not automatically released which causes a cursor leak.
+
+If either or both of the lines marked (*) are removed, then the script
+will fail with the error "ORA-01000: maximum open cursors exceeded".
+
+*/
+
+function fetch($c, $i) {
+ global $s; // (*) Allow parent statement to be available when child is used
+ $s = ociparse($c, 'select cursor(select * from bug43492_tab) c from bug43492_tab');
+ ociexecute($s, OCI_DEFAULT);
+ ocifetchinto($s, $result, OCI_ASSOC);
+ ociexecute($result['C'], OCI_DEFAULT);
+ return $result['C'];
+}
+
+for($i = 0; $i < 300; $i++) {
+ $cur = fetch($c, $i);
+ for($j = 0; $j < 10; $j++) {
+ ocifetchinto($cur, $row, OCI_NUM);
+ echo "$row[0] ";
+ }
+ echo "\n";
+ ocifreestatement($cur);
+ ocifreestatement($s); // (*) Free the parent statement cleanly
+}
+
+echo "Done\n";
+
+// Cleanup
+
+$stmtarray = array(
+ "DROP table bug43492_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+--EXPECT--
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+Done
diff --git a/tests/bug43492_2.phpt b/tests/bug43492_2.phpt
new file mode 100644
index 0000000000..fcf96e984e
--- /dev/null
+++ b/tests/bug43492_2.phpt
@@ -0,0 +1,369 @@
+--TEST--
+Bug #43492 (Nested cursor leaks after related bug #44206 fixed)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+// This test is similar to bug43492.phpt without the explict free.
+// Now that bug 44206 is fixed an automatic clean up will occur -
+// though it is still recommended in practice.
+
+require dirname(__FILE__).'/connect.inc';
+
+$stmtarray = array(
+ "DROP table bug43492_tab",
+ "CREATE TABLE bug43492_tab(col1 VARCHAR2(1))",
+ "INSERT INTO bug43492_tab VALUES ('A')",
+ "INSERT INTO bug43492_tab VALUES ('B')",
+ "INSERT INTO bug43492_tab VALUES ('C')",
+ "INSERT INTO bug43492_tab VALUES ('D')",
+ "INSERT INTO bug43492_tab VALUES ('E')",
+ "INSERT INTO bug43492_tab VALUES ('F')",
+ "INSERT INTO bug43492_tab VALUES ('G')",
+ "INSERT INTO bug43492_tab VALUES ('H')",
+ "INSERT INTO bug43492_tab VALUES ('I')",
+ "INSERT INTO bug43492_tab VALUES ('J')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+function fetch($c, $i) {
+ $s = ociparse($c, 'select cursor(select * from bug43492_tab) c from bug43492_tab');
+ ociexecute($s, OCI_DEFAULT);
+ ocifetchinto($s, $result, OCI_ASSOC);
+ ociexecute($result['C'], OCI_DEFAULT);
+ return $result['C'];
+}
+
+for($i = 0; $i < 300; $i++) {
+ $cur = fetch($c, $i);
+ for($j = 0; $j < 10; $j++) {
+ ocifetchinto($cur, $row, OCI_NUM);
+ echo "$row[0] ";
+ }
+ echo "\n";
+ ocifreestatement($cur);
+}
+
+echo "Done\n";
+
+// Cleanup
+
+$stmtarray = array(
+ "DROP table bug43492_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+--EXPECT--
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+A B C D E F G H I J
+Done
diff --git a/tests/bug43497.phpt b/tests/bug43497.phpt
new file mode 100644
index 0000000000..1ea46b40d7
--- /dev/null
+++ b/tests/bug43497.phpt
@@ -0,0 +1,303 @@
+--TEST--
+Bug #43497 (OCI8 XML/getClobVal aka temporary LOBs leak UGA memory)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Oracle Version => 9/', $phpinfo);
+if ($ov === 1) {
+ die ("skip expected output only valid for Oracle clients from 10g onwards");
+}
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+function sessionid($c) // determines and returns current session ID
+{
+ $query = "select sid from v\$session where audsid = userenv('sessionid')";
+
+ $stmt = oci_parse($c, $query);
+
+ if (oci_execute($stmt, OCI_DEFAULT)) {
+ $row = oci_fetch($stmt);
+ return oci_result($stmt, 1);
+ }
+
+ return null;
+}
+
+
+function templobs($c, $sid) // returns number of temporary LOBs
+{
+ $query = "select abstract_lobs from v\$temporary_lobs where sid = " . $sid;
+
+ $stmt = oci_parse($c, $query);
+
+ if (oci_execute($stmt, OCI_DEFAULT)) {
+ $row = oci_fetch($stmt);
+ $val = oci_result($stmt, 1);
+ oci_free_statement($stmt);
+ return $val;
+ }
+ return null;
+}
+
+
+// Read all XML data using explicit LOB locator
+function readxmltab_ex($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM)) {
+ $result[0]->free(); // cleanup properly
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+// Read all XML data using explicit LOB locator but without freeing the temp lobs
+function readxmltab_ex_nofree($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM)) {
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+// Read all XML data using implicit LOB locator
+function readxmltab_im($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM+OCI_RETURN_LOBS)) {
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+function createxmltab($c) // create table w/ field of XML type
+{
+ @dropxmltab($c);
+ $stmt = oci_parse($c, "create table bug43497_tab (id number primary key, xml xmltype)");
+ oci_execute($stmt);
+}
+
+function dropxmltab($c) // delete table
+{
+ $stmt = oci_parse($c, "drop table bug43497_tab");
+ oci_execute($stmt);
+}
+
+
+function fillxmltab($c)
+{
+ for ($id = 1; $id <= 100; $id++) {
+
+ // create an XML element string with random data
+ $s = "<data>";
+ for ($j = 0; $j < 128; $j++) {
+ $s .= rand();
+ }
+ $s .= "</data>\n";
+ for ($j = 0; $j < 4; $j++) {
+ $s .= $s;
+ }
+ $data = "<?xml version=\"1.0\"?><records>" . $s . "</records>";
+
+ // insert XML data into database
+
+ $stmt = oci_parse($c, "insert into bug43497_tab(id, xml) values (:id, sys.xmltype.createxml(:xml))");
+ oci_bind_by_name($stmt, ":id", $id);
+ $clob = oci_new_descriptor($c, OCI_D_LOB);
+ oci_bind_by_name($stmt, ":xml", $clob, -1, OCI_B_CLOB);
+ $clob->writetemporary($data);
+ oci_execute($stmt);
+
+ $clob->close();
+ $clob->free();
+ }
+}
+
+
+// Initialize
+
+createxmltab($c);
+fillxmltab($c);
+
+// Run Test
+
+$sid = sessionid($c);
+
+echo "Explicit LOB use\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_ex($c);
+}
+
+echo "\nImplicit LOB use\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_im($c);
+}
+
+echo "\nExplicit LOB with no free\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_ex_nofree($c);
+}
+
+
+
+// Cleanup
+
+dropxmltab($c);
+
+oci_close($c);
+
+echo "Done\n";
+?>
+--EXPECT--
+Explicit LOB use
+
+Run = 1
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 0
+Loop count check = 100
+
+Implicit LOB use
+
+Run = 1
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 0
+Loop count check = 100
+
+Explicit LOB with no free
+
+Run = 1
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 0
+Loop count check = 100
+Done
diff --git a/tests/bug43497_92.phpt b/tests/bug43497_92.phpt
new file mode 100644
index 0000000000..e2cb1ce486
--- /dev/null
+++ b/tests/bug43497_92.phpt
@@ -0,0 +1,303 @@
+--TEST--
+Bug #43497 (OCI8 XML/getClobVal aka temporary LOBs leak UGA memory)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Oracle Version => 9.2/', $phpinfo);
+if ($ov !== 1) {
+ die ("skip expected output only valid for Oracle 9.2 clients");
+}
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+function sessionid($c) // determines and returns current session ID
+{
+ $query = "select sid from v\$session where audsid = userenv('sessionid')";
+
+ $stmt = oci_parse($c, $query);
+
+ if (oci_execute($stmt, OCI_DEFAULT)) {
+ $row = oci_fetch($stmt);
+ return oci_result($stmt, 1);
+ }
+
+ return null;
+}
+
+
+function templobs($c, $sid) // returns number of temporary LOBs
+{
+ $query = "select abstract_lobs from v\$temporary_lobs where sid = " . $sid;
+
+ $stmt = oci_parse($c, $query);
+
+ if (oci_execute($stmt, OCI_DEFAULT)) {
+ $row = oci_fetch($stmt);
+ $val = oci_result($stmt, 1);
+ oci_free_statement($stmt);
+ return $val;
+ }
+ return null;
+}
+
+
+// Read all XML data using explicit LOB locator
+function readxmltab_ex($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM)) {
+ $result[0]->free(); // cleanup properly
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+// Read all XML data using explicit LOB locator but without freeing the temp lobs
+function readxmltab_ex_nofree($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM)) {
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+// Read all XML data using implicit LOB locator
+function readxmltab_im($c)
+{
+ $stmt = oci_parse($c, "select extract(xml, '/').getclobval() from bug43497_tab");
+
+ $cntchk = 0;
+ if (oci_execute($stmt)) {
+ while ($result = oci_fetch_array($stmt, OCI_NUM+OCI_RETURN_LOBS)) {
+ ++$cntchk;
+ }
+ }
+ echo "Loop count check = $cntchk\n";
+}
+
+function createxmltab($c) // create table w/ field of XML type
+{
+ @dropxmltab($c);
+ $stmt = oci_parse($c, "create table bug43497_tab (id number primary key, xml xmltype)");
+ oci_execute($stmt);
+}
+
+function dropxmltab($c) // delete table
+{
+ $stmt = oci_parse($c, "drop table bug43497_tab");
+ oci_execute($stmt);
+}
+
+
+function fillxmltab($c)
+{
+ for ($id = 1; $id <= 100; $id++) {
+
+ // create an XML element string with random data
+ $s = "<data>";
+ for ($j = 0; $j < 128; $j++) {
+ $s .= rand();
+ }
+ $s .= "</data>\n";
+ for ($j = 0; $j < 4; $j++) {
+ $s .= $s;
+ }
+ $data = "<?xml version=\"1.0\"?><records>" . $s . "</records>";
+
+ // insert XML data into database
+
+ $stmt = oci_parse($c, "insert into bug43497_tab(id, xml) values (:id, sys.xmltype.createxml(:xml))");
+ oci_bind_by_name($stmt, ":id", $id);
+ $clob = oci_new_descriptor($c, OCI_D_LOB);
+ oci_bind_by_name($stmt, ":xml", $clob, -1, OCI_B_CLOB);
+ $clob->writetemporary($data);
+ oci_execute($stmt);
+
+ $clob->close();
+ $clob->free();
+ }
+}
+
+
+// Initialize
+
+createxmltab($c);
+fillxmltab($c);
+
+// Run Test
+
+$sid = sessionid($c);
+
+echo "Explicit LOB use\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_ex($c);
+}
+
+echo "\nImplicit LOB use\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_im($c);
+}
+
+echo "\nExplicit LOB with no free (i.e. a temp lob leak)\n";
+for ($i = 1; $i <= 10; $i++) {
+ echo "\nRun = " . $i . "\n";
+ echo "Temporary LOBs = " . templobs($c, $sid) . "\n";
+ readxmltab_ex_nofree($c);
+}
+
+
+
+// Cleanup
+
+dropxmltab($c);
+
+oci_close($c);
+
+echo "Done\n";
+?>
+--EXPECT--
+Explicit LOB use
+
+Run = 1
+Temporary LOBs = 0
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 100
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 200
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 300
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 400
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 500
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 600
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 700
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 800
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 900
+Loop count check = 100
+
+Implicit LOB use
+
+Run = 1
+Temporary LOBs = 1000
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 1100
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 1200
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 1300
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 1400
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 1500
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 1600
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 1700
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 1800
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 1900
+Loop count check = 100
+
+Explicit LOB with no free (i.e. a temp lob leak)
+
+Run = 1
+Temporary LOBs = 2000
+Loop count check = 100
+
+Run = 2
+Temporary LOBs = 2100
+Loop count check = 100
+
+Run = 3
+Temporary LOBs = 2200
+Loop count check = 100
+
+Run = 4
+Temporary LOBs = 2300
+Loop count check = 100
+
+Run = 5
+Temporary LOBs = 2400
+Loop count check = 100
+
+Run = 6
+Temporary LOBs = 2500
+Loop count check = 100
+
+Run = 7
+Temporary LOBs = 2600
+Loop count check = 100
+
+Run = 8
+Temporary LOBs = 2700
+Loop count check = 100
+
+Run = 9
+Temporary LOBs = 2800
+Loop count check = 100
+
+Run = 10
+Temporary LOBs = 2900
+Loop count check = 100
+Done \ No newline at end of file
diff --git a/tests/bug44008.phpt b/tests/bug44008.phpt
new file mode 100644
index 0000000000..fd10b26b8b
--- /dev/null
+++ b/tests/bug44008.phpt
@@ -0,0 +1,54 @@
+--TEST--
+Bug #44008 (Incorrect usage of OCI-Lob->close doesn't crash PHP)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace procedure bug44008_proc (p in out clob)
+ as begin p := 'A';
+ end;"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+$s = oci_parse($c, 'begin bug44008_proc(:data); end;');
+$textLob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ":data", $textLob, -1, OCI_B_CLOB);
+oci_execute($s, OCI_DEFAULT);
+$r = $textLob->load();
+echo "$r\n";
+
+// Incorrectly closing the lob doesn't cause a crash.
+// OCI-LOB->close() is documented for use only with OCI-Lob->writeTemporary()
+$textLob->close();
+
+// Cleanup
+
+$stmtarray = array(
+ "drop procedure bug44008_proc"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+A
+Done
diff --git a/tests/bug44113.phpt b/tests/bug44113.phpt
new file mode 100644
index 0000000000..eee21c3aef
--- /dev/null
+++ b/tests/bug44113.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Bug #44113 (New collection creation can fail with OCI-22303)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__).'/details.inc');
+if ($stress_test !== true) die ('skip Slow test not run when $stress_test is FALSE');
+?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace type bug44113_list_t as table of number"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+// The test can take some time to complete and can exceed PHP's test
+// timout limit on slow networks.
+
+for ($x = 0; $x < 70000; $x++) {
+ if (!($var = oci_new_collection($c, 'BUG44113_LIST_T'))) {
+ print "Failed new collection creation on $x\n";
+ break;
+ }
+}
+
+print "Completed $x\n";
+
+// Cleanup
+
+$stmtarray = array(
+ "drop type bug44113_list_t"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Completed 70000
+Done
diff --git a/tests/bug44206.phpt b/tests/bug44206.phpt
new file mode 100644
index 0000000000..e5771e4182
--- /dev/null
+++ b/tests/bug44206.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Bug #44206 (Test if selecting ref cursors leads to ORA-1000 maximum open cursors reached)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Run Test
+
+for ($x = 0; $x < 400; $x++)
+{
+ $stmt = "select cursor (select $x from dual) a,
+ cursor (select $x from dual) b
+ from dual";
+ $s = oci_parse($c, $stmt);
+ $r = oci_execute($s);
+ if (!$r) {
+ echo "Exiting $x\n";
+ exit;
+ }
+ $mode = OCI_ASSOC | OCI_RETURN_NULLS;
+ $result = oci_fetch_array($s, $mode);
+ oci_execute($result['A']);
+ oci_execute($result['B']);
+ oci_fetch_array($result['A'], $mode);
+ oci_fetch_array($result['B'], $mode);
+ oci_free_statement($result['A']);
+ oci_free_statement($result['B']);
+ oci_free_statement($s);
+}
+
+echo "Completed $x\n";
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Completed 400
+Done
diff --git a/tests/bug45458.phpt b/tests/bug45458.phpt
new file mode 100644
index 0000000000..b1dc7720ce
--- /dev/null
+++ b/tests/bug45458.phpt
@@ -0,0 +1,84 @@
+--TEST--
+Bug #45458 (OCI8: Numeric keys for associative arrays are not handled properly)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Run Test
+
+echo "Test 1\n";
+
+$stmt = 'select dummy "a", dummy "20" from dual';
+
+$s = oci_parse($c, $stmt);
+oci_execute($s);
+$r = oci_fetch_all($s, $data, 0, -1, OCI_FETCHSTATEMENT_BY_ROW);
+var_dump($data);
+var_dump($data[0]);
+var_dump($data[0]["a"]);
+var_dump($data[0]["20"]);
+oci_free_statement($s);
+
+echo "Test 2\n";
+
+$s = oci_parse($c, $stmt);
+oci_execute($s);
+$r = oci_fetch_all($s, $data, 0, -1, OCI_ASSOC);
+var_dump($data);
+var_dump($data["a"]);
+var_dump($data["20"]);
+var_dump($data["a"][0]);
+var_dump($data["20"][0]);
+oci_free_statement($s);
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+Test 1
+array(1) {
+ [0]=>
+ array(2) {
+ ["a"]=>
+ string(1) "X"
+ [20]=>
+ string(1) "X"
+ }
+}
+array(2) {
+ ["a"]=>
+ string(1) "X"
+ [20]=>
+ string(1) "X"
+}
+string(1) "X"
+string(1) "X"
+Test 2
+array(2) {
+ ["a"]=>
+ array(1) {
+ [0]=>
+ string(1) "X"
+ }
+ [20]=>
+ array(1) {
+ [0]=>
+ string(1) "X"
+ }
+}
+array(1) {
+ [0]=>
+ string(1) "X"
+}
+array(1) {
+ [0]=>
+ string(1) "X"
+}
+string(1) "X"
+string(1) "X"
+===DONE===
diff --git a/tests/bug46994.phpt b/tests/bug46994.phpt
new file mode 100644
index 0000000000..0504952f69
--- /dev/null
+++ b/tests/bug46994.phpt
@@ -0,0 +1,86 @@
+--TEST--
+Bug #46994 (CLOB size does not update when using CLOB IN OUT param in stored procedure)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace procedure bug46994_proc1(p1 in out nocopy clob) is
+ begin
+ dbms_lob.trim(p1, 0);
+ dbms_lob.writeappend(p1, 26, 'This should be the output.');
+ end bug46994_proc1;",
+ "create or replace procedure bug46994_proc2(p1 in out nocopy clob) is
+ begin
+ dbms_lob.trim(p1, 0);
+ dbms_lob.writeappend(p1, 37, 'The output should be even longer now.');
+ end bug46994_proc2;"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Run Test
+
+$myclob = oci_new_descriptor($c, OCI_D_LOB);
+$myclob->writeTemporary("some data", OCI_TEMP_CLOB);
+
+echo "Test 1\n";
+
+$s = oci_parse($c, "begin bug46994_proc1(:myclob); end;");
+oci_bind_by_name($s, ":myclob", $myclob, -1, SQLT_CLOB);
+oci_execute($s, OCI_DEFAULT);
+var_dump($myclob->load());
+
+echo "Test 2\n";
+
+$s = oci_parse($c, "begin bug46994_proc2(:myclob); end;");
+oci_bind_by_name($s, ":myclob", $myclob, -1, SQLT_CLOB);
+oci_execute($s, OCI_DEFAULT);
+var_dump($myclob->load());
+
+echo "Test 3\n";
+
+$s = oci_parse($c, "begin bug46994_proc1(:myclob); end;");
+oci_bind_by_name($s, ":myclob", $myclob, -1, SQLT_CLOB);
+oci_execute($s, OCI_DEFAULT);
+var_dump($myclob->load());
+
+echo "Test 4\n";
+
+var_dump($myclob->load()); // Use cached size code path
+
+// Cleanup
+
+$stmtarray = array(
+ "drop procedure bug46994_proc1",
+ "drop procedure bug46994_proc2"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+string(26) "This should be the output."
+Test 2
+string(37) "The output should be even longer now."
+Test 3
+string(26) "This should be the output."
+Test 4
+string(26) "This should be the output."
+===DONE===
diff --git a/tests/bug47189.phpt b/tests/bug47189.phpt
new file mode 100644
index 0000000000..073b410fcd
--- /dev/null
+++ b/tests/bug47189.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Bug #47189 (Multiple oci_fetch_all calls)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+$s = oci_parse($c, "select * from dual");
+oci_execute($s);
+oci_fetch_all($s, $rs, 0, -1, OCI_FETCHSTATEMENT_BY_ROW);
+var_dump($rs);
+oci_fetch_all($s, $rs1, 0, -1, OCI_FETCHSTATEMENT_BY_ROW);
+var_dump($rs1);
+
+$s = oci_parse($c, "select * from dual");
+oci_execute($s);
+oci_fetch_all($s, $rs, 0, 1, OCI_FETCHSTATEMENT_BY_ROW);
+var_dump($rs);
+oci_fetch_all($s, $rs1, 0, 1, OCI_FETCHSTATEMENT_BY_ROW);
+var_dump($rs1);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ array(1) {
+ ["DUMMY"]=>
+ string(1) "X"
+ }
+}
+array(0) {
+}
+array(1) {
+ [0]=>
+ array(1) {
+ ["DUMMY"]=>
+ string(1) "X"
+ }
+}
+
+Warning: oci_fetch_all(): ORA-01002: %s in %s on line %d
+array(0) {
+}
+===DONE===
diff --git a/tests/bug47281.phpt b/tests/bug47281.phpt
new file mode 100644
index 0000000000..710246738e
--- /dev/null
+++ b/tests/bug47281.phpt
@@ -0,0 +1,73 @@
+--TEST--
+Bug #47281 ($php_errormsg is limited in size of characters)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--ENV--
+NLS_LANG=.AL32UTF8
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "create or replace procedure bug47281_sp as
+ begin
+ raise_application_error(-20000,
+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccDeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeFggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhIjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjKlllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllM');
+ end;"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+$s = oci_parse($c, 'begin bug47281_sp; end;');
+$r = @oci_execute($s);
+
+if (!$r) {
+ $m = oci_error($s);
+ echo $m['message'], "\n";
+}
+
+echo "Test 2\n";
+
+echo $php_errormsg. "\n";
+
+// Clean up
+
+$stmtarray = array(
+ "drop procedure bug47281_sp"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+ORA-20000: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccDeeeeeeeeeeee
+Test 2
+oci_execute(): ORA-20000: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+===DONE===
diff --git a/tests/bug51253.phpt b/tests/bug51253.phpt
new file mode 100644
index 0000000000..fea3333ccf
--- /dev/null
+++ b/tests/bug51253.phpt
@@ -0,0 +1,165 @@
+--TEST--
+Bug #51253 (oci_bind_array_by_name() array references)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+$drop = "DROP table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table bind_test(name VARCHAR(20))";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$create_pkg = "
+CREATE OR REPLACE PACKAGE ARRAYBINDPKG1 AS
+ TYPE ARRTYPE IS TABLE OF VARCHAR(20) INDEX BY BINARY_INTEGER;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE);
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg);
+oci_execute($statement);
+
+$create_pkg_body = "
+CREATE OR REPLACE PACKAGE BODY ARRAYBINDPKG1 AS
+ CURSOR CUR IS SELECT name FROM bind_test;
+ PROCEDURE iobind(c1 IN OUT ARRTYPE) IS
+ BEGIN
+ FOR i IN 1..5 LOOP
+ INSERT INTO bind_test VALUES (c1(i));
+ END LOOP;
+ IF NOT CUR%ISOPEN THEN
+ OPEN CUR;
+ END IF;
+ FOR i IN REVERSE 1..5 LOOP
+ FETCH CUR INTO c1(i);
+ IF CUR%NOTFOUND THEN
+ CLOSE CUR;
+ EXIT;
+ END IF;
+ END LOOP;
+ END iobind;
+END ARRAYBINDPKG1;";
+$statement = oci_parse($c, $create_pkg_body);
+oci_execute($statement);
+
+echo "Test 1\n";
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+$array1 = array("one", "two", "three", "four", "five");
+$array2 = $array1;
+oci_bind_array_by_name($statement, ":c1", $array2, 5, -1, SQLT_CHR);
+oci_execute($statement);
+
+var_dump($array1);
+var_dump($array2);
+
+
+echo "Test 2\n";
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+$array1 = array("one", "two", "three", "four", "five");
+$array2 = &$array1;
+oci_bind_array_by_name($statement, ":c1", $array2, 5, -1, SQLT_CHR);
+oci_execute($statement);
+
+var_dump($array1);
+var_dump($array2);
+
+
+echo "Test 3\n";
+$statement = oci_parse($c, "BEGIN ARRAYBINDPKG1.iobind(:c1); END;");
+$array1 = array("one", "two", "three", "four", "five");
+$array2 = &$array1;
+oci_bind_array_by_name($statement, ":c1", $array1, 5, -1, SQLT_CHR);
+oci_execute($statement);
+
+var_dump($array1);
+var_dump($array2);
+
+// Cleanup
+$statement = oci_parse($c, "DROP PACKAGE ARRAYBINDPKG1");
+@oci_execute($statement);
+$statement = oci_parse($c, "DROP TABLE BIND_TEST");
+@oci_execute($statement);
+
+echo "Done\n";
+?>
+--EXPECT--
+Test 1
+array(5) {
+ [0]=>
+ string(4) "five"
+ [1]=>
+ string(4) "four"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(3) "two"
+ [4]=>
+ string(3) "one"
+}
+array(5) {
+ [0]=>
+ string(4) "five"
+ [1]=>
+ string(4) "four"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(3) "two"
+ [4]=>
+ string(3) "one"
+}
+Test 2
+array(5) {
+ [0]=>
+ string(3) "one"
+ [1]=>
+ string(3) "two"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(4) "four"
+ [4]=>
+ string(4) "five"
+}
+array(5) {
+ [0]=>
+ string(3) "one"
+ [1]=>
+ string(3) "two"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(4) "four"
+ [4]=>
+ string(4) "five"
+}
+Test 3
+array(5) {
+ [0]=>
+ string(4) "five"
+ [1]=>
+ string(4) "four"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(3) "two"
+ [4]=>
+ string(3) "one"
+}
+array(5) {
+ [0]=>
+ string(4) "five"
+ [1]=>
+ string(4) "four"
+ [2]=>
+ string(5) "three"
+ [3]=>
+ string(3) "two"
+ [4]=>
+ string(3) "one"
+}
+Done
diff --git a/tests/bug51291.phpt b/tests/bug51291.phpt
new file mode 100644
index 0000000000..75851d63b1
--- /dev/null
+++ b/tests/bug51291.phpt
@@ -0,0 +1,434 @@
+--TEST--
+Bug #51291 (oci_error() doesn't report last error when called two times)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+echo "Test 1 - Parse\n";
+
+$s = @oci_parse($c, "select ' from dual");
+if (!$s) {
+ var_dump(oci_error($c));
+ echo "2nd call\n";
+ var_dump(oci_error($c));
+}
+
+echo "\nTest 2 - Parse\n";
+
+$s = @oci_parse($c, "select ' from dual");
+if (!$s) {
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+ echo "2nd call\n";
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+}
+
+echo "\nTest 3 - Execute\n";
+
+$s = @oci_parse($c, 'select doesnotexist from dual');
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ var_dump(oci_error($s));
+ echo "2nd call\n";
+ var_dump(oci_error($s));
+}
+
+echo "\nTest 4 - Execute - consecutive oci_error calls of different kinds\n";
+
+$s = @oci_parse($c, 'select doesnotexist from dual');
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+ echo "2nd call\n";
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+}
+
+
+echo "\nTest 5 - Execute - after oci_rollback\n";
+
+$s = @oci_parse($c, 'select doesnotexist from dual');
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+ $r = oci_rollback($c);
+ echo "Rollback status is ";
+ if (is_null($r)) echo "null";
+ else if ($r === false) echo "false";
+ else if ($r === true) echo "true";
+ else echo $r;
+ echo "\n";
+ echo "2nd call after oci_rollback\n";
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+}
+
+
+echo "\nTest 6 - Execute - after successful 2nd query with new handle\n";
+
+$s = @oci_parse($c, 'select doesnotexist from dual');
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+ $s2 = oci_parse($c, 'select 1 from dual');
+ $r = oci_execute($s2, OCI_DEFAULT);
+ echo "Execute status is ";
+ if (is_null($r)) echo "null";
+ else if ($r === false) echo "false";
+ else if ($r === true) echo "true";
+ else echo $r;
+ echo "\n";
+ echo "2nd call after successful execute\n";
+ var_dump(oci_error(), oci_error($c), oci_error($s), oci_error($s2));
+}
+
+
+echo "\nTest 7 - Execute - after successful 2nd query with same handle\n";
+
+$s = @oci_parse($c, 'select doesnotexist from dual');
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+ $s = oci_parse($c, 'select 1 from dual');
+ $r = oci_execute($s, OCI_DEFAULT);
+ echo "Execute status is ";
+ if (is_null($r)) echo "null";
+ else if ($r === false) echo "false";
+ else if ($r === true) echo "true";
+ else echo $r;
+ echo "\n";
+ echo "2nd call after successful execute\n";
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+}
+
+
+echo "\nTest 8 - Execute - after unsuccessful 2nd query with new handle\n";
+
+$s = @oci_parse($c, 'select doesnotexist from dual');
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+ $s2 = oci_parse($c, 'select reallynothere from dual');
+ $r = oci_execute($s2, OCI_DEFAULT);
+ echo "Execute status is ";
+ if (is_null($r)) echo "null";
+ else if ($r === false) echo "false";
+ else if ($r === true) echo "true";
+ else echo $r;
+ echo "\n";
+ echo "2nd call after unsuccessful execute\n";
+ var_dump(oci_error(), oci_error($c), oci_error($s), oci_error($s2));
+}
+
+echo "\nTest 9 - Execute - after unsuccessful 2nd query with same handle\n";
+
+$s = @oci_parse($c, 'select doesnotexist from dual');
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+ $s = oci_parse($c, 'select reallynothere from dual');
+ $r = oci_execute($s, OCI_DEFAULT);
+ echo "Execute status is ";
+ if (is_null($r)) echo "null";
+ else if ($r === false) echo "false";
+ else if ($r === true) echo "true";
+ else echo $r;
+ echo "\n";
+ echo "2nd call after unsuccessful execute\n";
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+}
+
+echo "\nTest 10 - Execute - after successful 2nd query with same statement\n";
+
+$s = oci_parse($c, "declare e exception; begin if :bv = 1 then raise e; end if; end;");
+$bv = 1;
+oci_bind_by_name($s, ":bv", $bv);
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+ $bv = 0;
+ $r = oci_execute($s, OCI_DEFAULT);
+ echo "Execute status is ";
+ if (is_null($r)) echo "null";
+ else if ($r === false) echo "false";
+ else if ($r === true) echo "true";
+ else echo $r;
+ echo "\n";
+ echo "2nd call after successful execute\n";
+ var_dump(oci_error(), oci_error($c), oci_error($s));
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1 - Parse
+array(4) {
+ ["code"]=>
+ int(1756)
+ ["message"]=>
+ string(48) "ORA-01756: %s"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+2nd call
+array(4) {
+ ["code"]=>
+ int(1756)
+ ["message"]=>
+ string(48) "ORA-01756: %s"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+
+Test 2 - Parse
+
+Warning: oci_error() expects parameter 1 to be resource, boolean given in %sbug51291.php on line %d
+bool(false)
+array(4) {
+ ["code"]=>
+ int(1756)
+ ["message"]=>
+ string(48) "ORA-01756: %s"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+NULL
+2nd call
+
+Warning: oci_error() expects parameter 1 to be resource, boolean given in %sbug51291.php on line %d
+bool(false)
+array(4) {
+ ["code"]=>
+ int(1756)
+ ["message"]=>
+ string(48) "ORA-01756: %s"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+NULL
+
+Test 3 - Execute
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+2nd call
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+
+Test 4 - Execute - consecutive oci_error calls of different kinds
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+2nd call
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+
+Test 5 - Execute - after oci_rollback
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+Rollback status is true
+2nd call after oci_rollback
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+
+Test 6 - Execute - after successful 2nd query with new handle
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+Execute status is true
+2nd call after successful execute
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+bool(false)
+
+Test 7 - Execute - after successful 2nd query with same handle
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+Execute status is true
+2nd call after successful execute
+bool(false)
+bool(false)
+bool(false)
+
+Test 8 - Execute - after unsuccessful 2nd query with new handle
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+
+Warning: oci_execute(): ORA-00904: "REALLYNOTHERE": %s in %sbug51291.php on line %d
+Execute status is false
+2nd call after unsuccessful execute
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(46) "ORA-00904: "REALLYNOTHERE": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(30) "select reallynothere from dual"
+}
+
+Test 9 - Execute - after unsuccessful 2nd query with same handle
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(45) "ORA-00904: "DOESNOTEXIST": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(29) "select doesnotexist from dual"
+}
+
+Warning: oci_execute(): ORA-00904: "REALLYNOTHERE": %s in %sbug51291.php on line %d
+Execute status is false
+2nd call after unsuccessful execute
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(904)
+ ["message"]=>
+ string(46) "ORA-00904: "REALLYNOTHERE": %s"
+ ["offset"]=>
+ int(7)
+ ["sqltext"]=>
+ string(30) "select reallynothere from dual"
+}
+
+Test 10 - Execute - after successful 2nd query with same statement
+bool(false)
+bool(false)
+array(4) {
+ ["code"]=>
+ int(6510)
+ ["message"]=>
+ string(72) "ORA-06510: PL/SQL: %s
+ORA-06512: %s"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(64) "declare e exception; begin if :bv = 1 then raise e; end if; end;"
+}
+Execute status is true
+2nd call after successful execute
+bool(false)
+bool(false)
+bool(false)
+===DONE===
diff --git a/tests/close.phpt b/tests/close.phpt
new file mode 100644
index 0000000000..55bb4ea364
--- /dev/null
+++ b/tests/close.phpt
@@ -0,0 +1,17 @@
+--TEST--
+connect/close/connect
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+oci_close($c);
+
+oci_connect($user, $password, $dbase);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Done
diff --git a/tests/coll_001.phpt b/tests/coll_001.phpt
new file mode 100644
index 0000000000..57d3cf1b47
--- /dev/null
+++ b/tests/coll_001.phpt
@@ -0,0 +1,27 @@
+--TEST--
+oci_new_collection()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+var_dump(oci_new_collection($c, $type_name));
+var_dump(oci_new_collection($c, "NONEXISTENT"));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+object(OCI-Collection)#%d (1) {
+ ["collection"]=>
+ resource(%d) of type (oci8 collection)
+}
+
+Warning: oci_new_collection(): OCI-22303: type ""."NONEXISTENT" not found in %s on line %d
+bool(false)
+Done
diff --git a/tests/coll_002.phpt b/tests/coll_002.phpt
new file mode 100644
index 0000000000..6d30519897
--- /dev/null
+++ b/tests/coll_002.phpt
@@ -0,0 +1,30 @@
+--TEST--
+oci_new_collection() + free()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+var_dump($coll1 = oci_new_collection($c, $type_name));
+
+var_dump($coll1->free());
+var_dump($coll1->size());
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+object(OCI-Collection)#%d (1) {
+ ["collection"]=>
+ resource(%d) of type (oci8 collection)
+}
+bool(true)
+
+Warning: OCI-Collection::size(): %d is not a valid oci8 collection resource in %s on line %d
+bool(false)
+Done
diff --git a/tests/coll_002_func.phpt b/tests/coll_002_func.phpt
new file mode 100644
index 0000000000..58e641ee24
--- /dev/null
+++ b/tests/coll_002_func.phpt
@@ -0,0 +1,30 @@
+--TEST--
+oci_new_collection() + free()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+var_dump($coll1 = oci_new_collection($c, $type_name));
+
+var_dump(oci_free_collection($coll1));
+var_dump(oci_collection_size($coll1));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+object(OCI-Collection)#%d (1) {
+ ["collection"]=>
+ resource(%d) of type (oci8 collection)
+}
+bool(true)
+
+Warning: oci_collection_size(): %d is not a valid oci8 collection resource in %s on line %d
+bool(false)
+Done
diff --git a/tests/coll_003.phpt b/tests/coll_003.phpt
new file mode 100644
index 0000000000..b5236ef6f6
--- /dev/null
+++ b/tests/coll_003.phpt
@@ -0,0 +1,34 @@
+--TEST--
+collection methods
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+$coll1 = oci_new_collection($c, $type_name);
+
+var_dump($coll1->size());
+var_dump($coll1->max());
+var_dump($coll1->trim(3));
+var_dump($coll1->append(1));
+var_dump($coll1->getElem(0));
+var_dump($coll1->assignElem(0,2));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+int(0)
+int(0)
+
+Warning: OCI-Collection::trim(): OCI-22167: given trim size [3] must be less than or equal to [0] in %s on line %d
+bool(false)
+bool(true)
+float(1)
+bool(true)
+Done
diff --git a/tests/coll_003_func.phpt b/tests/coll_003_func.phpt
new file mode 100644
index 0000000000..f5c6dc7f38
--- /dev/null
+++ b/tests/coll_003_func.phpt
@@ -0,0 +1,34 @@
+--TEST--
+collection methods
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+$coll1 = oci_new_collection($c, $type_name);
+
+var_dump(oci_collection_size($coll1));
+var_dump(oci_collection_max($coll1));
+var_dump(oci_collection_trim($coll1, 3));
+var_dump(oci_collection_append($coll1, 1));
+var_dump(oci_collection_element_get($coll1, 0));
+var_dump(oci_collection_element_assign($coll1, 0, 2));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+int(0)
+int(0)
+
+Warning: oci_collection_trim(): OCI-22167: given trim size [3] must be less than or equal to [0] in %s on line %d
+bool(false)
+bool(true)
+float(1)
+bool(true)
+Done
diff --git a/tests/coll_004.phpt b/tests/coll_004.phpt
new file mode 100644
index 0000000000..eb2ac7e26d
--- /dev/null
+++ b/tests/coll_004.phpt
@@ -0,0 +1,29 @@
+--TEST--
+oci_collection_assign()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+$coll1 = oci_new_collection($c, $type_name);
+$coll2 = oci_new_collection($c, $type_name);
+
+var_dump($coll1->append(1));
+
+var_dump($coll2->assign($coll1));
+
+var_dump($coll2->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+float(1)
+Done
diff --git a/tests/coll_004_func.phpt b/tests/coll_004_func.phpt
new file mode 100644
index 0000000000..57dff2eb35
--- /dev/null
+++ b/tests/coll_004_func.phpt
@@ -0,0 +1,29 @@
+--TEST--
+oci_collection_assign()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+$coll1 = oci_new_collection($c, $type_name);
+$coll2 = oci_new_collection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, 1));
+
+var_dump(oci_collection_assign($coll2, $coll1));
+
+var_dump(oci_collection_element_get($coll2, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+float(1)
+Done
diff --git a/tests/coll_005.phpt b/tests/coll_005.phpt
new file mode 100644
index 0000000000..0f40069964
--- /dev/null
+++ b/tests/coll_005.phpt
@@ -0,0 +1,27 @@
+--TEST--
+ocinewcollection()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+var_dump(ocinewcollection($c, $type_name));
+var_dump(ocinewcollection($c, "NONEXISTENT"));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+object(OCI-Collection)#%d (1) {
+ ["collection"]=>
+ resource(%d) of type (oci8 collection)
+}
+
+Warning: ocinewcollection(): OCI-22303: type ""."NONEXISTENT" not found in %s on line %d
+bool(false)
+Done
diff --git a/tests/coll_006.phpt b/tests/coll_006.phpt
new file mode 100644
index 0000000000..cf258cbe34
--- /dev/null
+++ b/tests/coll_006.phpt
@@ -0,0 +1,30 @@
+--TEST--
+ocinewcollection() + free()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+var_dump($coll1 = ocinewcollection($c, $type_name));
+
+var_dump($coll1->free());
+var_dump($coll1->size());
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+object(OCI-Collection)#%d (1) {
+ ["collection"]=>
+ resource(%d) of type (oci8 collection)
+}
+bool(true)
+
+Warning: OCI-Collection::size(): %d is not a valid oci8 collection resource in %s on line %d
+bool(false)
+Done
diff --git a/tests/coll_006_func.phpt b/tests/coll_006_func.phpt
new file mode 100644
index 0000000000..56707d6087
--- /dev/null
+++ b/tests/coll_006_func.phpt
@@ -0,0 +1,30 @@
+--TEST--
+ocinewcollection() + free()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+var_dump($coll1 = ocinewcollection($c, $type_name));
+
+var_dump(oci_free_collection($coll1));
+var_dump(oci_collection_size($coll1));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+object(OCI-Collection)#%d (1) {
+ ["collection"]=>
+ resource(%d) of type (oci8 collection)
+}
+bool(true)
+
+Warning: oci_collection_size(): %d is not a valid oci8 collection resource in %s on line %d
+bool(false)
+Done
diff --git a/tests/coll_007.phpt b/tests/coll_007.phpt
new file mode 100644
index 0000000000..31e10c065e
--- /dev/null
+++ b/tests/coll_007.phpt
@@ -0,0 +1,34 @@
+--TEST--
+collection methods
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->size());
+var_dump($coll1->max());
+var_dump($coll1->trim(3));
+var_dump($coll1->append(1));
+var_dump($coll1->getElem(0));
+var_dump($coll1->assignElem(0,2));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+int(0)
+int(0)
+
+Warning: OCI-Collection::trim(): OCI-22167: given trim size [3] must be less than or equal to [0] in %s on line %d
+bool(false)
+bool(true)
+float(1)
+bool(true)
+Done
diff --git a/tests/coll_008.phpt b/tests/coll_008.phpt
new file mode 100644
index 0000000000..57d44cc9ab
--- /dev/null
+++ b/tests/coll_008.phpt
@@ -0,0 +1,29 @@
+--TEST--
+ocicollassign()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append(1));
+
+var_dump($coll2->assign($coll1));
+
+var_dump($coll2->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+float(1)
+Done
diff --git a/tests/coll_009.phpt b/tests/coll_009.phpt
new file mode 100644
index 0000000000..296d6493e2
--- /dev/null
+++ b/tests/coll_009.phpt
@@ -0,0 +1,42 @@
+--TEST--
+collections and wrong dates
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF DATE";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append("2005-07-28"));
+
+var_dump($coll2->assign($coll1));
+
+var_dump($coll2->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+Warning: OCI-Collection::append(): OCI-01861: literal does not match format string in %s on line %d
+bool(false)
+bool(true)
+bool(false)
+Done
diff --git a/tests/coll_009_func.phpt b/tests/coll_009_func.phpt
new file mode 100644
index 0000000000..3ed416ce09
--- /dev/null
+++ b/tests/coll_009_func.phpt
@@ -0,0 +1,42 @@
+--TEST--
+collections and wrong dates
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF DATE";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, "2005-07-28"));
+
+var_dump(oci_collection_assign($coll2, $coll1));
+
+var_dump(oci_collection_element_get($coll2, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+Warning: oci_collection_append(): OCI-01861: literal does not match format string in %s on line %d
+bool(false)
+bool(true)
+bool(false)
+Done
diff --git a/tests/coll_010.phpt b/tests/coll_010.phpt
new file mode 100644
index 0000000000..6f72dd16c1
--- /dev/null
+++ b/tests/coll_010.phpt
@@ -0,0 +1,41 @@
+--TEST--
+collections and nulls
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR(10)";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append(null));
+
+var_dump($coll2->assign($coll1));
+
+var_dump($coll2->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+NULL
+Done
diff --git a/tests/coll_010_func.phpt b/tests/coll_010_func.phpt
new file mode 100644
index 0000000000..7b63a276f3
--- /dev/null
+++ b/tests/coll_010_func.phpt
@@ -0,0 +1,41 @@
+--TEST--
+collections and nulls
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR(10)";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, null));
+
+var_dump(oci_collection_assign($coll2, $coll1));
+
+var_dump(oci_collection_element_get($coll2, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+NULL
+Done
diff --git a/tests/coll_011.phpt b/tests/coll_011.phpt
new file mode 100644
index 0000000000..7d805d3f70
--- /dev/null
+++ b/tests/coll_011.phpt
@@ -0,0 +1,43 @@
+--TEST--
+collections and strings
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR(10)";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append("string"));
+var_dump($coll1->append("string"));
+
+var_dump($coll2->assign($coll1));
+
+var_dump($coll2->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+string(6) "string"
+Done
diff --git a/tests/coll_011_func.phpt b/tests/coll_011_func.phpt
new file mode 100644
index 0000000000..dca640e846
--- /dev/null
+++ b/tests/coll_011_func.phpt
@@ -0,0 +1,43 @@
+--TEST--
+collections and strings
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR(10)";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, "string"));
+var_dump(oci_collection_append($coll1, "string"));
+
+var_dump(oci_collection_assign($coll2, $coll1));
+
+var_dump(oci_collection_element_get($coll2, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+string(6) "string"
+Done
diff --git a/tests/coll_012.phpt b/tests/coll_012.phpt
new file mode 100644
index 0000000000..543dafd902
--- /dev/null
+++ b/tests/coll_012.phpt
@@ -0,0 +1,41 @@
+--TEST--
+collections and correct dates
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF DATE";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append("28-JUL-05"));
+
+var_dump($coll2->assign($coll1));
+
+var_dump($coll2->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+string(9) "28-JUL-05"
+Done
diff --git a/tests/coll_012_func.phpt b/tests/coll_012_func.phpt
new file mode 100644
index 0000000000..fd1019e411
--- /dev/null
+++ b/tests/coll_012_func.phpt
@@ -0,0 +1,41 @@
+--TEST--
+collections and correct dates
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF DATE";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+$coll2 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, "28-JUL-05"));
+
+var_dump(oci_collection_assign($coll2, $coll1));
+
+var_dump(oci_collection_element_get($coll2, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+string(9) "28-JUL-05"
+Done
diff --git a/tests/coll_013.phpt b/tests/coll_013.phpt
new file mode 100644
index 0000000000..00d88bb9a4
--- /dev/null
+++ b/tests/coll_013.phpt
@@ -0,0 +1,38 @@
+--TEST--
+collections and correct dates (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF DATE";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append("28-JUL-05"));
+var_dump($coll1->assignElem(0,"01-JAN-05"));
+var_dump($coll1->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+string(9) "01-JAN-05"
+Done
diff --git a/tests/coll_013_func.phpt b/tests/coll_013_func.phpt
new file mode 100644
index 0000000000..0d01bc1744
--- /dev/null
+++ b/tests/coll_013_func.phpt
@@ -0,0 +1,38 @@
+--TEST--
+collections and correct dates (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF DATE";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, "28-JUL-05"));
+var_dump(oci_collection_element_assign($coll1, 0, "01-JAN-05"));
+var_dump(oci_collection_element_get($coll1, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+string(9) "01-JAN-05"
+Done
diff --git a/tests/coll_014.phpt b/tests/coll_014.phpt
new file mode 100644
index 0000000000..8458525ae5
--- /dev/null
+++ b/tests/coll_014.phpt
@@ -0,0 +1,38 @@
+--TEST--
+collections and strings (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR(10)";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append("striing"));
+var_dump($coll1->assignElem(0,"blah"));
+var_dump($coll1->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+string(4) "blah"
+Done
diff --git a/tests/coll_014_func.phpt b/tests/coll_014_func.phpt
new file mode 100644
index 0000000000..a0fe555b61
--- /dev/null
+++ b/tests/coll_014_func.phpt
@@ -0,0 +1,38 @@
+--TEST--
+collections and strings (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR(10)";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, "striing"));
+var_dump(oci_collection_element_assign($coll1, 0,"blah"));
+var_dump(oci_collection_element_get($coll1, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+string(4) "blah"
+Done
diff --git a/tests/coll_015.phpt b/tests/coll_015.phpt
new file mode 100644
index 0000000000..64b0aea106
--- /dev/null
+++ b/tests/coll_015.phpt
@@ -0,0 +1,38 @@
+--TEST--
+collections and numbers (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF NUMBER";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append(1));
+var_dump($coll1->assignElem(0,2345));
+var_dump($coll1->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+float(2345)
+Done
diff --git a/tests/coll_015_func.phpt b/tests/coll_015_func.phpt
new file mode 100644
index 0000000000..eeed7839a7
--- /dev/null
+++ b/tests/coll_015_func.phpt
@@ -0,0 +1,38 @@
+--TEST--
+collections and numbers (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF NUMBER";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, 1));
+var_dump(oci_collection_element_assign($coll1,0,2345));
+var_dump(oci_collection_element_get($coll1, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+float(2345)
+Done
diff --git a/tests/coll_016.phpt b/tests/coll_016.phpt
new file mode 100644
index 0000000000..c2af9cc22d
--- /dev/null
+++ b/tests/coll_016.phpt
@@ -0,0 +1,48 @@
+--TEST--
+collections and negative/too big element indexes
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF NUMBER";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append(1));
+var_dump($coll1->assignElem(-1,2345));
+var_dump($coll1->assignElem(5000,2345));
+var_dump($coll1->getElem(-1));
+var_dump($coll1->getElem(-100));
+var_dump($coll1->getElem(500));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+bool(true)
+
+Warning: OCI-Collection::assignelem(): OCI-22165: given index [%d] must be in the range of %s to [0] in %s on line %d
+bool(false)
+
+Warning: OCI-Collection::assignelem(): OCI-22165: given index [5000] must be in the range of %s to [0] in %s on line %d
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+Done
diff --git a/tests/coll_016_func.phpt b/tests/coll_016_func.phpt
new file mode 100644
index 0000000000..cde26f22f0
--- /dev/null
+++ b/tests/coll_016_func.phpt
@@ -0,0 +1,48 @@
+--TEST--
+collections and negative/too big element indexes
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF NUMBER";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, 1));
+var_dump(oci_collection_element_assign($coll1,-1,2345));
+var_dump(oci_collection_element_assign($coll1,5000,2345));
+var_dump(oci_collection_element_get($coll1, -1));
+var_dump(oci_collection_element_get($coll1, -100));
+var_dump(oci_collection_element_get($coll1, 500));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+bool(true)
+
+Warning: oci_collection_element_assign(): OCI-22165: given index [%d] must be in the range of%s0%sto [0] in %s on line %d
+bool(false)
+
+Warning: oci_collection_element_assign(): OCI-22165: given index [5000] must be in the range of%s0%sto [0] in %s on line %d
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+Done
diff --git a/tests/coll_017.phpt b/tests/coll_017.phpt
new file mode 100644
index 0000000000..42347ba6f8
--- /dev/null
+++ b/tests/coll_017.phpt
@@ -0,0 +1,38 @@
+--TEST--
+collections and nulls (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR(10)";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump($coll1->append("string"));
+var_dump($coll1->assignElem(0, null));
+var_dump($coll1->getElem(0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+NULL
+Done
diff --git a/tests/coll_017_func.phpt b/tests/coll_017_func.phpt
new file mode 100644
index 0000000000..914844ae61
--- /dev/null
+++ b/tests/coll_017_func.phpt
@@ -0,0 +1,38 @@
+--TEST--
+collections and nulls (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+$statement = OCIParse($c,$ora_sql);
+@OCIExecute($statement);
+
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR(10)";
+
+$statement = OCIParse($c,$ora_sql);
+OCIExecute($statement);
+
+
+$coll1 = ocinewcollection($c, $type_name);
+
+var_dump(oci_collection_append($coll1, "string"));
+var_dump(oci_collection_element_assign($coll1, 0, null));
+var_dump(oci_collection_element_get($coll1, 0));
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+NULL
+Done
diff --git a/tests/coll_018.phpt b/tests/coll_018.phpt
new file mode 100644
index 0000000000..f97cc49e7c
--- /dev/null
+++ b/tests/coll_018.phpt
@@ -0,0 +1,93 @@
+--TEST--
+Collection trim tests
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_type.inc";
+
+$coll1 = oci_new_collection($c, $type_name);
+
+echo "Test 1.\n";
+var_dump($coll1->trim());
+
+echo "\nTest 2.\n";
+var_dump($coll1->trim(0));
+
+echo "\nTest 3.\n";
+var_dump($coll1->append(1));
+var_dump($coll1->append(2));
+var_dump($coll1->append(3));
+var_dump($coll1->append(4));
+
+var_dump($coll1->getElem(-1)); // check before the beginning
+var_dump($coll1->getElem(0));
+var_dump($coll1->getElem(1));
+var_dump($coll1->getElem(2));
+var_dump($coll1->getElem(3));
+var_dump($coll1->getElem(4)); // check past the end
+
+echo "\nTest 4.\n";
+var_dump($coll1->trim(1));
+var_dump($coll1->getElem(2)); // this should be the last element
+var_dump($coll1->getElem(3)); // this element should have gone
+
+echo "\nTest 5.\n";
+var_dump($coll1->trim(2));
+var_dump($coll1->getElem(0)); // this should be the last element
+var_dump($coll1->getElem(1)); // this element should have gone
+
+echo "\nTest 6.\n";
+var_dump($coll1->trim(0));
+var_dump($coll1->getElem(0)); // this should still be the last element
+
+echo "\nTest 7.\n";
+var_dump($coll1->trim(1));
+var_dump($coll1->getElem(0)); // this should have gone
+
+echo "Done\n";
+
+require dirname(__FILE__)."/drop_type.inc";
+
+?>
+--EXPECTF--
+Test 1.
+
+Warning: OCI-Collection::trim() expects exactly 1 parameter, 0 given in %s on line 9
+NULL
+
+Test 2.
+bool(true)
+
+Test 3.
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+float(1)
+float(2)
+float(3)
+float(4)
+bool(false)
+
+Test 4.
+bool(true)
+float(3)
+bool(false)
+
+Test 5.
+bool(true)
+float(1)
+bool(false)
+
+Test 6.
+bool(true)
+float(1)
+
+Test 7.
+bool(true)
+bool(false)
+Done
diff --git a/tests/coll_019.phpt b/tests/coll_019.phpt
new file mode 100644
index 0000000000..15a673d718
--- /dev/null
+++ b/tests/coll_019.phpt
@@ -0,0 +1,104 @@
+--TEST--
+Test collection Oracle error handling collections and numbers (2)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$ora_sql = "DROP TYPE ".$type_name;;
+$statement = oci_parse($c,$ora_sql);
+@oci_execute($statement);
+
+
+echo "Test 0\n";
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF BLOB";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+$coll1 = oci_new_collection($c, $type_name);
+
+var_dump($coll1->append('a long string')); // invalid type for append
+var_dump($coll1->assignElem(1, 'a long string')); // invalid type for assignelem()
+var_dump($coll1->getElem(0));
+
+require dirname(__FILE__)."/drop_type.inc";
+
+echo "Test 1\n";
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF NUMBER";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+$coll1 = oci_new_collection($c, $type_name);
+
+var_dump($coll1->assignElem(1, null)); // invalid location for null
+var_dump($coll1->getElem(0));
+
+echo "Test 2\n";
+var_dump($coll1->assignElem(1, 1234)); // invalid location for number
+var_dump($coll1->getElem(0));
+
+require dirname(__FILE__)."/drop_type.inc";
+
+echo "Test 3\n";
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF VARCHAR2(1)";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+$coll1 = oci_new_collection($c, $type_name);
+
+var_dump($coll1->assignElem(1, 'abc')); // invalid location for string
+var_dump($coll1->getElem(0));
+
+require dirname(__FILE__)."/drop_type.inc";
+
+echo "Test 4\n";
+$ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF DATE";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+$coll1 = oci_new_collection($c, $type_name);
+
+var_dump($coll1->append(1)); // invalid date format
+var_dump($coll1->assignElem(1, '01-JAN-06')); // invalid location for date
+var_dump($coll1->getElem(0));
+
+require dirname(__FILE__)."/drop_type.inc";
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 0
+
+Notice: OCI-Collection::append(): Unknown or unsupported type of element: 113 in %s on line %d
+bool(false)
+
+Notice: OCI-Collection::assignelem(): Unknown or unsupported type of element: 113 in %s on line %d
+bool(false)
+bool(false)
+Test 1
+
+Warning: OCI-Collection::assignelem(): OCI-22165: given index [1] must be in the range of %s in %s on line %d
+bool(false)
+bool(false)
+Test 2
+
+Warning: OCI-Collection::assignelem(): OCI-22165: given index [1] must be in the range of %s in %s on line %d
+bool(false)
+bool(false)
+Test 3
+
+Warning: OCI-Collection::assignelem(): OCI-22165: given index [1] must be in the range of %s in %s on line %d
+bool(false)
+bool(false)
+Test 4
+
+Warning: OCI-Collection::append(): OCI-01840: input value not long enough for date format in %s on line %d
+bool(false)
+
+Warning: OCI-Collection::assignelem(): OCI-22165: given index [1] must be in the range of %s in %s on line %d
+bool(false)
+bool(false)
+Done
diff --git a/tests/commit_001.phpt b/tests/commit_001.phpt
new file mode 100644
index 0000000000..836d2cd1df
--- /dev/null
+++ b/tests/commit_001.phpt
@@ -0,0 +1,156 @@
+--TEST--
+Test OCI_NO_AUTO_COMMIT constant
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+require(dirname(__FILE__).'/create_table.inc');
+
+$insert_sql = "insert into ".$schema.$table_name." (id, value) values (1,1)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+/* check with OCI_NO_AUTO_COMMIT mode */
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s, OCI_NO_AUTO_COMMIT)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s, OCI_DEFAULT)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+
+var_dump(oci_rollback($c));
+
+$select_sql = "select * from ".$schema.$table_name."";
+
+if (!($select = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+/* oci_fetch_all */
+if (!oci_execute($select)) {
+ die("oci_execute(select) failed!\n");
+}
+var_dump(oci_fetch_all($select, $all));
+var_dump($all);
+
+/* ocifetchstatement */
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+$insert_sql = "insert into ".$schema.$table_name." (id, value) values (1,1)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s, OCI_DEFAULT)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+var_dump(oci_commit($c));
+
+/* oci_fetch_all */
+if (!oci_execute($select)) {
+ die("oci_execute(select) failed!\n");
+}
+var_dump(oci_fetch_all($select, $all));
+var_dump($all);
+
+
+require(dirname(__FILE__).'/drop_table.inc');
+
+echo "Done\n";
+?>
+--EXPECTF--
+bool(true)
+int(0)
+array(5) {
+ [%u|b%"ID"]=>
+ array(0) {
+ }
+ [%u|b%"VALUE"]=>
+ array(0) {
+ }
+ [%u|b%"BLOB"]=>
+ array(0) {
+ }
+ [%u|b%"CLOB"]=>
+ array(0) {
+ }
+ [%u|b%"STRING"]=>
+ array(0) {
+ }
+}
+bool(true)
+int(4)
+array(5) {
+ [%u|b%"ID"]=>
+ array(4) {
+ [0]=>
+ %string|unicode%(1) "1"
+ [1]=>
+ %string|unicode%(1) "1"
+ [2]=>
+ %string|unicode%(1) "1"
+ [3]=>
+ %string|unicode%(1) "1"
+ }
+ [%u|b%"VALUE"]=>
+ array(4) {
+ [0]=>
+ %string|unicode%(1) "1"
+ [1]=>
+ %string|unicode%(1) "1"
+ [2]=>
+ %string|unicode%(1) "1"
+ [3]=>
+ %string|unicode%(1) "1"
+ }
+ [%u|b%"BLOB"]=>
+ array(4) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ }
+ [%u|b%"CLOB"]=>
+ array(4) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ }
+ [%u|b%"STRING"]=>
+ array(4) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ }
+}
+Done
diff --git a/tests/commit_002.phpt b/tests/commit_002.phpt
new file mode 100644
index 0000000000..1819fe116b
--- /dev/null
+++ b/tests/commit_002.phpt
@@ -0,0 +1,90 @@
+--TEST--
+Test oci_commit failure
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table commit_002_tab",
+ "create table commit_002_tab
+ ( x int constraint commit_002_tab_check_x check ( x > 0 ) deferrable initially immediate,
+ y int constraint commit_002_tab_check_y check ( y > 0 ) deferrable initially deferred)"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+echo "First Insert\n";
+$s = oci_parse($c, "insert into commit_002_tab values (-1, 1)");
+$r = @oci_execute($s, OCI_DEFAULT);
+if (!$r) {
+ $m = oci_error($s);
+ echo 'Could not execute: '. $m['message'] . "\n";
+}
+$r = oci_commit($c);
+if (!$r) {
+ $m = oci_error($c);
+ echo 'Could not commit: '. $m['message'] . "\n";
+}
+
+
+echo "Second Insert\n";
+$s = oci_parse($c, "insert into commit_002_tab values (1, -1)");
+$r = @oci_execute($s, OCI_NO_AUTO_COMMIT);
+if (!$r) {
+ $m = oci_error($s);
+ echo 'Could not execute: '. $m['message'] . "\n";
+}
+$r = oci_commit($c);
+if (!$r) {
+ $m = oci_error($c);
+ echo 'Could not commit: '. $m['message'] . "\n";
+}
+
+
+// Clean up
+
+$stmtarray = array(
+ "drop table commit_002_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+First Insert
+Could not execute: ORA-02290: %s (%s.COMMIT_002_TAB_CHECK_X) %s
+Second Insert
+
+Warning: oci_commit(): ORA-02091: %s
+ORA-02290: %s (%s.COMMIT_002_TAB_CHECK_Y) %s in %scommit_002.php on line %d
+Could not commit: ORA-02091: %s
+ORA-02290: %s (%s.COMMIT_002_TAB_CHECK_Y) %s
+===DONE===
diff --git a/tests/commit_old.phpt b/tests/commit_old.phpt
new file mode 100644
index 0000000000..196e0650cc
--- /dev/null
+++ b/tests/commit_old.phpt
@@ -0,0 +1,146 @@
+--TEST--
+ocicommit()/ocirollback()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__).'/create_table.inc';
+
+$insert_sql = "INSERT INTO ".$schema.$table_name." (id, value) VALUES (1,1)";
+
+if (!($s = ociparse($c, $insert_sql))) {
+ die("ociparse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!ociexecute($s, OCI_DEFAULT)) {
+ die("ociexecute(insert) failed!\n");
+ }
+}
+
+var_dump(ocirollback($c));
+
+$select_sql = "SELECT * FROM ".$schema.$table_name."";
+
+if (!($select = ociparse($c, $select_sql))) {
+ die("ociparse(select) failed!\n");
+}
+
+if (!oci_execute($select)) {
+ die("ociexecute(select) failed!\n");
+}
+var_dump(ocifetchstatement($select, $all));
+var_dump($all);
+
+/* ocifetchstatement */
+if (!ociexecute($s)) {
+ die("ociexecute(select) failed!\n");
+}
+
+$insert_sql = "INSERT INTO ".$schema.$table_name." (id, value) VALUES (1,1)";
+
+if (!($s = ociparse($c, $insert_sql))) {
+ die("ociparse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!ociexecute($s, OCI_DEFAULT)) {
+ die("ociexecute(insert) failed!\n");
+ }
+}
+
+var_dump(ocicommit($c));
+
+if (!ociexecute($select)) {
+ die("ociexecute(select) failed!\n");
+}
+var_dump(ocifetchstatement($select, $all));
+var_dump($all);
+
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECT--
+bool(true)
+int(0)
+array(5) {
+ ["ID"]=>
+ array(0) {
+ }
+ ["VALUE"]=>
+ array(0) {
+ }
+ ["BLOB"]=>
+ array(0) {
+ }
+ ["CLOB"]=>
+ array(0) {
+ }
+ ["STRING"]=>
+ array(0) {
+ }
+}
+bool(true)
+int(4)
+array(5) {
+ ["ID"]=>
+ array(4) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "1"
+ [3]=>
+ string(1) "1"
+ }
+ ["VALUE"]=>
+ array(4) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "1"
+ [3]=>
+ string(1) "1"
+ }
+ ["BLOB"]=>
+ array(4) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ }
+ ["CLOB"]=>
+ array(4) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ }
+ ["STRING"]=>
+ array(4) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ }
+}
+Done
diff --git a/tests/conn_attr.inc b/tests/conn_attr.inc
new file mode 100644
index 0000000000..2c086b1892
--- /dev/null
+++ b/tests/conn_attr.inc
@@ -0,0 +1,151 @@
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release (11\.2|12)\./', $sv, $matches);
+if ($sv == 1) {
+ // Server is Oracle 11.2+
+ $stmtarray = array(
+ "drop user testuser cascade",
+ "create user testuser identified by testuser",
+ "grant connect,resource,dba to testuser",
+ "alter user testuser enable editions",
+ "drop edition myedition1",
+ "drop edition myedition",
+ "grant create any edition to testuser",
+ "create edition myedition",
+ "create edition myedition1 as child of myedition",
+ "grant use on edition myedition to testuser",
+ "grant use on edition myedition1 to testuser",
+ );
+}
+else {
+ // Server is Pre 11.2
+ $stmtarray = array(
+ "drop user testuser cascade",
+ "create user testuser identified by testuser",
+ "grant connect,resource,dba to testuser",
+ );
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 1918 // user does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo "Error:" . $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ if ($m['code'] == 38807) {
+ echo "You appear to already have an edition in use that prevents this PHP test from running. Query DBA_EDITIONS to see existing editions.". PHP_EOL;
+ }
+ die;
+ }
+ }
+}
+
+function get_attr($conn,$attr)
+{
+ $sel_stmt="select " .$attr. " from v\$session where sid =
+ (select sid from v\$session where audsid =
+ sys_context('userenv','sessionid')) order by 1";
+ $s2 = oci_parse($conn,$sel_stmt);
+ oci_execute($s2,OCI_DEFAULT);
+ while (oci_fetch($s2)) {
+ echo "The value of ".$attr ." is ".oci_result($s2,1)."\n";
+ }
+}
+
+/* Pass $conn_type=1 for a connection with oci_connect()
+ Pass $conn_type=2 for ooci_pconnect
+ Default will give a oci_new_connect */
+
+function get_conn($conn_type)
+{
+ $user = 'testuser';
+ $password = 'testuser';
+ $dbase = $GLOBALS['dbase'];
+ switch($conn_type) {
+ case 1:
+ echo "Testing with oci_connect()\n";
+ return(oci_connect($user,$password,$dbase));
+ break;
+ case 2:
+ echo "Testing with oci_pconnect()\n";
+ return(oci_pconnect($user,$password,$dbase));
+ break;
+ default:
+ echo "Testing with oci_new_connect()\n";
+ return(oci_new_connect($user,$password,$dbase));
+ break;
+ }
+}
+
+function set_attr($conn,$attr,$sufix)
+{
+ if (!strcmp($attr,'MODULE'))
+ $r = oci_set_module_name($conn,'PHP TEST'.$sufix);
+ else if (!strcmp($attr,'ACTION'))
+ $r = oci_set_action($conn,'TASK'.$sufix);
+ else if (!strcmp($attr,'CLIENT_INFO'))
+ $r = oci_set_client_info($conn,'INFO1'.$sufix);
+ else if (!strcmp($attr,'CLIENT_IDENTIFIER'))
+ $r = oci_set_client_identifier($conn,'ID00'.$sufix);
+ else
+ echo "Pass one of the above four attibutes!!!\n";
+ if ($r) {
+ echo "Value of $attr has been set successfully\n";
+ }
+
+ //Do a round-trip here
+ oci_server_version($conn);
+ return $r;
+}
+
+function set_edit_attr($value)
+{
+ $r = oci_set_edition($value);
+ if ($r) {
+ echo " The value of edition has been successfully set\n";
+ }
+ return $r;
+}
+
+function get_edit_attr ($conn) {
+ $sel_stmt = "select sys_context('USERENV', 'CURRENT_EDITION_NAME') from dual";
+ $s2 = oci_parse($conn,$sel_stmt);
+ oci_execute($s2,OCI_DEFAULT);
+ while (oci_fetch($s2)) {
+ echo "The value of current EDITION is ".oci_result($s2,1)."\n";
+ }
+}
+
+function get_sys_attr($conn,$attr)
+{
+ $sel_stmt="select " .$attr. " from v\$session where sid =
+ (select sid from v\$session where audsid = sys_context('userenv','sessionid')) order by 1";
+ $s2 = oci_parse($conn,$sel_stmt);
+ oci_execute($s2,OCI_DEFAULT);
+ while (oci_fetch($s2)) {
+ echo "The value of ".$attr ." is ".oci_result($s2,1)."\n";
+ }
+}
+
+function clean_up($c) {
+ $stmtarray = array(
+ "drop user testuser cascade",
+ "drop edition myedition1",
+ "drop edition myedition",
+ );
+
+ foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+ }
+}
diff --git a/tests/conn_attr_1.phpt b/tests/conn_attr_1.phpt
new file mode 100644
index 0000000000..c7c1b870e5
--- /dev/null
+++ b/tests/conn_attr_1.phpt
@@ -0,0 +1,104 @@
+--TEST--
+Set and get of connection attributes with all types of connections.
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys"))
+ die("skip needs to be run as a DBA user");
+if ($test_drcp) die("skip output might vary with DRCP");
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[012]\./', $sv, $matches);
+if ($sv == 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 1[012]\./', $phpinfo);
+ if ($iv != 1) {
+ die ("skip test expected to work only with Oracle 10g or greater client ");
+ }
+}
+else {
+ die ("skip test expected to work only with Oracle 10g or greater server");
+}
+
+?>
+--FILE--
+<?php
+require(dirname(__FILE__)."/conn_attr.inc");
+
+$attr_array = array('MODULE','ACTION','CLIENT_INFO','CLIENT_IDENTIFIER');
+
+echo"**Test 1.1 - Default values for the attributes **************\n";
+$c = get_conn(1);
+foreach($attr_array as $attr) {
+ get_attr($c,$attr);
+}
+
+echo"**Test 1.2 - Set and get values for the attributes **************\n";
+
+// With oci_connect, oci_pconnect, oci_new_connect
+
+$conn1 = get_conn(1); //oci_connect()
+foreach($attr_array as $attr) {
+ set_attr($conn1,$attr,1);
+ get_attr($conn1,$attr);
+}
+
+$conn2 = get_conn(2); //oci_pconnect()
+foreach($attr_array as $attr) {
+ set_attr($conn2,$attr,2);
+ get_attr($conn2,$attr);
+}
+
+$conn3 = get_conn(3); //oci_new_connect()
+foreach($attr_array as $attr) {
+ set_attr($conn3,$attr,3);
+ get_attr($conn3,$attr);
+}
+
+// clean up
+oci_close($conn1);
+oci_close($conn2);
+oci_close($conn3);
+clean_up($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+**Test 1.1 - Default values for the attributes **************
+Testing with oci_connect()
+The value of MODULE is %s
+The value of ACTION is
+The value of CLIENT_INFO is
+The value of CLIENT_IDENTIFIER is
+**Test 1.2 - Set and get values for the attributes **************
+Testing with oci_connect()
+Value of MODULE has been set successfully
+The value of MODULE is PHP TEST1
+Value of ACTION has been set successfully
+The value of ACTION is TASK1
+Value of CLIENT_INFO has been set successfully
+The value of CLIENT_INFO is INFO11
+Value of CLIENT_IDENTIFIER has been set successfully
+The value of CLIENT_IDENTIFIER is ID001
+Testing with oci_pconnect()
+Value of MODULE has been set successfully
+The value of MODULE is PHP TEST2
+Value of ACTION has been set successfully
+The value of ACTION is TASK2
+Value of CLIENT_INFO has been set successfully
+The value of CLIENT_INFO is INFO12
+Value of CLIENT_IDENTIFIER has been set successfully
+The value of CLIENT_IDENTIFIER is ID002
+Testing with oci_new_connect()
+Value of MODULE has been set successfully
+The value of MODULE is PHP TEST3
+Value of ACTION has been set successfully
+The value of ACTION is TASK3
+Value of CLIENT_INFO has been set successfully
+The value of CLIENT_INFO is INFO13
+Value of CLIENT_IDENTIFIER has been set successfully
+The value of CLIENT_IDENTIFIER is ID003
+Done
diff --git a/tests/conn_attr_2.phpt b/tests/conn_attr_2.phpt
new file mode 100644
index 0000000000..4765d5eb7b
--- /dev/null
+++ b/tests/conn_attr_2.phpt
@@ -0,0 +1,111 @@
+--TEST--
+Set and get of connection attributes across persistent connections and sysdba connection.
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+if ($test_drcp) die("skip output might vary with DRCP");
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[012]\./', $sv, $matches);
+if ($sv == 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 1[012]\./', $phpinfo);
+ if ($iv != 1) {
+ die ("skip test expected to work only with Oracle 10g or greater version of client");
+ }
+}
+else {
+ die ("skip test expected to work only with Oracle 10g or greater version of server");
+}
+?>
+--INI--
+oci8.privileged_connect = On
+--FILE--
+
+<?php
+require(dirname(__FILE__)."/conn_attr.inc");
+$user='testuser';
+$password='testuser';
+$attr_array = array('MODULE','ACTION','CLIENT_INFO','CLIENT_IDENTIFIER');
+
+echo"**Set values using pconnect-1**\n";
+
+var_dump($pc1 = oci_pconnect($user,$password,$dbase));
+foreach($attr_array as $attr) {
+ set_attr($pc1,$attr,100);
+}
+
+// using pc1 again
+echo"\n**Get values using pconnect-2**\n";
+var_dump($pc3 = oci_pconnect($user,$password,$dbase));
+foreach($attr_array as $attr) {
+ get_attr($pc3,$attr);
+}
+
+// Get with different pconnect
+echo"\n**Get values using pconnect-3**\n";
+var_dump($pc2 = oci_pconnect($user,$password,$dbase,'UTF8'));
+foreach($attr_array as $attr) {
+ get_attr($pc2,$attr);
+}
+
+oci_close($pc1);
+oci_close($pc2);
+oci_close($pc3);
+
+// Re-open a persistent connection and check for the attr values.
+echo "\n**Re-open a pconnect()**\n";
+var_dump($pc4 = oci_pconnect($user,$password,$dbase));
+foreach($attr_array as $attr) {
+ get_attr($pc4,$attr);
+}
+oci_close($pc4);
+
+// Test with SYSDBA connection.
+var_dump($sys_c1 = oci_pconnect($user,$password,$dbase,false,OCI_SYSDBA));
+if ($sys_c1) {
+ set_attr($sys_c1,'ACTION',10);
+ get_sys_attr($sys_c1,'ACTION');
+ get_attr($pc2,'ACTION');
+ oci_close($sys_c1);
+}
+
+clean_up($c);
+
+echo "Done\n";
+?>
+--EXPECTF--
+**Set values using pconnect-1**
+resource(%d) of type (oci8 persistent connection)
+Value of MODULE has been set successfully
+Value of ACTION has been set successfully
+Value of CLIENT_INFO has been set successfully
+Value of CLIENT_IDENTIFIER has been set successfully
+
+**Get values using pconnect-2**
+resource(%d) of type (oci8 persistent connection)
+The value of MODULE is PHP TEST100
+The value of ACTION is TASK100
+The value of CLIENT_INFO is INFO1100
+The value of CLIENT_IDENTIFIER is ID00100
+
+**Get values using pconnect-3**
+resource(%d) of type (oci8 persistent connection)
+The value of MODULE is %s
+The value of ACTION is
+The value of CLIENT_INFO is
+The value of CLIENT_IDENTIFIER is
+
+**Re-open a pconnect()**
+resource(%d) of type (oci8 persistent connection)
+The value of MODULE is PHP TEST100
+The value of ACTION is TASK100
+The value of CLIENT_INFO is INFO1100
+The value of CLIENT_IDENTIFIER is ID00100
+
+Warning: oci_pconnect(): ORA-01031: %s on line %d
+bool(false)
+Done
diff --git a/tests/conn_attr_3.phpt b/tests/conn_attr_3.phpt
new file mode 100644
index 0000000000..8b6d921230
--- /dev/null
+++ b/tests/conn_attr_3.phpt
@@ -0,0 +1,94 @@
+--TEST--
+Set and get of connection attributes with oci_close().
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+if ($test_drcp) die("skip output might vary with DRCP");
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[012]\./', $sv, $matches);
+if ($sv == 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 1[012]\./', $phpinfo);
+ if ($iv != 1) {
+ die ("skip test expected to work only with Oracle 10g or greater version of client");
+ }
+}
+else {
+ die ("skip test expected to work only with Oracle 10g or greater version of server");
+}
+?>
+--FILE--
+<?php
+require(dirname(__FILE__)."/conn_attr.inc");
+
+echo"**Test Set and get values for the attributes with oci_close() ************\n";
+// With oci_connect ,oci_pconnect ,oci_new_connect
+
+var_dump($conn1 = get_conn(1)); //oci_connect()
+set_attr($conn1,'ACTION',1);
+get_attr($conn1,'ACTION');
+oci_close($conn1);
+
+// Open another connect and verify the value.
+var_dump($conn1 = get_conn(1)); //oci_connect()
+get_attr($conn1,'ACTION');
+oci_close($conn1);
+
+var_dump($pconn1 = get_conn(2)); //oci_pconnect()
+set_attr($pconn1,'MODULE',2);
+get_attr($pconn1,'MODULE');
+oci_close($pconn1);
+
+// Open another connect and verify the value.
+var_dump($pconn1 = get_conn(2)); //oci_pconnect()
+get_attr($pconn1,'MODULE');
+oci_close($pconn1);
+
+var_dump($nconn1 = get_conn(3)); //oci_new_connect()
+set_attr($nconn1,'CLIENT_INFO',3);
+set_attr($nconn1,'CLIENT_IDENTIFIER',3);
+get_attr($nconn1,'CLIENT_INFO');
+get_attr($nconn1,'CLIENT_IDENTIFIER');
+oci_close($nconn1);
+
+// Open another connect and verify the value.
+var_dump($nconn1 = get_conn(3)); //oci_new_connect()
+get_attr($nconn1,'CLIENT_INFO');
+get_attr($nconn1,'CLIENT_IDENTIFIER');
+oci_close($nconn1);
+
+clean_up($c);
+echo "Done\n";
+
+?>
+--EXPECTF--
+**Test Set and get values for the attributes with oci_close() ************
+Testing with oci_connect()
+resource(%d) of type (oci8 connection)
+Value of ACTION has been set successfully
+The value of ACTION is TASK1
+Testing with oci_connect()
+resource(%d) of type (oci8 connection)
+The value of ACTION is
+Testing with oci_pconnect()
+resource(%d) of type (oci8 persistent connection)
+Value of MODULE has been set successfully
+The value of MODULE is PHP TEST2
+Testing with oci_pconnect()
+resource(%d) of type (oci8 persistent connection)
+The value of MODULE is PHP TEST2
+Testing with oci_new_connect()
+resource(%d) of type (oci8 connection)
+Value of CLIENT_INFO has been set successfully
+Value of CLIENT_IDENTIFIER has been set successfully
+The value of CLIENT_INFO is INFO13
+The value of CLIENT_IDENTIFIER is ID003
+Testing with oci_new_connect()
+resource(%d) of type (oci8 connection)
+The value of CLIENT_INFO is
+The value of CLIENT_IDENTIFIER is
+Done
diff --git a/tests/conn_attr_4.phpt b/tests/conn_attr_4.phpt
new file mode 100644
index 0000000000..9f55f53263
--- /dev/null
+++ b/tests/conn_attr_4.phpt
@@ -0,0 +1,122 @@
+--TEST--
+Set and get of connection attributes with errors.
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+if ($test_drcp) die("skip output might vary with DRCP");
+if ($stress_test !== true) die ('skip Slow test not run when $stress_test is FALSE');
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[012]\./', $sv, $matches);
+if ($sv == 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 1[012]\./', $phpinfo);
+ if ($iv != 1) {
+ die ("skip test expected to work only with Oracle 10g or greater version of client");
+ }
+}
+else {
+ die ("skip test expected to work only with Oracle 10g or greater version of server");
+}
+?>
+--FILE--
+<?php
+require(dirname(__FILE__)."/conn_attr.inc");
+
+$user='testuser';
+$password='testuser';
+$attr_array = array('MODULE','ACTION','CLIENT_INFO','CLIENT_IDENTIFIER');
+
+echo"**Test Negative cases************\n";
+
+echo "\nInvalid Connection resource\n";
+$nc1=NULL;
+// Invalid connection handle.
+var_dump(oci_set_action($nc1,$nc1));
+
+// Variable instead of a connection resource.
+echo "\nInvalid Connection resource 2\n";
+$str1= 'not a conn';
+var_dump(oci_set_client_info($str1,$str1));
+
+// Setting an Invalid value.
+echo "\nInvalid Value \n";
+$c1=oci_connect($user,$password,$dbase);
+var_dump(oci_set_action($c1,$c1));
+
+// Setting values multiple times.
+echo "\nSet Values multiple times \n";
+var_dump(oci_set_action($c1,'ACTION1'));
+var_dump(oci_set_action($c1,'ACTION1'));
+var_dump(oci_set_action($c1,'ACTION2'));
+var_dump(oci_set_action($c1,'ACTION1'));
+get_attr($c1,'ACTION');
+
+// Testing with different types of values
+echo "\nSetting to different values \n";
+$values_array = array(1000,NULL,'this is a very huge string with a length > 64 !!!!!this is a very huge string with a length > 64 !!!!!this is a very huge string with a length > 64 !!!!!this is a very huge string with a length > 64 !!!!!');
+
+foreach($values_array as $val ) {
+ oci_set_module_name($c1,$val);
+ oci_set_client_identifier($c1,$val);
+ oci_set_client_info($c1,$val);
+ $r = oci_set_action($c1,$val);
+ if ($r) {
+ echo "Values set succesfully to $val\n";
+ foreach($attr_array as $attr) {
+ get_attr($c1,$attr);
+ }
+ }
+}
+
+clean_up($c);
+echo "Done\n";
+?>
+--EXPECTF--
+**Test Negative cases************
+
+Invalid Connection resource
+
+Warning: oci_set_action() expects parameter 1 to be resource, null given in %s on line %d
+NULL
+
+Invalid Connection resource 2
+
+Warning: oci_set_client_info() expects parameter 1 to be resource, %s given in %s on line %d
+NULL
+
+Invalid Value
+
+Warning: oci_set_action() expects parameter 2 to be %s, resource given in %s on line %d
+NULL
+
+Set Values multiple times
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+The value of ACTION is ACTION1
+
+Setting to different values
+Values set succesfully to 1000
+The value of MODULE is 1000
+The value of ACTION is 1000
+The value of CLIENT_INFO is 1000
+The value of CLIENT_IDENTIFIER is 1000
+Values set succesfully to
+The value of MODULE is
+The value of ACTION is
+The value of CLIENT_INFO is
+The value of CLIENT_IDENTIFIER is
+
+Warning: oci_set_module_name(): ORA-24960: %s OCI_ATTR_MODULE %s on line %d
+
+Warning: oci_set_client_identifier(): ORA-24960: %s OCI_ATTR_CLIENT_IDENTIFIER %s on line %d
+
+Warning: oci_set_client_info(): ORA-24960: %s OCI_ATTR_CLIENT_INFO %s on line %d
+
+Warning: oci_set_action(): ORA-24960: %s OCI_ATTR_ACTION %s on line %d
+Done
diff --git a/tests/conn_attr_5.phpt b/tests/conn_attr_5.phpt
new file mode 100644
index 0000000000..9f6b6c7247
--- /dev/null
+++ b/tests/conn_attr_5.phpt
@@ -0,0 +1,76 @@
+--TEST--
+Set and get connection attributes with scope end.
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+if ($test_drcp) die("skip output might vary with DRCP");
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release 1[012]\./', $sv, $matches);
+if ($sv == 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 1[012]\./', $phpinfo);
+ if ($iv != 1) {
+ die ("skip test expected to work only with Oracle 10g or greater version of client");
+ }
+}
+else {
+ die ("skip test expected to work only with Oracle 10g or greater version of server");
+}
+?>
+--FILE--
+<?php
+require(dirname(__FILE__)."/conn_attr.inc");
+
+echo"**Test - Set and get values for the attributes with scope end ************\n";
+
+// Set the attributes in one scope and verify the values from another scope.
+set_scope();
+
+echo "Get the Values from a different scope \n";
+get_scope();
+
+function set_scope() {
+ $conn1 = get_conn(1);
+ set_attr($conn1,'CLIENT_INFO',50);
+ set_attr($conn1,'CLIENT_IDENTIFIER',50);
+ $conn2 = get_conn(3);
+ set_attr($conn2,'ACTION',50);
+ $conn3 = get_conn(2);
+ set_attr($conn3,'MODULE',50);
+
+}
+
+function get_scope() {
+ $conn1 = get_conn(1);
+ get_attr($conn1,'CLIENT_INFO');
+ get_attr($conn1,'CLIENT_IDENTIFIER');
+ $conn2 = get_conn(3);
+ get_attr($conn2,'ACTION');
+ $conn3 = get_conn(2);
+ get_attr($conn3,'MODULE');
+}
+clean_up($c);
+echo "Done";
+?>
+--EXPECTF--
+**Test - Set and get values for the attributes with scope end ************
+Testing with oci_connect()
+Value of CLIENT_INFO has been set successfully
+Value of CLIENT_IDENTIFIER has been set successfully
+Testing with oci_new_connect()
+Value of ACTION has been set successfully
+Testing with oci_pconnect()
+Value of MODULE has been set successfully
+Get the Values from a different scope
+Testing with oci_connect()
+The value of CLIENT_INFO is
+The value of CLIENT_IDENTIFIER is
+Testing with oci_new_connect()
+The value of ACTION is
+Testing with oci_pconnect()
+The value of MODULE is PHP TEST50
+Done
diff --git a/tests/connect.inc b/tests/connect.inc
new file mode 100644
index 0000000000..5e340cf6fa
--- /dev/null
+++ b/tests/connect.inc
@@ -0,0 +1,18 @@
+<?php
+
+require("details.inc");
+
+if (!empty($dbase)) {
+ $c = @oci_connect($user, $password, $dbase);
+}
+else {
+ $c = @oci_connect($user, $password);
+}
+
+if (!$c) {
+ echo "connect.inc: Failed to connect as '$user' to '$dbase'\n";
+ $e = oci_error();
+ echo $e['message']."\n";
+}
+
+?>
diff --git a/tests/connect.phpt b/tests/connect.phpt
new file mode 100644
index 0000000000..6ce4c533ba
--- /dev/null
+++ b/tests/connect.phpt
@@ -0,0 +1,22 @@
+--TEST--
+oci_connect()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+if (!empty($dbase)) {
+ var_dump(oci_connect($user, $password, $dbase));
+}
+else {
+ var_dump(oci_connect($user, $password));
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+Done
diff --git a/tests/connect_1.phpt b/tests/connect_1.phpt
new file mode 100644
index 0000000000..647a92ceeb
--- /dev/null
+++ b/tests/connect_1.phpt
@@ -0,0 +1,35 @@
+--TEST--
+oci_pconnect() & oci_new_connect()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+if (!empty($dbase)) {
+ var_dump($c1 = oci_pconnect($user, $password, $dbase));
+}
+else {
+ var_dump($c1 = oci_pconnect($user, $password));
+}
+
+if (!empty($dbase)) {
+ var_dump($c2 = oci_new_connect($user, $password, $dbase));
+}
+else {
+ var_dump($c2 = oci_new_connect($user, $password));
+}
+
+var_dump(oci_close($c1));
+var_dump(ocilogoff($c2));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 connection)
+bool(true)
+bool(true)
+Done
diff --git a/tests/connect_1_old.phpt b/tests/connect_1_old.phpt
new file mode 100644
index 0000000000..8210b82d6c
--- /dev/null
+++ b/tests/connect_1_old.phpt
@@ -0,0 +1,35 @@
+--TEST--
+ociplogon() & ocinlogon()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+if (!empty($dbase)) {
+ var_dump($c1 = ociplogon($user, $password, $dbase));
+}
+else {
+ var_dump($c1 = ociplogon($user, $password));
+}
+
+if (!empty($dbase)) {
+ var_dump($c2 = ocinlogon($user, $password, $dbase));
+}
+else {
+ var_dump($c2 = ocinlogon($user, $password));
+}
+
+var_dump(ocilogoff($c1));
+var_dump(ocilogoff($c2));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 connection)
+bool(true)
+bool(true)
+Done
diff --git a/tests/connect_old.phpt b/tests/connect_old.phpt
new file mode 100644
index 0000000000..55f1734a5a
--- /dev/null
+++ b/tests/connect_old.phpt
@@ -0,0 +1,22 @@
+--TEST--
+ocilogon()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+if (!empty($dbase)) {
+ var_dump(ocilogon($user, $password, $dbase));
+}
+else {
+ var_dump(ocilogon($user, $password));
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+Done
diff --git a/tests/connect_scope1.phpt b/tests/connect_scope1.phpt
new file mode 100644
index 0000000000..d6d16f17ee
--- /dev/null
+++ b/tests/connect_scope1.phpt
@@ -0,0 +1,93 @@
+--TEST--
+Test oci_connect end-of-scope when statement returned
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table connect_scope1_tab",
+ "create table connect_scope1_tab (c1 number)",
+);
+
+if (!empty($dbase))
+ $c1 = oci_new_connect($user,$password,$dbase);
+else
+ $c1 = oci_new_connect($user,$password);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ @oci_execute($s1);
+}
+
+// Run Test
+
+echo "Test 1 - oci_connect\n";
+
+function f()
+{
+ global $user, $password, $dbase;
+
+ if (!empty($dbase))
+ $c = oci_connect($user,$password,$dbase);
+ else
+ $c = oci_connect($user,$password);
+ $s = oci_parse($c, "insert into connect_scope1_tab values (1)");
+ oci_execute($s, OCI_DEFAULT); // no commit
+ return($s); // this keeps the connection refcount positive so the connection isn't closed
+}
+
+$s2 = f();
+
+// Check nothing committed yet
+
+$s1 = oci_parse($c1, "select * from connect_scope1_tab");
+oci_execute($s1, OCI_DEFAULT);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// insert 2nd row on returned statement, committing both rows
+oci_execute($s2);
+
+// Verify data was committed
+
+$s1 = oci_parse($c1, "select * from connect_scope1_tab");
+oci_execute($s1);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table connect_scope1_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ oci_execute($s1);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1 - oci_connect
+array(1) {
+ ["C1"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["C1"]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+}
+Done
diff --git a/tests/connect_scope2.phpt b/tests/connect_scope2.phpt
new file mode 100644
index 0000000000..7017493f5a
--- /dev/null
+++ b/tests/connect_scope2.phpt
@@ -0,0 +1,93 @@
+--TEST--
+Test oci_pconnect end-of-scope when statement returned
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table connect_scope2_tab",
+ "create table connect_scope2_tab (c1 number)",
+);
+
+if (!empty($dbase))
+ $c1 = oci_new_connect($user,$password,$dbase);
+else
+ $c1 = oci_new_connect($user,$password);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ @oci_execute($s1);
+}
+
+// Run Test
+
+echo "Test 1 - oci_pconnect\n";
+
+function f()
+{
+ global $user, $password, $dbase;
+
+ if (!empty($dbase))
+ $c = oci_pconnect($user,$password,$dbase);
+ else
+ $c = oci_pconnect($user,$password);
+ $s = oci_parse($c, "insert into connect_scope2_tab values (1)");
+ oci_execute($s, OCI_DEFAULT); // no commit
+ return($s); // this keeps the connection refcount positive so the connection isn't closed
+}
+
+$s2 = f();
+
+// Check nothing committed yet
+
+$s1 = oci_parse($c1, "select * from connect_scope2_tab");
+oci_execute($s1, OCI_DEFAULT);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// insert 2nd row on returned statement, committing both rows
+oci_execute($s2);
+
+// Verify data was committed
+
+$s1 = oci_parse($c1, "select * from connect_scope2_tab");
+oci_execute($s1);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table connect_scope2_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ oci_execute($s1);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1 - oci_pconnect
+array(1) {
+ ["C1"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["C1"]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+}
+Done
diff --git a/tests/connect_scope_try1.phpt b/tests/connect_scope_try1.phpt
new file mode 100644
index 0000000000..a881ea6ead
--- /dev/null
+++ b/tests/connect_scope_try1.phpt
@@ -0,0 +1,100 @@
+--TEST--
+Check oci_connect try/catch end-of-scope with old_oci_close_semantics Off
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table scope_try1_tab",
+ "create table scope_try1_tab (c1 number)"
+);
+
+if (!empty($dbase))
+ $c1 = oci_new_connect($user,$password,$dbase);
+else
+ $c1 = oci_new_connect($user,$password);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ @oci_execute($s1);
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+// Make errors throw exceptions
+
+set_error_handler(create_function('$x, $y', 'throw new Exception($y, $x);'));
+
+try
+{
+ if (!empty($dbase))
+ $c = oci_connect($user,$password,$dbase);
+ else
+ $c = oci_connect($user,$password);
+ $s = oci_parse($c, "insert into scope_try1_tab values (1)");
+ oci_execute($s, OCI_DEFAULT); // no commit
+ $s = oci_parse($c, "insert into scope_try1_tab values (ABC)"); // syntax error -> throws exception
+ oci_execute($s, OCI_DEFAULT); // no commit
+}
+catch (Exception $e)
+{
+ echo "Caught Exception: ". $e->getMessage(), "\n";
+ var_dump($c);
+
+ // Verify data is not yet committed
+ $s1 = oci_parse($c1, "select * from scope_try1_tab");
+ oci_execute($s1);
+ oci_fetch_all($s1, $r);
+ var_dump($r);
+
+ // Now commit
+ oci_commit($c);
+}
+
+// Verify data was committed in the Catch block
+
+$s1 = oci_parse($c1, "select * from scope_try1_tab");
+oci_execute($s1);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table scope_try1_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ oci_execute($s1);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+Caught Exception: oci_execute(): ORA-00984: %s
+resource(%d) of type (oci8 connection)
+array(1) {
+ ["C1"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["C1"]=>
+ array(1) {
+ [0]=>
+ string(1) "1"
+ }
+}
+Done
diff --git a/tests/connect_scope_try2.phpt b/tests/connect_scope_try2.phpt
new file mode 100644
index 0000000000..9e6b5ce2e0
--- /dev/null
+++ b/tests/connect_scope_try2.phpt
@@ -0,0 +1,100 @@
+--TEST--
+Check oci_connect try/catch end-of-scope with old_oci_close_semantics On
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table scope_try2_tab",
+ "create table scope_try2_tab (c1 number)"
+);
+
+if (!empty($dbase))
+ $c1 = oci_new_connect($user,$password,$dbase);
+else
+ $c1 = oci_new_connect($user,$password);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ @oci_execute($s1);
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+// Make errors throw exceptions
+
+set_error_handler(create_function('$x, $y', 'throw new Exception($y, $x);'));
+
+try
+{
+ if (!empty($dbase))
+ $c = oci_connect($user,$password,$dbase);
+ else
+ $c = oci_connect($user,$password);
+ $s = oci_parse($c, "insert into scope_try2_tab values (1)");
+ oci_execute($s, OCI_DEFAULT); // no commit
+ $s = oci_parse($c, "insert into scope_try2_tab values (ABC)"); // syntax error -> throws exception
+ oci_execute($s, OCI_DEFAULT); // no commit
+}
+catch (Exception $e)
+{
+ echo "Caught Exception: ". $e->getMessage(), "\n";
+ var_dump($c);
+
+ // Verify data is not yet committed
+ $s1 = oci_parse($c1, "select * from scope_try2_tab");
+ oci_execute($s1);
+ oci_fetch_all($s1, $r);
+ var_dump($r);
+
+ // Now commit
+ oci_commit($c);
+}
+
+// Verify data was committed in the Catch block
+
+$s1 = oci_parse($c1, "select * from scope_try2_tab");
+oci_execute($s1);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table scope_try2_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ oci_execute($s1);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+Caught Exception: oci_execute(): ORA-00984: %s
+resource(%d) of type (oci8 connection)
+array(1) {
+ ["C1"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["C1"]=>
+ array(1) {
+ [0]=>
+ string(1) "1"
+ }
+}
+Done
diff --git a/tests/connect_scope_try3.phpt b/tests/connect_scope_try3.phpt
new file mode 100644
index 0000000000..1cd44b0218
--- /dev/null
+++ b/tests/connect_scope_try3.phpt
@@ -0,0 +1,100 @@
+--TEST--
+Check oci_new_connect try/catch end-of-scope with old_oci_close_semantics Off
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table scope_try3_tab",
+ "create table scope_try3_tab (c1 number)"
+);
+
+if (!empty($dbase))
+ $c1 = oci_new_connect($user,$password,$dbase);
+else
+ $c1 = oci_new_connect($user,$password);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ @oci_execute($s1);
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+// Make errors throw exceptions
+
+set_error_handler(create_function('$x, $y', 'throw new Exception($y, $x);'));
+
+try
+{
+ if (!empty($dbase))
+ $c = oci_new_connect($user,$password,$dbase);
+ else
+ $c = oci_new_connect($user,$password);
+ $s = oci_parse($c, "insert into scope_try3_tab values (1)");
+ oci_execute($s, OCI_DEFAULT); // no commit
+ $s = oci_parse($c, "insert into scope_try3_tab values (ABC)"); // syntax error -> throws exception
+ oci_execute($s, OCI_DEFAULT); // no commit
+}
+catch (Exception $e)
+{
+ echo "Caught Exception: ". $e->getMessage(), "\n";
+ var_dump($c);
+
+ // Verify data is not yet committed
+ $s1 = oci_parse($c1, "select * from scope_try3_tab");
+ oci_execute($s1);
+ oci_fetch_all($s1, $r);
+ var_dump($r);
+
+ // Now commit
+ oci_commit($c);
+}
+
+// Verify data was committed in the Catch block
+
+$s1 = oci_parse($c1, "select * from scope_try3_tab");
+oci_execute($s1);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table scope_try3_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ oci_execute($s1);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+Caught Exception: oci_execute(): ORA-00984: %s
+resource(%d) of type (oci8 connection)
+array(1) {
+ ["C1"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["C1"]=>
+ array(1) {
+ [0]=>
+ string(1) "1"
+ }
+}
+Done
diff --git a/tests/connect_scope_try4.phpt b/tests/connect_scope_try4.phpt
new file mode 100644
index 0000000000..9b4cd1f278
--- /dev/null
+++ b/tests/connect_scope_try4.phpt
@@ -0,0 +1,100 @@
+--TEST--
+Check oci_new_connect try/catch end-of-scope with old_oci_close_semantics On
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table scope_try4_tab",
+ "create table scope_try4_tab (c1 number)"
+);
+
+if (!empty($dbase))
+ $c1 = oci_new_connect($user,$password,$dbase);
+else
+ $c1 = oci_new_connect($user,$password);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ @oci_execute($s1);
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+// Make errors throw exceptions
+
+set_error_handler(create_function('$x, $y', 'throw new Exception($y, $x);'));
+
+try
+{
+ if (!empty($dbase))
+ $c = oci_new_connect($user,$password,$dbase);
+ else
+ $c = oci_new_connect($user,$password);
+ $s = oci_parse($c, "insert into scope_try4_tab values (1)");
+ oci_execute($s, OCI_DEFAULT); // no commit
+ $s = oci_parse($c, "insert into scope_try4_tab values (ABC)"); // syntax error -> throws exception
+ oci_execute($s, OCI_DEFAULT); // no commit
+}
+catch (Exception $e)
+{
+ echo "Caught Exception: ". $e->getMessage(), "\n";
+ var_dump($c);
+
+ // Verify data is not yet committed
+ $s1 = oci_parse($c1, "select * from scope_try4_tab");
+ oci_execute($s1);
+ oci_fetch_all($s1, $r);
+ var_dump($r);
+
+ // Now commit
+ oci_commit($c);
+}
+
+// Verify data was committed in the Catch block
+
+$s1 = oci_parse($c1, "select * from scope_try4_tab");
+oci_execute($s1);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table scope_try4_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ oci_execute($s1);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+Caught Exception: oci_execute(): ORA-00984: %s
+resource(%d) of type (oci8 connection)
+array(1) {
+ ["C1"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["C1"]=>
+ array(1) {
+ [0]=>
+ string(1) "1"
+ }
+}
+Done
diff --git a/tests/connect_scope_try5.phpt b/tests/connect_scope_try5.phpt
new file mode 100644
index 0000000000..121fb33dc5
--- /dev/null
+++ b/tests/connect_scope_try5.phpt
@@ -0,0 +1,100 @@
+--TEST--
+Check oci_pconnect try/catch end-of-scope with old_oci_close_semantics Off
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table scope_try5_tab",
+ "create table scope_try5_tab (c1 number)"
+);
+
+if (!empty($dbase))
+ $c1 = oci_new_connect($user,$password,$dbase);
+else
+ $c1 = oci_new_connect($user,$password);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ @oci_execute($s1);
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+// Make errors throw exceptions
+
+set_error_handler(create_function('$x, $y', 'throw new Exception($y, $x);'));
+
+try
+{
+ if (!empty($dbase))
+ $c = oci_pconnect($user,$password,$dbase);
+ else
+ $c = oci_pconnect($user,$password);
+ $s = oci_parse($c, "insert into scope_try5_tab values (1)");
+ oci_execute($s, OCI_DEFAULT); // no commit
+ $s = oci_parse($c, "insert into scope_try5_tab values (ABC)"); // syntax error -> throws exception
+ oci_execute($s, OCI_DEFAULT); // no commit
+}
+catch (Exception $e)
+{
+ echo "Caught Exception: ". $e->getMessage(), "\n";
+ var_dump($c);
+
+ // Verify data is not yet committed
+ $s1 = oci_parse($c1, "select * from scope_try5_tab");
+ oci_execute($s1);
+ oci_fetch_all($s1, $r);
+ var_dump($r);
+
+ // Now commit
+ oci_commit($c);
+}
+
+// Verify data was committed in the Catch block
+
+$s1 = oci_parse($c1, "select * from scope_try5_tab");
+oci_execute($s1);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table scope_try5_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ oci_execute($s1);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+Caught Exception: oci_execute(): ORA-00984: %s
+resource(%d) of type (oci8 persistent connection)
+array(1) {
+ ["C1"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["C1"]=>
+ array(1) {
+ [0]=>
+ string(1) "1"
+ }
+}
+Done
diff --git a/tests/connect_scope_try6.phpt b/tests/connect_scope_try6.phpt
new file mode 100644
index 0000000000..3347543ab8
--- /dev/null
+++ b/tests/connect_scope_try6.phpt
@@ -0,0 +1,100 @@
+--TEST--
+Check oci_pconnect try/catch end-of-scope with old_oci_close_semantics On
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table scope_try6_tab",
+ "create table scope_try6_tab (c1 number)"
+);
+
+if (!empty($dbase))
+ $c1 = oci_new_connect($user,$password,$dbase);
+else
+ $c1 = oci_new_connect($user,$password);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ @oci_execute($s1);
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+// Make errors throw exceptions
+
+set_error_handler(create_function('$x, $y', 'throw new Exception($y, $x);'));
+
+try
+{
+ if (!empty($dbase))
+ $c = oci_pconnect($user,$password,$dbase);
+ else
+ $c = oci_pconnect($user,$password);
+ $s = oci_parse($c, "insert into scope_try6_tab values (1)");
+ oci_execute($s, OCI_DEFAULT); // no commit
+ $s = oci_parse($c, "insert into scope_try6_tab values (ABC)"); // syntax error -> throws exception
+ oci_execute($s, OCI_DEFAULT); // no commit
+}
+catch (Exception $e)
+{
+ echo "Caught Exception: ". $e->getMessage(), "\n";
+ var_dump($c);
+
+ // Verify data is not yet committed
+ $s1 = oci_parse($c1, "select * from scope_try6_tab");
+ oci_execute($s1);
+ oci_fetch_all($s1, $r);
+ var_dump($r);
+
+ // Now commit
+ oci_commit($c);
+}
+
+// Verify data was committed in the Catch block
+
+$s1 = oci_parse($c1, "select * from scope_try6_tab");
+oci_execute($s1);
+oci_fetch_all($s1, $r);
+var_dump($r);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table scope_try6_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s1 = oci_parse($c1, $stmt);
+ oci_execute($s1);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+Caught Exception: oci_execute(): ORA-00984: %s
+resource(%d) of type (oci8 persistent connection)
+array(1) {
+ ["C1"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["C1"]=>
+ array(1) {
+ [0]=>
+ string(1) "1"
+ }
+}
+Done
diff --git a/tests/connect_with_charset_001.phpt b/tests/connect_with_charset_001.phpt
new file mode 100644
index 0000000000..9149747cdb
--- /dev/null
+++ b/tests/connect_with_charset_001.phpt
@@ -0,0 +1,37 @@
+--TEST--
+oci_connect() with invalid character set
+--SKIPIF--
+<?php if (!extension_loaded("oci8")) print "skip"; ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+var_dump($c1 = oci_connect($user, $password, $dbase));
+var_dump($c2 = oci_connect($user, $password, $dbase, ""));
+var_dump($c3 = oci_connect($user, $password, $dbase, "blah"));
+var_dump($c4 = oci_connect($user, $password, $dbase, "obviously wrong"));
+
+var_dump($c3 == $c4);
+
+var_dump($c5 = oci_connect($user, $password, $dbase, "US7ASCII"));
+var_dump($c6 = oci_connect($user, $password, $dbase, "UTF8"));
+
+var_dump($c5 == $c6);
+
+echo "Done\n";
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+
+Warning: oci_connect(): Invalid character set name: blah in %s on line %d
+resource(%d) of type (oci8 connection)
+
+Warning: oci_connect(): Invalid character set name: obviously wrong in %s on line %d
+resource(%d) of type (oci8 connection)
+bool(true)
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+bool(false)
+Done
diff --git a/tests/connect_without_oracle_home.phpt b/tests/connect_without_oracle_home.phpt
new file mode 100644
index 0000000000..42cbde8b48
--- /dev/null
+++ b/tests/connect_without_oracle_home.phpt
@@ -0,0 +1,34 @@
+--TEST--
+oci_connect() without ORACLE_HOME set (OCIServerAttach() segfaults)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo);
+if ($ov !== 1) {
+ die ("skip Test only valid when OCI8 is built with an ORACLE_HOME");
+}
+?>
+--ENV--
+ORACLE_HOME=""
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+
+if (!empty($dbase)) {
+ var_dump(oci_connect($user, $password, $dbase));
+}
+else {
+ var_dump(oci_connect($user, $password));
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Warning: oci_connect(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and %s are set and point to the right directories in %s on line %d
+bool(false)
+===DONE===
diff --git a/tests/connect_without_oracle_home_old.phpt b/tests/connect_without_oracle_home_old.phpt
new file mode 100644
index 0000000000..82d8ae451b
--- /dev/null
+++ b/tests/connect_without_oracle_home_old.phpt
@@ -0,0 +1,34 @@
+--TEST--
+ocilogon() without ORACLE_HOME set (OCIServerAttach() segfaults)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo);
+if ($ov !== 1) {
+ die ("skip Test only valid when OCI8 is built with an ORACLE_HOME");
+}
+?>
+--ENV--
+ORACLE_HOME=""
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+
+if (!empty($dbase)) {
+ var_dump(ocilogon($user, $password, $dbase));
+}
+else {
+ var_dump(ocilogon($user, $password));
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Warning: ocilogon(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and %s are set and point to the right directories in %s on line %d
+bool(false)
+===DONE===
diff --git a/tests/create_table.inc b/tests/create_table.inc
new file mode 100644
index 0000000000..afd1fceb9b
--- /dev/null
+++ b/tests/create_table.inc
@@ -0,0 +1,11 @@
+<?php
+ if ($c) {
+ $ora_sql = "DROP TABLE ".$schema.$table_name;
+ $statement = oci_parse($c, $ora_sql);
+ @oci_execute($statement);
+
+ $ora_sql = "CREATE TABLE ".$schema.$table_name." (id NUMBER, value NUMBER, blob BLOB, clob CLOB, string VARCHAR(10))";
+ $statement = oci_parse($c, $ora_sql);
+ oci_execute($statement);
+ }
+?>
diff --git a/tests/create_type.inc b/tests/create_type.inc
new file mode 100644
index 0000000000..e23f7cb903
--- /dev/null
+++ b/tests/create_type.inc
@@ -0,0 +1,17 @@
+<?php
+
+ if ($c) {
+ $ora_sql = "DROP TYPE
+ ".$type_name."
+ ";
+
+ $statement = OCIParse($c,$ora_sql);
+ @OCIExecute($statement);
+
+ $ora_sql = "CREATE TYPE ".$type_name." AS TABLE OF NUMBER(11)";
+
+ $statement = OCIParse($c,$ora_sql);
+ OCIExecute($statement);
+ }
+
+?>
diff --git a/tests/cursor_bind.phpt b/tests/cursor_bind.phpt
new file mode 100644
index 0000000000..c2ce15cb38
--- /dev/null
+++ b/tests/cursor_bind.phpt
@@ -0,0 +1,99 @@
+--TEST--
+bind and fetch cursor from a statement
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$drop_table = "DROP TABLE ".$schema.$table_name."";
+
+if (!($s = oci_parse($c, $drop_table))) {
+ die("oci_parse(drop) failed!\n");
+}
+
+@oci_execute($s);
+
+$create_table = "CREATE TABLE ".$schema.$table_name." (id NUMBER, value VARCHAR(20))";
+
+if (!($s = oci_parse($c, $create_table))) {
+ die("oci_parse(create) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(create) failed!\n");
+}
+
+$insert_sql = "INSERT INTO ".$schema.$table_name." (id, value) VALUES (1,1)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+if (!oci_commit($c)) {
+ die("oci_commit() failed!\n");
+}
+
+
+$sql = "
+DECLARE
+TYPE curtype IS REF CURSOR;
+cursor_var curtype;
+BEGIN
+ OPEN cursor_var FOR SELECT id, value FROM ".$schema.$table_name.";
+ :curs := cursor_var;
+END;
+";
+
+$stmt = oci_parse($c, $sql);
+
+$cursor = oci_new_cursor($c);
+oci_bind_by_name($stmt, ":curs", $cursor, -1, OCI_B_CURSOR);
+
+oci_execute($stmt);
+
+oci_execute($cursor);
+var_dump(oci_fetch_row($cursor));
+var_dump(oci_fetch_row($cursor));
+var_dump(oci_fetch_row($cursor));
+var_dump(oci_fetch_row($cursor));
+
+echo "Done\n";
+
+$drop_table = "DROP TABLE ".$schema.$table_name."";
+
+if (!($s = oci_parse($c, $drop_table))) {
+ die("oci_parse(drop) failed!\n");
+}
+
+@oci_execute($s);
+
+?>
+--EXPECT--
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+bool(false)
+Done
diff --git a/tests/cursor_bind_err.phpt b/tests/cursor_bind_err.phpt
new file mode 100644
index 0000000000..33bd04b6d2
--- /dev/null
+++ b/tests/cursor_bind_err.phpt
@@ -0,0 +1,70 @@
+--TEST--
+binding a cursor (with errors)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table cursor_bind_err_tab",
+ "create table cursor_bind_err_tab (id number, value number)",
+ "insert into cursor_bind_err_tab (id, value) values (1,1)",
+ "insert into cursor_bind_err_tab (id, value) values (1,1)",
+ "insert into cursor_bind_err_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+$sql = "select cursor(select * from cursor_bind_err_tab) into :cursor from dual";
+$stmt = oci_parse($c, $sql);
+
+$cursor = oci_new_cursor($c);
+oci_bind_by_name($stmt, ":cursor", $cursor, -1, OCI_B_CURSOR);
+
+oci_execute($stmt);
+
+oci_execute($cursor);
+var_dump(oci_fetch_assoc($cursor));
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table cursor_bind_err_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: oci_bind_by_name(): ORA-01036: %s in %s on line %d
+
+Warning: oci_fetch_assoc(): ORA-24338: %s in %s on line %d
+bool(false)
+Done
diff --git a/tests/cursors.phpt b/tests/cursors.phpt
new file mode 100644
index 0000000000..22c89c9c54
--- /dev/null
+++ b/tests/cursors.phpt
@@ -0,0 +1,65 @@
+--TEST--
+fetching cursor from a statement
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__)."/create_table.inc";
+
+$insert_sql = "INSERT INTO ".$schema.$table_name." (id, value) VALUES (1,1)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+if (!oci_commit($c)) {
+ die("oci_commit() failed!\n");
+}
+
+$sql = "select CURSOR(select * from ".$schema.$table_name.") as curs FROM dual";
+$stmt = oci_parse($c, $sql);
+
+oci_execute($stmt);
+
+while ($data = oci_fetch_assoc($stmt)) {
+ oci_execute($data["CURS"]);
+ $subdata = oci_fetch_assoc($data["CURS"]);
+ var_dump($subdata);
+ var_dump(oci_cancel($data["CURS"]));
+ $subdata = oci_fetch_assoc($data["CURS"]);
+ var_dump($subdata);
+ var_dump(oci_cancel($data["CURS"]));
+}
+
+require dirname(__FILE__)."/drop_table.inc";
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+array(5) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ ["BLOB"]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+bool(true)
+
+Warning: oci_fetch_assoc(): ORA-01002: fetch out of sequence in %s on line %d
+bool(false)
+bool(true)
+Done
diff --git a/tests/cursors_old.phpt b/tests/cursors_old.phpt
new file mode 100644
index 0000000000..73447c82b4
--- /dev/null
+++ b/tests/cursors_old.phpt
@@ -0,0 +1,86 @@
+--TEST--
+fetching cursor from a statement
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table cursors_old_tab",
+ "create table cursors_old_tab (id number, value number)",
+ "insert into cursors_old_tab (id, value) values (1,1)",
+ "insert into cursors_old_tab (id, value) values (1,1)",
+ "insert into cursors_old_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+$sql = "select cursor(select * from cursors_old_tab) as curs from dual";
+$stmt = ociparse($c, $sql);
+
+ociexecute($stmt);
+
+while ($result = ocifetchinto($stmt, $data, OCI_ASSOC)) {
+ ociexecute($data["CURS"]);
+ ocifetchinto($data["CURS"], $subdata, OCI_ASSOC);
+ var_dump($subdata);
+ var_dump(ocicancel($data["CURS"]));
+ ocifetchinto($data["CURS"], $subdata, OCI_ASSOC);
+ var_dump($subdata);
+ var_dump(ocicancel($data["CURS"]));
+}
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table cursors_old_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(1) "1"
+}
+bool(true)
+
+Warning: ocifetchinto():%sORA-01002: %s in %scursors_old.php on line %d
+array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(1) "1"
+}
+bool(true)
+Done
diff --git a/tests/debug.phpt b/tests/debug.phpt
new file mode 100644
index 0000000000..49e3d4cfd1
--- /dev/null
+++ b/tests/debug.phpt
@@ -0,0 +1,71 @@
+--TEST--
+oci_internal_debug()
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$iv = preg_match('/Oracle .*Version => (11\.2|12\.)/', $phpinfo);
+if ($iv !== 1) {
+ die ("skip expected output only valid when using Oracle 11gR2+ client libraries");
+}
+?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/details.inc");
+
+oci_internal_debug(true);
+
+if (!empty($dbase)) {
+ oci_connect($user, $password, $dbase);
+}
+else {
+ oci_connect($user, $password);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+OCI8 DEBUG: OCINlsEnvironmentVariableGet at (%s:%d)
+OCI8 DEBUG L1: Got NO cached connection at (%s:%d)
+OCI8 DEBUG: OCIEnvNlsCreate at (%s:%d)
+OCI8 DEBUG: OCIHandleAlloc at (%s:%d)
+OCI8 DEBUG: OCIHandleAlloc at (%s:%d)
+OCI8 DEBUG: OCIHandleAlloc at (%s:%d)
+OCI8 DEBUG: OCIAttrSet at (%s:%d)
+OCI8 DEBUG: OCIAttrSet at (%s:%d)
+OCI8 DEBUG: OCISessionPoolCreate at (%s:%d)
+OCI8 DEBUG: OCIAttrSet at (%s:%d)
+OCI8 DEBUG: OCIHandleFree at (%s:%d)
+OCI8 DEBUG L1: create_spool: (%s:%d)
+OCI8 DEBUG L1: using shared pool: (%s:%d)
+OCI8 DEBUG: OCIHandleAlloc at (%s:%d)
+OCI8 DEBUG: OCIHandleAlloc at (%s:%d)
+OCI8 DEBUG: OCIAttrSet at (%s:%d)
+OCI8 DEBUG: OCIAttrSet at (%s:%d)
+OCI8 DEBUG: OCIAttrGet at (%s:%d)
+OCI8 DEBUG: OCIAttrGet at (%s:%d)
+OCI8 DEBUG L1: (numopen=0)(numbusy=0) at (%s:%d)
+OCI8 DEBUG: OCISessionGet at (%s:%d)
+OCI8 DEBUG: OCIAttrGet at (%s:%d)
+OCI8 DEBUG: OCIAttrGet at (%s:%d)
+OCI8 DEBUG: OCIContextGetValue at (%s:%d)
+OCI8 DEBUG: OCIContextGetValue at (%s:%d)
+OCI8 DEBUG: OCIMemoryAlloc at (%s:%d)
+OCI8 DEBUG: OCIContextSetValue at (%s:%d)
+OCI8 DEBUG: OCIAttrSet at (%s:%d)
+OCI8 DEBUG L1: New Non-Persistent Connection address: (%s) at (%s:%d)
+OCI8 DEBUG L1: num_persistent=(%s:%d)
+OCI8 DEBUG: OCISessionRelease at (%s:%d)
+OCI8 DEBUG: OCIHandleFree at (%s:%d)
+OCI8 DEBUG: OCIHandleFree at (%s:%d)
+Done
+OCI8 DEBUG: OCISessionPoolDestroy at (%s:%d)
+OCI8 DEBUG: OCIHandleFree at (%s:%d)
+OCI8 DEBUG: OCIHandleFree at (%s:%d)
+OCI8 DEBUG: OCIHandleFree at (%s:%d)
+OCI8 DEBUG: OCIHandleFree at (%s:%d)
+OCI8 DEBUG: OCIHandleFree at (%s:%d)
diff --git a/tests/default_prefetch.phpt b/tests/default_prefetch.phpt
new file mode 100644
index 0000000000..47191c8585
--- /dev/null
+++ b/tests/default_prefetch.phpt
@@ -0,0 +1,73 @@
+--TEST--
+oci8.default_prefetch ini option
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.default_prefetch=20
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table default_prefetch_tab",
+ "create table default_prefetch_tab (id number, value number)",
+ "insert into default_prefetch_tab (id, value) values (1,1)",
+ "insert into default_prefetch_tab (id, value) values (1,1)",
+ "insert into default_prefetch_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+$select_sql = "select * from default_prefetch_tab";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+var_dump(oci_fetch($s));
+
+var_dump(oci_num_rows($s));
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table default_prefetch_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+
+echo "Done\n";
+?>
+--EXPECT--
+bool(true)
+int(1)
+Done
diff --git a/tests/default_prefetch1.phpt b/tests/default_prefetch1.phpt
new file mode 100644
index 0000000000..bcd66fa381
--- /dev/null
+++ b/tests/default_prefetch1.phpt
@@ -0,0 +1,72 @@
+--TEST--
+oci8.default_prefetch ini option
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.default_prefetch=100
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table default_prefetch1_tab",
+ "create table default_prefetch1_tab (id number, value number)",
+ "insert into default_prefetch1_tab (id, value) values (1,1)",
+ "insert into default_prefetch1_tab (id, value) values (1,1)",
+ "insert into default_prefetch1_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+$select_sql = "select * from default_prefetch1_tab";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+var_dump(oci_fetch($s));
+var_dump(oci_num_rows($s));
+
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table default_prefetch1_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+bool(true)
+int(1)
+Done
diff --git a/tests/default_prefetch2.phpt b/tests/default_prefetch2.phpt
new file mode 100644
index 0000000000..7b3f29f296
--- /dev/null
+++ b/tests/default_prefetch2.phpt
@@ -0,0 +1,74 @@
+--TEST--
+oci8.default_prefetch ini option
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.default_prefetch=100
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table default_prefetch2_tab",
+ "create table default_prefetch2_tab (id number, value number)",
+ "insert into default_prefetch2_tab (id, value) values (1,1)",
+ "insert into default_prefetch2_tab (id, value) values (1,1)",
+ "insert into default_prefetch2_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+$select_sql = "select * from default_prefetch2_tab";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+var_dump(oci_set_prefetch($s, 10));
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+var_dump(oci_fetch($s));
+var_dump(oci_num_rows($s));
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table default_prefetch2_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+bool(true)
+bool(true)
+int(1)
+Done
diff --git a/tests/define.phpt b/tests/define.phpt
new file mode 100644
index 0000000000..d99bc7e1a6
--- /dev/null
+++ b/tests/define.phpt
@@ -0,0 +1,62 @@
+--TEST--
+oci_define_by_name()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table define_tab",
+ "create table define_tab (string varchar(10))",
+ "insert into define_tab (string) values ('some')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run test
+
+$stmt = oci_parse($c, "select string from define_tab");
+
+/* the define MUST be done BEFORE ociexecute! */
+
+$string = '';
+oci_define_by_name($stmt, "STRING", $string, 20);
+
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ var_dump($string);
+}
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table define_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+%unicode|string%(%d) "some"
+Done
diff --git a/tests/define1.phpt b/tests/define1.phpt
new file mode 100644
index 0000000000..341bc9ed83
--- /dev/null
+++ b/tests/define1.phpt
@@ -0,0 +1,73 @@
+--TEST--
+oci_define_by_name()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table define1_tab",
+ "create table define1_tab (string varchar(10))",
+ "insert into define1_tab (string) values ('some')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run test
+
+$stmt = oci_parse($c, "select string from define1_tab");
+
+/* the define MUST be done BEFORE ociexecute! */
+
+$string = '';
+var_dump(oci_define_by_name($stmt, "STRING", $string, 20));
+var_dump(oci_define_by_name($stmt, "STRING", $string, 20));
+var_dump(oci_define_by_name($stmt, "", $string, 20));
+var_dump(oci_define_by_name($stmt, ""));
+
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ var_dump($string);
+}
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table define1_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+bool(true)
+bool(false)
+
+Warning: oci_define_by_name(): Column name cannot be empty in %s on line %d
+bool(false)
+
+Warning: oci_define_by_name() expects at least 3 parameters, 2 given in %s on line %d
+NULL
+%unicode|string%(4) "some"
+Done
diff --git a/tests/define2.phpt b/tests/define2.phpt
new file mode 100644
index 0000000000..46e11bf886
--- /dev/null
+++ b/tests/define2.phpt
@@ -0,0 +1,94 @@
+--TEST--
+Test oci_define_by_name types
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+$stmtarray = array(
+ "drop table phptestrawtable",
+ "create table phptestrawtable( id number(10), fileimage raw(1000))"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+$stmt = oci_parse ($c, "insert into phptestrawtable (id, fileimage) values (:id, :fileimage)");
+$i=1;
+$fileimage = file_get_contents( dirname(__FILE__)."/test.gif");
+$fileimage = substr($fileimage, 0, 300);
+var_dump(md5($fileimage));
+
+oci_bind_by_name( $stmt, ":id", $i, -1);
+oci_bind_by_name( $stmt, ":fileimage", $fileimage, -1, SQLT_BIN);
+oci_execute($stmt, OCI_DEFAULT);
+oci_commit($c);
+
+echo "Test 1\n";
+$stmt = oci_parse($c, "SELECT fileimage FROM phptestrawtable");
+var_dump(oci_define_by_name($stmt, 'FILEIMAGE', $fi));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ var_dump($fi);
+ echo "file md5:" . md5($fi) . "\n";
+}
+
+echo "Test 2\n";
+$stmt = oci_parse($c, "SELECT fileimage FROM phptestrawtable");
+var_dump(oci_define_by_name($stmt, 'FILEIMAGE', $fi));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ var_dump($fi);
+ echo "file md5:" . md5($fi) . "\n";
+}
+
+echo "Test 3 - test repeatability\n";
+$stmt = oci_parse($c, "SELECT fileimage FROM phptestrawtable");
+var_dump(oci_define_by_name($stmt, 'FILEIMAGE', $fi, SQLT_STR));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ var_dump($fi);
+ echo "file md5:" . md5($fi) . "\n";
+}
+
+echo "Test 4 - wrong type\n";
+$stmt = oci_parse($c, "SELECT fileimage FROM phptestrawtable");
+var_dump(oci_define_by_name($stmt, 'FILEIMAGE', $fi, SQLT_RSET));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ var_dump($fi);
+ echo "file md5:" . md5($fi) . "\n";
+}
+
+$stmt = oci_parse($c, "drop table phptestrawtable");
+oci_execute($stmt);
+
+echo "Done\n";
+?>
+--EXPECTF--
+string(32) "88b274d7a257ac6f70435b83abd4e26e"
+Test 1
+bool(true)
+string(300) "GIF89%s"
+file md5:88b274d7a257ac6f70435b83abd4e26e
+Test 2
+bool(true)
+string(300) "GIF89%s"
+file md5:88b274d7a257ac6f70435b83abd4e26e
+Test 3 - test repeatability
+bool(true)
+string(600) "47494638396178004300E66A007F82B839374728252ACCCDE2A1A4CBD3D5E7B2B4D44342588386B98283B35252729092C2C2C4DEAAACD04C4B635B5C83DDDEEC3B383C6E71A56A6D9D61638D7579B17B7EB5E5E6F0999CC68C8DC1B9BAD96B6B924E4E6B7174A97A7AA3888BBD7274A37473988E90C15A5B7EE2E3EF7B7DADA4A5D06D70A27276AC9596C8BBBDD97478AE8588BB9295C3D8D9EA9292C46466926B6E9FA5A8CE9496C52E2B2F535168B3B4D76C6A8C5C5B768A8DBF666896686A9A9C9FC8312E39AEB0D39C9CCD5556789EA1CA9699C58182AF6769973F3D50BCBEDA5E60899899C88C8EBF898ABA57587CB6B7D7D5D7E8221E206C6F9ECED0E4BFC0DC777BB47678A75F5E7D9999CC6E6F987377AE221E1FFFFFFF908E8F595657C7C6C7EEEEF5D5D4D5F6F6"
+file md5:80bb3201e2a8bdcb8ab3e1a44a82bb8a
+Test 4 - wrong type
+bool(true)
+
+Warning: oci_fetch(): ORA-00932: inconsistent datatypes%s on line %d
+Done
diff --git a/tests/define3.phpt b/tests/define3.phpt
new file mode 100644
index 0000000000..892e8e3809
--- /dev/null
+++ b/tests/define3.phpt
@@ -0,0 +1,112 @@
+--TEST--
+Test oci_define_by_name() LOB descriptor
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+$stmtarray = array(
+ "drop table phpdefblobtable",
+ "create table phpdefblobtable (id number(10), fileimage blob)"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+// Load data
+$stmt = oci_parse ($c, "insert into phpdefblobtable (id, fileimage) values (:id, empty_blob()) returning fileimage into :fileimage");
+$fileimage = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($stmt,":id",$id);
+oci_bind_by_name($stmt,":fileimage",$fileimage,-1,OCI_B_BLOB);
+$id = 1;
+oci_execute($stmt, OCI_DEFAULT);
+$fileimage->savefile(dirname(__FILE__)."/test.gif");
+$data = $fileimage->load();
+var_dump(md5($data)); // original md5
+oci_commit($c);
+
+// New row with different data
+$id = 2;
+$data = strrev($data);
+var_dump(md5($data));
+oci_execute($stmt, OCI_DEFAULT);
+$fileimage->save($data);
+oci_commit($c);
+
+echo "Test 1\n";
+$stmt = oci_parse($c, "SELECT fileimage FROM phpdefblobtable");
+var_dump(oci_define_by_name($stmt, 'FILEIMAGE', $f));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ var_dump($f);
+ echo "file md5:" . md5($f->load()) . "\n";
+}
+
+echo "Test 2\n";
+$stmt = oci_parse($c, "SELECT fileimage FROM phpdefblobtable");
+var_dump(oci_define_by_name($stmt, 'FILEIMAGE', $outdata, SQLT_STR));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ echo "file md5:" . md5($outdata) . "\n";
+}
+
+echo "Test 3\n";
+$stmt = oci_parse($c, "SELECT fileimage FROM phpdefblobtable");
+var_dump(oci_define_by_name($stmt, 'FILEIMAGE', $outdata, SQLT_BIN));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ echo "file md5:" . md5($outdata) . "\n";
+}
+
+echo "Test 4\n";
+$fid = oci_new_descriptor($c,OCI_D_LOB);
+$stmt = oci_parse($c, "SELECT fileimage FROM phpdefblobtable");
+var_dump(oci_define_by_name($stmt, 'FILEIMAGE', $fid));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ echo "file md5:" . md5($fid->load()) . "\n";
+}
+
+$stmt = oci_parse($c, "drop table phpdefblobtable");
+oci_execute($stmt);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+string(32) "614fcbba1effb7caa27ef0ef25c27fcf"
+string(32) "06d4f219d946c74d748d43932cd9dcb2"
+Test 1
+bool(true)
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+file md5:614fcbba1effb7caa27ef0ef25c27fcf
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+file md5:06d4f219d946c74d748d43932cd9dcb2
+Test 2
+bool(true)
+
+Warning: oci_fetch(): ORA-00932: %s on line %d
+Test 3
+bool(true)
+file md5:614fcbba1effb7caa27ef0ef25c27fcf
+file md5:06d4f219d946c74d748d43932cd9dcb2
+Test 4
+bool(true)
+file md5:614fcbba1effb7caa27ef0ef25c27fcf
+file md5:06d4f219d946c74d748d43932cd9dcb2
+Done
+
diff --git a/tests/define4.phpt b/tests/define4.phpt
new file mode 100644
index 0000000000..8d83f73ac3
--- /dev/null
+++ b/tests/define4.phpt
@@ -0,0 +1,88 @@
+--TEST--
+oci_define_by_name() on partial number of columns
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table define4_tab",
+ "create table define4_tab (value number, string varchar(10))",
+ "insert into define4_tab (value, string) values (1234, 'some')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run test
+
+$stmt = oci_parse($c, "select value, string from define4_tab");
+
+echo "Test 1\n";
+// Only one of the two columns is defined
+var_dump(oci_define_by_name($stmt, "STRING", $string));
+
+oci_execute($stmt);
+
+echo "Test 2\n";
+
+while (oci_fetch($stmt)) {
+ var_dump(oci_result($stmt, 'VALUE'));
+ var_dump($string);
+ var_dump(oci_result($stmt, 'STRING'));
+ var_dump($string);
+ var_dump(oci_result($stmt, 'VALUE'));
+ var_dump(oci_result($stmt, 'STRING'));
+}
+
+echo "Test 3\n";
+var_dump(oci_free_statement($stmt));
+var_dump($string);
+var_dump(oci_result($stmt, 'STRING'));
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table define4_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+bool(true)
+Test 2
+%unicode|string%(4) "1234"
+%unicode|string%(4) "some"
+%unicode|string%(4) "some"
+%unicode|string%(4) "some"
+%unicode|string%(4) "1234"
+%unicode|string%(4) "some"
+Test 3
+bool(true)
+%unicode|string%(4) "some"
+
+Warning: oci_result(): %d is not a valid oci8 statement resource in %s on line %d
+bool(false)
+Done
+
diff --git a/tests/define5.phpt b/tests/define5.phpt
new file mode 100644
index 0000000000..63541ce9dd
--- /dev/null
+++ b/tests/define5.phpt
@@ -0,0 +1,86 @@
+--TEST--
+oci_define_by_name() for statement re-execution
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table define5_tab",
+ "create table define5_tab (id number, string varchar(10))",
+ "insert into define5_tab (id, string) values (1, 'some')",
+ "insert into define5_tab (id, string) values (2, 'thing')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run test
+
+echo "Test 1 - must do define before execute\n";
+$stmt = oci_parse($c, "select string from define5_tab where id = 1");
+oci_execute($stmt);
+var_dump(oci_define_by_name($stmt, "STRING", $string));
+while (oci_fetch($stmt)) {
+ var_dump($string); // gives NULL
+ var_dump(oci_result($stmt, 'STRING'));
+}
+
+echo "Test 2 - normal define order\n";
+$stmt = oci_parse($c, "select string from define5_tab where id = 1");
+var_dump(oci_define_by_name($stmt, "STRING", $string));
+oci_execute($stmt);
+
+while (oci_fetch($stmt)) {
+ var_dump($string);
+}
+
+echo "Test 3 - no new define done\n";
+$stmt = oci_parse($c, "select string from define5_tab where id = 2");
+oci_execute($stmt);
+while (oci_fetch($stmt)) {
+ var_dump($string); // not updated with new value
+ var_dump(oci_result($stmt, 'STRING'));
+}
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table define5_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1 - must do define before execute
+bool(true)
+NULL
+%unicode|string%(4) "some"
+Test 2 - normal define order
+bool(true)
+%unicode|string%(4) "some"
+Test 3 - no new define done
+%unicode|string%(4) "some"
+%unicode|string%(5) "thing"
+Done
+
diff --git a/tests/define_old.phpt b/tests/define_old.phpt
new file mode 100644
index 0000000000..618f9d5f57
--- /dev/null
+++ b/tests/define_old.phpt
@@ -0,0 +1,63 @@
+--TEST--
+ocidefinebyname()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table define_old_tab",
+ "create table define_old_tab (string varchar(10))",
+ "insert into define_old_tab (string) values ('some')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run test
+
+$stmt = ociparse($c, "select string from define_old_tab");
+
+/* the define MUST be done BEFORE ociexecute! */
+
+$string = '';
+ocidefinebyname($stmt, "STRING", $string, 20);
+
+ociexecute($stmt);
+
+while (ocifetch($stmt)) {
+ var_dump($string);
+}
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table define_old_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+%unicode|string%(4) "some"
+Done
diff --git a/tests/descriptors.phpt b/tests/descriptors.phpt
new file mode 100644
index 0000000000..8be4f3a06d
--- /dev/null
+++ b/tests/descriptors.phpt
@@ -0,0 +1,49 @@
+--TEST--
+commit connection after destroying the descriptor
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+unset($blob);
+unset($statement);
+
+oci_commit($c);
+
+$ora_sql = "SELECT blob FROM ".$schema.$table_name." ";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_assoc($statement));
+unset($row['BLOB']);
+
+oci_commit($c);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECTF--
+array(1) {
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+Done
diff --git a/tests/details.inc b/tests/details.inc
new file mode 100644
index 0000000000..922b8c4f49
--- /dev/null
+++ b/tests/details.inc
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * Please change $user, $password and $dbase to match your configuration.
+ *
+ * Set $oracle_on_localhost to TRUE if the Oracle Database is
+ * installed on your localhost.
+ *
+ * Set $test_drcp to TRUE if you want to run the Oracle Database
+ * Resident Connection Pooling (DRCP) tests. For these tests to run
+ * successfully, you need a server and client which is Oracle 11g or
+ * greater, and $dbase should be set to the tnsnames.ora entry
+ * corresponding to the POOLED server instance or an Easy Connect
+ * string like hostname:port/service_name:POOLED
+ *
+ * Set $stress_test to TRUE if you want to run some longer/slower/more
+ * memory intensive tests.
+ */
+
+if (file_exists(dirname(__FILE__)."/details_local.inc")) {
+ include(dirname(__FILE__)."/details_local.inc"); // this file is not part of the source distribution; make it your own local variant of details.inc
+} else {
+ if (false !== getenv('PHP_OCI8_TEST_DB')) {
+ $user = getenv('PHP_OCI8_TEST_USER'); // Database username for tests
+ $password = getenv('PHP_OCI8_TEST_PASS'); // Password for $user
+ $dbase = getenv('PHP_OCI8_TEST_DB'); // Database connection string
+ $test_drcp = getenv('PHP_OCI8_TEST_DRCP');
+ if (false !== $test_drcp && 0 == strcasecmp($test_drcp,'TRUE')) {
+ $test_drcp = TRUE;
+ } else {
+ $test_drcp = FALSE;
+ }
+ $oracle_on_localhost = getenv('PHP_OCI8_TEST_DB_ON_LOCALHOST');
+ if (false !== $oracle_on_localhost && 0 == strcasecmp($oracle_on_localhost,'TRUE')) {
+ $oracle_on_localhost = TRUE;
+ } else {
+ $oracle_on_localhost = FALSE;
+ }
+ $stress_test = getenv('PHP_OCI8_STRESS_TEST');
+ if (false !== $stress_test && 0 == strcasecmp($stress_test,'TRUE')) {
+ $stress_test = TRUE;
+ } else {
+ $stress_test = FALSE;
+ }
+ } else {
+ $user = "system";
+ $password = "oracle";
+ $dbase = "localhost/XE";
+ $oracle_on_localhost = TRUE;
+ $test_drcp = FALSE;
+ $stress_test = FALSE;
+ }
+
+ /*
+ * Common object names for scripts to use
+ */
+
+ $table_name = "tb".substr(str_replace(Array(".", "-"), "_", php_uname("n")), 0, 5);
+ $type_name = strtoupper("tp".substr(str_replace(Array(".", "-"), "_", php_uname("n")), 0, 5));
+ $schema = '';
+}
+
+?>
diff --git a/tests/drcp_cclass1.phpt b/tests/drcp_cclass1.phpt
new file mode 100644
index 0000000000..068331e5a9
--- /dev/null
+++ b/tests/drcp_cclass1.phpt
@@ -0,0 +1,80 @@
+--TEST--
+DRCP: Test setting connection class inline
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__)."/details.inc");
+if (!$test_drcp) die("skip testing DRCP connection class only works in DRCP mode");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/details.inc");
+
+// Initialization
+
+$t = time();
+$cc1 = 'cc1_'.$t;
+$cc2 = 'cc2_'.$t;
+
+// Run Test
+
+echo "Test 1\n";
+
+ini_set('oci8.connection_class', $cc1);
+$c = oci_pconnect($user, $password, $dbase);
+$s = oci_parse($c, "select * from dual");
+oci_execute($s);
+oci_fetch_all($s, $r);
+var_dump($r);
+
+echo "Test 2\n";
+
+ini_set('oci8.connection_class', $cc2);
+$c = oci_pconnect($user, $password, $dbase);
+$s = oci_parse($c, "select * from dual");
+oci_execute($s);
+oci_fetch_all($s, $r);
+var_dump($r);
+
+echo "Test 3\n";
+
+$s = oci_parse($c, "select cclass_name from v\$cpool_cc_stats where cclass_name like '%.cc__$t' order by cclass_name");
+oci_execute($s);
+oci_fetch_all($s, $r);
+var_dump($r);
+
+// Cleanup
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+array(1) {
+ ["DUMMY"]=>
+ array(1) {
+ [0]=>
+ string(1) "X"
+ }
+}
+Test 2
+array(1) {
+ ["DUMMY"]=>
+ array(1) {
+ [0]=>
+ string(1) "X"
+ }
+}
+Test 3
+array(1) {
+ ["CCLASS_NAME"]=>
+ array(2) {
+ [0]=>
+ string(21) "%s.cc1_%d"
+ [1]=>
+ string(21) "%s.cc2_%d"
+ }
+}
+Done
diff --git a/tests/drcp_characterset.phpt b/tests/drcp_characterset.phpt
new file mode 100644
index 0000000000..657d4c5bab
--- /dev/null
+++ b/tests/drcp_characterset.phpt
@@ -0,0 +1,61 @@
+--TEST--
+DRCP: oci_pconnect() and oci_connect() with different character sets
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+
+// Create connections with oci_connect and oci_pconnect with UTF8 as Charset
+
+$c1 = oci_connect($user,$password,$dbase,"UTF8");
+var_dump($c1);
+
+// Now with oci_pconnect()
+
+$p1 = oci_pconnect($user,$password,$dbase,"UTF8");
+var_dump($p1);
+
+// Create two more connections with character set US7ASCII
+
+$c2 = oci_connect($user,$password,$dbase,"US7ASCII");
+var_dump($c2);
+
+// Now with oci_pconnect()
+
+$p2 = oci_pconnect($user,$password,$dbase,"US7ASCII");
+var_dump($p2);
+
+// The two connections c1 and c2 should not share resources as they use different
+//character sets
+
+if((int)$c1 === (int)$c2)
+ echo "First and third connections share a resource: NOT OK\n";
+else
+ echo "First and third connections are different: OK\n";
+
+// The two connections p1 and p2 should not share resources as they use different
+//character sets
+
+if((int)$p1 === (int)$p2)
+ echo "Second and fourth connections share a resource: NOT OK\n";
+else
+ echo "Second and fourth connections are different: OK\n";
+
+// Close all the connections
+oci_close($c1);
+oci_close($c2);
+oci_close($p1);
+oci_close($p2);
+
+echo "Done\n";
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 persistent connection)
+First and third connections are different: OK
+Second and fourth connections are different: OK
+Done
diff --git a/tests/drcp_conn_close1.phpt b/tests/drcp_conn_close1.phpt
new file mode 100644
index 0000000000..697b7e3575
--- /dev/null
+++ b/tests/drcp_conn_close1.phpt
@@ -0,0 +1,45 @@
+--TEST--
+DRCP: oci_connect() with oci_close() and oci8.old_oci_close_semantics ON
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+oci8.connection_class=test
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+
+// Test will open a connection
+// Close the connection
+// Open another connection
+// With oci_close() being a no-op, the same conneciton will be returned
+
+
+echo "This is with a OCI_CONNECT\n";
+var_dump($conn1 = oci_connect($user,$password,$dbase));
+$rn1 = (int)$conn1;
+oci_close($conn1);
+
+// Open another connection
+
+var_dump($conn2 = oci_connect($user,$password,$dbase));
+$rn2 = (int)$conn2;
+oci_close($conn2);
+
+// Compare the resource numbers
+
+if ($rn1 === $rn2)
+ echo "Both connections share a resource : OK \n";
+else
+ echo "Both connections are different : NOT OK \n";
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_CONNECT
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+Both connections share a resource : OK
+Done
diff --git a/tests/drcp_conn_close2.phpt b/tests/drcp_conn_close2.phpt
new file mode 100644
index 0000000000..0d3f8247f2
--- /dev/null
+++ b/tests/drcp_conn_close2.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DRCP: oci_connect() with oci_close() and oci8.old_oci_close_semantics OFF
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+oci8.connection_class=test
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+
+// Test will open a connection
+// Close the connection
+// Open another connection
+// With oci_close() the connection is released to the pool and hence the
+// the second conneciton will be different
+
+
+// OCI_CONNECT
+echo "This is with a OCI_CONNECT\n";
+var_dump($conn1 = oci_connect($user,$password,$dbase));
+$rn1 = (int)$conn1;
+oci_close($conn1);
+
+// Open another connection
+var_dump($conn2 = oci_connect($user,$password,$dbase));
+$rn2 = (int)$conn2;
+oci_close($conn2);
+
+// Compare the resource numbers
+
+if ($rn1 === $rn2)
+ echo "Both connections share a resource : NOT OK \n";
+else
+ echo "Both connections are different : OK \n";
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_CONNECT
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+Both connections are different : OK
+Done
diff --git a/tests/drcp_connect1.phpt b/tests/drcp_connect1.phpt
new file mode 100644
index 0000000000..bf619a4efd
--- /dev/null
+++ b/tests/drcp_connect1.phpt
@@ -0,0 +1,86 @@
+--TEST--
+DRCP: oci_connect()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.connection_class=test
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+require dirname(__FILE__)."/drcp_functions.inc";
+
+// Open a number of connections with oci_connect and oci_pconnect and verify
+// whether we get a used session with DRCP.
+// To verify this, we change the value of a PL/SQL package variable in one
+// session and query for this through another connection
+
+var_dump($conn1 = oci_connect($user,$password,$dbase));
+// Create the package
+drcp_create_package($conn1);
+
+// OCI_CONNECT
+echo " This is with OCI_CONNECT.....\n";
+drcp_select_packagevar($conn1); // Returns 0
+drcp_set_packagevar($conn1,1000);
+oci_close($conn1);
+echo " Connection conn1 closed....\n";
+
+// Second connection should return 0 for the package variable.
+var_dump($conn2 = oci_connect($user,$password,$dbase));
+echo " Select with connection 2 \n";
+drcp_select_packagevar($conn2); // Returns 0
+drcp_set_packagevar($conn2,100);
+
+// Third connection. There is no oci_close() for conn2 hence this should
+// return the value set by conn2.
+var_dump($conn3 = oci_connect($user,$password,$dbase));
+echo " Select with connection 3 \n";
+drcp_select_packagevar($conn3); // Returns 100
+
+// Close all the connections
+oci_close($conn2);
+oci_close($conn3);
+
+// OCI_PCONNECT
+echo "\n This is with oci_pconnect().....\n";
+var_dump($pconn1 = oci_pconnect($user,$password,$dbase));
+drcp_set_packagevar($pconn1,1000);
+oci_close($pconn1);
+echo " Connection pconn1 closed....\n";
+
+// Second connection with oci_pconnect should return the same session hence the
+// value returned is what is set by pconn1
+
+var_dump($pconn2 = oci_pconnect($user,$password,$dbase));
+echo " Select with persistent connection 2 \n";
+drcp_select_packagevar($pconn2); // Returns 1000
+oci_close($pconn2);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+ This is with OCI_CONNECT.....
+ The value of the package variable is 0
+ Package variable value set to 1000
+ Connection conn1 closed....
+resource(%d) of type (oci8 connection)
+ Select with connection 2
+ The value of the package variable is 0
+ Package variable value set to 100
+resource(%d) of type (oci8 connection)
+ Select with connection 3
+ The value of the package variable is 100
+
+ This is with oci_pconnect().....
+resource(%d) of type (oci8 persistent connection)
+ Package variable value set to 1000
+ Connection pconn1 closed....
+resource(%d) of type (oci8 persistent connection)
+ Select with persistent connection 2
+ The value of the package variable is 1000
+Done
+
diff --git a/tests/drcp_connection_class.phpt b/tests/drcp_connection_class.phpt
new file mode 100644
index 0000000000..2aed131c14
--- /dev/null
+++ b/tests/drcp_connection_class.phpt
@@ -0,0 +1,24 @@
+--TEST--
+DRCP: oci8.connection_class with ini_get() and ini_set()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.connection_class=test
+--FILE--
+<?php
+
+echo "Setting a new connection class now\n";
+ini_set('oci8.connection_class',"New cc");
+
+// Get the New connection class name .Should return New CC
+
+$new_cc = ini_get('oci8.connection_class');
+echo "The New oci8.connection_class is $new_cc \n";
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Setting a new connection class now
+The New oci8.connection_class is New cc
+Done
diff --git a/tests/drcp_functions.inc b/tests/drcp_functions.inc
new file mode 100644
index 0000000000..26adb21f35
--- /dev/null
+++ b/tests/drcp_functions.inc
@@ -0,0 +1,93 @@
+<?php
+
+/* This file contains functions required by the DRCP tests */
+
+function drcp_create_table($conn)
+{
+ $create_sql = "CREATE TABLE DRCPTEST (id NUMBER, name VARCHAR2(10), dept VARCHAR2(10))";
+ $statement = oci_parse($conn, $create_sql);
+ oci_execute($statement);
+
+ $id_values = array(100,101,102,103,104,105,106,107,108);
+ $name_values = array("WIILIAMS","JOHN","SMITH","JONES","ADAMS","ROBERT",
+ "BILL","LAWSON","MARY");
+ $dept_values = array("ACCOUNTS","HR","HR","ADMIN","ACCOUNTS","HR",
+ "ACCOUNTS","HR","ACCOUNTS");
+ for($i=0; $i<8; $i++) {
+ $insert = "INSERT INTO DRCPTEST VALUES('".$id_values[$i]."','". $name_values[$i]."','".$dept_values[$i]."')";
+ $s = oci_parse($conn, $insert);
+ oci_execute($s);
+ }
+}
+
+function drcp_drop_table($conn)
+{
+ $ora_sql = "DROP TABLE DRCPTEST";
+ $statement = oci_parse($conn, $ora_sql);
+ oci_execute($statement);
+}
+
+function drcp_update_table($conn)
+{
+ $update_stmt ="Update drcptest set dept ='NEWDEPT' where id = 105";
+ $s1 = oci_parse($conn,$update_stmt);
+ oci_execute($s1,OCI_DEFAULT);
+ echo "Update done-- DEPT value has been set to NEWDEPT\n";
+}
+
+function drcp_select_value($conn)
+{
+ $sel_stmt="select dept from drcptest where id=105";
+ $s2 = oci_parse($conn,$sel_stmt);
+ oci_execute($s2,OCI_DEFAULT);
+ while(oci_fetch($s2)) {
+ echo "The value of DEPT for id 105 is ".oci_result($s2,1)."\n";
+ }
+}
+
+function drcp_select_packagevar($conn)
+{
+ $sel_stmt="select drcp_test_package.f1 as f1 from dual";
+ $s2 = oci_parse($conn, $sel_stmt);
+ oci_define_by_name($s2,'f1',$ret_num);
+ oci_execute($s2);
+ while(oci_fetch($s2)) {
+ echo " The value of the package variable is ".oci_result($s2,1)."\n";
+ }
+}
+
+
+function drcp_set_packagevar($conn,$num)
+{
+ $set_stmt = "begin drcp_test_package.p1($num); end;";
+ $s1 = oci_parse($conn,$set_stmt);
+ oci_execute($s1);
+ echo " Package variable value set to " .$num."\n";
+}
+
+function drcp_create_package($c)
+{
+ $create_package_stmt = "create or replace package drcp_test_package as
+ var int :=0;
+ procedure p1(var1 int);
+ function f1 return number;
+ end;";
+ $s1 = oci_parse($c, $create_package_stmt);
+ oci_execute($s1);
+
+ $package_body = "create or replace package body drcp_test_package as
+ procedure p1(var1 int) is
+ begin
+ var :=var1;
+ end;
+ function f1 return number is
+ begin
+ return drcp_test_package.var;
+ end;
+ end;";
+
+ $s2 = oci_parse($c, $package_body);
+ oci_execute($s2);
+}
+
+?>
diff --git a/tests/drcp_newconnect.phpt b/tests/drcp_newconnect.phpt
new file mode 100644
index 0000000000..79718f4ee2
--- /dev/null
+++ b/tests/drcp_newconnect.phpt
@@ -0,0 +1,43 @@
+--TEST--
+DRCP: oci_new_connect()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.connection_class=test
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+
+// Open two connections with oci_new_connect
+// Verify they are different by comparing the resource ids
+
+var_dump($c1 = oci_new_connect($user,$password,$dbase));
+$rn1 = (int)$c1;
+
+// Another connection now
+
+var_dump($c2 = oci_new_connect($user,$password,$dbase));
+$rn2 = (int)$c2;
+
+// rn1 and rn2 should be different.
+
+if ($rn1 === $rn2)
+ echo "First and second connections share a resource: Not OK\n";
+else
+ echo "First and second connections are different OK\n";
+
+// Close the connections
+oci_close($c1);
+oci_close($c2);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+First and second connections are different OK
+Done
+
diff --git a/tests/drcp_pconn_close1.phpt b/tests/drcp_pconn_close1.phpt
new file mode 100644
index 0000000000..a9b912b26f
--- /dev/null
+++ b/tests/drcp_pconn_close1.phpt
@@ -0,0 +1,44 @@
+--TEST--
+DRCP: oci_pconnect() with oci_close() and oci8.old_oci_close_semantics ON
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+oci8.connection_class=test
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+
+// Test will open a persistent connection
+// Close the connection
+// Open another connection
+// With oci_close() being a no-op, the same conneciton will be returned
+
+echo "This is with a OCI_PCONNECT\n";
+var_dump($conn1 = oci_pconnect($user,$password,$dbase));
+$rn1 = (int)$conn1;
+oci_close($conn1);
+
+// Open another connection
+
+var_dump($conn2 = oci_pconnect($user,$password,$dbase));
+$rn2 = (int)$conn2;
+oci_close($conn2);
+
+// Compare the resource numbers
+
+if ($rn1 === $rn2)
+ echo "Both connections share a resource : OK \n";
+else
+ echo "Both connections are different : NOT OK \n";
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_PCONNECT
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 persistent connection)
+Both connections share a resource : OK
+Done
diff --git a/tests/drcp_pconn_close2.phpt b/tests/drcp_pconn_close2.phpt
new file mode 100644
index 0000000000..5fd2c2355f
--- /dev/null
+++ b/tests/drcp_pconn_close2.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DRCP: oci_pconnect() with oci_close() and oci8.old_oci_close_semantics OFF
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+oci8.connection_class=test
+--FILE--
+<?php
+
+require dirname(__FILE__)."/details.inc";
+
+// Test will open a persistent connection
+// Close the connection
+// Open another connection
+// With oci_close() the connection is released to the pool and hence the
+// the second connection will be different
+
+
+echo "This is with a OCI_PCONNECT\n";
+var_dump($conn1 = oci_pconnect($user,$password,$dbase));
+$rn1 = (int)$conn1;
+oci_close($conn1);
+
+// Query for the row updated. The new value should be returned
+
+var_dump($conn2 = oci_pconnect($user,$password,$dbase));
+$rn2 = (int)$conn2;
+oci_close($conn2);
+
+// Compare the resource numbers
+
+if ($rn1 === $rn2)
+ echo "Both connections share a resource : NOT OK \n";
+else
+ echo "Both connections are different : OK \n";
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_PCONNECT
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 persistent connection)
+Both connections are different : OK
+Done
diff --git a/tests/drcp_privileged.phpt b/tests/drcp_privileged.phpt
new file mode 100644
index 0000000000..9af20625ed
--- /dev/null
+++ b/tests/drcp_privileged.phpt
@@ -0,0 +1,47 @@
+--TEST--
+DRCP: privileged connect
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+require(dirname(__FILE__)."/details.inc");
+if (empty($oracle_on_localhost)) die("skip this test is unlikely to work with remote Oracle - unless an Oracle password file has been created");
+?>
+--INI--
+oci8.privileged_connect=1
+--FILE--
+<?php
+
+// Connecting as SYSDBA or SYSOPER through DRCP will give ORA-1031
+
+require dirname(__FILE__)."/details.inc";
+var_dump(oci_connect($user,$password,$dbase,false,OCI_SYSDBA));
+var_dump(oci_connect($user,$password,$dbase,false,OCI_SYSOPER));
+var_dump(oci_new_connect($user,$password,$dbase,false,OCI_SYSDBA));
+var_dump(oci_new_connect($user,$password,$dbase,false,OCI_SYSOPER));
+var_dump(oci_pconnect($user,$password,$dbase,false,OCI_SYSDBA));
+var_dump(oci_pconnect($user,$password,$dbase,false,OCI_SYSOPER));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: oci_connect(): ORA-01031: insufficient privileges in %s on line %d
+bool(false)
+
+Warning: oci_connect(): ORA-01031: insufficient privileges in %s on line %d
+bool(false)
+
+Warning: oci_new_connect(): ORA-01031: insufficient privileges in %s on line %d
+bool(false)
+
+Warning: oci_new_connect(): ORA-01031: insufficient privileges in %s on line %d
+bool(false)
+
+Warning: oci_pconnect(): ORA-01031: insufficient privileges in %s on line %d
+bool(false)
+
+Warning: oci_pconnect(): ORA-01031: insufficient privileges in %s on line %d
+bool(false)
+Done
+
diff --git a/tests/drcp_scope1.phpt b/tests/drcp_scope1.phpt
new file mode 100644
index 0000000000..57f1abe327
--- /dev/null
+++ b/tests/drcp_scope1.phpt
@@ -0,0 +1,92 @@
+--TEST--
+DRCP: oci_new_connect() and oci_connect() with scope end when oci8.old_oci_close_semantics ON
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require dirname(__FILE__)."/drcp_functions.inc";
+require dirname(__FILE__)."/details.inc";
+
+// Scope considered here is the functional scope
+// Test will open a connection within a function (function 1).
+// Update a table
+// Open another connection from function 2.
+// When the scope ends the txn is rolled back and hence the updated value
+// will not be reflected for oci_connect and oci_new_connect.
+
+// Create the table
+$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
+drcp_create_table($c);
+
+// OCI_NEW_CONNECT
+$conn_type = 1;
+echo "This is with a OCI_NEW_CONNECT\n";
+function1($user,$password,$dbase,$conn_type);
+
+// Should return the OLD value
+function2($user,$password,$dbase,$conn_type);
+
+// OCI_CONNECT
+$conn_type = 2;
+echo "\n\nThis is with a OCI_CONNECT\n";
+function1($user,$password,$dbase,$conn_type);
+
+// Should return the OLD value
+function2($user,$password,$dbase,$conn_type);
+
+//This is the first scope for the script
+
+function function1($user,$password,$dbase,$conn_type)
+{
+ switch($conn_type)
+ {
+ case 1:
+ var_dump($conn1 = oci_new_connect($user,$password,$dbase));
+ break;
+ case 2:
+ var_dump($conn1 = oci_connect($user,$password,$dbase));
+ break;
+ }
+ drcp_update_table($conn1);
+}
+
+// This is the second scope
+
+function function2($user,$password,$dbase,$conn_type)
+{
+ switch($conn_type)
+ {
+ case 1:
+ var_dump($conn1 = oci_new_connect($user,$password,$dbase));
+ break;
+ case 2:
+ var_dump($conn1 = oci_connect($user,$password,$dbase));
+ break;
+ }
+ drcp_select_value($conn1);
+}
+
+drcp_drop_table($c);
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_NEW_CONNECT
+resource(%d) of type (oci8 connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 connection)
+The value of DEPT for id 105 is HR
+
+
+This is with a OCI_CONNECT
+resource(%d) of type (oci8 connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 connection)
+The value of DEPT for id 105 is HR
+Done
diff --git a/tests/drcp_scope2.phpt b/tests/drcp_scope2.phpt
new file mode 100644
index 0000000000..b72e00dbb0
--- /dev/null
+++ b/tests/drcp_scope2.phpt
@@ -0,0 +1,91 @@
+--TEST--
+DRCP: oci_new_connect() and oci_connect with scope end when oci8.old_oci_close_semantics OFF
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require dirname(__FILE__)."/drcp_functions.inc";
+require dirname(__FILE__)."/details.inc";
+
+// Scope considered here is the functional scope
+// Test will open a connection within a function (function 1).
+// Update a table
+// Open another connection from function 2.
+// When the scope ends the txn is rolled back and hence the updated value
+// will not be reflected for oci_connect and oci_new_connect.
+
+// Create the table
+$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
+drcp_create_table($c);
+
+// OCI_NEW_CONNECT
+$conn_type = 1;
+echo "This is with a OCI_NEW_CONNECT\n";
+function1($user,$password,$dbase,$conn_type);
+
+// Should return the OLD value
+function2($user,$password,$dbase,$conn_type);
+
+// OCI_CONNECT
+$conn_type = 2;
+echo "\n\nThis is with a OCI_CONNECT\n";
+function1($user,$password,$dbase,$conn_type);
+
+// Should return the OLD value
+function2($user,$password,$dbase,$conn_type);
+
+//This is the first scope for the script
+
+function function1($user,$password,$dbase,$conn_type)
+{
+ switch($conn_type)
+ {
+ case 1:
+ var_dump($conn1 = oci_new_connect($user,$password,$dbase));
+ break;
+ case 2:
+ var_dump($conn1 = oci_connect($user,$password,$dbase));
+ break;
+ }
+ drcp_update_table($conn1);
+}
+
+// This is the second scope
+
+function function2($user,$password,$dbase,$conn_type)
+{
+ switch($conn_type)
+ {
+ case 1:
+ var_dump($conn1 = oci_new_connect($user,$password,$dbase));
+ break;
+ case 2:
+ var_dump($conn1 = oci_connect($user,$password,$dbase));
+ break;
+ }
+ drcp_select_value($conn1);
+}
+drcp_drop_table($c);
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_NEW_CONNECT
+resource(%d) of type (oci8 connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 connection)
+The value of DEPT for id 105 is HR
+
+
+This is with a OCI_CONNECT
+resource(%d) of type (oci8 connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 connection)
+The value of DEPT for id 105 is HR
+Done
diff --git a/tests/drcp_scope3.phpt b/tests/drcp_scope3.phpt
new file mode 100644
index 0000000000..b448a518ad
--- /dev/null
+++ b/tests/drcp_scope3.phpt
@@ -0,0 +1,61 @@
+--TEST--
+DRCP: oci_pconnect() with scope end when oci8.old_oci_close_semantics ON
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require dirname(__FILE__)."/drcp_functions.inc";
+require dirname(__FILE__)."/details.inc";
+
+// The test opens a connection within function1 and updates a table
+// (without committing). Another connection is opened from function
+// 2, and the table queried. When function1 ends, the connection from
+// function1 is not closed, so the updated value will be seen in
+// function2. Also the table can't be dropped because an uncommitted
+// transaction exists.
+
+// Create the table
+$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
+drcp_create_table($c);
+
+echo "This is with a OCI_PCONNECT\n";
+function1($user,$password,$dbase);
+
+// Should return the OLD value
+function2($user,$password,$dbase);
+
+// This is the first scope for the script
+
+function function1($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_update_table($c);
+}
+
+// This is the second scope
+
+function function2($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_select_value($c);
+}
+
+drcp_drop_table($c);
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_PCONNECT
+resource(%d) of type (oci8 persistent connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 persistent connection)
+The value of DEPT for id 105 is NEWDEPT
+
+Warning: oci_execute(): ORA-00054: %s
+Done \ No newline at end of file
diff --git a/tests/drcp_scope4.phpt b/tests/drcp_scope4.phpt
new file mode 100644
index 0000000000..87eaf0cbe6
--- /dev/null
+++ b/tests/drcp_scope4.phpt
@@ -0,0 +1,62 @@
+--TEST--
+DRCP: oci_pconnect() with scope end when oci8.old_oci_close_semantics OFF
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require dirname(__FILE__)."/drcp_functions.inc";
+require dirname(__FILE__)."/details.inc";
+
+// The default expected behavior of this test is different between PHP
+// 5.2 and PHP 5.3
+//
+// In PHP 5.3, the test opens a connection within function1 and
+// updates a table (without committing). Another connection is opened
+// from function 2, and the table queried. When function1 ends, the
+// txn is rolled back and hence the updated value will not be
+// reflected in function2. Use oci8.old_oci_close_semantics=1 to
+// get old behavior
+
+// Create the table
+$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
+drcp_create_table($c);
+
+echo "This is with a OCI_PCONNECT\n";
+function1($user,$password,$dbase);
+
+// Should return the OLD value
+function2($user,$password,$dbase);
+
+// This is the first scope for the script
+
+function function1($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_update_table($c);
+}
+
+// This is the second scope
+
+function function2($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_select_value($c);
+}
+
+drcp_drop_table($c);
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_PCONNECT
+resource(%d) of type (oci8 persistent connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 persistent connection)
+The value of DEPT for id 105 is HR
+Done
diff --git a/tests/drcp_scope5.phpt b/tests/drcp_scope5.phpt
new file mode 100644
index 0000000000..832e6aa8cb
--- /dev/null
+++ b/tests/drcp_scope5.phpt
@@ -0,0 +1,63 @@
+--TEST--
+DRCP: oci_pconnect() with scope end when oci8.old_oci_close_semantics ON
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require dirname(__FILE__)."/drcp_functions.inc";
+require dirname(__FILE__)."/details.inc";
+
+// Similar to drcp_scope3.phpt but does a commit before end of
+// function2, allowing the table to be dropped cleanly at the end.
+
+// The test opens a connection within function1 and updates a table
+// (without committing). Another connection is opened from function
+// 2, and the table queried. When function1 ends, the connection from
+// function1 is not closed, so the updated value will be seen in
+// function2. Also the table can't be dropped because an uncommitted
+// transaction exists.
+
+// Create the table
+$c = oci_new_connect($user,$password,$dbase);
+@drcp_drop_table($c);
+drcp_create_table($c);
+
+echo "This is with a OCI_PCONNECT\n";
+function1($user,$password,$dbase);
+
+// Should return the OLD value
+function2($user,$password,$dbase);
+
+// This is the first scope for the script
+
+function function1($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_update_table($c);
+}
+
+// This is the second scope
+
+function function2($user,$password,$dbase)
+{
+ var_dump($c = oci_pconnect($user,$password,$dbase));
+ drcp_select_value($c);
+ oci_commit($c);
+}
+
+drcp_drop_table($c);
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+This is with a OCI_PCONNECT
+resource(%d) of type (oci8 persistent connection)
+Update done-- DEPT value has been set to NEWDEPT
+resource(%d) of type (oci8 persistent connection)
+The value of DEPT for id 105 is NEWDEPT
+Done \ No newline at end of file
diff --git a/tests/driver_name.phpt b/tests/driver_name.phpt
new file mode 100644
index 0000000000..187d7e1862
--- /dev/null
+++ b/tests/driver_name.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Verify that the Driver Name attribute is set
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+
+require(dirname(__FILE__)."/connect.inc");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+if ($test_drcp) die("skip as Output might vary with DRCP");
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release (11.2|12)/', $sv, $matches);
+
+if ($sv == 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => (11.2|12)/', $phpinfo);
+ if ($iv != 1) {
+ die ("skip test expected to work only with Oracle 11g or greater version of client");
+ }
+}
+else {
+ die ("skip test expected to work only with Oracle 11g or greater version of server");
+}
+
+?>
+--FILE--
+<?php
+require(dirname(__FILE__)."/connect.inc");
+
+echo"**Test 1.1 - Default values for the attribute **************\n";
+get_attr($c);
+oci_close($c);
+
+echo"\n***Test 1.2 - Get the values from different connections **************\n";
+// with oci_pconnect()
+echo "Testing with oci_pconnect()\n";
+$pc1=oci_pconnect($user,$password,$dbase);
+get_attr($pc1);
+oci_close($pc1);
+
+echo "Testing with oci_new_connect()\n";
+$nc1=oci_new_connect($user,$password,$dbase);
+get_attr($nc1);
+oci_close($nc1);
+echo "Done\n";
+
+function get_attr($conn)
+{
+ $sel_stmt = "select client_driver
+ from v\$session_connect_info sci, v\$session s
+ where sci.client_driver is not null
+ and sci.sid = s.sid
+ and s.audsid = userenv('SESSIONID')";
+ $s2 = oci_parse($conn,$sel_stmt);
+ oci_execute($s2,OCI_DEFAULT);
+ oci_fetch($s2);
+ echo "The value of DRIVER_NAME is ".oci_result($s2,1)."\n";
+}
+
+?>
+--EXPECT--
+**Test 1.1 - Default values for the attribute **************
+The value of DRIVER_NAME is PHP OCI8
+
+***Test 1.2 - Get the values from different connections **************
+Testing with oci_pconnect()
+The value of DRIVER_NAME is PHP OCI8
+Testing with oci_new_connect()
+The value of DRIVER_NAME is PHP OCI8
+Done
diff --git a/tests/drop_table.inc b/tests/drop_table.inc
new file mode 100644
index 0000000000..592a95a3db
--- /dev/null
+++ b/tests/drop_table.inc
@@ -0,0 +1,7 @@
+<?php
+if ($c) {
+ $ora_sql = "DROP TABLE ".$schema.$table_name;
+ $statement = oci_parse($c,$ora_sql);
+ oci_execute($statement);
+}
+?>
diff --git a/tests/drop_type.inc b/tests/drop_type.inc
new file mode 100644
index 0000000000..98542a8085
--- /dev/null
+++ b/tests/drop_type.inc
@@ -0,0 +1,7 @@
+<?php
+if ($c) {
+ $ora_sql = "DROP TYPE ".$type_name;
+ $statement = oci_parse($c,$ora_sql);
+ oci_execute($statement);
+}
+?>
diff --git a/tests/edition_1.phpt b/tests/edition_1.phpt
new file mode 100644
index 0000000000..9a4b0f3b61
--- /dev/null
+++ b/tests/edition_1.phpt
@@ -0,0 +1,156 @@
+--TEST--
+Basic test for setting Oracle 11gR2 "edition" attribute
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys"))
+ die("skip needs to be run as a DBA user");
+if ($test_drcp)
+ die("skip as Output might vary with DRCP");
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release (11\.2|12)/', $sv, $matches);
+if ($sv == 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => (11\.2|12)/', $phpinfo);
+ if ($iv != 1) {
+ die ("skip tests a feature that works only with Oracle 11gR2 or greater version of client");
+ }
+}
+else {
+ die ("skip tests a feature that works only with Oracle 11gR2 or greater version of server");
+}
+
+?>
+--FILE--
+<?php
+
+/* In 11.2, there can only be one child edition. So this test will
+ * fail to create the necessary editions if a child edition exists
+ * already
+ */
+
+require(dirname(__FILE__)."/conn_attr.inc");
+
+function select_fn($conn) {
+ $s = oci_parse($conn,"select * from view_ed");
+ oci_execute($s);
+ while ($row = oci_fetch_row($s)) {
+ var_dump($row);
+ }
+}
+/* Create a editon MYEDITION
+ create a view view_ed in MYEDITION1.
+ create the same view 'view_ed' with a different definition in MYEDITION.
+ select from both the editions and verify the contents. */
+
+set_edit_attr('MYEDITION');
+$conn = oci_connect('testuser','testuser',$dbase);
+if ($conn === false) {
+ $m = oci_error();
+ die("Error:" . $m['message']);
+}
+
+$stmtarray = array(
+ "drop table edit_tab",
+ "create table edit_tab (name varchar2(10),age number,job varchar2(50), salary number)",
+ "insert into edit_tab values('mike',30,'Senior engineer',200)",
+ "insert into edit_tab values('juan',25,'engineer',100)",
+ "create or replace editioning view view_ed as select name,age,job from edit_tab",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($conn, $stmt);
+ @oci_execute($s);
+}
+
+// Check the current edition of the DB and the contents of view_ed.
+get_edit_attr($conn);
+select_fn($conn);
+
+// Create a different version of view_ed in MYEDITION1.
+set_edit_attr('MYEDITION1');
+$conn2 = oci_new_connect('testuser','testuser',$dbase);
+$stmt = "create or replace editioning view view_ed as select name,age,job,salary from edit_tab";
+$s = oci_parse($conn2, $stmt);
+oci_execute($s);
+
+// Check the current edition of the DB and the contents of view_ed.
+get_edit_attr($conn2);
+select_fn($conn2);
+
+// Verify the contents in MYEDITION EDITION.
+echo "version of view_ed in MYEDITION \n";
+get_edit_attr($conn);
+select_fn($conn);
+
+clean_up($c);
+
+oci_close($conn);
+oci_close($conn2);
+echo "Done\n";
+
+?>
+--EXPECTF--
+The value of edition has been successfully set
+The value of current EDITION is MYEDITION
+array(3) {
+ [0]=>
+ %unicode|string%(%d) "mike"
+ [1]=>
+ %unicode|string%(%d) "30"
+ [2]=>
+ %unicode|string%(%d) "Senior engineer"
+}
+array(3) {
+ [0]=>
+ %unicode|string%(%d) "juan"
+ [1]=>
+ %unicode|string%(%d) "25"
+ [2]=>
+ %unicode|string%(%d) "engineer"
+}
+ The value of edition has been successfully set
+The value of current EDITION is MYEDITION1
+array(4) {
+ [0]=>
+ %unicode|string%(%d) "mike"
+ [1]=>
+ %unicode|string%(%d) "30"
+ [2]=>
+ %unicode|string%(%d) "Senior engineer"
+ [3]=>
+ %unicode|string%(%d) "200"
+}
+array(4) {
+ [0]=>
+ %unicode|string%(%d) "juan"
+ [1]=>
+ %unicode|string%(%d) "25"
+ [2]=>
+ %unicode|string%(%d) "engineer"
+ [3]=>
+ %unicode|string%(%d) "100"
+}
+version of view_ed in MYEDITION
+The value of current EDITION is MYEDITION
+array(3) {
+ [0]=>
+ %unicode|string%(%d) "mike"
+ [1]=>
+ %unicode|string%(%d) "30"
+ [2]=>
+ %unicode|string%(%d) "Senior engineer"
+}
+array(3) {
+ [0]=>
+ %unicode|string%(%d) "juan"
+ [1]=>
+ %unicode|string%(%d) "25"
+ [2]=>
+ %unicode|string%(%d) "engineer"
+}
+Done
diff --git a/tests/edition_2.phpt b/tests/edition_2.phpt
new file mode 100644
index 0000000000..f7ab979bcf
--- /dev/null
+++ b/tests/edition_2.phpt
@@ -0,0 +1,248 @@
+--TEST--
+Set and check Oracle 11gR2 "edition" attribute
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys"))
+ die("skip needs to be run as a DBA user");
+if ($test_drcp)
+ die("skip as Output might vary with DRCP");
+
+$sv = oci_server_version($c);
+$sv = preg_match('/Release (11\.2|12)/', $sv, $matches);
+if ($sv == 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => (11\.2|12)/', $phpinfo);
+ if ($iv != 1) {
+ die ("skip tests a feature that works only with Oracle 11gR2 or greater version of client");
+ }
+}
+else {
+ die ("skip tests a feature that works only with Oracle 11gR2 or greater version of server");
+}
+
+?>
+--FILE--
+<?php
+
+/* In 11.2, there can only be one child edition. So this test will
+ * fail to create the necessary editions if a child edition exists
+ * already
+ */
+
+require(dirname(__FILE__)."/conn_attr.inc");
+
+$user = 'testuser';
+$password = 'testuser';
+
+echo"**Test 1.1 - Default value for the attribute **************\n";
+get_edit_attr($c);
+
+echo"\n\n**Test 1.2 - Set a value and get the same with different connections *********\n";
+set_edit_attr('MYEDITION');
+
+// With oci_connect, oci_pconnect, oci_new_connect
+$conn1 = get_conn(1);
+get_edit_attr($conn1);
+
+//pconnect
+$conn2 = get_conn(2);
+get_edit_attr($conn2);
+
+//new_connect
+$conn3 = get_conn(3);
+get_edit_attr($conn3);
+
+oci_close($conn1);
+
+// With a oci_pconnect with a different charset.
+$pc1 = oci_pconnect($user,$password,$dbase,"utf8");
+get_edit_attr($pc1);
+oci_close($pc1);
+
+
+echo"\n\n**Test 1.3 change the value and verify with existing conenctions.*********\n";
+set_edit_attr('MYEDITION1');
+get_edit_attr($conn2);
+get_edit_attr($conn3); // Old value
+oci_close($conn2);
+oci_close($conn3);
+
+//open a new connection and get the edition value . This will have the updated value.
+$c3 = get_conn(3); //oci_new_connect()
+get_edit_attr($c3);
+
+$c4 = get_conn(2); //oci_pconnect()
+get_edit_attr($c4);
+
+$c5 = get_conn(1); //oci_connect()
+get_edit_attr($c5);
+
+oci_close($c3);
+oci_close($c4);
+oci_close($c5);
+
+echo "\n\n**Test 1.4 - with different type of values *********\n";
+$values_array = array(123,NULL,'NO EDITION','edition name which has more than thirty chars!!!edition name which has more than thirty chars!!!');
+foreach ($values_array as $val ) {
+ set_edit_attr($val);
+ $c1 = get_conn(1); //oci_connect()
+ if ($c1) {
+ get_edit_attr($c1);
+ oci_close($c1);
+ }
+}
+
+echo "\n\n**Test 1.5 - Negative case with an invalid string value. *********\n";
+$c1 = get_conn(3);
+$r = set_edit_attr($c1);
+
+echo"\n\n**Test 1.6 - Set Multiple times.*****\n";
+set_edit_attr('MYEDITION');
+set_edit_attr('MYEDITION1');
+$c1 = get_conn(1);
+get_edit_attr($c1);
+oci_close($c1);
+
+echo "\n\n**Test 1.7 - Test with ALTER SESSION statement to change the edition *******\n";
+// Set the edition value to MYEDITION. open a conn .get the value.
+// execute the alter system set edition ='MYEDITION' .get the value .
+// set it back to MYEDITION using oci_set_edition. and get the value.
+
+set_edit_attr('MYEDITION');
+$c1 = get_conn(3);
+echo "get the value set to MYEDITION with oci_set_edition \n";
+get_edit_attr($c1);
+
+$alter_stmt = "alter session set edition = MYEDITION1";
+$s = oci_parse($c1,$alter_stmt);
+oci_execute($s);
+oci_commit($c1);
+echo "Get the value set to MYEDITION1 with alter session\n";
+get_edit_attr($c1);
+
+echo " Get the value with a new connection \n";
+$c2 = get_conn(1);
+get_edit_attr($c2);
+
+echo " Set the value back using oci-set_edition\n";
+set_edit_attr('MYEDITION');
+get_edit_attr($c2);
+
+echo " Get the value with a new conenction \n";
+$c3 = get_conn(1);
+get_edit_attr($c3);
+
+oci_close($c1);
+oci_close($c2);
+oci_close($c3);
+
+
+echo "\n\n**Test 1.8 - Test setting the attribute with scope ends*******\n";
+set_scope();
+get_scope();
+
+clean_up($c);
+echo "Done\n";
+
+
+function set_scope() {
+ $r = set_edit_attr('MYEDITION1');
+}
+
+function get_scope() {
+ $sc1 = oci_connect($GLOBALS['user'],$GLOBALS['password'],$GLOBALS['dbase']);
+ if ($sc1 === false) {
+ $m = oci_error();
+ die("Error:" . $m['message']);
+ }
+ get_edit_attr($sc1);
+ oci_close($sc1);
+}
+?>
+--EXPECTF--
+**Test 1.1 - Default value for the attribute **************
+The value of current EDITION is ORA$BASE
+
+
+**Test 1.2 - Set a value and get the same with different connections *********
+ The value of edition has been successfully set
+Testing with oci_connect()
+The value of current EDITION is MYEDITION
+Testing with oci_pconnect()
+The value of current EDITION is MYEDITION
+Testing with oci_new_connect()
+The value of current EDITION is MYEDITION
+The value of current EDITION is MYEDITION
+
+
+**Test 1.3 change the value and verify with existing conenctions.*********
+ The value of edition has been successfully set
+The value of current EDITION is MYEDITION
+The value of current EDITION is MYEDITION
+Testing with oci_new_connect()
+The value of current EDITION is MYEDITION1
+Testing with oci_pconnect()
+The value of current EDITION is MYEDITION1
+Testing with oci_connect()
+The value of current EDITION is MYEDITION1
+
+
+**Test 1.4 - with different type of values *********
+ The value of edition has been successfully set
+Testing with oci_connect()
+
+Warning: oci_connect(): ORA-38801: %s ORA_EDITION in %s on line %d
+ The value of edition has been successfully set
+Testing with oci_connect()
+The value of current EDITION is ORA$BASE
+ The value of edition has been successfully set
+Testing with oci_connect()
+
+Warning: oci_connect(): ORA-38801: %s ORA_EDITION in %s on line %d
+ The value of edition has been successfully set
+Testing with oci_connect()
+
+Warning: oci_connect(): ORA-38801: %s ORA_EDITION in %s on line %d
+
+
+**Test 1.5 - Negative case with an invalid string value. *********
+Testing with oci_new_connect()
+
+Warning: oci_new_connect(): ORA-38801: %s ORA_EDITION in %s on line %d
+ The value of edition has been successfully set
+
+
+**Test 1.6 - Set Multiple times.*****
+ The value of edition has been successfully set
+ The value of edition has been successfully set
+Testing with oci_connect()
+The value of current EDITION is MYEDITION1
+
+
+**Test 1.7 - Test with ALTER SESSION statement to change the edition *******
+ The value of edition has been successfully set
+Testing with oci_new_connect()
+get the value set to MYEDITION with oci_set_edition
+The value of current EDITION is MYEDITION
+Get the value set to MYEDITION1 with alter session
+The value of current EDITION is MYEDITION1
+ Get the value with a new connection
+Testing with oci_connect()
+The value of current EDITION is MYEDITION
+ Set the value back using oci-set_edition
+ The value of edition has been successfully set
+The value of current EDITION is MYEDITION
+ Get the value with a new conenction
+Testing with oci_connect()
+The value of current EDITION is MYEDITION
+
+
+**Test 1.8 - Test setting the attribute with scope ends*******
+ The value of edition has been successfully set
+The value of current EDITION is MYEDITION1
+Done
+
diff --git a/tests/error.phpt b/tests/error.phpt
new file mode 100644
index 0000000000..743820f901
--- /dev/null
+++ b/tests/error.phpt
@@ -0,0 +1,40 @@
+--TEST--
+oci_error()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+if (!empty($dbase)) {
+ var_dump(oci_connect($user, $password, $dbase));
+}
+else {
+ var_dump(oci_connect($user, $password));
+}
+
+var_dump($s = oci_parse($c, "WRONG SYNTAX"));
+var_dump(oci_execute($s));
+var_dump(oci_error($s));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%s) of type (oci8 connection)
+resource(%s) of type (oci8 statement)
+
+Warning: oci_execute(): ORA-00900: invalid SQL statement in %s on line %d
+bool(false)
+array(4) {
+ ["code"]=>
+ int(900)
+ ["message"]=>
+ string(32) "ORA-00900: invalid SQL statement"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(12) "WRONG SYNTAX"
+}
+Done
diff --git a/tests/error1.phpt b/tests/error1.phpt
new file mode 100644
index 0000000000..25a3f09e92
--- /dev/null
+++ b/tests/error1.phpt
@@ -0,0 +1,27 @@
+--TEST--
+oci_error() when oci_connect() fails
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+var_dump(oci_connect("some", "some", "some"));
+var_dump(oci_error());
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: oci_connect(): ORA-12154: TNS:could not resolve %s in %s on line %d
+bool(false)
+array(4) {
+ ["code"]=>
+ int(12154)
+ ["message"]=>
+ string(%d) "ORA-12154: TNS:could not resolve %s"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+Done
diff --git a/tests/error2.phpt b/tests/error2.phpt
new file mode 100644
index 0000000000..13ea6cebe2
--- /dev/null
+++ b/tests/error2.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Exercise error code for SUCCESS_WITH_INFO
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+ini_set('error_reporting', E_ALL);
+
+$s = oci_parse($c, "create or replace procedure myproc as begin bogus end;");
+$e = @oci_execute($s);
+if (!$e) {
+ $es = oci_error($s);
+ echo $es['message']."\n";
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+ORA-24344: success with compilation error
+Done
diff --git a/tests/error_bind.phpt b/tests/error_bind.phpt
new file mode 100644
index 0000000000..ad66ad59fe
--- /dev/null
+++ b/tests/error_bind.phpt
@@ -0,0 +1,70 @@
+--TEST--
+Test some oci_bind_by_name error conditions
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+$drop = "drop table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "create table bind_test(name varchar(10))";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+
+echo "Insert value\n";
+
+$name = 'abc';
+$stmt = oci_parse($c, "insert into bind_test values (:name)");
+oci_bind_by_name($stmt, ":name", $name, 10, SQLT_CHR);
+var_dump(oci_execute($stmt));
+
+echo "Test 1 - Assign a resource to the bind variable and execute \n";
+$name=$c;
+var_dump(oci_execute($stmt));
+
+echo "Test 2 - Re-bind a resource\n";
+oci_bind_by_name($stmt, ":name", $c);
+var_dump(oci_execute($stmt));
+var_dump($c);
+
+// Use a connection resource instead of a ROWID.
+echo "Test 3 - Resource mismatch !!\n";
+$stmt = oci_parse($c, "update bind_test set name='xyz' returning rowid into :r_id");
+oci_bind_by_name($stmt, ":r_id", $c);
+var_dump(oci_execute($stmt));
+
+// Clean up
+
+$drop = "drop table bind_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Insert value
+bool(true)
+Test 1 - Assign a resource to the bind variable and execute
+
+Warning: oci_execute(): Invalid variable used for bind in %s on line %d
+bool(false)
+Test 2 - Re-bind a resource
+
+Warning: oci_bind_by_name(): Invalid variable used for bind in %s on line %d
+
+Warning: oci_execute(): Invalid variable used for bind in %s on line %d
+bool(false)
+resource(%d) of type (oci8 connection)
+Test 3 - Resource mismatch !!
+
+Warning: oci_bind_by_name(): Invalid variable used for bind in %s on line %d
+
+Warning: oci_execute(): ORA-01008: %s on line %d
+bool(false)
+Done
diff --git a/tests/error_old.phpt b/tests/error_old.phpt
new file mode 100644
index 0000000000..a6889c897a
--- /dev/null
+++ b/tests/error_old.phpt
@@ -0,0 +1,40 @@
+--TEST--
+ocierror()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+if (!empty($dbase)) {
+ var_dump(ocilogon($user, $password, $dbase));
+}
+else {
+ var_dump(ocilogon($user, $password));
+}
+
+var_dump($s = ociparse($c, "WRONG SYNTAX"));
+var_dump(ociexecute($s));
+var_dump(ocierror($s));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%s) of type (oci8 connection)
+resource(%s) of type (oci8 statement)
+
+Warning: ociexecute(): ORA-00900: invalid SQL statement in %s on line %d
+bool(false)
+array(4) {
+ ["code"]=>
+ int(900)
+ ["message"]=>
+ string(32) "ORA-00900: invalid SQL statement"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(12) "WRONG SYNTAX"
+}
+Done
diff --git a/tests/error_parse.phpt b/tests/error_parse.phpt
new file mode 100644
index 0000000000..8100e31706
--- /dev/null
+++ b/tests/error_parse.phpt
@@ -0,0 +1,142 @@
+--TEST--
+Test error handling when persistent connection is passed to oci_error()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+// As part of the fix for Bug 42134, an error handling difference was
+// noticed when oci_error() was passed a persistent connection. This
+// was fixed and the behavior of oci_error() for all connections types
+// was made consistent.
+
+require(dirname(__FILE__).'/details.inc');
+
+// Test parse error for normal connection
+
+if (!empty($dbase)) {
+ $c1 = oci_connect($user,$password,$dbase);
+}
+else {
+ $c1 = oci_connect($user,$password);
+}
+
+$s = @oci_parse($c1, "select ' from dual");
+if (!$s) {
+ echo "Normal connection: Parse error\n";
+ $m = oci_error($c1);
+ var_dump($m);
+}
+
+// Test parse error for new connection
+
+if (!empty($dbase)) {
+ $c2 = oci_new_connect($user,$password,$dbase);
+}
+else {
+ $c2 = oci_new_connect($user,$password);
+}
+
+$s = @oci_parse($c2, "select ' from dual");
+if (!$s) {
+ echo "New connection: Parse error\n";
+ $m = oci_error($c2);
+ var_dump($m);
+}
+
+// Test parse error for persistent connection
+
+if (!empty($dbase)) {
+ $c3 = oci_pconnect($user,$password,$dbase);
+}
+else {
+ $c3 = oci_pconnect($user,$password);
+}
+
+$s = @oci_parse($c3, "select ' from dual");
+if (!$s) {
+ echo "Persistent connection: Parse error\n";
+ $m = oci_error($c3);
+ var_dump($m);
+}
+
+// Verify that passing no connection doesn't affect future calls
+
+$m = oci_error();
+echo "No connection: error: ";
+var_dump($m);
+
+// Check the errors are still accessible in the respective handles
+
+$m = oci_error($c1);
+echo "Normal connection (take #2): Parse error: ";
+echo $m["message"], "\n";
+
+$m = oci_error($c2);
+echo "New connection (take #2): Parse error: ";
+echo $m["message"], "\n";
+
+$m = oci_error($c3);
+echo "Persistent connection (take #2): Parse error: ";
+echo $m["message"], "\n";
+
+// Now create a new error for a normal connection and check all again
+
+$s = @oci_new_collection($c1, "ABC");
+$m = oci_error($c1);
+echo "Normal connection: New Collection error: ";
+echo $m["message"], "\n";
+
+$m = oci_error($c2);
+echo "New connection (take #3): Parse error: ";
+echo $m["message"], "\n";
+
+$m = oci_error($c3);
+echo "Persistent connection (take #3): Parse error: ";
+echo $m["message"], "\n";
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Normal connection: Parse error
+array(4) {
+ ["code"]=>
+ int(1756)
+ ["message"]=>
+ string(48) "ORA-01756: quoted string not properly terminated"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+New connection: Parse error
+array(4) {
+ ["code"]=>
+ int(1756)
+ ["message"]=>
+ string(48) "ORA-01756: quoted string not properly terminated"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+Persistent connection: Parse error
+array(4) {
+ ["code"]=>
+ int(1756)
+ ["message"]=>
+ string(48) "ORA-01756: quoted string not properly terminated"
+ ["offset"]=>
+ int(0)
+ ["sqltext"]=>
+ string(0) ""
+}
+No connection: error: bool(false)
+Normal connection (take #2): Parse error: ORA-01756: quoted string not properly terminated
+New connection (take #2): Parse error: ORA-01756: quoted string not properly terminated
+Persistent connection (take #2): Parse error: ORA-01756: quoted string not properly terminated
+Normal connection: New Collection error: OCI-22303: type ""."ABC" not found
+New connection (take #3): Parse error: ORA-01756: quoted string not properly terminated
+Persistent connection (take #3): Parse error: ORA-01756: quoted string not properly terminated
+Done
diff --git a/tests/exec_fetch.phpt b/tests/exec_fetch.phpt
new file mode 100644
index 0000000000..83aae69f7d
--- /dev/null
+++ b/tests/exec_fetch.phpt
@@ -0,0 +1,24 @@
+--TEST--
+fetch after failed oci_execute()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$sql = "select 2 from nonex_dual";
+$stmt = oci_parse($c, $sql);
+
+var_dump(oci_execute($stmt));
+var_dump(oci_fetch_array($stmt));
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_execute(): ORA-00942: table or view does not exist in %s on line %d
+bool(false)
+
+Warning: oci_fetch_array(): ORA-24374: define not done before fetch or execute and fetch in %s on line %d
+bool(false)
+Done
diff --git a/tests/execute_mode.phpt b/tests/execute_mode.phpt
new file mode 100644
index 0000000000..90570cae80
--- /dev/null
+++ b/tests/execute_mode.phpt
@@ -0,0 +1,19 @@
+--TEST--
+oci_execute() and invalid execute mode
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$pc = oci_pconnect($user, $password, $dbase);
+
+$stmt = oci_parse($pc, "select NULL from dual");
+oci_execute($stmt, -1);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_execute(): Invalid execute mode given: -1 in %s on line %d
+Done
diff --git a/tests/extauth_01.phpt b/tests/extauth_01.phpt
new file mode 100644
index 0000000000..993198c4de
--- /dev/null
+++ b/tests/extauth_01.phpt
@@ -0,0 +1,198 @@
+--TEST--
+Test External Authentication errors with oci_connect
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+if (substr(PHP_OS, 0, 3) == 'WIN') die("skip feature not available on Windows platforms");
+require(dirname(__FILE__).'/details.inc');
+if ($stress_test !== true) die ('skip Slow test not run when $stress_test is FALSE');
+?>
+--INI--
+oci8.privileged_connect=1
+--FILE--
+<?php
+
+// Run Test
+
+echo "Test 1\n";
+
+$c = oci_connect('/', 'notemtpy', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 2\n";
+
+$c = oci_connect('notemtpy', 'notemtpy', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 3\n";
+
+$c = oci_connect('notemtpy', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 4\n";
+
+$c = oci_connect('a', 'b', 'c', null, OCI_SYSDBA+OCI_SYSOPER);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 5\n";
+
+$c = oci_connect('a', 'b', 'c', null, OCI_SYSDBA+OCI_SYSOPER+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 6\n";
+
+$c = oci_connect('', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 7\n";
+
+$c = oci_connect('/', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 8\n";
+
+$c = oci_connect('/', null, 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 9\n";
+
+$c = oci_connect('/', '', 'c', null, OCI_SYSDBA+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 10\n";
+
+$c = oci_connect('/', '', 'c', null, OCI_SYSOPER+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+
+Warning: oci_connect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 2
+
+Warning: oci_connect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 3
+
+Warning: oci_connect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 4
+
+Warning: oci_connect(): OCI_SYSDBA and OCI_SYSOPER cannot be used together in %s on line %d
+bool(false)
+bool(false)
+Test 5
+
+Warning: oci_connect(): OCI_SYSDBA and OCI_SYSOPER cannot be used together in %s on line %d
+bool(false)
+bool(false)
+Test 6
+
+Warning: oci_connect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 7
+
+Warning: oci_connect(): ORA-12154: %s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(12154)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-12154: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 8
+
+Warning: oci_connect(): ORA-12154: %s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(12154)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-12154: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 9
+
+Warning: oci_connect(): ORA-%d: TNS:%s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(%d)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-%d: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 10
+
+Warning: oci_connect(): ORA-%d: TNS:%s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(%d)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-%d: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+===DONE===
diff --git a/tests/extauth_02.phpt b/tests/extauth_02.phpt
new file mode 100644
index 0000000000..d3bee0bfc3
--- /dev/null
+++ b/tests/extauth_02.phpt
@@ -0,0 +1,198 @@
+--TEST--
+Test External Authentication errors with oci_new_connect
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+if (substr(PHP_OS, 0, 3) == 'WIN') die("skip feature not available on Windows platforms");
+require(dirname(__FILE__).'/details.inc');
+if ($stress_test !== true) die ('skip Slow test not run when $stress_test is FALSE');
+?>
+--INI--
+oci8.privileged_connect=1
+--FILE--
+<?php
+
+// Run Test
+
+echo "Test 1\n";
+
+$c = oci_new_connect('/', 'notemtpy', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 2\n";
+
+$c = oci_new_connect('notemtpy', 'notemtpy', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 3\n";
+
+$c = oci_new_connect('notemtpy', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 4\n";
+
+$c = oci_new_connect('a', 'b', 'c', null, OCI_SYSDBA+OCI_SYSOPER);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 5\n";
+
+$c = oci_new_connect('a', 'b', 'c', null, OCI_SYSDBA+OCI_SYSOPER+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 6\n";
+
+$c = oci_new_connect('', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 7\n";
+
+$c = oci_new_connect('/', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 8\n";
+
+$c = oci_new_connect('/', null, 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 9\n";
+
+$c = oci_new_connect('/', '', 'c', null, OCI_SYSDBA+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 10\n";
+
+$c = oci_new_connect('/', '', 'c', null, OCI_SYSOPER+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+
+Warning: oci_new_connect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 2
+
+Warning: oci_new_connect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 3
+
+Warning: oci_new_connect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 4
+
+Warning: oci_new_connect(): OCI_SYSDBA and OCI_SYSOPER cannot be used together in %s on line %d
+bool(false)
+bool(false)
+Test 5
+
+Warning: oci_new_connect(): OCI_SYSDBA and OCI_SYSOPER cannot be used together in %s on line %d
+bool(false)
+bool(false)
+Test 6
+
+Warning: oci_new_connect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 7
+
+Warning: oci_new_connect(): ORA-12154: %s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(12154)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-12154: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 8
+
+Warning: oci_new_connect(): ORA-12154: %s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(12154)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-12154: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 9
+
+Warning: oci_new_connect(): ORA-%d: TNS:%s %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(%d)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-%d: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 10
+
+Warning: oci_new_connect(): ORA-%d: TNS:%s %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(%d)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-%d: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+===DONE===
diff --git a/tests/extauth_03.phpt b/tests/extauth_03.phpt
new file mode 100644
index 0000000000..e159c50f90
--- /dev/null
+++ b/tests/extauth_03.phpt
@@ -0,0 +1,198 @@
+--TEST--
+Test External Authentication errors with oci_pconnect
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+if (substr(PHP_OS, 0, 3) == 'WIN') die("skip feature not available on Windows platforms");
+require(dirname(__FILE__).'/details.inc');
+if ($stress_test !== true) die ('skip Slow test not run when $stress_test is FALSE');
+?>
+--INI--
+oci8.privileged_connect=1
+--FILE--
+<?php
+
+// Run Test
+
+echo "Test 1\n";
+
+$c = oci_pconnect('/', 'notemtpy', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 2\n";
+
+$c = oci_pconnect('notemtpy', 'notemtpy', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 3\n";
+
+$c = oci_pconnect('notemtpy', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 4\n";
+
+$c = oci_pconnect('a', 'b', 'c', null, OCI_SYSDBA+OCI_SYSOPER);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 5\n";
+
+$c = oci_pconnect('a', 'b', 'c', null, OCI_SYSDBA+OCI_SYSOPER+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 6\n";
+
+$c = oci_pconnect('', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 7\n";
+
+$c = oci_pconnect('/', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 8\n";
+
+$c = oci_pconnect('/', null, 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 9\n";
+
+$c = oci_pconnect('/', '', 'c', null, OCI_SYSDBA+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 10\n";
+
+$c = oci_pconnect('/', '', 'c', null, OCI_SYSOPER+OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+
+Warning: oci_pconnect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 2
+
+Warning: oci_pconnect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 3
+
+Warning: oci_pconnect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 4
+
+Warning: oci_pconnect(): OCI_SYSDBA and OCI_SYSOPER cannot be used together in %s on line %d
+bool(false)
+bool(false)
+Test 5
+
+Warning: oci_pconnect(): OCI_SYSDBA and OCI_SYSOPER cannot be used together in %s on line %d
+bool(false)
+bool(false)
+Test 6
+
+Warning: oci_pconnect(): OCI_CRED_EXT can only be used with a username of "/" and a NULL password in %s on line %d
+bool(false)
+bool(false)
+Test 7
+
+Warning: oci_pconnect(): ORA-12154: %s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(12154)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-12154: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 8
+
+Warning: oci_pconnect(): ORA-12154: %s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(12154)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-12154: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 9
+
+Warning: oci_pconnect(): ORA-%d: TNS:%s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(%d)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-%d: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+Test 10
+
+Warning: oci_pconnect(): ORA-%d: TNS:%s in %s on line %d
+array(4) {
+ [%u|b%"code"]=>
+ int(%d)
+ [%u|b%"message"]=>
+ %unicode|string%(%d) "ORA-%d: %s"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(0) ""
+}
+bool(false)
+===DONE===
diff --git a/tests/extauth_04.phpt b/tests/extauth_04.phpt
new file mode 100644
index 0000000000..e502435bb0
--- /dev/null
+++ b/tests/extauth_04.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Test External Authentication errors on Windows
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+if (substr(PHP_OS, 0, 3) != 'WIN') die("skip this test is for Windows platforms only");
+?>
+--FILE--
+<?php
+
+// Run Test
+
+echo "Test 1\n";
+
+$c = oci_connect('/', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 2\n";
+
+$c = oci_new_connect('/', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+echo "Test 3\n";
+
+$c = oci_pconnect('/', '', 'anything', null, OCI_CRED_EXT);
+if (!$c) {
+ $m = oci_error();
+ var_dump($m);
+}
+var_dump($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+Warning: oci_connect(): External Authentication is not supported on Windows in %s on line %d
+bool(false)
+bool(false)
+Test 2
+Warning: oci_new_connect(): External Authentication is not supported on Windows in %s on line %d
+bool(false)
+bool(false)
+Test 3
+Warning: oci_pconnect(): External Authentication is not supported on Windows in %s on line %d
+bool(false)
+bool(false)
+===DONE===
diff --git a/tests/fetch.phpt b/tests/fetch.phpt
new file mode 100644
index 0000000000..5206324940
--- /dev/null
+++ b/tests/fetch.phpt
@@ -0,0 +1,76 @@
+--TEST--
+ocifetch() & ociresult()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table fetch_tab",
+ "create table fetch_tab (id number, value number)",
+ "insert into fetch_tab (id, value) values (1,1)",
+ "insert into fetch_tab (id, value) values (1,1)",
+ "insert into fetch_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+if (!($s = oci_parse($c, "select * from fetch_tab"))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+while(ocifetch($s)) {
+ $row = ociresult($s, 1);
+ $row1 = ociresult($s, 2);
+ var_dump($row);
+ var_dump($row1);
+}
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table fetch_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+
+echo "Done\n";
+?>
+--EXPECTF--
+%unicode|string%(1) "1"
+%unicode|string%(1) "1"
+%unicode|string%(1) "1"
+%unicode|string%(1) "1"
+%unicode|string%(1) "1"
+%unicode|string%(1) "1"
+Done
diff --git a/tests/fetch_all.phpt b/tests/fetch_all.phpt
new file mode 100644
index 0000000000..a007bac830
--- /dev/null
+++ b/tests/fetch_all.phpt
@@ -0,0 +1,108 @@
+--TEST--
+oci_fetch_all()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table fetch_all_tab",
+ "create table fetch_all_tab (id number, value number)",
+ "insert into fetch_all_tab (id, value) values (1,1)",
+ "insert into fetch_all_tab (id, value) values (1,1)",
+ "insert into fetch_all_tab (id, value) values (1,1)"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+if (!($s = oci_parse($c, "select * from fetch_all_tab"))) {
+ die("oci_parse(select) failed!\n");
+}
+
+/* oci_fetch_all */
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+var_dump(oci_fetch_all($s, $all));
+var_dump($all);
+
+/* ocifetchstatement */
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+var_dump(ocifetchstatement($s, $all));
+var_dump($all);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table fetch_all_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECTF--
+int(3)
+array(2) {
+ [%u|b%"ID"]=>
+ array(3) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "1"
+ }
+ [%u|b%"VALUE"]=>
+ array(3) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "1"
+ }
+}
+int(3)
+array(2) {
+ [%u|b%"ID"]=>
+ array(3) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "1"
+ }
+ [%u|b%"VALUE"]=>
+ array(3) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "1"
+ }
+}
+Done
diff --git a/tests/fetch_all2.phpt b/tests/fetch_all2.phpt
new file mode 100644
index 0000000000..ff44cac70d
--- /dev/null
+++ b/tests/fetch_all2.phpt
@@ -0,0 +1,242 @@
+--TEST--
+oci_fetch_all() - 2
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__).'/create_table.inc';
+
+$insert_sql = "INSERT INTO ".$schema."".$table_name." (id, value) VALUES (1,1)";
+
+$s = oci_parse($c, $insert_sql);
+
+for ($i = 0; $i<3; $i++) {
+ oci_execute($s);
+}
+
+oci_commit($c);
+
+$select_sql = "SELECT * FROM ".$schema."".$table_name."";
+
+$s = oci_parse($c, $select_sql);
+
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all));
+var_dump($all);
+
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, 10, OCI_FETCHSTATEMENT_BY_ROW));
+var_dump($all);
+
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, -1, -1, OCI_FETCHSTATEMENT_BY_ROW));
+var_dump($all);
+
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, 2, OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM));
+var_dump($all);
+
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, 2, OCI_NUM));
+var_dump($all);
+
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, 1, OCI_BOTH));
+var_dump($all);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECT--
+int(3)
+array(5) {
+ ["ID"]=>
+ array(3) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "1"
+ }
+ ["VALUE"]=>
+ array(3) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ string(1) "1"
+ }
+ ["BLOB"]=>
+ array(3) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ }
+ ["CLOB"]=>
+ array(3) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ }
+ ["STRING"]=>
+ array(3) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ }
+}
+int(3)
+array(3) {
+ [0]=>
+ array(5) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ ["BLOB"]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ ["STRING"]=>
+ NULL
+ }
+ [1]=>
+ array(5) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ ["BLOB"]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ ["STRING"]=>
+ NULL
+ }
+ [2]=>
+ array(5) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ ["BLOB"]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ ["STRING"]=>
+ NULL
+ }
+}
+int(0)
+array(0) {
+}
+int(2)
+array(2) {
+ [0]=>
+ array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+ }
+ [1]=>
+ array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+ }
+}
+int(2)
+array(5) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ }
+ [2]=>
+ array(2) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ }
+ [3]=>
+ array(2) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ }
+ [4]=>
+ array(2) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ }
+}
+int(1)
+array(5) {
+ [0]=>
+ array(1) {
+ [0]=>
+ string(1) "1"
+ }
+ [1]=>
+ array(1) {
+ [0]=>
+ string(1) "1"
+ }
+ [2]=>
+ array(1) {
+ [0]=>
+ NULL
+ }
+ [3]=>
+ array(1) {
+ [0]=>
+ NULL
+ }
+ [4]=>
+ array(1) {
+ [0]=>
+ NULL
+ }
+}
+Done
diff --git a/tests/fetch_all3.phpt b/tests/fetch_all3.phpt
new file mode 100644
index 0000000000..42fe617dc9
--- /dev/null
+++ b/tests/fetch_all3.phpt
@@ -0,0 +1,612 @@
+--TEST--
+oci_fetch_all() - all combinations of flags
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table fetch_all3_tab",
+ "create table fetch_all3_tab (id number, value number)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+$insert_sql = "insert into fetch_all3_tab (id, value) values (:idbv,:vbv)";
+$s = oci_parse($c, $insert_sql);
+oci_bind_by_name($s, ":idbv", $idbv, SQLT_INT);
+oci_bind_by_name($s, ":vbv", $vbv, SQLT_INT);
+
+for ($i = 1; $i <= 4; $i++) {
+ $idbv = $i;
+ $vbv = -$i;
+ oci_execute($s, OCI_DEFAULT);
+}
+
+oci_commit($c);
+
+// Run Test
+
+$select_sql = "select id, value from fetch_all3_tab order by id";
+
+$s = oci_parse($c, $select_sql);
+
+echo "None\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1));
+var_dump($all);
+
+echo "OCI_ASSOC\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_ASSOC));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_COLUMN\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_COLUMN));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM|OCI_ASSOC\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM|OCI_ASSOC));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_ROW\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_ROW));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_ROW|OCI_ASSOC\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_ROW|OCI_ASSOC));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM|OCI_ASSOC\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM|OCI_ASSOC));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_ROW|OCI_NUM\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_ROW|OCI_NUM));
+var_dump($all);
+
+echo "OCI_FETCHSTATEMENT_BY_ROW|OCI_NUM|OCI_ASSOC\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_FETCHSTATEMENT_BY_ROW|OCI_NUM|OCI_ASSOC));
+var_dump($all);
+
+echo "OCI_NUM\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_NUM));
+var_dump($all);
+
+echo "OCI_NUM|OCI_ASSOC\n";
+oci_execute($s);
+var_dump(oci_fetch_all($s, $all, 0, -1, OCI_NUM|OCI_ASSOC));
+var_dump($all);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table fetch_all3_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECTF--
+None
+int(4)
+array(2) {
+ [%u|b%"ID"]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ }
+ [%u|b%"VALUE"]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(2) "-1"
+ [1]=>
+ %unicode|string%(2) "-2"
+ [2]=>
+ %unicode|string%(2) "-3"
+ [3]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_ASSOC
+int(4)
+array(2) {
+ [%u|b%"ID"]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ }
+ [%u|b%"VALUE"]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(2) "-1"
+ [1]=>
+ %unicode|string%(2) "-2"
+ [2]=>
+ %unicode|string%(2) "-3"
+ [3]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_COLUMN
+int(4)
+array(2) {
+ [%u|b%"ID"]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ }
+ [%u|b%"VALUE"]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(2) "-1"
+ [1]=>
+ %unicode|string%(2) "-2"
+ [2]=>
+ %unicode|string%(2) "-3"
+ [3]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC
+int(4)
+array(2) {
+ [%u|b%"ID"]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ }
+ [%u|b%"VALUE"]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(2) "-1"
+ [1]=>
+ %unicode|string%(2) "-2"
+ [2]=>
+ %unicode|string%(2) "-3"
+ [3]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM
+int(4)
+array(2) {
+ [0]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ }
+ [1]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(2) "-1"
+ [1]=>
+ %unicode|string%(2) "-2"
+ [2]=>
+ %unicode|string%(2) "-3"
+ [3]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM|OCI_ASSOC
+int(4)
+array(2) {
+ [0]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ }
+ [1]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(2) "-1"
+ [1]=>
+ %unicode|string%(2) "-2"
+ [2]=>
+ %unicode|string%(2) "-3"
+ [3]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_ROW
+int(4)
+array(4) {
+ [0]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-1"
+ }
+ [1]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-2"
+ }
+ [2]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "3"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-3"
+ }
+ [3]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_ROW|OCI_ASSOC
+int(4)
+array(4) {
+ [0]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-1"
+ }
+ [1]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-2"
+ }
+ [2]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "3"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-3"
+ }
+ [3]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN
+int(4)
+array(4) {
+ [0]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-1"
+ }
+ [1]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-2"
+ }
+ [2]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "3"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-3"
+ }
+ [3]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_ASSOC
+int(4)
+array(4) {
+ [0]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-1"
+ }
+ [1]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-2"
+ }
+ [2]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "3"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-3"
+ }
+ [3]=>
+ array(2) {
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM
+int(4)
+array(4) {
+ [0]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(2) "-1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(2) "-2"
+ }
+ [2]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "3"
+ [1]=>
+ %unicode|string%(2) "-3"
+ }
+ [3]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "4"
+ [1]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_ROW|OCI_FETCHSTATEMENT_BY_COLUMN|OCI_NUM|OCI_ASSOC
+int(4)
+array(4) {
+ [0]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(2) "-1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(2) "-2"
+ }
+ [2]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "3"
+ [1]=>
+ %unicode|string%(2) "-3"
+ }
+ [3]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "4"
+ [1]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_ROW|OCI_NUM
+int(4)
+array(4) {
+ [0]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(2) "-1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(2) "-2"
+ }
+ [2]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "3"
+ [1]=>
+ %unicode|string%(2) "-3"
+ }
+ [3]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "4"
+ [1]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_FETCHSTATEMENT_BY_ROW|OCI_NUM|OCI_ASSOC
+int(4)
+array(4) {
+ [0]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(2) "-1"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(2) "-2"
+ }
+ [2]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "3"
+ [1]=>
+ %unicode|string%(2) "-3"
+ }
+ [3]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "4"
+ [1]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_NUM
+int(4)
+array(2) {
+ [0]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ }
+ [1]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(2) "-1"
+ [1]=>
+ %unicode|string%(2) "-2"
+ [2]=>
+ %unicode|string%(2) "-3"
+ [3]=>
+ %unicode|string%(2) "-4"
+ }
+}
+OCI_NUM|OCI_ASSOC
+int(4)
+array(2) {
+ [0]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ }
+ [1]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(2) "-1"
+ [1]=>
+ %unicode|string%(2) "-2"
+ [2]=>
+ %unicode|string%(2) "-3"
+ [3]=>
+ %unicode|string%(2) "-4"
+ }
+}
+Done
diff --git a/tests/fetch_all4.phpt b/tests/fetch_all4.phpt
new file mode 100644
index 0000000000..9b82262e3f
--- /dev/null
+++ b/tests/fetch_all4.phpt
@@ -0,0 +1,82 @@
+--TEST--
+Test oci_fetch_* array overwriting when query returns no rows
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table fetch_all4_tab",
+ "create table fetch_all4_tab (mycol1 number, mycol2 varchar2(20))",
+ "insert into fetch_all4_tab values (1, 'abc')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+$s = oci_parse($c, "select * from fetch_all4_tab where 1 = 0");
+oci_execute($s);
+$res = array(1,2,3); // this array is replaced as a result of the query
+$r = oci_fetch_all($s, $res);
+var_dump($r);
+var_dump($res);
+
+echo "Test 2\n";
+
+$s = oci_parse($c, "select * from fetch_all4_tab where 1 = 0");
+oci_execute($s);
+$row = array(1,2,3); // this array is replaced as a result of the query
+$row = oci_fetch_array($s);
+var_dump($row);
+
+// Clean up
+
+$stmtarray = array(
+ "drop table fetch_all4_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+int(0)
+array(2) {
+ [%u|b%"MYCOL1"]=>
+ array(0) {
+ }
+ [%u|b%"MYCOL2"]=>
+ array(0) {
+ }
+}
+Test 2
+bool(false)
+===DONE===
diff --git a/tests/fetch_all5.phpt b/tests/fetch_all5.phpt
new file mode 100644
index 0000000000..bb9061a445
--- /dev/null
+++ b/tests/fetch_all5.phpt
@@ -0,0 +1,127 @@
+--TEST--
+Test oci_fetch_all with 0 and -1 skip & maxrows
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table fetch_all5_tab",
+ "create table fetch_all5_tab (mycol1 number, mycol2 varchar2(20))",
+ "insert into fetch_all5_tab values (1, 'abc')",
+ "insert into fetch_all5_tab values (2, 'def')",
+ "insert into fetch_all5_tab values (3, 'ghi')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+$s = oci_parse($c, "select * from fetch_all5_tab order by 1");
+oci_execute($s);
+$r = oci_fetch_all($s, $res, 0, -1);
+var_dump($r);
+var_dump($res);
+
+echo "Test 1\n";
+
+$s = oci_parse($c, "select * from fetch_all5_tab order by 1");
+oci_execute($s);
+$r = oci_fetch_all($s, $res, 0, 0);
+var_dump($r);
+var_dump($res);
+
+echo "Test 3\n";
+
+$s = oci_parse($c, "select * from fetch_all5_tab order by 1");
+oci_execute($s);
+$r = oci_fetch_all($s, $res, -1, 0);
+var_dump($r);
+var_dump($res);
+
+// Clean up
+
+$stmtarray = array(
+ "drop table fetch_all5_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+int(3)
+array(2) {
+ [%u|b%"MYCOL1"]=>
+ array(3) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ }
+ [%u|b%"MYCOL2"]=>
+ array(3) {
+ [0]=>
+ %unicode|string%(3) "abc"
+ [1]=>
+ %unicode|string%(3) "def"
+ [2]=>
+ %unicode|string%(3) "ghi"
+ }
+}
+Test 1
+int(3)
+array(2) {
+ [%u|b%"MYCOL1"]=>
+ array(3) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ }
+ [%u|b%"MYCOL2"]=>
+ array(3) {
+ [0]=>
+ %unicode|string%(3) "abc"
+ [1]=>
+ %unicode|string%(3) "def"
+ [2]=>
+ %unicode|string%(3) "ghi"
+ }
+}
+Test 3
+int(0)
+array(0) {
+}
+===DONE===
diff --git a/tests/fetch_array.phpt b/tests/fetch_array.phpt
new file mode 100644
index 0000000000..e2f32483d5
--- /dev/null
+++ b/tests/fetch_array.phpt
@@ -0,0 +1,308 @@
+--TEST--
+oci_fetch_array()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__).'/create_table.inc';
+
+$insert_sql = "INSERT INTO ".$schema."".$table_name." (id, value) VALUES (1,1)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+if (!oci_commit($c)) {
+ die("oci_commit() failed!\n");
+}
+
+$select_sql = "SELECT * FROM ".$schema."".$table_name."";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+while ($row = oci_fetch_array($s)) {
+ var_dump($row);
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+while ($row = oci_fetch_array($s, OCI_NUM)) {
+ var_dump($row);
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+while ($row = oci_fetch_array($s, OCI_ASSOC)) {
+ var_dump($row);
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+while ($row = oci_fetch_array($s, OCI_BOTH)) {
+ var_dump($row);
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+while ($row = oci_fetch_array($s, OCI_RETURN_LOBS)) {
+ var_dump($row);
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+while ($row = oci_fetch_array($s, OCI_RETURN_NULLS)) {
+ var_dump($row);
+}
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECT--
+array(10) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ ["BLOB"]=>
+ NULL
+ [3]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ [4]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+array(10) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ ["BLOB"]=>
+ NULL
+ [3]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ [4]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+array(10) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ ["BLOB"]=>
+ NULL
+ [3]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ [4]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+array(2) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(2) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(2) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(4) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(4) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(4) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(4) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(4) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(4) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+array(10) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ ["BLOB"]=>
+ NULL
+ [3]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ [4]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+array(10) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ ["BLOB"]=>
+ NULL
+ [3]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ [4]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+array(10) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ ["BLOB"]=>
+ NULL
+ [3]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ [4]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+Done
diff --git a/tests/fetch_assoc.phpt b/tests/fetch_assoc.phpt
new file mode 100644
index 0000000000..7dacf2e5b2
--- /dev/null
+++ b/tests/fetch_assoc.phpt
@@ -0,0 +1,82 @@
+--TEST--
+oci_fetch_assoc()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__).'/create_table.inc';
+
+$insert_sql = "INSERT INTO ".$schema."".$table_name." (id, value) VALUES (1,1)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+if (!oci_commit($c)) {
+ die("oci_commit() failed!\n");
+}
+
+$select_sql = "SELECT * FROM ".$schema."".$table_name."";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+while ($row = oci_fetch_assoc($s)) {
+ var_dump($row);
+}
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+array(5) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ ["BLOB"]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+array(5) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ ["BLOB"]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+array(5) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ ["BLOB"]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+Done
diff --git a/tests/fetch_into.phpt b/tests/fetch_into.phpt
new file mode 100644
index 0000000000..17e06e1cf8
--- /dev/null
+++ b/tests/fetch_into.phpt
@@ -0,0 +1,90 @@
+--TEST--
+ocifetchinto()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table fetch_into_tab",
+ "create table fetch_into_tab (id number, value number)",
+ "insert into fetch_into_tab (id, value) values (1,1)",
+ "insert into fetch_into_tab (id, value) values (1,1)",
+ "insert into fetch_into_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+if (!($s = oci_parse($c, "select * from fetch_into_tab"))) {
+ die("oci_parse(select) failed!\n");
+}
+
+/* ocifetchinto */
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+var_dump(ocifetchinto($s, $all));
+var_dump($all);
+
+/* ocifetchinto */
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+var_dump(ocifetchinto($s, $all, OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS));
+var_dump($all);
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table fetch_into_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECTF--
+int(2)
+array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+}
+int(2)
+array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"ID"]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+ [%u|b%"VALUE"]=>
+ %unicode|string%(1) "1"
+}
+Done
diff --git a/tests/fetch_into1.phpt b/tests/fetch_into1.phpt
new file mode 100644
index 0000000000..263590d140
--- /dev/null
+++ b/tests/fetch_into1.phpt
@@ -0,0 +1,192 @@
+--TEST--
+various ocifetchinto() tests
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__).'/create_table.inc';
+
+$insert_sql = "INSERT INTO ".$schema."".$table_name." (id, value, string) VALUES (1, 1, NULL)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<20; $i++) {
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+if (!oci_commit($c)) {
+ die("oci_commit() failed!\n");
+}
+
+$select_sql = "SELECT * FROM ".$schema."".$table_name."";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+var_dump(ocifetchinto($s, $all, OCI_NUM));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_ASSOC));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_RETURN_NULLS));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_RETURN_LOBS));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_NUM+OCI_ASSOC));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_RETURN_NULLS+OCI_RETURN_LOBS));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS));
+var_dump($all);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECT--
+int(5)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+int(5)
+array(2) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+int(5)
+array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+}
+int(5)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+int(5)
+array(4) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+}
+int(5)
+array(10) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ ["BLOB"]=>
+ NULL
+ [3]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ [4]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+int(5)
+array(10) {
+ [0]=>
+ string(1) "1"
+ ["ID"]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ ["BLOB"]=>
+ NULL
+ [3]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ [4]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+int(5)
+array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+}
+int(5)
+array(5) {
+ ["ID"]=>
+ string(1) "1"
+ ["VALUE"]=>
+ string(1) "1"
+ ["BLOB"]=>
+ NULL
+ ["CLOB"]=>
+ NULL
+ ["STRING"]=>
+ NULL
+}
+int(5)
+array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+}
+Done
diff --git a/tests/fetch_into2.phpt b/tests/fetch_into2.phpt
new file mode 100644
index 0000000000..c196d39f62
--- /dev/null
+++ b/tests/fetch_into2.phpt
@@ -0,0 +1,70 @@
+--TEST--
+ocifetchinto() & wrong number of params
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__).'/create_table.inc';
+
+$insert_sql = "INSERT INTO ".$schema."".$table_name." (id, value, string) VALUES (1, 1, NULL)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<20; $i++) {
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+if (!oci_commit($c)) {
+ die("oci_commit() failed!\n");
+}
+
+$select_sql = "SELECT * FROM ".$schema."".$table_name."";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+var_dump(ocifetchinto($s));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, OCI_ASSOC, 5));
+var_dump($all);
+var_dump(ocifetchinto($c, $all, OCI_RETURN_LOBS));
+var_dump($all);
+var_dump(ocifetchinto($s, $all, 1000000));
+var_dump($all);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: ocifetchinto() expects at least 2 parameters, 1 given in %s on line %d
+NULL
+
+Notice: Undefined variable: all in %s on line %d
+NULL
+
+Warning: ocifetchinto() expects at most 3 parameters, 4 given in %s on line %d
+NULL
+NULL
+
+Warning: ocifetchinto(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+NULL
+int(5)
+array(2) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+}
+Done
diff --git a/tests/fetch_object.phpt b/tests/fetch_object.phpt
new file mode 100644
index 0000000000..674a88ff28
--- /dev/null
+++ b/tests/fetch_object.phpt
@@ -0,0 +1,137 @@
+--TEST--
+oci_fetch_object()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table fetch_object_tab",
+ "create table fetch_object_tab (\"caseSensitive\" number, secondcol varchar2(20), anothercol char(15))",
+ "insert into fetch_object_tab values (123, '1st row col2 string', '1 more text')",
+ "insert into fetch_object_tab values (456, '2nd row col2 string', '2 more text')",
+ "insert into fetch_object_tab values (789, '3rd row col2 string', '3 more text')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+if (!($s = oci_parse($c, 'select * from fetch_object_tab'))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+while ($row = oci_fetch_object($s)) {
+ var_dump($row);
+}
+
+echo "Test 2\n";
+
+if (!($s = oci_parse($c, 'select * from fetch_object_tab'))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+while ($row = oci_fetch_object($s)) {
+ echo $row->caseSensitive . "\n";
+ echo $row->SECONDCOL . "\n";
+ echo $row->ANOTHERCOL . "\n";
+}
+
+echo "Test 3\n";
+
+if (!($s = oci_parse($c, 'select * from fetch_object_tab where rownum < 2 order by "caseSensitive"'))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+$row = oci_fetch_object($s);
+echo $row->caseSensitive . "\n";
+echo $row->CASESENSITIVE . "\n";
+
+// Clean up
+
+$stmtarray = array(
+ "drop table fetch_object_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+object(stdClass)#1 (3) {
+ [%u|b%"caseSensitive"]=>
+ %unicode|string%(3) "123"
+ [%u|b%"SECONDCOL"]=>
+ %unicode|string%(19) "1st row col2 string"
+ [%u|b%"ANOTHERCOL"]=>
+ %unicode|string%(15) "1 more text "
+}
+object(stdClass)#2 (3) {
+ [%u|b%"caseSensitive"]=>
+ %unicode|string%(3) "456"
+ [%u|b%"SECONDCOL"]=>
+ %unicode|string%(19) "2nd row col2 string"
+ [%u|b%"ANOTHERCOL"]=>
+ %unicode|string%(15) "2 more text "
+}
+object(stdClass)#1 (3) {
+ [%u|b%"caseSensitive"]=>
+ %unicode|string%(3) "789"
+ [%u|b%"SECONDCOL"]=>
+ %unicode|string%(19) "3rd row col2 string"
+ [%u|b%"ANOTHERCOL"]=>
+ %unicode|string%(15) "3 more text "
+}
+Test 2
+123
+1st row col2 string
+1 more text
+456
+2nd row col2 string
+2 more text
+789
+3rd row col2 string
+3 more text
+Test 3
+123
+
+Notice: Undefined property: stdClass::$CASESENSITIVE in %sfetch_object.php on line %d
+
+===DONE===
diff --git a/tests/fetch_object_2.phpt b/tests/fetch_object_2.phpt
new file mode 100644
index 0000000000..b078ebb1d3
--- /dev/null
+++ b/tests/fetch_object_2.phpt
@@ -0,0 +1,127 @@
+--TEST--
+oci_fetch_object() with CLOB and NULL
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table fetch_object_2_tab",
+ "create table fetch_object_2_tab (col1 number, col2 CLOB, col3 varchar2(15))",
+ "insert into fetch_object_2_tab values (123, '1st row col2 string', '1 more text')",
+ "insert into fetch_object_2_tab values (456, '2nd row col2 string', NULL)",
+ "insert into fetch_object_2_tab values (789, '3rd row col2 string', '3 more text')",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+echo "Test 1\n";
+
+if (!($s = oci_parse($c, 'select * from fetch_object_2_tab order by 1'))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+while ($row = oci_fetch_object($s)) {
+ var_dump($row);
+}
+
+echo "Test 2\n";
+
+if (!($s = oci_parse($c, 'select * from fetch_object_2_tab order by 1'))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+while ($row = oci_fetch_object($s)) {
+ echo $row->COL1 . "\n";
+ echo $row->COL2->load(100) . "\n";
+ echo $row->COL3 . "\n";
+}
+
+// Clean up
+
+$stmtarray = array(
+ "drop table fetch_object_2_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+object(stdClass)#%d (3) {
+ [%u|b%"COL1"]=>
+ %unicode|string%(3) "123"
+ [%u|b%"COL2"]=>
+ object(OCI-Lob)#%d (1) {
+ [%u|b%"descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ [%u|b%"COL3"]=>
+ %unicode|string%(11) "1 more text"
+}
+object(stdClass)#%d (3) {
+ [%u|b%"COL1"]=>
+ %unicode|string%(3) "456"
+ [%u|b%"COL2"]=>
+ object(OCI-Lob)#%d (1) {
+ [%u|b%"descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ [%u|b%"COL3"]=>
+ NULL
+}
+object(stdClass)#%d (3) {
+ [%u|b%"COL1"]=>
+ %unicode|string%(3) "789"
+ [%u|b%"COL2"]=>
+ object(OCI-Lob)#%d (1) {
+ [%u|b%"descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ [%u|b%"COL3"]=>
+ %unicode|string%(11) "3 more text"
+}
+Test 2
+123
+1st row col2 string
+1 more text
+456
+2nd row col2 string
+
+789
+3rd row col2 string
+3 more text
+===DONE===
diff --git a/tests/fetch_row.phpt b/tests/fetch_row.phpt
new file mode 100644
index 0000000000..c6084d4fe2
--- /dev/null
+++ b/tests/fetch_row.phpt
@@ -0,0 +1,84 @@
+--TEST--
+oci_fetch_row()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table fetch_row_tab",
+ "create table fetch_row_tab (id number, value number)",
+ "insert into fetch_row_tab (id, value) values (1,1)",
+ "insert into fetch_row_tab (id, value) values (1,1)",
+ "insert into fetch_row_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+if (!($s = oci_parse($c, "select * from fetch_row_tab"))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+while ($row = oci_fetch_row($s)) {
+ var_dump($row);
+}
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table fetch_row_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+}
+Done
diff --git a/tests/field_funcs.phpt b/tests/field_funcs.phpt
new file mode 100644
index 0000000000..18143f6f1b
--- /dev/null
+++ b/tests/field_funcs.phpt
@@ -0,0 +1,105 @@
+--TEST--
+oci_field_*() family
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__).'/create_table.inc';
+
+$insert_sql = "INSERT INTO ".$schema."".$table_name." (id, value) VALUES (1,1)";
+
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+if (!oci_commit($c)) {
+ die("oci_commit() failed!\n");
+}
+
+$select_sql = "SELECT * FROM ".$schema."".$table_name."";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+$row = oci_fetch_array($s, OCI_NUM + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
+var_dump($row);
+
+foreach ($row as $num => $field) {
+ $num++;
+ var_dump(oci_field_is_null($s, $num));
+ var_dump(oci_field_name($s, $num));
+ var_dump(oci_field_type($s, $num));
+ var_dump(oci_field_type_raw($s, $num));
+ var_dump(oci_field_scale($s, $num));
+ var_dump(oci_field_precision($s, $num));
+ var_dump(oci_field_size($s, $num));
+}
+
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+}
+bool(false)
+string(2) "ID"
+string(6) "NUMBER"
+int(2)
+int(-127)
+int(0)
+int(22)
+bool(false)
+string(5) "VALUE"
+string(6) "NUMBER"
+int(2)
+int(-127)
+int(0)
+int(22)
+bool(true)
+string(4) "BLOB"
+string(4) "BLOB"
+int(113)
+int(0)
+int(0)
+int(4000)
+bool(true)
+string(4) "CLOB"
+string(4) "CLOB"
+int(112)
+int(0)
+int(0)
+int(4000)
+bool(true)
+string(6) "STRING"
+string(8) "VARCHAR2"
+int(1)
+int(0)
+int(0)
+int(10)
+Done
diff --git a/tests/field_funcs1.phpt b/tests/field_funcs1.phpt
new file mode 100644
index 0000000000..0b4ad76b39
--- /dev/null
+++ b/tests/field_funcs1.phpt
@@ -0,0 +1,194 @@
+--TEST--
+oci_field_*() family
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table field_funcs1_tab",
+ "create table field_funcs1_tab (id number, value number)",
+ "insert into field_funcs1_tab (id, value) values (1,1)",
+ "insert into field_funcs1_tab (id, value) values (1,1)",
+ "insert into field_funcs1_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+if (!($s = oci_parse($c, "select * from field_funcs1_tab"))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+$row = oci_fetch_array($s, OCI_NUM + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
+var_dump($row);
+
+var_dump(oci_field_is_null($s, -1));
+var_dump(oci_field_name($s, -1));
+var_dump(oci_field_type($s, -1));
+var_dump(oci_field_type_raw($s, -1));
+var_dump(oci_field_scale($s, -1));
+var_dump(oci_field_precision($s, -1));
+var_dump(oci_field_size($s, -1));
+
+var_dump(oci_field_is_null($s, "none"));
+var_dump(oci_field_name($s, "none"));
+var_dump(oci_field_type($s, "none"));
+var_dump(oci_field_type_raw($s, "none"));
+var_dump(oci_field_scale($s, "none"));
+var_dump(oci_field_precision($s, "none"));
+var_dump(oci_field_size($s, "none"));
+
+var_dump(oci_field_is_null($c, -1));
+var_dump(oci_field_name($c, -1));
+var_dump(oci_field_type($c, -1));
+var_dump(oci_field_type_raw($c, -1));
+var_dump(oci_field_scale($c, -1));
+var_dump(oci_field_precision($c, -1));
+var_dump(oci_field_size($c, -1));
+
+var_dump(oci_field_is_null($s, array()));
+var_dump(oci_field_name($s, array()));
+var_dump(oci_field_type($s, array()));
+var_dump(oci_field_type_raw($s, array()));
+var_dump(oci_field_scale($s, array()));
+var_dump(oci_field_precision($s, array()));
+var_dump(oci_field_size($s, array()));
+
+var_dump(oci_field_size($s));
+
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table field_funcs1_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "1"
+}
+
+Warning: oci_field_is_null(): Invalid column index "-1" in %s on line %d
+bool(false)
+
+Warning: oci_field_name(): Invalid column index "-1" in %s on line %d
+bool(false)
+
+Warning: oci_field_type(): Invalid column index "-1" in %s on line %d
+bool(false)
+
+Warning: oci_field_type_raw(): Invalid column index "-1" in %s on line %d
+bool(false)
+
+Warning: oci_field_scale(): Invalid column index "-1" in %s on line %d
+bool(false)
+
+Warning: oci_field_precision(): Invalid column index "-1" in %s on line %d
+bool(false)
+
+Warning: oci_field_size(): Invalid column index "-1" in %s on line %d
+bool(false)
+
+Warning: oci_field_is_null(): Invalid column name "none" in %s on line %d
+bool(false)
+
+Warning: oci_field_name(): Invalid column name "none" in %s on line %d
+bool(false)
+
+Warning: oci_field_type(): Invalid column name "none" in %s on line %d
+bool(false)
+
+Warning: oci_field_type_raw(): Invalid column name "none" in %s on line %d
+bool(false)
+
+Warning: oci_field_scale(): Invalid column name "none" in %s on line %d
+bool(false)
+
+Warning: oci_field_precision(): Invalid column name "none" in %s on line %d
+bool(false)
+
+Warning: oci_field_size(): Invalid column name "none" in %s on line %d
+bool(false)
+
+Warning: oci_field_is_null(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+
+Warning: oci_field_name(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+
+Warning: oci_field_type(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+
+Warning: oci_field_type_raw(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+
+Warning: oci_field_scale(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+
+Warning: oci_field_precision(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+
+Warning: oci_field_size(): supplied resource is not a valid oci8 statement resource in %s on line %d
+bool(false)
+
+Warning: oci_field_is_null(): Invalid column index "0" in %s on line %d
+bool(false)
+
+Warning: oci_field_name(): Invalid column index "0" in %s on line %d
+bool(false)
+
+Warning: oci_field_type(): Invalid column index "0" in %s on line %d
+bool(false)
+
+Warning: oci_field_type_raw(): Invalid column index "0" in %s on line %d
+bool(false)
+
+Warning: oci_field_scale(): Invalid column index "0" in %s on line %d
+bool(false)
+
+Warning: oci_field_precision(): Invalid column index "0" in %s on line %d
+bool(false)
+
+Warning: oci_field_size(): Invalid column index "0" in %s on line %d
+bool(false)
+
+Warning: oci_field_size() expects exactly 2 parameters, 1 given in %s on line %d
+bool(false)
+Done
diff --git a/tests/field_funcs2.phpt b/tests/field_funcs2.phpt
new file mode 100644
index 0000000000..502d079139
--- /dev/null
+++ b/tests/field_funcs2.phpt
@@ -0,0 +1,69 @@
+--TEST--
+Bug #41917 (invalid scale and precision)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+$s = oci_parse($c, 'drop table field_funcs2_tab');
+@oci_execute($s);
+
+$t = array("C01" => "NUMBER",
+ "C02" => "NUMBER(*,1)",
+ "C03" => "NUMBER(9)",
+ "C04" => "NUMBER(9,2)",
+ "C05" => "NUMBER(9,1)",
+ "C06" => "NUMBER(7,-2)",
+ "C07" => "DECIMAL(4,9)",
+ "C08" => "NUMERIC(4,9)",
+ "C09" => "DECIMAL(4)",
+ "C10" => "INTEGER",
+ "C11" => "INT",
+ "C12" => "SMALLINT",
+ "C13" => "FLOAT",
+ "C14" => "FLOAT(9)",
+ "C15" => "DOUBLE PRECISION",
+ "C16" => "REAL",
+ );
+
+$stmt = "create table field_funcs2_tab (\n";
+foreach ($t as $colname => $type) {
+ $stmt .= "$colname $type,\n";
+}
+$stmt[strlen($stmt)-2] = ")";
+
+$s = oci_parse($c, $stmt);
+oci_execute($s);
+
+$s = oci_parse($c, "select * from field_funcs2_tab");
+oci_execute($s);
+
+for ($i = 1; $i <= oci_num_fields($s); $i++) {
+ $name = oci_field_name($s, $i);
+ $precision = oci_field_precision($s, $i);
+ $scale = oci_field_scale($s, $i);
+ echo "$name ".$t[$name] .": precision $precision, scale $scale\n";
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+C01 NUMBER: precision 0, scale -127
+C02 NUMBER(*,1): precision 38, scale 1
+C03 NUMBER(9): precision 9, scale 0
+C04 NUMBER(9,2): precision 9, scale 2
+C05 NUMBER(9,1): precision 9, scale 1
+C06 NUMBER(7,-2): precision 7, scale -2
+C07 DECIMAL(4,9): precision 4, scale 9
+C08 NUMERIC(4,9): precision 4, scale 9
+C09 DECIMAL(4): precision 4, scale 0
+C10 INTEGER: precision 38, scale 0
+C11 INT: precision 38, scale 0
+C12 SMALLINT: precision 38, scale 0
+C13 FLOAT: precision 126, scale -127
+C14 FLOAT(9): precision 9, scale -127
+C15 DOUBLE PRECISION: precision 126, scale -127
+C16 REAL: precision 63, scale -127
+Done
diff --git a/tests/field_funcs_old.phpt b/tests/field_funcs_old.phpt
new file mode 100644
index 0000000000..e0d24cd7b7
--- /dev/null
+++ b/tests/field_funcs_old.phpt
@@ -0,0 +1,105 @@
+--TEST--
+ocicolumn*() family
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+require dirname(__FILE__).'/create_table.inc';
+
+$insert_sql = "INSERT INTO ".$schema."".$table_name." (id, value) VALUES (1,1)";
+
+if (!($s = ociparse($c, $insert_sql))) {
+ die("ociparse(insert) failed!\n");
+}
+
+for ($i = 0; $i<3; $i++) {
+ if (!ociexecute($s)) {
+ die("ociexecute(insert) failed!\n");
+ }
+}
+
+if (!ocicommit($c)) {
+ die("ocicommit() failed!\n");
+}
+
+$select_sql = "SELECT * FROM ".$schema."".$table_name."";
+
+if (!($s = ociparse($c, $select_sql))) {
+ die("ociparse(select) failed!\n");
+}
+
+if (!ociexecute($s)) {
+ die("ociexecute(select) failed!\n");
+}
+
+ocifetchinto($s, $row, OCI_NUM + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
+var_dump($row);
+
+foreach ($row as $num => $field) {
+ $num++;
+ var_dump(ocicolumnisnull($s, $num));
+ var_dump(ocicolumnname($s, $num));
+ var_dump(ocicolumntype($s, $num));
+ var_dump(ocicolumntyperaw($s, $num));
+ var_dump(ocicolumnscale($s, $num));
+ var_dump(ocicolumnprecision($s, $num));
+ var_dump(ocicolumnsize($s, $num));
+}
+
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+array(5) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "1"
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+}
+bool(false)
+string(2) "ID"
+string(6) "NUMBER"
+int(2)
+int(-127)
+int(0)
+int(22)
+bool(false)
+string(5) "VALUE"
+string(6) "NUMBER"
+int(2)
+int(-127)
+int(0)
+int(22)
+bool(true)
+string(4) "BLOB"
+string(4) "BLOB"
+int(113)
+int(0)
+int(0)
+int(4000)
+bool(true)
+string(4) "CLOB"
+string(4) "CLOB"
+int(112)
+int(0)
+int(0)
+int(4000)
+bool(true)
+string(6) "STRING"
+string(8) "VARCHAR2"
+int(1)
+int(0)
+int(0)
+int(10)
+Done
diff --git a/tests/function_aliases.phpt b/tests/function_aliases.phpt
new file mode 100644
index 0000000000..4c6ce83759
--- /dev/null
+++ b/tests/function_aliases.phpt
@@ -0,0 +1,198 @@
+--TEST--
+Existence of old function aliases
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+var_dump(oci_free_cursor());
+var_dump(ocifreecursor());
+var_dump(ocibindbyname());
+var_dump(ocidefinebyname());
+var_dump(ocicolumnisnull());
+var_dump(ocicolumnname());
+var_dump(ocicolumnsize());
+var_dump(ocicolumnscale());
+var_dump(ocicolumnprecision());
+var_dump(ocicolumntype());
+var_dump(ocicolumntyperaw());
+var_dump(ociexecute());
+var_dump(ocicancel());
+var_dump(ocifetch());
+var_dump(ocifetchstatement());
+var_dump(ocifreestatement());
+var_dump(ociinternaldebug());
+var_dump(ocinumcols());
+var_dump(ociparse());
+var_dump(ocinewcursor());
+var_dump(ociresult());
+var_dump(ociserverversion());
+var_dump(ocistatementtype());
+var_dump(ocirowcount());
+var_dump(ocilogoff());
+var_dump(ocilogon());
+var_dump(ocinlogon());
+var_dump(ociplogon());
+var_dump(ocierror());
+var_dump(ocifreedesc());
+var_dump(ocisavelob());
+var_dump(ocisavelobfile());
+var_dump(ociwritelobtofile());
+var_dump(ociloadlob());
+var_dump(ocicommit());
+var_dump(ocirollback());
+var_dump(ocinewdescriptor());
+var_dump(ocisetprefetch());
+var_dump(ocipasswordchange());
+var_dump(ocifreecollection());
+var_dump(ocinewcollection());
+var_dump(ocicollappend());
+var_dump(ocicollgetelem());
+var_dump(ocicollassignelem());
+var_dump(ocicollsize());
+var_dump(ocicollmax());
+var_dump(ocicolltrim());
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: oci_free_cursor() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocifreecursor() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocibindbyname() expects at least 3 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocidefinebyname() expects at least 3 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocicolumnisnull() expects exactly 2 parameters, 0 given in %s on line %d
+bool(false)
+
+Warning: ocicolumnname() expects exactly 2 parameters, 0 given in %s on line %d
+bool(false)
+
+Warning: ocicolumnsize() expects exactly 2 parameters, 0 given in %s on line %d
+bool(false)
+
+Warning: ocicolumnscale() expects exactly 2 parameters, 0 given in %s on line %d
+bool(false)
+
+Warning: ocicolumnprecision() expects exactly 2 parameters, 0 given in %s on line %d
+bool(false)
+
+Warning: ocicolumntype() expects exactly 2 parameters, 0 given in %s on line %d
+bool(false)
+
+Warning: ocicolumntyperaw() expects exactly 2 parameters, 0 given in %s on line %d
+bool(false)
+
+Warning: ociexecute() expects at least 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocicancel() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocifetch() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocifetchstatement() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocifreestatement() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ociinternaldebug() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocinumcols() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ociparse() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocinewcursor() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ociresult() expects exactly 2 parameters, 0 given in %s on line %d
+bool(false)
+
+Warning: ociserverversion() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocistatementtype() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocirowcount() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocilogoff() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocilogon() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocinlogon() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ociplogon() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+bool(false)
+
+Warning: ocifreedesc() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocisavelob() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocisavelobfile() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ociwritelobtofile() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ociloadlob() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocicommit() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocirollback() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocinewdescriptor() expects at least 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocisetprefetch() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: Wrong parameter count for ocipasswordchange() in %s on line %d
+NULL
+
+Warning: ocifreecollection() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocinewcollection() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocicollappend() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocicollgetelem() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocicollassignelem() expects exactly 3 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocicollsize() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocicollmax() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocicolltrim() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+Done
diff --git a/tests/lob_001.phpt b/tests/lob_001.phpt
new file mode 100644
index 0000000000..cbcb92e7ec
--- /dev/null
+++ b/tests/lob_001.phpt
Binary files differ
diff --git a/tests/lob_002.phpt b/tests/lob_002.phpt
new file mode 100644
index 0000000000..ebbef1815e
--- /dev/null
+++ b/tests/lob_002.phpt
@@ -0,0 +1,66 @@
+--TEST--
+oci_lob_write() and friends (with errors)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+var_dump($blob->write("test", -1));
+var_dump($blob->write("test", "str"));
+var_dump($blob->write("test", 1000000));
+var_dump($blob->write(str_repeat("test", 10000), 1000000));
+var_dump($blob->tell());
+var_dump($blob->seek("str", -5));
+var_dump($blob->flush());
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name."";
+$s = oci_parse($c, $select_sql);
+oci_execute($s);
+
+$row = oci_fetch_array($s, OCI_RETURN_LOBS);
+
+var_dump(strlen($row[0]));
+
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+int(0)
+
+Warning: OCI-Lob::write() expects parameter 2 to be long, string given in %slob_002.php on line %d
+NULL
+int(4)
+int(40000)
+int(40004)
+
+Warning: OCI-Lob::seek() expects parameter 1 to be long, string given in %slob_002.php on line %d
+NULL
+bool(false)
+int(40004)
+Done
diff --git a/tests/lob_003.phpt b/tests/lob_003.phpt
new file mode 100644
index 0000000000..8a492d16ca
--- /dev/null
+++ b/tests/lob_003.phpt
Binary files differ
diff --git a/tests/lob_004.phpt b/tests/lob_004.phpt
new file mode 100644
index 0000000000..32de4a0120
--- /dev/null
+++ b/tests/lob_004.phpt
@@ -0,0 +1,80 @@
+--TEST--
+oci_lob_seek()/rewind()/append()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+var_dump($blob->write("test"));
+var_dump($blob->rewind());
+var_dump($blob->write("str"));
+var_dump($blob->seek(10, OCI_SEEK_SET));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+var_dump($row[0]->append($blob));
+var_dump($row[0]->read(10000));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+$row = oci_fetch_array($s);
+
+var_dump($row[0]->read(10000));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+int(4)
+bool(true)
+int(3)
+bool(true)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+bool(true)
+string(4) "strt"
+string(8) "strtstrt"
+Done
diff --git a/tests/lob_005.phpt b/tests/lob_005.phpt
new file mode 100644
index 0000000000..e1ac6e5340
--- /dev/null
+++ b/tests/lob_005.phpt
@@ -0,0 +1,52 @@
+--TEST--
+oci_lob_is_equal()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+var_dump(oci_lob_is_equal($row[0], $row['BLOB']));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+bool(true)
+Done
diff --git a/tests/lob_006.phpt b/tests/lob_006.phpt
new file mode 100644
index 0000000000..3192ebc906
--- /dev/null
+++ b/tests/lob_006.phpt
Binary files differ
diff --git a/tests/lob_007.phpt b/tests/lob_007.phpt
new file mode 100644
index 0000000000..1fe63092c6
--- /dev/null
+++ b/tests/lob_007.phpt
@@ -0,0 +1,66 @@
+--TEST--
+oci_lob_write()/size()/load()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+var_dump($blob->size());
+var_dump($blob->write(str_repeat("string.", 1000)));
+var_dump($blob->size());
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+var_dump($row[0]->size());
+var_dump(strlen($row[0]->load()));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+int(0)
+int(7000)
+int(7000)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+int(7000)
+int(7000)
+Done
diff --git a/tests/lob_008.phpt b/tests/lob_008.phpt
new file mode 100644
index 0000000000..a36bb4a340
--- /dev/null
+++ b/tests/lob_008.phpt
@@ -0,0 +1,65 @@
+--TEST--
+oci_lob_write()/read()/eof()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+var_dump($blob->write(str_repeat("string.", 1000)));
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+
+$len = 0;
+while (!$row[0]->eof()) {
+ $len += strlen($row[0]->read(1024));
+}
+var_dump($len);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+int(7000)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+int(7000)
+Done
diff --git a/tests/lob_009.phpt b/tests/lob_009.phpt
new file mode 100644
index 0000000000..b9f7401128
--- /dev/null
+++ b/tests/lob_009.phpt
@@ -0,0 +1,69 @@
+--TEST--
+oci_lob_import()/read()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+var_dump($blob->seek(10, OCI_SEEK_CUR));
+var_dump($blob->import(dirname(__FILE__)."/lob_009.txt"));
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+while (!$row[0]->eof()) {
+ var_dump($row[0]->read(1024));
+}
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+bool(true)
+bool(true)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(43) "this
+is
+a
+test
+file for
+test lob_009.phpt
+"
+Done
diff --git a/tests/lob_009.txt b/tests/lob_009.txt
new file mode 100644
index 0000000000..f57bc8af37
--- /dev/null
+++ b/tests/lob_009.txt
@@ -0,0 +1,6 @@
+this
+is
+a
+test
+file for
+test lob_009.phpt
diff --git a/tests/lob_010.phpt b/tests/lob_010.phpt
new file mode 100644
index 0000000000..59f3e145f2
--- /dev/null
+++ b/tests/lob_010.phpt
@@ -0,0 +1,46 @@
+--TEST--
+oci_lob_save()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob->save("string"));
+var_dump($blob->save("string", 3));
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+$row = oci_fetch_array($s);
+
+while (!$row[0]->eof()) {
+ var_dump($row[0]->read(1024));
+}
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+string(9) "strstring"
+Done
diff --git a/tests/lob_011.phpt b/tests/lob_011.phpt
new file mode 100644
index 0000000000..b074e1730e
--- /dev/null
+++ b/tests/lob_011.phpt
@@ -0,0 +1,78 @@
+--TEST--
+oci_lob_copy()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (id, blob)
+ VALUES (1, empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob->write("some string here. string, I said"));
+oci_commit($c);
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (id, blob)
+ VALUES (2, empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." WHERE id = 1";
+$s = oci_parse($c, $select_sql);
+oci_execute($s);
+
+$row1 = oci_fetch_array($s);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." WHERE id = 2 FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+$row2 = oci_fetch_array($s);
+
+var_dump(oci_lob_copy($row2[0], $row1[0]));
+var_dump($row1[0]->read(100));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." WHERE id = 2 FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row2 = oci_fetch_array($s, OCI_RETURN_LOBS));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+int(32)
+bool(true)
+string(32) "some string here. string, I said"
+array(2) {
+ [0]=>
+ string(32) "some string here. string, I said"
+ ["BLOB"]=>
+ string(32) "some string here. string, I said"
+}
+Done
diff --git a/tests/lob_012.phpt b/tests/lob_012.phpt
new file mode 100644
index 0000000000..2061969bc4
--- /dev/null
+++ b/tests/lob_012.phpt
@@ -0,0 +1,50 @@
+--TEST--
+oci_lob_export()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+$blob;
+
+var_dump($blob->write("test string is here\nnew string"));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+$row = oci_fetch_array($s);
+
+var_dump($row[0]->export(dirname(__FILE__)."/lob_012.tmp", 3, 10));
+
+var_dump(file_get_contents(dirname(__FILE__)."/lob_012.tmp"));
+
+@unlink(dirname(__FILE__)."/lob_012.tmp");
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+int(30)
+bool(true)
+string(10) "t string i"
+Done
diff --git a/tests/lob_013.phpt b/tests/lob_013.phpt
new file mode 100644
index 0000000000..c56de56198
--- /dev/null
+++ b/tests/lob_013.phpt
@@ -0,0 +1,54 @@
+--TEST--
+lob buffering
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob->write("test"));
+var_dump($blob->getBuffering());
+var_dump($blob->setBuffering(true));
+var_dump($blob->write("test"));
+var_dump($blob->getBuffering());
+var_dump($blob->flush());
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name."";
+$s = oci_parse($c, $select_sql);
+oci_execute($s);
+
+$row = oci_fetch_array($s, OCI_RETURN_LOBS);
+
+var_dump($row[0]);
+
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+int(4)
+bool(false)
+bool(true)
+int(4)
+bool(true)
+bool(true)
+string(8) "testtest"
+Done
diff --git a/tests/lob_014.phpt b/tests/lob_014.phpt
new file mode 100644
index 0000000000..1ba29ee649
--- /dev/null
+++ b/tests/lob_014.phpt
@@ -0,0 +1,56 @@
+--TEST--
+oci_lob_free()/close()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+$blob;
+
+var_dump($blob->write("test"));
+var_dump($blob->close());
+var_dump($blob->write("test"));
+var_dump($blob->free());
+var_dump($blob->write("test"));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name."";
+$s = oci_parse($c, $select_sql);
+oci_execute($s);
+
+var_dump(oci_fetch_array($s, OCI_NUM + OCI_RETURN_LOBS));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+int(4)
+bool(true)
+int(4)
+bool(true)
+
+Warning: OCI-Lob::write(): %d is not a valid oci8 descriptor resource in %slob_014.php on line %d
+bool(false)
+array(1) {
+ [0]=>
+ string(8) "testtest"
+}
+Done
diff --git a/tests/lob_015.phpt b/tests/lob_015.phpt
new file mode 100644
index 0000000000..297d5b4971
--- /dev/null
+++ b/tests/lob_015.phpt
@@ -0,0 +1,53 @@
+--TEST--
+various tests with wrong param count
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB,1,2,3);
+$blob = oci_new_descriptor($c);
+$int = 1;
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB,4);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB,4,5);
+oci_bind_by_name($statement,":v_blob", $int,-1);
+oci_bind_by_name($statement,":v_blob", $int);
+oci_bind_by_name($statement,":v_blob");
+oci_bind_by_name($statement);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: oci_new_descriptor() expects at most 2 parameters, 5 given in %s on line %d
+
+Warning: oci_bind_by_name() expects at most 5 parameters, 6 given in %s on line %d
+
+Warning: oci_bind_by_name() expects at most 5 parameters, 7 given in %s on line %d
+
+Warning: oci_bind_by_name() expects at least 3 parameters, 2 given in %s on line %d
+
+Warning: oci_bind_by_name() expects at least 3 parameters, 1 given in %s on line %d
+
+Warning: oci_execute(): ORA-00932: inconsistent datatypes: expected NUMBER got BLOB in %s on line %d
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+Done
diff --git a/tests/lob_016.phpt b/tests/lob_016.phpt
new file mode 100644
index 0000000000..642e7195ef
--- /dev/null
+++ b/tests/lob_016.phpt
@@ -0,0 +1,67 @@
+--TEST--
+returning multiple lobs
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table lob_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table lob_test(lob_1 BLOB, lob_2 BLOB)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$init = "INSERT INTO lob_test VALUES(EMPTY_BLOB(), EMPTY_BLOB())";
+$statement = oci_parse($c, $init);
+oci_execute($statement);
+
+$select = "SELECT * FROM lob_test FOR UPDATE";
+$statement = oci_parse($c, $select);
+oci_execute($statement, OCI_DEFAULT);
+
+$row = oci_fetch_assoc($statement);
+
+$row['LOB_1']->write("first");
+$row['LOB_2']->write("second");
+
+unset($row);
+
+oci_commit($c);
+
+$select = "SELECT * FROM lob_test FOR UPDATE";
+$statement = oci_parse($c, $select);
+oci_execute($statement, OCI_DEFAULT);
+
+$row = oci_fetch_assoc($statement);
+
+var_dump($row);
+var_dump($row['LOB_1']->load());
+var_dump($row['LOB_2']->load());
+
+$drop = "DROP table lob_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+array(2) {
+ ["LOB_1"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["LOB_2"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(5) "first"
+string(6) "second"
+Done
diff --git a/tests/lob_017.phpt b/tests/lob_017.phpt
new file mode 100644
index 0000000000..ed12cc4685
--- /dev/null
+++ b/tests/lob_017.phpt
@@ -0,0 +1,69 @@
+--TEST--
+returning multiple lobs (using persistent connection)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$c = oci_pconnect($user, $password, $dbase);
+
+$drop = "DROP table lob_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table lob_test(lob_1 BLOB, lob_2 BLOB)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$init = "INSERT INTO lob_test VALUES(EMPTY_BLOB(), EMPTY_BLOB())";
+$statement = oci_parse($c, $init);
+oci_execute($statement);
+
+$select = "SELECT * FROM lob_test FOR UPDATE";
+$statement = oci_parse($c, $select);
+oci_execute($statement, OCI_DEFAULT);
+
+$row = oci_fetch_assoc($statement);
+
+$row['LOB_1']->write("first");
+$row['LOB_2']->write("second");
+
+unset($row);
+
+oci_commit($c);
+
+$select = "SELECT * FROM lob_test FOR UPDATE";
+$statement = oci_parse($c, $select);
+oci_execute($statement, OCI_DEFAULT);
+
+$row = oci_fetch_assoc($statement);
+
+var_dump($row);
+var_dump($row['LOB_1']->load());
+var_dump($row['LOB_2']->load());
+
+$drop = "DROP table lob_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+array(2) {
+ ["LOB_1"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["LOB_2"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(5) "first"
+string(6) "second"
+Done
diff --git a/tests/lob_018.phpt b/tests/lob_018.phpt
new file mode 100644
index 0000000000..35cec4bd7d
--- /dev/null
+++ b/tests/lob_018.phpt
@@ -0,0 +1,67 @@
+--TEST--
+fetching the same lob several times
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table lob_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table lob_test(mykey NUMBER, lob_1 CLOB)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$init = "INSERT INTO lob_test (mykey, lob_1) VALUES(1, EMPTY_CLOB()) RETURNING lob_1 INTO :mylob";
+$statement = oci_parse($c, $init);
+$clob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($statement, ":mylob", $clob, -1, OCI_B_CLOB);
+oci_execute($statement, OCI_DEFAULT);
+$clob->save("data");
+
+oci_commit($c);
+
+$init = "INSERT INTO lob_test (mykey, lob_1) VALUES(2, EMPTY_CLOB()) RETURNING lob_1 INTO :mylob";
+$statement = oci_parse($c, $init);
+$clob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($statement, ":mylob", $clob, -1, OCI_B_CLOB);
+oci_execute($statement, OCI_DEFAULT);
+$clob->save("long data");
+
+oci_commit($c);
+
+
+$query = 'SELECT * FROM lob_test ORDER BY mykey ASC';
+$statement = oci_parse ($c, $query);
+oci_execute($statement, OCI_DEFAULT);
+
+while ($row = oci_fetch_array($statement, OCI_ASSOC)) {
+ $result = $row['LOB_1']->load();
+ var_dump($result);
+}
+
+$query = 'SELECT * FROM lob_test ORDER BY mykey DESC';
+$statement = oci_parse ($c, $query);
+oci_execute($statement, OCI_DEFAULT);
+
+while ($row = oci_fetch_array($statement, OCI_ASSOC)) {
+ $result = $row['LOB_1']->load();
+ var_dump($result);
+}
+
+$drop = "DROP table lob_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+string(4) "data"
+string(9) "long data"
+string(9) "long data"
+string(4) "data"
+Done
diff --git a/tests/lob_019.phpt b/tests/lob_019.phpt
new file mode 100644
index 0000000000..fb9a3c8188
--- /dev/null
+++ b/tests/lob_019.phpt
Binary files differ
diff --git a/tests/lob_020.phpt b/tests/lob_020.phpt
new file mode 100644
index 0000000000..6564dede9b
--- /dev/null
+++ b/tests/lob_020.phpt
Binary files differ
diff --git a/tests/lob_021.phpt b/tests/lob_021.phpt
new file mode 100644
index 0000000000..0ae6b377ab
--- /dev/null
+++ b/tests/lob_021.phpt
@@ -0,0 +1,70 @@
+--TEST--
+oci_lob_free()/close()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob->write("test"));
+var_dump($blob->close());
+var_dump($blob->write("test"));
+var_dump(oci_free_descriptor($blob));
+var_dump($blob->write("test"));
+
+var_dump(oci_free_descriptor($blob));
+var_dump(oci_free_descriptor(new stdclass));
+
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+unset($blob->descriptor);
+var_dump(oci_free_descriptor($blob));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name."";
+$s = oci_parse($c, $select_sql);
+oci_execute($s);
+
+var_dump(oci_fetch_array($s, OCI_NUM + OCI_RETURN_LOBS));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+int(4)
+bool(true)
+int(4)
+bool(true)
+
+Warning: OCI-Lob::write(): %d is not a valid oci8 descriptor resource in %s on line %d
+bool(false)
+
+Warning: oci_free_descriptor(): %d is not a valid oci8 descriptor resource in %s on line %d
+bool(false)
+
+Warning: oci_free_descriptor() expects parameter 1 to be OCI-Lob, object given in %s on line %d
+NULL
+
+Warning: oci_free_descriptor(): Unable to find descriptor property in %s on line %d
+bool(false)
+array(1) {
+ [0]=>
+ string(8) "testtest"
+}
+Done
diff --git a/tests/lob_022.phpt b/tests/lob_022.phpt
new file mode 100644
index 0000000000..5fb9dfab0e
--- /dev/null
+++ b/tests/lob_022.phpt
@@ -0,0 +1,80 @@
+--TEST--
+fetching the same lob several times
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$drop = "DROP table lob_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+$create = "CREATE table lob_test(mykey NUMBER, lob_1 CLOB)";
+$statement = oci_parse($c, $create);
+oci_execute($statement);
+
+$init = "INSERT INTO lob_test (mykey, lob_1) VALUES(1, EMPTY_CLOB()) RETURNING lob_1 INTO :mylob";
+$statement = oci_parse($c, $init);
+$clob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($statement, ":mylob", $clob, -1, OCI_B_CLOB);
+oci_execute($statement, OCI_DEFAULT);
+$clob->save();
+oci_lob_save();
+oci_lob_save($clob, "data");
+unset($clob->descriptor);
+oci_lob_save($clob, "data");
+
+oci_commit($c);
+
+$init = "INSERT INTO lob_test (mykey, lob_1) VALUES(2, EMPTY_CLOB()) RETURNING lob_1 INTO :mylob";
+$statement = oci_parse($c, $init);
+$clob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($statement, ":mylob", $clob, -1, OCI_B_CLOB);
+oci_execute($statement, OCI_DEFAULT);
+$clob->save("long data");
+$clob->save("long data", -1);
+$clob->save("long data", 0);
+
+oci_commit($c);
+
+
+$query = 'SELECT * FROM lob_test ORDER BY mykey ASC';
+$statement = oci_parse ($c, $query);
+oci_execute($statement, OCI_DEFAULT);
+
+while ($row = oci_fetch_array($statement, OCI_ASSOC)) {
+ $result = $row['LOB_1']->load();
+ var_dump($result);
+}
+
+$query = 'SELECT * FROM lob_test ORDER BY mykey DESC';
+$statement = oci_parse ($c, $query);
+oci_execute($statement, OCI_DEFAULT);
+
+while ($row = oci_fetch_array($statement, OCI_ASSOC)) {
+ $result = $row['LOB_1']->load();
+ var_dump($result);
+}
+
+$drop = "DROP table lob_test";
+$statement = oci_parse($c, $drop);
+@oci_execute($statement);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: OCI-Lob::save() expects at least 1 parameter, 0 given in %s on line %d
+
+Warning: oci_lob_save() expects at least 2 parameters, 0 given in %s on line %d
+
+Warning: oci_lob_save(): Unable to find descriptor property in %s on line %d
+
+Warning: OCI-Lob::save(): Offset parameter must be greater than or equal to 0 in %s on line %d
+string(4) "data"
+string(9) "long data"
+string(9) "long data"
+string(4) "data"
+Done
diff --git a/tests/lob_023.phpt b/tests/lob_023.phpt
new file mode 100644
index 0000000000..0c352956de
--- /dev/null
+++ b/tests/lob_023.phpt
@@ -0,0 +1,84 @@
+--TEST--
+oci_lob_import()/read()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+var_dump($blob->seek(10, OCI_SEEK_CUR));
+var_dump($blob->import(dirname(__FILE__)."/lob_009.txt"));
+var_dump($blob->import());
+var_dump(oci_lob_import($blob));
+var_dump(oci_lob_import($blob, dirname(__FILE__)."/lob_009.txt"));
+unset($blob->descriptor);
+var_dump(oci_lob_import($blob, dirname(__FILE__)."/lob_009.txt"));
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+while (!$row[0]->eof()) {
+ var_dump($row[0]->read(1024));
+}
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+bool(true)
+bool(true)
+
+Warning: OCI-Lob::import() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_import() expects exactly 2 parameters, 1 given in %s on line %d
+NULL
+bool(true)
+
+Warning: oci_lob_import(): Unable to find descriptor property in %s on line %d
+bool(false)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(43) "this
+is
+a
+test
+file for
+test lob_009.phpt
+"
+Done
diff --git a/tests/lob_024.phpt b/tests/lob_024.phpt
new file mode 100644
index 0000000000..9a7f53240d
--- /dev/null
+++ b/tests/lob_024.phpt
@@ -0,0 +1,75 @@
+--TEST--
+oci_lob_load()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+var_dump($blob->size());
+var_dump($blob->write(str_repeat("string.", 1000)));
+var_dump($blob->size());
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+var_dump(strlen($row[0]->load()));
+var_dump(strlen(oci_lob_load($row[0])));
+var_dump(oci_lob_load());
+unset($row[0]->descriptor);
+var_dump(oci_lob_load($row[0]));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+int(0)
+int(7000)
+int(7000)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+int(7000)
+int(7000)
+
+Warning: oci_lob_load() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_load(): Unable to find descriptor property in %s on line %d
+bool(false)
+Done
diff --git a/tests/lob_025.phpt b/tests/lob_025.phpt
new file mode 100644
index 0000000000..5b5e845a7a
--- /dev/null
+++ b/tests/lob_025.phpt
@@ -0,0 +1,82 @@
+--TEST--
+oci_lob_read() tests
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob->size());
+var_dump($blob->write(str_repeat("string.", 1000)));
+var_dump($blob->size());
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+var_dump(oci_lob_read($row[0], 2));
+var_dump(oci_lob_read($row[0]));
+var_dump(oci_lob_read());
+var_dump(oci_lob_eof($row[0]));
+var_dump(oci_lob_eof());
+
+unset($row[0]->descriptor);
+var_dump(oci_lob_read($row[0],1));
+var_dump(oci_lob_eof($row[0]));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+int(0)
+int(7000)
+int(7000)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(2) "st"
+
+Warning: oci_lob_read() expects exactly 2 parameters, 1 given in %s on line %d
+NULL
+
+Warning: oci_lob_read() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+bool(false)
+
+Warning: oci_lob_eof() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_read(): Unable to find descriptor property in %s on line %d
+bool(false)
+
+Warning: oci_lob_eof(): Unable to find descriptor property in %s on line %d
+bool(false)
+Done
diff --git a/tests/lob_026.phpt b/tests/lob_026.phpt
new file mode 100644
index 0000000000..157d78a2b6
--- /dev/null
+++ b/tests/lob_026.phpt
@@ -0,0 +1,100 @@
+--TEST--
+oci_lob_seek()/rewind()/append()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+var_dump(oci_lob_write($blob, "test"));
+var_dump(oci_lob_rewind());
+var_dump(oci_lob_rewind($blob));
+var_dump(oci_lob_write($blob, "str"));
+var_dump(oci_lob_seek(10, OCI_SEEK_SET));
+var_dump(oci_lob_seek($blob, 10, OCI_SEEK_SET));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+
+var_dump(oci_lob_append());
+var_dump(oci_lob_append($blob));
+var_dump(oci_lob_append($row[0], $blob));
+var_dump(oci_lob_read(10000));
+var_dump(oci_lob_read($row[0], 10000));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+$row = oci_fetch_array($s);
+
+var_dump(oci_lob_read($row[0], 10000));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+int(4)
+
+Warning: oci_lob_rewind() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+bool(true)
+int(3)
+
+Warning: oci_lob_seek() expects parameter 1 to be OCI-Lob, integer given in %s on line %d
+NULL
+bool(true)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+
+Warning: oci_lob_append() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_append() expects exactly 2 parameters, 1 given in %s on line %d
+NULL
+bool(true)
+
+Warning: oci_lob_read() expects exactly 2 parameters, 1 given in %s on line %d
+NULL
+string(4) "strt"
+string(8) "strtstrt"
+Done
diff --git a/tests/lob_027.phpt b/tests/lob_027.phpt
new file mode 100644
index 0000000000..8b49b1ac5b
--- /dev/null
+++ b/tests/lob_027.phpt
@@ -0,0 +1,103 @@
+--TEST--
+oci_lob_truncate()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+$str = "this is a biiiig faaat test string. why are you reading it, I wonder? =)";
+var_dump($blob->write($str));
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row = oci_fetch_array($s));
+oci_commit($c);
+
+for ($i = 5; $i >= 0; $i--) {
+
+ $select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+ $s = oci_parse($c, $select_sql);
+ oci_execute($s, OCI_DEFAULT);
+
+ $row = oci_fetch_array($s);
+ var_dump($row['BLOB']->load());
+ var_dump($row['BLOB']->truncate(($i-1)*10));
+
+ oci_commit($c);
+}
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+$row = oci_fetch_array($s);
+var_dump($row['BLOB']->load());
+var_dump($row['BLOB']->truncate(-1));
+var_dump($row['BLOB']->truncate(0));
+
+oci_commit($c);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+int(72)
+array(2) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+ ["BLOB"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(72) "this is a biiiig faaat test string. why are you reading it, I wonder? =)"
+bool(true)
+string(40) "this is a biiiig faaat test string. why "
+bool(true)
+string(30) "this is a biiiig faaat test st"
+bool(true)
+string(20) "this is a biiiig faa"
+bool(true)
+string(10) "this is a "
+bool(true)
+string(0) ""
+
+Warning: OCI-Lob::truncate(): Length must be greater than or equal to zero in %s on line %d
+bool(false)
+string(0) ""
+
+Warning: OCI-Lob::truncate(): Length must be greater than or equal to zero in %s on line %d
+bool(false)
+bool(true)
+Done
diff --git a/tests/lob_028.phpt b/tests/lob_028.phpt
new file mode 100644
index 0000000000..8ac2da3a32
--- /dev/null
+++ b/tests/lob_028.phpt
@@ -0,0 +1,84 @@
+--TEST--
+Test descriptor types for oci_new_descriptor()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Successful statements
+
+$d = oci_new_descriptor($c, OCI_D_FILE);
+var_dump($d);
+
+$d = oci_new_descriptor($c, OCI_DTYPE_FILE);
+var_dump($d);
+
+$d = oci_new_descriptor($c, OCI_D_LOB);
+var_dump($d);
+
+$d = oci_new_descriptor($c, OCI_DTYPE_LOB);
+var_dump($d);
+
+$d = oci_new_descriptor($c, OCI_D_ROWID);
+var_dump($d);
+
+$d = oci_new_descriptor($c, OCI_DTYPE_ROWID);
+var_dump($d);
+
+// Unsuccessful statements
+
+$d = oci_new_descriptor($c, OCI_B_CLOB);
+var_dump($d);
+
+$d = oci_new_descriptor($c, OCI_B_CLOB);
+var_dump($d);
+
+$d = oci_new_descriptor($c, OCI_DEFAULT);
+var_dump($d);
+
+$d = oci_new_descriptor($c, 1);
+var_dump($d);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+
+Warning: oci_new_descriptor(): Unknown descriptor type %d in %s on line %d
+NULL
+
+Warning: oci_new_descriptor(): Unknown descriptor type %d in %s on line %d
+NULL
+
+Warning: oci_new_descriptor(): Unknown descriptor type %d in %s on line %d
+NULL
+
+Warning: oci_new_descriptor(): Unknown descriptor type %d in %s on line %d
+NULL
+Done
diff --git a/tests/lob_029.phpt b/tests/lob_029.phpt
new file mode 100644
index 0000000000..6826f36cda
--- /dev/null
+++ b/tests/lob_029.phpt
@@ -0,0 +1,125 @@
+--TEST--
+reading/writing BFILE LOBs
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+include "details.inc";
+if (empty($oracle_on_localhost)) die("skip this test won't work with remote Oracle");
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$realdirname = dirname(__FILE__);
+$realfilename1 = "oci8bfiletest1.txt";
+$fullname1 = $realdirname."/".$realfilename1;
+$realfilename2 = "oci8bfiletest2.txt";
+$fullname2 = $realdirname."/".$realfilename2;
+$realfilename3 = "oci8bfiletest3.txt";
+$fullname3 = $realdirname."/".$realfilename3;
+
+// Setup
+$s = oci_parse($c, "drop table FileTest");
+@oci_execute($s);
+
+$s = oci_parse($c, "drop directory TestDir");
+@oci_execute($s);
+
+$s = oci_parse($c, "create directory TestDir as '$realdirname'");
+oci_execute($s);
+
+file_put_contents($fullname1, 'Some text in the bfile 1');
+file_put_contents($fullname2, 'Some text in the bfile 2');
+file_put_contents($fullname3, 'Some text in the bfile 3');
+
+$s = oci_parse($c, "create table FileTest (FileNum number, FileDesc varchar2(30), Image bfile)");
+oci_execute($s);
+
+$s = oci_parse($c, "insert into FileTest (FileNum, FileDesc, Image) values (1, 'Description 1', bfilename('TESTDIR', '$realfilename1'))");
+oci_execute($s);
+
+$s = oci_parse($c, "insert into FileTest (FileNum, FileDesc, Image) values (2, 'Description 2', bfilename('TESTDIR', '$realfilename2'))");
+oci_execute($s);
+
+$s = oci_parse($c, "insert into FileTest (FileNum, FileDesc, Image) values (3, 'Description 3', bfilename('TESTDIR', '$realfilename3'))");
+oci_execute($s);
+
+// Run tests
+
+echo "Test 1. Check how many rows in the table\n";
+
+$s = oci_parse($c, "select count(*) numrows from FileTest");
+oci_execute($s);
+oci_fetch_all($s, $res);
+var_dump($res);
+
+echo "Test 2\n";
+$s = oci_parse($c, "select * from FileTest order by FileNum");
+oci_execute($s);
+oci_fetch_all($s, $res);
+var_dump($res);
+
+echo "Test 3\n";
+$d = oci_new_descriptor($c, OCI_D_FILE);
+
+$s = oci_parse($c, "insert into FileTest (FileNum, FileDesc, Image) values (2, 'Description 2', bfilename('TESTDIR', '$realfilename1')) returning Image into :im");
+oci_bind_by_name($s, ":im", $d, -1, OCI_B_BFILE);
+oci_execute($s);
+
+$r = $d->read(40);
+var_dump($r);
+
+unlink($fullname1);
+unlink($fullname2);
+unlink($fullname3);
+
+$s = oci_parse($c, "drop table FileTest");
+oci_execute($s);
+
+$s = oci_parse($c, "drop directory TestDir");
+oci_execute($s);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Test 1. Check how many rows in the table
+array(1) {
+ ["NUMROWS"]=>
+ array(1) {
+ [0]=>
+ string(1) "3"
+ }
+}
+Test 2
+array(3) {
+ ["FILENUM"]=>
+ array(3) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "2"
+ [2]=>
+ string(1) "3"
+ }
+ ["FILEDESC"]=>
+ array(3) {
+ [0]=>
+ string(13) "Description 1"
+ [1]=>
+ string(13) "Description 2"
+ [2]=>
+ string(13) "Description 3"
+ }
+ ["IMAGE"]=>
+ array(3) {
+ [0]=>
+ string(24) "Some text in the bfile 1"
+ [1]=>
+ string(24) "Some text in the bfile 2"
+ [2]=>
+ string(24) "Some text in the bfile 3"
+ }
+}
+Test 3
+string(24) "Some text in the bfile 1"
+Done
diff --git a/tests/lob_030.phpt b/tests/lob_030.phpt
new file mode 100644
index 0000000000..86b2956a51
--- /dev/null
+++ b/tests/lob_030.phpt
@@ -0,0 +1,75 @@
+--TEST--
+Test piecewise fetch of CLOBs equal to, and larger than PHP_OCI_LOB_BUFFER_SIZE
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+function insert_verify($c, $tn, $id, $length)
+{
+ // Insert the data
+ $ora_sql = "INSERT INTO
+ ".$tn." (id, clob)
+ VALUES (".$id.", empty_clob())
+ RETURNING
+ clob
+ INTO :v_clob ";
+
+ $statement = oci_parse($c,$ora_sql);
+ $clob = oci_new_descriptor($c,OCI_D_LOB);
+ oci_bind_by_name($statement,":v_clob", $clob, -1, OCI_B_CLOB);
+ oci_execute($statement, OCI_DEFAULT);
+
+ $data = str_pad("x", $length, "x");
+ $clob->write($data);
+
+ // Verify the data
+ $select_sql = "SELECT clob FROM ".$tn." where id = ".$id;
+ $s = oci_parse($c, $select_sql);
+ oci_execute($s);
+
+ $row = oci_fetch_array($s, OCI_RETURN_LOBS);
+
+ var_dump(strlen($row[0]));
+}
+
+echo "Test 1: A CLOB with an even number of bytes\n";
+insert_verify($c, $schema.$table_name, 1, 1050000);
+
+echo "Test 2: A CLOB with an odd number of bytes\n";
+insert_verify($c, $schema.$table_name, 2, 1050001);
+
+echo "Test 3: A CLOB of 1048576 bytes (== size of PHP_OCI_LOB_BUFFER_SIZE at time of test creation)\n";
+insert_verify($c, $schema.$table_name, 3, 1048576);
+
+echo "Test 4: A CLOB of 1049028 bytes (the value used for chunks in the code)\n";
+insert_verify($c, $schema.$table_name, 4, 1049028);
+
+echo "Test 5: A CLOB of 1049028-1 bytes\n";
+insert_verify($c, $schema.$table_name, 5, 1049028-1);
+
+echo "Test 6: A CLOB of 1049028+1 bytes\n";
+insert_verify($c, $schema.$table_name, 6, 1049028+1);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1: A CLOB with an even number of bytes
+int(1050000)
+Test 2: A CLOB with an odd number of bytes
+int(1050001)
+Test 3: A CLOB of 1048576 bytes (== size of PHP_OCI_LOB_BUFFER_SIZE at time of test creation)
+int(1048576)
+Test 4: A CLOB of 1049028 bytes (the value used for chunks in the code)
+int(1049028)
+Test 5: A CLOB of 1049028-1 bytes
+int(1049027)
+Test 6: A CLOB of 1049028+1 bytes
+int(1049029)
+Done
diff --git a/tests/lob_031.phpt b/tests/lob_031.phpt
new file mode 100644
index 0000000000..a27d53bb38
--- /dev/null
+++ b/tests/lob_031.phpt
@@ -0,0 +1,107 @@
+--TEST--
+Test LOB->read(), LOB->seek() and LOB->tell() with nul bytes in data
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+$blob->write("test");
+$blob->tell();
+$blob->seek(10, OCI_SEEK_CUR);
+$blob->write("string");
+$blob->flush();
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name;
+$s = oci_parse($c, $select_sql);
+oci_execute($s);
+$row = oci_fetch_array($s);
+
+$row[0]->read(3);
+echo " 1. ".$row[0]->tell(). "\n";
+
+$row[0]->read(3);
+echo " 2. ".$row[0]->tell(). "\n";
+
+$row[0]->read(3);
+echo " 3. ".$row[0]->tell(). "\n";
+
+$row[0]->read(6);
+echo " 4. ".$row[0]->tell(). "\n";
+
+$row[0]->read(4);
+echo " 5. ".$row[0]->tell(). "\n";
+
+// Read past end
+$row[0]->read(5);
+echo " 6. ".$row[0]->tell(). "\n";
+
+$row[0]->read(1);
+echo " 8. ".$row[0]->tell(). "\n";
+
+// Now seek
+$row[0]->seek(1);
+echo " 9. ".$row[0]->tell(). "\n";
+
+$row[0]->seek(8);
+echo "10. ".$row[0]->tell(). "\n";
+
+$row[0]->seek(20);
+echo "11. ".$row[0]->tell(). "\n";
+
+// Seek past end
+$row[0]->seek(25);
+echo "12. ".$row[0]->tell(). "\n";
+
+// Seek past end
+$row[0]->seek(2, OCI_SEEK_SET);
+echo "13. ".$row[0]->tell(). "\n";
+
+// Move on 2 more
+$row[0]->seek(2, OCI_SEEK_CUR);
+echo "14. ".$row[0]->tell(). "\n";
+
+// Move 3 past the end
+$row[0]->seek(3, OCI_SEEK_END);
+echo "15. ".$row[0]->tell(). "\n";
+
+// Move 4 before the end
+$row[0]->seek(-4, OCI_SEEK_END);
+echo "16. ".$row[0]->tell(). "\n";
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+ 1. 3
+ 2. 6
+ 3. 9
+ 4. 15
+ 5. 19
+ 6. 20
+ 8. 20
+ 9. 1
+10. 8
+11. 20
+12. 25
+13. 2
+14. 4
+15. 23
+16. 16
+Done
diff --git a/tests/lob_032.phpt b/tests/lob_032.phpt
new file mode 100644
index 0000000000..5d6ff6ec90
--- /dev/null
+++ b/tests/lob_032.phpt
@@ -0,0 +1,33 @@
+--TEST--
+oci_lob_write() and friends
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (id, clob)
+ VALUES (2, empty_clob())
+ RETURNING
+ clob
+ INTO :v_clob ";
+
+$statement = oci_parse($c,$ora_sql);
+$clob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_clob", $clob,-1,OCI_B_CLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+oci_commit($c); // This will cause subsequent ->write() to fail
+$clob->write("data");
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: OCI-Lob::write(): ORA-22990: %s in %s on line 19
+Done
diff --git a/tests/lob_033.phpt b/tests/lob_033.phpt
new file mode 100644
index 0000000000..5647cd9a41
--- /dev/null
+++ b/tests/lob_033.phpt
@@ -0,0 +1,38 @@
+--TEST--
+various oci_lob_write() error messages
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (id, blob)
+ VALUES (2, empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+
+$blob->save("");
+
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob->save(""));
+var_dump($blob->save("data", 100));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Warning: OCI-Lob::save(): OCI_INVALID_HANDLE in %s on line %d
+bool(true)
+bool(true)
+Done
diff --git a/tests/lob_034.phpt b/tests/lob_034.phpt
new file mode 100644
index 0000000000..6bf4058e74
--- /dev/null
+++ b/tests/lob_034.phpt
@@ -0,0 +1,50 @@
+--TEST--
+lob buffering - 2
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob->getBuffering());
+var_dump($blob->setBuffering(false));
+var_dump($blob->setBuffering(false));
+var_dump($blob->setBuffering(true));
+var_dump($blob->setBuffering(true));
+var_dump($blob->flush());
+var_dump($blob->flush(0));
+var_dump($blob->flush(-1));
+
+oci_commit($c);
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+
+Warning: OCI-Lob::flush(): Invalid flag value: -1 in %s on line %d
+bool(false)
+Done
diff --git a/tests/lob_035.phpt b/tests/lob_035.phpt
new file mode 100644
index 0000000000..6e1f5a7359
--- /dev/null
+++ b/tests/lob_035.phpt
@@ -0,0 +1,108 @@
+--TEST--
+oci_lob_copy() - 2
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (id, blob)
+ VALUES (1, empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob->write("some string here. string, I said"));
+oci_commit($c);
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (id, blob)
+ VALUES (2, empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." WHERE id = 1";
+$s = oci_parse($c, $select_sql);
+oci_execute($s);
+
+$row1 = oci_fetch_array($s);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." WHERE id = 2 FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+$row2 = oci_fetch_array($s);
+
+$dummy = oci_new_descriptor($c, OCI_D_LOB);
+
+var_dump(oci_lob_copy($dummy, $row1[0]));
+var_dump(oci_lob_copy($row2[0], $dummy));
+
+var_dump(oci_lob_copy($row2[0], $row1[0], 0));
+var_dump(oci_lob_copy($row2[0], $row1[0], -1));
+var_dump(oci_lob_copy($row2[0], $row1[0], 100000));
+
+var_dump(oci_lob_size());
+var_dump(oci_lob_size($row2[0]));
+unset($dummy->descriptor);
+var_dump(oci_lob_size($dummy));
+
+oci_rollback($c);
+oci_rollback($c);
+oci_commit($c);
+oci_commit($c);
+
+$select_sql = "SELECT blob FROM ".$schema.$table_name." WHERE id = 2 FOR UPDATE";
+$s = oci_parse($c, $select_sql);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($row2 = oci_fetch_array($s, OCI_RETURN_LOBS));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+int(32)
+
+Warning: oci_lob_copy(): OCI_INVALID_HANDLE in %s on line %d
+bool(false)
+
+Warning: oci_lob_copy(): OCI_INVALID_HANDLE in %s on line %d
+bool(false)
+bool(false)
+
+Warning: oci_lob_copy(): Length parameter must be greater than 0 in %s on line %d
+bool(false)
+bool(true)
+
+Warning: oci_lob_size() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+int(0)
+
+Warning: oci_lob_size(): Unable to find descriptor property in %s on line %d
+bool(false)
+array(2) {
+ [0]=>
+ string(0) ""
+ ["BLOB"]=>
+ string(0) ""
+}
+Done
diff --git a/tests/lob_036.phpt b/tests/lob_036.phpt
new file mode 100644
index 0000000000..e72c1cf081
--- /dev/null
+++ b/tests/lob_036.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Exercise cleanup code when LOB buffering is on
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$s = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_DTYPE_LOB);
+
+
+oci_bind_by_name($s,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($blob->write("test"));
+var_dump($blob->setBuffering(true));
+var_dump($blob->write("test"));
+
+$blob = null;
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+int(4)
+bool(true)
+int(4)
+Done
diff --git a/tests/lob_037.phpt b/tests/lob_037.phpt
new file mode 100644
index 0000000000..228f5e8123
--- /dev/null
+++ b/tests/lob_037.phpt
@@ -0,0 +1,68 @@
+--TEST--
+Fetching two different lobs and using them after fetch
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+/* insert the first LOB */
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$s = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_DTYPE_LOB);
+
+oci_bind_by_name($s,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($blob->write("first lob data"));
+oci_commit($c);
+
+/* insert the second LOB */
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$s = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_DTYPE_LOB);
+
+oci_bind_by_name($s,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($s, OCI_DEFAULT);
+
+var_dump($blob->write("second lob data"));
+oci_commit($c);
+
+/* select both */
+
+$ora_sql = "SELECT blob FROM ".$schema.$table_name;
+$s = oci_parse($c,$ora_sql);
+oci_execute($s, OCI_DEFAULT);
+
+$rows = array();
+$rows[0] = oci_fetch_assoc($s);
+$rows[1] = oci_fetch_assoc($s);
+
+var_dump($rows[0]['BLOB']->read(1000));
+var_dump($rows[1]['BLOB']->read(1000));
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+int(14)
+int(15)
+string(14) "first lob data"
+string(15) "second lob data"
+Done
diff --git a/tests/lob_038.phpt b/tests/lob_038.phpt
new file mode 100644
index 0000000000..91dac66c0d
--- /dev/null
+++ b/tests/lob_038.phpt
@@ -0,0 +1,189 @@
+--TEST--
+Array fetch CLOB and BLOB
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+echo "Test 1: CLOB\n";
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (clob)
+ VALUES (empty_clob())
+ RETURNING
+ clob
+ INTO :v_clob ";
+
+$s = oci_parse($c,$ora_sql);
+$clob = oci_new_descriptor($c,OCI_DTYPE_LOB);
+
+
+oci_bind_by_name($s,":v_clob", $clob,-1,OCI_B_CLOB);
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($clob->save("clob test 1"));
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($clob->save("clob test 2"));
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($clob->save("clob test 3"));
+
+
+$s = oci_parse($c,"select clob from ".$schema.$table_name);
+var_dump(oci_execute($s));
+
+oci_fetch_all($s, $res);
+
+var_dump($res);
+
+
+echo "Test 1b\n";
+
+$s = oci_parse($c, "select clob from ".$schema.$table_name);
+var_dump(oci_execute($s, OCI_DEFAULT));
+while ($row = oci_fetch_array($s, OCI_ASSOC)) {
+ var_dump($row);
+ $result = $row['CLOB']->load();
+ var_dump($result);
+}
+
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Test 2: BLOB\n";
+
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$s = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_DTYPE_LOB);
+
+
+oci_bind_by_name($s,":v_blob", $blob,-1,OCI_B_BLOB);
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($blob->save("blob test 1"));
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($blob->save("blob test 2"));
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($blob->save("blob test 3"));
+
+$s = oci_parse($c, "select blob from ".$schema.$table_name);
+var_dump(oci_execute($s));
+oci_fetch_all($s, $res);
+var_dump($res);
+
+echo "Test 2b\n";
+
+$s = oci_parse($c, "select blob from ".$schema.$table_name);
+var_dump(oci_execute($s, OCI_DEFAULT));
+while ($row = oci_fetch_array($s, OCI_ASSOC)) {
+ var_dump($row);
+ $result = $row['BLOB']->load();
+ var_dump($result);
+}
+
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1: CLOB
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+array(1) {
+ ["CLOB"]=>
+ array(3) {
+ [0]=>
+ string(11) "clob test 1"
+ [1]=>
+ string(11) "clob test 2"
+ [2]=>
+ string(11) "clob test 3"
+ }
+}
+Test 1b
+bool(true)
+array(1) {
+ ["CLOB"]=>
+ object(OCI-Lob)#2 (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(11) "clob test 1"
+array(1) {
+ ["CLOB"]=>
+ object(OCI-Lob)#3 (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(11) "clob test 2"
+array(1) {
+ ["CLOB"]=>
+ object(OCI-Lob)#2 (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(11) "clob test 3"
+Test 2: BLOB
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+array(1) {
+ ["BLOB"]=>
+ array(3) {
+ [0]=>
+ string(11) "blob test 1"
+ [1]=>
+ string(11) "blob test 2"
+ [2]=>
+ string(11) "blob test 3"
+ }
+}
+Test 2b
+bool(true)
+array(1) {
+ ["BLOB"]=>
+ object(OCI-Lob)#3 (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(11) "blob test 1"
+array(1) {
+ ["BLOB"]=>
+ object(OCI-Lob)#4 (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(11) "blob test 2"
+array(1) {
+ ["BLOB"]=>
+ object(OCI-Lob)#3 (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+string(11) "blob test 3"
+Done \ No newline at end of file
diff --git a/tests/lob_039.phpt b/tests/lob_039.phpt
new file mode 100644
index 0000000000..5675f5a928
--- /dev/null
+++ b/tests/lob_039.phpt
@@ -0,0 +1,65 @@
+--TEST--
+Test CLOB->write() for multiple inserts
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+echo "Test 1: CLOB\n";
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (clob)
+ VALUES (empty_clob())
+ RETURNING
+ clob
+ INTO :v_clob ";
+
+$s = oci_parse($c,$ora_sql);
+$clob = oci_new_descriptor($c,OCI_DTYPE_LOB);
+
+
+oci_bind_by_name($s,":v_clob", $clob,-1,OCI_B_CLOB);
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($clob->write("clob test 1"));
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($clob->write("clob test 2"));
+
+oci_execute($s, OCI_DEFAULT);
+var_dump($clob->write("clob test 3"));
+
+$s = oci_parse($c,"select clob from ".$schema.$table_name);
+var_dump(oci_execute($s));
+
+oci_fetch_all($s, $res);
+
+var_dump($res);
+
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Test 1: CLOB
+int(11)
+int(11)
+int(11)
+bool(true)
+array(1) {
+ ["CLOB"]=>
+ array(3) {
+ [0]=>
+ string(11) "clob test 1"
+ [1]=>
+ string(22) " clob test 2"
+ [2]=>
+ string(33) " clob test 3"
+ }
+}
+Done
diff --git a/tests/lob_040.phpt b/tests/lob_040.phpt
new file mode 100644
index 0000000000..3f8a73dc5a
--- /dev/null
+++ b/tests/lob_040.phpt
@@ -0,0 +1,1041 @@
+--TEST--
+Bug #37706 (Test LOB locator reuse. Extends simple test of lob_037.phpt)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+define('NUMLOBS', 200);
+
+require(dirname(__FILE__).'/connect.inc');
+require(dirname(__FILE__).'/create_table.inc');
+
+for ($i = 0; $i < NUMLOBS; $i++) {
+ $s = oci_parse($c, "insert into ".$schema.$table_name." (id, clob) values(".$i.", '".$i."aaaa".$i.$i."aaaaaaaaaaaaaaaaaaaaaaaaaaaz')");
+ oci_execute($s);
+}
+
+echo "Test 1: CLOB as locator\n";
+
+$s = oci_parse($c, "select clob from ".$schema.$table_name." order by id");
+oci_execute($s);
+
+$row = array();
+for ($i = 0; $i < NUMLOBS; $i++) {
+ $row[$i] = oci_fetch_array($s, OCI_NUM);
+}
+
+for ($i = 0; $i < NUMLOBS; $i++) {
+ echo "Row $i Size: " . $row[$i][0]->size() . "\n";;
+ echo "Pos 1: " . $row[$i][0]->tell() . "\n";
+ echo "Data: " . $row[$i][0]->read(5) . "\n";;
+ echo "Pos 2: " . $row[$i][0]->tell() . "\n";
+ echo "Data: " . $row[$i][0]->read(12) . "\n";
+}
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Test 1: CLOB as locator
+Row 0 Size: 35
+Pos 1: 0
+Data: 0aaaa
+Pos 2: 5
+Data: 00aaaaaaaaaa
+Row 1 Size: 35
+Pos 1: 0
+Data: 1aaaa
+Pos 2: 5
+Data: 11aaaaaaaaaa
+Row 2 Size: 35
+Pos 1: 0
+Data: 2aaaa
+Pos 2: 5
+Data: 22aaaaaaaaaa
+Row 3 Size: 35
+Pos 1: 0
+Data: 3aaaa
+Pos 2: 5
+Data: 33aaaaaaaaaa
+Row 4 Size: 35
+Pos 1: 0
+Data: 4aaaa
+Pos 2: 5
+Data: 44aaaaaaaaaa
+Row 5 Size: 35
+Pos 1: 0
+Data: 5aaaa
+Pos 2: 5
+Data: 55aaaaaaaaaa
+Row 6 Size: 35
+Pos 1: 0
+Data: 6aaaa
+Pos 2: 5
+Data: 66aaaaaaaaaa
+Row 7 Size: 35
+Pos 1: 0
+Data: 7aaaa
+Pos 2: 5
+Data: 77aaaaaaaaaa
+Row 8 Size: 35
+Pos 1: 0
+Data: 8aaaa
+Pos 2: 5
+Data: 88aaaaaaaaaa
+Row 9 Size: 35
+Pos 1: 0
+Data: 9aaaa
+Pos 2: 5
+Data: 99aaaaaaaaaa
+Row 10 Size: 38
+Pos 1: 0
+Data: 10aaa
+Pos 2: 5
+Data: a1010aaaaaaa
+Row 11 Size: 38
+Pos 1: 0
+Data: 11aaa
+Pos 2: 5
+Data: a1111aaaaaaa
+Row 12 Size: 38
+Pos 1: 0
+Data: 12aaa
+Pos 2: 5
+Data: a1212aaaaaaa
+Row 13 Size: 38
+Pos 1: 0
+Data: 13aaa
+Pos 2: 5
+Data: a1313aaaaaaa
+Row 14 Size: 38
+Pos 1: 0
+Data: 14aaa
+Pos 2: 5
+Data: a1414aaaaaaa
+Row 15 Size: 38
+Pos 1: 0
+Data: 15aaa
+Pos 2: 5
+Data: a1515aaaaaaa
+Row 16 Size: 38
+Pos 1: 0
+Data: 16aaa
+Pos 2: 5
+Data: a1616aaaaaaa
+Row 17 Size: 38
+Pos 1: 0
+Data: 17aaa
+Pos 2: 5
+Data: a1717aaaaaaa
+Row 18 Size: 38
+Pos 1: 0
+Data: 18aaa
+Pos 2: 5
+Data: a1818aaaaaaa
+Row 19 Size: 38
+Pos 1: 0
+Data: 19aaa
+Pos 2: 5
+Data: a1919aaaaaaa
+Row 20 Size: 38
+Pos 1: 0
+Data: 20aaa
+Pos 2: 5
+Data: a2020aaaaaaa
+Row 21 Size: 38
+Pos 1: 0
+Data: 21aaa
+Pos 2: 5
+Data: a2121aaaaaaa
+Row 22 Size: 38
+Pos 1: 0
+Data: 22aaa
+Pos 2: 5
+Data: a2222aaaaaaa
+Row 23 Size: 38
+Pos 1: 0
+Data: 23aaa
+Pos 2: 5
+Data: a2323aaaaaaa
+Row 24 Size: 38
+Pos 1: 0
+Data: 24aaa
+Pos 2: 5
+Data: a2424aaaaaaa
+Row 25 Size: 38
+Pos 1: 0
+Data: 25aaa
+Pos 2: 5
+Data: a2525aaaaaaa
+Row 26 Size: 38
+Pos 1: 0
+Data: 26aaa
+Pos 2: 5
+Data: a2626aaaaaaa
+Row 27 Size: 38
+Pos 1: 0
+Data: 27aaa
+Pos 2: 5
+Data: a2727aaaaaaa
+Row 28 Size: 38
+Pos 1: 0
+Data: 28aaa
+Pos 2: 5
+Data: a2828aaaaaaa
+Row 29 Size: 38
+Pos 1: 0
+Data: 29aaa
+Pos 2: 5
+Data: a2929aaaaaaa
+Row 30 Size: 38
+Pos 1: 0
+Data: 30aaa
+Pos 2: 5
+Data: a3030aaaaaaa
+Row 31 Size: 38
+Pos 1: 0
+Data: 31aaa
+Pos 2: 5
+Data: a3131aaaaaaa
+Row 32 Size: 38
+Pos 1: 0
+Data: 32aaa
+Pos 2: 5
+Data: a3232aaaaaaa
+Row 33 Size: 38
+Pos 1: 0
+Data: 33aaa
+Pos 2: 5
+Data: a3333aaaaaaa
+Row 34 Size: 38
+Pos 1: 0
+Data: 34aaa
+Pos 2: 5
+Data: a3434aaaaaaa
+Row 35 Size: 38
+Pos 1: 0
+Data: 35aaa
+Pos 2: 5
+Data: a3535aaaaaaa
+Row 36 Size: 38
+Pos 1: 0
+Data: 36aaa
+Pos 2: 5
+Data: a3636aaaaaaa
+Row 37 Size: 38
+Pos 1: 0
+Data: 37aaa
+Pos 2: 5
+Data: a3737aaaaaaa
+Row 38 Size: 38
+Pos 1: 0
+Data: 38aaa
+Pos 2: 5
+Data: a3838aaaaaaa
+Row 39 Size: 38
+Pos 1: 0
+Data: 39aaa
+Pos 2: 5
+Data: a3939aaaaaaa
+Row 40 Size: 38
+Pos 1: 0
+Data: 40aaa
+Pos 2: 5
+Data: a4040aaaaaaa
+Row 41 Size: 38
+Pos 1: 0
+Data: 41aaa
+Pos 2: 5
+Data: a4141aaaaaaa
+Row 42 Size: 38
+Pos 1: 0
+Data: 42aaa
+Pos 2: 5
+Data: a4242aaaaaaa
+Row 43 Size: 38
+Pos 1: 0
+Data: 43aaa
+Pos 2: 5
+Data: a4343aaaaaaa
+Row 44 Size: 38
+Pos 1: 0
+Data: 44aaa
+Pos 2: 5
+Data: a4444aaaaaaa
+Row 45 Size: 38
+Pos 1: 0
+Data: 45aaa
+Pos 2: 5
+Data: a4545aaaaaaa
+Row 46 Size: 38
+Pos 1: 0
+Data: 46aaa
+Pos 2: 5
+Data: a4646aaaaaaa
+Row 47 Size: 38
+Pos 1: 0
+Data: 47aaa
+Pos 2: 5
+Data: a4747aaaaaaa
+Row 48 Size: 38
+Pos 1: 0
+Data: 48aaa
+Pos 2: 5
+Data: a4848aaaaaaa
+Row 49 Size: 38
+Pos 1: 0
+Data: 49aaa
+Pos 2: 5
+Data: a4949aaaaaaa
+Row 50 Size: 38
+Pos 1: 0
+Data: 50aaa
+Pos 2: 5
+Data: a5050aaaaaaa
+Row 51 Size: 38
+Pos 1: 0
+Data: 51aaa
+Pos 2: 5
+Data: a5151aaaaaaa
+Row 52 Size: 38
+Pos 1: 0
+Data: 52aaa
+Pos 2: 5
+Data: a5252aaaaaaa
+Row 53 Size: 38
+Pos 1: 0
+Data: 53aaa
+Pos 2: 5
+Data: a5353aaaaaaa
+Row 54 Size: 38
+Pos 1: 0
+Data: 54aaa
+Pos 2: 5
+Data: a5454aaaaaaa
+Row 55 Size: 38
+Pos 1: 0
+Data: 55aaa
+Pos 2: 5
+Data: a5555aaaaaaa
+Row 56 Size: 38
+Pos 1: 0
+Data: 56aaa
+Pos 2: 5
+Data: a5656aaaaaaa
+Row 57 Size: 38
+Pos 1: 0
+Data: 57aaa
+Pos 2: 5
+Data: a5757aaaaaaa
+Row 58 Size: 38
+Pos 1: 0
+Data: 58aaa
+Pos 2: 5
+Data: a5858aaaaaaa
+Row 59 Size: 38
+Pos 1: 0
+Data: 59aaa
+Pos 2: 5
+Data: a5959aaaaaaa
+Row 60 Size: 38
+Pos 1: 0
+Data: 60aaa
+Pos 2: 5
+Data: a6060aaaaaaa
+Row 61 Size: 38
+Pos 1: 0
+Data: 61aaa
+Pos 2: 5
+Data: a6161aaaaaaa
+Row 62 Size: 38
+Pos 1: 0
+Data: 62aaa
+Pos 2: 5
+Data: a6262aaaaaaa
+Row 63 Size: 38
+Pos 1: 0
+Data: 63aaa
+Pos 2: 5
+Data: a6363aaaaaaa
+Row 64 Size: 38
+Pos 1: 0
+Data: 64aaa
+Pos 2: 5
+Data: a6464aaaaaaa
+Row 65 Size: 38
+Pos 1: 0
+Data: 65aaa
+Pos 2: 5
+Data: a6565aaaaaaa
+Row 66 Size: 38
+Pos 1: 0
+Data: 66aaa
+Pos 2: 5
+Data: a6666aaaaaaa
+Row 67 Size: 38
+Pos 1: 0
+Data: 67aaa
+Pos 2: 5
+Data: a6767aaaaaaa
+Row 68 Size: 38
+Pos 1: 0
+Data: 68aaa
+Pos 2: 5
+Data: a6868aaaaaaa
+Row 69 Size: 38
+Pos 1: 0
+Data: 69aaa
+Pos 2: 5
+Data: a6969aaaaaaa
+Row 70 Size: 38
+Pos 1: 0
+Data: 70aaa
+Pos 2: 5
+Data: a7070aaaaaaa
+Row 71 Size: 38
+Pos 1: 0
+Data: 71aaa
+Pos 2: 5
+Data: a7171aaaaaaa
+Row 72 Size: 38
+Pos 1: 0
+Data: 72aaa
+Pos 2: 5
+Data: a7272aaaaaaa
+Row 73 Size: 38
+Pos 1: 0
+Data: 73aaa
+Pos 2: 5
+Data: a7373aaaaaaa
+Row 74 Size: 38
+Pos 1: 0
+Data: 74aaa
+Pos 2: 5
+Data: a7474aaaaaaa
+Row 75 Size: 38
+Pos 1: 0
+Data: 75aaa
+Pos 2: 5
+Data: a7575aaaaaaa
+Row 76 Size: 38
+Pos 1: 0
+Data: 76aaa
+Pos 2: 5
+Data: a7676aaaaaaa
+Row 77 Size: 38
+Pos 1: 0
+Data: 77aaa
+Pos 2: 5
+Data: a7777aaaaaaa
+Row 78 Size: 38
+Pos 1: 0
+Data: 78aaa
+Pos 2: 5
+Data: a7878aaaaaaa
+Row 79 Size: 38
+Pos 1: 0
+Data: 79aaa
+Pos 2: 5
+Data: a7979aaaaaaa
+Row 80 Size: 38
+Pos 1: 0
+Data: 80aaa
+Pos 2: 5
+Data: a8080aaaaaaa
+Row 81 Size: 38
+Pos 1: 0
+Data: 81aaa
+Pos 2: 5
+Data: a8181aaaaaaa
+Row 82 Size: 38
+Pos 1: 0
+Data: 82aaa
+Pos 2: 5
+Data: a8282aaaaaaa
+Row 83 Size: 38
+Pos 1: 0
+Data: 83aaa
+Pos 2: 5
+Data: a8383aaaaaaa
+Row 84 Size: 38
+Pos 1: 0
+Data: 84aaa
+Pos 2: 5
+Data: a8484aaaaaaa
+Row 85 Size: 38
+Pos 1: 0
+Data: 85aaa
+Pos 2: 5
+Data: a8585aaaaaaa
+Row 86 Size: 38
+Pos 1: 0
+Data: 86aaa
+Pos 2: 5
+Data: a8686aaaaaaa
+Row 87 Size: 38
+Pos 1: 0
+Data: 87aaa
+Pos 2: 5
+Data: a8787aaaaaaa
+Row 88 Size: 38
+Pos 1: 0
+Data: 88aaa
+Pos 2: 5
+Data: a8888aaaaaaa
+Row 89 Size: 38
+Pos 1: 0
+Data: 89aaa
+Pos 2: 5
+Data: a8989aaaaaaa
+Row 90 Size: 38
+Pos 1: 0
+Data: 90aaa
+Pos 2: 5
+Data: a9090aaaaaaa
+Row 91 Size: 38
+Pos 1: 0
+Data: 91aaa
+Pos 2: 5
+Data: a9191aaaaaaa
+Row 92 Size: 38
+Pos 1: 0
+Data: 92aaa
+Pos 2: 5
+Data: a9292aaaaaaa
+Row 93 Size: 38
+Pos 1: 0
+Data: 93aaa
+Pos 2: 5
+Data: a9393aaaaaaa
+Row 94 Size: 38
+Pos 1: 0
+Data: 94aaa
+Pos 2: 5
+Data: a9494aaaaaaa
+Row 95 Size: 38
+Pos 1: 0
+Data: 95aaa
+Pos 2: 5
+Data: a9595aaaaaaa
+Row 96 Size: 38
+Pos 1: 0
+Data: 96aaa
+Pos 2: 5
+Data: a9696aaaaaaa
+Row 97 Size: 38
+Pos 1: 0
+Data: 97aaa
+Pos 2: 5
+Data: a9797aaaaaaa
+Row 98 Size: 38
+Pos 1: 0
+Data: 98aaa
+Pos 2: 5
+Data: a9898aaaaaaa
+Row 99 Size: 38
+Pos 1: 0
+Data: 99aaa
+Pos 2: 5
+Data: a9999aaaaaaa
+Row 100 Size: 41
+Pos 1: 0
+Data: 100aa
+Pos 2: 5
+Data: aa100100aaaa
+Row 101 Size: 41
+Pos 1: 0
+Data: 101aa
+Pos 2: 5
+Data: aa101101aaaa
+Row 102 Size: 41
+Pos 1: 0
+Data: 102aa
+Pos 2: 5
+Data: aa102102aaaa
+Row 103 Size: 41
+Pos 1: 0
+Data: 103aa
+Pos 2: 5
+Data: aa103103aaaa
+Row 104 Size: 41
+Pos 1: 0
+Data: 104aa
+Pos 2: 5
+Data: aa104104aaaa
+Row 105 Size: 41
+Pos 1: 0
+Data: 105aa
+Pos 2: 5
+Data: aa105105aaaa
+Row 106 Size: 41
+Pos 1: 0
+Data: 106aa
+Pos 2: 5
+Data: aa106106aaaa
+Row 107 Size: 41
+Pos 1: 0
+Data: 107aa
+Pos 2: 5
+Data: aa107107aaaa
+Row 108 Size: 41
+Pos 1: 0
+Data: 108aa
+Pos 2: 5
+Data: aa108108aaaa
+Row 109 Size: 41
+Pos 1: 0
+Data: 109aa
+Pos 2: 5
+Data: aa109109aaaa
+Row 110 Size: 41
+Pos 1: 0
+Data: 110aa
+Pos 2: 5
+Data: aa110110aaaa
+Row 111 Size: 41
+Pos 1: 0
+Data: 111aa
+Pos 2: 5
+Data: aa111111aaaa
+Row 112 Size: 41
+Pos 1: 0
+Data: 112aa
+Pos 2: 5
+Data: aa112112aaaa
+Row 113 Size: 41
+Pos 1: 0
+Data: 113aa
+Pos 2: 5
+Data: aa113113aaaa
+Row 114 Size: 41
+Pos 1: 0
+Data: 114aa
+Pos 2: 5
+Data: aa114114aaaa
+Row 115 Size: 41
+Pos 1: 0
+Data: 115aa
+Pos 2: 5
+Data: aa115115aaaa
+Row 116 Size: 41
+Pos 1: 0
+Data: 116aa
+Pos 2: 5
+Data: aa116116aaaa
+Row 117 Size: 41
+Pos 1: 0
+Data: 117aa
+Pos 2: 5
+Data: aa117117aaaa
+Row 118 Size: 41
+Pos 1: 0
+Data: 118aa
+Pos 2: 5
+Data: aa118118aaaa
+Row 119 Size: 41
+Pos 1: 0
+Data: 119aa
+Pos 2: 5
+Data: aa119119aaaa
+Row 120 Size: 41
+Pos 1: 0
+Data: 120aa
+Pos 2: 5
+Data: aa120120aaaa
+Row 121 Size: 41
+Pos 1: 0
+Data: 121aa
+Pos 2: 5
+Data: aa121121aaaa
+Row 122 Size: 41
+Pos 1: 0
+Data: 122aa
+Pos 2: 5
+Data: aa122122aaaa
+Row 123 Size: 41
+Pos 1: 0
+Data: 123aa
+Pos 2: 5
+Data: aa123123aaaa
+Row 124 Size: 41
+Pos 1: 0
+Data: 124aa
+Pos 2: 5
+Data: aa124124aaaa
+Row 125 Size: 41
+Pos 1: 0
+Data: 125aa
+Pos 2: 5
+Data: aa125125aaaa
+Row 126 Size: 41
+Pos 1: 0
+Data: 126aa
+Pos 2: 5
+Data: aa126126aaaa
+Row 127 Size: 41
+Pos 1: 0
+Data: 127aa
+Pos 2: 5
+Data: aa127127aaaa
+Row 128 Size: 41
+Pos 1: 0
+Data: 128aa
+Pos 2: 5
+Data: aa128128aaaa
+Row 129 Size: 41
+Pos 1: 0
+Data: 129aa
+Pos 2: 5
+Data: aa129129aaaa
+Row 130 Size: 41
+Pos 1: 0
+Data: 130aa
+Pos 2: 5
+Data: aa130130aaaa
+Row 131 Size: 41
+Pos 1: 0
+Data: 131aa
+Pos 2: 5
+Data: aa131131aaaa
+Row 132 Size: 41
+Pos 1: 0
+Data: 132aa
+Pos 2: 5
+Data: aa132132aaaa
+Row 133 Size: 41
+Pos 1: 0
+Data: 133aa
+Pos 2: 5
+Data: aa133133aaaa
+Row 134 Size: 41
+Pos 1: 0
+Data: 134aa
+Pos 2: 5
+Data: aa134134aaaa
+Row 135 Size: 41
+Pos 1: 0
+Data: 135aa
+Pos 2: 5
+Data: aa135135aaaa
+Row 136 Size: 41
+Pos 1: 0
+Data: 136aa
+Pos 2: 5
+Data: aa136136aaaa
+Row 137 Size: 41
+Pos 1: 0
+Data: 137aa
+Pos 2: 5
+Data: aa137137aaaa
+Row 138 Size: 41
+Pos 1: 0
+Data: 138aa
+Pos 2: 5
+Data: aa138138aaaa
+Row 139 Size: 41
+Pos 1: 0
+Data: 139aa
+Pos 2: 5
+Data: aa139139aaaa
+Row 140 Size: 41
+Pos 1: 0
+Data: 140aa
+Pos 2: 5
+Data: aa140140aaaa
+Row 141 Size: 41
+Pos 1: 0
+Data: 141aa
+Pos 2: 5
+Data: aa141141aaaa
+Row 142 Size: 41
+Pos 1: 0
+Data: 142aa
+Pos 2: 5
+Data: aa142142aaaa
+Row 143 Size: 41
+Pos 1: 0
+Data: 143aa
+Pos 2: 5
+Data: aa143143aaaa
+Row 144 Size: 41
+Pos 1: 0
+Data: 144aa
+Pos 2: 5
+Data: aa144144aaaa
+Row 145 Size: 41
+Pos 1: 0
+Data: 145aa
+Pos 2: 5
+Data: aa145145aaaa
+Row 146 Size: 41
+Pos 1: 0
+Data: 146aa
+Pos 2: 5
+Data: aa146146aaaa
+Row 147 Size: 41
+Pos 1: 0
+Data: 147aa
+Pos 2: 5
+Data: aa147147aaaa
+Row 148 Size: 41
+Pos 1: 0
+Data: 148aa
+Pos 2: 5
+Data: aa148148aaaa
+Row 149 Size: 41
+Pos 1: 0
+Data: 149aa
+Pos 2: 5
+Data: aa149149aaaa
+Row 150 Size: 41
+Pos 1: 0
+Data: 150aa
+Pos 2: 5
+Data: aa150150aaaa
+Row 151 Size: 41
+Pos 1: 0
+Data: 151aa
+Pos 2: 5
+Data: aa151151aaaa
+Row 152 Size: 41
+Pos 1: 0
+Data: 152aa
+Pos 2: 5
+Data: aa152152aaaa
+Row 153 Size: 41
+Pos 1: 0
+Data: 153aa
+Pos 2: 5
+Data: aa153153aaaa
+Row 154 Size: 41
+Pos 1: 0
+Data: 154aa
+Pos 2: 5
+Data: aa154154aaaa
+Row 155 Size: 41
+Pos 1: 0
+Data: 155aa
+Pos 2: 5
+Data: aa155155aaaa
+Row 156 Size: 41
+Pos 1: 0
+Data: 156aa
+Pos 2: 5
+Data: aa156156aaaa
+Row 157 Size: 41
+Pos 1: 0
+Data: 157aa
+Pos 2: 5
+Data: aa157157aaaa
+Row 158 Size: 41
+Pos 1: 0
+Data: 158aa
+Pos 2: 5
+Data: aa158158aaaa
+Row 159 Size: 41
+Pos 1: 0
+Data: 159aa
+Pos 2: 5
+Data: aa159159aaaa
+Row 160 Size: 41
+Pos 1: 0
+Data: 160aa
+Pos 2: 5
+Data: aa160160aaaa
+Row 161 Size: 41
+Pos 1: 0
+Data: 161aa
+Pos 2: 5
+Data: aa161161aaaa
+Row 162 Size: 41
+Pos 1: 0
+Data: 162aa
+Pos 2: 5
+Data: aa162162aaaa
+Row 163 Size: 41
+Pos 1: 0
+Data: 163aa
+Pos 2: 5
+Data: aa163163aaaa
+Row 164 Size: 41
+Pos 1: 0
+Data: 164aa
+Pos 2: 5
+Data: aa164164aaaa
+Row 165 Size: 41
+Pos 1: 0
+Data: 165aa
+Pos 2: 5
+Data: aa165165aaaa
+Row 166 Size: 41
+Pos 1: 0
+Data: 166aa
+Pos 2: 5
+Data: aa166166aaaa
+Row 167 Size: 41
+Pos 1: 0
+Data: 167aa
+Pos 2: 5
+Data: aa167167aaaa
+Row 168 Size: 41
+Pos 1: 0
+Data: 168aa
+Pos 2: 5
+Data: aa168168aaaa
+Row 169 Size: 41
+Pos 1: 0
+Data: 169aa
+Pos 2: 5
+Data: aa169169aaaa
+Row 170 Size: 41
+Pos 1: 0
+Data: 170aa
+Pos 2: 5
+Data: aa170170aaaa
+Row 171 Size: 41
+Pos 1: 0
+Data: 171aa
+Pos 2: 5
+Data: aa171171aaaa
+Row 172 Size: 41
+Pos 1: 0
+Data: 172aa
+Pos 2: 5
+Data: aa172172aaaa
+Row 173 Size: 41
+Pos 1: 0
+Data: 173aa
+Pos 2: 5
+Data: aa173173aaaa
+Row 174 Size: 41
+Pos 1: 0
+Data: 174aa
+Pos 2: 5
+Data: aa174174aaaa
+Row 175 Size: 41
+Pos 1: 0
+Data: 175aa
+Pos 2: 5
+Data: aa175175aaaa
+Row 176 Size: 41
+Pos 1: 0
+Data: 176aa
+Pos 2: 5
+Data: aa176176aaaa
+Row 177 Size: 41
+Pos 1: 0
+Data: 177aa
+Pos 2: 5
+Data: aa177177aaaa
+Row 178 Size: 41
+Pos 1: 0
+Data: 178aa
+Pos 2: 5
+Data: aa178178aaaa
+Row 179 Size: 41
+Pos 1: 0
+Data: 179aa
+Pos 2: 5
+Data: aa179179aaaa
+Row 180 Size: 41
+Pos 1: 0
+Data: 180aa
+Pos 2: 5
+Data: aa180180aaaa
+Row 181 Size: 41
+Pos 1: 0
+Data: 181aa
+Pos 2: 5
+Data: aa181181aaaa
+Row 182 Size: 41
+Pos 1: 0
+Data: 182aa
+Pos 2: 5
+Data: aa182182aaaa
+Row 183 Size: 41
+Pos 1: 0
+Data: 183aa
+Pos 2: 5
+Data: aa183183aaaa
+Row 184 Size: 41
+Pos 1: 0
+Data: 184aa
+Pos 2: 5
+Data: aa184184aaaa
+Row 185 Size: 41
+Pos 1: 0
+Data: 185aa
+Pos 2: 5
+Data: aa185185aaaa
+Row 186 Size: 41
+Pos 1: 0
+Data: 186aa
+Pos 2: 5
+Data: aa186186aaaa
+Row 187 Size: 41
+Pos 1: 0
+Data: 187aa
+Pos 2: 5
+Data: aa187187aaaa
+Row 188 Size: 41
+Pos 1: 0
+Data: 188aa
+Pos 2: 5
+Data: aa188188aaaa
+Row 189 Size: 41
+Pos 1: 0
+Data: 189aa
+Pos 2: 5
+Data: aa189189aaaa
+Row 190 Size: 41
+Pos 1: 0
+Data: 190aa
+Pos 2: 5
+Data: aa190190aaaa
+Row 191 Size: 41
+Pos 1: 0
+Data: 191aa
+Pos 2: 5
+Data: aa191191aaaa
+Row 192 Size: 41
+Pos 1: 0
+Data: 192aa
+Pos 2: 5
+Data: aa192192aaaa
+Row 193 Size: 41
+Pos 1: 0
+Data: 193aa
+Pos 2: 5
+Data: aa193193aaaa
+Row 194 Size: 41
+Pos 1: 0
+Data: 194aa
+Pos 2: 5
+Data: aa194194aaaa
+Row 195 Size: 41
+Pos 1: 0
+Data: 195aa
+Pos 2: 5
+Data: aa195195aaaa
+Row 196 Size: 41
+Pos 1: 0
+Data: 196aa
+Pos 2: 5
+Data: aa196196aaaa
+Row 197 Size: 41
+Pos 1: 0
+Data: 197aa
+Pos 2: 5
+Data: aa197197aaaa
+Row 198 Size: 41
+Pos 1: 0
+Data: 198aa
+Pos 2: 5
+Data: aa198198aaaa
+Row 199 Size: 41
+Pos 1: 0
+Data: 199aa
+Pos 2: 5
+Data: aa199199aaaa
+Done
diff --git a/tests/lob_041.phpt b/tests/lob_041.phpt
new file mode 100644
index 0000000000..d04b43606a
--- /dev/null
+++ b/tests/lob_041.phpt
@@ -0,0 +1,92 @@
+--TEST--
+Check LOBS are valid after statement free
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Initialization
+
+$stmtarray = array(
+ "DROP table lob_041_tab",
+ "CREATE table lob_041_tab(c1 CLOB)",
+ "INSERT INTO lob_041_tab VALUES('test data')"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+echo "Test 1 - explicit statement close\n";
+
+$s = oci_parse($c, "SELECT C1 FROM lob_041_tab");
+$desc = oci_new_descriptor($c, OCI_DTYPE_LOB);
+oci_define_by_name($s, "C1", $desc);
+oci_execute($s);
+$data = oci_fetch_assoc($s);
+oci_free_statement($s);
+echo $data['C1']->load(), "\n";
+oci_free_descriptor($desc);
+
+echo "\nTest 2 - implicit statement close\n";
+
+$s = oci_parse($c, "SELECT C1 FROM lob_041_tab");
+$desc = oci_new_descriptor($c, OCI_DTYPE_LOB);
+oci_define_by_name($s, "C1", $desc);
+oci_execute($s);
+$data = oci_fetch_assoc($s);
+$s = null;
+echo $data['C1']->load(), "\n";
+oci_free_descriptor($desc);
+var_dump($desc);
+
+echo "\nTest 3 - no preallocated descriptor\n";
+
+$s = oci_parse($c, "SELECT C1 FROM lob_041_tab");
+oci_execute($s);
+$data = oci_fetch_assoc($s);
+$s = null;
+echo $data['C1']->load(), "\n";
+var_dump($data);
+
+// Cleanup
+
+echo "Done\n";
+
+$stmtarray = array(
+ "DROP table lob_041_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ @oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+
+--EXPECTF--
+Test 1 - explicit statement close
+test data
+
+Test 2 - implicit statement close
+test data
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+
+Test 3 - no preallocated descriptor
+test data
+array(1) {
+ ["C1"]=>
+ object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+Done
diff --git a/tests/lob_042.phpt b/tests/lob_042.phpt
new file mode 100644
index 0000000000..25309d6fc0
--- /dev/null
+++ b/tests/lob_042.phpt
@@ -0,0 +1,69 @@
+--TEST--
+Check various LOB error messages
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+require(dirname(__FILE__).'/create_table.inc');
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob)
+ VALUES (empty_blob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$statement = oci_parse($c,$ora_sql);
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+oci_bind_by_name($statement,":v_blob", $blob,-1,OCI_B_BLOB);
+oci_execute($statement, OCI_DEFAULT);
+
+var_dump($blob);
+
+var_dump($blob->writeTemporary("test", OCI_D_LOB));
+
+$str = "string";
+var_dump($blob->write($str));
+var_dump($blob->truncate(1));
+var_dump($blob->truncate(1));
+var_dump($blob->truncate(2));
+var_dump($blob->truncate(-1));
+var_dump($blob->read(2));
+
+var_dump($blob->import("does_not_exist"));
+var_dump($blob->saveFile("does_not_exist"));
+
+require(dirname(__FILE__).'/drop_table.inc');
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+object(OCI-Lob)#%d (1) {
+ ["descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+}
+
+Warning: OCI-Lob::writetemporary(): Invalid temporary lob type: %d in %s on line %d
+bool(false)
+int(6)
+bool(true)
+bool(true)
+
+Warning: OCI-Lob::truncate(): Size must be less than or equal to the current LOB size in %s on line %d
+bool(false)
+
+Warning: OCI-Lob::truncate(): Length must be greater than or equal to zero in %s on line %d
+bool(false)
+
+Warning: OCI-Lob::read(): Offset must be less than size of the LOB in %s on line %d
+bool(false)
+
+Warning: OCI-Lob::import(): Can't open file %s in %s on line %d
+bool(false)
+
+Warning: OCI-Lob::savefile(): Can't open file %s in %s on line %d
+bool(false)
+Done
diff --git a/tests/lob_043.phpt b/tests/lob_043.phpt
new file mode 100644
index 0000000000..0280ef6de8
--- /dev/null
+++ b/tests/lob_043.phpt
@@ -0,0 +1,104 @@
+--TEST--
+Bug #49560 (LOB resource destructor and refcount test)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+require(dirname(__FILE__).'/details.inc');
+if ($stress_test !== true) die ('skip Slow test not run when $stress_test is FALSE');
+?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table lob_043_tab",
+ "create table lob_043_tab(id number, c1 clob)",
+ "begin
+ for i in 1..50000 loop
+ insert into lob_043_tab (id, c1) values (i, i || ' abcdefghijklmnopq');
+ end loop;
+ end;",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ , 38802 // edition does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+function f1($c)
+{
+ $s = oci_parse($c, 'select id, c1 from lob_043_tab order by id');
+ oci_execute($s);
+ $r = array();
+ while (($row = oci_fetch_array($s, OCI_RETURN_NULLS+OCI_ASSOC+OCI_RETURN_LOBS)) !== false) {
+ $r[] = $row['C1'];
+ }
+ echo "f1 ended\n";
+ return $r;
+}
+
+function f2($c)
+{
+ $s = oci_parse($c, 'select id, c1 from lob_043_tab order by id');
+ oci_execute($s);
+ $r = array();
+ while (($row = oci_fetch_array($s, OCI_RETURN_NULLS+OCI_ASSOC)) !== false) {
+ $r[] = $row['C1'];
+ }
+ echo "f2 ended\n";
+ return $r;
+}
+
+echo "Test 1\n";
+$r = f1($c);
+/*
+ foreach ($r as $v) {
+ echo $v, "\n";
+ }
+*/
+
+echo "Test 2\n";
+$r = f2($c);
+/*
+ foreach ($r as $v) {
+ echo $v->load(), "\n";
+ }
+*/
+
+// Clean up
+
+$stmtarray = array(
+ "drop table lob_043_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+f1 ended
+Test 2
+f2 ended
+===DONE===
diff --git a/tests/lob_aliases.phpt b/tests/lob_aliases.phpt
new file mode 100644
index 0000000000..faa59bf12d
--- /dev/null
+++ b/tests/lob_aliases.phpt
@@ -0,0 +1,99 @@
+--TEST--
+LOB method aliases
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+// Function existence
+echo "Test 1\n";
+var_dump(oci_lob_load());
+var_dump(oci_lob_tell());
+var_dump(oci_lob_truncate());
+var_dump(oci_lob_erase());
+var_dump(oci_lob_flush());
+var_dump(ocisetbufferinglob());
+var_dump(ocigetbufferinglob());
+var_dump(oci_lob_rewind());
+var_dump(oci_lob_read());
+var_dump(oci_lob_eof());
+var_dump(oci_lob_seek());
+var_dump(oci_lob_write());
+var_dump(oci_lob_append());
+var_dump(oci_lob_size());
+var_dump(oci_lob_export());
+var_dump(oci_lob_export());
+var_dump(oci_lob_import());
+// No PHP_FE for oci_lob_write_temporary() or oci_lob_close()
+//var_dump(oci_lob_write_temporary());
+//var_dump(oci_lob_close());
+var_dump(oci_lob_save());
+var_dump(oci_lob_import());
+var_dump(oci_free_descriptor());
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+
+Warning: oci_lob_load() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_tell() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_truncate() expects at least 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_erase() expects at least 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_flush() expects at least 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocisetbufferinglob() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: ocigetbufferinglob() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_rewind() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_read() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_eof() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_seek() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_write() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_append() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_size() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_export() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_export() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_import() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_save() expects at least 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_lob_import() expects exactly 2 parameters, 0 given in %s on line %d
+NULL
+
+Warning: oci_free_descriptor() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+Done
diff --git a/tests/lob_null.phpt b/tests/lob_null.phpt
new file mode 100644
index 0000000000..227ebb89fb
--- /dev/null
+++ b/tests/lob_null.phpt
@@ -0,0 +1,265 @@
+--TEST--
+Test null data for CLOBs
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+// Initialization
+
+$s = oci_parse($c, 'drop table lob_null_tab');
+@oci_execute($s);
+
+$s = oci_parse($c, 'create table lob_null_tab (id number, data clob)');
+oci_execute($s);
+
+$s = oci_parse($c,
+'create or replace procedure lob_null_proc_in (pid in number, pdata in CLOB)
+ as begin
+ insert into lob_null_tab (id, data) values (pid, pdata);
+ end;');
+oci_execute($s);
+
+$s = oci_parse($c,
+'create or replace procedure lob_null_proc_out (pid in number, pdata out clob)
+ as begin
+ select data into pdata from lob_null_tab where id = pid;
+ end;');
+oci_execute($s);
+
+// TEMPORARY CLOB
+
+echo "Temporary CLOB: NULL\n";
+$s = oci_parse($c, "insert into lob_null_tab values (1, :b)");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary(null);
+$r = @oci_execute($s);
+if (!$r) {
+ $m = oci_error($s);
+ echo $m['message'], "\n";
+}
+else {
+ $lob->close();
+}
+
+echo "Temporary CLOB: ''\n";
+$s = oci_parse($c, "insert into lob_null_tab values (2, :b)");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary('');
+$r = @oci_execute($s);
+if (!$r) {
+ $m = oci_error($s);
+ echo $m['message'], "\n";
+}
+else {
+ $lob->close();
+}
+
+echo "Temporary CLOB: text\n";
+$s = oci_parse($c, "insert into lob_null_tab values (3, :b)");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary('Inserted via SQL statement');
+$r = @oci_execute($s);
+if (!$r) {
+ $m = oci_error($s);
+ echo $m['message'], "\n";
+}
+else {
+ $lob->close();
+}
+
+// PROCEDURE PARAMETER
+
+echo "Procedure parameter: NULL\n";
+$s = oci_parse($c, "call lob_null_proc_in(4, :b)");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary(null);
+$r = @oci_execute($s);
+if (!$r) {
+ $m = oci_error($s);
+ echo $m['message'], "\n";
+}
+else {
+ $lob->close();
+}
+
+echo "Procedure parameter: ''\n";
+$s = oci_parse($c, "call lob_null_proc_in(5, :b)");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary('');
+$r = @oci_execute($s);
+if (!$r) {
+ $m = oci_error($s);
+ echo $m['message'], "\n";
+}
+else {
+ $lob->close();
+}
+
+echo "Procedure parameter: text\n";
+$s = oci_parse($c, "call lob_null_proc_in(6, :b)");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary('Inserted via procedure parameter');
+$r = @oci_execute($s);
+if (!$r) {
+ $m = oci_error($s);
+ echo $m['message'], "\n";
+}
+else {
+ $lob->close();
+}
+
+// RETURNING INTO
+
+echo "RETURNING INTO: null\n";
+$s = oci_parse($c, "insert into lob_null_tab values (7, empty_clob()) returning data into :b");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+oci_execute($s, OCI_DEFAULT); // Must have OCI_DEFAULT here so locator is still valid
+$lob->save(null);
+
+echo "RETURNING INTO: ''\n";
+$s = oci_parse($c, "insert into lob_null_tab values (8, empty_clob()) returning data into :b");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+oci_execute($s, OCI_DEFAULT); // Must have OCI_DEFAULT here so locator is still valid
+$lob->save('');
+
+echo "RETURNING INTO: text\n";
+$s = oci_parse($c, "insert into lob_null_tab values (9, empty_clob()) returning data into :b");
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+oci_execute($s, OCI_DEFAULT); // Must have OCI_DEFAULT here so locator is still valid
+$lob->save('Inserted with RETURNING INTO');
+
+echo "Fetch as string\n";
+$s = oci_parse ($c, 'select id, data from lob_null_tab order by id');
+oci_execute($s);
+oci_fetch_all($s, $res);
+var_dump($res);
+
+echo "\nFetch as a descriptor\n";
+$s = oci_parse ($c, 'select id, data from lob_null_tab order by id');
+oci_execute($s);
+while ($arr = oci_fetch_assoc($s)) {
+ if (is_object($arr['DATA'])) {
+ echo $arr['ID'] . " is an object: ";
+ $r = $arr['DATA']->load();
+ var_dump($r);
+ }
+ else {
+ echo $arr['ID'] . " is not an object\n";
+ }
+}
+
+echo "\nFetch via the procedure parameter\n";
+for ($i = 1; $i <= 9; $i++)
+{
+ $s = oci_parse ($c, "call lob_null_proc_out($i, :b)");
+ $lob = oci_new_descriptor($c, OCI_D_LOB);
+ oci_bind_by_name($s, ':b', $lob, -1, OCI_B_CLOB);
+ oci_execute($s);
+ if (is_object($lob)) {
+ echo $i . " is an object: ";
+ $r = $lob->load();
+ var_dump($r);
+ }
+ else {
+ echo $i . " is not an object\n";
+ }
+}
+
+// Cleanup
+
+$s = oci_parse($c, 'drop table lob_null_tab');
+@oci_execute($s);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Temporary CLOB: NULL
+Temporary CLOB: ''
+Temporary CLOB: text
+Procedure parameter: NULL
+Procedure parameter: ''
+Procedure parameter: text
+RETURNING INTO: null
+RETURNING INTO: ''
+RETURNING INTO: text
+Fetch as string
+array(2) {
+ ["ID"]=>
+ array(9) {
+ [0]=>
+ string(1) "1"
+ [1]=>
+ string(1) "2"
+ [2]=>
+ string(1) "3"
+ [3]=>
+ string(1) "4"
+ [4]=>
+ string(1) "5"
+ [5]=>
+ string(1) "6"
+ [6]=>
+ string(1) "7"
+ [7]=>
+ string(1) "8"
+ [8]=>
+ string(1) "9"
+ }
+ ["DATA"]=>
+ array(9) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(0) ""
+ [2]=>
+ string(26) "Inserted via SQL statement"
+ [3]=>
+ string(0) ""
+ [4]=>
+ string(0) ""
+ [5]=>
+ string(32) "Inserted via procedure parameter"
+ [6]=>
+ string(0) ""
+ [7]=>
+ string(0) ""
+ [8]=>
+ string(28) "Inserted with RETURNING INTO"
+ }
+}
+
+Fetch as a descriptor
+1 is an object: string(0) ""
+2 is an object: string(0) ""
+3 is an object: string(26) "Inserted via SQL statement"
+4 is an object: string(0) ""
+5 is an object: string(0) ""
+6 is an object: string(32) "Inserted via procedure parameter"
+7 is an object: string(0) ""
+8 is an object: string(0) ""
+9 is an object: string(28) "Inserted with RETURNING INTO"
+
+Fetch via the procedure parameter
+1 is an object: string(0) ""
+2 is an object: string(0) ""
+3 is an object: string(26) "Inserted via SQL statement"
+4 is an object: string(0) ""
+5 is an object: string(0) ""
+6 is an object: string(32) "Inserted via procedure parameter"
+7 is an object: string(0) ""
+8 is an object: string(0) ""
+9 is an object: string(28) "Inserted with RETURNING INTO"
+Done \ No newline at end of file
diff --git a/tests/lob_temp.phpt b/tests/lob_temp.phpt
new file mode 100644
index 0000000000..cad2d39058
--- /dev/null
+++ b/tests/lob_temp.phpt
@@ -0,0 +1,36 @@
+--TEST--
+temporary lobs
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+var_dump($blob->writeTemporary("test"));
+var_dump($blob->load());
+var_dump($blob->seek(0, SEEK_SET));
+var_dump($blob->read(2));
+
+$c = oci_pconnect($user, $password, $dbase);
+
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+var_dump($blob->writeTemporary("test"));
+var_dump($blob->load());
+var_dump($blob->seek(0, SEEK_SET));
+var_dump($blob->read(2));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+bool(true)
+string(4) "test"
+bool(true)
+string(2) "te"
+bool(true)
+string(4) "test"
+bool(true)
+string(2) "te"
+Done
diff --git a/tests/lob_temp1.phpt b/tests/lob_temp1.phpt
new file mode 100644
index 0000000000..2482d65f64
--- /dev/null
+++ b/tests/lob_temp1.phpt
@@ -0,0 +1,32 @@
+--TEST--
+closing temporary lobs
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+var_dump($blob->writeTemporary("test"));
+var_dump($blob->load());
+var_dump($blob->close());
+
+$c = oci_pconnect($user, $password, $dbase);
+
+$blob = oci_new_descriptor($c,OCI_D_LOB);
+var_dump($blob->writeTemporary("test"));
+var_dump($blob->load());
+var_dump($blob->close());
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+bool(true)
+string(4) "test"
+bool(true)
+bool(true)
+string(4) "test"
+bool(true)
+Done
diff --git a/tests/minfo.phpt b/tests/minfo.phpt
new file mode 100644
index 0000000000..f6b95ff296
--- /dev/null
+++ b/tests/minfo.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Code coverage for PHP_MINFO_FUNCTION(oci)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+ob_start();
+phpinfo(INFO_MODULES);
+$v = ob_get_clean();
+$r = strpos($v, 'OCI8 Support => enabled');
+var_dump($r);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+int(%d)
+Done
diff --git a/tests/num.phpt b/tests/num.phpt
new file mode 100644
index 0000000000..e9dc6a8ac2
--- /dev/null
+++ b/tests/num.phpt
@@ -0,0 +1,256 @@
+--TEST--
+oci_num_*() family
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table num_tab",
+ "create table num_tab (id number, value number)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+echo "Test 1\n";
+var_dump(ocirowcount());
+var_dump(oci_num_rows());
+var_dump(ocinumcols());
+var_dump(oci_num_fields());
+
+echo "Test 2\n";
+$insert_sql = "insert into num_tab (id, value) values (1,1)";
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+for ($i = 0; $i<3; $i++) {
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+echo "Test 3\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+if (!oci_commit($c)) {
+ die("oci_commit() failed!\n");
+}
+
+echo "Test 4\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+// All rows
+$select_sql = "select * from num_tab";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+echo "Test 5a\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+echo "Test 5b\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+
+if (oci_fetch_all($s,$r) === false) {
+ die("oci_fetch_all(select) failed!\n");
+}
+
+echo "Test 5c\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+// One row
+$select_sql = "SELECT id, value FROM num_tab WHERE ROWNUM < 2";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+if (oci_fetch_all($s,$r) === false) {
+ die("oci_fetch_all(select) failed!\n");
+}
+
+echo "Test 6\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+// No rows
+$select_sql = "select id from num_tab where 1=0";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+if (oci_fetch_all($s,$r) === false) {
+ die("oci_fetch_all(select) failed!\n");
+}
+
+echo "Test 7\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+$delete_sql = "delete from num_tab";
+
+if (!($s = oci_parse($c, $delete_sql))) {
+ die("oci_parse(delete) failed!\n");
+}
+
+if (!oci_execute($s)) {
+ die("oci_execute(delete) failed!\n");
+}
+
+echo "Test 8a\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+
+oci_commit($c);
+
+echo "Test 8b\n";
+var_dump(ocirowcount($s));
+var_dump(oci_num_rows($s));
+var_dump(ocinumcols($s));
+var_dump(oci_num_fields($s));
+
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table num_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+
+Warning: ocirowcount() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_num_rows() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: ocinumcols() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+
+Warning: oci_num_fields() expects exactly 1 parameter, 0 given in %s on line %d
+NULL
+Test 2
+int(0)
+int(0)
+int(0)
+int(0)
+Test 3
+int(1)
+int(1)
+int(0)
+int(0)
+Test 4
+int(1)
+int(1)
+int(0)
+int(0)
+Test 5a
+int(0)
+int(0)
+int(0)
+int(0)
+Test 5b
+int(0)
+int(0)
+int(2)
+int(2)
+Test 5c
+int(3)
+int(3)
+int(2)
+int(2)
+Test 6
+int(1)
+int(1)
+int(2)
+int(2)
+Test 7
+int(0)
+int(0)
+int(1)
+int(1)
+Test 8a
+int(3)
+int(3)
+int(0)
+int(0)
+Test 8b
+int(3)
+int(3)
+int(0)
+int(0)
+Done
diff --git a/tests/oci8safemode.phpt b/tests/oci8safemode.phpt
new file mode 100644
index 0000000000..1c62f36d39
--- /dev/null
+++ b/tests/oci8safemode.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test functionality disabled in safe mode
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+safe_mode=On
+oci8.privileged_connect=On
+--FILE--
+<?php
+
+$c = oci_connect("hr", "hrpwd", "//localhost/XE", null, OCI_SYSDBA);
+
+$r = oci_password_change($c, "hr", "hrpwd", "hrpwd");
+
+echo "Done\n";
+?>
+--EXPECTF--
+%sarning:%sDirective 'safe_mode' is deprecated in PHP 5.3 and greater in Unknown on line 0
+
+Warning: oci_connect(): Privileged connect is disabled in Safe Mode in %s on line %d
+
+Warning: oci_password_change(): is disabled in Safe Mode in %s on line %d
+Done
diff --git a/tests/oci_execute_segfault.phpt b/tests/oci_execute_segfault.phpt
new file mode 100644
index 0000000000..9ba7d770fd
--- /dev/null
+++ b/tests/oci_execute_segfault.phpt
@@ -0,0 +1,48 @@
+--TEST--
+oci_execute() segfault after repeated bind of LOB descriptor
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (blob, clob)
+ VALUES (empty_blob(), empty_clob())
+ RETURNING
+ blob
+ INTO :v_blob ";
+
+$s = oci_parse($c, $ora_sql);
+$blob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ":v_blob", $blob, -1, OCI_B_BLOB);
+oci_execute($s, OCI_DEFAULT);
+var_dump($blob->save("some binary data"));
+
+oci_bind_by_name($s, ":v_blob", $blob, -1, OCI_B_BLOB);
+oci_execute($s, OCI_DEFAULT);
+var_dump($blob->save("some more binary data"));
+
+$query = 'SELECT blob, DBMS_LOB.GETLENGTH(blob) FROM '.$schema.$table_name.' ORDER BY 2';
+
+$s = oci_parse ($c, $query);
+oci_execute($s, OCI_DEFAULT);
+
+while ($arr = oci_fetch_assoc($s)) {
+ $result = $arr['BLOB']->load();
+ var_dump($result);
+}
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+string(16) "some binary data"
+string(21) "some more binary data"
+Done
diff --git a/tests/old_oci_close.phpt b/tests/old_oci_close.phpt
new file mode 100644
index 0000000000..f15b7febea
--- /dev/null
+++ b/tests/old_oci_close.phpt
@@ -0,0 +1,23 @@
+--TEST--
+oci8.old_oci_close_semantics On
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=1
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+var_dump($c);
+var_dump(oci_close($c));
+var_dump(oci_parse($c, "select 1 from dual"));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+NULL
+resource(%d) of type (oci8 statement)
+Done
diff --git a/tests/old_oci_close1.phpt b/tests/old_oci_close1.phpt
new file mode 100644
index 0000000000..9af2eeb398
--- /dev/null
+++ b/tests/old_oci_close1.phpt
@@ -0,0 +1,25 @@
+--TEST--
+oci8.old_oci_close_semantics Off
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.old_oci_close_semantics=0
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+var_dump($c);
+var_dump(oci_close($c));
+var_dump(oci_parse($c, "select 1 from dual"));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+bool(true)
+
+Warning: oci_parse() expects parameter 1 to be resource, null given in %s on line %d
+NULL
+Done
diff --git a/tests/password.phpt b/tests/password.phpt
new file mode 100644
index 0000000000..7133d8bae8
--- /dev/null
+++ b/tests/password.phpt
@@ -0,0 +1,83 @@
+--TEST--
+oci_password_change() for non-persistent connections
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/details.inc");
+if (empty($dbase)) die ("skip requires database connection string be set");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+if ($test_drcp) die("skip password change not supported in DRCP Mode");
+?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/details.inc");
+
+// Create a user we can stuff around with and not affect subsequent tests
+$c0 = oci_connect($user, $password, $dbase);
+$stmts = array(
+ "drop user testuser",
+ "begin
+ execute immediate 'create user testuser identified by testuserpwd';
+ execute immediate 'grant connect, create session to testuser';
+ end;");
+foreach ($stmts as $sql) {
+ $s = oci_parse($c0, $sql);
+ @oci_execute($s);
+}
+
+// Connect and change the password
+$c1 = oci_connect("testuser", "testuserpwd", $dbase);
+var_dump($c1);
+$rn1 = (int)$c1;
+
+oci_password_change($c1, "testuser", "testuserpwd", "testuserpwd2");
+
+// Second connect should return a new resource because the hash string will be different from $c1
+$c2 = oci_connect("testuser", "testuserpwd2", $dbase);
+var_dump($c2);
+$rn2 = (int)$c2;
+
+// Despite using the old password this connect should succeed and return the original resource
+$c3 = oci_connect("testuser", "testuserpwd", $dbase);
+var_dump($c3);
+$rn3 = (int)$c3;
+
+// Connections should differ
+if ($rn1 == $rn2) {
+ echo "First and second connections share a resource: Not OK\n";
+ var_dump($c1);
+}
+else {
+ echo "First and second connections are different: OK\n";
+}
+
+// Connections should be the same
+if ($rn1 == $rn3) {
+ echo "First and third connections share a resource: OK\n";
+}
+else {
+ echo "First and third connections are different: Not OK\n";
+ var_dump($c1);
+ var_dump($c2);
+}
+
+// Clean up
+oci_close($c1);
+oci_close($c2);
+oci_close($c3);
+
+// Clean up
+$s = oci_parse($c0, "drop user cascade testuser");
+@oci_execute($s);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+First and second connections are different: OK
+First and third connections share a resource: OK
+Done
diff --git a/tests/password_2.phpt b/tests/password_2.phpt
new file mode 100644
index 0000000000..71423e717b
--- /dev/null
+++ b/tests/password_2.phpt
@@ -0,0 +1,83 @@
+--TEST--
+oci_password_change() for persistent connections
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/details.inc");
+if (empty($dbase)) die ("skip requires database connection string be set");
+if (strcasecmp($user, "system") && strcasecmp($user, "sys")) die("skip needs to be run as a DBA user");
+if ($test_drcp) die("skip password change not supported in DRCP Mode");
+?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/details.inc");
+
+// Create a user we can stuff around with and not affect subsequent tests
+$c0 = oci_connect($user, $password, $dbase);
+$stmts = array(
+ "drop user testuser",
+ "begin
+ execute immediate 'create user testuser identified by testuserpwd';
+ execute immediate 'grant connect, create session to testuser';
+ end;");
+foreach ($stmts as $sql) {
+ $s = oci_parse($c0, $sql);
+ @oci_execute($s);
+}
+
+// Connect (persistent) and change the password
+$c1 = oci_pconnect("testuser", "testuserpwd", $dbase);
+var_dump($c1);
+$rn1 = (int)$c1;
+
+oci_password_change($c1, "testuser", "testuserpwd", "testuserpwd2");
+
+// Second connect should return a new resource because the hash string will be different from $c1
+$c2 = oci_pconnect("testuser", "testuserpwd2", $dbase);
+var_dump($c2);
+$rn2 = (int)$c2;
+
+// Despite using the old password this connect should succeed and return the original resource
+$c3 = oci_pconnect("testuser", "testuserpwd", $dbase);
+var_dump($c3);
+$rn3 = (int)$c3;
+
+// Connections should differ
+if ($rn1 == $rn2) {
+ echo "First and second connections share a resource: Not OK\n";
+ var_dump($c1);
+}
+else {
+ echo "First and second connections are different: OK\n";
+}
+
+// Connections should be the same
+if ($rn1 == $rn3) {
+ echo "First and third connections share a resource: OK\n";
+}
+else {
+ echo "First and third connections are different: Not OK\n";
+ var_dump($c1);
+ var_dump($c2);
+}
+
+// Clean up
+oci_close($c1);
+oci_close($c2);
+oci_close($c3);
+
+// Clean up
+$s = oci_parse($c0, "drop user cascade testuser");
+@oci_execute($s);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 persistent connection)
+First and second connections are different: OK
+First and third connections share a resource: OK
+Done
diff --git a/tests/password_new.phpt b/tests/password_new.phpt
new file mode 100644
index 0000000000..ba6baa964b
--- /dev/null
+++ b/tests/password_new.phpt
@@ -0,0 +1,49 @@
+--TEST--
+oci_password_change()
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (empty($dbase)) die ("skip requires database connection string be set");
+if ($test_drcp) die("skip password change not supported in DRCP Mode");
+
+// This test is known to fail with Oracle 10.2.0.4 client libraries
+// connecting to Oracle Database 11 (Oracle bug 6277160, fixed 10.2.0.5)
+$sv = oci_server_version($c);
+$sv = preg_match('/Release (11|12)\./', $sv, $matches);
+if ($sv === 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 10/', $phpinfo);
+ if ($iv === 1) {
+ die ("skip test known to fail using Oracle 10.2.0.4 client libs connecting to Oracle 11 (6277160)");
+ }
+}
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$new_password = "test";
+var_dump(oci_password_change($dbase, $user, $password, $new_password));
+
+if (!empty($dbase)) {
+ var_dump($new_c = ocilogon($user,$new_password,$dbase));
+}
+else {
+ var_dump($new_c = ocilogon($user,$new_password));
+}
+
+var_dump(oci_password_change($dbase, $user, $new_password, $password));
+
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+Done
diff --git a/tests/password_old.phpt b/tests/password_old.phpt
new file mode 100644
index 0000000000..abcaeb1e56
--- /dev/null
+++ b/tests/password_old.phpt
@@ -0,0 +1,49 @@
+--TEST--
+ocipasswordchange()
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+if (empty($dbase)) die ("skip requires database connection string be set");
+if ($test_drcp) die("skip password change not supported in DRCP Mode");
+
+// This test is known to fail with Oracle 10.2.0.4 client libraries
+// connecting to Oracle Database 11 (Oracle bug 6277160, fixed 10.2.0.5)
+$sv = oci_server_version($c);
+$sv = preg_match('/Release (11|12)\./', $sv, $matches);
+if ($sv === 1) {
+ ob_start();
+ phpinfo(INFO_MODULES);
+ $phpinfo = ob_get_clean();
+ $iv = preg_match('/Oracle .*Version => 10/', $phpinfo);
+ if ($iv === 1) {
+ die ("skip test known to fail using Oracle 10.2.0.4 client libs connecting to Oracle 11 (6277160)");
+ }
+}
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$new_password = "test";
+var_dump(ocipasswordchange($dbase, $user, $password, $new_password));
+
+if (!empty($dbase)) {
+ var_dump($new_c = ocilogon($user,$new_password,$dbase));
+}
+else {
+ var_dump($new_c = ocilogon($user,$new_password));
+}
+
+var_dump(ocipasswordchange($dbase, $user, $new_password, $password));
+
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+Done
diff --git a/tests/pecl_bug10194.phpt b/tests/pecl_bug10194.phpt
new file mode 100644
index 0000000000..4714fadcd4
--- /dev/null
+++ b/tests/pecl_bug10194.phpt
@@ -0,0 +1,47 @@
+--TEST--
+PECL Bug #10194 (segfault in Instant Client when memory_limit is reached inside the callback)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+memory_limit=10M
+--FILE--
+<?php
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO
+ ".$schema.$table_name." (clob)
+ VALUES (empty_clob())
+ ";
+
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+$ora_sql = "SELECT clob FROM ".$schema.$table_name." FOR UPDATE";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement, OCI_DEFAULT);
+
+$row = oci_fetch_assoc($statement);
+
+$string = str_repeat("test", 32768*4*4);
+
+for ($i = 0; $i < 8; $i++) {
+ $row['CLOB']->write($string);
+}
+
+oci_commit($c);
+
+$ora_sql = "SELECT clob FROM ".$schema.$table_name."";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+$row = oci_fetch_assoc($statement);
+var_dump(strlen($row['CLOB']->load())); /* here it should fail */
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECTF--
+Fatal error: Allowed memory size of 10485760 bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
diff --git a/tests/pecl_bug10194_blob.phpt b/tests/pecl_bug10194_blob.phpt
new file mode 100644
index 0000000000..4c6aa4f1c9
--- /dev/null
+++ b/tests/pecl_bug10194_blob.phpt
@@ -0,0 +1,54 @@
+--TEST--
+PECL Bug #10194 (segfault in Instant Client when memory_limit is reached inside the callback)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platforms only");
+?>
+--INI--
+memory_limit=3M
+--FILE--
+<?php
+
+// This test is dependent on the behavior of the memory manager
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO ".$schema.$table_name." (blob)
+ VALUES (empty_blob())";
+
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+$ora_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement, OCI_DEFAULT);
+
+$row = oci_fetch_assoc($statement);
+
+$string = str_repeat("test", 32768*4*4);
+
+for ($i = 0; $i < 8; $i++) {
+ $row['BLOB']->write($string);
+}
+
+oci_commit($c);
+
+$ora_sql = "SELECT blob FROM ".$schema.$table_name;
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+echo "Before load()\n";
+
+$row = oci_fetch_assoc($statement);
+var_dump(strlen($row['BLOB']->load())); /* here it should fail */
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECTF--
+Before load()
+
+Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
diff --git a/tests/pecl_bug10194_blob_64.phpt b/tests/pecl_bug10194_blob_64.phpt
new file mode 100644
index 0000000000..433d586a4e
--- /dev/null
+++ b/tests/pecl_bug10194_blob_64.phpt
@@ -0,0 +1,54 @@
+--TEST--
+PECL Bug #10194 (segfault in Instant Client when memory_limit is reached inside the callback)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platforms only");
+?>
+--INI--
+memory_limit=6M
+--FILE--
+<?php
+
+// This test is dependent on the behavior of the memory manager
+
+require dirname(__FILE__).'/connect.inc';
+require dirname(__FILE__).'/create_table.inc';
+
+$ora_sql = "INSERT INTO ".$schema.$table_name." (blob)
+ VALUES (empty_blob())";
+
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+$ora_sql = "SELECT blob FROM ".$schema.$table_name." FOR UPDATE";
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement, OCI_DEFAULT);
+
+$row = oci_fetch_assoc($statement);
+
+$string = str_repeat("test", 32768*4*4);
+
+for ($i = 0; $i < 8; $i++) {
+ $row['BLOB']->write($string);
+}
+
+oci_commit($c);
+
+$ora_sql = "SELECT blob FROM ".$schema.$table_name;
+$statement = oci_parse($c,$ora_sql);
+oci_execute($statement);
+
+echo "Before load()\n";
+
+$row = oci_fetch_assoc($statement);
+var_dump(strlen($row['BLOB']->load())); /* here it should fail */
+
+require dirname(__FILE__).'/drop_table.inc';
+
+echo "Done\n";
+?>
+--EXPECTF--
+Before load()
+
+Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
diff --git a/tests/pecl_bug16035.phpt b/tests/pecl_bug16035.phpt
new file mode 100644
index 0000000000..fc91bc91bc
--- /dev/null
+++ b/tests/pecl_bug16035.phpt
@@ -0,0 +1,26 @@
+--TEST--
+PECL Bug #16035 (Crash with Oracle 10.2 connecting with a character set but ORACLE_HOME isn't set)
+--SKIPIF--
+<?php
+if (!extension_loaded('oci8')) die ("skip no oci8 extension");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$ov = preg_match('/Compile-time ORACLE_HOME/', $phpinfo);
+if ($ov !== 1) {
+ die ("skip Test only valid when OCI8 is built with an ORACLE_HOME");
+}
+?>
+--ENV--
+ORACLE_HOME=""
+--FILE--
+<?php
+
+oci_connect('abc', 'def', 'ghi', 'jkl');
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Warning: oci_connect(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that ORACLE_HOME and %s are set and point to the right directories in %s on line %d
+===DONE===
diff --git a/tests/pecl_bug16842.phpt b/tests/pecl_bug16842.phpt
new file mode 100644
index 0000000000..d796d2506e
--- /dev/null
+++ b/tests/pecl_bug16842.phpt
@@ -0,0 +1,69 @@
+--TEST--
+PECL Bug #16842 (NO_DATA_FOUND exception is a warning)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--INI--
+error_reporting = E_WARNING
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Run Test
+
+echo "Test 1\n";
+
+echo "Raises NO_DATA_FOUND\n";
+$s = oci_parse($c, 'begin raise NO_DATA_FOUND; end;');
+$e = oci_execute($s);
+var_dump($e);
+var_dump(oci_error($s));
+
+echo "Test 2\n";
+
+echo "Raises ZERO_DIVIDE\n";
+$s = oci_parse($c, 'begin raise ZERO_DIVIDE; end;');
+$e = oci_execute($s);
+var_dump($e);
+var_dump(oci_error($s));
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1
+Raises NO_DATA_FOUND
+
+Warning: oci_execute(): OCI_NO_DATA in %s on line 11
+bool(false)
+array(4) {
+ [%u|b%"code"]=>
+ int(1403)
+ [%u|b%"message"]=>
+ %unicode|string%(45) "ORA-01403: %s
+ORA-06512: at line 1"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(31) "begin raise NO_DATA_FOUND; end;"
+}
+Test 2
+Raises ZERO_DIVIDE
+
+Warning: oci_execute(): ORA-01476: %s
+ORA-06512: at line 1 in %s on line 19
+bool(false)
+array(4) {
+ [%u|b%"code"]=>
+ int(1476)
+ [%u|b%"message"]=>
+ %unicode|string%(56) "ORA-01476: %s
+ORA-06512: at line 1"
+ [%u|b%"offset"]=>
+ int(0)
+ [%u|b%"sqltext"]=>
+ %unicode|string%(29) "begin raise ZERO_DIVIDE; end;"
+}
+===DONE===
diff --git a/tests/pecl_bug6109.phpt b/tests/pecl_bug6109.phpt
new file mode 100644
index 0000000000..d0762fa883
--- /dev/null
+++ b/tests/pecl_bug6109.phpt
@@ -0,0 +1,40 @@
+--TEST--
+PECL Bug #6109 (Error messages not kept)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Run Test
+
+echo "Test 1\n";
+
+$s = oci_parse($c, 'delete from table_does_not_exist');
+$r = @oci_execute($s);
+
+if ($r) {
+ echo "whoops - table does exist\n";
+} else {
+ for ($i = 0; $i < 5; $i++) {
+ $err = oci_error($s);
+ echo ($i) .' -> '.$err['message'] ."\n";
+ }
+}
+
+// Cleanup
+
+oci_close($c);
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Test 1
+0 -> ORA-00942: %s
+1 -> ORA-00942: %s
+2 -> ORA-00942: %s
+3 -> ORA-00942: %s
+4 -> ORA-00942: %s
+Done
diff --git a/tests/pecl_bug8816.phpt b/tests/pecl_bug8816.phpt
new file mode 100644
index 0000000000..c369711fcf
--- /dev/null
+++ b/tests/pecl_bug8816.phpt
@@ -0,0 +1,98 @@
+--TEST--
+PECL Bug #8816 (issue in php_oci_statement_fetch with more than one piecewise column)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$create_1 = "CREATE TABLE t1 (id INTEGER, l1 LONG)";
+$create_2 = "CREATE TABLE t2 (id INTEGER, l2 LONG)";
+$drop_1 = "DROP TABLE t1";
+$drop_2 = "DROP TABLE t2";
+
+$s1 = oci_parse($c, $drop_1);
+$s2 = oci_parse($c, $drop_2);
+@oci_execute($s1);
+@oci_execute($s2);
+
+$s1 = oci_parse($c, $create_1);
+$s2 = oci_parse($c, $create_2);
+oci_execute($s1);
+oci_execute($s2);
+
+$values = array("1234567890111111111", "122222222222222", "985456745674567654567654567654", "123456789", "987654321");
+
+$i = 0;
+foreach ($values as $val) {
+ $i++;
+ $insert = "INSERT INTO t1 VALUES($i, ".$val.")";
+ $s = oci_parse($c, $insert);
+ oci_execute($s);
+}
+
+foreach ($values as $val) {
+ $insert = "INSERT INTO t2 VALUES($i, ".$val.")";
+ $s = oci_parse($c, $insert);
+ oci_execute($s);
+ $i--;
+}
+
+$query ="
+SELECT
+ t1.l1, t2.l2
+FROM
+t1, t2
+WHERE
+t1.id = t2.id
+ORDER BY t1.id ASC
+";
+
+$sth = oci_parse($c, $query);
+oci_execute($sth);
+
+while ( $row = oci_fetch_assoc($sth) ) {
+ var_dump($row);
+}
+
+$s1 = oci_parse($c, $drop_1);
+$s2 = oci_parse($c, $drop_2);
+@oci_execute($s1);
+@oci_execute($s2);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+array(2) {
+ ["L1"]=>
+ string(19) "1234567890111111111"
+ ["L2"]=>
+ string(9) "987654321"
+}
+array(2) {
+ ["L1"]=>
+ string(15) "122222222222222"
+ ["L2"]=>
+ string(9) "123456789"
+}
+array(2) {
+ ["L1"]=>
+ string(30) "985456745674567654567654567654"
+ ["L2"]=>
+ string(30) "985456745674567654567654567654"
+}
+array(2) {
+ ["L1"]=>
+ string(9) "123456789"
+ ["L2"]=>
+ string(15) "122222222222222"
+}
+array(2) {
+ ["L1"]=>
+ string(9) "987654321"
+ ["L2"]=>
+ string(19) "1234567890111111111"
+}
+Done
diff --git a/tests/persistent.phpt b/tests/persistent.phpt
new file mode 100644
index 0000000000..884cd35a4c
--- /dev/null
+++ b/tests/persistent.phpt
@@ -0,0 +1,26 @@
+--TEST--
+reusing persistent connections
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+var_dump(oci_pconnect($user, $password, $dbase));
+var_dump(oci_pconnect($user, $password, $dbase));
+var_dump(oci_pconnect($user, $password, $dbase));
+var_dump(oci_connect($user, $password, $dbase));
+var_dump(oci_connect($user, $password, $dbase));
+var_dump(oci_connect($user, $password, $dbase));
+
+echo "Done\n";
+?>
+--EXPECTF--
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 persistent connection)
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+resource(%d) of type (oci8 connection)
+Done
diff --git a/tests/prefetch.phpt b/tests/prefetch.phpt
new file mode 100644
index 0000000000..26762601df
--- /dev/null
+++ b/tests/prefetch.phpt
@@ -0,0 +1,72 @@
+--TEST--
+oci_set_prefetch()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialize
+
+$stmtarray = array(
+ "drop table prefetch_tab",
+ "create table prefetch_tab (id number, value number)",
+ "insert into prefetch_tab (id, value) values (1,1)",
+ "insert into prefetch_tab (id, value) values (1,1)",
+ "insert into prefetch_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+$select_sql = "select * from prefetch_tab";
+
+if (!($s = oci_parse($c, $select_sql))) {
+ die("oci_parse(select) failed!\n");
+}
+
+var_dump(oci_set_prefetch($s, 10));
+
+if (!oci_execute($s)) {
+ die("oci_execute(select) failed!\n");
+}
+
+var_dump(oci_fetch($s));
+var_dump(oci_num_rows($s));
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table prefetch_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+bool(true)
+bool(true)
+int(1)
+Done
diff --git a/tests/prefetch_old.phpt b/tests/prefetch_old.phpt
new file mode 100644
index 0000000000..c2ac8fe841
--- /dev/null
+++ b/tests/prefetch_old.phpt
@@ -0,0 +1,75 @@
+--TEST--
+ocisetprefetch()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+$stmtarray = array(
+ "drop table prefetch_old_tab",
+ "create table prefetch_old_tab (id number, value number)",
+ "insert into prefetch_old_tab (id, value) values (1,1)",
+ "insert into prefetch_old_tab (id, value) values (1,1)",
+ "insert into prefetch_old_tab (id, value) values (1,1)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+// Run Test
+
+if (!ocicommit($c)) {
+ die("ocicommit() failed!\n");
+}
+
+$select_sql = "select * from prefetch_old_tab";
+
+if (!($s = ociparse($c, $select_sql))) {
+ die("ociparse(select) failed!\n");
+}
+
+var_dump(ocisetprefetch($s, 10));
+
+if (!ociexecute($s)) {
+ die("ociexecute(select) failed!\n");
+}
+
+var_dump(ocifetch($s));
+var_dump(ocirowcount($s));
+
+
+// Cleanup
+
+$stmtarray = array(
+ "drop table prefetch_old_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+bool(true)
+bool(true)
+int(1)
+Done
diff --git a/tests/privileged_connect.phpt b/tests/privileged_connect.phpt
new file mode 100644
index 0000000000..39122240a7
--- /dev/null
+++ b/tests/privileged_connect.phpt
@@ -0,0 +1,25 @@
+--TEST--
+privileged connect tests
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+oci_connect("", "", "", false, OCI_SYSOPER);
+oci_connect("", "", "", false, OCI_SYSDBA);
+oci_connect("", "", "", false, -1);
+oci_connect("", "", "", false, "qwe");
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_connect(): Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA in %s on line %d
+
+Warning: oci_connect(): Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA in %s on line %d
+
+Warning: oci_connect(): Invalid session mode specified (-1) in %s on line %d
+
+Warning: oci_connect() expects parameter 5 to be long, string given in %s on line %d
+Done
diff --git a/tests/privileged_connect1.phpt b/tests/privileged_connect1.phpt
new file mode 100644
index 0000000000..44bb2f60a8
--- /dev/null
+++ b/tests/privileged_connect1.phpt
@@ -0,0 +1,27 @@
+--TEST--
+privileged connect tests
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--INI--
+oci8.privileged_connect=1
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+oci_connect("", "", "", false, OCI_SYSOPER);
+oci_connect("", "", "", false, OCI_SYSDBA);
+oci_connect("", "", "", false, -1);
+oci_connect("", "", "", false, "qwe");
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: oci_connect(): ORA-%d: %s in %s on line %d
+
+Warning: oci_connect(): ORA-%d: %s in %s on line %d
+
+Warning: oci_connect(): Invalid session mode specified (-1) in %s on line %d
+
+Warning: oci_connect() expects parameter 5 to be long, string given in %s on line %d
+Done
diff --git a/tests/refcur_prefetch_1.phpt b/tests/refcur_prefetch_1.phpt
new file mode 100644
index 0000000000..904e4da1ff
--- /dev/null
+++ b/tests/refcur_prefetch_1.phpt
@@ -0,0 +1,256 @@
+--TEST--
+Prefetch with REF cursor. Test different values for prefetch with oci_set_prefetch().
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$iv = preg_match('/Oracle .*Version => (11\.2|12\.)/', $phpinfo);
+if ($iv == 1) {
+ $sv = oci_server_version($c);
+ $sv = preg_match('/Release 1[012]\./', $sv, $matches);
+ if ($sv != 1) {
+ die ("skip expected output only valid when using Oracle 10g or greater server");
+ }
+}
+else {
+ die ("skip expected output only valid when using Oracle 11.2 or greater client");
+}
+?>
+--FILE--
+<?php
+require(dirname(__FILE__)."/connect.inc");
+
+// Creates the necessary package and tables.
+$stmtarray = array(
+ "DROP TABLE refcurtest",
+ "CREATE TABLE refcurtest (c1 NUMBER, c2 VARCHAR(20))",
+ "CREATE or REPLACE PACKAGE refcurpkg is
+ type refcursortype is ref cursor;
+ procedure open_ref_cur(cur1 out refcursortype);
+ procedure fetch_ref_cur(cur1 in refcursortype, c1 out number,c2 out varchar2);
+ end refcurpkg;",
+ "CREATE or REPLACE PACKAGE body refcurpkg is
+ procedure open_ref_cur(cur1 out refcursortype) is
+ begin
+ open cur1 for select * from refcurtest order by c1;
+ end open_ref_cur;
+ procedure fetch_ref_cur(cur1 in refcursortype, c1 out number,
+ c2 out varchar2) is
+ begin
+ fetch cur1 into c1,c2;
+ end fetch_ref_cur;
+ end refcurpkg;"
+ );
+
+foreach($stmtarray as $stmt) {
+ $s = oci_parse($c,$stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $msg = oci_error($s);
+ if ($msg['code'] != 942) {
+ echo $msg['message'],"\n";
+ }
+ }
+}
+
+// Insert 500 rows into the table.
+$insert_sql = "INSERT INTO refcurtest (c1, c2) VALUES (:c1,:c2)";
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<=500; $i++) {
+ $val2 = 'test'.$i;
+ oci_bind_by_name($s,':c1',$i);
+ oci_bind_by_name($s,':c2',$val2);
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+// Various values for prefetch
+$pref = array(0,1,501,499,250,12345,-12345,-1);
+foreach($pref as $value) {
+ echo"-----------------------------------------------\n";
+ echo "Test with Prefetch value set to $value \n";
+ echo"-----------------------------------------------\n";
+ $cur1 = oci_new_cursor($c);
+ fetch_frm_php($c,$cur1,$value);
+ fetch_frm_plsql($c,$cur1);
+}
+
+
+// This function sets the prefetch count to the given $value and fetches one row .
+
+function fetch_frm_php($c,$cur1,$value) {
+ $sql1 = "begin refcurpkg.open_ref_cur(:cur1); end;";
+ $s1 = oci_parse($c,$sql1);
+ if (!oci_bind_by_name($s1,":cur1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql1) failed!\n");
+ }
+ oci_execute($s1);
+ oci_set_prefetch($cur1,$value);
+ oci_execute($cur1);
+ echo "Fetch Row from PHP\n";
+ var_dump(oci_fetch_row($cur1));
+}
+
+// This function calls the fetch_ref_cur procedure to get the values from the REF cur.
+
+function fetch_frm_plsql($c,$cur1) {
+ $sql2 = "begin refcurpkg.fetch_ref_cur(:curs1,:c1,:c2); end;";
+ $s2 = oci_parse($c,$sql2);
+ if (!oci_bind_by_name($s2,":curs1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+ }
+ if (!oci_bind_by_name($s2,":c1",$c1,SQLT_INT)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+ }
+ if (!oci_bind_by_name($s2,":c2",$c2,SQLT_AFC)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+ }
+ oci_execute($s2);
+ echo "Fetch Row from PL/SQL\n";
+ var_dump($c1);
+ var_dump($c2);
+}
+
+// Clean up here
+
+$stmtarray = array(
+ "drop package refcurpkg",
+ "drop table refcurtest"
+);
+
+foreach($stmtarray as $stmt) {
+ $s = oci_parse($c,$stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $msg = oci_error($s);
+ echo $msg['message'],"\n";
+ }
+}
+oci_close($c);
+echo "Done\n";
+?>
+--EXPECTF--
+-----------------------------------------------
+Test with Prefetch value set to 0
+-----------------------------------------------
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row from PL/SQL
+%unicode|string%(%d) "1"
+%unicode|string%(%d) "test1"
+-----------------------------------------------
+Test with Prefetch value set to 1
+-----------------------------------------------
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row from PL/SQL
+%unicode|string%(%d) "2"
+%unicode|string%(%d) "test2"
+-----------------------------------------------
+Test with Prefetch value set to 501
+-----------------------------------------------
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+
+Warning: oci_execute(): ORA-01002: %s
+ORA-06512: at "%s.REFCURPKG", line %d
+ORA-06512: at line %d in %s on line %d
+Fetch Row from PL/SQL
+NULL
+NULL
+-----------------------------------------------
+Test with Prefetch value set to 499
+-----------------------------------------------
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row from PL/SQL
+%unicode|string%(%d) "500"
+%unicode|string%(%d) "test500"
+-----------------------------------------------
+Test with Prefetch value set to 250
+-----------------------------------------------
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row from PL/SQL
+%unicode|string%(%d) "251"
+%unicode|string%(%d) "test251"
+-----------------------------------------------
+Test with Prefetch value set to 12345
+-----------------------------------------------
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+
+Warning: oci_execute(): ORA-01002: %s
+ORA-06512: at "%s.REFCURPKG", line %d
+ORA-06512: at line %d in %s on line %d
+Fetch Row from PL/SQL
+NULL
+NULL
+-----------------------------------------------
+Test with Prefetch value set to -12345
+-----------------------------------------------
+
+Warning: oci_set_prefetch(): Number of rows to be prefetched has to be greater than or equal to 0 in %s on line %d
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row from PL/SQL
+%unicode|string%(%d) "101"
+%unicode|string%(%d) "test101"
+-----------------------------------------------
+Test with Prefetch value set to -1
+-----------------------------------------------
+
+Warning: oci_set_prefetch(): Number of rows to be prefetched has to be greater than or equal to 0 in %s on line %d
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row from PL/SQL
+%unicode|string%(%d) "101"
+%unicode|string%(%d) "test101"
+Done
diff --git a/tests/refcur_prefetch_2.phpt b/tests/refcur_prefetch_2.phpt
new file mode 100644
index 0000000000..751ffa78f0
--- /dev/null
+++ b/tests/refcur_prefetch_2.phpt
@@ -0,0 +1,317 @@
+--TEST--
+Prefetch with REF cursor. Test No 2
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$iv = preg_match('/Oracle .*Version => (11\.2|12\.)/', $phpinfo);
+if ($iv == 1) {
+ $sv = oci_server_version($c);
+ $sv = preg_match('/Release 1[012]\./', $sv, $matches);
+ if ($sv != 1) {
+ die ("skip expected output only valid when using Oracle 10g or greater server");
+ }
+}
+else {
+ die ("skip expected output only valid when using Oracle 11.1 or greater client");
+}
+?>
+--FILE--
+<?php
+require dirname(__FILE__)."/connect.inc";
+
+// Creates the necessary package and tables.
+$stmtarray = array(
+ "DROP TABLE refcurtest",
+ "CREATE TABLE refcurtest (c1 NUMBER, c2 VARCHAR(20))",
+ "CREATE or REPLACE PACKAGE refcurpkg is
+ type refcursortype is ref cursor;
+ procedure open_ref_cur(cur1 out refcursortype);
+ procedure fetch_ref_cur(cur1 in refcursortype, c1 out number,c2 out varchar2);
+ end refcurpkg;",
+ "CREATE or REPLACE PACKAGE body refcurpkg is
+ procedure open_ref_cur(cur1 out refcursortype) is
+ begin
+ open cur1 for select * from refcurtest order by c1;
+ end open_ref_cur;
+ procedure fetch_ref_cur(cur1 in refcursortype, c1 out number,
+ c2 out varchar2) is
+ begin
+ fetch cur1 into c1,c2;
+ end fetch_ref_cur;
+ end refcurpkg;"
+ );
+
+foreach($stmtarray as $stmt) {
+ $s = oci_parse($c,$stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $msg = oci_error($s);
+ if ($msg['code'] != 942) {
+ echo $msg['message'],"\n";
+ }
+ }
+}
+
+// Insert 500 rows into the table.
+$insert_sql = "INSERT INTO refcurtest (c1, c2) VALUES (:c1,:c2)";
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i <= 500; $i++) {
+ $val2 = 'test'.$i;
+ oci_bind_by_name($s,':c1',$i);
+ oci_bind_by_name($s,':c2',$val2);
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+// Steps to Fetch from PHP . For every sub-test,the cursor is bound and then executed.
+
+$sql1 = "begin refcurpkg.open_ref_cur(:cur1); end;";
+$s1 = oci_parse($c,$sql1);
+$cur1 = oci_new_cursor($c);
+if (!oci_bind_by_name($s1,":cur1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql1) failed!\n");
+}
+
+
+// Steps to Fetch from PL/SQL . For every sub-test,the cursor is bound and then executed.
+
+$sql2 = "begin refcurpkg.fetch_ref_cur(:curs1,:c1,:c2); end;";
+$s2 = oci_parse($c,$sql2);
+if (!oci_bind_by_name($s2,":curs1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+}
+if (!oci_bind_by_name($s2,":c1",$c1,SQLT_INT)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+}
+if (!oci_bind_by_name($s2,":c2",$c2,SQLT_AFC)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+}
+
+
+echo "------Test 1- Check Roundtrips with prefetch 0 and 5 -----------\n";
+oci_execute($s1);
+oci_execute($cur1);
+$initial_rt = print_roundtrips($c);
+oci_set_prefetch($cur1,0);
+for ($i = 0;$i<5;$i++) {
+ var_dump(oci_fetch_row($cur1));
+}
+
+$cnt = (print_roundtrips($c) - $initial_rt);
+echo "Number of roundtrips made with prefetch count 0 for 5 rows is $cnt\n";
+
+$initial_rt = print_roundtrips($c);
+oci_set_prefetch($cur1,5);
+for ($i = 0;$i<5;$i++) {
+ var_dump(oci_fetch_row($cur1));
+}
+
+$cnt = (print_roundtrips($c) - $initial_rt );
+echo "Number of roundtrips made with prefetch count 5 for 5 rows is $cnt\n";
+
+echo "------Test 2 - Set Prefetch before PL/SQL fetch ----------\n";
+// Fetch from PHP
+$cur1 = oci_new_cursor($c);
+if (!oci_bind_by_name($s1,":cur1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql1) failed!\n");
+}
+
+echo "Fetch Row from PHP\n";
+oci_execute($s1);
+oci_execute($cur1);
+var_dump(oci_fetch_row($cur1));
+oci_set_prefetch($cur1,5);
+
+// Fetch from PL/SQL
+if (!oci_bind_by_name($s2,":curs1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+}
+oci_execute($s2);
+echo "Fetch Row from PL/SQL\n";
+var_dump($c1);
+var_dump($c2);
+
+echo "------Test 3 - Set Prefetch after PL/SQL fetch ----------\n";
+$cur1 = oci_new_cursor($c);
+// Fetch from PL/SQL
+if (!oci_bind_by_name($s2,":curs1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+}
+oci_execute($s2);
+echo "Fetch Row from PL/SQL\n";
+var_dump($c1);
+var_dump($c2);
+
+// Fetch from PHP
+echo "Fetch Row from PHP\n";
+if (!oci_bind_by_name($s1,":cur1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql1) failed!\n");
+}
+oci_set_prefetch($cur1,5);
+oci_execute($s1);
+oci_execute($cur1);
+var_dump(oci_fetch_row($cur1));
+
+echo "------Test 4- Overwrite prefetch-----------\n";
+// Fetch from PHP
+$cur1 = oci_new_cursor($c);
+if (!oci_bind_by_name($s1,":cur1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql1) failed!\n");
+}
+echo "Fetch Row from PHP\n";
+oci_execute($s1);
+oci_execute($cur1);
+var_dump(oci_fetch_row($cur1));
+oci_set_prefetch($cur1,5);
+oci_set_prefetch($cur1,0);
+oci_set_prefetch($cur1,100);
+
+// Fetch from PL/SQL
+if (!oci_bind_by_name($s2,":curs1",$cur1,-1,SQLT_RSET)) {
+ die("oci_bind_by_name(sql2) failed!\n");
+}
+oci_execute($s2);
+echo "Fetch Row from PL/SQL\n";
+var_dump($c1);
+var_dump($c2);
+
+
+function print_roundtrips($c) {
+ $sql_stmt = "select value from v\$mystat a,v\$statname c where
+ a.statistic#=c.statistic# and c.name='SQL*Net roundtrips to/from client'";
+ $s = oci_parse($c,$sql_stmt);
+ oci_define_by_name($s,"VALUE",$value);
+ oci_execute($s);
+ oci_fetch($s);
+ return $value;
+}
+
+// Clean up here
+
+$stmtarray = array(
+ "drop package refcurpkg",
+ "drop table refcurtest"
+);
+
+foreach($stmtarray as $stmt) {
+ $s = oci_parse($c,$stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $msg = oci_error($s);
+ echo $msg['message'],"\n";
+ }
+}
+
+oci_close($c);
+echo "Done\n";
+?>
+--EXPECTF--
+------Test 1- Check Roundtrips with prefetch 0 and 5 -----------
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "1"
+ [1]=>
+ %unicode|string%(%d) "test1"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "2"
+ [1]=>
+ %unicode|string%(%d) "test2"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "3"
+ [1]=>
+ %unicode|string%(%d) "test3"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "4"
+ [1]=>
+ %unicode|string%(%d) "test4"
+}
+Number of roundtrips made with prefetch count 0 for 5 rows is 6
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "5"
+ [1]=>
+ %unicode|string%(%d) "test5"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "6"
+ [1]=>
+ %unicode|string%(%d) "test6"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "7"
+ [1]=>
+ %unicode|string%(%d) "test7"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "8"
+ [1]=>
+ %unicode|string%(%d) "test8"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "9"
+ [1]=>
+ %unicode|string%(%d) "test9"
+}
+Number of roundtrips made with prefetch count 5 for 5 rows is 2
+------Test 2 - Set Prefetch before PL/SQL fetch ----------
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row from PL/SQL
+%unicode|string%(%d) "101"
+%unicode|string%(%d) "test101"
+------Test 3 - Set Prefetch after PL/SQL fetch ----------
+
+Warning: oci_execute(): ORA-01001: %s
+ORA-06512: at "SYSTEM.REFCURPKG", line %d
+ORA-06512: at line %d in %s on line %d
+Fetch Row from PL/SQL
+%unicode|string%(%d) "101"
+%unicode|string%(%d) "test101"
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+------Test 4- Overwrite prefetch-----------
+Fetch Row from PHP
+array(2) {
+ [0]=>
+ %unicode|string%(%d) "0"
+ [1]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row from PL/SQL
+%unicode|string%(%d) "101"
+%unicode|string%(%d) "test101"
+Done
diff --git a/tests/refcur_prefetch_3.phpt b/tests/refcur_prefetch_3.phpt
new file mode 100644
index 0000000000..0666a96e90
--- /dev/null
+++ b/tests/refcur_prefetch_3.phpt
@@ -0,0 +1,161 @@
+--TEST--
+Prefetch with Nested cursors with INI setting.
+--INI--
+oci8.default_prefetch=5
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension");
+if (!extension_loaded('oci8')) die("skip no oci8 extension");
+require(dirname(__FILE__)."/connect.inc");
+ob_start();
+phpinfo(INFO_MODULES);
+$phpinfo = ob_get_clean();
+$iv = preg_match('/Oracle .*Version => (11\.2|12\.)/', $phpinfo);
+if ($iv == 1) {
+ $sv = oci_server_version($c);
+ $sv = preg_match('/Release (11\.2|12\.)/', $sv, $matches);
+ if ($sv != 1) {
+ die ("skip expected output only valid when using Oracle 11.2 or greater server");
+ }
+}
+else {
+ die ("skip expected output only valid when using Oracle 11.2 or greater client");
+}
+
+?>
+--FILE--
+<?php
+require dirname(__FILE__)."/connect.inc";
+
+//Create tables here
+$stmtarray = array(
+ "drop table nescurtest",
+ "create table nescurtest(c1 varchar2(10))"
+);
+
+foreach($stmtarray as $stmt) {
+ $s = oci_parse($c,$stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $msg = oci_error($s);
+ if ($msg['code'] !=942) {
+ echo $msg['message'],"\n";
+ }
+ }
+}
+// Insert 500 rows into the table.
+$insert_sql = "INSERT INTO nescurtest (c1) VALUES (:c1)";
+if (!($s = oci_parse($c, $insert_sql))) {
+ die("oci_parse(insert) failed!\n");
+}
+
+for ($i = 0; $i<=500; $i++) {
+ $val2 = 'test'.$i;
+ oci_bind_by_name($s,':c1',$val2);
+ if (!oci_execute($s)) {
+ die("oci_execute(insert) failed!\n");
+ }
+}
+
+echo"-----------------------------------------------\n";
+echo "Test with Nested Cursors\n";
+echo"-----------------------------------------------\n";
+$cur1 = oci_new_cursor($c);
+$sqlstmt = "select cursor(select * from nescurtest) curs1 from dual";
+$s = oci_parse($c,$sqlstmt);
+oci_execute($s);
+$data = oci_fetch_array($s);
+oci_execute($data['CURS1']);
+
+// Calculate round-trips
+$initial_rt = print_roundtrips($c);
+for ($i = 0;$i<10;$i++) {
+ echo "Fetch Row using Nested cursor Query\n";
+ var_dump(oci_fetch_row($data['CURS1']));
+}
+
+$cnt = (print_roundtrips($c) - $initial_rt);
+echo "Number of roundtrips made with prefetch count 5 for 10 rows is $cnt\n";
+
+function print_roundtrips($c) {
+ $sql_stmt = "select value from v\$mystat a,v\$statname c where
+ a.statistic#=c.statistic# and c.name='SQL*Net roundtrips to/from client'";
+ $s = oci_parse($c,$sql_stmt);
+ oci_define_by_name($s,"VALUE",$value);
+ oci_execute($s);
+ oci_fetch($s);
+ return $value;
+}
+
+// Clean up here
+
+$stmtarray = array(
+ "drop table nescurtest"
+);
+
+foreach($stmtarray as $stmt) {
+ $s = oci_parse($c,$stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $msg = oci_error($s);
+ echo $msg['message'],"\n";
+ }
+}
+oci_close($c);
+echo "Done\n";
+?>
+--EXPECTF--
+-----------------------------------------------
+Test with Nested Cursors
+-----------------------------------------------
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test0"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test1"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test2"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test3"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test4"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test5"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test6"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test7"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test8"
+}
+Fetch Row using Nested cursor Query
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "test9"
+}
+Number of roundtrips made with prefetch count 5 for 10 rows is 3
+Done
diff --git a/tests/reflection1.phpt b/tests/reflection1.phpt
new file mode 100644
index 0000000000..5f2e73d80b
--- /dev/null
+++ b/tests/reflection1.phpt
@@ -0,0 +1,1096 @@
+--TEST--
+Test OCI8 Reflection
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+/* ALL PHP_FE or PHP_ALIAS user callable functions should appear here */
+
+reflection::export(new reflectionfunction('oci_define_by_name'));
+reflection::export(new reflectionfunction('oci_bind_by_name'));
+reflection::export(new reflectionfunction('oci_bind_array_by_name'));
+reflection::export(new reflectionfunction('oci_field_is_null'));
+reflection::export(new reflectionfunction('oci_field_name'));
+reflection::export(new reflectionfunction('oci_field_size'));
+reflection::export(new reflectionfunction('oci_field_scale'));
+reflection::export(new reflectionfunction('oci_field_precision'));
+reflection::export(new reflectionfunction('oci_field_type'));
+reflection::export(new reflectionfunction('oci_field_type_raw'));
+reflection::export(new reflectionfunction('oci_execute'));
+reflection::export(new reflectionfunction('oci_cancel'));
+reflection::export(new reflectionfunction('oci_fetch'));
+reflection::export(new reflectionfunction('oci_fetch_object'));
+reflection::export(new reflectionfunction('oci_fetch_row'));
+reflection::export(new reflectionfunction('oci_fetch_assoc'));
+reflection::export(new reflectionfunction('oci_fetch_array'));
+reflection::export(new reflectionfunction('ocifetchinto'));
+reflection::export(new reflectionfunction('oci_fetch_all'));
+reflection::export(new reflectionfunction('oci_free_statement'));
+reflection::export(new reflectionfunction('oci_internal_debug'));
+reflection::export(new reflectionfunction('oci_num_fields'));
+reflection::export(new reflectionfunction('oci_parse'));
+reflection::export(new reflectionfunction('oci_new_cursor'));
+reflection::export(new reflectionfunction('oci_result'));
+reflection::export(new reflectionfunction('oci_server_version'));
+reflection::export(new reflectionfunction('oci_statement_type'));
+reflection::export(new reflectionfunction('oci_num_rows'));
+reflection::export(new reflectionfunction('oci_close'));
+reflection::export(new reflectionfunction('oci_connect'));
+reflection::export(new reflectionfunction('oci_new_connect'));
+reflection::export(new reflectionfunction('oci_pconnect'));
+reflection::export(new reflectionfunction('oci_error'));
+reflection::export(new reflectionfunction('oci_free_descriptor'));
+reflection::export(new reflectionfunction('oci_lob_save'));
+reflection::export(new reflectionfunction('oci_lob_import'));
+reflection::export(new reflectionfunction('oci_lob_size'));
+reflection::export(new reflectionfunction('oci_lob_load'));
+reflection::export(new reflectionfunction('oci_lob_read'));
+reflection::export(new reflectionfunction('oci_lob_eof'));
+reflection::export(new reflectionfunction('oci_lob_tell'));
+reflection::export(new reflectionfunction('oci_lob_truncate'));
+reflection::export(new reflectionfunction('oci_lob_erase'));
+reflection::export(new reflectionfunction('oci_lob_flush'));
+reflection::export(new reflectionfunction('ocisetbufferinglob'));
+reflection::export(new reflectionfunction('ocigetbufferinglob'));
+reflection::export(new reflectionfunction('oci_lob_is_equal'));
+reflection::export(new reflectionfunction('oci_lob_rewind'));
+reflection::export(new reflectionfunction('oci_lob_write'));
+reflection::export(new reflectionfunction('oci_lob_append'));
+reflection::export(new reflectionfunction('oci_lob_copy'));
+reflection::export(new reflectionfunction('oci_lob_export'));
+reflection::export(new reflectionfunction('oci_lob_seek'));
+reflection::export(new reflectionfunction('oci_commit'));
+reflection::export(new reflectionfunction('oci_rollback'));
+reflection::export(new reflectionfunction('oci_new_descriptor'));
+reflection::export(new reflectionfunction('oci_set_prefetch'));
+reflection::export(new reflectionfunction('oci_password_change'));
+reflection::export(new reflectionfunction('oci_free_collection'));
+reflection::export(new reflectionfunction('oci_collection_append'));
+reflection::export(new reflectionfunction('oci_collection_element_get'));
+reflection::export(new reflectionfunction('oci_collection_element_assign'));
+reflection::export(new reflectionfunction('oci_collection_assign'));
+reflection::export(new reflectionfunction('oci_collection_size'));
+reflection::export(new reflectionfunction('oci_collection_max'));
+reflection::export(new reflectionfunction('oci_collection_trim'));
+reflection::export(new reflectionfunction('oci_new_collection'));
+reflection::export(new reflectionfunction('oci_free_cursor'));
+reflection::export(new reflectionfunction('ocifreecursor'));
+reflection::export(new reflectionfunction('ocibindbyname'));
+reflection::export(new reflectionfunction('ocidefinebyname'));
+reflection::export(new reflectionfunction('ocicolumnisnull'));
+reflection::export(new reflectionfunction('ocicolumnname'));
+reflection::export(new reflectionfunction('ocicolumnsize'));
+reflection::export(new reflectionfunction('ocicolumnscale'));
+reflection::export(new reflectionfunction('ocicolumnprecision'));
+reflection::export(new reflectionfunction('ocicolumntype'));
+reflection::export(new reflectionfunction('ocicolumntyperaw'));
+reflection::export(new reflectionfunction('ociexecute'));
+reflection::export(new reflectionfunction('ocicancel'));
+reflection::export(new reflectionfunction('ocifetch'));
+reflection::export(new reflectionfunction('ocifetchstatement'));
+reflection::export(new reflectionfunction('ocifreestatement'));
+reflection::export(new reflectionfunction('ociinternaldebug'));
+reflection::export(new reflectionfunction('ocinumcols'));
+reflection::export(new reflectionfunction('ociparse'));
+reflection::export(new reflectionfunction('ocinewcursor'));
+reflection::export(new reflectionfunction('ociresult'));
+reflection::export(new reflectionfunction('ociserverversion'));
+reflection::export(new reflectionfunction('ocistatementtype'));
+reflection::export(new reflectionfunction('ocirowcount'));
+reflection::export(new reflectionfunction('ocilogoff'));
+reflection::export(new reflectionfunction('ocilogon'));
+reflection::export(new reflectionfunction('ocinlogon'));
+reflection::export(new reflectionfunction('ociplogon'));
+reflection::export(new reflectionfunction('ocierror'));
+reflection::export(new reflectionfunction('ocifreedesc'));
+reflection::export(new reflectionfunction('ocisavelob'));
+reflection::export(new reflectionfunction('ocisavelobfile'));
+reflection::export(new reflectionfunction('ociwritelobtofile'));
+reflection::export(new reflectionfunction('ociloadlob'));
+reflection::export(new reflectionfunction('ocicommit'));
+reflection::export(new reflectionfunction('ocirollback'));
+reflection::export(new reflectionfunction('ocinewdescriptor'));
+reflection::export(new reflectionfunction('ocisetprefetch'));
+reflection::export(new reflectionfunction('ocipasswordchange'));
+reflection::export(new reflectionfunction('ocifreecollection'));
+reflection::export(new reflectionfunction('ocinewcollection'));
+reflection::export(new reflectionfunction('ocicollappend'));
+reflection::export(new reflectionfunction('ocicollgetelem'));
+reflection::export(new reflectionfunction('ocicollassignelem'));
+reflection::export(new reflectionfunction('ocicollsize'));
+reflection::export(new reflectionfunction('ocicollmax'));
+reflection::export(new reflectionfunction('ocicolltrim'));
+reflection::export(new reflectionfunction('oci_set_edition'));
+reflection::export(new reflectionfunction('oci_set_module_name'));
+reflection::export(new reflectionfunction('oci_set_action'));
+reflection::export(new reflectionfunction('oci_set_client_info'));
+reflection::export(new reflectionfunction('oci_set_client_identifier'));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Function [ <internal%s> function oci_define_by_name ] {
+
+ - Parameters [4] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_name ]
+ Parameter #2 [ <required> &$variable ]
+ Parameter #3 [ <optional> $type ]
+ }
+}
+
+Function [ <internal%s> function oci_bind_by_name ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_name ]
+ Parameter #2 [ <required> &$variable ]
+ Parameter #3 [ <optional> $maximum_length ]
+ Parameter #4 [ <optional> $type ]
+ }
+}
+
+Function [ <internal%s> function oci_bind_array_by_name ] {
+
+ - Parameters [6] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_name ]
+ Parameter #2 [ <required> &$variable ]
+ Parameter #3 [ <required> $maximum_array_length ]
+ Parameter #4 [ <optional> $maximum_item_length ]
+ Parameter #5 [ <optional> $type ]
+ }
+}
+
+Function [ <internal%s> function oci_field_is_null ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number_or_name ]
+ }
+}
+
+Function [ <internal%s> function oci_field_name ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function oci_field_size ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number_or_name ]
+ }
+}
+
+Function [ <internal%s> function oci_field_scale ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function oci_field_precision ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function oci_field_type ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function oci_field_type_raw ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function oci_execute ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <optional> $mode ]
+ }
+}
+
+Function [ <internal%s> function oci_cancel ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_fetch ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_fetch_object ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_fetch_row ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_fetch_assoc ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_fetch_array ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <optional> $mode ]
+ }
+}
+
+Function [ <internal%s> function ocifetchinto ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> &$result ]
+ Parameter #2 [ <optional> $mode ]
+ }
+}
+
+Function [ <internal%s> function oci_fetch_all ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> &$output ]
+ Parameter #2 [ <optional> $skip ]
+ Parameter #3 [ <optional> $maximum_rows ]
+ Parameter #4 [ <optional> $flags ]
+ }
+}
+
+Function [ <internal%s> function oci_free_statement ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_internal_debug ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $mode ]
+ }
+}
+
+Function [ <internal%s> function oci_num_fields ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_parse ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <required> $sql_text ]
+ }
+}
+
+Function [ <internal%s> function oci_new_cursor ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_result ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number_or_name ]
+ }
+}
+
+Function [ <internal%s> function oci_server_version ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_statement_type ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_num_rows ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_close ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_connect ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $username ]
+ Parameter #1 [ <required> $password ]
+ Parameter #2 [ <optional> $connection_string ]
+ Parameter #3 [ <optional> $character_set ]
+ Parameter #4 [ <optional> $session_mode ]
+ }
+}
+
+Function [ <internal%s> function oci_new_connect ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $username ]
+ Parameter #1 [ <required> $password ]
+ Parameter #2 [ <optional> $connection_string ]
+ Parameter #3 [ <optional> $character_set ]
+ Parameter #4 [ <optional> $session_mode ]
+ }
+}
+
+Function [ <internal%s> function oci_pconnect ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $username ]
+ Parameter #1 [ <required> $password ]
+ Parameter #2 [ <optional> $connection_string ]
+ Parameter #3 [ <optional> $character_set ]
+ Parameter #4 [ <optional> $session_mode ]
+ }
+}
+
+Function [ <internal%s> function oci_error ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <optional> $connection_or_statement_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_free_descriptor ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_save ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $data ]
+ Parameter #2 [ <optional> $offset ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_import ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $filename ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_size ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_load ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_read ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $length ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_eof ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_tell ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_truncate ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <optional> $length ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_erase ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <optional> $offset ]
+ Parameter #2 [ <optional> $length ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_flush ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <optional> $flag ]
+ }
+}
+
+Function [ <internal%s> function ocisetbufferinglob ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $mode ]
+ }
+}
+
+Function [ <internal%s> function ocigetbufferinglob ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_is_equal ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_rewind ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_write ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $string ]
+ Parameter #2 [ <optional> $length ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_append ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $lob_descriptor_to ]
+ Parameter #1 [ <required> $lob_descriptor_from ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_copy ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $lob_descriptor_to ]
+ Parameter #1 [ <required> $lob_descriptor_from ]
+ Parameter #2 [ <optional> $length ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_export ] {
+
+ - Parameters [4] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $filename ]
+ Parameter #2 [ <optional> $start ]
+ Parameter #3 [ <optional> $length ]
+ }
+}
+
+Function [ <internal%s> function oci_lob_seek ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $offset ]
+ Parameter #2 [ <optional> $whence ]
+ }
+}
+
+Function [ <internal%s> function oci_commit ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_rollback ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function oci_new_descriptor ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <optional> $type ]
+ }
+}
+
+Function [ <internal%s> function oci_set_prefetch ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $number_of_rows ]
+ }
+}
+
+Function [ <internal%s> function oci_password_change ] {
+
+ - Parameters [4] {
+ Parameter #0 [ <required> $connection_resource_or_connection_string ]
+ Parameter #1 [ <required> $username ]
+ Parameter #2 [ <required> $old_password ]
+ Parameter #3 [ <required> $new_password ]
+ }
+}
+
+Function [ <internal%s> function oci_free_collection ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $collection ]
+ }
+}
+
+Function [ <internal%s> function oci_collection_append ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $collection ]
+ Parameter #1 [ <required> $value ]
+ }
+}
+
+Function [ <internal%s> function oci_collection_element_get ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $collection ]
+ Parameter #1 [ <required> $index ]
+ }
+}
+
+Function [ <internal%s> function oci_collection_element_assign ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $collection ]
+ Parameter #1 [ <required> $index ]
+ Parameter #2 [ <required> $value ]
+ }
+}
+
+Function [ <internal%s> function oci_collection_assign ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $collection_to ]
+ Parameter #1 [ <required> $collection_from ]
+ }
+}
+
+Function [ <internal%s> function oci_collection_size ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $collection ]
+ }
+}
+
+Function [ <internal%s> function oci_collection_max ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $collection ]
+ }
+}
+
+Function [ <internal%s> function oci_collection_trim ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $collection ]
+ Parameter #1 [ <required> $number ]
+ }
+}
+
+Function [ <internal%s> function oci_new_collection ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <required> $type_name ]
+ Parameter #2 [ <optional> $schema_name ]
+ }
+}
+
+Function [ <internal%s> function oci_free_cursor ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ocifreecursor ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ocibindbyname ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_name ]
+ Parameter #2 [ <required> &$variable ]
+ Parameter #3 [ <optional> $maximum_length ]
+ Parameter #4 [ <optional> $type ]
+ }
+}
+
+Function [ <internal%s> function ocidefinebyname ] {
+
+ - Parameters [4] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_name ]
+ Parameter #2 [ <required> &$variable ]
+ Parameter #3 [ <optional> $type ]
+ }
+}
+
+Function [ <internal%s> function ocicolumnisnull ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number_or_name ]
+ }
+}
+
+Function [ <internal%s> function ocicolumnname ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function ocicolumnsize ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number_or_name ]
+ }
+}
+
+Function [ <internal%s> function ocicolumnscale ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function ocicolumnprecision ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function ocicolumntype ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function ocicolumntyperaw ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number ]
+ }
+}
+
+Function [ <internal%s> function ociexecute ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <optional> $mode ]
+ }
+}
+
+Function [ <internal%s> function ocicancel ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ocifetch ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ocifetchstatement ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> &$output ]
+ Parameter #2 [ <optional> $skip ]
+ Parameter #3 [ <optional> $maximum_rows ]
+ Parameter #4 [ <optional> $flags ]
+ }
+}
+
+Function [ <internal%s> function ocifreestatement ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ociinternaldebug ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $mode ]
+ }
+}
+
+Function [ <internal%s> function ocinumcols ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ociparse ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <required> $sql_text ]
+ }
+}
+
+Function [ <internal%s> function ocinewcursor ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function ociresult ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $column_number_or_name ]
+ }
+}
+
+Function [ <internal%s> function ociserverversion ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function ocistatementtype ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ocirowcount ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ocilogoff ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function ocilogon ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $username ]
+ Parameter #1 [ <required> $password ]
+ Parameter #2 [ <optional> $connection_string ]
+ Parameter #3 [ <optional> $character_set ]
+ Parameter #4 [ <optional> $session_mode ]
+ }
+}
+
+Function [ <internal%s> function ocinlogon ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $username ]
+ Parameter #1 [ <required> $password ]
+ Parameter #2 [ <optional> $connection_string ]
+ Parameter #3 [ <optional> $character_set ]
+ Parameter #4 [ <optional> $session_mode ]
+ }
+}
+
+Function [ <internal%s> function ociplogon ] {
+
+ - Parameters [5] {
+ Parameter #0 [ <required> $username ]
+ Parameter #1 [ <required> $password ]
+ Parameter #2 [ <optional> $connection_string ]
+ Parameter #3 [ <optional> $character_set ]
+ Parameter #4 [ <optional> $session_mode ]
+ }
+}
+
+Function [ <internal%s> function ocierror ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <optional> $connection_or_statement_resource ]
+ }
+}
+
+Function [ <internal%s> function ocifreedesc ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function ocisavelob ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $data ]
+ Parameter #2 [ <optional> $offset ]
+ }
+}
+
+Function [ <internal%s> function ocisavelobfile ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $filename ]
+ }
+}
+
+Function [ <internal%s> function ociwritelobtofile ] {
+
+ - Parameters [4] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ Parameter #1 [ <required> $filename ]
+ Parameter #2 [ <optional> $start ]
+ Parameter #3 [ <optional> $length ]
+ }
+}
+
+Function [ <internal%s> function ociloadlob ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor ]
+ }
+}
+
+Function [ <internal%s> function ocicommit ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function ocirollback ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $connection_resource ]
+ }
+}
+
+Function [ <internal%s> function ocinewdescriptor ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <optional> $type ]
+ }
+}
+
+Function [ <internal%s> function ocisetprefetch ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $statement_resource ]
+ Parameter #1 [ <required> $number_of_rows ]
+ }
+}
+
+Function [ <internal%s> function ocipasswordchange ] {
+
+ - Parameters [4] {
+ Parameter #0 [ <required> $connection_resource_or_connection_string ]
+ Parameter #1 [ <required> $username ]
+ Parameter #2 [ <required> $old_password ]
+ Parameter #3 [ <required> $new_password ]
+ }
+}
+
+Function [ <internal%s> function ocifreecollection ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $collection ]
+ }
+}
+
+Function [ <internal%s> function ocinewcollection ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <required> $type_name ]
+ Parameter #2 [ <optional> $schema_name ]
+ }
+}
+
+Function [ <internal%s> function ocicollappend ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $collection ]
+ Parameter #1 [ <required> $value ]
+ }
+}
+
+Function [ <internal%s> function ocicollgetelem ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $collection ]
+ Parameter #1 [ <required> $index ]
+ }
+}
+
+Function [ <internal%s> function ocicollassignelem ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $collection ]
+ Parameter #1 [ <required> $index ]
+ Parameter #2 [ <required> $value ]
+ }
+}
+
+Function [ <internal%s> function ocicollsize ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $collection ]
+ }
+}
+
+Function [ <internal%s> function ocicollmax ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $collection ]
+ }
+}
+
+Function [ <internal%s> function ocicolltrim ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $collection ]
+ Parameter #1 [ <required> $number ]
+ }
+}
+
+Function [ <internal%s> function oci_set_edition ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $edition_name ]
+ }
+}
+
+Function [ <internal%s> function oci_set_module_name ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <required> $module_name ]
+ }
+}
+
+Function [ <internal%s> function oci_set_action ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <required> $action ]
+ }
+}
+
+Function [ <internal%s> function oci_set_client_info ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <required> $client_information ]
+ }
+}
+
+Function [ <internal%s> function oci_set_client_identifier ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $connection_resource ]
+ Parameter #1 [ <required> $client_identifier ]
+ }
+}
+
+===DONE===
diff --git a/tests/reflection2.phpt b/tests/reflection2.phpt
new file mode 100644
index 0000000000..9e63db1d63
--- /dev/null
+++ b/tests/reflection2.phpt
@@ -0,0 +1,258 @@
+--TEST--
+Test OCI8 LOB & Collection Class Reflection
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+reflection::export(new reflectionclass('OCI-Lob'));
+reflection::export(new reflectionclass('OCI-Collection'));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Class [ <internal:oci8> class OCI-Lob ] {
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [22] {
+ Method [ <internal%s> public method load ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method tell ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method truncate ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <optional> $length ]
+ }
+ }
+
+ Method [ <internal%s> public method erase ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <optional> $offset ]
+ Parameter #1 [ <optional> $length ]
+ }
+ }
+
+ Method [ <internal%s> public method flush ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <optional> $flag ]
+ }
+ }
+
+ Method [ <internal%s> public method setbuffering ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $mode ]
+ }
+ }
+
+ Method [ <internal%s> public method getbuffering ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method rewind ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method read ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $length ]
+ }
+ }
+
+ Method [ <internal%s> public method eof ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method seek ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $offset ]
+ Parameter #1 [ <optional> $whence ]
+ }
+ }
+
+ Method [ <internal%s> public method write ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $string ]
+ Parameter #1 [ <optional> $length ]
+ }
+ }
+
+ Method [ <internal%s> public method append ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $lob_descriptor_from ]
+ }
+ }
+
+ Method [ <internal%s> public method size ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method writetofile ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $filename ]
+ Parameter #1 [ <optional> $start ]
+ Parameter #2 [ <optional> $length ]
+ }
+ }
+
+ Method [ <internal%s> public method export ] {
+
+ - Parameters [3] {
+ Parameter #0 [ <required> $filename ]
+ Parameter #1 [ <optional> $start ]
+ Parameter #2 [ <optional> $length ]
+ }
+ }
+
+ Method [ <internal%s> public method import ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $filename ]
+ }
+ }
+
+ Method [ <internal%s> public method writetemporary ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $data ]
+ Parameter #1 [ <optional> $type ]
+ }
+ }
+
+ Method [ <internal%s> public method close ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method save ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $data ]
+ Parameter #1 [ <optional> $offset ]
+ }
+ }
+
+ Method [ <internal%s> public method savefile ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $filename ]
+ }
+ }
+
+ Method [ <internal%s> public method free ] {
+
+ - Parameters [0] {
+ }
+ }
+ }
+}
+
+Class [ <internal%s> class OCI-Collection ] {
+
+ - Constants [0] {
+ }
+
+ - Static properties [0] {
+ }
+
+ - Static methods [0] {
+ }
+
+ - Properties [0] {
+ }
+
+ - Methods [8] {
+ Method [ <internal%s> public method append ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $value ]
+ }
+ }
+
+ Method [ <internal%s> public method getelem ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $index ]
+ }
+ }
+
+ Method [ <internal%s> public method assignelem ] {
+
+ - Parameters [2] {
+ Parameter #0 [ <required> $index ]
+ Parameter #1 [ <required> $value ]
+ }
+ }
+
+ Method [ <internal%s> public method assign ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $collection_from ]
+ }
+ }
+
+ Method [ <internal%s> public method size ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method max ] {
+
+ - Parameters [0] {
+ }
+ }
+
+ Method [ <internal%s> public method trim ] {
+
+ - Parameters [1] {
+ Parameter #0 [ <required> $number ]
+ }
+ }
+
+ Method [ <internal%s> public method free ] {
+
+ - Parameters [0] {
+ }
+ }
+ }
+}
+
+===DONE===
diff --git a/tests/select_null.phpt b/tests/select_null.phpt
new file mode 100644
index 0000000000..87c5b815fd
--- /dev/null
+++ b/tests/select_null.phpt
@@ -0,0 +1,25 @@
+--TEST--
+SELECTing NULL values
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$pc = oci_pconnect($user, $password, $dbase);
+
+$stmt = oci_parse($pc, "select NULL from dual");
+oci_execute($stmt);
+var_dump(oci_fetch_array($stmt, OCI_RETURN_NULLS));
+
+echo "Done\n";
+?>
+--EXPECT--
+array(2) {
+ [0]=>
+ NULL
+ ["NULL"]=>
+ NULL
+}
+Done
diff --git a/tests/serverversion.phpt b/tests/serverversion.phpt
new file mode 100644
index 0000000000..bf32fe4b54
--- /dev/null
+++ b/tests/serverversion.phpt
@@ -0,0 +1,30 @@
+--TEST--
+oci_server_version()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+if (!empty($dbase)) {
+ var_dump($c = oci_connect($user, $password, $dbase));
+}
+else {
+ var_dump($c = oci_connect($user, $password));
+}
+
+$v = oci_server_version($c);
+var_dump(str_replace("\n", "", $v));
+
+$v = ociserverversion($c);
+var_dump(str_replace("\n", "", $v));
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+string(%d) "%s"
+string(%d) "%s"
+Done
diff --git a/tests/skipif.inc b/tests/skipif.inc
new file mode 100644
index 0000000000..ed0992c8d9
--- /dev/null
+++ b/tests/skipif.inc
@@ -0,0 +1,10 @@
+<?php
+
+if (!extension_loaded('oci8')) die("skip oci8 extension is not available\n");
+
+/*
+ * Remove or comment this line to run tests
+ *
+ * */
+die("skip change default login/password\n");
+?>
diff --git a/tests/statement_cache.phpt b/tests/statement_cache.phpt
new file mode 100644
index 0000000000..19e69d4c21
--- /dev/null
+++ b/tests/statement_cache.phpt
@@ -0,0 +1,35 @@
+--TEST--
+statement cache
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$pc = oci_pconnect($user, $password, $dbase);
+
+$stmt = oci_parse($pc, "select 1+3 from dual");
+oci_execute($stmt);
+var_dump(oci_fetch_array($stmt));
+
+$stmt = oci_parse($pc, "select 1+3 from dual");
+oci_execute($stmt);
+var_dump(oci_fetch_array($stmt));
+
+echo "Done\n";
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ string(1) "4"
+ ["1+3"]=>
+ string(1) "4"
+}
+array(2) {
+ [0]=>
+ string(1) "4"
+ ["1+3"]=>
+ string(1) "4"
+}
+Done
diff --git a/tests/statement_type.phpt b/tests/statement_type.phpt
new file mode 100644
index 0000000000..29cdd94402
--- /dev/null
+++ b/tests/statement_type.phpt
@@ -0,0 +1,48 @@
+--TEST--
+oci_statement_type()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$sqls = Array(
+ "SELECT * FROM table",
+ "DELETE FROM table WHERE id = 1",
+ "INSERT INTO table VALUES(1)",
+ "UPDATE table SET id = 1",
+ "DROP TABLE table",
+ "CREATE OR REPLACE PROCEDURE myproc(v1 NUMBER) as BEGIN DBMS_OUTPUT.PUT_LINE(v1); END;",
+ "CREATE TABLE table (id NUMBER)",
+ "ALTER TABLE table ADD (col1 NUMBER)",
+ "BEGIN NULL; END;",
+ "DECLARE myn NUMBER BEGIN myn := 1; END;",
+ "CALL myproc(1)",
+ "WRONG SYNTAX",
+ ""
+);
+
+foreach ($sqls as $sql) {
+ $s = oci_parse($c, $sql);
+ var_dump(oci_statement_type($s));
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+string(6) "SELECT"
+string(6) "DELETE"
+string(6) "INSERT"
+string(6) "UPDATE"
+string(4) "DROP"
+string(6) "CREATE"
+string(6) "CREATE"
+string(5) "ALTER"
+string(5) "BEGIN"
+string(7) "DECLARE"
+string(4) "CALL"
+string(7) "UNKNOWN"
+string(7) "UNKNOWN"
+Done
diff --git a/tests/statement_type_old.phpt b/tests/statement_type_old.phpt
new file mode 100644
index 0000000000..2626d6203c
--- /dev/null
+++ b/tests/statement_type_old.phpt
@@ -0,0 +1,56 @@
+--TEST--
+ocistatementtype()
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+if (!empty($dbase)) {
+ var_dump($c = ocilogon($user, $password, $dbase));
+}
+else {
+ var_dump($c = ocilogon($user, $password));
+}
+
+$sqls = Array(
+ "SELECT * FROM table",
+ "DELETE FROM table WHERE id = 1",
+ "INSERT INTO table VALUES(1)",
+ "UPDATE table SET id = 1",
+ "DROP TABLE table",
+ "CREATE OR REPLACE PROCEDURE myproc(v1 NUMBER) as BEGIN DBMS_OUTPUT.PUT_LINE(v1); END;",
+ "CREATE TABLE table (id NUMBER)",
+ "ALTER TABLE table ADD (col1 NUMBER)",
+ "BEGIN NULL; END;",
+ "DECLARE myn NUMBER BEGIN myn := 1; END;",
+ "CALL myproc(1)",
+ "WRONG SYNTAX",
+ ""
+);
+
+foreach ($sqls as $sql) {
+ $s = ociparse($c, $sql);
+ var_dump(ocistatementtype($s));
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+resource(%d) of type (oci8 connection)
+string(6) "SELECT"
+string(6) "DELETE"
+string(6) "INSERT"
+string(6) "UPDATE"
+string(4) "DROP"
+string(6) "CREATE"
+string(6) "CREATE"
+string(5) "ALTER"
+string(5) "BEGIN"
+string(7) "DECLARE"
+string(4) "CALL"
+string(7) "UNKNOWN"
+string(7) "UNKNOWN"
+Done
diff --git a/tests/test.gif b/tests/test.gif
new file mode 100644
index 0000000000..f352c7308f
--- /dev/null
+++ b/tests/test.gif
Binary files differ
diff --git a/tests/test.txt b/tests/test.txt
new file mode 100644
index 0000000000..4b89727035
--- /dev/null
+++ b/tests/test.txt
@@ -0,0 +1,9 @@
+Ipsum lorem, IPSUM Lorem Ipsum lorem Ipsum lorem
+Ipsum lorem IPSum Lorem Ipsum lorem ipsum Lorem
+Ipsum Lorem ipsum Lorem - ipsum Lorem ipsum lorem
+Ipsum lorem IPSUM Lorem Ipsum lorem, Ipsum lorem.
+
+Ipsum LOREM, ipsum Lorem Ipsum lorem Ipsum lorem
+Ipsum lorem Ipsum Lorem Ipsum lorem ipsum Lorem
+Ipsum Lorem ipsum Lorem ipsum Lorem; ipsum lorem
+Ipsum lorem ipsum LOREM Ipsum lorem Ipsum lorem!
diff --git a/tests/testping.phpt b/tests/testping.phpt
new file mode 100644
index 0000000000..a0d65a30c3
--- /dev/null
+++ b/tests/testping.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Exercise OCIPing functionality on reconnect (code coverage test)
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--INI--
+oci8.ping_interval=0
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/details.inc');
+
+for ($i = 0; $i < 2; $i++) {
+ if (!empty($dbase)) {
+ $c = oci_pconnect($user,$password,$dbase);
+ }
+ else {
+ $c = oci_pconnect($user,$password);
+ }
+}
+
+echo "Done\n";
+
+?>
+--EXPECTF--
+Done
diff --git a/tests/uncommitted.phpt b/tests/uncommitted.phpt
new file mode 100644
index 0000000000..3c341c8cb4
--- /dev/null
+++ b/tests/uncommitted.phpt
@@ -0,0 +1,16 @@
+--TEST--
+uncommitted connection
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require dirname(__FILE__)."/connect.inc";
+
+$stmt = oci_parse($c, "select 1 from dual");
+oci_execute($stmt, OCI_DEFAULT);
+
+echo "Done\n";
+?>
+--EXPECTF--
+Done
diff --git a/tests/xmltype_01.phpt b/tests/xmltype_01.phpt
new file mode 100644
index 0000000000..a9458c83d4
--- /dev/null
+++ b/tests/xmltype_01.phpt
@@ -0,0 +1,121 @@
+--TEST--
+Basic XMLType test
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die("skip no oci8 extension"); ?>
+<?php if (!extension_loaded("simplexml")) die("skip no simplexml extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__)."/connect.inc");
+
+// Initialization
+
+$stmts = array(
+ "drop table xtt",
+ "create table xtt
+ (xt_id number, xt_spec xmltype)
+ xmltype xt_spec store as clob",
+ "insert into xtt (xt_id, xt_spec) values
+ (1,
+ xmltype('<?xml version=\"1.0\"?>
+ <Xt>
+ <XtId>1</XtId>
+ <Size>Big</Size>
+ <Area>12345</Area>
+ <Hardness>20</Hardness>
+ <Lip>Curved</Lip>
+ <Color>Red</Color>
+ <Nice>N</Nice>
+ <Compact>Tiny</Compact>
+ <Material>Steel</Material>
+ </Xt>'))"
+);
+
+foreach ($stmts as $q) {
+ $s = oci_parse($c, $q);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if ($m['code'] != 942) { // table or view doesn't exist
+ echo $m['message'], "\n";
+ }
+ }
+}
+
+function do_query($c)
+{
+ $s = oci_parse($c, 'select XMLType.getClobVal(xt_spec)
+ from xtt where xt_id = 1');
+ oci_execute($s);
+ $row = oci_fetch_row($s);
+ $data = $row[0]->load();
+ var_dump($data);
+ return($data);
+}
+
+// Check
+echo "Initial Data\n";
+$data = do_query($c);
+
+// Manipulate the data using SimpleXML
+$sx = simplexml_load_string($data);
+$sx->Hardness = $sx->Hardness - 1;
+$sx->Nice = 'Y';
+
+// Insert changes using a temporary CLOB
+$s = oci_parse($c, 'update xtt
+ set xt_spec = XMLType(:clob)
+ where xt_id = 1');
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':clob', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary($sx->asXml());
+oci_execute($s);
+$lob->close();
+
+// Verify
+echo "Verify\n";
+$data = do_query($c);
+
+// Cleanup
+
+$stmts = array(
+ "drop table xtt",
+);
+
+foreach ($stmts as $q) {
+ $s = oci_parse($c, $q);
+ @oci_execute($s);
+}
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Initial Data
+string(250) "<?xml version="1.0"?>
+ <Xt>
+ <XtId>1</XtId>
+ <Size>Big</Size>
+ <Area>12345</Area>
+ <Hardness>20</Hardness>
+ <Lip>Curved</Lip>
+ <Color>Red</Color>
+ <Nice>N</Nice>
+ <Compact>Tiny</Compact>
+ <Material>Steel</Material>
+ </Xt>"
+Verify
+string(249) "<?xml version="1.0"?>
+<Xt>
+ <XtId>1</XtId>
+ <Size>Big</Size>
+ <Area>12345</Area>
+ <Hardness>19</Hardness>
+ <Lip>Curved</Lip>
+ <Color>Red</Color>
+ <Nice>Y</Nice>
+ <Compact>Tiny</Compact>
+ <Material>Steel</Material>
+ </Xt>
+"
+Done
diff --git a/tests/xmltype_02.phpt b/tests/xmltype_02.phpt
new file mode 100644
index 0000000000..9b6fa8ad32
--- /dev/null
+++ b/tests/xmltype_02.phpt
@@ -0,0 +1,197 @@
+--TEST--
+Basic XMLType test #2
+--SKIPIF--
+<?php if (!extension_loaded('oci8')) die ("skip no oci8 extension"); ?>
+--FILE--
+<?php
+
+require(dirname(__FILE__).'/connect.inc');
+
+// Initialization
+
+$stmtarray = array(
+ "drop table xmltype_02_tab",
+ "create table xmltype_02_tab (warehouse_id number, warehouse_spec xmltype)",
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ $r = @oci_execute($s);
+ if (!$r) {
+ $m = oci_error($s);
+ if (!in_array($m['code'], array( // ignore expected errors
+ 942 // table or view does not exist
+ , 2289 // sequence does not exist
+ , 4080 // trigger does not exist
+ ))) {
+ echo $stmt . PHP_EOL . $m['message'] . PHP_EOL;
+ }
+ }
+}
+
+// Run Test
+
+
+$id = 1;
+
+// Delete any current entry
+$s = oci_parse($c, "delete from xmltype_02_tab where warehouse_id = :id");
+oci_bind_by_name($s, ':id', $id);
+oci_execute($s);
+
+// XML data to be inserted
+$xml =<<<EOF
+<?xml version="1.0"?>
+<Warehouse>
+<WarehouseId>1</WarehouseId>
+<WarehouseName>Southlake, Texas</WarehouseName>
+<Building>Owned</Building>
+<Area>25000</Area>
+<Docks>2</Docks>
+<DockType>Rear load</DockType>
+<WaterAccess>true</WaterAccess>
+<RailAccess>N</RailAccess>
+<Parking>Street</Parking>
+<VClearance>10</VClearance>
+</Warehouse>
+EOF;
+
+echo "Test 1 Insert new XML data using a temporary CLOB\n";
+$s = oci_parse($c,
+ "insert into xmltype_02_tab (warehouse_id, warehouse_spec)
+ values (:id, XMLType(:clob))");
+oci_bind_by_name($s, ':id', $id);
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':clob', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary($xml);
+oci_execute($s);
+$lob->close();
+
+// Query the row back
+$s = oci_parse($c, 'select xmltype.getclobval(warehouse_spec)
+ from xmltype_02_tab where warehouse_id = :id');
+$r = oci_bind_by_name($s, ':id', $id);
+oci_execute($s);
+$row = oci_fetch_array($s, OCI_NUM);
+
+var_dump($row);
+
+echo "Test 2 Manipulate the data using SimpleXML\n";
+
+$sx = simplexml_load_string((binary)$row[0]->load());
+$row[0]->free();
+var_dump($sx);
+
+$sx->Docks -= 1; // change the data
+
+var_dump($sx);
+
+echo "Test 3: Update changes using a temporary CLOB\n";
+
+$s = oci_parse($c, 'update xmltype_02_tab
+ set warehouse_spec = XMLType(:clob)
+ where warehouse_id = :id');
+oci_bind_by_name($s, ':id', $id);
+$lob = oci_new_descriptor($c, OCI_D_LOB);
+oci_bind_by_name($s, ':clob', $lob, -1, OCI_B_CLOB);
+$lob->writeTemporary($sx->asXml());
+oci_execute($s);
+$lob->close();
+
+// Query the changed row back and print it
+$s = oci_parse($c, 'select xmltype.getclobval(warehouse_spec)
+ from xmltype_02_tab where warehouse_id = :id');
+$r = oci_bind_by_name($s, ':id', $id);
+oci_execute($s);
+$row = oci_fetch_array($s, OCI_NUM);
+var_dump($row[0]->load());
+$row[0]->free();
+
+// Clean up
+
+//require(dirname(__FILE__).'/drop_table.inc');
+
+$stmtarray = array(
+ "drop table xmltype_02_tab"
+);
+
+foreach ($stmtarray as $stmt) {
+ $s = oci_parse($c, $stmt);
+ oci_execute($s);
+}
+
+oci_close($c);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Test 1 Insert new XML data using a temporary CLOB
+array(1) {
+ [0]=>
+ object(OCI-Lob)#%d (1) {
+ [%u|b%"descriptor"]=>
+ resource(%d) of type (oci8 descriptor)
+ }
+}
+Test 2 Manipulate the data using SimpleXML
+object(SimpleXMLElement)#%d (10) {
+ [%u|b%"WarehouseId"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"WarehouseName"]=>
+ %unicode|string%(16) "Southlake, Texas"
+ [%u|b%"Building"]=>
+ %unicode|string%(5) "Owned"
+ [%u|b%"Area"]=>
+ %unicode|string%(5) "25000"
+ [%u|b%"Docks"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"DockType"]=>
+ %unicode|string%(9) "Rear load"
+ [%u|b%"WaterAccess"]=>
+ %unicode|string%(4) "true"
+ [%u|b%"RailAccess"]=>
+ %unicode|string%(1) "N"
+ [%u|b%"Parking"]=>
+ %unicode|string%(6) "Street"
+ [%u|b%"VClearance"]=>
+ %unicode|string%(2) "10"
+}
+object(SimpleXMLElement)#%d (10) {
+ [%u|b%"WarehouseId"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"WarehouseName"]=>
+ %unicode|string%(16) "Southlake, Texas"
+ [%u|b%"Building"]=>
+ %unicode|string%(5) "Owned"
+ [%u|b%"Area"]=>
+ %unicode|string%(5) "25000"
+ [%u|b%"Docks"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"DockType"]=>
+ %unicode|string%(9) "Rear load"
+ [%u|b%"WaterAccess"]=>
+ %unicode|string%(4) "true"
+ [%u|b%"RailAccess"]=>
+ %unicode|string%(1) "N"
+ [%u|b%"Parking"]=>
+ %unicode|string%(6) "Street"
+ [%u|b%"VClearance"]=>
+ %unicode|string%(2) "10"
+}
+Test 3: Update changes using a temporary CLOB
+%unicode|string%(331) "<?xml version="1.0"?>
+<Warehouse>
+<WarehouseId>1</WarehouseId>
+<WarehouseName>Southlake, Texas</WarehouseName>
+<Building>Owned</Building>
+<Area>25000</Area>
+<Docks>1</Docks>
+<DockType>Rear load</DockType>
+<WaterAccess>true</WaterAccess>
+<RailAccess>N</RailAccess>
+<Parking>Street</Parking>
+<VClearance>10</VClearance>
+</Warehouse>
+"
+===DONE=== \ No newline at end of file