summaryrefslogtreecommitdiff
path: root/ext/oracle/oracle.c
diff options
context:
space:
mode:
authorStig Bakken <ssb@php.net>1999-04-21 22:49:16 +0000
committerStig Bakken <ssb@php.net>1999-04-21 22:49:16 +0000
commitf67a9bdc52c39eed6837aef8a1eca195549b1469 (patch)
tree0a7be5c5b405910f4d616df0d9bed82196d3c966 /ext/oracle/oracle.c
parent96660d9a8ce06f12f186d0e3bb5697ce747182a5 (diff)
downloadphp-git-f67a9bdc52c39eed6837aef8a1eca195549b1469.tar.gz
moved dav, msql and oracle to ext/
Diffstat (limited to 'ext/oracle/oracle.c')
-rw-r--r--ext/oracle/oracle.c1715
1 files changed, 1715 insertions, 0 deletions
diff --git a/ext/oracle/oracle.c b/ext/oracle/oracle.c
new file mode 100644
index 0000000000..780750fbf7
--- /dev/null
+++ b/ext/oracle/oracle.c
@@ -0,0 +1,1715 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@guardian.no> |
+ | Mitch Golden <mgolden@interport.net> |
+ | Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ | Andreas Karajannis <Andreas.Karajannis@gmd.de> |
+ +----------------------------------------------------------------------+
+ */
+#if defined(COMPILE_DL)
+# if PHP_31
+# include "../phpdl.h"
+# else
+# ifdef THREAD_SAFE
+# undef THREAD_SAFE
+# endif
+# include "dl/phpdl.h"
+# endif
+#endif
+#include "php.h"
+#include "oracle.h"
+
+#if HAVE_ORACLE
+#if !(WIN32|WINNT)
+#include "build-defs.h"
+#endif
+#include "snprintf.h"
+#include "zend_globals.h"
+
+#ifndef min
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+#ifdef THREAD_SAFE
+
+void *oracle_mutex;
+DWORD ORACLETls;
+static int numthreads=0;
+
+typedef struct oracle_global_struct {
+ oracle_module php3_oracle_module;
+} oracle_global_struct;
+
+#define ORACLE_GLOBAL(a) oracle_globals->a
+
+#define ORACLE_TLS_VARS \
+ oracle_global_struct *oracle_globals = TlsGetValue(ORACLETls);
+
+#else
+oracle_module php3_oracle_module;
+#define ORACLE_GLOBAL(a) a
+#define ORACLE_TLS_VARS
+#endif
+
+#undef ORACLE_DEBUG
+
+#define DB_SIZE 65536
+
+static oraConnection *ora_get_conn(HashTable *, int);
+static int ora_add_cursor(HashTable *, oraCursor *);
+static oraCursor *ora_get_cursor(HashTable *, int);
+static void ora_del_cursor(HashTable *, int);
+static char *ora_error(Cda_Def *);
+static int ora_describe_define(oraCursor *);
+static int _cursors_cleanup(list_entry *le);
+static void _close_oraconn(oraConnection *conn);
+static void _close_orapconn(oraConnection *conn);
+static void _close_oracur(oraCursor *cur);
+static int _ora_ping(oraConnection *conn);
+int ora_set_param_values(oraCursor *cursor, int isout);
+
+void php3_Ora_Do_Logon(INTERNAL_FUNCTION_PARAMETERS, int persistent);
+
+function_entry oracle_functions[] = {
+ {"ora_bind", php3_Ora_Bind, NULL},
+ {"ora_close", php3_Ora_Close, NULL},
+ {"ora_commit", php3_Ora_Commit, NULL},
+ {"ora_commitoff", php3_Ora_CommitOff, NULL},
+ {"ora_commiton", php3_Ora_CommitOn, NULL},
+ {"ora_do", php3_Ora_Do, NULL},
+ {"ora_error", php3_Ora_Error, NULL},
+ {"ora_errorcode", php3_Ora_ErrorCode, NULL},
+ {"ora_exec", php3_Ora_Exec, NULL},
+ {"ora_fetch", php3_Ora_Fetch, NULL},
+ {"ora_fetch_into", php3_Ora_FetchInto, NULL},
+ {"ora_columntype", php3_Ora_ColumnType, NULL},
+ {"ora_columnname", php3_Ora_ColumnName, NULL},
+ {"ora_columnsize", php3_Ora_ColumnSize, NULL},
+ {"ora_getcolumn", php3_Ora_GetColumn, NULL},
+ {"ora_numcols", php3_Ora_NumCols, NULL},
+ {"ora_numrows", php3_Ora_NumRows, NULL},
+ {"ora_logoff", php3_Ora_Logoff, NULL},
+ {"ora_logon", php3_Ora_Logon, NULL},
+ {"ora_plogon", php3_Ora_PLogon, NULL},
+ {"ora_open", php3_Ora_Open, NULL},
+ {"ora_parse", php3_Ora_Parse, NULL},
+ {"ora_rollback", php3_Ora_Rollback, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry oracle_module_entry = {
+ "Oracle",
+ oracle_functions,
+ php3_minit_oracle,
+ php3_mshutdown_oracle,
+ php3_rinit_oracle,
+ NULL,
+ php3_info_oracle,
+ STANDARD_MODULE_PROPERTIES
+};
+
+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"
+};
+
+#if COMPILE_DL
+DLEXPORT php3_module_entry *get_module() { return &oracle_module_entry; };
+#endif
+
+static int _cursors_cleanup(list_entry *le)
+{
+ ORACLE_TLS_VARS;
+
+ if (le->type == ORACLE_GLOBAL(php3_oracle_module).le_cursor){
+ oraCursor *curs = ((oraCursor *) le->ptr);
+ oraConnection *conn = curs->conn_ptr;
+
+ if ((!(conn->open)) && (curs->open > 0)){
+ oclose(&curs->cda);
+ curs->open = 0;
+ }
+ }
+ return 0;
+}
+
+static void _close_oraconn(oraConnection *conn)
+{
+ ORACLE_TLS_VARS;
+
+ conn->open = 0;
+ _php3_hash_apply(ORACLE_GLOBAL(php3_oracle_module).resource_list,
+ (int (*)(void *))_cursors_cleanup);
+
+ ologof(&conn->lda);
+ ORACLE_GLOBAL(php3_oracle_module).num_links--;
+ efree(conn);
+}
+
+static void _close_orapconn(oraConnection *conn)
+{
+ ORACLE_TLS_VARS;
+
+ conn->open = 0;
+ _php3_hash_apply(ORACLE_GLOBAL(php3_oracle_module).resource_plist,
+ (int (*)(void *))_cursors_cleanup);
+
+ ologof(&conn->lda);
+ free(conn);
+ ORACLE_GLOBAL(php3_oracle_module).num_links--;
+ ORACLE_GLOBAL(php3_oracle_module).num_persistent--;
+}
+
+static void _close_oracur(oraCursor *cur)
+{
+ int i;
+
+ if (cur){
+ if (cur->query){
+ efree(cur->query);
+ }
+ if (cur->params){
+ _php3_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){
+ oclose(&cur->cda);
+ cur->open = 0;
+ }
+ efree(cur);
+ }
+}
+
+int php3_minit_oracle(INIT_FUNC_ARGS)
+{
+#if defined(THREAD_SAFE)
+ oracle_global_struct *oracle_globals;
+ PHP3_MUTEX_ALLOC(oracle_mutex);
+ PHP3_MUTEX_LOCK(oracle_mutex);
+ numthreads++;
+ if (numthreads==1){
+ if (!PHP3_TLS_PROC_STARTUP(ORACLETls)){
+ PHP3_MUTEX_UNLOCK(oracle_mutex);
+ PHP3_MUTEX_FREE(oracle_mutex);
+ return FAILURE;
+ }
+ }
+ PHP3_MUTEX_UNLOCK(oracle_mutex);
+ if(!PHP3_TLS_THREAD_INIT(ORACLETls,oracle_globals,oracle_global_struct)){
+ PHP3_MUTEX_FREE(oracle_mutex);
+ return FAILURE;
+ }
+#endif
+
+ ORACLE_GLOBAL(php3_oracle_module).le_conn =
+ register_list_destructors(_close_oraconn,NULL);
+ ORACLE_GLOBAL(php3_oracle_module).le_cursor =
+ register_list_destructors(_close_oracur,NULL);
+
+ if (cfg_get_long("oracle.allow_persistent",
+ &ORACLE_GLOBAL(php3_oracle_module).allow_persistent)
+ == FAILURE) {
+ ORACLE_GLOBAL(php3_oracle_module).allow_persistent = -1;
+ }
+ if (cfg_get_long("oracle.max_persistent",
+ &ORACLE_GLOBAL(php3_oracle_module).max_persistent)
+ == FAILURE) {
+ ORACLE_GLOBAL(php3_oracle_module).max_persistent = -1;
+ }
+ if (cfg_get_long("oracle.max_links",
+ &ORACLE_GLOBAL(php3_oracle_module).max_links)
+ == FAILURE) {
+ ORACLE_GLOBAL(php3_oracle_module).max_links = -1;
+ }
+
+ ORACLE_GLOBAL(php3_oracle_module).num_persistent = 0;
+
+ ORACLE_GLOBAL(php3_oracle_module).le_cursor =
+ register_list_destructors(_close_oracur, NULL);
+ ORACLE_GLOBAL(php3_oracle_module).le_conn =
+ register_list_destructors(_close_oraconn, NULL);
+ ORACLE_GLOBAL(php3_oracle_module).le_pconn =
+ register_list_destructors(NULL, _close_orapconn);
+
+ 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);
+
+ return SUCCESS;
+}
+
+int php3_rinit_oracle(INIT_FUNC_ARGS)
+{
+ ORACLE_TLS_VARS;
+
+ ORACLE_GLOBAL(php3_oracle_module).num_links =
+ ORACLE_GLOBAL(php3_oracle_module).num_persistent;
+ /*
+ ORACLE_GLOBAL(php3_oracle_module).defaultlrl = 0;
+ ORACLE_GLOBAL(php3_oracle_module).defaultbinmode = 0;
+ ORACLE_GLOBAL(php3_oracle_module).defaultconn = 0;
+ */
+ return SUCCESS;
+}
+
+
+int php3_mshutdown_oracle(SHUTDOWN_FUNC_ARGS)
+{
+ ORACLE_TLS_VARS;
+#ifdef THREAD_SAFE
+ PHP3_TLS_THREAD_FREE(oracle_globals);
+ PHP3_MUTEX_LOCK(oracle_mutex);
+ numthreads--;
+ if (numthreads<1) {
+ PHP3_TLS_PROC_SHUTDOWN(ORACLETls);
+ PHP3_MUTEX_UNLOCK(oracle_mutex);
+ PHP3_MUTEX_FREE(oracle_mutex);
+ return SUCCESS;
+ }
+ PHP3_MUTEX_UNLOCK(oracle_mutex);
+#endif
+ return SUCCESS;
+
+}
+
+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 int ora_logon(string user, string password)
+ Open an Oracle connection */
+void php3_Ora_Logon(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_Ora_Do_Logon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto int ora_plogon(string user, string password)
+ Open a persistant Oracle connection */
+void php3_Ora_PLogon(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_Ora_Do_Logon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+void php3_Ora_Do_Logon(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+{
+ char *user = NULL;
+ char *pwd = NULL;
+ pval *arg1, *arg2;
+ oraConnection *db_conn;
+ list_entry *index_ptr;
+ char *hashed_details;
+ int hashed_len, len, id;
+ ORACLE_TLS_VARS;
+
+ ORACLE_GLOBAL(php3_oracle_module).resource_list = list;
+ ORACLE_GLOBAL(php3_oracle_module).resource_plist = plist;
+
+ if (getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_string(arg1);
+ convert_to_string(arg2);
+
+ user = arg1->value.str.val;
+ pwd = arg2->value.str.val;
+
+ if (!ORACLE_GLOBAL(php3_oracle_module).allow_persistent) {
+ persistent = 0;
+ }
+
+ if (ORACLE_GLOBAL(php3_oracle_module).max_links != -1 &&
+ ORACLE_GLOBAL(php3_oracle_module).num_links >=
+ ORACLE_GLOBAL(php3_oracle_module).max_links) {
+ php3_error(E_WARNING, "Oracle: Too many open links (%d)",
+ ORACLE_GLOBAL(php3_oracle_module).num_links);
+ RETURN_FALSE;
+ }
+
+ /* the user requested a persistent connection */
+ if (persistent &&
+ ORACLE_GLOBAL(php3_oracle_module).max_persistent != -1 &&
+ ORACLE_GLOBAL(php3_oracle_module).num_persistent >=
+ ORACLE_GLOBAL(php3_oracle_module).max_persistent) {
+ php3_error(E_WARNING,"Oracle: Too many open persistent links (%d)",
+ ORACLE_GLOBAL(php3_oracle_module).num_persistent);
+ RETURN_FALSE;
+ }
+
+ len = strlen(user) + strlen(pwd) + 9;
+ hashed_details = emalloc(len);
+
+ if (hashed_details == NULL) {
+ php3_error(E_WARNING, "Out of memory");
+ RETURN_FALSE;
+ }
+
+ hashed_len = _php3_sprintf(hashed_details, "ora_%s_%s", user, pwd);
+
+ /* try to find if we already have this link in our persistent list,
+ * no matter if it is to be persistent or not
+ */
+
+ if (_php3_hash_find(plist, hashed_details, hashed_len + 1,
+ (void **) &index_ptr) == FAILURE) {
+ /* the link is not in the persistent list */
+ list_entry new_index_ptr;
+
+ if (persistent)
+ db_conn = (oraConnection *)malloc(sizeof(oraConnection));
+ else
+ db_conn = (oraConnection *)emalloc(sizeof(oraConnection));
+
+ if (db_conn == NULL){
+ efree(hashed_details);
+ php3_error(E_WARNING, "Out of memory");
+ RETURN_FALSE;
+ }
+
+ if (orlon(&db_conn->lda, db_conn->hda, user,
+ strlen(user), pwd, strlen(pwd), 0)) {
+ php3_error(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;
+ }
+
+ db_conn->open = 1;
+ if (persistent){
+ /*new_le.type = ORACLE_GLOBAL(php3_oracle_module).le_pconn;
+ new_le.ptr = db_conn;*/
+ return_value->value.lval =
+ php3_plist_insert(db_conn, ORACLE_GLOBAL(php3_oracle_module).le_pconn);
+ new_index_ptr.ptr = (void *) return_value->value.lval;
+#ifdef THREAD_SAFE
+ new_index_ptr.type = _php3_le_index_ptr();
+#else
+ new_index_ptr.type = le_index_ptr;
+#endif
+ if (_php3_hash_update(plist,hashed_details,hashed_len + 1,(void *) &new_index_ptr,
+ sizeof(list_entry),NULL) == FAILURE) {
+ ologof(&db_conn->lda);
+ free(db_conn);
+ efree(hashed_details);
+ php3_error(E_WARNING, "Can't update hashed details list");
+ RETURN_FALSE;
+ }
+ ORACLE_GLOBAL(php3_oracle_module).num_persistent++;
+ } else {
+ /* non persistent, simply add to list */
+ return_value->value.lval =
+ php3_list_insert(db_conn, ORACLE_GLOBAL(php3_oracle_module).le_conn);
+ }
+
+ ORACLE_GLOBAL(php3_oracle_module).num_links++;
+
+ } else {
+ int type;
+
+ /* the link is already in the persistent list */
+#ifdef THREAD_SAFE
+ if (index_ptr->type != _php3_le_index_ptr()) {
+#else
+ if (index_ptr->type != le_index_ptr) {
+#endif
+ efree(hashed_details);
+ php3_error(E_WARNING, "Oops, something went completly wrong");
+ RETURN_FALSE;
+ }
+ id = (int) index_ptr->ptr;
+ db_conn = (oraConnection *)php3_plist_find(id, &type);
+
+ if (db_conn && (type == ORACLE_GLOBAL(php3_oracle_module).le_conn ||
+ type == ORACLE_GLOBAL(php3_oracle_module).le_pconn)){
+ if(!_ora_ping(db_conn)) {
+ /* XXX Reinitialize lda, hda ? */
+ if(orlon(&db_conn->lda, db_conn->hda, user,
+ strlen(user), pwd, strlen(pwd), 0)) {
+ php3_error(E_WARNING, "Unable to reconnect to ORACLE (%s)",
+ ora_error(&db_conn->lda));
+ /* Delete list entry for this connection */
+ php3_plist_delete(id);
+ /* Delete hashed list entry for this dead connection */
+ _php3_hash_del(plist, hashed_details, hashed_len);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ }
+ return_value->value.lval = id;
+ }
+ }
+ efree(hashed_details);
+ return_value->type = IS_LONG;
+}
+
+/* {{{ proto int ora_logoff(int connection)
+ Close an Oracle connection */
+void php3_Ora_Logoff(INTERNAL_FUNCTION_PARAMETERS)
+{ /* conn_index */
+ int type, ind;
+ oraConnection *conn;
+ pval *arg;
+ ORACLE_TLS_VARS;
+
+ if (getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg);
+ ind = (int)arg->value.lval;
+
+ conn = (oraConnection *)php3_list_find(ind, &type);
+ if (!conn || (type != ORACLE_GLOBAL(php3_oracle_module).le_conn &&
+ type != ORACLE_GLOBAL(php3_oracle_module).le_pconn)) {
+ return;
+ }
+ php3_list_delete(ind);
+}
+/* }}} */
+
+/* {{{ proto int ora_open(int connection)
+ Open an Oracle cursor */
+void php3_Ora_Open(INTERNAL_FUNCTION_PARAMETERS)
+{ /* conn_index */
+ pval *arg;
+ oraConnection *conn = NULL;
+ oraCursor *cursor = NULL;
+ int conn_ind;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg);
+
+ conn_ind = arg->value.lval;
+ conn = ora_get_conn(list, conn_ind);
+ if (conn == NULL) {
+ RETURN_FALSE;
+ }
+
+ if ((cursor = (oraCursor *)emalloc(sizeof(oraCursor))) == NULL){
+ php3_error(E_WARNING, "Out of memory");
+ RETURN_FALSE;
+ }
+ memset(cursor, 0, sizeof(oraCursor));
+ if (oopen(&cursor->cda, &conn->lda, (text *) 0, -1, -1, (text *) 0, -1)) {
+ php3_error(E_WARNING, "Unable to open new cursor (%s)",
+ ora_error(&cursor->cda));
+ efree(cursor);
+ RETURN_FALSE;
+ }
+ cursor->open = 1;
+ cursor->conn_ptr = conn;
+ RETURN_LONG(ora_add_cursor(list, cursor));
+}
+/* }}} */
+
+/* {{{ proto int ora_close(int cursor)
+ Close an Oracle cursor */
+void php3_Ora_Close(INTERNAL_FUNCTION_PARAMETERS)
+{ /* conn_index */
+ pval *arg;
+
+ if (getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg);
+
+ ora_del_cursor(list, arg->value.lval);
+ RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_commitoff(int connection)
+ Disable automatic commit */
+void php3_Ora_CommitOff(INTERNAL_FUNCTION_PARAMETERS)
+{ /* conn_index */
+ pval *arg;
+ oraConnection *conn;
+
+ if (getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg);
+
+ conn = ora_get_conn(list, arg->value.lval);
+ if (conn == NULL) {
+ RETURN_FALSE;
+ }
+ if (ocof(&conn->lda)) {
+ php3_error(E_WARNING, "Unable to turn off auto-commit (%s)",
+ ora_error(&conn->lda));
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_commiton(int connection)
+ Enable automatic commit */
+void php3_Ora_CommitOn(INTERNAL_FUNCTION_PARAMETERS)
+{ /* conn_index */
+ pval *arg;
+ oraConnection *conn;
+
+ if (getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg);
+
+ if (!(conn = ora_get_conn(list, arg->value.lval))) {
+ RETURN_FALSE;
+ }
+
+ if (ocon(&conn->lda)) {
+ php3_error(E_WARNING, "Unable to turn on auto-commit (%s)",
+ ora_error(&conn->lda));
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_commit(int connection)
+ Commit an Oracle transaction */
+void php3_Ora_Commit(INTERNAL_FUNCTION_PARAMETERS)
+{ /* conn_index */
+ pval *arg;
+ oraConnection *conn;
+
+ if (getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg);
+
+ conn = ora_get_conn(list, arg->value.lval);
+ if (conn == NULL) {
+ RETURN_FALSE;
+ }
+ if (ocom(&conn->lda)) {
+ php3_error(E_WARNING, "Unable to commit transaction (%s)",
+ ora_error(&conn->lda));
+ RETURN_FALSE;
+ }
+ RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_rollback(int connection)
+ Roll back an Oracle transaction */
+void php3_Ora_Rollback(INTERNAL_FUNCTION_PARAMETERS)
+{ /* conn_index */
+ pval *arg;
+ oraConnection *conn;
+
+ if (getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg);
+
+ conn = ora_get_conn(list, arg->value.lval);
+ if (conn == NULL) {
+ RETURN_FALSE;
+ }
+ if (orol(&conn->lda)) {
+ php3_error(E_WARNING, "Unable to roll back transaction (%s)",
+ ora_error(&conn->lda));
+ RETURN_FALSE;
+ }
+ RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_parse(int cursor, string sql_statement [, int defer])
+ Parse an Oracle SQL statement */
+void php3_Ora_Parse(INTERNAL_FUNCTION_PARAMETERS)
+{
+ /* cursor_ind, sql_statement [, defer] */
+ int argc;
+ pval *argv[3];
+ oraCursor *cursor;
+ sword defer = 0;
+ text *query;
+
+ argc = ARG_COUNT(ht);
+ if ((argc != 2 && argc != 3) || getParametersArray(ht, argc, argv) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(argv[0]);
+ convert_to_string(argv[1]);
+
+ if (argc == 3) {
+ convert_to_long(argv[2]);
+ if (argv[2]->value.lval != 0) {
+ defer = DEFER_PARSE;
+ }
+ }
+
+ query = (text *) estrndup(argv[1]->value.str.val,argv[1]->value.str.len);
+
+ if (query == NULL) {
+ php3_error(E_WARNING, "Invalid query");
+ RETURN_FALSE;
+ }
+ if (!(cursor = ora_get_cursor(list, argv[0]->value.lval))){
+ RETURN_FALSE;
+ }
+
+ if (cursor->query) {
+ efree(cursor->query);
+ }
+ cursor->query = query;
+ cursor->fetched = 0;
+ if(cursor->params && cursor->nparams > 0){
+ _php3_hash_destroy(cursor->params);
+ efree(cursor->params);
+ cursor->params = NULL;
+ cursor->nparams = 0;
+ }
+
+ if (oparse(&cursor->cda, query, (sb4) - 1, defer, VERSION_7)) {
+ php3_error(E_WARNING, "Ora_Parse failed (%s)",
+ ora_error(&cursor->cda));
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_bind(int cursor, string php_variable_name, string sql_parameter_name, int length [, int type])
+ Bind a PHP variable to an Oracle parameter */
+void php3_Ora_Bind(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_ind, php_var_name, sql_var_name, data_len [, inout]*/
+ /* inout: 0 = in/out, 1 = in, 2 = out */
+ int argc;
+ pval *argv[5];
+ oraParam *newparam, *paramptr;
+ oraCursor *cursor;
+ char *paramname;
+
+ argc = ARG_COUNT(ht);
+ if (argc < 4 || argc > 5 || getParametersArray(ht, argc, argv) == FAILURE){
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(argv[0]);
+ convert_to_string(argv[1]);
+ convert_to_string(argv[2]);
+ convert_to_long(argv[3]);
+
+ cursor = ora_get_cursor(list, argv[0]->value.lval);
+ if (cursor == NULL) {
+ php3_error(E_WARNING, "Invalid cursor index %d",
+ argv[0]->value.lval);
+ RETURN_FALSE;
+ }
+
+ if(cursor->params == NULL){
+ cursor->params = (HashTable *)emalloc(sizeof(HashTable));
+ if (!cursor->params ||
+ _php3_hash_init(cursor->params, 19, NULL,
+ NULL, 0) ==
+ /* (void (*)(void *))pval_ora_param_destructor, 0) == */
+ FAILURE){
+ php3_error(E_ERROR, "Unable to initialize parameter list");
+ RETURN_FALSE;
+ }
+ }
+ if((newparam = (oraParam *)emalloc(sizeof(oraParam))) == NULL){
+ php3_error(E_WARNING, "Out of memory for parameter");
+ RETURN_FALSE;
+ }
+
+ if((paramname = estrndup(argv[1]->value.str.val, argv[1]->value.str.len)) == NULL){
+ php3_error(E_WARNING, "Out of memory for parametername");
+ efree(newparam);
+ RETURN_FALSE;
+ }
+
+ if (_php3_hash_add(cursor->params, paramname, argv[1]->value.str.len + 1, newparam, sizeof(oraParam), (void **)&paramptr) == FAILURE) {
+ /* XXX _php3_hash_destroy */
+ efree(paramname);
+ efree(newparam);
+ php3_error(E_ERROR, "Could not make parameter placeholder");
+ RETURN_FALSE;
+ }
+
+ efree(newparam);
+ efree(paramname);
+
+ paramptr->progvl = argv[3]->value.lval + 1;
+ if(argc > 4){
+ convert_to_long(argv[4]);
+ paramptr->type = (short)argv[4]->value.lval;
+ }else{
+ paramptr->type = 0;
+ }
+
+ if((paramptr->progv = (text *)emalloc(paramptr->progvl)) == NULL){
+ php3_error(E_WARNING, "Out of memory for parameter value");
+ RETURN_FALSE;
+ }
+
+/* XXX Maximum for progvl */
+ paramptr->alen = paramptr->progvl;
+ if(obndra(&cursor->cda, argv[2]->value.str.val, -1,
+ (ub1 *)paramptr->progv, paramptr->progvl, SQLT_STR,
+ -1, 0, &paramptr->alen, 0, 0, 0, 0, -1, -1)){
+ php3_error(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 int ora_exec(int cursor)
+ Execute a parsed statement */
+void php3_Ora_Exec(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index */
+ pval *arg;
+ oraCursor *cursor = NULL;
+
+ if (getParameters(ht, 1, &arg) == FAILURE)
+ WRONG_PARAM_COUNT;
+
+ convert_to_long(arg);
+
+ if ((cursor = ora_get_cursor(list, arg->value.lval)) == 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)){
+ RETURN_FALSE;
+ }
+ }
+
+ if (oexec(&cursor->cda)) {
+ php3_error(E_WARNING, "Ora_Exec failed (%s)",
+ ora_error(&cursor->cda));
+ RETURN_FALSE;
+ }
+
+ if(cursor->nparams > 0){
+ if(!ora_set_param_values(cursor, 1)){
+ RETURN_FALSE;
+ }
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_numcols(int cursor)
+ Returns the numbers of columns in a result */
+void php3_Ora_NumCols(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index */
+ pval *arg;
+ oraCursor *cursor = NULL;
+
+ if (getParameters(ht, 1, &arg) == FAILURE)
+ WRONG_PARAM_COUNT;
+
+ convert_to_long(arg);
+
+ if ((cursor = ora_get_cursor(list, arg->value.lval)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(cursor->ncols);
+}
+/* }}} */
+
+/* {{{ proto int ora_numrows(int cursor)
+ Returns the number of rows in a result */
+void php3_Ora_NumRows(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index */
+ pval *arg;
+ oraCursor *cursor = NULL;
+
+ if(getParameters(ht, 1, &arg) == FAILURE)
+ WRONG_PARAM_COUNT;
+
+ convert_to_long(arg);
+
+ if((cursor = ora_get_cursor(list, arg->value.lval)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(cursor->cda.rpc);
+}
+/* }}} */
+
+/* prepares/executes/fetches 1st row if avail*/
+/* {{{ proto int ora_do(int connection, int cursor)
+ Parse and execute a statement and fetch first result row */
+void php3_Ora_Do(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *argv[2];
+ oraConnection *conn = NULL;
+ oraCursor *cursor = NULL;
+ text *query;
+
+ if (ARG_COUNT(ht) != 2 || getParametersArray(ht, 2, argv) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(argv[0]);
+ convert_to_string(argv[1]);
+
+ conn = ora_get_conn(list, argv[0]->value.lval);
+ if (conn == NULL) {
+ RETURN_FALSE;
+ }
+
+ if ((cursor = (oraCursor *)emalloc(sizeof(oraCursor))) == NULL){
+ php3_error(E_WARNING, "Out of memory");
+ RETURN_FALSE;
+ }
+
+ memset(cursor, 0, sizeof(oraCursor));
+
+ query = (text *) estrndup(argv[1]->value.str.val,argv[1]->value.str.len);
+
+ if (query == NULL) {
+ php3_error(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)) {
+ php3_error(E_WARNING, "Unable to open new cursor (%s)",
+ ora_error(&cursor->cda));
+ efree(cursor);
+ RETURN_FALSE;
+ }
+ cursor->open = 1;
+ cursor->conn_ptr = conn;
+
+ /* Prepare stmt */
+
+ if (oparse(&cursor->cda, query, (sb4) - 1, 1, VERSION_7)){
+ php3_error(E_WARNING, "Ora_Do failed (%s)",
+ ora_error(&cursor->cda));
+ _close_oracur(cursor);
+ 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);
+ RETURN_FALSE;
+ }
+ if (oexfet(&cursor->cda, 1, 0, 0)) {
+ php3_error(E_WARNING, "Ora_Do failed (%s)",
+ ora_error(&cursor->cda));
+ _close_oracur(cursor);
+ RETURN_FALSE;
+ }
+ cursor->fetched = 1;
+ } else {
+ if (oexec(&cursor->cda)) {
+ php3_error(E_WARNING, "Ora_Do failed (%s)",
+ ora_error(&cursor->cda));
+ _close_oracur(cursor);
+ RETURN_FALSE;
+ }
+ }
+
+ RETURN_LONG(ora_add_cursor(list, cursor));
+}
+/* }}} */
+
+/* {{{ proto int ora_fetch(int cursor)
+ Fetch a row of result data from a cursor */
+void php3_Ora_Fetch(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index */
+ pval *arg;
+ oraCursor *cursor;
+
+ if (getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg);
+
+ /* Find the cursor */
+ if ((cursor = ora_get_cursor(list, arg->value.lval)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ if (cursor->ncols == 0){
+ php3_error(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) {
+ php3_error(E_WARNING, "Ora_Fetch failed (%s)",
+ ora_error(&cursor->cda));
+ }
+ RETURN_FALSE;
+ }
+ cursor->fetched++;
+ RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ora_fetchinto(int cursor, array result)
+ Fetch a row into the specified result array */
+void php3_Ora_FetchInto(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index, array ref */
+ pval *arg1, *arr, tmp;
+ oraCursor *cursor;
+ ub4 ret_len;
+ int i;
+
+ if (getParameters(ht, 2, &arg1, &arr) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (!ParameterPassedByReference(ht, 2)){
+ php3_error(E_WARNING, "Array not passed by reference in call to ora_fetch_into()");
+ RETURN_FALSE;
+ }
+
+ convert_to_long(arg1);
+
+ /* Find the cursor */
+ if ((cursor = ora_get_cursor(list, arg1->value.lval)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ if (cursor->ncols == 0){
+ php3_error(E_WARNING, "No tuples available on this cursor");
+ RETURN_FALSE;
+ }
+
+ if (arr->type != IS_ARRAY){
+ if (array_init(arr) == FAILURE){
+ php3_error(E_WARNING, "Can't convert to type Array");
+ RETURN_FALSE;
+ }
+ }
+
+ if (ofetch(&cursor->cda)) {
+ if (cursor->cda.rc != NO_DATA_FOUND) {
+ php3_error(E_WARNING, "Ora_Fetch_Into failed (%s)",
+ ora_error(&cursor->cda));
+ }
+ RETURN_FALSE;
+ }
+ cursor->fetched++;
+
+ for (i = 0; i < cursor->ncols; i++) {
+ tmp.type = IS_STRING;
+ tmp.value.str.len = 0;
+
+ if (cursor->columns[i].col_retcode == 1405) {
+ continue; /* don't add anything for NULL columns */
+ } 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 {
+ switch(cursor->columns[i].dbtype) {
+ case SQLT_LNG:
+ case SQLT_LBI:
+ /* XXX 64k max for LONG and LONG RAW */
+ oflng(&cursor->cda, (sword)(i + 1), cursor->columns[i].buf, DB_SIZE, 1,
+ &ret_len, 0);
+ tmp.value.str.len = ret_len;
+ break;
+ default:
+ tmp.value.str.len = min(cursor->columns[i].col_retlen,
+ cursor->columns[i].dsize);
+ break;
+ }
+ tmp.value.str.val = estrndup(cursor->columns[i].buf,
+ tmp.value.str.len);
+ }
+ _php3_hash_index_update(arr->value.ht, i, (void *) &tmp, sizeof(pval), NULL);
+ }
+
+ RETURN_LONG(cursor->ncols);
+}
+/* }}} */
+
+/* {{{ proto string ora_columnname(int cursor, int column)
+ Get the name of an Oracle result column */
+void php3_Ora_ColumnName(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index, column_index */
+ pval *argv[2];
+ int cursor_ind;
+ oraCursor *cursor = NULL;
+
+ if (ARG_COUNT(ht) != 2 || getParametersArray(ht, 2, argv) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(argv[0]);
+
+ cursor_ind = argv[0]->value.lval;
+ /* Find the cursor */
+ if ((cursor = ora_get_cursor(list, cursor_ind)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ convert_to_long(argv[1]);
+
+ if (cursor->ncols == 0){
+ php3_error(E_WARNING, "No tuples available at this cursor index");
+ RETURN_FALSE;
+ }
+
+ if (argv[1]->value.lval >= cursor->ncols){
+ php3_error(E_WARNING, "Column index larger than number of columns");
+ RETURN_FALSE;
+ }
+
+ if (argv[1]->value.lval < 0){
+ php3_error(E_WARNING, "Column numbering starts at 0");
+ RETURN_FALSE;
+ }
+
+ RETURN_STRINGL(cursor->columns[argv[1]->value.lval].cbuf,
+ cursor->columns[argv[1]->value.lval].cbufl,1);
+}
+/* }}} */
+
+/* {{{ proto string ora_columntype(int cursor, int column)
+ Get the type of an Oracle result column */
+void php3_Ora_ColumnType(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index, column_index */
+ pval *argv[2];
+ int cursor_ind, colno;
+ oraCursor *cursor = NULL;
+
+ if (ARG_COUNT(ht) != 2 || getParametersArray(ht, 2, argv) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(argv[0]);
+ /* don't convert the column index yet, it might be the column name */
+
+ cursor_ind = argv[0]->value.lval;
+ /* Find the cursor */
+ if ((cursor = ora_get_cursor(list, cursor_ind)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ convert_to_long(argv[1]);
+ colno = argv[1]->value.lval;
+
+ if (cursor->ncols == 0){
+ php3_error(E_WARNING, "No tuples available at this cursor index");
+ RETURN_FALSE;
+ }
+
+ if (colno >= cursor->ncols){
+ php3_error(E_WARNING, "Column index larger than number of columns");
+ RETURN_FALSE;
+ }
+
+ if (colno < 0){
+ php3_error(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 */
+void php3_Ora_ColumnSize(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index, column_index */
+ pval *argv[2];
+ int cursor_ind;
+ oraCursor *cursor = NULL;
+
+ if (ARG_COUNT(ht) != 2 || getParametersArray(ht, 2, argv) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(argv[0]);
+
+ cursor_ind = argv[0]->value.lval;
+ /* Find the cursor */
+ if ((cursor = ora_get_cursor(list, cursor_ind)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ convert_to_long(argv[1]);
+
+ if (cursor->ncols == 0){
+ php3_error(E_WARNING, "No tuples available at this cursor index");
+ RETURN_FALSE;
+ }
+
+ if (argv[1]->value.lval >= cursor->ncols){
+ php3_error(E_WARNING, "Column index larger than number of columns");
+ RETURN_FALSE;
+ }
+
+ if (argv[1]->value.lval < 0){
+ php3_error(E_WARNING, "Column numbering starts at 0");
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(cursor->columns[argv[1]->value.lval].dbsize);
+}
+/* }}} */
+
+/* {{{ proto mixed ora_getcolumn(int cursor, int column)
+ Get data from a fetched row */
+void php3_Ora_GetColumn(INTERNAL_FUNCTION_PARAMETERS)
+{ /* cursor_index, column_index */
+ pval *argv[2];
+ int colno;
+ oraCursor *cursor = NULL;
+ oraColumn *column = NULL;
+ sb2 type;
+
+ if (ARG_COUNT(ht) != 2 || getParametersArray(ht, 2, argv) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(argv[0]);
+
+ /* Find the cursor */
+ if ((cursor = ora_get_cursor(list, argv[0]->value.lval)) == NULL) {
+ RETURN_FALSE;
+ }
+
+ if (cursor->ncols == 0){
+ php3_error(E_WARNING, "No tuples available at this cursor index");
+ RETURN_FALSE;
+ }
+
+ convert_to_long(argv[1]);
+ colno = argv[1]->value.lval;
+
+ if (colno >= cursor->ncols){
+ php3_error(E_WARNING, "Column index larger than number of columns");
+ RETURN_FALSE;
+ }
+
+ if (colno < 0){
+ php3_error(E_WARNING, "Column numbering starts at 0");
+ RETURN_FALSE;
+ }
+
+ if (cursor->fetched == 0){
+ if (ofetch(&cursor->cda)) {
+ if (cursor->cda.rc != NO_DATA_FOUND) {
+ php3_error(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 != 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:
+ RETURN_STRINGL(column->buf, min(column->col_retlen, column->dsize), 1);
+ case SQLT_LNG:
+ case SQLT_LBI:
+ {
+ ub4 ret_len;
+ /* XXX 64k max for LONG and LONG RAW */
+ oflng(&cursor->cda, (sword)(colno + 1), column->buf, DB_SIZE, 1,
+ &ret_len, 0);
+ RETURN_STRINGL(column->buf, ret_len, 1);
+ }
+ default:
+ php3_error(E_WARNING,
+ "Ora_GetColumn found invalid type (%d)", type);
+ RETURN_FALSE;
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto string ora_error(int cursor_or_connection)
+ Get an Oracle error message */
+void php3_Ora_Error(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg;
+ oraCursor *cursor;
+ oraConnection *conn;
+
+ if (ARG_COUNT(ht) != 1 || getParametersArray(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg);
+ if ((cursor = ora_get_cursor(list, arg->value.lval)) != NULL) {
+ return_value->type = IS_STRING;
+ return_value->value.str.val = ora_error(&cursor->cda);
+ return_value->value.str.len = strlen(return_value->value.str.val);
+ } else if ((conn = ora_get_conn(list, arg->value.lval)) != NULL) {
+ return_value->type = IS_STRING;
+ return_value->value.str.val = ora_error(&conn->lda);
+ return_value->value.str.len = strlen(return_value->value.str.val);
+ }
+}
+/* }}} */
+
+/* {{{ proto int ora_errorcode(int cursor_or_connection)
+ Get an Oracle error code */
+void php3_Ora_ErrorCode(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg;
+ oraCursor *cursor;
+ oraConnection *conn;
+
+ if (ARG_COUNT(ht) != 1 || getParametersArray(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg);
+ if ((cursor = ora_get_cursor(list, arg->value.lval)) != NULL) {
+ RETVAL_LONG(cursor->cda.rc);
+ } else if ((conn = ora_get_conn(list, arg->value.lval)) != NULL) {
+ RETURN_LONG(conn->lda.rc);
+ }
+}
+/* }}} */
+
+void php3_info_oracle()
+{
+#if !(WIN32|WINNT)
+ php3_printf("Oracle version: %s<br>\n"
+ "Compile-time ORACLE_HOME: %s<br>\n"
+ "Libraries used: %s",
+ PHP_ORACLE_VERSION, PHP_ORACLE_HOME, PHP_ORACLE_LIBS);
+#endif
+}
+
+
+/*
+** Functions internal to this module.
+*/
+
+static oraConnection *
+ora_get_conn(HashTable *list, int ind)
+{
+ oraConnection *conn = NULL;
+ int type;
+ HashTable *plist;
+ ORACLE_TLS_VARS;
+
+ plist = ORACLE_GLOBAL(php3_oracle_module).resource_plist;
+
+ conn = (oraConnection *)php3_list_find(ind, &type);
+ if (conn && type == ORACLE_GLOBAL(php3_oracle_module).le_conn)
+ return conn;
+
+ conn = (oraConnection *)php3_plist_find(ind, &type);
+ if (conn && type == ORACLE_GLOBAL(php3_oracle_module).le_pconn)
+ return conn;
+
+ php3_error(E_WARNING,"Bad Oracle connection number (%d)", ind);
+ return NULL;
+}
+
+int ora_add_cursor(HashTable *list, oraCursor *cursor)
+{
+ ORACLE_TLS_VARS;
+ return php3_list_insert(cursor, ORACLE_GLOBAL(php3_oracle_module).le_cursor);
+}
+
+static oraCursor *
+ora_get_cursor(HashTable *list, int ind)
+{
+ oraCursor *cursor;
+ int type;
+ ORACLE_TLS_VARS;
+
+ cursor = php3_list_find(ind, &type);
+ if (!cursor || type != ORACLE_GLOBAL(php3_oracle_module).le_cursor) {
+ php3_error(E_WARNING, "Invalid cursor index %d", ind);
+ return NULL;
+ }
+ return cursor;
+}
+
+void ora_del_cursor(HashTable *list, int ind)
+{
+ oraCursor *cursor;
+ int type;
+ ORACLE_TLS_VARS;
+
+ cursor = (oraCursor *) php3_list_find(ind, &type);
+ if (!cursor || type != ORACLE_GLOBAL(php3_oracle_module).le_cursor) {
+ php3_error(E_WARNING,"Can't find cursor %d",ind);
+ return;
+ }
+ php3_list_delete(ind);
+}
+
+static char *
+ora_error(Cda_Def * cda)
+{
+ sword n, l;
+ text *errmsg;
+
+ errmsg = (text *) emalloc(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;
+}
+
+static sword
+ora_describe_define(oraCursor * cursor)
+{
+ long col = 0;
+ int i;
+ sb2 type;
+ sb4 dbsize;
+
+ 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 {
+ php3_error(E_WARNING, "%s", ora_error(&cursor->cda));
+ cursor->ncols = 0;
+ return -1;
+ }
+ }
+ cursor->ncols++;
+ }
+
+ if (cursor->ncols > 0){
+ cursor->columns = (oraColumn *) emalloc(sizeof(oraColumn) * cursor->ncols);
+ if (cursor->columns == NULL){
+ php3_error(E_WARNING, "Out of memory");
+ return -1;
+ }
+ }
+
+ for(col = 0; col < cursor->ncols; col++){
+ memset(&cursor->columns[col], 0, sizeof(oraColumn));
+ 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 {
+ php3_error(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;
+ }
+
+ if ((cursor->columns[col].buf = (ub1 *) emalloc(cursor->columns[col].dsize + 1)) == NULL){
+ php3_error(E_WARNING, "Out of memory");
+ return -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)) {
+ php3_error(E_WARNING, "%s", ora_error(&cursor->cda));
+ return -1;
+ }
+ }
+ return 1;
+}
+
+/* see oracle_hack.c */
+extern PHPAPI HashTable *php3i_get_symbol_table(void);
+
+int ora_set_param_values(oraCursor *cursor, int isout)
+{
+ char *paramname;
+ oraParam *param;
+ pval *pdata;
+ int i, len;
+#if (WIN32|WINNT)
+ /* see oracle_hack.c */
+ HashTable *symbol_table=php3i_get_symbol_table();
+#endif
+ _php3_hash_internal_pointer_reset(cursor->params);
+
+ if(_php3_hash_num_elements(cursor->params) != cursor->nparams){
+ php3_error(E_WARNING, "Mismatch in number of parameters");
+ return 0;
+ }
+
+ for(i = 0; i < cursor->nparams; i++, _php3_hash_move_forward(cursor->params)){
+ if(_php3_hash_get_current_key(cursor->params, &paramname, NULL) != HASH_KEY_IS_STRING){
+ php3_error(E_WARNING, "Can't get parameter name");
+ return 0;
+ }
+ if(_php3_hash_get_current_data(cursor->params, (void **)&param) == FAILURE){
+ php3_error(E_WARNING, "Can't get parameter data");
+ efree(paramname);
+ return 0;
+ }
+
+ if(isout){
+ /* XXX param->alen + 1 ?? */
+ if(param->type != 1 && param->alen > 0){
+#if (WIN32|WINNT)
+ /* see oracle_hack.c */
+ {
+ pval var;
+ char *name=(paramname);
+ var.value.str.val = (param->progv);
+ var.value.str.len = (param->alen);
+ var.type = IS_STRING;
+ _php3_hash_update(symbol_table, name, strlen(name)+1, &var, sizeof(pval),NULL);
+ }
+#else
+ SET_VAR_STRINGL(paramname, param->progv, param->alen);
+#endif
+ }
+ efree(paramname);
+ continue;
+ }else if(param->type == 2){
+ efree(paramname);
+ continue;
+ }
+
+ /* FIXME Globals don't work in extensions on windows, have to do something
+ else here. See oracle_hack.c */
+#if (WIN32|WINNT)
+ if(_php3_hash_find(symbol_table, paramname, strlen(paramname) + 1, (void **)&pdata) == FAILURE){
+ php3_error(E_WARNING, "Can't find variable for parameter");
+ efree(paramname);
+ return 0;
+ }
+#else
+ if(_php3_hash_find(&EG(symbol_table), paramname, strlen(paramname) + 1, (void **)&pdata) == FAILURE){
+ php3_error(E_WARNING, "Can't find variable for parameter");
+ efree(paramname);
+ return 0;
+ }
+#endif
+ convert_to_string(pdata);
+ if(param->progvl <= pdata->value.str.len){
+ php3_error(E_NOTICE, "Input value will be truncated");
+ }
+
+ len = min(param->progvl - 1, pdata->value.str.len);
+ strncpy(param->progv, pdata->value.str.val, len);
+
+ param->progv[len] = '\0';
+ efree(paramname);
+ }
+ return 1;
+
+}
+
+#endif /* HAVE_ORACLE */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */