diff options
author | Wez Furlong <wez@php.net> | 2005-11-25 03:35:04 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2005-11-25 03:35:04 +0000 |
commit | 70331c361e5457f09523bfbd81dce92c01741181 (patch) | |
tree | 83902f2b3eec1bec0d0d740a847365751c09f213 /ext/pdo_pgsql/pgsql_driver.c | |
parent | 2256ec00ef3a90290d333c0cc157a65210e14cde (diff) | |
download | php-git-70331c361e5457f09523bfbd81dce92c01741181.tar.gz |
Addresses #35338.
Postgres client API is pretty poor, so we have zero idea about the actual
parameter types in a statement.
We now defer the preparation of a statement until the first call to execute is
made. At that point, we have the parameters defined by the calling script, so
we can use the typing specified there when we perform the prepare.
For PDO_PARAM_LOB parameters, we set the binary formatting flag.
We can't just set this flag for all parameters, because its meaning is not
"string data, counted length" but "data is in native format". If this flag is
set for a numeric column and we send the number 1 formatted as a string, then
we will get an "insufficient data left in message" error message, because the
library was expecting sizeof(int4) bytes but only saw 1 byte for "1".
This is infuriating because we have no way to determine the datatypes for
parameters, and the type we explicitly set has to match the type in the
database. The only choice we're left with is telling postgres to deduce the
type; we still have no idea what type was deduced.
Diffstat (limited to 'ext/pdo_pgsql/pgsql_driver.c')
-rw-r--r-- | ext/pdo_pgsql/pgsql_driver.c | 43 |
1 files changed, 9 insertions, 34 deletions
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 43ed6e3258..96d2202536 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -153,8 +153,9 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, } #if HAVE_PQPREPARE - if (!driver_options || pdo_attr_lval(driver_options, - PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 0) { + if ((!driver_options || pdo_attr_lval(driver_options, + PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 0) + && PQprotocolVersion(H->server) > 2) { 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); @@ -169,41 +170,15 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, } spprintf(&S->stmt_name, 0, "pdo_pgsql_stmt_%08x", (unsigned int)stmt); - res = PQprepare(H->server, S->stmt_name, sql, 0, NULL); + /* that's all for now; we'll defer the actual prepare until the first execute call */ + if (nsql) { - efree(nsql); - } - if (!res) { - pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); - return 0; + S->query = nsql; + } else { + S->query = estrdup(sql); } - /* 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 */ + return 1; } #endif |