diff options
Diffstat (limited to 'ext/pdo_pgsql')
-rw-r--r-- | ext/pdo_pgsql/config.m4 | 20 | ||||
-rw-r--r-- | ext/pdo_pgsql/config.w32 | 5 | ||||
-rw-r--r-- | ext/pdo_pgsql/pdo_pgsql.c | 1 | ||||
-rw-r--r-- | ext/pdo_pgsql/pgsql_driver.c | 68 | ||||
-rw-r--r-- | ext/pdo_pgsql/pgsql_statement.c | 86 | ||||
-rw-r--r-- | ext/pdo_pgsql/php_pdo_pgsql_int.h | 13 | ||||
-rw-r--r-- | ext/pdo_pgsql/tests/bug48764.phpt | 22 | ||||
-rw-r--r-- | ext/pdo_pgsql/tests/bug62479.phpt | 4 | ||||
-rw-r--r-- | ext/pdo_pgsql/tests/bug_33876.phpt | 2 | ||||
-rw-r--r-- | ext/pdo_pgsql/tests/disable_prepares.phpt | 54 |
10 files changed, 166 insertions, 109 deletions
diff --git a/ext/pdo_pgsql/config.m4 b/ext/pdo_pgsql/config.m4 index afe42e06a5..c61c5de4f4 100644 --- a/ext/pdo_pgsql/config.m4 +++ b/ext/pdo_pgsql/config.m4 @@ -34,7 +34,7 @@ if test "$PHP_PDO_PGSQL" != "no"; then else PGSQL_SEARCH_PATHS=$PHP_PDO_PGSQL fi - + for i in $PGSQL_SEARCH_PATHS; do for j in include include/pgsql include/postgres include/postgresql ""; do if test -r "$i/$j/libpq-fe.h"; then @@ -47,7 +47,7 @@ if test "$PHP_PDO_PGSQL" != "no"; then done for j in $PHP_LIBDIR $PHP_LIBDIR/pgsql $PHP_LIBDIR/postgres $PHP_LIBDIR/postgresql ""; do - if test -f "$i/$j/libpq.so" || test -f "$i/$j/libpq.a"; then + if test -f "$i/$j/libpq.so" || test -f "$i/$j/libpq.a"; then PGSQL_LIBDIR=$i/$j fi done @@ -84,17 +84,11 @@ if test "$PHP_PDO_PGSQL" != "no"; then old_LIBS=$LIBS old_LDFLAGS=$LDFLAGS LDFLAGS="-L$PGSQL_LIBDIR $LDFLAGS" - AC_CHECK_LIB(pq, PQparameterStatus,AC_DEFINE(HAVE_PQPARAMETERSTATUS,1,[PostgreSQL 7.4 or later]), [ - echo "Unable to build the PDO PostgreSQL driver: libpq 7.4+ is required" - exit 1 - ]) - - AC_CHECK_LIB(pq, PQprepare,AC_DEFINE(HAVE_PQPREPARE,1,[PostgreSQL 8.0 or later])) - AC_CHECK_LIB(pq, PQescapeStringConn, AC_DEFINE(HAVE_PQESCAPE_CONN,1,[PostgreSQL 8.1.4 or later])) - AC_CHECK_LIB(pq, PQescapeByteaConn, AC_DEFINE(HAVE_PQESCAPE_BYTEA_CONN,1,[PostgreSQL 8.1.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_MSG_ERROR([Unable to build the PDO PostgreSQL driver: a newer libpq is required])) + AC_CHECK_LIB(pq, PQexecParams,, AC_MSG_ERROR([Unable to build the PDO PostgreSQL driver: a newer libpq is required])) + AC_CHECK_LIB(pq, PQescapeStringConn,, AC_MSG_ERROR([Unable to build the PDO PostgreSQL driver: a newer libpq is required])) + AC_CHECK_LIB(pq, PQescapeByteaConn,, AC_MSG_ERROR([Unable to build the PDO PostgreSQL driver: a newer libpq is required])) LIBS=$old_LIBS LDFLAGS=$old_LDFLAGS @@ -124,6 +118,6 @@ if test "$PHP_PDO_PGSQL" != "no"; then PHP_NEW_EXTENSION(pdo_pgsql, pdo_pgsql.c pgsql_driver.c pgsql_statement.c, $ext_shared,,-I$pdo_cv_inc_path $PDO_PGSQL_CFLAGS) ifdef([PHP_ADD_EXTENSION_DEP], [ - PHP_ADD_EXTENSION_DEP(pdo_pgsql, pdo) + PHP_ADD_EXTENSION_DEP(pdo_pgsql, pdo) ]) fi diff --git a/ext/pdo_pgsql/config.w32 b/ext/pdo_pgsql/config.w32 index 223780e3f9..2097dc2da9 100644 --- a/ext/pdo_pgsql/config.w32 +++ b/ext/pdo_pgsql/config.w32 @@ -13,10 +13,7 @@ if (PHP_PDO_PGSQL != "no") { } AC_DEFINE('HAVE_PDO_PGSQL', 1, 'Have PostgreSQL library'); - AC_DEFINE('HAVE_PQESCAPE_BYTEA_CONN', 1, 'Have PQescapeByteaConn'); - AC_DEFINE('HAVE_PQESCAPE_CONN', 1, 'Have PQescapeConn'); - AC_DEFINE('HAVE_PQPREPARE', 1, 'Have PQprepare'); - ADD_FLAG('CFLAGS_PDO_PGSQL', "/D HAVE_PQPARAMETERSTATUS=1 /D HAVE_PQPROTOCOLVERSION=1 /D HAVE_PGTRANSACTIONSTATUS=1 /D HAVE_PQUNESCAPEBYTEA=1 /D HAVE_PQRESULTERRORFIELD=1 /D HAVE_PQESCAPE_CONN=1 /D HAVE_PQESCAPE_BYTEA_CONN=1"); + ADD_EXTENSION_DEP('pdo_pgsql', 'pdo'); } else { WARNING("pdo_pgsql not enabled; libraries and headers not found"); diff --git a/ext/pdo_pgsql/pdo_pgsql.c b/ext/pdo_pgsql/pdo_pgsql.c index 8e4cc97fb5..fe003f8ab9 100644 --- a/ext/pdo_pgsql/pdo_pgsql.c +++ b/ext/pdo_pgsql/pdo_pgsql.c @@ -86,6 +86,7 @@ ZEND_GET_MODULE(pdo_pgsql) PHP_MINIT_FUNCTION(pdo_pgsql) { REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT); + REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_PREPARES", PDO_PGSQL_ATTR_DISABLE_PREPARES); REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_IDLE", (long)PGSQL_TRANSACTION_IDLE); REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_ACTIVE", (long)PGSQL_TRANSACTION_ACTIVE); REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_INTRANS", (long)PGSQL_TRANSACTION_INTRANS); diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index ebdaaed3f1..24a5865c75 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -58,7 +58,7 @@ static char * _pdo_pgsql_trim_message(const char *message, int persistent) tmp = pemalloc(i + 1, persistent); memcpy(tmp, message, i); tmp[i] = '\0'; - + return tmp; } @@ -220,12 +220,11 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, 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 int ret; char *nsql = NULL; int nsql_len = 0; int emulate = 0; -#endif + int execute_only = 0; S->H = H; stmt->driver_data = S; @@ -239,19 +238,21 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, efree(S->cursor_name); } spprintf(&S->cursor_name, 0, "pdo_crsr_%08x", ++H->stmt_counter); -#if HAVE_PQPREPARE emulate = 1; -#endif - } - -#if HAVE_PQPREPARE - else if (driver_options) { - if (pdo_attr_lval(driver_options, PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, H->disable_native_prepares TSRMLS_CC) == 1 || - pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES, H->emulate_prepares TSRMLS_CC) == 1) { + } else if (driver_options) { + if (pdo_attr_lval(driver_options, PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, H->disable_native_prepares TSRMLS_CC) == 1) { + php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead"); + emulate = 1; + } + if (pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES, H->emulate_prepares TSRMLS_CC) == 1) { emulate = 1; } + if (pdo_attr_lval(driver_options, PDO_PGSQL_ATTR_DISABLE_PREPARES, H->disable_prepares TSRMLS_CC) == 1) { + execute_only = 1; + } } else { emulate = H->disable_native_prepares || H->emulate_prepares; + execute_only = H->disable_prepares; } if (!emulate && PQprotocolVersion(H->server) > 2) { @@ -268,9 +269,12 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, return 0; } - spprintf(&S->stmt_name, 0, "pdo_stmt_%08x", ++H->stmt_counter); - /* that's all for now; we'll defer the actual prepare until the first execute call */ - + if (!execute_only) { + /* prepared query: set the query name and defer the + actual prepare until the first execute call */ + spprintf(&S->stmt_name, 0, "pdo_stmt_%08x", ++H->stmt_counter); + } + if (nsql) { S->query = nsql; } else { @@ -279,7 +283,6 @@ static int pgsql_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, return 1; } -#endif stmt->supports_placeholders = PDO_PLACEHOLDER_NONE; return 1; @@ -291,7 +294,7 @@ static long pgsql_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRM PGresult *res; long ret = 1; ExecStatusType qs; - + if (!(res = PQexec(H->server, sql))) { /* fatal error */ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); @@ -315,15 +318,11 @@ static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote unsigned char *escaped; pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; size_t tmp_len; - + switch (paramtype) { case PDO_PARAM_LOB: /* escapedlen returned by PQescapeBytea() accounts for trailing 0 */ -#ifdef HAVE_PQESCAPE_BYTEA_CONN escaped = PQescapeByteaConn(H->server, (unsigned char *)unquoted, (size_t)unquotedlen, &tmp_len); -#else - escaped = PQescapeBytea((unsigned char *)unquoted, (size_t)unquotedlen, &tmp_len); -#endif *quotedlen = (int)tmp_len + 1; *quoted = emalloc(*quotedlen + 1); memcpy((*quoted)+1, escaped, *quotedlen-2); @@ -335,11 +334,7 @@ static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquote default: *quoted = safe_emalloc(2, unquotedlen, 3); (*quoted)[0] = '\''; -#ifndef HAVE_PQESCAPE_CONN - *quotedlen = PQescapeString(*quoted + 1, unquoted, (size_t)unquotedlen); -#else *quotedlen = PQescapeStringConn(H->server, *quoted + 1, unquoted, (size_t)unquotedlen, NULL); -#endif (*quoted)[*quotedlen + 1] = '\''; (*quoted)[*quotedlen + 2] = '\0'; *quotedlen += 2; @@ -441,8 +436,8 @@ static int pdo_pgsql_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value case PDO_ATTR_SERVER_INFO: { int spid = PQbackendPID(H->server); char *tmp; - spprintf(&tmp, 0, - "PID: %d; Client Encoding: %s; Is Superuser: %s; Session Authorization: %s; Date Style: %s", + spprintf(&tmp, 0, + "PID: %d; Client Encoding: %s; Is Superuser: %s; Session Authorization: %s; Date Style: %s", spid, (char*)PQparameterStatus(H->server, "client_encoding"), (char*)PQparameterStatus(H->server, "is_superuser"), @@ -453,7 +448,7 @@ static int pdo_pgsql_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value break; default: - return 0; + return 0; } return 1; @@ -577,7 +572,7 @@ static PHP_METHOD(PDO, pgsqlCopyFromArray) while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) { int query_len; convert_to_string_ex(tmp); - + if (buffer_len < Z_STRLEN_PP(tmp)) { buffer_len = Z_STRLEN_PP(tmp); query = erealloc(query, buffer_len + 2); /* room for \n\0 */ @@ -873,7 +868,7 @@ static PHP_METHOD(PDO, pgsqlCopyToArray) int ret = PQgetCopyData(H->server, &csv, 0); if (ret == -1) { break; /* copy done */ - } else if (ret > 0) { + } else if (ret > 0) { add_next_index_stringl(return_value, csv, ret); PQfreemem(csv); } else { @@ -951,7 +946,7 @@ static PHP_METHOD(PDO, pgsqlLOBOpen) if (strpbrk(modestr, "+w")) { mode = INV_READ|INV_WRITE; } - + dbh = zend_object_store_get_object(getThis() TSRMLS_CC); PDO_CONSTRUCT_CHECK; PDO_DBH_CLEAR_ERR(); @@ -1118,15 +1113,16 @@ static int pdo_pgsql_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC) pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; switch (attr) { -#if HAVE_PQPREPARE case PDO_ATTR_EMULATE_PREPARES: H->emulate_prepares = Z_LVAL_P(val); return 1; case PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT: + php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead"); H->disable_native_prepares = Z_LVAL_P(val); return 1; -#endif - + case PDO_PGSQL_ATTR_DISABLE_PREPARES: + H->disable_prepares = Z_LVAL_P(val); + return 1; default: return 0; } @@ -1163,7 +1159,7 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ H->einfo.errcode = 0; H->einfo.errmsg = NULL; - + /* PostgreSQL wants params in the connect string to be separated by spaces, * if the PDO standard semicolons are used, we convert them to spaces */ @@ -1233,7 +1229,7 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ dbh->max_escaped_char_length = 2; ret = 1; - + cleanup: dbh->methods = &pgsql_methods; if (!ret) { diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 904bce6c67..c9c9e5c450 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -54,7 +54,6 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) S->result = NULL; } -#if HAVE_PQPREPARE if (S->stmt_name) { pdo_pgsql_db_handle *H = S->H; char *q = NULL; @@ -91,7 +90,6 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) efree(S->query); S->query = NULL; } -#endif if (S->cursor_name) { pdo_pgsql_db_handle *H = S->H; @@ -105,7 +103,7 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) efree(S->cursor_name); S->cursor_name = NULL; } - + if(S->cols) { efree(S->cols); S->cols = NULL; @@ -126,7 +124,7 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) PQclear(S->result); S->result = NULL; } - + S->current_row = 0; if (S->cursor_name) { @@ -156,16 +154,14 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) spprintf(&q, 0, "FETCH FORWARD 0 FROM %s", S->cursor_name); S->result = PQexec(H->server, q); efree(q); - } else -#if HAVE_PQPREPARE - if (S->stmt_name) { + } else if (S->stmt_name) { /* using a prepared statement */ if (!S->is_prepared) { stmt_retry: /* 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, + 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); @@ -178,10 +174,10 @@ stmt_retry: break; default: { char *sqlstate = pdo_pgsql_sqlstate(S->result); - /* 42P05 means that the prepared statement already existed. this can happen if you use - * a connection pooling software line pgpool which doesn't close the db-connection once - * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no - * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we + /* 42P05 means that the prepared statement already existed. this can happen if you use + * a connection pooling software line pgpool which doesn't close the db-connection once + * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no + * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we * deallocate it and retry ONCE (thies 2005.12.15) */ if (sqlstate && !strcmp(sqlstate, "42P05")) { @@ -208,9 +204,17 @@ stmt_retry: S->param_lengths, S->param_formats, 0); - } else -#endif - { + } else if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED) { + /* execute query with parameters */ + S->result = PQexecParams(H->server, S->query, + stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, + S->param_types, + (const char**)S->param_values, + S->param_lengths, + S->param_formats, + 0); + } else { + /* execute plain query (with embedded parameters) */ S->result = PQexec(H->server, stmt->active_query_string); } status = PQresultStatus(S->result); @@ -238,10 +242,9 @@ stmt_retry: static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC) { -#if HAVE_PQPREPARE pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; - if (S->stmt_name && param->is_param) { + if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED && param->is_param) { switch (event_type) { case PDO_PARAM_EVT_FREE: if (param->driver_data) { @@ -320,10 +323,10 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data * return 1; } else { int len; - + SEPARATE_ZVAL_IF_NOT_REF(¶m->parameter); Z_TYPE_P(param->parameter) = IS_STRING; - + if ((len = php_stream_copy_to_mem(stm, &Z_STRVAL_P(param->parameter), PHP_STREAM_COPY_ALL, 0)) > 0) { Z_STRLEN_P(param->parameter) = len; } else { @@ -362,20 +365,15 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data * } break; } - } else { -#endif - if (param->is_param) { - /* We need to manually convert to a pg native boolean value */ - if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && - ((param->param_type & PDO_PARAM_INPUT_OUTPUT) != PDO_PARAM_INPUT_OUTPUT)) { - SEPARATE_ZVAL(¶m->parameter); - param->param_type = PDO_PARAM_STR; - ZVAL_STRINGL(param->parameter, Z_BVAL_P(param->parameter) ? "t" : "f", 1, 1); - } - } -#if HAVE_PQPREPARE + } else if (param->is_param) { + /* We need to manually convert to a pg native boolean value */ + if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && + ((param->param_type & PDO_PARAM_INPUT_OUTPUT) != PDO_PARAM_INPUT_OUTPUT)) { + SEPARATE_ZVAL(¶m->parameter); + param->param_type = PDO_PARAM_STR; + ZVAL_STRINGL(param->parameter, Z_BVAL_P(param->parameter) ? "t" : "f", 1, 1); + } } -#endif return 1; } @@ -399,7 +397,7 @@ static int pgsql_stmt_fetch(pdo_stmt_t *stmt, default: return 0; } - + spprintf(&q, 0, "FETCH %s FROM %s", ori_str, S->cursor_name); efree(ori_str); S->result = PQexec(S->H->server, q); @@ -432,7 +430,7 @@ static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; struct pdo_column_data *cols = stmt->columns; struct pdo_bound_param_data *param; - + if (!S->result) { return 0; } @@ -442,13 +440,13 @@ static int pgsql_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) cols[colno].maxlen = PQfsize(S->result, colno); cols[colno].precision = PQfmod(S->result, colno); S->cols[colno].pgsql_type = PQftype(S->result, colno); - + switch(S->cols[colno].pgsql_type) { case BOOLOID: cols[colno].param_type = PDO_PARAM_BOOL; break; - + case OIDOID: /* did the user bind the column as a LOB ? */ if (stmt->bound_columns && ( @@ -506,7 +504,7 @@ static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned } else { *ptr = PQgetvalue(S->result, S->current_row - 1, colno); *len = PQgetlength(S->result, S->current_row - 1, colno); - + switch(cols[colno].param_type) { case PDO_PARAM_INT: @@ -520,7 +518,7 @@ static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned *ptr = (char *) &(S->cols[colno].boolval); *len = sizeof(zend_bool); break; - + case PDO_PARAM_LOB: if (S->cols[colno].pgsql_type == OIDOID) { /* ooo, a real large object */ @@ -574,15 +572,15 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, long colno, zval *return PGresult *res; char *q=NULL; ExecStatusType status; - + if (!S->result) { return FAILURE; } - + if (colno >= stmt->column_count) { return FAILURE; } - + array_init(return_value); add_assoc_long(return_value, "pgsql:oid", S->cols[colno].pgsql_type); @@ -590,9 +588,9 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, long colno, zval *return spprintf(&q, 0, "SELECT TYPNAME FROM PG_TYPE WHERE OID=%u", S->cols[colno].pgsql_type); res = PQexec(S->H->server, q); efree(q); - + status = PQresultStatus(res); - + if (status != PGRES_TUPLES_OK) { /* Failed to get system catalogue, but return success * with the data we have collected so far @@ -607,7 +605,7 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, long colno, zval *return add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0)); done: - PQclear(res); + PQclear(res); return 1; } diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h index 908f47d57c..1fedababd2 100644 --- a/ext/pdo_pgsql/php_pdo_pgsql_int.h +++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h @@ -43,14 +43,12 @@ typedef struct { unsigned _reserved:31; pdo_pgsql_error_info einfo; Oid pgoid; -#if HAVE_PQPREPARE /* The following two variables have the same purpose. Unfortunately we need - to keep track of two different attributes having the same effect. - It might be worth to deprecate the driver specific one soon. */ + to keep track of two different attributes having the same effect. */ int emulate_prepares; - int disable_native_prepares; -#endif - unsigned int stmt_counter; + int disable_native_prepares; /* deprecated since 5.6 */ + int disable_prepares; + unsigned int stmt_counter; } pdo_pgsql_db_handle; typedef struct { @@ -66,14 +64,12 @@ typedef struct { int current_row; pdo_pgsql_column *cols; char *cursor_name; -#if HAVE_PQPREPARE char *stmt_name; char *query; char **param_values; int *param_lengths; int *param_formats; Oid *param_types; -#endif zend_bool is_prepared; } pdo_pgsql_stmt; @@ -95,6 +91,7 @@ extern struct pdo_stmt_methods pgsql_stmt_methods; enum { PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT = PDO_ATTR_DRIVER_SPECIFIC, + PDO_PGSQL_ATTR_DISABLE_PREPARES, }; struct pdo_pgsql_lob_self { diff --git a/ext/pdo_pgsql/tests/bug48764.phpt b/ext/pdo_pgsql/tests/bug48764.phpt index 67e8f3971f..83fa5655d8 100644 --- a/ext/pdo_pgsql/tests/bug48764.phpt +++ b/ext/pdo_pgsql/tests/bug48764.phpt @@ -104,7 +104,7 @@ function bug($db, $options = array()) { } } ---EXPECT-- +--EXPECTF-- Test 1 42P18 Test 2 @@ -112,23 +112,43 @@ Test 2 OK Test 3 42P18 + +Deprecated: PDO::prepare(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d OK Test 4 OK 42P18 Test 5 + +Deprecated: PDO::setAttribute(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d + +Deprecated: PDO::prepare(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d OK + +Deprecated: PDO::setAttribute(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d 42P18 Test 6 OK 42P18 OK + +Deprecated: PDO::__construct(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d Test 7 + +Deprecated: PDO::prepare(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d OK + +Deprecated: PDO::prepare(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d OK 42P18 + +Deprecated: PDO::__construct(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d Test 8 + +Deprecated: PDO::prepare(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d OK + +Deprecated: PDO::prepare(): PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT is deprecated, use PDO::ATTR_EMULATE_PREPARES instead in %s on line %d OK OK 42P18 diff --git a/ext/pdo_pgsql/tests/bug62479.phpt b/ext/pdo_pgsql/tests/bug62479.phpt index 2e19f15002..a12bb8d1ff 100644 --- a/ext/pdo_pgsql/tests/bug62479.phpt +++ b/ext/pdo_pgsql/tests/bug62479.phpt @@ -30,7 +30,7 @@ $testQuery = 'SELECT 1 as verification'; // Create temp user with space in password $sql = sprintf($template, 'my password'); $pdo->query($sql); -$testConn = new PDO($_ENV['PDOTEST_DSN'], $user, "my password"); +$testConn = new PDO($conf['ENV']['PDOTEST_DSN'], $user, "my password"); $result = $testConn->query($testQuery)->fetch(); $check = $result[0]; var_dump($check); @@ -42,7 +42,7 @@ $pdo->query($dropUser); $sql = sprintf($template, "my pass''word"); $pdo->query($sql); -$testConn = new PDO($_ENV['PDOTEST_DSN'], $user, "my pass'word"); +$testConn = new PDO($conf['ENV']['PDOTEST_DSN'], $user, "my pass'word"); $result = $testConn->query($testQuery)->fetch(); $check = $result[0]; var_dump($check); diff --git a/ext/pdo_pgsql/tests/bug_33876.phpt b/ext/pdo_pgsql/tests/bug_33876.phpt index 6a93905b43..15c4275d80 100644 --- a/ext/pdo_pgsql/tests/bug_33876.phpt +++ b/ext/pdo_pgsql/tests/bug_33876.phpt @@ -54,7 +54,7 @@ echo "EMUL\n"; $res = $db->prepare('SELECT foo from test where bar = ?', array( - PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => true)); + PDO::ATTR_EMULATE_PREPARES => true)); # this is the portable approach to binding a bool $res->bindValue(1, false, PDO::PARAM_BOOL); diff --git a/ext/pdo_pgsql/tests/disable_prepares.phpt b/ext/pdo_pgsql/tests/disable_prepares.phpt new file mode 100644 index 0000000000..99a7695404 --- /dev/null +++ b/ext/pdo_pgsql/tests/disable_prepares.phpt @@ -0,0 +1,54 @@ +--TEST-- +PDO PgSQL PGSQL_ATTR_DISABLE_PREPARES +--SKIPIF-- +<?php +if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded'); +require dirname(__FILE__) . '/config.inc'; +require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc'; +PDOTest::skip(); +?> +--FILE-- +<?php +require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc'; +$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt'); +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_COLUMN); + +$stmt = $db->prepare("SELECT statement FROM pg_prepared_statements", array( + PDO::ATTR_EMULATE_PREPARES => true)); + +$stmt2 = $db->prepare("SELECT (?)::int2"); +$stmt2->execute(array(1)); +var_dump($stmt2->fetch()); +$stmt2->execute(array(2)); +var_dump($stmt2->fetch()); + +$stmt->execute(); +$first = $stmt->fetchAll(); + +$stmt3 = $db->prepare("SELECT (?)::int4", array( + PDO::PGSQL_ATTR_DISABLE_PREPARES => true)); +$stmt3->execute(array(3)); +var_dump($stmt3->fetch()); +$stmt3->execute(array(4)); +var_dump($stmt3->fetch()); + +$stmt->execute(); +$second = $stmt->fetchAll(); + +var_dump($first, $second); + +?> +--EXPECT-- +string(1) "1" +string(1) "2" +string(1) "3" +string(1) "4" +array(1) { + [0]=> + string(17) "SELECT ($1)::int2" +} +array(1) { + [0]=> + string(17) "SELECT ($1)::int2" +} |