]> granicus.if.org Git - php/commitdiff
Don't roundtrip to the database to get the column type if you already know it
authorJoe Bylund <joseph.bylund@gmail.com>
Tue, 22 Sep 2015 17:11:20 +0000 (13:11 -0400)
committerAnatol Belski <ab@php.net>
Tue, 5 Apr 2016 13:03:04 +0000 (15:03 +0200)
add_assoc_string now takes just three args

nikic's fix to move pqclear outside the if, would be a possible memory leak inside the if

(joe) check behavior of getColumnMeta

ext/pdo_pgsql/pgsql_statement.c
ext/pdo_pgsql/tests/bug62498.phpt [new file with mode: 0644]

index efa0aa787ed579af0daf3ae671fa9081c3dd6881..6a18d6dfb0b5cedc945cc74580bb4f8607a7b8ba 100644 (file)
 #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)
 {
@@ -591,29 +605,46 @@ 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;
-       }
-
-       /* We want exactly one row returned */
-       if (1 != PQntuples(res)) {
-               goto done;
-       }
-
-       add_assoc_string(return_value, "native_type", PQgetvalue(res, 0, 0));
-done:
-       PQclear(res);
-       return 1;
+  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);
+   }
+   return 1;
 }
 
 static int pdo_pgsql_stmt_cursor_closer(pdo_stmt_t *stmt)
diff --git a/ext/pdo_pgsql/tests/bug62498.phpt b/ext/pdo_pgsql/tests/bug62498.phpt
new file mode 100644 (file)
index 0000000..cefcd1f
--- /dev/null
@@ -0,0 +1,103 @@
+--TEST--
+PDO PgSQL Bug #62498 (pdo_pgsql inefficient when getColumnMeta() is used)
+--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
+echo "Begin test...\n";
+
+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);
+
+// create the table
+$db->exec("CREATE TEMPORARY TABLE bugtest_62498 (intcol INTEGER, stringcol VARCHAR(255), boolcol BOOLEAN, datecol DATE)");
+
+// insert some data
+$statement = $db->prepare("INSERT INTO bugtest_62498 (intcol, stringcol, boolcol, datecol) VALUES (:intval, :stringval, :boolval, :dateval)");
+$statement->execute(array(
+    "intval" => "42",
+    "stringval" => "The Answer",
+    "boolval" => true,
+    "dateval" => '2015-12-14',
+));
+
+$select = $db->query('SELECT intcol, stringcol, boolcol, datecol FROM bugtest_62498');
+$meta = [];
+for ($i=0; $i < 4; $i++) {
+  $meta[] = $select->getColumnMeta(0);
+}
+var_dump($meta);
+
+?>
+Done
+--EXPECT--
+Begin test...
+array(4) {
+  [0]=>
+  array(6) {
+    ["pgsql:oid"]=>
+    int(23)
+    ["native_type"]=>
+    string(4) "int4"
+    ["name"]=>
+    string(6) "intcol"
+    ["len"]=>
+    int(4)
+    ["precision"]=>
+    int(-1)
+    ["pdo_type"]=>
+    int(1)
+  }
+  [1]=>
+  array(6) {
+    ["pgsql:oid"]=>
+    int(23)
+    ["native_type"]=>
+    string(4) "int4"
+    ["name"]=>
+    string(6) "intcol"
+    ["len"]=>
+    int(4)
+    ["precision"]=>
+    int(-1)
+    ["pdo_type"]=>
+    int(1)
+  }
+  [2]=>
+  array(6) {
+    ["pgsql:oid"]=>
+    int(23)
+    ["native_type"]=>
+    string(4) "int4"
+    ["name"]=>
+    string(6) "intcol"
+    ["len"]=>
+    int(4)
+    ["precision"]=>
+    int(-1)
+    ["pdo_type"]=>
+    int(1)
+  }
+  [3]=>
+  array(6) {
+    ["pgsql:oid"]=>
+    int(23)
+    ["native_type"]=>
+    string(4) "int4"
+    ["name"]=>
+    string(6) "intcol"
+    ["len"]=>
+    int(4)
+    ["precision"]=>
+    int(-1)
+    ["pdo_type"]=>
+    int(1)
+  }
+}
+Done