helly Sat Sep 6 14:34:55 2003 EDT
Added files:
/php-src/ext/pgsql/tests 22pg_fetch_object.phpt
Modified files:
/php-src/ext/pgsql pgsql.c
/php-src/ext/pgsql/tests 03sync_query.phpt 04async_query.phpt
17result.phpt
Log:
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.
Index: php-src/ext/pgsql/pgsql.c
diff -u php-src/ext/pgsql/pgsql.c:1.295 php-src/ext/pgsql/pgsql.c:1.296
--- php-src/ext/pgsql/pgsql.c:1.295 Sat Sep 6 11:30:28 2003
+++ php-src/ext/pgsql/pgsql.c Sat Sep 6 14:34:54 2003
@@ -19,7 +19,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: pgsql.c,v 1.295 2003/09/06 15:30:28 helly Exp $ */
+/* $Id: pgsql.c,v 1.296 2003/09/06 18:34:54 helly Exp $ */
#include <stdlib.h>
@@ -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 @@
/* }}} */
/* {{{ 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;
+ 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;
- 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;
+ 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 @@
}
}
}
+
+ 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 @@
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 @@
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 @@
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);
}
/* }}} */
Index: php-src/ext/pgsql/tests/03sync_query.phpt
diff -u php-src/ext/pgsql/tests/03sync_query.phpt:1.2
php-src/ext/pgsql/tests/03sync_query.phpt:1.3
--- php-src/ext/pgsql/tests/03sync_query.phpt:1.2 Mon May 19 20:14:46 2003
+++ php-src/ext/pgsql/tests/03sync_query.phpt Sat Sep 6 14:34:55 2003
@@ -20,7 +20,7 @@
}
for ($i=0; $i < $rows; $i++)
{
- pg_fetch_object($result, $i, PGSQL_ASSOC);
+ pg_fetch_object($result);
}
for ($i=0; $i < $rows; $i++)
{
Index: php-src/ext/pgsql/tests/04async_query.phpt
diff -u php-src/ext/pgsql/tests/04async_query.phpt:1.2
php-src/ext/pgsql/tests/04async_query.phpt:1.3
--- php-src/ext/pgsql/tests/04async_query.phpt:1.2 Mon May 19 20:14:46 2003
+++ php-src/ext/pgsql/tests/04async_query.phpt Sat Sep 6 14:34:55 2003
@@ -30,7 +30,7 @@
}
for ($i=0; $i < $rows; $i++)
{
- pg_fetch_object($result, $i, PGSQL_ASSOC);
+ pg_fetch_object($result);
}
for ($i=0; $i < $rows; $i++)
{
Index: php-src/ext/pgsql/tests/17result.phpt
diff -u php-src/ext/pgsql/tests/17result.phpt:1.3
php-src/ext/pgsql/tests/17result.phpt:1.4
--- php-src/ext/pgsql/tests/17result.phpt:1.3 Mon May 19 20:14:46 2003
+++ php-src/ext/pgsql/tests/17result.phpt Sat Sep 6 14:34:55 2003
@@ -14,7 +14,8 @@
$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 @@
echo "Ok\n";
?>
--EXPECT--
+bool(true)
object(stdClass)#1 (3) {
["num"]=>
string(1) "1"
Index: php-src/ext/pgsql/tests/22pg_fetch_object.phpt
+++ php-src/ext/pgsql/tests/22pg_fetch_object.phpt
--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
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php