mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
OCI driver for PDO, supporting bound input and output parameters.
Will not build under unix yet.
This commit is contained in:
parent
684be9cf36
commit
1b1ced539b
2
ext/pdo_oci/CREDITS
Executable file
2
ext/pdo_oci/CREDITS
Executable file
@ -0,0 +1,2 @@
|
||||
Oracle (OCI) driver for PDO
|
||||
Wez Furlong
|
0
ext/pdo_oci/EXPERIMENTAL
Normal file
0
ext/pdo_oci/EXPERIMENTAL
Normal file
169
ext/pdo_oci/config.m4
Executable file
169
ext/pdo_oci/config.m4
Executable file
@ -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
|
45
ext/pdo_oci/config.w32
Executable file
45
ext/pdo_oci/config.w32
Executable file
@ -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');
|
||||
}
|
||||
|
379
ext/pdo_oci/oci_driver.c
Executable file
379
ext/pdo_oci/oci_driver.c
Executable file
@ -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
|
||||
*/
|
410
ext/pdo_oci/oci_statement.c
Executable file
410
ext/pdo_oci/oci_statement.c
Executable file
@ -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, ¶m, 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
|
||||
*/
|
120
ext/pdo_oci/pdo_oci.c
Executable file
120
ext/pdo_oci/pdo_oci.c
Executable file
@ -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
|
||||
*/
|
53
ext/pdo_oci/php_pdo_oci.h
Executable file
53
ext/pdo_oci/php_pdo_oci.h
Executable file
@ -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
|
||||
*/
|
80
ext/pdo_oci/php_pdo_oci_int.h
Executable file
80
ext/pdo_oci/php_pdo_oci_int.h
Executable file
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user