Skip to content

Commit 4a0ec3d

Browse files
authored
Make ext/odbc default value handling more consistent (#13910)
These changes are carved off from https://github.com/php/php-src/pull/12040/files. I noticed that there are some inconsistencies between odbc_fetch_object()/odbc_fetch_array(), odbc_fetch_into(), as well as odbc_fetch_row(), specifically in how they handle the $row parameter. Now, I tried to align their behaviour the following way: - I made null the default value. Previously, the default values were one of the following: -1, -1, 0, and null, respectively. - odbc_fetch_row() has been returning false indicating there is no more rows when 0 is passed as $row. Now, a warning is also emitted in this case, because the null default value is not new, because it's available since PHP 8.0. - When HAVE_SQL_EXTENDED_FETCH is not defined, the $row parameter is always ignored. Previously, some of the functions didn't accept it at all. Now a warning is emitted if the feature is not supported, but the parameter has any meaningful value (is greater than or equal to 1).
1 parent 4d28e40 commit 4a0ec3d

File tree

5 files changed

+64
-42
lines changed

5 files changed

+64
-42
lines changed

UPGRADING

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ PHP 8.4 UPGRADE NOTES
6464
is converted to Unicode. This is significant because around 40 SJIS-Mac characters
6565
convert to a sequence of multiple Unicode codepoints.
6666

67+
- ODBC:
68+
. odbc_fetch_row() returns false when a value less than or equal to 0 is
69+
passed for parameter $row. Now, a warning is emitted in this case.
70+
6771
- Opcache:
6872
. The JIT config defaults changed from opcache.jit=tracing and
6973
opcache.jit_buffer_size=0 to opcache.jit=disable and
@@ -360,6 +364,12 @@ PHP 8.4 UPGRADE NOTES
360364
. New serial_hex parameter added to openssl_csr_sign to allow setting serial
361365
number in the hexadecimal format.
362366

367+
- ODBC:
368+
. Parameter $row of odbc_fetch_object(), odbc_fetch_array(), and
369+
odbc_fetch_into() now has a default value of null, consistent with
370+
odbc_fetch_row(). Previously, the default values were -1, -1, and 0,
371+
respectively.
372+
363373
- Output:
364374
. Output handler status flags passed to the flags parameter of ob_start
365375
are now cleared.

ext/odbc/odbc.stub.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,17 +352,17 @@ function odbc_do($odbc, string $query) {}
352352

353353
#ifdef PHP_ODBC_HAVE_FETCH_HASH
354354
/** @param resource $statement */
355-
function odbc_fetch_object($statement, int $row = -1): stdClass|false {}
355+
function odbc_fetch_object($statement, ?int $row = null): stdClass|false {}
356356

357357
/** @param resource $statement */
358-
function odbc_fetch_array($statement, int $row = -1): array|false {}
358+
function odbc_fetch_array($statement, ?int $row = null): array|false {}
359359
#endif
360360

361361
/**
362362
* @param resource $statement
363363
* @param array $array
364364
*/
365-
function odbc_fetch_into($statement, &$array, int $row = 0): int|false {}
365+
function odbc_fetch_into($statement, &$array, ?int $row = null): int|false {}
366366

367367
/** @param resource $statement */
368368
function odbc_fetch_row($statement, ?int $row = null): bool {}

ext/odbc/odbc_arginfo.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/odbc/php_odbc.c

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,29 +1269,29 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
12691269
RETCODE rc;
12701270
SQLSMALLINT sql_c_type;
12711271
char *buf = NULL;
1272+
zend_long pv_row = 0;
1273+
bool pv_row_is_null = true;
1274+
zval *pv_res, tmp;
12721275
#ifdef HAVE_SQL_EXTENDED_FETCH
12731276
SQLULEN crow;
12741277
SQLUSMALLINT RowStatus[1];
1275-
SQLLEN rownum;
1276-
zval *pv_res, tmp;
1277-
zend_long pv_row = -1;
1278+
#endif
12781279

1279-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &pv_res, &pv_row) == FAILURE) {
1280+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l!", &pv_res, &pv_row, &pv_row_is_null) == FAILURE) {
12801281
RETURN_THROWS();
12811282
}
12821283

1283-
rownum = pv_row;
1284-
#else
1285-
zval *pv_res, tmp;
1286-
1287-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pv_res) == FAILURE) {
1284+
if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
12881285
RETURN_THROWS();
12891286
}
1290-
#endif
12911287

1292-
if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
1293-
RETURN_THROWS();
1288+
/* TODO deprecate $row argument values less than 1 after PHP 8.4 */
1289+
1290+
#ifndef HAVE_SQL_EXTENDED_FETCH
1291+
if (!pv_row_is_null && pv_row > 0) {
1292+
php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored");
12941293
}
1294+
#endif
12951295

12961296
if (result->numcols == 0) {
12971297
php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
@@ -1300,8 +1300,8 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
13001300

13011301
#ifdef HAVE_SQL_EXTENDED_FETCH
13021302
if (result->fetch_abs) {
1303-
if (rownum > 0) {
1304-
rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
1303+
if (!pv_row_is_null && pv_row > 0) {
1304+
rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus);
13051305
} else {
13061306
rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
13071307
}
@@ -1316,8 +1316,8 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
13161316
array_init(return_value);
13171317

13181318
#ifdef HAVE_SQL_EXTENDED_FETCH
1319-
if (rownum > 0 && result->fetch_abs)
1320-
result->fetched = rownum;
1319+
if (!pv_row_is_null && pv_row > 0 && result->fetch_abs)
1320+
result->fetched = (SQLLEN)pv_row;
13211321
else
13221322
#endif
13231323
result->fetched++;
@@ -1430,28 +1430,28 @@ PHP_FUNCTION(odbc_fetch_into)
14301430
SQLSMALLINT sql_c_type;
14311431
char *buf = NULL;
14321432
zval *pv_res, *pv_res_arr, tmp;
1433-
#ifdef HAVE_SQL_EXTENDED_FETCH
14341433
zend_long pv_row = 0;
1434+
bool pv_row_is_null = true;
1435+
#ifdef HAVE_SQL_EXTENDED_FETCH
14351436
SQLULEN crow;
14361437
SQLUSMALLINT RowStatus[1];
1437-
SQLLEN rownum = -1;
14381438
#endif /* HAVE_SQL_EXTENDED_FETCH */
14391439

1440-
#ifdef HAVE_SQL_EXTENDED_FETCH
1441-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|l", &pv_res, &pv_res_arr, &pv_row) == FAILURE) {
1440+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|l!", &pv_res, &pv_res_arr, &pv_row, &pv_row_is_null) == FAILURE) {
14421441
RETURN_THROWS();
14431442
}
14441443

1445-
rownum = pv_row;
1446-
#else
1447-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &pv_res, &pv_res_arr) == FAILURE) {
1444+
if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
14481445
RETURN_THROWS();
14491446
}
1450-
#endif /* HAVE_SQL_EXTENDED_FETCH */
14511447

1452-
if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) {
1453-
RETURN_THROWS();
1448+
/* TODO deprecate $row argument values less than 1 after PHP 8.4 */
1449+
1450+
#ifndef HAVE_SQL_EXTENDED_FETCH
1451+
if (!pv_row_is_null && pv_row > 0) {
1452+
php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored");
14541453
}
1454+
#endif
14551455

14561456
if (result->numcols == 0) {
14571457
php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
@@ -1465,8 +1465,8 @@ PHP_FUNCTION(odbc_fetch_into)
14651465

14661466
#ifdef HAVE_SQL_EXTENDED_FETCH
14671467
if (result->fetch_abs) {
1468-
if (rownum > 0) {
1469-
rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
1468+
if (!pv_row_is_null && pv_row > 0) {
1469+
rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus);
14701470
} else {
14711471
rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
14721472
}
@@ -1479,8 +1479,8 @@ PHP_FUNCTION(odbc_fetch_into)
14791479
}
14801480

14811481
#ifdef HAVE_SQL_EXTENDED_FETCH
1482-
if (rownum > 0 && result->fetch_abs)
1483-
result->fetched = rownum;
1482+
if (!pv_row_is_null && pv_row > 0 && result->fetch_abs)
1483+
result->fetched = (SQLLEN)pv_row;
14841484
else
14851485
#endif
14861486
result->fetched++;
@@ -1560,8 +1560,8 @@ PHP_FUNCTION(odbc_fetch_row)
15601560
odbc_result *result;
15611561
RETCODE rc;
15621562
zval *pv_res;
1563-
zend_long pv_row;
1564-
bool pv_row_is_null = 1;
1563+
zend_long pv_row = 0;
1564+
bool pv_row_is_null = true;
15651565
#ifdef HAVE_SQL_EXTENDED_FETCH
15661566
SQLULEN crow;
15671567
SQLUSMALLINT RowStatus[1];
@@ -1575,6 +1575,17 @@ PHP_FUNCTION(odbc_fetch_row)
15751575
RETURN_THROWS();
15761576
}
15771577

1578+
#ifndef HAVE_SQL_EXTENDED_FETCH
1579+
if (!pv_row_is_null) {
1580+
php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored");
1581+
}
1582+
#else
1583+
if (!pv_row_is_null && pv_row < 1) {
1584+
php_error_docref(NULL, E_WARNING, "Argument #3 ($row) must be greater than or equal to 1");
1585+
RETURN_FALSE;
1586+
}
1587+
#endif
1588+
15781589
if (result->numcols == 0) {
15791590
php_error_docref(NULL, E_WARNING, "No tuples available at this result index");
15801591
RETURN_FALSE;
@@ -1594,12 +1605,12 @@ PHP_FUNCTION(odbc_fetch_row)
15941605
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
15951606
RETURN_FALSE;
15961607
}
1597-
1608+
#ifdef HAVE_SQL_EXTENDED_FETCH
15981609
if (!pv_row_is_null) {
15991610
result->fetched = (SQLLEN)pv_row;
1600-
} else {
1611+
} else
1612+
#endif
16011613
result->fetched++;
1602-
}
16031614

16041615
RETURN_TRUE;
16051616
}

ext/odbc/tests/odbc_fetch_row_001.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ $conn = odbc_connect($dsn, $user, $pass);
4040
odbc_exec($conn, 'DROP TABLE fetch_row');
4141
?>
4242
--EXPECTF--
43+
Warning: odbc_fetch_row(): Argument #3 ($row) must be greater than or equal to 1 in %s on line %d
4344
bool(false)
4445
bool(true)
4546
string(1) "1"

0 commit comments

Comments
 (0)