From: Felipe Pena Date: Thu, 16 Oct 2008 00:36:49 +0000 (+0000) Subject: - Fixed: X-Git-Tag: BEFORE_HEAD_NS_CHANGE~220 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e6194c69f0cdf0ff6ba7247ef1ad30fae64f545f;p=php - 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 --- diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index a2bdda0072..02d36e7b64 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -4897,27 +4897,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; @@ -5832,7 +5852,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); } } @@ -6183,7 +6203,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 index 0000000000..abb65be142 --- /dev/null +++ b/ext/pgsql/tests/pg_delete_001.phpt @@ -0,0 +1,86 @@ +--TEST-- +PostgreSQL pg_delete() - basic test using schema +--SKIPIF-- + +--FILE-- + 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 index 0000000000..7d27219187 --- /dev/null +++ b/ext/pgsql/tests/pg_insert_001.phpt @@ -0,0 +1,40 @@ +--TEST-- +PostgreSQL pg_select() - basic test using schema +--SKIPIF-- + +--FILE-- + 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 index 0000000000..2841de83d1 --- /dev/null +++ b/ext/pgsql/tests/pg_meta_data_001.phpt @@ -0,0 +1,92 @@ +--TEST-- +PostgreSQL pg_meta_data() - basic test using schema +--SKIPIF-- + +--FILE-- + +--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 index 0000000000..68af48eeb9 --- /dev/null +++ b/ext/pgsql/tests/pg_select_001.phpt @@ -0,0 +1,61 @@ +--TEST-- +PostgreSQL pg_select() - basic test using schema +--SKIPIF-- + +--FILE-- + 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 index 0000000000..95fa692568 --- /dev/null +++ b/ext/pgsql/tests/pg_update_001.phpt @@ -0,0 +1,51 @@ +--TEST-- +PostgreSQL pg_update() - basic test using schema +--SKIPIF-- + +--FILE-- + 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" +}