wez Thu Nov 24 22:35:06 2005 EDT Modified files: (Branch: PHP_5_1) /php-src/ext/pdo_pgsql package.xml pgsql_driver.c pgsql_statement.c php_pdo_pgsql_int.h Log: 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. http://cvs.php.net/diff.php/php-src/ext/pdo_pgsql/package.xml?r1=1.5.2.2&r2=1.5.2.3&ty=u Index: php-src/ext/pdo_pgsql/package.xml diff -u php-src/ext/pdo_pgsql/package.xml:1.5.2.2 php-src/ext/pdo_pgsql/package.xml:1.5.2.3 --- php-src/ext/pdo_pgsql/package.xml:1.5.2.2 Mon Oct 31 22:10:09 2005 +++ php-src/ext/pdo_pgsql/package.xml Thu Nov 24 22:35:04 2005 @@ -30,7 +30,7 @@ <license>PHP</license> <release> <state>beta</state> - <version>1.0RC2</version> + <version>1.0</version> <date>2005-11-01</date> <notes> http://cvs.php.net/diff.php/php-src/ext/pdo_pgsql/pgsql_driver.c?r1=1.53&r2=1.53.2.1&ty=u Index: php-src/ext/pdo_pgsql/pgsql_driver.c diff -u php-src/ext/pdo_pgsql/pgsql_driver.c:1.53 php-src/ext/pdo_pgsql/pgsql_driver.c:1.53.2.1 --- php-src/ext/pdo_pgsql/pgsql_driver.c:1.53 Wed Aug 3 10:07:39 2005 +++ php-src/ext/pdo_pgsql/pgsql_driver.c Thu Nov 24 22:35:04 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pgsql_driver.c,v 1.53 2005/08/03 14:07:39 sniper Exp $ */ +/* $Id: pgsql_driver.c,v 1.53.2.1 2005/11/25 03:35:04 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -153,8 +153,9 @@ } #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 @@ } 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 http://cvs.php.net/diff.php/php-src/ext/pdo_pgsql/pgsql_statement.c?r1=1.31.2.3&r2=1.31.2.4&ty=u Index: php-src/ext/pdo_pgsql/pgsql_statement.c diff -u php-src/ext/pdo_pgsql/pgsql_statement.c:1.31.2.3 php-src/ext/pdo_pgsql/pgsql_statement.c:1.31.2.4 --- php-src/ext/pdo_pgsql/pgsql_statement.c:1.31.2.3 Sat Sep 24 14:47:50 2005 +++ php-src/ext/pdo_pgsql/pgsql_statement.c Thu Nov 24 22:35:04 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pgsql_statement.c,v 1.31.2.3 2005/09/24 18:47:50 wez Exp $ */ +/* $Id: pgsql_statement.c,v 1.31.2.4 2005/11/25 03:35:04 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -36,6 +36,7 @@ #define INT8OID 20 #define INT2OID 21 #define INT4OID 23 +#define TEXTOID 25 #define OIDOID 26 @@ -105,12 +106,10 @@ pdo_pgsql_db_handle *H = S->H; ExecStatusType status; - if (stmt->executed) { - /* ensure that we free any previous unfetched results */ - if(S->result) { - PQclear(S->result); - S->result = NULL; - } + /* ensure that we free any previous unfetched results */ + if(S->result) { + PQclear(S->result); + S->result = NULL; } S->current_row = 0; @@ -119,13 +118,32 @@ if (S->stmt_name) { /* using a prepared statement */ + if (!stmt->executed) { + /* we deferred the prepare until now, because we didn't + * know anything about the parameter types; now we do */ + S->result = PQprepare(H->server, S->stmt_name, S->query, + stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, + S->param_types); + status = PQresultStatus(S->result); + switch (status) { + case PGRES_COMMAND_OK: + case PGRES_TUPLES_OK: + /* it worked */ + PQclear(S->result); + break; + default: + pdo_pgsql_error_stmt(stmt, status, + pdo_pgsql_sqlstate(S->result)); + return 0; + } + } S->result = PQexecPrepared(H->server, S->stmt_name, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, (const char**)S->param_values, S->param_lengths, - NULL, + S->param_formats, 0); } else #endif @@ -196,7 +214,9 @@ S->param_formats = ecalloc( zend_hash_num_elements(stmt->bound_params), sizeof(int)); - + S->param_types = ecalloc( + zend_hash_num_elements(stmt->bound_params), + sizeof(Oid)); } if (param->paramno >= 0) { if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB && @@ -222,12 +242,19 @@ } else if (Z_TYPE_P(param->parameter) == IS_BOOL) { S->param_values[param->paramno] = Z_BVAL_P(param->parameter) ? "t" : "f"; S->param_lengths[param->paramno] = 1; - S->param_formats[param->paramno] = 1; + S->param_formats[param->paramno] = 0; } else { convert_to_string(param->parameter); S->param_values[param->paramno] = Z_STRVAL_P(param->parameter); S->param_lengths[param->paramno] = Z_STRLEN_P(param->parameter); + S->param_formats[param->paramno] = 0; + } + + if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) { + S->param_types[param->paramno] = 0; S->param_formats[param->paramno] = 1; + } else { + S->param_types[param->paramno] = 0; } } break; http://cvs.php.net/diff.php/php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h?r1=1.13&r2=1.13.2.1&ty=u Index: php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h diff -u php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h:1.13 php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h:1.13.2.1 --- php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h:1.13 Tue Jul 19 22:37:57 2005 +++ php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h Thu Nov 24 22:35:04 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_pdo_pgsql_int.h,v 1.13 2005/07/20 02:37:57 wez Exp $ */ +/* $Id: php_pdo_pgsql_int.h,v 1.13.2.1 2005/11/25 03:35:04 wez Exp $ */ #ifndef PHP_PDO_PGSQL_INT_H #define PHP_PDO_PGSQL_INT_H @@ -57,9 +57,11 @@ char *cursor_name; #if HAVE_PQPREPARE char *stmt_name; + char *query; char **param_values; int *param_lengths; int *param_formats; + Oid *param_types; #endif } pdo_pgsql_stmt;
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php