From: Jon Parise Date: Tue, 19 Jun 2001 18:10:08 +0000 (+0000) Subject: Allow the PostgreSQL driver to do internal row counting when iterating X-Git-Tag: PRE_GRANULAR_GARBAGE_FIX~31 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dbd51aaf611a94b835f62e67543335b2a1802762;p=php Allow the PostgreSQL driver to do internal row counting when iterating through a result set. Submitted by: Georg von Zezschwitz --- diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index d86a6afe80..c1bb10e486 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -776,6 +776,7 @@ PHP_FUNCTION(pg_exec) 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); @@ -1088,27 +1089,37 @@ PHP_FUNCTION(pg_fieldnum) } /* }}} */ -/* {{{ proto mixed pg_result(int result, int row_number, mixed field_name) +/* {{{ proto mixed pg_result(int result, [int row_number,] mixed field_name) Returns values from a result identifier */ PHP_FUNCTION(pg_result) { zval **result, **row, **field=NULL; PGresult *pgsql_result; pgsql_result_handle *pg_result; - int field_offset; + int field_offset, pgsql_row; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &result, &row, &field)==FAILURE) { + 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; - - 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; + 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: @@ -1124,10 +1135,10 @@ PHP_FUNCTION(pg_result) RETURN_FALSE; } - if (PQgetisnull(pgsql_result, Z_LVAL_PP(row), field_offset)) { + if (PQgetisnull(pgsql_result, pgsql_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.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; @@ -1142,12 +1153,20 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) zval **result, **row, **arg3; PGresult *pgsql_result; pgsql_result_handle *pg_result; - int i, num_fields; + 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; @@ -1171,15 +1190,25 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) 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; + + 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); iresult; - - 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; + 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); @@ -1289,17 +1329,17 @@ void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) switch (entry_type) { case PHP_PG_DATA_LENGTH: - return_value->value.lval = PQgetlength(pgsql_result, Z_LVAL_PP(row), field_offset); + return_value->value.lval = PQgetlength(pgsql_result, pgsql_row, field_offset); break; case PHP_PG_DATA_ISNULL: - return_value->value.lval = PQgetisnull(pgsql_result, Z_LVAL_PP(row), field_offset); + return_value->value.lval = PQgetisnull(pgsql_result, pgsql_row, field_offset); break; } return_value->type = IS_LONG; } /* }}} */ -/* {{{ proto int pg_fieldprtlen(int result, int row, mixed field_name_or_number) +/* {{{ proto int pg_fieldprtlen(int result, [int row,] mixed field_name_or_number) Returns the printed length */ PHP_FUNCTION(pg_fieldprtlen) { @@ -1307,7 +1347,7 @@ PHP_FUNCTION(pg_fieldprtlen) } /* }}} */ -/* {{{ proto int pg_fieldisnull(int result, int row, mixed field_name_or_number) +/* {{{ proto int pg_fieldisnull(int result, [int row,] mixed field_name_or_number) Test if a field is NULL */ PHP_FUNCTION(pg_fieldisnull) { diff --git a/ext/pgsql/php_pgsql.h b/ext/pgsql/php_pgsql.h index 4fd7032b4f..09d47dfcf6 100644 --- a/ext/pgsql/php_pgsql.h +++ b/ext/pgsql/php_pgsql.h @@ -112,6 +112,7 @@ typedef struct pgLofp { typedef struct _php_pgsql_result_handle { PGconn *conn; PGresult *result; + int row; } pgsql_result_handle; typedef struct {