mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Added new PDO::PGSQL_ATTR_DISABLE_PREPARES that uses PQexecParams
Faster than prepared statements when queries are run once. Slightly slower than PDO::ATTR_EMULATE_PREPARES but without the potential security implications of embedding parameters in the query itself.
This commit is contained in:
parent
d72621ab9e
commit
e378348a31
5 changed files with 81 additions and 3 deletions
|
@ -86,6 +86,7 @@ ZEND_GET_MODULE(pdo_pgsql)
|
|||
PHP_MINIT_FUNCTION(pdo_pgsql)
|
||||
{
|
||||
REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT);
|
||||
REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_PREPARES", PDO_PGSQL_ATTR_DISABLE_PREPARES);
|
||||
REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_IDLE", (long)PGSQL_TRANSACTION_IDLE);
|
||||
REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_ACTIVE", (long)PGSQL_TRANSACTION_ACTIVE);
|
||||
REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_INTRANS", (long)PGSQL_TRANSACTION_INTRANS);
|
||||
|
|
|
@ -224,6 +224,7 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
|
|||
char *nsql = NULL;
|
||||
int nsql_len = 0;
|
||||
int emulate = 0;
|
||||
int execute_only = 0;
|
||||
|
||||
S->H = H;
|
||||
stmt->driver_data = S;
|
||||
|
@ -246,8 +247,12 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
|
|||
if (pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES, H->emulate_prepares TSRMLS_CC) == 1) {
|
||||
emulate = 1;
|
||||
}
|
||||
if (pdo_attr_lval(driver_options, PDO_PGSQL_ATTR_DISABLE_PREPARES, H->disable_prepares TSRMLS_CC) == 1) {
|
||||
execute_only = 1;
|
||||
}
|
||||
} else {
|
||||
emulate = H->disable_native_prepares || H->emulate_prepares;
|
||||
execute_only = H->disable_prepares;
|
||||
}
|
||||
|
||||
if (!emulate && PQprotocolVersion(H->server) > 2) {
|
||||
|
@ -264,8 +269,11 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
spprintf(&S->stmt_name, 0, "pdo_stmt_%08x", ++H->stmt_counter);
|
||||
/* that's all for now; we'll defer the actual prepare until the first execute call */
|
||||
if (!execute_only) {
|
||||
/* prepared query: set the query name and defer the
|
||||
actual prepare until the first execute call */
|
||||
spprintf(&S->stmt_name, 0, "pdo_stmt_%08x", ++H->stmt_counter);
|
||||
}
|
||||
|
||||
if (nsql) {
|
||||
S->query = nsql;
|
||||
|
@ -1112,6 +1120,9 @@ static int pdo_pgsql_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
|
|||
php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead");
|
||||
H->disable_native_prepares = Z_LVAL_P(val);
|
||||
return 1;
|
||||
case PDO_PGSQL_ATTR_DISABLE_PREPARES:
|
||||
H->disable_prepares = Z_LVAL_P(val);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -204,7 +204,17 @@ stmt_retry:
|
|||
S->param_lengths,
|
||||
S->param_formats,
|
||||
0);
|
||||
} else if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED) {
|
||||
/* execute query with parameters */
|
||||
S->result = PQexecParams(H->server, S->query,
|
||||
stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0,
|
||||
S->param_types,
|
||||
(const char**)S->param_values,
|
||||
S->param_lengths,
|
||||
S->param_formats,
|
||||
0);
|
||||
} else {
|
||||
/* execute plain query (with embedded parameters) */
|
||||
S->result = PQexec(H->server, stmt->active_query_string);
|
||||
}
|
||||
status = PQresultStatus(S->result);
|
||||
|
@ -234,7 +244,7 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *
|
|||
{
|
||||
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
|
||||
|
||||
if (S->stmt_name && param->is_param) {
|
||||
if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED && param->is_param) {
|
||||
switch (event_type) {
|
||||
case PDO_PARAM_EVT_FREE:
|
||||
if (param->driver_data) {
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef struct {
|
|||
to keep track of two different attributes having the same effect. */
|
||||
int emulate_prepares;
|
||||
int disable_native_prepares; /* deprecated since 5.6 */
|
||||
int disable_prepares;
|
||||
unsigned int stmt_counter;
|
||||
} pdo_pgsql_db_handle;
|
||||
|
||||
|
@ -90,6 +91,7 @@ extern struct pdo_stmt_methods pgsql_stmt_methods;
|
|||
|
||||
enum {
|
||||
PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT = PDO_ATTR_DRIVER_SPECIFIC,
|
||||
PDO_PGSQL_ATTR_DISABLE_PREPARES,
|
||||
};
|
||||
|
||||
struct pdo_pgsql_lob_self {
|
||||
|
|
54
ext/pdo_pgsql/tests/disable_prepares.phpt
Normal file
54
ext/pdo_pgsql/tests/disable_prepares.phpt
Normal file
|
@ -0,0 +1,54 @@
|
|||
--TEST--
|
||||
PDO PgSQL PGSQL_ATTR_DISABLE_PREPARES
|
||||
--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';
|
||||
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_COLUMN);
|
||||
|
||||
$stmt = $db->prepare("SELECT statement FROM pg_prepared_statements", array(
|
||||
PDO::ATTR_EMULATE_PREPARES => true));
|
||||
|
||||
$stmt2 = $db->prepare("SELECT (?)::int2");
|
||||
$stmt2->execute(array(1));
|
||||
var_dump($stmt2->fetch());
|
||||
$stmt2->execute(array(2));
|
||||
var_dump($stmt2->fetch());
|
||||
|
||||
$stmt->execute();
|
||||
$first = $stmt->fetchAll();
|
||||
|
||||
$stmt3 = $db->prepare("SELECT (?)::int4", array(
|
||||
PDO::PGSQL_ATTR_DISABLE_PREPARES => true));
|
||||
$stmt3->execute(array(3));
|
||||
var_dump($stmt3->fetch());
|
||||
$stmt3->execute(array(4));
|
||||
var_dump($stmt3->fetch());
|
||||
|
||||
$stmt->execute();
|
||||
$second = $stmt->fetchAll();
|
||||
|
||||
var_dump($first, $second);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(1) "1"
|
||||
string(1) "2"
|
||||
string(1) "3"
|
||||
string(1) "4"
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(17) "SELECT ($1)::int2"
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(17) "SELECT ($1)::int2"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue