diff options
| -rw-r--r-- | ext/dbx/dbx.c | 155 | ||||
| -rw-r--r-- | ext/dbx/dbx.h | 1 | ||||
| -rw-r--r-- | ext/dbx/php_dbx.h | 1 | ||||
| -rw-r--r-- | ext/dbx/tests/002.phpt | 1 | ||||
| -rw-r--r-- | ext/dbx/tests/005.phpt | 7 | ||||
| -rw-r--r-- | ext/dbx/tests/010.phpt | 52 |
6 files changed, 189 insertions, 28 deletions
diff --git a/ext/dbx/dbx.c b/ext/dbx/dbx.c index cbb8424c06..0116d9459a 100644 --- a/ext/dbx/dbx.c +++ b/ext/dbx/dbx.c @@ -100,6 +100,20 @@ int split_dbx_handle_object(zval **dbx_object, zval ***pdbx_handle, zval ***pdbx return 1; } +int split_dbx_result_object(zval **dbx_result, zval ***pdbx_link, zval ***pdbx_handle, zval ***pdbx_flags, zval ***pdbx_info, zval ***pdbx_cols , zval ***pdbx_rows TSRMLS_DC) +{ + convert_to_object_ex(dbx_result); + if (zend_hash_find(Z_OBJPROP_PP(dbx_result), "link", 5, (void **) pdbx_link)==FAILURE + || zend_hash_find(Z_OBJPROP_PP(dbx_result), "handle", 7, (void **) pdbx_handle)==FAILURE + || zend_hash_find(Z_OBJPROP_PP(dbx_result), "flags", 6, (void **) pdbx_flags)==FAILURE + || zend_hash_find(Z_OBJPROP_PP(dbx_result), "info", 5, (void **) pdbx_info)==FAILURE + || zend_hash_find(Z_OBJPROP_PP(dbx_result), "cols", 5, (void **) pdbx_cols)==FAILURE + || zend_hash_find(Z_OBJPROP_PP(dbx_result), "rows", 5, (void **) pdbx_rows)==FAILURE) { + return 0; + } + return 1; +} + /* from dbx.h, to be used in support-files (dbx_mysql.c etc...) */ void dbx_call_any_function(INTERNAL_FUNCTION_PARAMETERS, char *function_name, zval **returnvalue, int number_of_arguments, zval ***params) { @@ -149,6 +163,7 @@ function_entry dbx_functions[] = { ZEND_FE(dbx_connect, NULL) ZEND_FE(dbx_close, NULL) ZEND_FE(dbx_query, NULL) + ZEND_FE(dbx_fetch_row, NULL) ZEND_FE(dbx_error, NULL) ZEND_FE(dbx_escape_string, NULL) @@ -197,6 +212,7 @@ ZEND_MINIT_FUNCTION(dbx) REGISTER_LONG_CONSTANT("DBX_RESULT_INFO", DBX_RESULT_INFO, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DBX_RESULT_INDEX", DBX_RESULT_INDEX, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DBX_RESULT_ASSOC", DBX_RESULT_ASSOC, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("DBX_RESULT_UNBUFFERED", DBX_RESULT_UNBUFFERED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DBX_COLNAMES_UNCHANGED", DBX_COLNAMES_UNCHANGED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DBX_COLNAMES_UPPERCASE", DBX_COLNAMES_UPPERCASE, CONST_CS | CONST_PERSISTENT); @@ -231,7 +247,7 @@ ZEND_MINFO_FUNCTION(dbx) { php_info_print_table_start(); php_info_print_table_row(2, "dbx support", "enabled"); - php_info_print_table_row(2, "dbx version", "1.0.1"); + php_info_print_table_row(2, "dbx version", "1.1.0"); php_info_print_table_row(2, "supported databases", "MySQL\nODBC\nPostgreSQL\nMicrosoft SQL Server\nFrontBase\nOracle 8 (oci8)\nSybase-CT\nSQLite"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); @@ -395,11 +411,12 @@ ZEND_FUNCTION(dbx_query) convert_to_long_ex(arguments[2]); query_flags = Z_LVAL_PP(arguments[2]); /* fieldnames are needed for association! */ - result_flags = (query_flags & DBX_RESULT_INFO) | (query_flags & DBX_RESULT_INDEX) | (query_flags & DBX_RESULT_ASSOC); + result_flags = (query_flags & DBX_RESULT_INFO) | (query_flags & DBX_RESULT_INDEX) | (query_flags & DBX_RESULT_ASSOC) | (query_flags & DBX_RESULT_UNBUFFERED); if (result_flags & DBX_RESULT_ASSOC) { result_flags |= DBX_RESULT_INFO; } if (!result_flags) result_flags = DBX_RESULT_INFO | DBX_RESULT_INDEX | DBX_RESULT_ASSOC; + if (result_flags == DBX_RESULT_UNBUFFERED) result_flags |= DBX_RESULT_INFO | DBX_RESULT_INDEX | DBX_RESULT_ASSOC; /* override ini-setting for colcase */ if (query_flags & DBX_COLNAMES_UNCHANGED) { colcase = DBX_COLNAMES_UNCHANGED; @@ -427,8 +444,15 @@ ZEND_FUNCTION(dbx_query) /* init return_value as object (of rows) */ object_init(return_value); + zend_hash_update(Z_OBJPROP_P(return_value), "link", 5, (void *)(arguments[0]), sizeof(zval *), NULL); + /* need extra refcount here otherwise the link object is destroyed when the + * query resultobject is destroyed (or not assigned!) + */ + zval_add_ref(arguments[0]); /* add result_handle property to return_value */ zend_hash_update(Z_OBJPROP_P(return_value), "handle", 7, (void *)&(rv_result_handle), sizeof(zval *), NULL); + /* add flags property to return_value */ + add_property_long(return_value, "flags", result_flags | colcase); /* init info property as array and add to return_value as a property */ if (result_flags & DBX_RESULT_INFO) { MAKE_STD_ZVAL(info); @@ -436,9 +460,11 @@ ZEND_FUNCTION(dbx_query) zend_hash_update(Z_OBJPROP_P(return_value), "info", 5, (void *)&(info), sizeof(zval *), NULL); } /* init data property as array and add to return_value as a property */ - MAKE_STD_ZVAL(data); - array_init(data); - zend_hash_update(Z_OBJPROP_P(return_value), "data", 5, (void *)&(data), sizeof(zval *), NULL); + if (!(result_flags & DBX_RESULT_UNBUFFERED)) { + MAKE_STD_ZVAL(data); + array_init(data); + zend_hash_update(Z_OBJPROP_P(return_value), "data", 5, (void *)&(data), sizeof(zval *), NULL); + } /* get columncount and add to returnvalue as property */ MAKE_STD_ZVAL(rv_column_count); ZVAL_LONG(rv_column_count, 0); @@ -490,36 +516,109 @@ ZEND_FUNCTION(dbx_query) zend_hash_update(Z_ARRVAL_P(info), "type", 5, (void *) &info_row_type, sizeof(zval *), NULL); } /* fill each row array with fieldvalues (indexed (and assoc)) */ - row_count=0; - result=1; - while (result) { - zval *rv_row; - MAKE_STD_ZVAL(rv_row); - ZVAL_LONG(rv_row, 0); - result = switch_dbx_getrow(&rv_row, &rv_result_handle, row_count, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module); - if (result) { - zend_hash_index_update(Z_ARRVAL_P(data), row_count, (void *)&(rv_row), sizeof(zval *), (void **) &row_ptr); - /* associate results with fieldnames */ - if (result_flags & DBX_RESULT_ASSOC) { - zval **columnname_ptr, **actual_ptr; - for (col_index=0; col_index<Z_LVAL_P(rv_column_count); ++col_index) { - zend_hash_index_find(Z_ARRVAL_PP(inforow_ptr), col_index, (void **) &columnname_ptr); - zend_hash_index_find(Z_ARRVAL_PP(row_ptr), col_index, (void **) &actual_ptr); - (*actual_ptr)->refcount+=1; - (*actual_ptr)->is_ref=1; - zend_hash_update(Z_ARRVAL_PP(row_ptr), Z_STRVAL_PP(columnname_ptr), Z_STRLEN_PP(columnname_ptr) + 1, actual_ptr, sizeof(zval *), NULL); + if (!(result_flags & DBX_RESULT_UNBUFFERED)) { + row_count=0; + result=1; + while (result) { + zval *rv_row; + MAKE_STD_ZVAL(rv_row); + ZVAL_LONG(rv_row, 0); + result = switch_dbx_getrow(&rv_row, &rv_result_handle, row_count, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module); + if (result) { + zend_hash_index_update(Z_ARRVAL_P(data), row_count, (void *)&(rv_row), sizeof(zval *), (void **) &row_ptr); + /* associate results with fieldnames */ + if (result_flags & DBX_RESULT_ASSOC) { + zval **columnname_ptr, **actual_ptr; + for (col_index=0; col_index<Z_LVAL_P(rv_column_count); ++col_index) { + zend_hash_index_find(Z_ARRVAL_PP(inforow_ptr), col_index, (void **) &columnname_ptr); + zend_hash_index_find(Z_ARRVAL_PP(row_ptr), col_index, (void **) &actual_ptr); + (*actual_ptr)->refcount+=1; + (*actual_ptr)->is_ref=1; + zend_hash_update(Z_ARRVAL_PP(row_ptr), Z_STRVAL_PP(columnname_ptr), Z_STRLEN_PP(columnname_ptr) + 1, actual_ptr, sizeof(zval *), NULL); + } } + ++row_count; + } else { + FREE_ZVAL(rv_row); + } + } + /* add row_count property */ + add_property_long(return_value, "rows", row_count); + } + else { + add_property_long(return_value, "rows", 0); + } +} +/* }}} */ + +/* {{{ proto dbx_row dbx_fetch_row(dbx_query_object dbx_q) + Returns a row (index and assoc based on query) on success and returns 0 on failure or no more rows */ +ZEND_FUNCTION(dbx_fetch_row) +{ + int min_number_of_arguments=1; + int number_of_arguments=1; + zval **arguments[1]; + + zval **dbx_result_link; + zval **dbx_result_handle; + zval **dbx_result_flags; + zval **dbx_result_info; + zval **dbx_result_cols; + zval **dbx_result_rows; + + zval **dbx_handle; + zval **dbx_module; + zval **dbx_database; + + int result; + long col_index; + long col_count; + long row_count; + long result_flags; + zval **inforow_ptr; + + if (ZEND_NUM_ARGS()!=number_of_arguments || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), arguments) == FAILURE) { + WRONG_PARAM_COUNT; + } + if (!split_dbx_result_object(arguments[0], &dbx_result_link, &dbx_result_handle, &dbx_result_flags, &dbx_result_info, &dbx_result_cols, &dbx_result_rows TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "not a valid dbx_result-object..."); + RETURN_LONG(0); + } + if (!split_dbx_handle_object(dbx_result_link, &dbx_handle, &dbx_module, &dbx_database TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "not a valid dbx_handle-object..."); + RETURN_LONG(0); + } + + /* default values */ + result_flags = Z_LVAL_PP(dbx_result_flags); + col_count = Z_LVAL_PP(dbx_result_cols); + row_count = Z_LVAL_PP(dbx_result_rows); + + /* find fieldnames (for assoc) */ + if (result_flags & DBX_RESULT_ASSOC) { + zend_hash_find(Z_ARRVAL_PP(dbx_result_info), "name", 5, (void **) &inforow_ptr); + } + + result = switch_dbx_getrow(&return_value, dbx_result_handle, row_count, INTERNAL_FUNCTION_PARAM_PASSTHRU, dbx_module); + if (result) { + /* associate results with fieldnames */ + if (result_flags & DBX_RESULT_ASSOC) { + zval **columnname_ptr, **actual_ptr; + for (col_index=0; col_index<col_count; ++col_index) { + zend_hash_index_find(Z_ARRVAL_PP(inforow_ptr), col_index, (void **) &columnname_ptr); + zend_hash_index_find(Z_ARRVAL_P(return_value), col_index, (void **) &actual_ptr); + (*actual_ptr)->refcount+=1; + (*actual_ptr)->is_ref=1; + zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_PP(columnname_ptr), Z_STRLEN_PP(columnname_ptr) + 1, actual_ptr, sizeof(zval *), NULL); } - ++row_count; - } else { - FREE_ZVAL(rv_row); } + ++row_count; + add_property_long(*arguments[0], "rows", row_count); } - /* add row_count property */ - add_property_long(return_value, "rows", row_count); } /* }}} */ + /* {{{ proto string dbx_error(dbx_link_object dbx_link) Returns success or failure */ diff --git a/ext/dbx/dbx.h b/ext/dbx/dbx.h index eb784e8e91..d627921a8b 100644 --- a/ext/dbx/dbx.h +++ b/ext/dbx/dbx.h @@ -40,6 +40,7 @@ #define DBX_COLNAMES_UNCHANGED (1<<3) #define DBX_COLNAMES_UPPERCASE (1<<4) #define DBX_COLNAMES_LOWERCASE (1<<5) +#define DBX_RESULT_UNBUFFERED (1<<6) #define DBX_CMP_NATIVE (1<<0) #define DBX_CMP_TEXT (1<<1) diff --git a/ext/dbx/php_dbx.h b/ext/dbx/php_dbx.h index 6fc33d9f58..3e8e8c5d35 100644 --- a/ext/dbx/php_dbx.h +++ b/ext/dbx/php_dbx.h @@ -48,6 +48,7 @@ ZEND_MINFO_FUNCTION(dbx); ZEND_FUNCTION(dbx_connect); ZEND_FUNCTION(dbx_close); ZEND_FUNCTION(dbx_query); +ZEND_FUNCTION(dbx_fetch_row); ZEND_FUNCTION(dbx_error); ZEND_FUNCTION(dbx_escape_string); diff --git a/ext/dbx/tests/002.phpt b/ext/dbx/tests/002.phpt index f3ec8eeef3..b708b66aca 100644 --- a/ext/dbx/tests/002.phpt +++ b/ext/dbx/tests/002.phpt @@ -16,6 +16,7 @@ if (DBX_PERSISTENT=="DBX_PERSISTENT") print('!DBX_PERSISTENT'); if (DBX_RESULT_INFO=="DBX_RESULT_INFO") print('!DBX_RESULT_INFO'); if (DBX_RESULT_INDEX=="DBX_RESULT_INDEX") print('!DBX_RESULT_INDEX'); if (DBX_RESULT_ASSOC=="DBX_RESULT_ASSOC") print('!DBX_RESULT_ASSOC'); +if (DBX_RESULT_UNBUFFERED=="DBX_RESULT_UNBUFFERED") print('!DBX_RESULT_UNBUFFERED'); if (DBX_COLNAMES_UNCHANGED=="DBX_COLNAMES_UNCHANGED") print('!DBX_COLNAMES_UNCHANGED'); if (DBX_COLNAMES_UPPERCASE=="DBX_COLNAMES_UPPERCASE") print('!DBX_COLNAMES_UPPERCASE'); if (DBX_COLNAMES_LOWERCASE=="DBX_COLNAMES_LOWERCASE") print('!DBX_COLNAMES_LOWERCASE'); diff --git a/ext/dbx/tests/005.phpt b/ext/dbx/tests/005.phpt index d12e1ca893..354d7ec564 100644 --- a/ext/dbx/tests/005.phpt +++ b/ext/dbx/tests/005.phpt @@ -58,6 +58,13 @@ else { } } } + // DBX_RESULT_UNBUFFERED + if ($dro=dbx_query($dlo, $sql_statement, DBX_RESULT_UNBUFFERED)) { + $properties = get_object_vars($dro); + if (array_key_exists('data', $properties)) { + print("data property not expected with DBX_RESULT_UNBUFFERED flag."); + } + } // colnames_case flags if ($dro=dbx_query($dlo, $sql_statement, DBX_COLNAMES_LOWERCASE)) { print('column name lowercased: '); diff --git a/ext/dbx/tests/010.phpt b/ext/dbx/tests/010.phpt new file mode 100644 index 0000000000..66f423de2c --- /dev/null +++ b/ext/dbx/tests/010.phpt @@ -0,0 +1,52 @@ +--TEST-- +dbx_fetch_row +--SKIPIF-- +<?php +include_once("skipif.inc"); +?> +--INI-- +magic_quotes_runtime=0 +--FILE-- +<?php +include_once("dbx_test.p"); +$sql_statement = "select * from tbl order by id"; + +$dlo = dbx_connect($module, $host, $database, $username, $password); +if (!$dlo) { + print('this won\'t work'."\n"); + } +else { + // especially for sybase I need to set the textsize to >64 k, as one of the test-fields + // requires this (shouldn't this be a php.ini-entry??) + if ($connection === DBX_SYBASECT) @dbx_query($dlo, "set textsize 100000"); + // select query + if ($dro=dbx_query($dlo, $sql_statement, DBX_RESULT_UNBUFFERED)) { + while ($row = dbx_fetch_row($dro)) { + print($dro->rows.".".$row['id'].".".$row['description'].".".$row['field1'].".".strlen($row['field2'])."\n"); + } + } + // generate errors + $invalid_result_object = 'invalid'; + if (!@dbx_fetch_row($invalid_result_object)) { + print('wrong dbx_result_object: fetch_row failure works ok'."\n"); + } + if (!@dbx_fetch_row($dro, "12many")) { + print('too many parameters: fetch_row failure works ok'."\n"); + } + if (!@dbx_fetch_row()) { + print('too few parameters: fetch_row failure works ok'."\n"); + } + dbx_close($dlo); + } +?> +--EXPECT-- +1.1.root.empty fields.0 +2.10.abc.field2 contains single quote.3 +3.20.cba.field2 contains double quote.3 +4.30.bac.field2 contains >4k text.4591 +5.40.100.field2 contains >64k text.70051 +6.50.20.empty fields.0 +7.60.20.empty fields.0 +wrong dbx_result_object: fetch_row failure works ok +too many parameters: fetch_row failure works ok +too few parameters: fetch_row failure works ok |
