]> granicus.if.org Git - php/commitdiff
MFH:
authorFelipe Pena <felipe@php.net>
Thu, 16 Oct 2008 00:45:21 +0000 (00:45 +0000)
committerFelipe Pena <felipe@php.net>
Thu, 16 Oct 2008 00:45:21 +0000 (00:45 +0000)
- Fixed:
  . Memory leak in pg_delete() when using PGSQL_DML_STRING.
  . Bug #24679 (pg_insert problem!)
  . Bug #35996 (pg_meta_data should take the schema into account)
  . Bug #40808 (pg_insert problem)
  . Bug #42078 (pg_meta_data mix tables metadata from different schemas)
- Improved:
  . Error messages
- Added:
  . Tests

NEWS
ext/pgsql/pgsql.c
ext/pgsql/tests/pg_delete_001.phpt [new file with mode: 0644]
ext/pgsql/tests/pg_insert_001.phpt [new file with mode: 0644]
ext/pgsql/tests/pg_meta_data_001.phpt [new file with mode: 0644]
ext/pgsql/tests/pg_select_001.phpt [new file with mode: 0644]
ext/pgsql/tests/pg_update_001.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index c58d6d13c206cb25cff9ddff6e5b9e576252e973..905fad1fe58a57055f7442d5452d5777ea2ef62d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,7 +14,10 @@ PHP                                                                        NEWS
   after end of stream). (Keisial at gmail dot com, Greg)
 - Fixed bug #44251, #41125 (PDO + quote() + prepare() can result in segfault).
   (tsteiner at nerdclub dot net)
+- Fixed bug #42078 (pg_meta_data mix tables metadata from different schemas).
+  (Felipe)
 - Fixed bug #37100 (data is returned truncated with BINARY CURSOR). (Tony)
+- Fixed bug #24679 (pg_* functions doesn't work using schema). (Felipe)
 
 09 Oct 2008, PHP 5.2.7RC1
 - Reverted fix for bug #44197 due to behaviour change in minor version.
index aca9fec5d5899a0a78786676361a592daba5ccc8..dbfc84f471280979aae6cd59b6b46f6afa659898 100644 (file)
@@ -4411,27 +4411,47 @@ PHP_FUNCTION(pg_get_pid)
 PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, zval *meta TSRMLS_DC) 
 {
        PGresult *pg_result;
-       char *tmp_name;
+       char *src, *tmp_name, *tmp_name2 = NULL;
        smart_str querystr = {0};
        int new_len;
        int i, num_rows;
        zval *elem;
        
+       if (!*table_name) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "The table name must be specified");
+               return FAILURE;
+       }
+
+       src = estrdup(table_name);
+       tmp_name = php_strtok_r(src, ".", &tmp_name2);
+       
+       if (!*tmp_name2) {
+               /* Default schema */
+               tmp_name2 = tmp_name;
+               tmp_name = "public";
+       }
+
        smart_str_appends(&querystr, 
                        "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotNULL, a.atthasdef, a.attndims "
-                       "FROM pg_class as c, pg_attribute a, pg_type t "
+                       "FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n "
                        "WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '");
+       tmp_name2 = php_addslashes(tmp_name2, strlen(tmp_name2), &new_len, 0 TSRMLS_CC);
+       smart_str_appendl(&querystr, tmp_name2, new_len);
        
-       tmp_name = php_addslashes((char *)table_name, strlen(table_name), &new_len, 0 TSRMLS_CC);
+       smart_str_appends(&querystr, "' AND c.relnamespace = n.oid AND n.nspname = '");
+       tmp_name = php_addslashes(tmp_name, strlen(tmp_name), &new_len, 0 TSRMLS_CC);
        smart_str_appendl(&querystr, tmp_name, new_len);
-       efree(tmp_name);
 
        smart_str_appends(&querystr, "' AND a.atttypid = t.oid ORDER BY a.attnum;");
        smart_str_0(&querystr);
        
+       efree(tmp_name2);
+       efree(tmp_name);
+       efree(src);     
+       
        pg_result = PQexec(pg_link, querystr.c);
        if (PQresultStatus(pg_result) != PGRES_TUPLES_OK || (num_rows = PQntuples(pg_result)) == 0) {
-               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Failed to query meta_data for '%s' table %s", table_name, querystr.c);
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Table '%s' doesn't exists", table_name);
                smart_str_free(&querystr);
                PQclear(pg_result);
                return FAILURE;
@@ -5346,7 +5366,7 @@ static int do_exec(smart_str *querystr, int expect, PGconn *pg_link, ulong opt T
                        PQclear(pg_result);
                        return 0;
                } else {
-                       php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Failed to execute '%s'", querystr->c);
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", PQresultErrorMessage(pg_result));
                        PQclear(pg_result);
                }
        }
@@ -5697,7 +5717,7 @@ cleanup:
                FREE_ZVAL(ids_converted);
        }
        if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
-               *sql = estrdup(querystr.c);
+               *sql = querystr.c;
        }
        else {
                smart_str_free(&querystr);
diff --git a/ext/pgsql/tests/pg_delete_001.phpt b/ext/pgsql/tests/pg_delete_001.phpt
new file mode 100644 (file)
index 0000000..abb65be
--- /dev/null
@@ -0,0 +1,86 @@
+--TEST--
+PostgreSQL pg_delete() - basic test using schema
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--FILE--
+<?php
+
+include('config.inc');
+
+$conn = pg_connect($conn_str);
+
+pg_query('CREATE SCHEMA phptests');
+
+pg_query('CREATE TABLE foo (id INT, id2 INT)');
+pg_query('CREATE TABLE phptests.foo (id INT, id2 INT)');
+
+pg_insert($conn, 'foo', array('id' => 1, 'id2' => 1));
+pg_insert($conn, 'foo', array('id' => 1, 'id2' => 2));
+pg_insert($conn, 'foo', array('id' => 1, 'id2' => 2));
+pg_insert($conn, 'foo', array('id' => 3, 'id2' => 3));
+
+pg_insert($conn, 'phptests.foo', array('id' => 1, 'id2' => 1));
+pg_insert($conn, 'phptests.foo', array('id' => 1, 'id2' => 2));
+pg_insert($conn, 'phptests.foo', array('id' => 2, 'id2' => 3));
+pg_insert($conn, 'phptests.foo', array('id' => 2, 'id2' => 3));
+
+pg_delete($conn, 'foo', array('id' => 1, 'id2' => 0));
+pg_delete($conn, 'foo', array('id' => 1, 'id2' => 2));
+var_dump(pg_delete($conn, 'foo', array('id' => 1, 'id2' => 2), PGSQL_DML_STRING));
+
+pg_delete($conn, 'phptests.foo', array('id' => 2, 'id2' => 1));
+pg_delete($conn, 'phptests.foo', array('id' => 2, 'id2' => 3));
+var_dump(pg_delete($conn, 'phptests.foo', array('id' => 2, 'id2' => 3), PGSQL_DML_STRING));
+
+var_dump(pg_fetch_all(pg_query('SELECT * FROM foo')));
+var_dump(pg_fetch_all(pg_query('SELECT * FROM phptests.foo')));
+
+/* Inexistent */
+pg_delete($conn, 'bar', array('id' => 1, 'id2' => 2));
+var_dump(pg_delete($conn, 'bar', array('id' => 1, 'id2' => 2), PGSQL_DML_STRING));
+
+pg_query('DROP TABLE foo');
+pg_query('DROP TABLE phptests.foo');
+pg_query('DROP SCHEMA phptests');
+
+?>
+--EXPECTF--
+string(37) "DELETE FROM foo WHERE id=1 AND id2=2;"
+string(46) "DELETE FROM phptests.foo WHERE id=2 AND id2=3;"
+array(2) {
+  [0]=>
+  array(2) {
+    ["id"]=>
+    string(1) "1"
+    ["id2"]=>
+    string(1) "1"
+  }
+  [1]=>
+  array(2) {
+    ["id"]=>
+    string(1) "3"
+    ["id2"]=>
+    string(1) "3"
+  }
+}
+array(2) {
+  [0]=>
+  array(2) {
+    ["id"]=>
+    string(1) "1"
+    ["id2"]=>
+    string(1) "1"
+  }
+  [1]=>
+  array(2) {
+    ["id"]=>
+    string(1) "1"
+    ["id2"]=>
+    string(1) "2"
+  }
+}
+
+Warning: pg_delete(): Table 'bar' doesn't exists in %s on line %d
+
+Warning: pg_delete(): Table 'bar' doesn't exists in %s on line %d
+bool(false)
diff --git a/ext/pgsql/tests/pg_insert_001.phpt b/ext/pgsql/tests/pg_insert_001.phpt
new file mode 100644 (file)
index 0000000..7d27219
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+PostgreSQL pg_select() - basic test using schema
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--FILE--
+<?php
+
+include('config.inc');
+
+$conn = pg_connect($conn_str);
+
+pg_query('CREATE SCHEMA phptests');
+pg_query('CREATE TABLE phptests.foo (id INT, id2 INT)');
+
+
+pg_insert($conn, 'foo', array('id' => 1, 'id2' => 1));
+
+pg_insert($conn, 'phptests.foo', array('id' => 1, 'id2' => 2));
+
+var_dump(pg_insert($conn, 'phptests.foo', array('id' => 1, 'id2' => 2), PGSQL_DML_STRING));
+
+var_dump(pg_select($conn, 'phptests.foo', array('id' => 1)));
+
+pg_query('DROP TABLE phptests.foo');
+pg_query('DROP SCHEMA phptests');
+
+?>
+--EXPECTF--
+
+Warning: pg_insert(): Table 'foo' doesn't exists in %s on line %d
+string(47) "INSERT INTO phptests.foo (id,id2) VALUES (1,2);"
+array(1) {
+  [0]=>
+  array(2) {
+    ["id"]=>
+    string(1) "1"
+    ["id2"]=>
+    string(1) "2"
+  }
+}
diff --git a/ext/pgsql/tests/pg_meta_data_001.phpt b/ext/pgsql/tests/pg_meta_data_001.phpt
new file mode 100644 (file)
index 0000000..2841de8
--- /dev/null
@@ -0,0 +1,92 @@
+--TEST--
+PostgreSQL pg_meta_data() - basic test using schema
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--FILE--
+<?php
+
+include('config.inc');
+
+$conn = pg_connect($conn_str);
+
+pg_query('CREATE SCHEMA phptests');
+
+pg_query('CREATE TABLE phptests.foo (id INT, id2 INT)');
+
+pg_query('CREATE TABLE foo (id INT, id3 INT)');
+
+
+var_dump(pg_meta_data($conn, 'foo'));
+var_dump(pg_meta_data($conn, 'phptests.foo'));
+
+
+pg_query('DROP TABLE foo');
+pg_query('DROP TABLE phptests.foo');
+pg_query('DROP SCHEMA phptests');
+
+?>
+--EXPECT--
+array(2) {
+  ["id"]=>
+  array(6) {
+    ["num"]=>
+    int(1)
+    ["type"]=>
+    string(4) "int4"
+    ["len"]=>
+    int(4)
+    ["not null"]=>
+    bool(false)
+    ["has default"]=>
+    bool(false)
+    ["array dims"]=>
+    int(0)
+  }
+  ["id3"]=>
+  array(6) {
+    ["num"]=>
+    int(2)
+    ["type"]=>
+    string(4) "int4"
+    ["len"]=>
+    int(4)
+    ["not null"]=>
+    bool(false)
+    ["has default"]=>
+    bool(false)
+    ["array dims"]=>
+    int(0)
+  }
+}
+array(2) {
+  ["id"]=>
+  array(6) {
+    ["num"]=>
+    int(1)
+    ["type"]=>
+    string(4) "int4"
+    ["len"]=>
+    int(4)
+    ["not null"]=>
+    bool(false)
+    ["has default"]=>
+    bool(false)
+    ["array dims"]=>
+    int(0)
+  }
+  ["id2"]=>
+  array(6) {
+    ["num"]=>
+    int(2)
+    ["type"]=>
+    string(4) "int4"
+    ["len"]=>
+    int(4)
+    ["not null"]=>
+    bool(false)
+    ["has default"]=>
+    bool(false)
+    ["array dims"]=>
+    int(0)
+  }
+}
diff --git a/ext/pgsql/tests/pg_select_001.phpt b/ext/pgsql/tests/pg_select_001.phpt
new file mode 100644 (file)
index 0000000..68af48e
--- /dev/null
@@ -0,0 +1,61 @@
+--TEST--
+PostgreSQL pg_select() - basic test using schema
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--FILE--
+<?php
+
+include('config.inc');
+
+$conn = pg_connect($conn_str);
+
+pg_query('CREATE SCHEMA phptests');
+
+pg_query('CREATE TABLE phptests.foo (id INT, id2 INT)');
+pg_query('INSERT INTO phptests.foo VALUES (1,2), (2,3)');
+
+pg_query('CREATE TABLE phptests.bar (id4 INT, id3 INT)');
+pg_query('INSERT INTO phptests.bar VALUES (4,5), (6,7)');
+
+/* Inexistent table */
+var_dump(pg_select($conn, 'foo', array('id' => 1)));
+
+/* Existent column */
+var_dump(pg_select($conn, 'phptests.foo', array('id' => 1)));
+
+/* Testing with inexistent column */
+var_dump(pg_select($conn, 'phptests.bar', array('id' => 1)));
+
+/* Existent column */
+var_dump(pg_select($conn, 'phptests.bar', array('id4' => 4)));
+
+
+pg_query('DROP TABLE phptests.foo');
+pg_query('DROP TABLE phptests.bar');
+pg_query('DROP SCHEMA phptests');
+
+?>
+--EXPECTF--
+Warning: pg_select(): Table 'foo' doesn't exists in %s on line %d
+bool(false)
+array(1) {
+  [0]=>
+  array(2) {
+    ["id"]=>
+    string(1) "1"
+    ["id2"]=>
+    string(1) "2"
+  }
+}
+
+Notice: pg_select(): Invalid field name (id) in values in %s on line %d
+bool(false)
+array(1) {
+  [0]=>
+  array(2) {
+    ["id4"]=>
+    string(1) "4"
+    ["id3"]=>
+    string(1) "5"
+  }
+}
diff --git a/ext/pgsql/tests/pg_update_001.phpt b/ext/pgsql/tests/pg_update_001.phpt
new file mode 100644 (file)
index 0000000..95fa692
--- /dev/null
@@ -0,0 +1,51 @@
+--TEST--
+PostgreSQL pg_update() - basic test using schema
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--FILE--
+<?php
+
+include('config.inc');
+
+$conn = pg_connect($conn_str);
+
+pg_query('CREATE SCHEMA phptests');
+
+pg_query('CREATE TABLE foo (id INT, id2 INT)');
+pg_query('CREATE TABLE phptests.foo (id INT, id2 INT)');
+
+
+pg_insert($conn, 'foo', array('id' => 1, 'id2' => 1));
+pg_insert($conn, 'phptests.foo', array('id' => 1, 'id2' => 2));
+
+pg_update($conn, 'foo', array('id' => 10), array('id' => 1));
+var_dump(pg_update($conn, 'foo', array('id' => 10), array('id' => 1), PGSQL_DML_STRING));
+
+pg_update($conn, 'phptests.foo', array('id' => 100), array('id2' => 2));
+var_dump(pg_update($conn, 'phptests.foo', array('id' => 100), array('id2' => 2), PGSQL_DML_STRING));
+
+$rs = pg_query('SELECT * FROM foo UNION SELECT * FROM phptests.foo');
+while ($row = pg_fetch_assoc($rs)) {
+       var_dump($row);
+}
+
+pg_query('DROP TABLE foo');
+pg_query('DROP TABLE phptests.foo');
+pg_query('DROP SCHEMA phptests');
+
+?>
+--EXPECT--
+string(32) "UPDATE foo SET id=10 WHERE id=1;"
+string(43) "UPDATE phptests.foo SET id=100 WHERE id2=2;"
+array(2) {
+  ["id"]=>
+  string(2) "10"
+  ["id2"]=>
+  string(1) "1"
+}
+array(2) {
+  ["id"]=>
+  string(3) "100"
+  ["id2"]=>
+  string(1) "2"
+}