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
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;
}
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;
S->cols = NULL;
}
efree(S);
+ stmt->driver_data = NULL;
return 1;
}
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);
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;
}
+----------------------------------------------------------------------+
| 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 |
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 {