mirror of
https://github.com/php/php-src.git
synced 2025-01-22 11:44:09 +08:00
Add PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT attribute, which, when set
to true, forces the driver to use PDO's own emulated prepared statement support. Why would you want that, considering that native prepared statements are supposed to be the best thing ever? "Often postgresql will have to plan the query without knowing the parameters - and it will choose a bad plan. In some cases it will plan based on the first parameters you send. " Ugh. So now we have a way to let you decide that you know better than the pgsql query planner.
This commit is contained in:
parent
9438584d76
commit
79f3cb9856
@ -77,6 +77,7 @@ ZEND_GET_MODULE(pdo_pgsql)
|
||||
PHP_MINIT_FUNCTION(pdo_pgsql)
|
||||
{
|
||||
php_pdo_register_driver(&pdo_pgsql_driver);
|
||||
REGISTER_LONG_CONSTANT("PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, CONST_CS|CONST_PERSISTENT);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -153,55 +153,58 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len,
|
||||
}
|
||||
|
||||
#if HAVE_PQPREPARE
|
||||
stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED;
|
||||
stmt->named_rewrite_template = "$%d";
|
||||
ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
|
||||
|
||||
if (ret == 1) {
|
||||
/* query was re-written */
|
||||
sql = nsql;
|
||||
} else if (ret == -1) {
|
||||
/* couldn't grok it */
|
||||
strcpy(dbh->error_code, stmt->error_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spprintf(&S->stmt_name, 0, "pdo_pgsql_stmt_%08x", (unsigned int)stmt);
|
||||
res = PQprepare(H->server, S->stmt_name, sql, 0, NULL);
|
||||
if (nsql) {
|
||||
efree(nsql);
|
||||
}
|
||||
if (!res) {
|
||||
pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL);
|
||||
return 0;
|
||||
}
|
||||
if (!driver_options || pdo_attr_lval(driver_options,
|
||||
PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 0) {
|
||||
stmt->supports_placeholders = PDO_PLACEHOLDER_NAMED;
|
||||
stmt->named_rewrite_template = "$%d";
|
||||
ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
|
||||
|
||||
/* check if the connection is using protocol version 2.0.
|
||||
* if that is the reason that the prepare failed, we want to fall
|
||||
* through and let PDO emulate it for us */
|
||||
status = PQresultStatus(res);
|
||||
switch (status) {
|
||||
case PGRES_COMMAND_OK:
|
||||
case PGRES_TUPLES_OK:
|
||||
/* it worked */
|
||||
PQclear(res);
|
||||
return 1;
|
||||
|
||||
case PGRES_BAD_RESPONSE:
|
||||
/* server is probably too old; fall through and let
|
||||
* PDO emulate it */
|
||||
efree(S->stmt_name);
|
||||
S->stmt_name = NULL;
|
||||
PQclear(res);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* protocol 3.0 and above; hard error */
|
||||
pdo_pgsql_error(dbh, status, pdo_pgsql_sqlstate(res));
|
||||
PQclear(res);
|
||||
if (ret == 1) {
|
||||
/* query was re-written */
|
||||
sql = nsql;
|
||||
} else if (ret == -1) {
|
||||
/* couldn't grok it */
|
||||
strcpy(dbh->error_code, stmt->error_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spprintf(&S->stmt_name, 0, "pdo_pgsql_stmt_%08x", (unsigned int)stmt);
|
||||
res = PQprepare(H->server, S->stmt_name, sql, 0, NULL);
|
||||
if (nsql) {
|
||||
efree(nsql);
|
||||
}
|
||||
if (!res) {
|
||||
pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if the connection is using protocol version 2.0.
|
||||
* if that is the reason that the prepare failed, we want to fall
|
||||
* through and let PDO emulate it for us */
|
||||
status = PQresultStatus(res);
|
||||
switch (status) {
|
||||
case PGRES_COMMAND_OK:
|
||||
case PGRES_TUPLES_OK:
|
||||
/* it worked */
|
||||
PQclear(res);
|
||||
return 1;
|
||||
|
||||
case PGRES_BAD_RESPONSE:
|
||||
/* server is probably too old; fall through and let
|
||||
* PDO emulate it */
|
||||
efree(S->stmt_name);
|
||||
S->stmt_name = NULL;
|
||||
PQclear(res);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* protocol 3.0 and above; hard error */
|
||||
pdo_pgsql_error(dbh, status, pdo_pgsql_sqlstate(res));
|
||||
PQclear(res);
|
||||
return 0;
|
||||
}
|
||||
/* fall through */
|
||||
}
|
||||
/* fall through */
|
||||
#endif
|
||||
|
||||
stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
|
||||
|
@ -84,6 +84,10 @@ extern struct pdo_stmt_methods pgsql_stmt_methods;
|
||||
#define pdo_pgsql_sqlstate(r) (const char *)NULL
|
||||
#endif
|
||||
|
||||
enum {
|
||||
PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT = PDO_ATTR_DRIVER_SPECIFIC,
|
||||
};
|
||||
|
||||
#endif /* PHP_PDO_PGSQL_INT_H */
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user