mirror of
https://github.com/php/php-src.git
synced 2025-08-18 23:18:56 +02:00
parent
dd6b8d4ceb
commit
61476ca182
3 changed files with 114 additions and 16 deletions
|
@ -232,13 +232,13 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
|
|||
if (S->cursor_name) {
|
||||
efree(S->cursor_name);
|
||||
}
|
||||
/* TODO: check how scrollable cursors related to prepared statements */
|
||||
spprintf(&S->cursor_name, 0, "pdo_pgsql_cursor_%08x", (unsigned int) stmt);
|
||||
emulate = 1;
|
||||
}
|
||||
|
||||
#if HAVE_PQPREPARE
|
||||
|
||||
if (driver_options) {
|
||||
else if (driver_options) {
|
||||
if (pdo_attr_lval(driver_options,
|
||||
PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 1) {
|
||||
emulate = 1;
|
||||
|
|
|
@ -129,6 +129,24 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
|
|||
|
||||
S->current_row = 0;
|
||||
|
||||
if (S->cursor_name) {
|
||||
char *q = NULL;
|
||||
spprintf(&q, 0, "DECLARE %s SCROLL CURSOR WITH HOLD FOR %s", S->cursor_name, stmt->active_query_string);
|
||||
S->result = PQexec(H->server, q);
|
||||
efree(q);
|
||||
|
||||
/* check if declare failed */
|
||||
status = PQresultStatus(S->result);
|
||||
if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
|
||||
pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fetch to be able to get the number of tuples later, but don't advance the cursor pointer */
|
||||
spprintf(&q, 0, "FETCH FORWARD 0 FROM %s", S->cursor_name);
|
||||
S->result = PQexec(H->server, q);
|
||||
efree(q);
|
||||
} else
|
||||
#if HAVE_PQPREPARE
|
||||
if (S->stmt_name) {
|
||||
/* using a prepared statement */
|
||||
|
@ -182,12 +200,7 @@ stmt_retry:
|
|||
0);
|
||||
} else
|
||||
#endif
|
||||
if (S->cursor_name) {
|
||||
char *q = NULL;
|
||||
spprintf(&q, 0, "DECLARE %s CURSOR FOR %s", S->cursor_name, stmt->active_query_string);
|
||||
S->result = PQexec(H->server, q);
|
||||
efree(q);
|
||||
} else {
|
||||
{
|
||||
S->result = PQexec(H->server, stmt->active_query_string);
|
||||
}
|
||||
status = PQresultStatus(S->result);
|
||||
|
@ -350,19 +363,23 @@ static int pgsql_stmt_fetch(pdo_stmt_t *stmt,
|
|||
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
|
||||
|
||||
if (S->cursor_name) {
|
||||
char *ori_str;
|
||||
char *ori_str = NULL;
|
||||
char *q = NULL;
|
||||
ExecStatusType status;
|
||||
|
||||
switch (ori) {
|
||||
case PDO_FETCH_ORI_NEXT: ori_str = "FORWARD"; break;
|
||||
case PDO_FETCH_ORI_PRIOR: ori_str = "BACKWARD"; break;
|
||||
case PDO_FETCH_ORI_REL: ori_str = "RELATIVE"; break;
|
||||
case PDO_FETCH_ORI_NEXT: spprintf(&ori_str, 0, "NEXT"); break;
|
||||
case PDO_FETCH_ORI_PRIOR: spprintf(&ori_str, 0, "BACKWARD"); break;
|
||||
case PDO_FETCH_ORI_FIRST: spprintf(&ori_str, 0, "FIRST"); break;
|
||||
case PDO_FETCH_ORI_LAST: spprintf(&ori_str, 0, "LAST"); break;
|
||||
case PDO_FETCH_ORI_ABS: spprintf(&ori_str, 0, "ABSOLUTE %ld", offset); break;
|
||||
case PDO_FETCH_ORI_REL: spprintf(&ori_str, 0, "RELATIVE %ld", offset); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
spprintf(&q, 0, "FETCH %s %ld FROM %s", ori_str, offset, S->cursor_name);
|
||||
spprintf(&q, 0, "FETCH %s FROM %s", ori_str, S->cursor_name);
|
||||
efree(ori_str);
|
||||
S->result = PQexec(S->H->server, q);
|
||||
efree(q);
|
||||
status = PQresultStatus(S->result);
|
||||
|
@ -372,9 +389,12 @@ static int pgsql_stmt_fetch(pdo_stmt_t *stmt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
S->current_row = 1;
|
||||
return 1;
|
||||
|
||||
if (PQntuples(S->result)) {
|
||||
S->current_row = 1;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (S->current_row < stmt->row_count) {
|
||||
S->current_row++;
|
||||
|
|
78
ext/pdo_pgsql/tests/bug44861.phpt
Normal file
78
ext/pdo_pgsql/tests/bug44861.phpt
Normal file
|
@ -0,0 +1,78 @@
|
|||
--TEST--
|
||||
Bug #44861 (scrollable cursor don't work with pgsql)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
|
||||
require dirname(__FILE__) . '/config.inc';
|
||||
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
|
||||
PDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
|
||||
$dbh = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
|
||||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$query = "SELECT 'row1' AS r UNION SELECT 'row2' UNION SELECT 'row3' UNION SELECT 'row4'";
|
||||
$aParams = array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL);
|
||||
|
||||
$res = $dbh->prepare($query, $aParams);
|
||||
$res->execute();
|
||||
var_dump($res->fetchColumn());
|
||||
var_dump($res->fetchColumn());
|
||||
var_dump($res->fetchColumn());
|
||||
var_dump($res->fetchColumn());
|
||||
var_dump($res->fetchColumn());
|
||||
|
||||
var_dump($res->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_ABS, 3));
|
||||
var_dump($res->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR));
|
||||
var_dump($res->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_FIRST));
|
||||
var_dump($res->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_LAST));
|
||||
var_dump($res->fetch(PDO::FETCH_NUM, PDO::FETCH_ORI_REL, -1));
|
||||
|
||||
var_dump($res->fetchAll(PDO::FETCH_ASSOC));
|
||||
|
||||
// Test binding params via emulated prepared query
|
||||
$res = $dbh->prepare("SELECT ?", $aParams);
|
||||
$res->execute(array("it's working"));
|
||||
var_dump($res->fetch(PDO::FETCH_NUM));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(4) "row1"
|
||||
string(4) "row2"
|
||||
string(4) "row3"
|
||||
string(4) "row4"
|
||||
bool(false)
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(4) "row3"
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(4) "row2"
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(4) "row1"
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(4) "row4"
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(4) "row3"
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
["r"]=>
|
||||
string(4) "row4"
|
||||
}
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(12) "it's working"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue