Re: Modifications for Postgres driver

From: Date: Tue, 19 Jun 2001 14:28:42 +0000
Subject: Re: Modifications for Postgres driver
References: 1  Groups: php.dev 
Request: Send a blank email to php-dev+get-57263@lists.php.net to get a copy of this message
Hi! I wrote: > What I disliked (like the PEAR people) is the missing of a > row counter when fetching rows from Postgres result tables. > > The mysql/ODBC/Adabas/some-other - way is: > > $dbr = xxx_exec ($connection, $query); > while (list ($a, $b, $c) = xxx_fetch_row ($dbr)) { > ... // Great, I have my results > } > > The traditional and only Postgres way is: > > $dbr = xxx_exec ($connection, $query); > $cnt = pg_num_rows ($dbr); > for ($i = 0; $i < $cnt; $i++) { > list ($a, $b, $c) = pg_fetch_row ($dbr, $i) > } Now, the patch for PHP 4.0.5 is attached, together with a description. Could anybody with CVS access test it / apply it? I think who writes the code should also do some documentation. I do not know the "source format" of the documentation and where to get it - could somebody mail me the Postgres-Doc- Sources? Thanks a lot, Georg ------------ snip ------------- description ---------- The patch enables the Postgresql-driver to do the row counting within the driver when iterating through an array. It does this by adding a row counter to the internal data structure of the postgres result set. Instead of writing: $dbr = pg_exec ($connection, $query); $cnt = pg_numrows ($dbr); for ($i = 0; $i < $cnt; $i++) { list ($a, $b, $c) = pg_fetch_row ($dbr, $i) ... // Got the data here } one *can* write: $dbr = pg_exec ($connection, $query); while (list ($a, $b, $c) = pg_fetch_row ($dbr)) { ... // Great, I have my results } This unifies the behaviour with other PHP database drivers and helps the PEAR-libary developers (see notes there). Moreover, one can e.g. write: $dbr = pg_exec ("SELECT MAX(id)+1 FROM table"); // Try to get the new id if (! ($newid = pg_result ($dbr, 0))) $newid = 1; // No row found // Insert with the new id here instead of verifying first if a row is available. This is a description of the API change: The following functions have a different syntax PG_RESULT Old syntax: pg_result (<resultset>, <row>, <field>) New syntax: pg_result (<resultset>, [<row>,] <field>) Change: If row is ommited, the result is taken from the current data row. If no row has been fetched yet, the first row will be fetched. If there is no result row, false will be silently returned without an error message. Traditional behaviour is not affected. PG_FETCH_ROW / PG_FETCH_ARRAY / PG_FETCH_OBJECT Old syntax: pg_fetch_<func> (<resultset>, <row> [, <resulttype>]) New syntax: pg_fetch_<func> (<resultset>, [<row> [, <resulttype>]]) Change: If row is ommited, the next row is fetched. If row is ommited, and the last row is reached, no error will be written, but silently false returned. Traditional behaviour not affected. It is not possible to ommit the row but to specify a resulttype. PG_FIELDPRTLEN / PG_FIELDISNULL Old syntax: pg_field<func> (<resultset>, <row>, <field>) New syntax: pg_field<func> (<resultset>, [<row>,] <field>) Change: If row is ommited, the result is taken from the current data row. If no row has been fetched yet, the first row will be fetched. If there is no result row, false will be silently returned without an error message. Traditional behaviour is not affected. ------------ snip ------------- patch ---------- diff -r -c php-4.0.5.orig/ext/pgsql/pgsql.c php-4.0.5/ext/pgsql/pgsql.c *** php-4.0.5.orig/ext/pgsql/pgsql.c Wed Apr 4 23:51:58 2001 --- php-4.0.5/ext/pgsql/pgsql.c Wed Jun 20 13:20:38 2001 *************** *** 713,718 **** --- 713,719 ---- pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle)); pg_result->conn = pgsql; pg_result->result = pgsql_result; + pg_result->row = -1; ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result); /* return_value->value.lval = zend_list_insert(pg_result,le_result); *************** *** 1010,1029 **** zval **result, **row, **field=NULL; PGresult *pgsql_result; pgsql_result_handle *pg_result; ! int field_offset; ! if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &result, &row, &field)==FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; ! ! convert_to_long_ex(row); ! if (Z_LVAL_PP(row) < 0 || Z_LVAL_PP(row) >= PQntuples(pgsql_result)) { ! php_error(E_WARNING,"Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result)); ! RETURN_FALSE; } switch(Z_TYPE_PP(field)) { case IS_STRING: --- 1011,1040 ---- zval **result, **row, **field=NULL; PGresult *pgsql_result; pgsql_result_handle *pg_result; ! int field_offset, pgsql_row; ! if ((ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &result, &row, &field)==FAILURE) && ! (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &result, &field)==FAILURE)) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; ! if (ZEND_NUM_ARGS() == 2) { ! if (pg_result->row < 0) ! pg_result->row = 0; ! pgsql_row = pg_result->row; ! if (pgsql_row >= PQntuples(pgsql_result)) { ! RETURN_FALSE; ! } ! } else { ! convert_to_long_ex(row); ! pgsql_row = Z_LVAL_PP(row); ! if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { ! php_error(E_WARNING,"Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result)); ! RETURN_FALSE; ! } } switch(Z_TYPE_PP(field)) { case IS_STRING: *************** *** 1039,1048 **** RETURN_FALSE; } ! if (PQgetisnull(pgsql_result, Z_LVAL_PP(row), field_offset)) { return_value->type = IS_NULL; } else { ! return_value->value.str.val = PQgetvalue(pgsql_result, Z_LVAL_PP(row), field_offset); return_value->value.str.len = (return_value->value.str.val ? strlen(return_value->value.str.val) : 0); return_value->value.str.val = safe_estrndup(return_value->value.str.val,return_value->value.str.len); return_value->type = IS_STRING; --- 1050,1059 ---- RETURN_FALSE; } ! if (PQgetisnull(pgsql_result, pgsql_row, field_offset)) { return_value->type = IS_NULL; } else { ! return_value->value.str.val = PQgetvalue(pgsql_result, pgsql_row, field_offset); return_value->value.str.len = (return_value->value.str.val ? strlen(return_value->value.str.val) : 0); return_value->value.str.val = safe_estrndup(return_value->value.str.val,return_value->value.str.len); return_value->type = IS_STRING; *************** *** 1056,1067 **** zval **result, **row, **arg3; PGresult *pgsql_result; pgsql_result_handle *pg_result; ! int i, num_fields; char *element, *field_name; uint element_len; PLS_FETCH(); switch (ZEND_NUM_ARGS()) { case 2: if (zend_get_parameters_ex(2, &result, &row)==FAILURE) { RETURN_FALSE; --- 1067,1086 ---- zval **result, **row, **arg3; PGresult *pgsql_result; pgsql_result_handle *pg_result; ! int i, num_fields, pgsql_row; char *element, *field_name; uint element_len; PLS_FETCH(); switch (ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &result)==FAILURE) { + RETURN_FALSE; + } + if (!result_type) { + result_type = PGSQL_BOTH; + } + break; case 2: if (zend_get_parameters_ex(2, &result, &row)==FAILURE) { RETURN_FALSE; *************** *** 1085,1099 **** ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; ! ! convert_to_long_ex(row); ! if (Z_LVAL_PP(row) < 0 || Z_LVAL_PP(row) >= PQntuples(pgsql_result)) { ! php_error(E_WARNING,"Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result)); ! RETURN_FALSE; } array_init(return_value); for (i = 0, num_fields = PQnfields(pgsql_result); i<num_fields; i++) { ! if (PQgetisnull(pgsql_result, Z_LVAL_PP(row), i)) { if (result_type & PGSQL_NUM) { add_index_null(return_value, i); } --- 1104,1128 ---- ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; ! ! if (ZEND_NUM_ARGS() == 1) { ! pg_result->row++; ! pgsql_row = pg_result->row; ! if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { ! RETURN_FALSE; ! } ! } else { ! 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(E_WARNING,"Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result)); ! RETURN_FALSE; ! } } array_init(return_value); for (i = 0, num_fields = PQnfields(pgsql_result); i<num_fields; i++) { ! if (PQgetisnull(pgsql_result, pgsql_row, i)) { if (result_type & PGSQL_NUM) { add_index_null(return_value, i); } *************** *** 1102,1108 **** add_assoc_null(return_value, field_name); } } else { ! element = PQgetvalue(pgsql_result, Z_LVAL_PP(row), i); element_len = (element ? strlen(element) : 0); if (element) { char *data; --- 1131,1137 ---- add_assoc_null(return_value, field_name); } } else { ! element = PQgetvalue(pgsql_result, pgsql_row, i); element_len = (element ? strlen(element) : 0); if (element) { char *data; *************** *** 1169,1189 **** zval **result, **row, **field; PGresult *pgsql_result; pgsql_result_handle *pg_result; ! int field_offset; ! if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &result, &row, &field)==FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; ! ! convert_to_long_ex(row); ! if (Z_LVAL_PP(row) < 0 || Z_LVAL_PP(row) >= PQntuples(pgsql_result)) { ! php_error(E_WARNING,"Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result)); ! RETURN_FALSE; } switch(Z_TYPE_PP(field)) { case IS_STRING: convert_to_string_ex(field); --- 1198,1229 ---- zval **result, **row, **field; PGresult *pgsql_result; pgsql_result_handle *pg_result; ! int field_offset, pgsql_row; ! if ((ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &result, &row, &field)==FAILURE) && ! (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &result, &field)==FAILURE)) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; ! if (ZEND_NUM_ARGS() == 2) { ! if (pg_result->row < 0) ! pg_result->row = 0; ! pgsql_row = pg_result->row; ! if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { ! RETURN_FALSE; ! } ! } else { ! convert_to_long_ex(row); ! pgsql_row = Z_LVAL_PP(row); ! if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { ! php_error(E_WARNING,"Unable to jump to row %d on PostgreSQL result index %d", Z_LVAL_PP(row), Z_LVAL_PP(result)); ! RETURN_FALSE; ! } } + switch(Z_TYPE_PP(field)) { case IS_STRING: convert_to_string_ex(field); *************** *** 1201,1210 **** switch (entry_type) { case PHP_PG_DATA_LENGTH: ! return_value->value.lval = PQgetlength(pgsql_result, Z_LVAL_PP(row), field_offset); break; case PHP_PG_DATA_ISNULL: ! return_value->value.lval = PQgetisnull(pgsql_result, Z_LVAL_PP(row), field_offset); break; } return_value->type = IS_LONG; --- 1241,1250 ---- switch (entry_type) { case PHP_PG_DATA_LENGTH: ! return_value->value.lval = PQgetlength(pgsql_result, pgsql_row, field_offset); break; case PHP_PG_DATA_ISNULL: ! return_value->value.lval = PQgetisnull(pgsql_result, pgsql_row, field_offset); break; } return_value->type = IS_LONG; diff -r -c php-4.0.5.orig/ext/pgsql/php_pgsql.h php-4.0.5/ext/pgsql/php_pgsql.h *** php-4.0.5.orig/ext/pgsql/php_pgsql.h Wed Apr 4 23:51:58 2001 --- php-4.0.5/ext/pgsql/php_pgsql.h Wed Jun 20 13:29:50 2001 *************** *** 111,116 **** --- 111,117 ---- typedef struct _php_pgsql_result_handle { PGconn *conn; PGresult *result; + int row; } pgsql_result_handle; typedef struct {

« previous php.dev (#57263) next »