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) {
|
if (S->cursor_name) {
|
||||||
efree(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);
|
spprintf(&S->cursor_name, 0, "pdo_pgsql_cursor_%08x", (unsigned int) stmt);
|
||||||
|
emulate = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_PQPREPARE
|
#if HAVE_PQPREPARE
|
||||||
|
|
||||||
if (driver_options) {
|
else if (driver_options) {
|
||||||
if (pdo_attr_lval(driver_options,
|
if (pdo_attr_lval(driver_options,
|
||||||
PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 1) {
|
PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 1) {
|
||||||
emulate = 1;
|
emulate = 1;
|
||||||
|
|
|
@ -129,6 +129,24 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
|
||||||
|
|
||||||
S->current_row = 0;
|
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 HAVE_PQPREPARE
|
||||||
if (S->stmt_name) {
|
if (S->stmt_name) {
|
||||||
/* using a prepared statement */
|
/* using a prepared statement */
|
||||||
|
@ -182,12 +200,7 @@ stmt_retry:
|
||||||
0);
|
0);
|
||||||
} else
|
} else
|
||||||
#endif
|
#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);
|
S->result = PQexec(H->server, stmt->active_query_string);
|
||||||
}
|
}
|
||||||
status = PQresultStatus(S->result);
|
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;
|
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
|
||||||
|
|
||||||
if (S->cursor_name) {
|
if (S->cursor_name) {
|
||||||
char *ori_str;
|
char *ori_str = NULL;
|
||||||
char *q = NULL;
|
char *q = NULL;
|
||||||
ExecStatusType status;
|
ExecStatusType status;
|
||||||
|
|
||||||
switch (ori) {
|
switch (ori) {
|
||||||
case PDO_FETCH_ORI_NEXT: ori_str = "FORWARD"; break;
|
case PDO_FETCH_ORI_NEXT: spprintf(&ori_str, 0, "NEXT"); break;
|
||||||
case PDO_FETCH_ORI_PRIOR: ori_str = "BACKWARD"; break;
|
case PDO_FETCH_ORI_PRIOR: spprintf(&ori_str, 0, "BACKWARD"); break;
|
||||||
case PDO_FETCH_ORI_REL: ori_str = "RELATIVE"; 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:
|
default:
|
||||||
return 0;
|
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);
|
S->result = PQexec(S->H->server, q);
|
||||||
efree(q);
|
efree(q);
|
||||||
status = PQresultStatus(S->result);
|
status = PQresultStatus(S->result);
|
||||||
|
@ -372,9 +389,12 @@ static int pgsql_stmt_fetch(pdo_stmt_t *stmt,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PQntuples(S->result)) {
|
||||||
S->current_row = 1;
|
S->current_row = 1;
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (S->current_row < stmt->row_count) {
|
if (S->current_row < stmt->row_count) {
|
||||||
S->current_row++;
|
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