]> granicus.if.org Git - php/commitdiff
OCI driver for PDO, supporting bound input and output parameters.
authorWez Furlong <wez@php.net>
Mon, 17 May 2004 15:42:33 +0000 (15:42 +0000)
committerWez Furlong <wez@php.net>
Mon, 17 May 2004 15:42:33 +0000 (15:42 +0000)
Will not build under unix yet.

ext/pdo_oci/CREDITS [new file with mode: 0755]
ext/pdo_oci/EXPERIMENTAL [new file with mode: 0644]
ext/pdo_oci/config.m4 [new file with mode: 0755]
ext/pdo_oci/config.w32 [new file with mode: 0755]
ext/pdo_oci/oci_driver.c [new file with mode: 0755]
ext/pdo_oci/oci_statement.c [new file with mode: 0755]
ext/pdo_oci/pdo_oci.c [new file with mode: 0755]
ext/pdo_oci/php_pdo_oci.h [new file with mode: 0755]
ext/pdo_oci/php_pdo_oci_int.h [new file with mode: 0755]

diff --git a/ext/pdo_oci/CREDITS b/ext/pdo_oci/CREDITS
new file mode 100755 (executable)
index 0000000..63e863a
--- /dev/null
@@ -0,0 +1,2 @@
+Oracle (OCI) driver for PDO
+Wez Furlong
diff --git a/ext/pdo_oci/EXPERIMENTAL b/ext/pdo_oci/EXPERIMENTAL
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ext/pdo_oci/config.m4 b/ext/pdo_oci/config.m4
new file mode 100755 (executable)
index 0000000..df8f05d
--- /dev/null
@@ -0,0 +1,169 @@
+dnl
+dnl $Id$
+dnl
+
+dnl This file is more or less a straight copy from oci8; it won't work with pdo_oci yet!
+
+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_OCI_VERSION,[
+  AC_MSG_CHECKING([Oracle version])
+  if test -s "$OCI_DIR/orainst/unix.rgs"; then
+    OCI_VERSION=`grep '"ocommon"' $OCI_DIR/orainst/unix.rgs | sed 's/[ ][ ]*/:/g' | cut -d: -f 6 | cut -c 2-4`
+    test -z "$OCI_VERSION" && OCI_VERSION=7.3
+  elif test -f $OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.10.1; then
+    OCI_VERSION=10.1    
+  elif test -f $OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.9.0; then
+    OCI_VERSION=9.0
+  elif test -f $OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.8.0; then
+    OCI_VERSION=8.1
+  elif test -f $OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.1.0; then
+    OCI_VERSION=8.0
+  elif test -f $OCI_DIR/lib/libclntsh.a; then 
+    if test -f $OCI_DIR/lib/libcore4.a; then 
+      OCI_VERSION=8.0
+    else
+      OCI_VERSION=8.1
+    fi
+  else
+    AC_MSG_ERROR(Oracle-OCI needed libraries not found)
+  fi
+  AC_MSG_RESULT($OCI_VERSION)
+])                                                                                                                                                                
+
+PHP_ARG_WITH(oci, for Oracle-OCI support,
+[  --with-oci[=DIR]       Include Oracle-oci support. Default DIR is ORACLE_HOME.])
+
+if test "$PHP_OCI" != "no"; then
+  AC_MSG_CHECKING([Oracle Install-Dir])
+  if test "$PHP_OCI" = "yes"; then
+    OCI_DIR=$ORACLE_HOME
+  else
+    OCI_DIR=$PHP_OCI
+  fi
+  AC_MSG_RESULT($OCI_DIR)
+
+  if test -d "$OCI_DIR/rdbms/public"; then
+    PHP_ADD_INCLUDE($OCI_DIR/rdbms/public)
+    OCI_INCLUDES="$OCI_INCLUDES -I$OCI_DIR/rdbms/public"
+  fi
+  if test -d "$OCI_DIR/rdbms/demo"; then
+    PHP_ADD_INCLUDE($OCI_DIR/rdbms/demo)
+    OCI_INCLUDES="$OCI_INCLUDES -I$OCI_DIR/rdbms/demo"
+  fi
+  if test -d "$OCI_DIR/network/public"; then
+    PHP_ADD_INCLUDE($OCI_DIR/network/public)
+    OCI_INCLUDES="$OCI_INCLUDES -I$OCI_DIR/network/public"
+  fi
+  if test -d "$OCI_DIR/plsql/public"; then
+    PHP_ADD_INCLUDE($OCI_DIR/plsql/public)
+    OCI_INCLUDES="$OCI_INCLUDES -I$OCI_DIR/plsql/public"
+  fi
+
+  if test -f "$OCI_DIR/lib/sysliblist"; then
+    PHP_EVAL_LIBLINE(`cat $OCI_DIR/lib/sysliblist`, OCI_SYSLIB)
+  elif test -f "$OCI_DIR/rdbms/lib/sysliblist"; then
+    PHP_EVAL_LIBLINE(`cat $OCI_DIR/rdbms/lib/sysliblist`, OCI_SYSLIB)
+  fi
+
+  AC_OCI_VERSION($OCI_DIR)
+  case $OCI_VERSION in
+    8.0)
+      PHP_ADD_LIBRARY_WITH_PATH(nlsrtl3, "", OCI_SHARED_LIBADD)
+      PHP_ADD_LIBRARY_WITH_PATH(core4, "", OCI_SHARED_LIBADD)
+      PHP_ADD_LIBRARY_WITH_PATH(psa, "", OCI_SHARED_LIBADD)
+      PHP_ADD_LIBRARY_WITH_PATH(clntsh, $OCI_DIR/lib, OCI_SHARED_LIBADD)
+      ;;
+
+    8.1)
+      PHP_ADD_LIBRARY(clntsh, 1, OCI_SHARED_LIBADD)
+      PHP_ADD_LIBPATH($OCI_DIR/lib, OCI_SHARED_LIBADD)
+
+      dnl 
+      dnl OCI_ATTR_STATEMENT is not available in all 8.1.x versions
+      dnl 
+      PHP_OCI_IF_DEFINED(OCI_ATTR_STATEMENT, [AC_DEFINE(HAVE_OCI_ATTR_STATEMENT,1,[ ])], $OCI_INCLUDES)
+      ;;
+
+    9.0)
+      PHP_ADD_LIBRARY(clntsh, 1, OCI_SHARED_LIBADD)
+      PHP_ADD_LIBPATH($OCI_DIR/lib, OCI_SHARED_LIBADD)
+      AC_DEFINE(HAVE_OCI_ATTR_STATEMENT,1,[ ])
+
+      dnl These functions are only available in version >= 9.2
+      PHP_CHECK_LIBRARY(clntsh, OCIEnvNlsCreate,
+      [
+        PHP_CHECK_LIBRARY(clntsh, OCINlsCharSetNameToId,
+        [
+          AC_DEFINE(HAVE_OCI_9_2,1,[ ])
+          OCI_VERSION=9.2
+        ], [], [
+          -L$OCI_DIR/lib $OCI_SHARED_LIBADD
+        ])
+      ], [], [
+        -L$OCI_DIR/lib $OCI_SHARED_LIBADD
+      ])
+      ;;
+      
+    10.1)
+      PHP_ADD_LIBRARY(clntsh, 1, OCI_SHARED_LIBADD)
+      PHP_ADD_LIBPATH($OCI_DIR/lib, OCI_SHARED_LIBADD)
+      AC_DEFINE(HAVE_OCI_ATTR_STATEMENT,1,[ ])
+      AC_DEFINE(HAVE_OCI_9_2,1,[ ])
+      ;;
+    *)
+      AC_MSG_ERROR(Unsupported Oracle version!)
+      ;;
+  esac
+
+  dnl
+  dnl Check if we need to add -locijdbc8 
+  dnl
+  PHP_CHECK_LIBRARY(clntsh, OCILobIsTemporary,
+  [
+    AC_DEFINE(HAVE_OCI_TEMP_LOB,1,[ ])
+  ], [
+    PHP_CHECK_LIBRARY(ocijdbc8, OCILobIsTemporary,
+    [
+      PHP_ADD_LIBRARY(ocijdbc8, 1, OCI_SHARED_LIBADD)
+      AC_DEFINE(HAVE_OCI_TEMP_LOB,1,[ ])
+    ], [], [
+      -L$OCI_DIR/lib $OCI_SHARED_LIBADD
+    ])
+  ], [
+    -L$OCI_DIR/lib $OCI_SHARED_LIBADD
+  ])
+
+  dnl
+  dnl Check if we have collections
+  dnl
+  PHP_CHECK_LIBRARY(clntsh, OCICollAssign,
+  [
+    AC_DEFINE(PHP_OCI_HAVE_COLLECTIONS,1,[ ])
+  ], [], [
+    -L$OCI_DIR/lib $OCI_SHARED_LIBADD
+  ])
+
+
+  PHP_NEW_EXTENSION(pdo_oci, pdo_oci.c oci_driver.c oci_statement.c, $ext_shared)
+  AC_DEFINE(HAVE_OCI,1,[ ])
+
+  PHP_SUBST_OLD(OCI_SHARED_LIBADD)
+  PHP_SUBST_OLD(OCI_DIR)
+  PHP_SUBST_OLD(OCI_VERSION)
+  
+fi
diff --git a/ext/pdo_oci/config.w32 b/ext/pdo_oci/config.w32
new file mode 100755 (executable)
index 0000000..7c1e4bd
--- /dev/null
@@ -0,0 +1,45 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("pdo-oci", "Oracle OCI support for PDO", "yes,shared");
+
+if (PHP_PDO_OCI != "no") {
+
+       php_oci_dirs = new Array(
+               PHP_PDO_OCI,
+               PHP_PDO_OCI + "\\oci",
+               PHP_PHP_BUILD + "\\oci92",
+               PHP_PHP_BUILD + "\\oci805"
+       );
+
+       php_oci_lib_paths = "";
+       php_oci_inc_paths = "";
+
+       // find the oracle install
+       for (i = 0; i < php_oci_dirs.length; i++) {
+               php_oci_lib_paths += php_oci_dirs[i] + "\\lib;";
+               php_oci_lib_paths += php_oci_dirs[i] + "\\lib\\msvc;";
+               php_oci_inc_paths += php_oci_dirs[i] + "\\include;";
+       }
+
+       if (CHECK_HEADER_ADD_INCLUDE("oci.h", "CFLAGS_PDO_OCI", php_oci_inc_paths) &&
+                       CHECK_LIB("oci.lib", "pdo_oci", php_oci_lib_paths)
+                       ) {
+
+               EXTENSION('pdo_oci', 'pdo_oci.c oci_driver.c oci_statement.c');
+               ADD_FLAG('CFLAGS_PDO_OCI', "/I ..\\pecl");
+
+               AC_DEFINE('HAVE_OCI_TEMP_LOB', 1);
+               AC_DEFINE('HAVE_OCI', 1);
+               AC_DEFINE('HAVE_OCI_ATTR_STATEMENT', 1);
+               AC_DEFINE('PHP_OCI_HAVE_COLLECTIONS', 1);
+
+               /* LOCAL HACKS: assume you have OCI 9.2 */
+               AC_DEFINE('HAVE_OCIENVCREATE', 1);
+               AC_DEFINE('HAVE_OCIENVNLSCREATE', 1);
+       } else {
+               WARNING("pdo-oci not enabled; libraries and headers not found");
+       }
+       ADD_EXTENSION_DEP('pdo_oci', 'pdo');
+}
+
diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c
new file mode 100755 (executable)
index 0000000..3c39a9e
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2004 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.0 of the PHP license,       |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_0.txt.                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author: Wez Furlong <wez@php.net>                                    |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "pdo/php_pdo.h"
+#include "pdo/php_pdo_driver.h"
+#include "php_pdo_oci.h"
+#include "php_pdo_oci_int.h"
+
+ub4 _oci_error(OCIError *err, char *what, sword status, const char *file, int line TSRMLS_DC) /* {{{ */
+{
+       text errbuf[1024] = "<<Unknown>>";
+       sb4 errcode = 0;
+
+       switch (status) {
+               case OCI_SUCCESS:
+                       break;
+               case OCI_ERROR:
+                       OCIErrorGet(err, (ub4)1, NULL, &errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%s:%d) %s: %d %s", file, line, what, errcode, errbuf);
+                       break;
+               case OCI_SUCCESS_WITH_INFO:
+                       OCIErrorGet(err, (ub4)1, NULL, &errcode, errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR);
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%s:%d) %s: OCI_SUCCESS_WITH_INFO: %s", file, line, what, errbuf);
+                       break;
+               case OCI_NEED_DATA:
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%s:%d) %s: OCI_NEED_DATA",  file, line, what);
+                       break;
+               case OCI_NO_DATA:
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%s:%d) %s: OCI_NO_DATA", file, line,  what);
+                       break;
+               case OCI_INVALID_HANDLE:
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%s:%d) %s: OCI_INVALID_HANDLE", file, line,  what);
+                       break;
+               case OCI_STILL_EXECUTING:
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%s:%d) %s: OCI_STILL_EXECUTING", file, line,  what);
+                       break;
+               case OCI_CONTINUE:
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "(%s:%d) %s: OCI_CONTINUE", file, line,  what);
+                       break;
+       }
+       return errcode;
+}
+/* }}} */
+
+ub4 oci_handle_error(pdo_dbh_t *dbh, pdo_oci_db_handle *H, ub4 errcode) /* {{{ */
+{
+       switch (errcode) {
+               case 1013:      /* user requested cancel of current operation */
+                       zend_bailout();
+                       break;
+               case 22:        /* ORA-00022: invalid session id */
+               case 1012:      /* ORA-01012: */
+               case 3113:      /* ORA-03133: end of file on communication channel */
+               case 604:
+               case 1041:
+                       /* consider the connection closed */
+                       dbh->is_closed = 1;
+                       H->attached = 0;
+                       return 1;
+       }
+       return 0;
+}
+/* }}} */
+
+static int oci_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
+{
+       pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+       
+       if (H->svc) {
+               /* rollback any outstanding work */
+               OCITransRollback(H->svc, H->err, 0);
+       }
+
+       if (H->session) {
+               OCIHandleFree(H->session, OCI_HTYPE_SESSION);
+               H->session = NULL;
+       }
+
+       if (H->svc) {
+               OCIHandleFree(H->svc, OCI_HTYPE_SVCCTX);
+               H->svc = NULL;
+       }
+       
+       if (H->server && H->attached) {
+               H->last_err = OCIServerDetach(H->server, H->err, OCI_DEFAULT);
+               if (H->last_err) {
+                       oci_error(H->err, "OCIServerDetach", H->last_err);
+               }
+               H->attached = 0;
+       }
+
+       if (H->server) {
+               OCIHandleFree(H->server, OCI_HTYPE_SERVER);
+               H->server = NULL;
+       }
+
+       OCIHandleFree(H->err, OCI_HTYPE_ERROR);
+       H->err = NULL;
+
+       if (H->charset && H->env) {
+               OCIHandleFree(H->env, OCI_HTYPE_ENV);
+               H->env = NULL;
+       }
+
+       pefree(H, dbh->is_persistent);
+
+       return 0;
+}
+/* }}} */
+
+static int oci_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt TSRMLS_DC)
+{
+       pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+       pdo_oci_stmt *S = ecalloc(1, sizeof(*S));
+
+       S->H = H;
+       
+       /* create an OCI statement handle */
+       OCIHandleAlloc(H->env, &S->stmt, OCI_HTYPE_STMT, 0, NULL);
+
+       /* and our own private error handle */
+       OCIHandleAlloc(H->env, &S->err, OCI_HTYPE_ERROR, 0, NULL);
+
+       if (sql_len) {
+               H->last_err = OCIStmtPrepare(S->stmt, H->err, (text*)sql, sql_len, OCI_NTV_SYNTAX, OCI_DEFAULT);
+
+               if (H->last_err) {
+                       H->last_err = oci_error(H->err, "OCIStmtPrepare", H->last_err);
+                       OCIHandleFree(S->stmt, OCI_HTYPE_STMT);
+                       OCIHandleFree(S->err, OCI_HTYPE_ERROR);
+                       efree(S);
+                       oci_handle_error(dbh, H, H->last_err);
+                       return 0;
+               }
+       }
+
+       stmt->driver_data = S;
+       stmt->methods = &oci_stmt_methods;
+       
+       return 1;
+}
+
+static int oci_handle_doer(pdo_dbh_t *dbh, const char *sql TSRMLS_DC)
+{
+       pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+       return 0;
+}
+
+static int oci_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, char **quoted, int *quotedlen  TSRMLS_DC)
+{
+       pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+       return 0;
+}
+
+static int oci_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
+{
+       /* with Oracle, there is nothing special to be done */
+       return 1;
+}
+
+static int oci_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
+{
+       pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+       H->last_err = OCITransCommit(H->svc, H->err, 0);
+
+       if (H->last_err) {
+               H->last_err = oci_error(H->err, "OCITransCommit", H->last_err);
+               oci_handle_error(dbh, H, H->last_err);
+               return 0;
+       }
+       return 1;
+}
+
+static int oci_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
+{
+       pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+       H->last_err = OCITransRollback(H->svc, H->err, 0);
+
+       if (H->last_err) {
+               H->last_err = oci_error(H->err, "OCITransRollback", H->last_err);
+               oci_handle_error(dbh, H, H->last_err);
+               return 0;
+       }
+       return 1;
+}
+
+static int oci_handle_set_attribute(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
+{
+       pdo_oci_db_handle *H = (pdo_oci_db_handle *)dbh->driver_data;
+
+       if (dbh->in_txn) {
+               /* Assume they want to commit whatever is outstanding */
+               H->last_err = OCITransCommit(H->svc, H->err, 0);
+
+               if (H->last_err) {
+                       H->last_err = oci_error(H->err, "OCITransCommit", H->last_err);
+                       oci_handle_error(dbh, H, H->last_err);
+                       return 0;
+               }
+               dbh->in_txn = 0;
+       }
+       
+       convert_to_long(val);
+
+       dbh->auto_commit = Z_LVAL_P(val);
+       
+       return 1;
+}
+
+static struct pdo_dbh_methods oci_methods = {
+       oci_handle_closer,
+       oci_handle_preparer,
+       oci_handle_doer,
+       oci_handle_quoter,
+       oci_handle_begin,
+       oci_handle_commit,
+       oci_handle_rollback,
+       oci_handle_set_attribute
+};
+
+static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
+{
+       pdo_oci_db_handle *H;
+       int i, ret = 0;
+       struct pdo_data_src_parser vars[] = {
+               { "charset",  NULL,     0 },
+               { "dbname",   "",       0 }
+       };
+
+       php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 4);
+       
+       H = pecalloc(1, sizeof(*H), dbh->is_persistent);
+       
+       /* allocate an environment */
+#if HAVE_OCIENVNLSCREATE
+       if (vars[0].optval) {
+               H->charset = OCINlsCharSetNameToId(pdo_oci_Env, vars[0].optval);
+               if (H->charset) {
+                       OCIEnvNlsCreate(&H->env, PDO_OCI_INIT_MODE, 0, NULL, NULL, NULL, 0, NULL, H->charset, H->charset);
+               }
+       }
+#endif
+       if (H->env == NULL) {
+               /* use the global environment */
+               H->env = pdo_oci_Env;
+       }
+
+       /* something to hold errors */
+       OCIHandleAlloc(H->env, (dvoid **)&H->err, OCI_HTYPE_ERROR, 0, NULL);
+       
+       /* handle for the server */
+       OCIHandleAlloc(H->env, (dvoid **)&H->server, OCI_HTYPE_SERVER, 0, NULL);
+       
+       H->last_err = OCIServerAttach(H->server, H->err, (text*)vars[1].optval,
+                       strlen(vars[1].optval), OCI_DEFAULT);
+
+       if (H->last_err) {
+               oci_error(H->err, "pdo_oci_handle_factory", H->last_err);
+               goto cleanup;
+       }
+
+       H->attached = 1;
+
+       /* create a service context */
+       H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->svc, OCI_HTYPE_SVCCTX, 0, NULL);
+       if (H->last_err) {
+               oci_error(H->err, "OCIHandleAlloc: OCI_HTYPE_SVCCTX", H->last_err);
+               goto cleanup;
+       }
+
+       H->last_err = OCIHandleAlloc(H->env, (dvoid**)&H->session, OCI_HTYPE_SESSION, 0, NULL);
+       if (H->last_err) {
+               oci_error(H->err, "OCIHandleAlloc: OCI_HTYPE_SESSION", H->last_err);
+               goto cleanup;
+       }
+
+       /* set server handle into service handle */
+       H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->server, 0, OCI_ATTR_SERVER, H->err);
+       if (H->last_err) {
+               oci_error(H->err, "OCIAttrSet: OCI_ATTR_SERVER", H->last_err);
+               goto cleanup;
+       }
+
+       /* username */
+       H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
+                       dbh->username, strlen(dbh->username),
+                       OCI_ATTR_USERNAME, H->err);
+       if (H->last_err) {
+               oci_error(H->err, "OCIAttrSet: OCI_ATTR_USERNAME", H->last_err);
+               goto cleanup;
+       }
+
+       /* password */
+       H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
+                       dbh->password, strlen(dbh->password),
+                       OCI_ATTR_PASSWORD, H->err);
+       if (H->last_err) {
+               oci_error(H->err, "OCIAttrSet: OCI_ATTR_PASSWORD", H->last_err);
+               goto cleanup;
+       }
+
+       /* Now fire up the session */
+       H->last_err = OCISessionBegin(H->svc, H->err, H->session, OCI_CRED_RDBMS, OCI_DEFAULT); 
+       if (H->last_err) {
+               oci_error(H->err, "OCISessionBegin:", H->last_err);
+               goto cleanup;
+       }
+
+       /* set the server handle into service handle */
+       H->last_err = OCIAttrSet(H->svc, OCI_HTYPE_SVCCTX, H->session, 0, OCI_ATTR_SESSION, H->err);
+       if (H->last_err) {
+               oci_error(H->err, "OCIAttrSet: OCI_ATTR_SESSION:", H->last_err);
+               goto cleanup;
+       }
+       
+       dbh->driver_data = H;
+       dbh->methods = &oci_methods;
+       dbh->alloc_own_columns = 1;
+       dbh->supports_placeholders = 1;
+       dbh->placeholders_can_be_strings = 1;
+
+       ret = 1;
+       
+cleanup:
+       for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
+               if (vars[i].freeme) {
+                       efree(vars[i].optval);
+               }
+       }
+
+       if (!ret) {
+               oci_handle_closer(dbh TSRMLS_CC);
+       }
+
+       return ret;
+}
+/* }}} */
+
+pdo_driver_t pdo_oci_driver = {
+       PDO_DRIVER_HEADER(oci),
+       pdo_oci_handle_factory
+};
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c
new file mode 100755 (executable)
index 0000000..39aa458
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2004 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.0 of the PHP license,       |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_0.txt.                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author: Wez Furlong <wez@php.net>                                    |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "pdo/php_pdo.h"
+#include "pdo/php_pdo_driver.h"
+#include "php_pdo_oci.h"
+#include "php_pdo_oci_int.h"
+
+#define STMT_CALL(name, params)        \
+       S->last_err = name params; \
+       S->last_err = _oci_error(S->err, #name, S->last_err, __FILE__, __LINE__ TSRMLS_CC); \
+       if (S->last_err) { \
+               oci_handle_error(stmt->dbh, S->H, S->last_err); \
+               return 0; \
+       }
+
+#define STMT_CALL_MSG(name, msg, params)       \
+       S->last_err = name params; \
+       S->last_err = _oci_error(S->err, #name ": " #msg, S->last_err, __FILE__, __LINE__ TSRMLS_CC); \
+       if (S->last_err) { \
+               oci_handle_error(stmt->dbh, S->H, S->last_err); \
+               return 0; \
+       }
+
+
+static int oci_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
+{
+       pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
+       int i;
+
+       if (S->stmt) {
+               /* cancel server side resources for the statement if we didn't
+                * fetch it all */
+               OCIStmtFetch(S->stmt, S->err, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
+
+               /* free the handle */
+               OCIHandleFree(S->stmt, OCI_HTYPE_STMT);
+               S->stmt = NULL;
+       }
+       if (S->err) {
+               OCIHandleFree(S->err, OCI_HTYPE_ERROR);
+               S->err = NULL;
+       }
+
+       if (S->cols) {
+               for (i = 0; i < stmt->column_count; i++) {
+                       if (S->cols[i].data) {
+                               efree(S->cols[i].data);
+                       }
+               }
+               efree(S->cols);
+               S->cols = NULL;
+       }
+       efree(S);
+
+       return 1;
+}
+
+static int oci_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
+{
+       pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
+       ub4 rowcount;
+
+       if (!S->stmt_type) {
+               STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_STMT_TYPE",
+                               (S->stmt, OCI_HTYPE_STMT, &S->stmt_type, 0, OCI_ATTR_STMT_TYPE, S->err));
+       }
+
+       if (stmt->executed) {
+               /* ensure that we cancel the cursor from a previous fetch */
+               OCIStmtFetch(S->stmt, S->err, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
+       }
+
+       STMT_CALL(OCIStmtExecute, (S->H->svc, S->stmt, S->err,
+                               S->stmt_type == OCI_STMT_SELECT ? 0 : 1, 0, NULL, NULL,
+                               (stmt->dbh->auto_commit & !stmt->dbh->in_txn) ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT));
+
+       if (!stmt->executed) {
+               ub4 colcount;
+               /* do first-time-only definition of bind/mapping stuff */
+
+               /* how many columns do we have ? */
+               STMT_CALL_MSG(OCIAttrGet, "ATTR_PARAM_COUNT",
+                               (S->stmt, OCI_HTYPE_STMT, &colcount, 0, OCI_ATTR_PARAM_COUNT, S->err));
+
+               stmt->column_count = (int)colcount;
+
+               S->cols = ecalloc(colcount, sizeof(pdo_oci_column));
+       }
+       
+       STMT_CALL_MSG(OCIAttrGet, "ATTR_ROW_COUNT",
+                       (S->stmt, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROW_COUNT, S->err));
+       stmt->row_count = (long)rowcount;
+
+       return 1;
+}
+
+static sb4 oci_bind_input_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp,
+               ub4 *alenp, ub1 *piecep, dvoid **indpp)
+{
+       struct pdo_bound_param_data *param = (struct pdo_bound_param_data*)ctx;
+       pdo_oci_bound_param *P = (pdo_oci_bound_param*)ecalloc(1, sizeof(pdo_oci_bound_param));
+       TSRMLS_FETCH();
+
+       if (!param || !param->parameter) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "param is NULL in oci_bind_input_cb; this should not happen");
+               return OCI_ERROR;
+       }
+       
+       *indpp = &P->indicator;
+
+       if (ZVAL_IS_NULL(param->parameter)) {
+               /* insert a NULL value into the column */
+               P->indicator = -1; /* NULL */
+               *bufpp = 0;
+               *alenp = -1;
+       } else if (!P->thing) {
+               /* regular string bind */
+               convert_to_string(param->parameter);
+               *bufpp = Z_STRVAL_P(param->parameter);
+               *alenp = Z_STRLEN_P(param->parameter);
+       } else {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "P->thing should not be set??");
+               return OCI_ERROR;
+       }
+
+       *piecep = OCI_ONE_PIECE;
+       return OCI_CONTINUE;
+}
+
+static sb4 oci_bind_output_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, dvoid **bufpp, ub4 **alenpp,
+               ub1 *piecep, dvoid **indpp, ub2 **rcodepp)
+{
+       struct pdo_bound_param_data *param = (struct pdo_bound_param_data*)ctx;
+       pdo_oci_bound_param *P = (pdo_oci_bound_param*)ecalloc(1, sizeof(pdo_oci_bound_param));
+       TSRMLS_FETCH();
+
+       if (!param || !param->parameter) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "param is NULL in oci_bind_output_cb; this should not happen");
+               return OCI_ERROR;
+       }
+       
+       if (Z_TYPE_P(param->parameter) == IS_OBJECT || Z_TYPE_P(param->parameter) == IS_RESOURCE) {
+               return OCI_CONTINUE;
+       }
+
+       convert_to_string(param->parameter);
+       zval_dtor(param->parameter);
+
+       Z_STRLEN_P(param->parameter) = param->max_value_len;
+       Z_STRVAL_P(param->parameter) = emalloc(Z_STRLEN_P(param->parameter)+1);
+
+       
+       *alenpp = &P->actual_len;
+       *bufpp = Z_STRVAL_P(param->parameter);
+       *piecep = OCI_ONE_PIECE;
+       *rcodepp = &P->retcode;
+       *indpp = &P->indicator;
+
+       return OCI_CONTINUE;
+}
+
+static int oci_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
+               enum pdo_param_event event_type TSRMLS_DC)
+{
+       pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
+
+       /* we're only interested in parameters for prepared SQL right now */
+       if (param->is_param) {
+               pdo_oci_bound_param *P;
+               sb4 value_sz = -1;
+               
+               P = (pdo_oci_bound_param*)param->driver_data;
+
+               switch (event_type) {
+                       case PDO_PARAM_EVT_ALLOC:
+                               P = (pdo_oci_bound_param*)ecalloc(1, sizeof(pdo_oci_bound_param));
+                               param->driver_data = P;
+                       
+                               /* figure out what we're doing */
+                               switch (param->param_type) {
+                                       case PDO_PARAM_LOB:
+                                       case PDO_PARAM_STMT:
+                                               return 0;
+
+                                       case PDO_PARAM_STR:
+                                       default:
+                                               P->oci_type = SQLT_CHR;
+                                               convert_to_string(param->parameter);
+                                               value_sz = param->max_value_len + 1;
+                                               P->actual_len = Z_STRLEN_P(param->parameter);
+                                               
+                               }
+                               
+                               if (param->name) {
+                                       STMT_CALL(OCIBindByName, (S->stmt,
+                                                       &P->bind, S->err, (text*)param->name,
+                                                       param->namelen, 0, value_sz, P->oci_type,
+                                                       &P->indicator, 0, &P->retcode, 0, 0,
+                                                       OCI_DATA_AT_EXEC));
+                               } else {
+                                       STMT_CALL(OCIBindByPos, (S->stmt,
+                                                       &P->bind, S->err, param->paramno+1,
+                                                       0, value_sz, P->oci_type,
+                                                       &P->indicator, 0, &P->retcode, 0, 0,
+                                                       OCI_DATA_AT_EXEC));
+                               }
+                       
+                               STMT_CALL(OCIBindDynamic, (P->bind,
+                                                       S->err,
+                                                       param, oci_bind_input_cb,
+                                                       param, oci_bind_output_cb));
+
+                               return 1;
+
+                       case PDO_PARAM_EVT_EXEC_PRE:
+                               P->indicator = 0;
+                               return 1;
+
+                       case PDO_PARAM_EVT_EXEC_POST:
+                               /* fixup stuff set in motion in oci_bind_output_cb */
+                               if (P->indicator == -1) {
+                                       /* set up a NULL value */
+                                       if (Z_TYPE_P(param->parameter) == IS_STRING && Z_STRVAL_P(param->parameter) != empty_string) {
+                                               /* OCI likes to stick non-terminated strings in things */
+                                               *Z_STRVAL_P(param->parameter) = '\0';
+                                       }
+                                       zval_dtor(param->parameter);
+                                       ZVAL_NULL(param->parameter);
+                               } else if (Z_TYPE_P(param->parameter) == IS_STRING && Z_STRVAL_P(param->parameter) != empty_string) {
+                                       Z_STRLEN_P(param->parameter) = P->actual_len;
+                                       Z_STRVAL_P(param->parameter) = erealloc(Z_STRVAL_P(param->parameter), P->actual_len+1);
+                                       Z_STRVAL_P(param->parameter)[P->actual_len] = '\0';
+                               }
+
+                               return 1;
+               }
+       }
+       
+       return 1;
+}
+
+static int oci_stmt_fetch(pdo_stmt_t *stmt TSRMLS_DC)
+{
+       pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
+
+       S->last_err = OCIStmtFetch(S->stmt, S->err, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
+
+       if (S->last_err == OCI_NO_DATA) {
+               /* no (more) data */
+               return 0;
+       }
+
+       if (S->last_err == OCI_NEED_DATA) {
+               oci_error(S->err, "OCI_NEED_DATA", S->last_err);
+               return 0;
+       }
+
+       if (S->last_err == OCI_SUCCESS_WITH_INFO || S->last_err == OCI_SUCCESS) {
+               return 1;
+       }
+       
+       oci_error(S->err, "OCIStmtFetch", S->last_err);
+       oci_handle_error(stmt->dbh, S->H, S->last_err);
+
+       return 0;
+}
+
+static int oci_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
+{
+       pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
+       OCIParam *param = NULL;
+       text *colname;
+       ub2 dtype, data_size, scale, precis;
+       ub4 namelen;
+       struct pdo_column_data *col = &stmt->columns[colno];
+       zend_bool dyn = FALSE;
+
+       /* describe the column */
+       STMT_CALL(OCIParamGet, (S->stmt, OCI_HTYPE_STMT, S->err, &param, colno+1));
+
+       /* what type ? */
+       STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_DATA_TYPE",
+                       (param, OCI_DTYPE_PARAM, &dtype, 0, OCI_ATTR_DATA_TYPE, S->err));
+
+       /* how big ? */
+       STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_DATA_SIZE",
+                       (param, OCI_DTYPE_PARAM, &data_size, 0, OCI_ATTR_DATA_SIZE, S->err));
+
+       /* scale ? */
+       STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_SCALE",
+                       (param, OCI_DTYPE_PARAM, &scale, 0, OCI_ATTR_SCALE, S->err));
+
+       /* precision ? */
+       STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_PRECISION",
+                       (param, OCI_DTYPE_PARAM, &precis, 0, OCI_ATTR_PRECISION, S->err));
+
+       /* name ? */
+       STMT_CALL_MSG(OCIAttrGet, "OCI_ATTR_NAME",
+                       (param, OCI_DTYPE_PARAM, &colname, &namelen, OCI_ATTR_NAME, S->err));
+
+       col->precision = scale;
+       col->maxlen = data_size;
+       col->namelen = namelen;
+       col->name = estrndup(colname, namelen);
+
+       /* how much room do we need to store the field */
+       switch (dtype) {
+               case SQLT_BIN:
+               default:
+                       dyn = FALSE;
+                       if (dtype == SQLT_DAT || dtype == SQLT_NUM
+#ifdef SQLT_TIMESTAMP
+                                       || dtype == SQLT_TIMESTAMP
+#endif
+#ifdef SQLT_TIMESTAMP_TZ
+                                       || dtype == SQLT_TIMESTAMP_TZ
+#endif
+                                       ) {
+                               /* should be big enough for most date formats and numbers */
+                               S->cols[colno].datalen = 512;
+                       } else {
+                               S->cols[colno].datalen = col->maxlen + 1; /* 1 for NUL terminator */
+                       }
+                       if (dtype == SQLT_BIN) {
+                               S->cols[colno].datalen *= 3;
+                       }
+                       S->cols[colno].data = emalloc(S->cols[colno].datalen);
+                       dtype = SQLT_CHR;
+
+                       /* returning data as a string */
+                       col->param_type = PDO_PARAM_STR;
+       }
+
+       if (!dyn) {
+               STMT_CALL(OCIDefineByPos, (S->stmt, &S->cols[colno].def, S->err, colno+1,
+                                       S->cols[colno].data, S->cols[colno].datalen, dtype, &S->cols[colno].indicator,
+                                       &S->cols[colno].fetched_len, &S->cols[colno].retcode));
+       }
+       
+       return 1;
+}
+
+static int oci_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len TSRMLS_DC)
+{
+       pdo_oci_stmt *S = (pdo_oci_stmt*)stmt->driver_data;
+       pdo_oci_column *C = &S->cols[colno];
+
+       /* check the indicator to ensure that the data is intact */
+       if (C->indicator == -1) {
+               /* A NULL value */
+               *ptr = NULL;
+               *len = 0;
+               return 1;
+       } else if (C->indicator == 0) {
+               /* it was stored perfectly */
+               *ptr = C->data;
+               *len = C->fetched_len;
+               return 1;
+       } else {
+               /* it was truncated */
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "column %d data was too large for buffer and was truncated to fit it", colno);
+
+               *ptr = C->data;
+               *len = C->fetched_len;
+               return 1;
+       }
+}
+
+struct pdo_stmt_methods oci_stmt_methods = {
+       oci_stmt_dtor,
+       oci_stmt_execute,
+       oci_stmt_fetch,
+       oci_stmt_describe,
+       oci_stmt_get_col,
+       oci_stmt_param_hook
+};
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/pdo_oci/pdo_oci.c b/ext/pdo_oci/pdo_oci.c
new file mode 100755 (executable)
index 0000000..154faa7
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2004 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.0 of the PHP license,       |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_0.txt.                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author: Wez Furlong <wez@php.net>                                    |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "pdo/php_pdo.h"
+#include "pdo/php_pdo_driver.h"
+#include "php_pdo_oci.h"
+#include "php_pdo_oci_int.h"
+
+/* {{{ pdo_oci_functions[] */
+function_entry pdo_oci_functions[] = {
+       {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ pdo_oci_module_entry */
+zend_module_entry pdo_oci_module_entry = {
+       STANDARD_MODULE_HEADER,
+       "pdo_oci",
+       pdo_oci_functions,
+       PHP_MINIT(pdo_oci),
+       PHP_MSHUTDOWN(pdo_oci),
+       NULL,
+       NULL,
+       PHP_MINFO(pdo_oci),
+       "0.1",
+       STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_PDO_OCI
+ZEND_GET_MODULE(pdo_oci)
+#endif
+
+const ub4 PDO_OCI_INIT_MODE = 
+#if 0 && defined(OCI_SHARED)
+                       /* shared mode is known to be bad for PHP */
+                       OCI_SHARED
+#else
+                       OCI_DEFAULT
+#endif
+#ifdef OCI_OBJECT
+                       |OCI_OBJECT
+#endif
+#ifdef ZTS
+                       |OCI_THREADED
+#endif
+                       ;
+
+/* true global environment */
+OCIEnv *pdo_oci_Env = NULL;
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(pdo_oci)
+{
+       php_pdo_register_driver(&pdo_oci_driver);
+
+#if HAVE_OCIENVCREATE
+       OCIEnvCreate(&pdo_oci_Env, PDO_OCI_INIT_MODE, NULL, NULL, NULL, NULL, 0, NULL);
+#else
+       OCIInitialize(PDO_OCI_INIT_MODE, NULL, NULL, NULL, NULL);
+       OCIEnvInit(&pdo_oci_Env, OCI_DEFAULT, 0, NULL);
+#endif
+
+       return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(pdo_oci)
+{
+       php_pdo_unregister_driver(&pdo_oci_driver);
+       OCIHandleFree((dvoid*)pdo_oci_Env, OCI_HTYPE_ENV);
+       return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(pdo_oci)
+{
+       php_info_print_table_start();
+       php_info_print_table_header(2, "PDO Driver for OCI 8 and later", "enabled");
+       php_info_print_table_end();
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/pdo_oci/php_pdo_oci.h b/ext/pdo_oci/php_pdo_oci.h
new file mode 100755 (executable)
index 0000000..fe9f247
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2004 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.0 of the PHP license,       |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_0.txt.                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author: Wez Furlong <wez@php.net>                                    |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_PDO_OCI_H
+#define PHP_PDO_OCI_H
+
+extern zend_module_entry pdo_oci_module_entry;
+#define phpext_pdo_oci_ptr &pdo_oci_module_entry
+
+#ifdef PHP_WIN32
+#define PHP_PDO_OCI_API __declspec(dllexport)
+#else
+#define PHP_PDO_OCI_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+PHP_MINIT_FUNCTION(pdo_oci);
+PHP_MSHUTDOWN_FUNCTION(pdo_oci);
+PHP_RINIT_FUNCTION(pdo_oci);
+PHP_RSHUTDOWN_FUNCTION(pdo_oci);
+PHP_MINFO_FUNCTION(pdo_oci);
+
+#endif /* PHP_PDO_OCI_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/pdo_oci/php_pdo_oci_int.h b/ext/pdo_oci/php_pdo_oci_int.h
new file mode 100755 (executable)
index 0000000..4933f9b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 5                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2004 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.0 of the PHP license,       |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_0.txt.                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author: Wez Furlong <wez@php.net>                                    |
+  +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include <oci.h>
+
+/* stuff we use in an OCI database handle */
+typedef struct {
+       OCIServer       *server;
+       OCISession      *session;
+       OCIEnv          *env;
+       OCIError        *err;
+       OCISvcCtx       *svc;
+       /* OCI9; 0 == use NLS_LANG */
+       ub2                     charset;
+       sword           last_err;
+
+       unsigned attached:1;
+       unsigned _reserved:31;
+} pdo_oci_db_handle;
+
+typedef struct {
+       OCIDefine       *def;
+       ub2                     fetched_len;
+       ub2                     retcode;
+       sb2                     indicator;
+
+       char *data;
+       unsigned long datalen;
+
+} pdo_oci_column;
+
+typedef struct {
+       pdo_oci_db_handle *H;
+       OCIStmt         *stmt;
+       OCIError        *err;
+       sword           last_err;
+       ub2                     stmt_type;
+
+       pdo_oci_column *cols;
+} pdo_oci_stmt;
+
+typedef struct {
+       OCIBind         *bind;  /* allocated by OCI */
+       sb2                     oci_type;
+       sb2                     indicator;
+       ub2                     retcode;
+
+       ub4                     actual_len;
+
+       dvoid           *thing; /* for LOBS, REFCURSORS etc. */
+} pdo_oci_bound_param;
+
+extern const ub4 PDO_OCI_INIT_MODE;
+extern pdo_driver_t pdo_oci_driver;
+extern OCIEnv *pdo_oci_Env;
+
+ub4 _oci_error(OCIError *err, char *what, sword status, const char *file, int line TSRMLS_DC);
+#define oci_error(e, w, s)     _oci_error(e, w, s, __FILE__, __LINE__ TSRMLS_CC)
+
+ub4 oci_handle_error(pdo_dbh_t *dbh, pdo_oci_db_handle *H, ub4 errcode);
+
+extern struct pdo_stmt_methods oci_stmt_methods;
+