summaryrefslogtreecommitdiff
path: root/ext/pdo_pgsql/pgsql_statement.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_pgsql/pgsql_statement.c')
-rw-r--r--ext/pdo_pgsql/pgsql_statement.c140
1 files changed, 108 insertions, 32 deletions
diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c
index efa0aa787e..ee06cfc439 100644
--- a/ext/pdo_pgsql/pgsql_statement.c
+++ b/ext/pdo_pgsql/pgsql_statement.c
@@ -36,17 +36,33 @@
#endif
/* from postgresql/src/include/catalog/pg_type.h */
+#define BOOLLABEL "bool"
#define BOOLOID 16
+#define BYTEALABEL "bytea"
#define BYTEAOID 17
-#define INT8OID 20
+#define DATELABEL "date"
+#define DATEOID 1082
+#define INT2LABEL "int2"
#define INT2OID 21
+#define INT4LABEL "int4"
#define INT4OID 23
-#define TEXTOID 25
+#define INT8LABEL "int8"
+#define INT8OID 20
#define OIDOID 26
+#define TEXTLABEL "text"
+#define TEXTOID 25
+#define TIMESTAMPLABEL "timestamp"
+#define TIMESTAMPOID 1114
+#define VARCHARLABEL "varchar"
+#define VARCHAROID 1043
+
+
static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
{
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
+ zend_bool server_obj_usable = IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE(stmt->database_object_handle)])
+ && !(GC_FLAGS(Z_OBJ(stmt->database_object_handle)) & IS_OBJ_FREE_CALLED);
if (S->result) {
/* free the resource */
@@ -55,11 +71,11 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
}
if (S->stmt_name) {
- pdo_pgsql_db_handle *H = S->H;
- char *q = NULL;
- PGresult *res;
+ if (S->is_prepared && server_obj_usable) {
+ pdo_pgsql_db_handle *H = S->H;
+ char *q = NULL;
+ PGresult *res;
- if (S->is_prepared) {
spprintf(&q, 0, "DEALLOCATE %s", S->stmt_name);
res = PQexec(H->server, q);
efree(q);
@@ -92,14 +108,16 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
}
if (S->cursor_name) {
- pdo_pgsql_db_handle *H = S->H;
- char *q = NULL;
- PGresult *res;
+ if (server_obj_usable) {
+ pdo_pgsql_db_handle *H = S->H;
+ char *q = NULL;
+ PGresult *res;
- spprintf(&q, 0, "CLOSE %s", S->cursor_name);
- res = PQexec(H->server, q);
- efree(q);
- if (res) PQclear(res);
+ spprintf(&q, 0, "CLOSE %s", S->cursor_name);
+ res = PQexec(H->server, q);
+ efree(q);
+ if (res) PQclear(res);
+ }
efree(S->cursor_name);
S->cursor_name = NULL;
}
@@ -274,6 +292,10 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *
break;
case PDO_PARAM_EVT_ALLOC:
+ if (!zend_hash_index_exists(stmt->bound_param_map, param->paramno)) {
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
+ return 0;
+ }
case PDO_PARAM_EVT_EXEC_POST:
case PDO_PARAM_EVT_FETCH_PRE:
case PDO_PARAM_EVT_FETCH_POST:
@@ -301,10 +323,12 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *
if (param->paramno >= 0) {
zval *parameter;
+ /*
if (param->paramno >= zend_hash_num_elements(stmt->bound_params)) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
return 0;
}
+ */
if (Z_ISREF(param->parameter)) {
parameter = Z_REFVAL(param->parameter);
@@ -573,12 +597,40 @@ static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulon
return 1;
}
+static zend_always_inline char * pdo_pgsql_translate_oid_to_table(Oid oid, PGconn *conn)
+{
+ char *table_name = NULL;
+ PGresult *tmp_res;
+ char *querystr = NULL;
+
+ spprintf(&querystr, 0, "SELECT RELNAME FROM PG_CLASS WHERE OID=%d", oid);
+
+ if ((tmp_res = PQexec(conn, querystr)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
+ if (tmp_res) {
+ PQclear(tmp_res);
+ }
+ efree(querystr);
+ return 0;
+ }
+ efree(querystr);
+
+ if ((table_name = PQgetvalue(tmp_res, 0, 0)) == NULL) {
+ PQclear(tmp_res);
+ return 0;
+ }
+
+ PQclear(tmp_res);
+ return table_name;
+}
+
static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
{
pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
PGresult *res;
char *q=NULL;
ExecStatusType status;
+ Oid table_oid;
+ char *table_name=NULL;
if (!S->result) {
return FAILURE;
@@ -591,28 +643,52 @@ static int pgsql_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *r
array_init(return_value);
add_assoc_long(return_value, "pgsql:oid", S->cols[colno].pgsql_type);
- /* Fetch metadata from Postgres system catalogue */
- 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
- */
- goto done;
+ table_oid = PQftable(S->result, colno);
+ add_assoc_long(return_value, "pgsql:table_oid", table_oid);
+ table_name = pdo_pgsql_translate_oid_to_table(table_oid, S->H->server);
+ if (table_name) {
+ add_assoc_string(return_value, "table", table_name);
}
- /* We want exactly one row returned */
- if (1 != PQntuples(res)) {
- goto done;
+ switch (S->cols[colno].pgsql_type) {
+ case BOOLOID:
+ add_assoc_string(return_value, "native_type", BOOLLABEL);
+ break;
+ case BYTEAOID:
+ add_assoc_string(return_value, "native_type", BYTEALABEL);
+ break;
+ case INT8OID:
+ add_assoc_string(return_value, "native_type", INT8LABEL);
+ break;
+ case INT2OID:
+ add_assoc_string(return_value, "native_type", INT2LABEL);
+ break;
+ case INT4OID:
+ add_assoc_string(return_value, "native_type", INT4LABEL);
+ break;
+ case TEXTOID:
+ add_assoc_string(return_value, "native_type", TEXTLABEL);
+ break;
+ case VARCHAROID:
+ add_assoc_string(return_value, "native_type", VARCHARLABEL);
+ break;
+ case DATEOID:
+ add_assoc_string(return_value, "native_type", DATELABEL);
+ break;
+ case TIMESTAMPOID:
+ add_assoc_string(return_value, "native_type", TIMESTAMPLABEL);
+ break;
+ default:
+ /* Fetch metadata from Postgres system catalogue */
+ 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 && 1 == PQntuples(res)) {
+ add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0));
+ }
+ PQclear(res);
}
-
- add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0));
-done:
- PQclear(res);
return 1;
}