summaryrefslogtreecommitdiff
path: root/ext/oci8/oci8_statement.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/oci8/oci8_statement.c')
-rw-r--r--ext/oci8/oci8_statement.c113
1 files changed, 106 insertions, 7 deletions
diff --git a/ext/oci8/oci8_statement.c b/ext/oci8/oci8_statement.c
index 00c6079d9..bdba6dcce 100644
--- a/ext/oci8/oci8_statement.c
+++ b/ext/oci8/oci8_statement.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2009 The PHP Group |
+ | Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -25,7 +25,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: oci8_statement.c 277003 2009-03-11 16:47:14Z sixd $ */
+/* $Id: oci8_statement.c 294441 2010-02-03 19:37:35Z pajoye $ */
#ifdef HAVE_CONFIG_H
@@ -93,10 +93,11 @@ php_oci_statement *php_oci_statement_create (php_oci_connection *connection, cha
statement->connection = connection;
statement->has_data = 0;
+ statement->has_descr = 0;
statement->parent_stmtid = 0;
zend_list_addref(statement->connection->rsrc_id);
- if (OCI_G(default_prefetch) > 0) {
+ if (OCI_G(default_prefetch) >= 0) {
php_oci_statement_set_prefetch(statement, OCI_G(default_prefetch) TSRMLS_CC);
}
@@ -114,8 +115,8 @@ int php_oci_statement_set_prefetch(php_oci_statement *statement, long size TSRML
{
ub4 prefetch = size;
- if (size < 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows has to be greater than or equal to 1");
+ if (size < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of rows to be prefetched has to be greater than or equal to 0");
return 1;
}
@@ -131,6 +132,40 @@ int php_oci_statement_set_prefetch(php_oci_statement *statement, long size TSRML
}
/* }}} */
+/* {{{ php_oci_cleanup_pre_fetch()
+ Helper function to cleanup ref-cursors and descriptors from the previous row */
+int php_oci_cleanup_pre_fetch(void *data TSRMLS_DC)
+{
+ php_oci_out_column *outcol = data;
+
+ if (!outcol->is_descr && !outcol->is_cursor)
+ return ZEND_HASH_APPLY_KEEP;
+
+ switch(outcol->data_type) {
+ case SQLT_CLOB:
+ case SQLT_BLOB:
+ case SQLT_RDD:
+ case SQLT_BFILE:
+ if (outcol->descid) {
+ zend_list_delete(outcol->descid);
+ outcol->descid = 0;
+ }
+ break;
+ case SQLT_RSET:
+ if (outcol->stmtid) {
+ zend_list_delete(outcol->stmtid);
+ outcol->stmtid = 0;
+ outcol->nested_statement = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ return ZEND_HASH_APPLY_KEEP;
+
+} /* }}} */
+
+
/* {{{ php_oci_statement_fetch()
Fetch a row from the statement */
int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC)
@@ -143,6 +178,10 @@ int php_oci_statement_fetch(php_oci_statement *statement, ub4 nrows TSRMLS_DC)
php_oci_out_column *column;
+ if (statement->has_descr && statement->columns) {
+ zend_hash_apply(statement->columns, (apply_func_t) php_oci_cleanup_pre_fetch TSRMLS_CC);
+ }
+
PHP_OCI_CALL_RETURN(statement->errcode, OCIStmtFetch, (statement->stmt, statement->err, nrows, OCI_FETCH_NEXT, OCI_DEFAULT));
if ( statement->errcode == OCI_NO_DATA || nrows == 0 ) {
@@ -413,7 +452,11 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
we don't want to execute!!! */
if (statement->binds) {
- zend_hash_apply(statement->binds, (apply_func_t) php_oci_bind_pre_exec TSRMLS_CC);
+ int result = 0;
+ zend_hash_apply_with_argument(statement->binds, (apply_func_arg_t) php_oci_bind_pre_exec, (void *)&result TSRMLS_CC);
+ if (result) {
+ return 1;
+ }
}
/* execute statement */
@@ -566,6 +609,7 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
define_type = SQLT_RSET;
outcol->is_cursor = 1;
+ outcol->statement->has_descr = 1;
outcol->storage_size4 = -1;
outcol->retlen = -1;
dynamic = OCI_DYNAMIC_FETCH;
@@ -579,6 +623,7 @@ int php_oci_statement_execute(php_oci_statement *statement, ub4 mode TSRMLS_DC)
define_type = outcol->data_type;
outcol->is_descr = 1;
+ outcol->statement->has_descr = 1;
outcol->storage_size4 = -1;
dynamic = OCI_DYNAMIC_FETCH;
break;
@@ -763,10 +808,51 @@ void php_oci_statement_free(php_oci_statement *statement TSRMLS_DC)
/* {{{ php_oci_bind_pre_exec()
Helper function */
-int php_oci_bind_pre_exec(void *data TSRMLS_DC)
+int php_oci_bind_pre_exec(void *data, void *result TSRMLS_DC)
{
php_oci_bind *bind = (php_oci_bind *) data;
+ *(int *)result = 0;
+ switch (bind->type) {
+ case SQLT_NTY:
+ case SQLT_BFILEE:
+ case SQLT_CFILEE:
+ case SQLT_CLOB:
+ case SQLT_BLOB:
+ case SQLT_RDD:
+ if (Z_TYPE_P(bind->zval) != IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ *(int *)result = 1;
+ }
+ break;
+
+ case SQLT_INT:
+ case SQLT_NUM:
+ if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ *(int *)result = 1;
+ }
+ break;
+
+ case SQLT_LBI:
+ case SQLT_BIN:
+ case SQLT_LNG:
+ case SQLT_AFC:
+ case SQLT_CHR:
+ if (Z_TYPE_P(bind->zval) == IS_RESOURCE || Z_TYPE_P(bind->zval) == IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ *(int *)result = 1;
+ }
+ break;
+
+ case SQLT_RSET:
+ if (Z_TYPE_P(bind->zval) != IS_RESOURCE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ *(int *)result = 1;
+ }
+ break;
+ }
+
/* reset all bind stuff to a normal state..-. */
bind->indicator = 0;
@@ -942,6 +1028,10 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len,
case SQLT_INT:
case SQLT_NUM:
+ if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ return 1;
+ }
convert_to_long(var);
bind_data = (ub4 *)&Z_LVAL_P(var);
value_sz = sizeof(ub4);
@@ -953,6 +1043,10 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len,
case SQLT_LNG:
case SQLT_AFC:
case SQLT_CHR: /* SQLT_CHR is the default value when type was not specified */
+ if (Z_TYPE_P(var) == IS_RESOURCE || Z_TYPE_P(var) == IS_OBJECT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ return 1;
+ }
if (Z_TYPE_P(var) != IS_NULL) {
convert_to_string(var);
}
@@ -964,6 +1058,10 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len,
break;
case SQLT_RSET:
+ if (Z_TYPE_P(var) != IS_RESOURCE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid variable used for bind");
+ return 1;
+ }
PHP_OCI_ZVAL_TO_STATEMENT_EX(var, bind_statement);
value_sz = sizeof(void*);
@@ -1003,6 +1101,7 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len,
bindp->statement = oci_stmt;
bindp->parent_statement = statement;
bindp->zval = var;
+ bindp->type = type;
zval_add_ref(&var);
PHP_OCI_CALL_RETURN(statement->errcode,