summaryrefslogtreecommitdiff
path: root/ext/oci8/oci8_statement.c
diff options
context:
space:
mode:
authorAntony Dovgal <tony2001@php.net>2005-11-22 16:30:36 +0000
committerAntony Dovgal <tony2001@php.net>2005-11-22 16:30:36 +0000
commit066fb72fdd263147aa6b691fa7d68451f66b3225 (patch)
treeb1276fbf6d3fa047a485bedd168cd91bd4a0f0c8 /ext/oci8/oci8_statement.c
parent8115e710390da71c3e5a376f118136f69a4cf46d (diff)
downloadphp-git-066fb72fdd263147aa6b691fa7d68451f66b3225.tar.gz
Initial implementation of oci_bind_array_by_name()
At the moment we support only these types: SQLT_NUM, SQLT_INT, SQLT_LNG - integer/long SQLT_FLT - float SQLT_AFC, SQLT_CHR, SQLT_VCS, SQLT_AVC, SQLT_STR, SQLT_LVC - char/varchar SQLT_ODT - date More supported types may follow.
Diffstat (limited to 'ext/oci8/oci8_statement.c')
-rw-r--r--ext/oci8/oci8_statement.c351
1 files changed, 350 insertions, 1 deletions
diff --git a/ext/oci8/oci8_statement.c b/ext/oci8/oci8_statement.c
index 6d9eb1240a..3927392e30 100644
--- a/ext/oci8/oci8_statement.c
+++ b/ext/oci8/oci8_statement.c
@@ -637,6 +637,7 @@ int php_oci_bind_pre_exec(void *data TSRMLS_DC)
int php_oci_bind_post_exec(void *data TSRMLS_DC)
{
php_oci_bind *bind = (php_oci_bind *) data;
+ php_oci_connection *connection = bind->parent_statement->connection;
if (bind->indicator == -1) { /* NULL */
zval *val = bind->zval;
@@ -649,7 +650,87 @@ int php_oci_bind_post_exec(void *data TSRMLS_DC)
Z_STRVAL_P(bind->zval) = erealloc(Z_STRVAL_P(bind->zval), Z_STRLEN_P(bind->zval)+1);
Z_STRVAL_P(bind->zval)[ Z_STRLEN_P(bind->zval) ] = '\0';
}
-
+ else if (Z_TYPE_P(bind->zval) == IS_ARRAY) {
+ int i;
+ zval **entry;
+ HashTable *hash = HASH_OF(bind->zval);
+
+ switch (bind->array.type) {
+ case SQLT_NUM:
+ case SQLT_INT:
+ case SQLT_LNG:
+ for (i = 0; i < bind->array.current_length; i++) {
+ if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ zval_dtor(*entry);
+ ZVAL_LONG(*entry, ((ub4 *)(bind->array.elements))[i]);
+ zend_hash_move_forward(hash);
+ }
+ else {
+ add_next_index_long(bind->zval, ((ub4 *)(bind->array.elements))[i]);
+ }
+ }
+ break;
+ case SQLT_FLT:
+ for (i = 0; i < bind->array.current_length; i++) {
+ if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ zval_dtor(*entry);
+ ZVAL_DOUBLE(*entry, ((double *)(bind->array.elements))[i]);
+ zend_hash_move_forward(hash);
+ }
+ else {
+ add_next_index_double(bind->zval, ((double *)(bind->array.elements))[i]);
+ }
+ }
+ break;
+ case SQLT_ODT:
+ for (i = 0; i < bind->array.current_length; i++) {
+ char buff[1024];
+ int buff_len = 1024;
+
+ memset((void*)buff,0,sizeof(buff));
+
+ if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ connection->errcode = PHP_OCI_CALL(OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
+ zval_dtor(*entry);
+
+ if (connection->errcode != OCI_SUCCESS) {
+ php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ ZVAL_NULL(*entry);
+ }
+ ZVAL_STRINGL(*entry, buff, buff_len, 1);
+ zend_hash_move_forward(hash);
+ }
+ else {
+ connection->errcode = PHP_OCI_CALL(OCIDateToText, (connection->err, &(((OCIDate *)(bind->array.elements))[i]), 0, 0, 0, 0, &buff_len, buff));
+ if (connection->errcode != OCI_SUCCESS) {
+ php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ add_next_index_null(bind->zval);
+ }
+ add_next_index_stringl(bind->zval, buff, buff_len, 1);
+ }
+ }
+ break;
+
+ case SQLT_AFC:
+ case SQLT_CHR:
+ case SQLT_VCS:
+ case SQLT_AVC:
+ case SQLT_STR:
+ case SQLT_LVC:
+ for (i = 0; i < bind->array.current_length; i++) {
+ if ((i < bind->array.old_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ zval_dtor(*entry);
+ ZVAL_STRINGL(*entry, ((text *)bind->array.elements)+i*bind->array.max_length, bind->array.max_length, 1);
+ Z_STRVAL_PP(entry)[ bind->array.max_length ] = '\0';
+ zend_hash_move_forward(hash);
+ }
+ else {
+ add_next_index_stringl(bind->zval, ((text *)bind->array.elements)+i*bind->array.max_length, bind->array.max_length, 1);
+ }
+ }
+ break;
+ }
+ }
return 0;
}
@@ -766,6 +847,7 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, int name_len,
bindp->descriptor = oci_desc;
bindp->statement = oci_stmt;
+ bindp->parent_statement = statement;
bindp->zval = var;
zval_add_ref(&var);
@@ -995,4 +1077,271 @@ int php_oci_statement_get_numrows(php_oci_statement *statement, ub4 *numrows TSR
return 0;
} /* }}} */
+/* {{{ php_oci_bind_array_by_name()
+ Bind arrays to PL/SQL types */
+int php_oci_bind_array_by_name(php_oci_statement *statement, char *name, int name_len, zval* var, long max_table_length, long maxlength, long type TSRMLS_DC)
+{
+ php_oci_bind *bind, *bindp;
+
+ convert_to_array(var);
+
+ if (maxlength < -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid max length value (%ld)", maxlength);
+ return 1;
+ }
+
+ switch(type) {
+ case SQLT_NUM:
+ case SQLT_INT:
+ case SQLT_LNG:
+ bind = php_oci_bind_array_helper_number(var, max_table_length TSRMLS_CC);
+ break;
+
+ case SQLT_FLT:
+ bind = php_oci_bind_array_helper_double(var, max_table_length TSRMLS_CC);
+ break;
+
+ case SQLT_AFC:
+ case SQLT_CHR:
+ case SQLT_VCS:
+ case SQLT_AVC:
+ case SQLT_STR:
+ case SQLT_LVC:
+ if (maxlength == -1 && zend_hash_num_elements(Z_ARRVAL_P(var)) == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must provide max length value for empty arrays");
+ return 1;
+ }
+ bind = php_oci_bind_array_helper_string(var, max_table_length, maxlength TSRMLS_CC);
+ break;
+ case SQLT_ODT:
+ bind = php_oci_bind_array_helper_date(var, max_table_length, statement->connection TSRMLS_CC);
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not supported bind type (%ld)", type);
+ return 1;
+ break;
+ }
+
+ if (bind == NULL) {
+ /* failed to generate bind struct */
+ return 1;
+ }
+
+ if (!statement->binds) {
+ ALLOC_HASHTABLE(statement->binds);
+ zend_hash_init(statement->binds, 13, NULL, php_oci_bind_hash_dtor, 0);
+ }
+
+ zend_hash_update(statement->binds, name, name_len + 1, bind, sizeof(php_oci_bind), (void **)&bindp);
+
+ bindp->descriptor = NULL;
+ bindp->statement = NULL;
+ bindp->parent_statement = statement;
+ bindp->bind = NULL;
+ bindp->zval = var;
+ bindp->array.type = type;
+ zval_add_ref(&var);
+
+ statement->errcode = PHP_OCI_CALL(
+ OCIBindByName,
+ (
+ statement->stmt,
+ (OCIBind **)&bindp->bind,
+ statement->err,
+ (text *)name,
+ name_len,
+ (dvoid *) bindp->array.elements,
+ (sb4) bind->array.max_length,
+ type,
+ (dvoid *)0, /* bindp->array.indicators, */
+ (ub2 *)0, /* bindp->array.element_lengths, */
+ (ub2 *)0, /* bindp->array.retcodes, */
+ (ub4) max_table_length,
+ (ub4 *) &(bindp->array.current_length),
+ (ub4) OCI_DEFAULT
+ )
+ );
+
+
+ if (statement->errcode != OCI_SUCCESS) {
+ efree(bind);
+ php_oci_error(statement->err, statement->errcode TSRMLS_CC);
+ PHP_OCI_HANDLE_ERROR(statement->connection, statement->errcode);
+ return 1;
+ }
+ efree(bind);
+ return 0;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_helper_string()
+ Bind arrays to PL/SQL types */
+php_oci_bind *php_oci_bind_array_helper_string(zval* var, long max_table_length, long maxlength TSRMLS_DC)
+{
+ php_oci_bind *bind;
+ ub4 i;
+ HashTable *hash;
+ zval **entry;
+
+ hash = HASH_OF(var);
+
+ if (maxlength == -1) {
+ zend_hash_internal_pointer_reset(hash);
+ while (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE) {
+ convert_to_string_ex(entry);
+ if (Z_STRLEN_PP(entry) > maxlength) {
+ maxlength = Z_STRLEN_PP(entry);
+ }
+ zend_hash_move_forward(hash);
+ }
+ }
+
+ bind = emalloc(sizeof(php_oci_bind));
+ bind->array.elements = (text *)emalloc(max_table_length * sizeof(text) * (maxlength + 1));
+ bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
+ bind->array.old_length = bind->array.current_length;
+ bind->array.max_length = maxlength;
+
+ zend_hash_internal_pointer_reset(hash);
+ for (i = 0; i < max_table_length; i++) {
+ if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ int element_length;
+
+ convert_to_string_ex(entry);
+ element_length = (maxlength > Z_STRLEN_PP(entry)) ? Z_STRLEN_PP(entry) : maxlength;
+
+ memcpy(bind->array.elements + i*maxlength, Z_STRVAL_PP(entry), element_length);
+ ((text *)bind->array.elements)[i*maxlength + element_length] = '\0';
+
+ zend_hash_move_forward(hash);
+ }
+ else {
+ ((text *)bind->array.elements)[i*maxlength] = '\0';
+ }
+ }
+ zend_hash_internal_pointer_reset(hash);
+
+ return bind;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_helper_number()
+ Bind arrays to PL/SQL types */
+php_oci_bind *php_oci_bind_array_helper_number(zval* var, long max_table_length TSRMLS_DC)
+{
+ php_oci_bind *bind;
+ ub4 i;
+ HashTable *hash;
+ zval **entry;
+
+ hash = HASH_OF(var);
+
+ bind = emalloc(sizeof(php_oci_bind));
+ bind->array.elements = (ub4 *)emalloc(max_table_length * sizeof(ub4));
+ bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
+ bind->array.old_length = bind->array.current_length;
+ bind->array.max_length = sizeof(ub4);
+
+ zend_hash_internal_pointer_reset(hash);
+ for (i = 0; i < max_table_length; i++) {
+ if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ convert_to_long_ex(entry);
+ ((ub4 *)bind->array.elements)[i] = (ub4) Z_LVAL_PP(entry);
+ zend_hash_move_forward(hash);
+ }
+ else {
+ ((ub4 *)bind->array.elements)[i] = 0;
+ }
+ }
+ zend_hash_internal_pointer_reset(hash);
+
+ return bind;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_helper_double()
+ Bind arrays to PL/SQL types */
+php_oci_bind *php_oci_bind_array_helper_double(zval* var, long max_table_length TSRMLS_DC)
+{
+ php_oci_bind *bind;
+ ub4 i;
+ HashTable *hash;
+ zval **entry;
+
+ hash = HASH_OF(var);
+
+ bind = emalloc(sizeof(php_oci_bind));
+ bind->array.elements = (double *)emalloc(max_table_length * sizeof(double));
+ bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
+ bind->array.old_length = bind->array.current_length;
+ bind->array.max_length = sizeof(double);
+
+ zend_hash_internal_pointer_reset(hash);
+ for (i = 0; i < max_table_length; i++) {
+ if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+ convert_to_double_ex(entry);
+ ((double *)bind->array.elements)[i] = (double) Z_DVAL_PP(entry);
+ zend_hash_move_forward(hash);
+ }
+ else {
+ ((double *)bind->array.elements)[i] = 0;
+ }
+ }
+ zend_hash_internal_pointer_reset(hash);
+
+ return bind;
+} /* }}} */
+
+/* {{{ php_oci_bind_array_helper_date()
+ Bind arrays to PL/SQL types */
+php_oci_bind *php_oci_bind_array_helper_date(zval* var, long max_table_length, php_oci_connection *connection TSRMLS_DC)
+{
+ php_oci_bind *bind;
+ ub4 i;
+ HashTable *hash;
+ zval **entry;
+
+ hash = HASH_OF(var);
+
+ bind = emalloc(sizeof(php_oci_bind));
+ bind->array.elements = (OCIDate *)emalloc(max_table_length * sizeof(OCIDate));
+ bind->array.current_length = zend_hash_num_elements(Z_ARRVAL_P(var));
+ bind->array.old_length = bind->array.current_length;
+ bind->array.max_length = sizeof(OCIDate);
+
+ zend_hash_internal_pointer_reset(hash);
+ for (i = 0; i < max_table_length; i++) {
+ OCIDate oci_date;
+ if ((i < bind->array.current_length) && (zend_hash_get_current_data(hash, (void **) &entry) != FAILURE)) {
+
+ convert_to_string_ex(entry);
+ connection->errcode = PHP_OCI_CALL(OCIDateFromText, (connection->err, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), NULL, 0, NULL, 0, &oci_date));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ /* failed to convert string to date */
+ efree(bind->array.elements);
+ efree(bind);
+ php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ return NULL;
+ }
+
+ ((OCIDate *)bind->array.elements)[i] = oci_date;
+ zend_hash_move_forward(hash);
+ }
+ else {
+ connection->errcode = PHP_OCI_CALL(OCIDateFromText, (connection->err, "01-JAN-00", sizeof("01-JAN-00")-1, NULL, 0, NULL, 0, &oci_date));
+
+ if (connection->errcode != OCI_SUCCESS) {
+ /* failed to convert string to date */
+ efree(bind->array.elements);
+ efree(bind);
+ php_oci_error(connection->err, connection->errcode TSRMLS_CC);
+ return NULL;
+ }
+
+ ((OCIDate *)bind->array.elements)[i] = oci_date;
+ }
+ }
+ zend_hash_internal_pointer_reset(hash);
+
+ return bind;
+} /* }}} */
+
#endif /* HAVE_OCI8 */