wez Fri Jul 8 11:27:35 2005 EDT Modified files: /php-src/ext/pdo_pgsql config.m4 pgsql_driver.c pgsql_statement.c php_pdo_pgsql_int.h Log: Add early support for native prepared statements in pgsql. Note that some tests now fail; if we can't resolve this in time for the beta, the prepare code should be disabled (I'll add a flag for this later today).
http://cvs.php.net/diff.php/php-src/ext/pdo_pgsql/config.m4?r1=1.11&r2=1.12&ty=u Index: php-src/ext/pdo_pgsql/config.m4 diff -u php-src/ext/pdo_pgsql/config.m4:1.11 php-src/ext/pdo_pgsql/config.m4:1.12 --- php-src/ext/pdo_pgsql/config.m4:1.11 Thu Jul 7 09:35:39 2005 +++ php-src/ext/pdo_pgsql/config.m4 Fri Jul 8 11:27:34 2005 @@ -1,5 +1,5 @@ dnl -dnl $Id: config.m4,v 1.11 2005/07/07 13:35:39 iliaa Exp $ +dnl $Id: config.m4,v 1.12 2005/07/08 15:27:34 wez Exp $ dnl if test "$PHP_PDO" != "no"; then @@ -93,6 +93,9 @@ AC_CHECK_LIB(pq, PQExecParams,AC_DEFINE(HAVE_PQEXECPARAMS,1,[PostgreSQL 7.4 or later])) AC_CHECK_LIB(pq, PQresultErrorField,AC_DEFINE(HAVE_PQRESULTERRORFIELD,1,[PostgreSQL 7.4 or later])) AC_CHECK_LIB(pq, pg_encoding_to_char,AC_DEFINE(HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT,1,[Whether libpq is compiled with --enable-multibyte])) + + AC_CHECK_LIB(pq, PQprepare,AC_DEFINE(HAVE_PQPREPARE,1,[prepared statements])) + LIBS=$old_LIBS LDFLAGS=$old_LDFLAGS http://cvs.php.net/diff.php/php-src/ext/pdo_pgsql/pgsql_driver.c?r1=1.49&r2=1.50&ty=u Index: php-src/ext/pdo_pgsql/pgsql_driver.c diff -u php-src/ext/pdo_pgsql/pgsql_driver.c:1.49 php-src/ext/pdo_pgsql/pgsql_driver.c:1.50 --- php-src/ext/pdo_pgsql/pgsql_driver.c:1.49 Thu Jul 7 09:35:39 2005 +++ php-src/ext/pdo_pgsql/pgsql_driver.c Fri Jul 8 11:27:34 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pgsql_driver.c,v 1.49 2005/07/07 13:35:39 iliaa Exp $ */ +/* $Id: pgsql_driver.c,v 1.50 2005/07/08 15:27:34 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -132,19 +132,77 @@ pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; pdo_pgsql_stmt *S = ecalloc(1, sizeof(pdo_pgsql_stmt)); int scrollable; +#if HAVE_PQPREPARE + PGresult *res; + int ret; + char *nsql = NULL; + int nsql_len = 0; + ExecStatusType status; +#endif S->H = H; stmt->driver_data = S; stmt->methods = &pgsql_stmt_methods; - stmt->supports_placeholders = PDO_PLACEHOLDER_NONE; scrollable = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC) == PDO_CURSOR_SCROLL; if (scrollable) { + /* TODO: check how scrollable cursors related to prepared statements */ spprintf(&S->cursor_name, 0, "pdo_pgsql_cursor_%08x", (unsigned int) stmt); } +#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; + } + + /* 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 */ + 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; + break; + + default: + /* protocol 3.0 and above; hard error */ + pdo_pgsql_error(dbh, status, pdo_pgsql_sqlstate(res)); + PQclear(res); + return 0; + } + /* fall through */ +#endif + + stmt->supports_placeholders = PDO_PLACEHOLDER_NONE; return 1; } http://cvs.php.net/diff.php/php-src/ext/pdo_pgsql/pgsql_statement.c?r1=1.24&r2=1.25&ty=u Index: php-src/ext/pdo_pgsql/pgsql_statement.c diff -u php-src/ext/pdo_pgsql/pgsql_statement.c:1.24 php-src/ext/pdo_pgsql/pgsql_statement.c:1.25 --- php-src/ext/pdo_pgsql/pgsql_statement.c:1.24 Sat Jul 2 23:04:13 2005 +++ php-src/ext/pdo_pgsql/pgsql_statement.c Fri Jul 8 11:27:34 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pgsql_statement.c,v 1.24 2005/07/03 03:04:13 wez Exp $ */ +/* $Id: pgsql_statement.c,v 1.25 2005/07/08 15:27:34 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -49,6 +49,29 @@ S->result = NULL; } +#if HAVE_PQPREPARE + if (S->stmt_name) { + pdo_pgsql_db_handle *H = S->H; + char *q = NULL; + PGresult *res; + + spprintf(&q, 0, "DEALLOCATE %s", S->stmt_name); + res = PQexec(H->server, q); + efree(q); + if (res) PQclear(res); + efree(S->stmt_name); + S->stmt_name = NULL; + } + if (S->param_lengths) { + efree(S->param_lengths); + S->param_lengths = NULL; + } + if (S->param_values) { + efree(S->param_values); + S->param_values = NULL; + } +#endif + if (S->cursor_name) { pdo_pgsql_db_handle *H = S->H; char *q = NULL; @@ -67,6 +90,7 @@ S->cols = NULL; } efree(S); + stmt->driver_data = NULL; return 1; } @@ -86,6 +110,20 @@ S->current_row = 0; +#if HAVE_PQPREPARE + if (S->stmt_name) { + /* using a prepared statement */ + + 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, + 0); + } else +#endif if (S->cursor_name) { char *q = NULL; spprintf(&q, 0, "DECLARE %s CURSOR FOR %s", S->cursor_name, stmt->active_query_string); @@ -119,6 +157,44 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC) { + pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; + + if (S->stmt_name && param->is_param) { + switch (event_type) { + case PDO_PARAM_EVT_ALLOC: + /* decode name from $1, $2 into 0, 1 etc. */ + if (param->name) { + param->paramno = atoi(param->name + 1); + } + break; + + case PDO_PARAM_EVT_EXEC_PRE: + if (!S->param_values) { + S->param_values = ecalloc( + zend_hash_num_elements(stmt->bound_params), + sizeof(char*)); + S->param_lengths = ecalloc( + zend_hash_num_elements(stmt->bound_params), + sizeof(int)); + S->param_formats = ecalloc( + zend_hash_num_elements(stmt->bound_params), + sizeof(int)); + + } + if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_NULL || + Z_TYPE_P(param->parameter) == IS_NULL) { + S->param_values[param->paramno] = NULL; + S->param_lengths[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] = 1; + } + + break; + } + } return 1; } http://cvs.php.net/diff.php/php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h?r1=1.11&r2=1.12&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.11 php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h:1.12 --- php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h:1.11 Fri Jul 1 18:30:55 2005 +++ php-src/ext/pdo_pgsql/php_pdo_pgsql_int.h Fri Jul 8 11:27:34 2005 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | + | Copyright (c) 1997-2005 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_pdo_pgsql_int.h,v 1.11 2005/07/01 22:30:55 edink Exp $ */ +/* $Id: php_pdo_pgsql_int.h,v 1.12 2005/07/08 15:27:34 wez Exp $ */ #ifndef PHP_PDO_PGSQL_INT_H #define PHP_PDO_PGSQL_INT_H @@ -55,6 +55,12 @@ int current_row; pdo_pgsql_column *cols; char *cursor_name; +#if HAVE_PQPREPARE + char *stmt_name; + char **param_values; + int *param_lengths; + int *param_formats; +#endif } pdo_pgsql_stmt; typedef struct {
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php