summaryrefslogtreecommitdiff
path: root/ext/oracle/oracle.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/oracle/oracle.c')
-rw-r--r--ext/oracle/oracle.c1770
1 files changed, 1770 insertions, 0 deletions
diff --git a/ext/oracle/oracle.c b/ext/oracle/oracle.c
new file mode 100644
index 000000000..efeaca94a
--- /dev/null
+++ b/ext/oracle/oracle.c
@@ -0,0 +1,1770 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@php.net> |
+ | Mitch Golden <mgolden@interport.net> |
+ | Rasmus Lerdorf <rasmus@php.net> |
+ | Andreas Karajannis <Andreas.Karajannis@gmd.de> |
+ | Thies C. Arntzen <thies@thieso.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id: oracle.c,v 1.94 2004/01/08 08:16:41 andi Exp $ */
+
+/* comment out the next line if you're on Oracle 7.x and don't have the olog
+ call. */
+
+#define HAS_OLOG 1
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#include "zend_globals.h"
+
+#if HAVE_ORACLE
+
+#include "php_oracle.h"
+#define HASH_DTOR (void (*)(void *))
+
+#include "ext/standard/info.h"
+
+
+#ifndef min
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+#ifdef PHP_WIN32
+#define PHP_ORA_API __declspec(dllexport)
+#else
+#define PHP_ORA_API
+#endif
+
+#ifdef ZTS
+int ora_globals_id;
+#else
+PHP_ORA_API php_ora_globals ora_globals;
+#endif
+
+#define DB_SIZE 65536
+
+#define ORA_FETCHINTO_ASSOC (1<<0)
+#define ORA_FETCHINTO_NULLS (1<<1)
+
+static oraCursor *ora_get_cursor(HashTable *, pval ** TSRMLS_DC);
+static char *ora_error(Cda_Def *);
+static int ora_describe_define(oraCursor *);
+static void _close_oraconn(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+static int _close_oracur(oraCursor *cur TSRMLS_DC);
+static int _ora_ping(oraConnection *conn);
+int ora_set_param_values(oraCursor *cursor, int isout TSRMLS_DC);
+
+void ora_do_logon(INTERNAL_FUNCTION_PARAMETERS, int persistent);
+
+static int le_conn, le_pconn, le_cursor;
+
+/* {{{ prototypes
+ */
+PHP_FUNCTION(ora_bind);
+PHP_FUNCTION(ora_close);
+PHP_FUNCTION(ora_commit);
+PHP_FUNCTION(ora_commitoff);
+PHP_FUNCTION(ora_commiton);
+PHP_FUNCTION(ora_do);
+PHP_FUNCTION(ora_error);
+PHP_FUNCTION(ora_errorcode);
+PHP_FUNCTION(ora_exec);
+PHP_FUNCTION(ora_fetch);
+PHP_FUNCTION(ora_fetch_into);
+PHP_FUNCTION(ora_columntype);
+PHP_FUNCTION(ora_columnname);
+PHP_FUNCTION(ora_columnsize);
+PHP_FUNCTION(ora_getcolumn);
+PHP_FUNCTION(ora_numcols);
+PHP_FUNCTION(ora_numrows);
+PHP_FUNCTION(ora_logoff);
+PHP_FUNCTION(ora_logon);
+PHP_FUNCTION(ora_plogon);
+PHP_FUNCTION(ora_open);
+PHP_FUNCTION(ora_parse);
+PHP_FUNCTION(ora_rollback);
+
+PHP_MINIT_FUNCTION(oracle);
+PHP_RINIT_FUNCTION(oracle);
+PHP_MSHUTDOWN_FUNCTION(oracle);
+PHP_RSHUTDOWN_FUNCTION(oracle);
+PHP_MINFO_FUNCTION(oracle);
+/* }}} */
+
+/* {{{ oracle_functions[]
+ */
+function_entry oracle_functions[] = {
+ PHP_FE(ora_bind, NULL)
+ PHP_FE(ora_close, NULL)
+ PHP_FE(ora_commit, NULL)
+ PHP_FE(ora_commitoff, NULL)
+ PHP_FE(ora_commiton, NULL)
+ PHP_FE(ora_do, NULL)
+ PHP_FE(ora_error, NULL)
+ PHP_FE(ora_errorcode, NULL)
+ PHP_FE(ora_exec, NULL)
+ PHP_FE(ora_fetch, NULL)
+ PHP_FE(ora_fetch_into, second_arg_force_ref)
+ PHP_FE(ora_columntype, NULL)
+ PHP_FE(ora_columnname, NULL)
+ PHP_FE(ora_columnsize, NULL)
+ PHP_FE(ora_getcolumn, NULL)
+ PHP_FE(ora_numcols, NULL)
+ PHP_FE(ora_numrows, NULL)
+ PHP_FE(ora_logoff, NULL)
+ PHP_FE(ora_logon, NULL)
+ PHP_FE(ora_plogon, NULL)
+ PHP_FE(ora_open, NULL)
+ PHP_FE(ora_parse, NULL)
+ PHP_FE(ora_rollback, NULL)
+ {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ oracle_module_entry
+ */
+zend_module_entry oracle_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "oracle",
+ oracle_functions,
+ PHP_MINIT(oracle), /* extension-wide startup function */
+ PHP_MSHUTDOWN(oracle), /* extension-wide shutdown function */
+ PHP_RINIT(oracle), /* per-request startup function */
+ PHP_RSHUTDOWN(oracle), /* per-request shutdown function */
+ PHP_MINFO(oracle),
+ NO_VERSION_YET,
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+/* {{{ ora_func_tab[]
+ */
+static const text *ora_func_tab[] =
+{(text *) "unused",
+/* 1, 2 */ (text *) "unused", (text *) "OSQL",
+/* 3, 4 */ (text *) "unused", (text *) "OEXEC/OEXN",
+/* 5, 6 */ (text *) "unused", (text *) "OBIND",
+/* 7, 8 */ (text *) "unused", (text *) "ODEFIN",
+/* 9, 10 */ (text *) "unused", (text *) "ODSRBN",
+/* 11, 12 */ (text *) "unused", (text *) "OFETCH/OFEN",
+/* 13, 14 */ (text *) "unused", (text *) "OOPEN",
+/* 15, 16 */ (text *) "unused", (text *) "OCLOSE",
+/* 17, 18 */ (text *) "unused", (text *) "unused",
+/* 19, 20 */ (text *) "unused", (text *) "unused",
+/* 21, 22 */ (text *) "unused", (text *) "ODSC",
+/* 23, 24 */ (text *) "unused", (text *) "ONAME",
+/* 25, 26 */ (text *) "unused", (text *) "OSQL3",
+/* 27, 28 */ (text *) "unused", (text *) "OBNDRV",
+/* 29, 30 */ (text *) "unused", (text *) "OBNDRN",
+/* 31, 32 */ (text *) "unused", (text *) "unused",
+/* 33, 34 */ (text *) "unused", (text *) "OOPT",
+/* 35, 36 */ (text *) "unused", (text *) "unused",
+/* 37, 38 */ (text *) "unused", (text *) "unused",
+/* 39, 40 */ (text *) "unused", (text *) "unused",
+/* 41, 42 */ (text *) "unused", (text *) "unused",
+/* 43, 44 */ (text *) "unused", (text *) "unused",
+/* 45, 46 */ (text *) "unused", (text *) "unused",
+/* 47, 48 */ (text *) "unused", (text *) "unused",
+/* 49, 50 */ (text *) "unused", (text *) "unused",
+/* 51, 52 */ (text *) "unused", (text *) "OCAN",
+/* 53, 54 */ (text *) "unused", (text *) "OPARSE",
+/* 55, 56 */ (text *) "unused", (text *) "OEXFET",
+/* 57, 58 */ (text *) "unused", (text *) "OFLNG",
+/* 59, 60 */ (text *) "unused", (text *) "ODESCR",
+/* 61, 62 */ (text *) "unused", (text *) "OBNDRA"
+};
+/* }}} */
+
+#ifdef COMPILE_DL_ORACLE
+ZEND_GET_MODULE(oracle)
+# ifdef PHP_WIN32
+# include "zend_arg_defs.c"
+# endif
+#endif
+
+/* {{{ _close_oraconn
+ */
+static void _close_oraconn(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ oraConnection *conn = (oraConnection *)rsrc->ptr;
+
+ conn->open = 0;
+
+ ologof(&conn->lda);
+ ORA(num_links)--;
+
+ zend_hash_del(ORA(conns),(void*)&conn,sizeof(void*));
+
+ if (conn->persistent) {
+ ORA(num_persistent)--;
+ free(conn);
+ } else {
+ efree(conn);
+ }
+}
+/* }}} */
+
+/* {{{ pval_ora_param_destructor
+ */
+static void
+pval_ora_param_destructor(oraParam *param)
+{
+ if (param->progv) {
+ efree(param->progv);
+ }
+}
+/* }}} */
+
+/* {{{ _close_oracur
+ */
+static int _close_oracur(oraCursor *cur TSRMLS_DC)
+{
+ int i;
+
+ if (cur){
+ if (cur->query){
+ efree(cur->query);
+ }
+ if (cur->params){
+ zend_hash_destroy(cur->params);
+ efree(cur->params);
+ cur->params = NULL;
+ }
+ if (cur->columns){
+ for(i = 0; i < cur->ncols; i++){
+ if (cur->columns[i].buf)
+ efree(cur->columns[i].buf);
+ }
+ efree(cur->columns);
+ cur->columns = NULL;
+ }
+
+ if (cur->open){
+ oraConnection *db_conn;
+
+ if (zend_hash_find(ORA(conns),(void*)&(cur->conn_ptr),sizeof(void*),(void **)&db_conn) == SUCCESS) {
+ oclose(&cur->cda);
+ }
+ }
+
+ efree(cur);
+ }
+
+ return 1;
+}
+/* }}} */
+
+/* {{{ php_close_ora_cursor
+ */
+static void php_close_ora_cursor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ oraCursor *cur = (oraCursor *)rsrc->ptr;
+
+ _close_oracur(cur TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ php_ora_init_globals
+ */
+static void php_ora_init_globals(php_ora_globals *ora_globals_p TSRMLS_DC)
+{
+ if (cfg_get_long("oracle.allow_persistent",
+ &ORA(allow_persistent))
+ == FAILURE) {
+ ORA(allow_persistent) = -1;
+ }
+ if (cfg_get_long("oracle.max_persistent",
+ &ORA(max_persistent))
+ == FAILURE) {
+ ORA(max_persistent) = -1;
+ }
+ if (cfg_get_long("oracle.max_links",
+ &ORA(max_links))
+ == FAILURE) {
+ ORA(max_links) = -1;
+ }
+
+ ORA(num_persistent) = 0;
+
+ ORA(conns) = malloc(sizeof(HashTable));
+ zend_hash_init(ORA(conns), 13, NULL, NULL, 1);
+
+ memset((void*) &ORA(db_err_conn),0,sizeof(ORA(db_err_conn)));
+}
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(oracle)
+{
+#ifdef ZTS
+ ts_allocate_id(&ora_globals_id, sizeof(php_ora_globals), (ts_allocate_ctor) php_ora_init_globals, NULL);
+#else
+ php_ora_init_globals(&ora_globals TSRMLS_CC);
+#endif
+
+ le_cursor = zend_register_list_destructors_ex(php_close_ora_cursor, NULL, "oracle cursor", module_number);
+ le_conn = zend_register_list_destructors_ex(_close_oraconn, NULL, "oracle link", module_number);
+ le_pconn = zend_register_list_destructors_ex(NULL, _close_oraconn, "oracle link persistent", module_number);
+
+ REGISTER_LONG_CONSTANT("ORA_BIND_INOUT", 0, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ORA_BIND_IN", 1, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ORA_BIND_OUT", 2, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("ORA_FETCHINTO_ASSOC",ORA_FETCHINTO_ASSOC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("ORA_FETCHINTO_NULLS",ORA_FETCHINTO_NULLS, CONST_CS | CONST_PERSISTENT);
+
+#ifdef ZTS
+ opinit(OCI_EV_TSF);
+#endif
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RINIT_FUNCTION
+ */
+PHP_RINIT_FUNCTION(oracle)
+{
+ ORA(num_links) =
+ ORA(num_persistent);
+ /*
+ ORA(defaultlrl) = 0;
+ ORA(defaultbinmode) = 0;
+ ORA(defaultconn) = 0;
+ */
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(oracle)
+{
+ zend_hash_destroy(ORA(conns));
+ free(ORA(conns));
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RSHUTDOWN_FUNCTION
+ */
+PHP_RSHUTDOWN_FUNCTION(oracle)
+{
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ _ora_ping
+ */
+static int _ora_ping(oraConnection *conn)
+{
+ Cda_Def cda;
+
+ if (oopen(&cda, &conn->lda, (text *) 0, -1, -1, (text *) 0, -1)) {
+ return 0;
+ }
+
+ if (oparse(&cda, "select sysdate from dual", (sb4) - 1, 0, VERSION_7)) {
+ oclose(&cda);
+ return 0;
+ }
+
+ oclose(&cda);
+ return 1;
+
+}
+/* }}} */
+
+/*
+ ** PHP functions
+*/
+
+/* {{{ proto resource ora_logon(string user, string password)
+ Open an Oracle connection */
+PHP_FUNCTION(ora_logon)
+{
+ ora_do_logon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto resource ora_plogon(string user, string password)
+ Open a persistent Oracle connection */
+PHP_FUNCTION(ora_plogon)
+{
+ ora_do_logon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ ora_do_logon
+ */
+void ora_do_logon(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+{
+ char *user,*passwd;
+ pval **arg1, **arg2;
+ char *hashed_details;
+ int hashed_details_length;
+ oraConnection *db_conn;
+
+ if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_string_ex(arg1);
+ convert_to_string_ex(arg2);
+
+ user = Z_STRVAL_PP(arg1);
+ passwd = Z_STRVAL_PP(arg2);
+
+ hashed_details_length = sizeof("oracle__")-1+strlen(user)+strlen(passwd);
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"oracle_%s_%s",user,passwd);
+
+ if (!ORA(allow_persistent)) {
+ persistent=0;
+ }
+ if (persistent) {
+ list_entry *le;
+
+ /* try to find if we already have this link in our persistent list */
+ if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) { /* we don't */
+ list_entry new_le;
+
+ if (ORA(max_links)!=-1 && ORA(num_links)>=ORA(max_links)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Oracle: Too many open links (%d)",ORA(num_links));
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ if (ORA(max_persistent)!=-1 && ORA(num_persistent)>=ORA(max_persistent)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Oracle: Too many open persistent links (%d)",ORA(num_persistent));
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ /* create the link */
+ db_conn = (oraConnection *)malloc(sizeof(oraConnection));
+ memset((void *) db_conn,0,sizeof(oraConnection));
+ db_conn->persistent = 1;
+
+ if (
+#if HAS_OLOG
+ olog(&db_conn->lda, db_conn->hda, user,strlen(user), passwd, strlen(passwd), 0, -1, OCI_LM_DEF)
+#else
+ orlon(&db_conn->lda, db_conn->hda, user,strlen(user), passwd, strlen(passwd), 0)
+#endif
+ ) {
+ ORA(db_err_conn) = *db_conn;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to connect to ORACLE (%s)",ora_error(&db_conn->lda));
+
+ if (persistent) {
+ free(db_conn);
+ } else {
+ efree(db_conn);
+ }
+
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* hash it up */
+ Z_TYPE(new_le) = le_pconn;
+ new_le.ptr = db_conn;
+ if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry), NULL)==FAILURE) {
+ free(db_conn);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ ORA(num_persistent)++;
+ ORA(num_links)++;
+ zend_hash_add(ORA(conns),(void*)&db_conn,sizeof(void*),(void*)&db_conn,sizeof(void*),NULL);
+ } else { /* we do */
+ if (Z_TYPE_P(le) != le_pconn) {
+ RETURN_FALSE;
+ }
+
+ db_conn = (oraConnection *) le->ptr;
+
+ /* ensure that the link did not die */
+
+ if (!_ora_ping(db_conn)) {
+ if (
+#if HAS_OLOG
+ olog(&db_conn->lda, db_conn->hda, user,strlen(user), passwd, strlen(passwd), 0, -1, OCI_LM_DEF)
+#else
+ orlon(&db_conn->lda, db_conn->hda, user,strlen(user), passwd, strlen(passwd), 0)
+#endif
+ ) {
+ ORA(db_err_conn) = *db_conn;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Oracle: Link to server lost, unable to reconnect",ora_error(&db_conn->lda));
+ zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ }
+ }
+ ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn);
+ } else { /* non persistent */
+ list_entry *index_ptr,new_index_ptr;
+
+ /* first we check the hash for the hashed_details key. if it exists,
+ * it should point us to the right offset where the actual Oracle link sits.
+ * if it doesn't, open a new Oracle link, add it to the resource list,
+ * and add a pointer to it with hashed_details as the key.
+ */
+ if (zend_hash_find(&EG(regular_list),hashed_details,hashed_details_length+1,(void **) &index_ptr)==SUCCESS) {
+ int type,link;
+ void *ptr;
+
+ if (Z_TYPE_P(index_ptr) != le_index_ptr) {
+ RETURN_FALSE;
+ }
+ link = (int) index_ptr->ptr;
+ ptr = zend_list_find(link,&type); /* check if the link is still there */
+ if (ptr && (type==le_conn || type==le_pconn)) {
+ zend_list_addref(link);
+ Z_LVAL_P(return_value) = link;
+ Z_TYPE_P(return_value) = IS_RESOURCE;
+ efree(hashed_details);
+ return;
+ } else {
+ zend_hash_del(&EG(regular_list),hashed_details,hashed_details_length+1);
+ }
+ }
+ if (ORA(max_links)!=-1 && ORA(num_links)>=ORA(max_links)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Oracle: Too many open links (%d)",ORA(num_links));
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ db_conn = (oraConnection *) emalloc(sizeof(oraConnection));
+ memset((void *) db_conn,0,sizeof(oraConnection));
+ db_conn->persistent = 0;
+
+ if (
+#if HAS_OLOG
+ olog(&db_conn->lda, db_conn->hda, user,strlen(user), passwd, strlen(passwd), 0, -1, OCI_LM_DEF)
+#else
+ orlon(&db_conn->lda, db_conn->hda, user,strlen(user), passwd, strlen(passwd), 0)
+#endif
+ ) {
+ ORA(db_err_conn) = *db_conn;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Oracle: Connection Failed: %s\n",ora_error(&db_conn->lda));
+ efree(hashed_details);
+ efree(db_conn);
+ RETURN_FALSE;
+ }
+
+ /* add it to the list */
+ ZEND_REGISTER_RESOURCE(return_value, db_conn, le_conn);
+
+ /* add it to the hash */
+ new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
+ Z_TYPE(new_index_ptr) = le_index_ptr;
+ if (zend_hash_update(&EG(regular_list),hashed_details,hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ zend_hash_add(ORA(conns),(void*)&db_conn,sizeof(void*),(void*)&db_conn,sizeof(void*),NULL);
+ ORA(num_links)++;
+ }
+
+ efree(hashed_details);
+}
+/* }}} */
+
+/* {{{ proto bool ora_logoff(resource connection)
+ Close an Oracle connection */
+PHP_FUNCTION(ora_logoff)
+{ /* conn_index */
+ oraConnection *conn;
+ pval **arg;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ ZEND_FETCH_RESOURCE2(conn, oraConnection *, arg, -1, "Oracle-Connection", le_conn, le_pconn);
+
+ zend_list_delete(Z_LVAL_PP(arg));
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto resource ora_open(resource connection)
+ Open an Oracle cursor */
+PHP_FUNCTION(ora_open)
+{ /* conn_index */
+ pval **arg;
+ oraConnection *conn = NULL;
+ oraCursor *cursor = NULL;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ ZEND_FETCH_RESOURCE2(conn, oraConnection *, arg, -1, "Oracle-Connection", le_conn, le_pconn);
+
+ cursor = (oraCursor *)emalloc(sizeof(oraCursor));
+ memset(cursor, 0, sizeof(oraCursor));
+ if (oopen(&cursor->cda, &conn->lda, (text *) 0, -1, -1, (text *) 0, -1)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open new cursor (%s)",
+ ora_error(&cursor->cda));
+ efree(cursor);
+ RETURN_FALSE;
+ }
+ cursor->open = 1;
+ cursor->conn_ptr = conn;
+ ZEND_REGISTER_RESOURCE(return_value, cursor, le_cursor);
+ cursor->conn_id = Z_LVAL_P(return_value);
+}
+
+/* }}} */
+
+/* {{{ proto bool ora_close(resource cursor)
+ Close an Oracle cursor */
+PHP_FUNCTION(ora_close)
+{ /* conn_index */
+ pval **arg;
+ oraCursor *cursor;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ ZEND_FETCH_RESOURCE(cursor, oraCursor *, arg, -1, "Oracle-Cursor", le_cursor);
+
+ zend_list_delete(Z_LVAL_PP(arg));
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ora_commitoff(resource connection)
+ Disable automatic commit */
+PHP_FUNCTION(ora_commitoff)
+{ /* conn_index */
+ pval **arg;
+ oraConnection *conn;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ ZEND_FETCH_RESOURCE2(conn, oraConnection *, arg, -1, "Oracle-Connection", le_conn, le_pconn);
+
+ if (ocof(&conn->lda)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to turn off auto-commit (%s)",
+ ora_error(&conn->lda));
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ora_commiton(resource connection)
+ Enable automatic commit */
+PHP_FUNCTION(ora_commiton)
+{ /* conn_index */
+ pval **arg;
+ oraConnection *conn;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ ZEND_FETCH_RESOURCE2(conn, oraConnection *, arg, -1, "Oracle-Connection", le_conn, le_pconn);
+
+ if (ocon(&conn->lda)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to turn on auto-commit (%s)",
+ ora_error(&conn->lda));
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ora_commit(resource connection)
+ Commit an Oracle transaction */
+PHP_FUNCTION(ora_commit)
+{ /* conn_index */
+ pval **arg;
+ oraConnection *conn;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ ZEND_FETCH_RESOURCE2(conn, oraConnection *, arg, -1, "Oracle-Connection", le_conn, le_pconn);
+
+ if (ocom(&conn->lda)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to commit transaction (%s)",
+ ora_error(&conn->lda));
+ RETURN_FALSE;
+ }
+ RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ora_rollback(resource connection)
+ Roll back an Oracle transaction */
+PHP_FUNCTION(ora_rollback)
+{ /* conn_index */
+ pval **arg;
+ oraConnection *conn;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ ZEND_FETCH_RESOURCE2(conn, oraConnection *, arg, -1, "Oracle-Connection", le_conn, le_pconn);
+
+ if (orol(&conn->lda)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to roll back transaction (%s)",
+ ora_error(&conn->lda));
+ RETURN_FALSE;
+ }
+ RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ora_parse(resource cursor, string sql_statement [, int defer])
+ Parse an Oracle SQL statement */
+PHP_FUNCTION(ora_parse)
+{
+ pval **curs, **sql, **def;
+ oraCursor *cursor;
+ sword defer = 0;
+ text *query;
+
+ switch (ZEND_NUM_ARGS()) {
+ case 3:
+ zend_get_parameters_ex(3,&curs,&sql,&def);
+ convert_to_long_ex(def);
+ if (Z_LVAL_PP(def)) {
+ defer = DEFER_PARSE;
+ }
+ break;
+ case 2:
+ zend_get_parameters_ex(2,&curs,&sql);
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_string_ex(sql);
+ query = (text *) estrndup(Z_STRVAL_PP(sql),Z_STRLEN_PP(sql));
+
+ if (query == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid query");
+ RETURN_FALSE;
+ }
+
+ if (!(cursor = ora_get_cursor(&EG(regular_list),curs TSRMLS_CC))){
+ efree(query);
+ RETURN_FALSE;
+ }
+
+ if (cursor->query) {
+ efree(cursor->query);
+ }
+
+ cursor->query = query;
+ cursor->fetched = 0;
+
+ if (cursor->params && cursor->nparams > 0){
+ zend_hash_destroy(cursor->params);
+ efree(cursor->params);
+ cursor->params = NULL;
+ cursor->nparams = 0;
+ }
+
+ if (oparse(&cursor->cda, query, (sb4) - 1, defer, VERSION_7)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Parse failed (%s)",ora_error(&cursor->cda));
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ora_bind(resource cursor, string php_variable_name, string sql_parameter_name, int length [, int type])
+ Bind a PHP variable to an Oracle parameter */
+PHP_FUNCTION(ora_bind)
+{
+ pval **curs, **pvar, **svar, **plen, **ptyp;
+ int inout = 0;
+ oraParam *newparam, *paramptr;
+ oraCursor *cursor;
+ char *paramname;
+
+ switch (ZEND_NUM_ARGS()) {
+ case 5:
+ zend_get_parameters_ex(5,&curs,&pvar,&svar,&plen,&ptyp);
+ convert_to_long_ex(ptyp);
+ inout = Z_LVAL_PP(ptyp);
+ break;
+ case 4:
+ zend_get_parameters_ex(4,&curs,&pvar,&svar,&plen);
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ }
+
+ cursor = ora_get_cursor(&EG(regular_list), curs TSRMLS_CC);
+ if (cursor == NULL) {
+ RETURN_FALSE;
+ }
+
+ convert_to_string_ex(pvar);
+ convert_to_string_ex(svar);
+ convert_to_long_ex(plen);
+
+ if (cursor->params == NULL) {
+ ALLOC_HASHTABLE(cursor->params);
+ if (!cursor->params ||
+ zend_hash_init(cursor->params, 19, NULL,
+ HASH_DTOR pval_ora_param_destructor, 0) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to initialize parameter list");
+ RETURN_FALSE;
+ }
+ }
+ newparam = (oraParam *)emalloc(sizeof(oraParam));
+
+ if ((paramname = estrndup(Z_STRVAL_PP(pvar), Z_STRLEN_PP(pvar))) == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Out of memory for parametername");
+ efree(newparam);
+ RETURN_FALSE;
+ }
+
+ if (zend_hash_add(cursor->params, paramname, Z_STRLEN_PP(pvar) + 1,
+ newparam, sizeof(oraParam), (void **)&paramptr) == FAILURE) {
+ /* XXX zend_hash_destroy */
+ efree(paramname);
+ efree(newparam);
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not make parameter placeholder");
+ RETURN_FALSE;
+ }
+
+ efree(newparam);
+ efree(paramname);
+
+ paramptr->progvl = Z_LVAL_PP(plen) + 1;
+ paramptr->inout = inout;
+
+ paramptr->progv = (text *)emalloc(paramptr->progvl);
+
+/* XXX Maximum for progvl */
+ paramptr->alen = paramptr->progvl;
+
+ if (obndra(&cursor->cda,
+ Z_STRVAL_PP(svar),
+ -1,
+ (ub1 *)paramptr->progv,
+ paramptr->progvl,
+ SQLT_STR, /* ftype */
+ -1, /* scale */
+ 0/*&paramptr->ind*/, /* ind */
+ &paramptr->alen, /* alen */
+ 0 /*&paramptr->arcode*/,
+ 0, /* maxsize */
+ 0,
+ 0,
+ -1,
+ -1)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Bind failed (%s)",
+ ora_error(&cursor->cda));
+ RETURN_FALSE;
+ }
+
+ cursor->nparams++;
+ RETURN_TRUE;
+}
+/* }}} */
+
+/*
+ XXX Make return values compatible with old module ?
+ */
+/* {{{ proto bool ora_exec(resource cursor)
+ Execute a parsed statement */
+PHP_FUNCTION(ora_exec)
+{ /* cursor_index */
+ pval **arg;
+ oraCursor *cursor = NULL;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE)
+ WRONG_PARAM_COUNT;
+
+ if ((cursor = ora_get_cursor(&EG(regular_list), arg TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ if (cursor->cda.ft == FT_SELECT) {
+ if (ora_describe_define(cursor) < 0) {
+ /* error message is given by ora_describe_define() */
+ RETURN_FALSE;
+ }
+ }
+
+ if(cursor->nparams > 0){
+ if(!ora_set_param_values(cursor, 0 TSRMLS_CC)){
+ RETURN_FALSE;
+ }
+ }
+
+ if (oexec(&cursor->cda)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Exec failed (%s)",
+ ora_error(&cursor->cda));
+ RETURN_FALSE;
+ }
+
+ if(cursor->nparams > 0){
+ if(!ora_set_param_values(cursor, 1 TSRMLS_CC)){
+ RETURN_FALSE;
+ }
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_numcols(resource cursor)
+ Returns the numbers of columns in a result */
+PHP_FUNCTION(ora_numcols)
+{ /* cursor_index */
+ pval **arg;
+ oraCursor *cursor = NULL;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE)
+ WRONG_PARAM_COUNT;
+
+ if ((cursor = ora_get_cursor(&EG(regular_list), arg TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(cursor->ncols);
+}
+/* }}} */
+
+/* {{{ proto int ora_numrows(resource cursor)
+ Returns the number of rows in a result */
+PHP_FUNCTION(ora_numrows)
+{ /* cursor_index */
+ pval **arg;
+ oraCursor *cursor = NULL;
+
+ if(zend_get_parameters_ex(1, &arg) == FAILURE)
+ WRONG_PARAM_COUNT;
+
+ if((cursor = ora_get_cursor(&EG(regular_list), arg TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(cursor->cda.rpc);
+}
+/* }}} */
+
+/* prepares/executes/fetches 1st row if avail*/
+/* {{{ proto resource ora_do(resource connection, resource cursor)
+ Parse and execute a statement and fetch first result row */
+PHP_FUNCTION(ora_do)
+{
+ pval **con,**sql;
+ oraConnection *conn = NULL;
+ oraCursor *cursor = NULL;
+ text *query;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &con,&sql) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ ZEND_FETCH_RESOURCE2(conn, oraConnection *, con, -1, "Oracle-Connection", le_conn, le_pconn);
+
+ convert_to_string_ex(sql);
+
+ cursor = (oraCursor *)emalloc(sizeof(oraCursor));
+
+ memset(cursor, 0, sizeof(oraCursor));
+
+ query = (text *) estrndup(Z_STRVAL_PP(sql),Z_STRLEN_PP(sql));
+
+ if (query == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid query in Ora_Do");
+ RETURN_FALSE;
+ }
+
+ cursor->query = query;
+
+ if (oopen(&cursor->cda, &conn->lda, (text *) 0, -1, -1, (text *) 0, -1)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open new cursor (%s)",
+ ora_error(&cursor->cda));
+ efree(cursor);
+ RETURN_FALSE;
+ }
+ cursor->open = 1;
+ cursor->conn_ptr = conn;
+ cursor->conn_id = Z_LVAL_PP(con);
+
+ /* Prepare stmt */
+
+ if (oparse(&cursor->cda, query, (sb4) - 1, 1, VERSION_7)){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Do failed (%s)",
+ ora_error(&cursor->cda));
+ _close_oracur(cursor TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ /* Execute stmt (and fetch 1st row for selects) */
+ if (cursor->cda.ft == FT_SELECT) {
+ if (ora_describe_define(cursor) < 0){
+ /* error message is given by ora_describe_define() */
+ _close_oracur(cursor TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ if (oexfet(&cursor->cda, 1, 0, 0)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Do failed (%s)",
+ ora_error(&cursor->cda));
+ _close_oracur(cursor TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ cursor->fetched = 1;
+ } else {
+ if (oexec(&cursor->cda)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Do failed (%s)",
+ ora_error(&cursor->cda));
+ _close_oracur(cursor TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ }
+
+ ZEND_REGISTER_RESOURCE(return_value, cursor, le_cursor);
+}
+/* }}} */
+
+/* {{{ proto bool ora_fetch(resource cursor)
+ Fetch a row of result data from a cursor */
+PHP_FUNCTION(ora_fetch)
+{ /* cursor_index */
+ pval **arg;
+ oraCursor *cursor;
+
+ if (zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((cursor = ora_get_cursor(&EG(regular_list), arg TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ if (cursor->ncols == 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available on this cursor");
+ RETURN_FALSE;
+ }
+
+ /* Get data from Oracle */
+ if (ofetch(&cursor->cda)) {
+ if (cursor->cda.rc != NO_DATA_FOUND) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Fetch failed (%s)",
+ ora_error(&cursor->cda));
+ }
+ RETURN_FALSE;
+ }
+ cursor->fetched++;
+ RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_fetch_into(resource cursor, array result [, int flags])
+ Fetch a row into the specified result array */
+PHP_FUNCTION(ora_fetch_into)
+{
+ pval **curs, **arr, **flg, *tmp;
+ oraCursor *cursor;
+ int i;
+ int flags = 0;
+
+ switch(ZEND_NUM_ARGS()){
+ case 2:
+ zend_get_parameters_ex(2, &curs, &arr);
+ break;
+
+ case 3:
+ zend_get_parameters_ex(3, &curs, &arr, &flg);
+ convert_to_long_ex(flg);
+ flags = Z_LVAL_PP(flg);
+ break;
+
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ /* Find the cursor */
+ if ((cursor = ora_get_cursor(&EG(regular_list), curs TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ if (cursor->ncols == 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available on this cursor");
+ RETURN_FALSE;
+ }
+
+ if (ofetch(&cursor->cda)) {
+ if (cursor->cda.rc != NO_DATA_FOUND) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Fetch_Into failed (%s)",ora_error(&cursor->cda));
+ }
+ RETURN_FALSE;
+ }
+ cursor->fetched++;
+
+ if (Z_TYPE_PP(arr) != IS_ARRAY){
+ pval_destructor(*arr);
+ array_init(*arr);
+ }
+ zend_hash_internal_pointer_reset(Z_ARRVAL_PP(arr));
+
+ for (i = 0; i < cursor->ncols; i++) {
+ if (cursor->columns[i].col_retcode == 1405) {
+ if (!(flags&ORA_FETCHINTO_NULLS)){
+ continue; /* don't add anything for NULL columns, unless the calles wants it */
+ } else {
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_NULL(tmp);
+ }
+ } else if (cursor->columns[i].col_retcode != 0 &&
+ cursor->columns[i].col_retcode != 1406) {
+ /* So error fetching column. The most common is 1405, a NULL */
+ /* was retreived. 1406 is ASCII or string buffer data was */
+ /* truncated. The converted data from the database did not fit */
+ /* into the buffer. Since we allocated the buffer to be large */
+ /* enough, this should not occur. Anyway, we probably want to */
+ /* return what we did get, in that case */
+ RETURN_FALSE;
+ } else {
+ MAKE_STD_ZVAL(tmp);
+
+ Z_TYPE_P(tmp) = IS_STRING;
+ Z_STRLEN_P(tmp) = 0;
+
+ switch(cursor->columns[i].dbtype) {
+ case SQLT_LNG:
+ case SQLT_LBI:
+ {
+ ub4 ret_len;
+ int offset = cursor->columns[i].col_retlen;
+ sb2 result;
+
+ if (cursor->columns[i].col_retcode == 1406) { /* truncation -> get the rest! */
+ while (1) {
+ cursor->columns[i].buf = erealloc(cursor->columns[i].buf,offset + DB_SIZE + 1);
+
+ if (! cursor->columns[i].buf) {
+ offset = 0;
+ break;
+ }
+
+ result = oflng(&cursor->cda,
+ (sword)(i + 1),
+ cursor->columns[i].buf + offset,
+ DB_SIZE,
+ 1,
+ &ret_len,
+ offset);
+ if (result) {
+ break;
+ }
+
+ if (ret_len <= 0) {
+ break;
+ }
+
+ offset += ret_len;
+ }
+ }
+ if (cursor->columns[i].buf && offset) {
+ Z_STRLEN_P(tmp) = offset;
+ } else {
+ Z_STRLEN_P(tmp) = 0;
+ }
+ }
+ break;
+ default:
+ Z_STRLEN_P(tmp) = min(cursor->columns[i].col_retlen,
+ cursor->columns[i].dsize);
+ break;
+ }
+ Z_STRVAL_P(tmp) = estrndup(cursor->columns[i].buf,Z_STRLEN_P(tmp));
+ }
+
+ if (flags&ORA_FETCHINTO_ASSOC){
+ zend_hash_update(Z_ARRVAL_PP(arr), cursor->columns[i].cbuf, cursor->columns[i].cbufl+1, (void *) &tmp, sizeof(pval*), NULL);
+ } else {
+ zend_hash_index_update(Z_ARRVAL_PP(arr), i, (void *) &tmp, sizeof(pval*), NULL);
+ }
+
+ }
+
+ RETURN_LONG(cursor->ncols);
+}
+/* }}} */
+
+/* {{{ proto string ora_columnname(resource cursor, int column)
+ Get the name of an Oracle result column */
+PHP_FUNCTION(ora_columnname)
+{ /* cursor_index, column_index */
+ pval **curs, **col;
+ oraCursor *cursor = NULL;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &curs, &col) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((cursor = ora_get_cursor(&EG(regular_list), curs TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ convert_to_long_ex(col);
+
+ if (cursor->ncols == 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this cursor index");
+ RETURN_FALSE;
+ }
+
+ if (Z_LVAL_PP(col) >= cursor->ncols){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index larger than number of columns");
+ RETURN_FALSE;
+ }
+
+ if (Z_LVAL_PP(col) < 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column numbering starts at 0");
+ RETURN_FALSE;
+ }
+
+ RETURN_STRINGL(cursor->columns[Z_LVAL_PP(col)].cbuf,
+ cursor->columns[Z_LVAL_PP(col)].cbufl,1);
+}
+/* }}} */
+
+/* {{{ proto string ora_columntype(resource cursor, int column)
+ Get the type of an Oracle result column */
+PHP_FUNCTION(ora_columntype)
+{ /* cursor_index, column_index */
+ pval **curs, **col;
+ int colno;
+ oraCursor *cursor = NULL;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &curs, &col) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((cursor = ora_get_cursor(&EG(regular_list), curs TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ convert_to_long_ex(col);
+ colno = Z_LVAL_PP(col);
+
+ if (cursor->ncols == 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this cursor index");
+ RETURN_FALSE;
+ }
+
+ if (colno >= cursor->ncols){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index larger than number of columns");
+ RETURN_FALSE;
+ }
+
+ if (colno < 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column numbering starts at 0");
+ RETURN_FALSE;
+ }
+
+ switch (cursor->columns[colno].dbtype) {
+ case SQLT_CHR:
+ RETURN_STRINGL("VARCHAR2", 8, 1);
+ case SQLT_VCS:
+ case SQLT_AVC:
+ RETURN_STRINGL("VARCHAR", 7, 1);
+ case SQLT_STR:
+ case SQLT_AFC:
+ RETURN_STRINGL("CHAR", 4, 1);
+ case SQLT_NUM: case SQLT_INT:
+ case SQLT_FLT: case SQLT_UIN:
+ RETURN_STRINGL("NUMBER", 6, 1);
+ case SQLT_LNG:
+ RETURN_STRINGL("LONG", 4, 1);
+ case SQLT_LBI:
+ RETURN_STRINGL("LONG RAW", 8, 1);
+ case SQLT_RID:
+ RETURN_STRINGL("ROWID", 5, 1);
+ case SQLT_DAT:
+ RETURN_STRINGL("DATE", 4, 1);
+#ifdef SQLT_CUR
+ case SQLT_CUR:
+ RETURN_STRINGL("CURSOR", 6, 1);
+#endif
+ default:
+ {
+ char numbuf[21];
+ snprintf(numbuf, 20, "UNKNOWN(%d)", cursor->columns[colno].dbtype);
+ numbuf[20] = '\0';
+ RETVAL_STRING(numbuf,1);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto int ora_columnsize(int cursor, int column)
+ Return the size of the column */
+PHP_FUNCTION(ora_columnsize)
+{ /* cursor_index, column_index */
+ pval **curs, **col;
+ oraCursor *cursor = NULL;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &curs, &col) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ /* Find the cursor */
+ if ((cursor = ora_get_cursor(&EG(regular_list), curs TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ convert_to_long_ex(col);
+
+ if (cursor->ncols == 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this cursor index");
+ RETURN_FALSE;
+ }
+
+ if (Z_LVAL_PP(col) >= cursor->ncols){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index larger than number of columns");
+ RETURN_FALSE;
+ }
+
+ if (Z_LVAL_PP(col) < 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column numbering starts at 0");
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(cursor->columns[Z_LVAL_PP(col)].dbsize);
+}
+/* }}} */
+
+/* {{{ proto mixed ora_getcolumn(resource cursor, int column)
+ Get data from a fetched row */
+PHP_FUNCTION(ora_getcolumn)
+{ /* cursor_index, column_index */
+ pval **curs,**col;
+ int colno;
+ oraCursor *cursor = NULL;
+ oraColumn *column = NULL;
+ int len;
+ sb2 type;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &curs, &col) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((cursor = ora_get_cursor(&EG(regular_list), curs TSRMLS_CC)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ if (cursor->ncols == 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this cursor index");
+ RETURN_FALSE;
+ }
+
+ convert_to_long_ex(col);
+ colno = Z_LVAL_PP(col);
+
+ if (colno >= cursor->ncols){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column index larger than number of columns");
+ RETURN_FALSE;
+ }
+
+ if (colno < 0){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Column numbering starts at 0");
+ RETURN_FALSE;
+ }
+
+ if (cursor->fetched == 0){
+ if (ofetch(&cursor->cda)) {
+ if (cursor->cda.rc != NO_DATA_FOUND) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_Fetch failed (%s)",
+ ora_error(&cursor->cda));
+ }
+ RETURN_FALSE;
+ }
+ cursor->fetched++;
+ }
+
+ column = &cursor->columns[colno];
+
+ type = column->dbtype;
+
+ if (column->col_retcode == 1405) {
+ RETURN_NULL();
+ }
+
+ if (column->col_retcode != 0 && column->col_retcode != 1406) {
+ /* So error fetching column. The most common is 1405, a NULL
+ * was retreived. 1406 is ASCII or string buffer data was
+ * truncated. The converted data from the database did not fit
+ * into the buffer. Since we allocated the buffer to be large
+ * enough, this should not occur. Anyway, we probably want to
+ * return what we did get, in that case
+ */
+ RETURN_FALSE;
+ } else {
+ switch(type) {
+ case SQLT_CHR:
+ case SQLT_NUM:
+ case SQLT_INT:
+ case SQLT_FLT:
+ case SQLT_STR:
+ case SQLT_UIN:
+ case SQLT_AFC:
+ case SQLT_AVC:
+ case SQLT_DAT:
+ len = min(column->col_retlen, column->dsize);
+ RETURN_STRINGL(column->buf,len,1);
+
+ case SQLT_LNG:
+ case SQLT_LBI:
+ {
+ ub4 ret_len;
+ int offset = column->col_retlen;
+ sb2 result;
+
+ if (column->col_retcode == 1406) { /* truncation -> get the rest! */
+ while (1) {
+ column->buf = erealloc(column->buf,offset + DB_SIZE + 1);
+
+ if (! column->buf) {
+ offset = 0;
+ break;
+ }
+
+ result = oflng(&cursor->cda,
+ (sword)(colno + 1),
+ column->buf + offset,
+ DB_SIZE,
+ 1,
+ &ret_len,
+ offset);
+ if (result) {
+ break;
+ }
+
+ if (ret_len <= 0) {
+ break;
+ }
+
+ offset += ret_len;
+ }
+ }
+ if (column->buf && offset) {
+ RETURN_STRINGL(column->buf, offset, 1);
+ } else {
+ RETURN_FALSE;
+ }
+ }
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Ora_GetColumn found invalid type (%d)", type);
+ RETURN_FALSE;
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto string ora_error(resource cursor_or_connection)
+ Get an Oracle error message */
+PHP_FUNCTION(ora_error)
+{
+ pval **arg;
+ oraCursor *cursor;
+ oraConnection *conn;
+ void *res;
+ int what;
+ int argc = ZEND_NUM_ARGS();
+
+ if (argc < 0 || argc >> 1 || zend_get_parameters_ex(argc, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (argc == 1) {
+ res = zend_fetch_resource(arg TSRMLS_CC, -1,"Oracle-Connection/Cursor",&what,3,le_conn, le_pconn, le_cursor);
+ ZEND_VERIFY_RESOURCE(res);
+
+ if (what == le_cursor) {
+ cursor = (oraCursor *) res;
+ RETURN_STRING(ora_error(&cursor->cda),1);
+ } else {
+ conn = (oraConnection *) res;
+ RETURN_STRING(ora_error(&conn->lda),1);
+ }
+ } else {
+ RETURN_STRING(ora_error(&ORA(db_err_conn).lda),1);
+ }
+}
+/* }}} */
+
+/* {{{ proto int ora_errorcode(resource cursor_or_connection)
+ Get an Oracle error code */
+PHP_FUNCTION(ora_errorcode)
+{
+ pval **arg;
+ oraCursor *cursor;
+ oraConnection *conn;
+ void *res;
+ int what;
+ int argc = ZEND_NUM_ARGS();
+
+ if (argc < 0 || argc >> 1 || zend_get_parameters_ex(argc, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (argc == 1) {
+ res = zend_fetch_resource(arg TSRMLS_CC, -1,"Oracle-Connection/Cursor",&what,3,le_conn, le_pconn, le_cursor);
+ ZEND_VERIFY_RESOURCE(res);
+
+ if (what == le_cursor) {
+ cursor = (oraCursor *) res;
+ RETURN_LONG(cursor->cda.rc);
+ } else {
+ conn = (oraConnection *) res;
+ RETURN_LONG(conn->lda.rc);
+ }
+ } else {
+ RETURN_LONG(ORA(db_err_conn).lda.rc);
+ }
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(oracle)
+{
+ php_info_print_table_start();
+ php_info_print_table_row(2, "Oracle Support", "enabled");
+#ifndef PHP_WIN32
+ php_info_print_table_row(2, "Oracle Version", PHP_ORACLE_VERSION );
+ php_info_print_table_row(2, "Compile-time ORACLE_HOME", PHP_ORACLE_DIR );
+ php_info_print_table_row(2, "Libraries Used", PHP_ORACLE_SHARED_LIBADD );
+#endif
+ php_info_print_table_end();
+}
+/* }}} */
+
+/*
+** Functions internal to this module.
+*/
+
+/* {{{ ora_get_cursor
+ */
+static oraCursor *
+ora_get_cursor(HashTable *list, pval **ind TSRMLS_DC)
+{
+ oraCursor *cursor;
+ oraConnection *db_conn;
+
+ cursor = (oraCursor *) zend_fetch_resource(ind TSRMLS_CC, -1, "Oracle-Cursor", NULL, 1, le_cursor);
+ if (! cursor) {
+ return NULL;
+ }
+
+ if (zend_hash_find(ORA(conns),(void*)&(cursor->conn_ptr),sizeof(void*),(void **)&db_conn) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection already closed for cursor index %d", ind);
+ return NULL;
+ }
+
+ return cursor;
+}
+/* }}} */
+
+/* {{{ ora_error
+ */
+static char *
+ora_error(Cda_Def * cda)
+{
+ sword n, l;
+ static text errmsg[ 512 ];
+
+ n = oerhms(cda, cda->rc, errmsg, 400);
+
+ /* remove the last newline */
+ l = strlen(errmsg);
+ if (l < 400 && errmsg[l - 1] == '\n') {
+ errmsg[l - 1] = '\0';
+ l--;
+ }
+ if (cda->fc > 0) {
+ strcat(errmsg, " -- while processing OCI function ");
+ strncat(errmsg, ora_func_tab[cda->fc], 75); /* 512 - 400 - 36 */
+ }
+ return (char *) errmsg;
+}
+/* }}} */
+
+/* {{{ ora_describe_define
+ */
+static sword
+ora_describe_define(oraCursor * cursor)
+{
+ long col = 0;
+ int i;
+ sb2 type;
+ sb4 dbsize;
+ TSRMLS_FETCH();
+
+ if (cursor == NULL) {
+ return -1;
+ }
+
+ if (cursor->columns) {
+ for(i = 0; i < cursor->ncols; i++){
+ if (cursor->columns[i].buf)
+ efree(cursor->columns[i].buf);
+ }
+ efree(cursor->columns);
+ }
+
+ cursor->ncols = 0;
+
+ while(1){
+ if (odescr(&cursor->cda, (sword) cursor->ncols + 1, &dbsize, (sb2 *)0, (sb1 *)0,
+ (sb4 *)0, (sb4 *)0, (sb2 *)0, (sb2 *)0, (sb2 *)0)){
+ if (cursor->cda.rc == VAR_NOT_IN_LIST) {
+ break;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ora_error(&cursor->cda));
+ cursor->ncols = 0;
+ return -1;
+ }
+ }
+ cursor->ncols++;
+ }
+
+ if (cursor->ncols > 0){
+ cursor->columns = (oraColumn *) safe_emalloc(sizeof(oraColumn), cursor->ncols, 0);
+ memset(cursor->columns,0,sizeof(oraColumn) * cursor->ncols);
+ }
+
+ for(col = 0; col < cursor->ncols; col++){
+ cursor->columns[col].cbufl = ORANAMELEN;
+
+ if (odescr(&cursor->cda, (sword)col + 1, &cursor->columns[col].dbsize,
+ &cursor->columns[col].dbtype, &cursor->columns[col].cbuf[0],
+ &cursor->columns[col].cbufl, &cursor->columns[col].dsize,
+ &cursor->columns[col].prec, &cursor->columns[col].scale,
+ &cursor->columns[col].nullok)) {
+ if (cursor->cda.rc == VAR_NOT_IN_LIST) {
+ break;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ora_error(&cursor->cda));
+ return -1;
+ }
+ }
+
+ cursor->columns[col].cbuf[cursor->columns[col].cbufl] = '\0';
+
+ switch (cursor->columns[col].dbtype) {
+ case SQLT_LBI:
+ cursor->columns[col].dsize = DB_SIZE;
+ type = SQLT_LBI;
+ break;
+ case SQLT_LNG:
+ cursor->columns[col].dsize = DB_SIZE;
+ default:
+ type = SQLT_STR;
+ break;
+ }
+
+ cursor->columns[col].buf = (ub1 *) emalloc(cursor->columns[col].dsize + 1);
+
+ /* Define an output variable for the column */
+ if (odefin(&cursor->cda, (sword)col + 1, cursor->columns[col].buf,
+ cursor->columns[col].dsize + 1, type, -1, &cursor->columns[col].indp,
+ (text *) 0, -1, -1, &cursor->columns[col].col_retlen,
+ &cursor->columns[col].col_retcode)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ora_error(&cursor->cda));
+ return -1;
+ }
+ }
+ return 1;
+}
+/* }}} */
+
+/* {{{ ora_set_param_values
+ */
+int ora_set_param_values(oraCursor *cursor, int isout TSRMLS_DC)
+{
+ char *paramname;
+ oraParam *param;
+ pval **pdata;
+ int i, len, plen;
+
+ zend_hash_internal_pointer_reset(cursor->params);
+
+ if(zend_hash_num_elements(cursor->params) != cursor->nparams){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Mismatch in number of parameters");
+ return 0;
+ }
+
+ for(i = 0; i < cursor->nparams; i++, zend_hash_move_forward(cursor->params)){
+ if(zend_hash_get_current_key(cursor->params, &paramname, NULL, 0) != HASH_KEY_IS_STRING){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't get parameter name");
+ return 0;
+ }
+
+ if(zend_hash_get_current_data(cursor->params, (void **)&param) == FAILURE){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't get parameter data");
+ return 0;
+ }
+
+ if(isout){
+ SET_VAR_STRINGL(paramname, estrdup(param->progv), strlen(param->progv));
+ continue;
+ }
+
+ /* doing the in-loop */
+
+ if (zend_hash_find(&EG(symbol_table), paramname, strlen(paramname) + 1, (void **)&pdata) == FAILURE){
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't find variable for parameter");
+ return 0;
+ }
+
+ convert_to_string(*pdata);
+ plen = Z_STRLEN_PP(pdata);
+
+ if (param->progvl <= plen){
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Input value will be truncated");
+ }
+
+ len = min(param->progvl - 1, plen);
+
+ strncpy(param->progv, Z_STRVAL_PP(pdata), len);
+ param->progv[len] = '\0';
+ }
+
+ return 1;
+}
+/* }}} */
+
+#endif /* HAVE_ORACLE */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */