diff options
| author | Marcus Boerger <helly@php.net> | 2003-09-06 18:34:55 +0000 |
|---|---|---|
| committer | Marcus Boerger <helly@php.net> | 2003-09-06 18:34:55 +0000 |
| commit | f6239c33bc5208fd3e9e6bf0f8a862b1f97a34d8 (patch) | |
| tree | 723401ea295684856b1a99423a2c8b08ace30dd9 /ext/pgsql | |
| parent | 620683792942d458df0a2a09aff2f163074f77ae (diff) | |
| download | php-git-f6239c33bc5208fd3e9e6bf0f8a862b1f97a34d8.tar.gz | |
Modify pg_fetch_object() to be able to instantiate a selected class and pass
parameters to the constructor. Update tests and add a test for these features.
Diffstat (limited to 'ext/pgsql')
| -rw-r--r-- | ext/pgsql/pgsql.c | 176 | ||||
| -rw-r--r-- | ext/pgsql/tests/03sync_query.phpt | 2 | ||||
| -rw-r--r-- | ext/pgsql/tests/04async_query.phpt | 2 | ||||
| -rw-r--r-- | ext/pgsql/tests/17result.phpt | 4 | ||||
| -rwxr-xr-x | ext/pgsql/tests/22pg_fetch_object.phpt | 37 |
5 files changed, 158 insertions, 63 deletions
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 8ad85502c9..148f289aea 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -37,6 +37,7 @@ #include "ext/standard/php_smart_str.h" #include "php_pgsql.h" #include "php_globals.h" +#include "zend_default_classes.h" #if HAVE_PGSQL @@ -1397,72 +1398,69 @@ PHP_FUNCTION(pg_fetch_result) /* }}} */ /* {{{ void php_pgsql_fetch_hash */ -static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) +static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type, int into_object) { - zval **result, **row, **arg3; - PGresult *pgsql_result; + zval *result; + PGresult *pgsql_result; pgsql_result_handle *pg_result; - int i, num_fields, pgsql_row; - char *element, *field_name; - uint element_len; - - switch (ZEND_NUM_ARGS()) { - case 1: /* pg_fetch_*(result) */ - if (zend_get_parameters_ex(1, &result) == FAILURE) { - RETURN_FALSE; - } - break; - case 2: /* pg_fetch_*(result, row) */ - if (zend_get_parameters_ex(2, &result, &row) == FAILURE) { - RETURN_FALSE; - } - break; - case 3: /* pg_fetch_*(result, row, result_type) */ - if (zend_get_parameters_ex(3, &result, &row, &arg3) == FAILURE) { - RETURN_FALSE; - } - convert_to_long_ex(arg3); - result_type = Z_LVAL_PP(arg3); - break; - default: - WRONG_PARAM_COUNT; - break; + int i, num_fields, pgsql_row, use_row; + long row; + char *element, *field_name; + uint element_len; + zval *ctor_params = NULL; + zend_class_entry *ce = NULL; + + if (into_object) { + char *class_name; + int class_name_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|sz", &result, &class_name, &class_name_len, &ctor_params) == FAILURE) { + return; + } + if (ZEND_NUM_ARGS() < 2) { + ce = zend_standard_class_def; + } else { + ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); + } + if (!ce) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name); + return; + } + result_type = PGSQL_ASSOC; + use_row = 0; + } else { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ll", &result, &row, &result_type) == FAILURE) { + return; + } + use_row = ZEND_NUM_ARGS() > 1; } - + if (!(result_type & PGSQL_BOTH)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type"); RETURN_FALSE; } - ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result); + ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; - if (ZEND_NUM_ARGS() == 1) { - pgsql_row = pg_result->row; + if (use_row) { + pgsql_row = row; + pg_result->row = pgsql_row; if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld", + row, Z_LVAL_P(result)); RETURN_FALSE; } - pg_result->row++; } else { - if (Z_TYPE_PP(row) != IS_NULL) { - convert_to_long_ex(row); - pgsql_row = Z_LVAL_PP(row); - pg_result->row = pgsql_row; - if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld", - Z_LVAL_PP(row), Z_LVAL_PP(result)); - RETURN_FALSE; - } - } else { - /* If 2nd param is NULL, use internal row counter to access next row */ - pgsql_row = pg_result->row; - if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { - RETURN_FALSE; - } - pg_result->row++; + /* If 2nd param is NULL, use internal row counter to access next row */ + pgsql_row = pg_result->row; + if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { + RETURN_FALSE; } + pg_result->row++; } + array_init(return_value); for (i = 0, num_fields = PQnfields(pgsql_result); i < num_fields; i++) { if (PQgetisnull(pgsql_result, pgsql_row, i)) { @@ -1500,6 +1498,70 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) } } } + + if (into_object) { + zval dataset = *return_value; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + zval *retval_ptr; + + object_and_properties_init(return_value, ce, NULL); + zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC); + + if (ce->constructor) { + fci.size = sizeof(fci); + fci.function_table = &ce->function_table; + fci.function_name = NULL; + fci.symbol_table = NULL; + fci.object_pp = &return_value; + fci.retval_ptr_ptr = &retval_ptr; + if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) { + if (Z_TYPE_P(ctor_params) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(ctor_params); + Bucket *p; + + fci.param_count = 0; + fci.params = emalloc(sizeof(zval*) * ht->nNumOfElements); + p = ht->pListHead; + while (p != NULL) { + fci.params[fci.param_count++] = (zval**)p->pData; + p = p->pListNext; + } + } else { + /* Two problems why we throw exceptions here: PHP is typeless + * and hence passing one argument that's not an array could be + * by mistake and the other way round is possible, too. The + * single value is an array. Also we'd have to make that one + * argument passed by reference. + */ + zend_throw_exception(zend_exception_get_default(), "Parameter ctor_params must be an array", 0 TSRMLS_CC); + return; + } + } else { + fci.param_count = 0; + fci.params = NULL; + } + fci.no_separation = 1; + + fcc.initialized = 1; + fcc.function_handler = ce->constructor; + fcc.calling_scope = EG(scope); + fcc.object_pp = &return_value; + + if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) { + zend_throw_exception_ex(zend_exception_get_default(), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name); + } else { + if (retval_ptr) { + zval_ptr_dtor(&retval_ptr); + } + } + if (fci.params) { + efree(fci.params); + } + } else if (ctor_params) { + zend_throw_exception_ex(zend_exception_get_default(), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name); + } + } } /* }}} */ @@ -1507,7 +1569,7 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) Get a row as an enumerated array */ PHP_FUNCTION(pg_fetch_row) { - php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_NUM); + php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_NUM, 0); } /* }}} */ @@ -1519,7 +1581,7 @@ PHP_FUNCTION(pg_fetch_assoc) there is 3rd parameter */ if (ZEND_NUM_ARGS() > 2) WRONG_PARAM_COUNT; - php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC); + php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 0); } /* }}} */ @@ -1527,23 +1589,17 @@ PHP_FUNCTION(pg_fetch_assoc) Fetch a row as an array */ PHP_FUNCTION(pg_fetch_array) { - php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_BOTH); + php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_BOTH, 0); } /* }}} */ -/* {{{ proto object pg_fetch_object(resource result [, int row]) +/* {{{ proto object pg_fetch_object(resource result [, string class_name [, NULL|array ctor_params]]) Fetch a row as an object */ PHP_FUNCTION(pg_fetch_object) { /* pg_fetch_object() allowed result_type used to be. 3rd parameter must be allowed for compatibility */ - php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC); - if (Z_TYPE_P(return_value)==IS_ARRAY) { - object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value)); - } else { - zval_dtor(return_value); - return_value->type = IS_NULL; - } + php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 1); } /* }}} */ diff --git a/ext/pgsql/tests/03sync_query.phpt b/ext/pgsql/tests/03sync_query.phpt index c65426d7d8..96827fe5a2 100644 --- a/ext/pgsql/tests/03sync_query.phpt +++ b/ext/pgsql/tests/03sync_query.phpt @@ -20,7 +20,7 @@ for ($i=0; $i < $rows; $i++) } for ($i=0; $i < $rows; $i++) { - pg_fetch_object($result, $i, PGSQL_ASSOC); + pg_fetch_object($result); } for ($i=0; $i < $rows; $i++) { diff --git a/ext/pgsql/tests/04async_query.phpt b/ext/pgsql/tests/04async_query.phpt index 15728ec1ee..7711240a79 100644 --- a/ext/pgsql/tests/04async_query.phpt +++ b/ext/pgsql/tests/04async_query.phpt @@ -30,7 +30,7 @@ for ($i=0; $i < $rows; $i++) } for ($i=0; $i < $rows; $i++) { - pg_fetch_object($result, $i, PGSQL_ASSOC); + pg_fetch_object($result); } for ($i=0; $i < $rows; $i++) { diff --git a/ext/pgsql/tests/17result.phpt b/ext/pgsql/tests/17result.phpt index 265d00c657..c3f9959aa2 100644 --- a/ext/pgsql/tests/17result.phpt +++ b/ext/pgsql/tests/17result.phpt @@ -14,7 +14,8 @@ $sql = "SELECT * FROM $table_name"; $result = pg_query($db, $sql) or die('Cannot qeury db'); $rows = pg_num_rows($result); -var_dump(pg_fetch_object($result, 1)); +var_dump(pg_result_seek($result, 1)); +var_dump(pg_fetch_object($result)); var_dump(pg_fetch_array($result, 1)); var_dump(pg_fetch_row($result, 1)); var_dump(pg_fetch_assoc($result, 1)); @@ -23,6 +24,7 @@ var_dump(pg_result_seek($result, 0)); echo "Ok\n"; ?> --EXPECT-- +bool(true) object(stdClass)#1 (3) { ["num"]=> string(1) "1" diff --git a/ext/pgsql/tests/22pg_fetch_object.phpt b/ext/pgsql/tests/22pg_fetch_object.phpt new file mode 100755 index 0000000000..d0b406d879 --- /dev/null +++ b/ext/pgsql/tests/22pg_fetch_object.phpt @@ -0,0 +1,37 @@ +--TEST-- +PostgreSQL pg_fetch_*() functions +--SKIPIF-- +<?php include("skipif.inc"); ?> +--FILE-- +<?php +error_reporting(E_ALL); + +include 'config.inc'; + +class test_class { + function __construct($arg1, $arg2) { + echo __METHOD__ . "($arg1,$arg2)\n"; + } +} + +$db = pg_connect($conn_str); + +$sql = "SELECT * FROM $table_name"; +$result = pg_query($db, $sql) or die('Cannot qeury db'); +$rows = pg_num_rows($result); + +var_dump(pg_fetch_object($result, 'test_class', array(1, 2))); + +echo "Ok\n"; +?> +--EXPECT-- +test_class::__construct(1,2) +object(test_class)#1 (3) { + ["num"]=> + string(1) "0" + ["str"]=> + string(3) "ABC" + ["bin"]=> + NULL +} +Ok |
