diff options
Diffstat (limited to 'ext/oracle/oracle.c')
-rw-r--r-- | ext/oracle/oracle.c | 1770 |
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 **)¶mptr) == 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/*¶mptr->ind*/, /* ind */ + ¶mptr->alen, /* alen */ + 0 /*¶mptr->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, ¶mname, 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 **)¶m) == 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 + */ |