Skip to content

Commit

Permalink
Merge pull request #51 from racklin/bugfix/postgresql_describe
Browse files Browse the repository at this point in the history
Fixed PostgreSQL describeColumns bug and describe* with schema support.
  • Loading branch information
Phalcon committed Sep 4, 2012
2 parents 72fb3d6 + 5b3e354 commit a03deab
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 39 deletions.
48 changes: 24 additions & 24 deletions dev/db/adapter/pdo/postgresql.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ PHP_METHOD(Phalcon_Db_Adapter_Pdo_Postgresql, describeColumns){
zval *matches = NULL, *pattern = NULL, *column_name = NULL, *column = NULL;
zval *t0 = NULL, *t1 = NULL;
zval *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *r4 = NULL;
zval *char_size = NULL, *numeric_size = NULL;
HashTable *ah0;
HashPosition hp0;
zval **hd;
Expand Down Expand Up @@ -181,50 +182,72 @@ PHP_METHOD(Phalcon_Db_Adapter_Pdo_Postgresql, describeColumns){
PHALCON_INIT_VAR(column_type);
phalcon_array_fetch_string(&column_type, field, SL("type"), PH_NOISY_CC);

PHALCON_INIT_VAR(char_size);
phalcon_array_fetch_string(&char_size, field, SL("size"), PH_NOISY_CC);

PHALCON_INIT_VAR(numeric_size);
phalcon_array_fetch_string(&numeric_size, field, SL("numericsize"), PH_NOISY_CC);

PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("int") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 0, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string_bool(&definition, SL("isNumeric"), 1, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string(&definition, SL("size"), &numeric_size, PH_COPY | PH_SEPARATE TSRMLS_CC);
} else {
PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("varying") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 2, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string(&definition, SL("size"), &char_size, PH_COPY | PH_SEPARATE TSRMLS_CC);
} else {
PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("date") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 1, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string_long(&definition, SL("size"), 0, PH_SEPARATE TSRMLS_CC);
} else {
PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("numeric") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 3, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string_bool(&definition, SL("isNumeric"), 1, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string(&definition, SL("size"), &numeric_size, PH_COPY | PH_SEPARATE TSRMLS_CC);
} else {
PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("char") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 5, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string(&definition, SL("size"), &char_size, PH_COPY | PH_SEPARATE TSRMLS_CC);
} else {
PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("timestamp") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 4, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string_long(&definition, SL("size"), 0, PH_SEPARATE TSRMLS_CC);
} else {
PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("text") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 6, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string(&definition, SL("size"), &char_size, PH_COPY | PH_SEPARATE TSRMLS_CC);
} else {
PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("float") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 7, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string_bool(&definition, SL("isNumeric"), 1, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string(&definition, SL("size"), &numeric_size, PH_COPY | PH_SEPARATE TSRMLS_CC);
} else {
phalcon_array_update_string_long(&definition, SL("type"), 2, PH_SEPARATE TSRMLS_CC);
PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("uuid") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
phalcon_array_update_string_long(&definition, SL("type"), 5, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string_long(&definition, SL("size"), 36, PH_SEPARATE TSRMLS_CC);
} else {
phalcon_array_update_string_long(&definition, SL("type"), 2, PH_SEPARATE TSRMLS_CC);
phalcon_array_update_string(&definition, SL("size"), &char_size, PH_COPY | PH_SEPARATE TSRMLS_CC);
}
}
}
}
Expand All @@ -234,29 +257,6 @@ PHP_METHOD(Phalcon_Db_Adapter_Pdo_Postgresql, describeColumns){
}
}

PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("(") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
PHALCON_INIT_VAR(matches);
array_init(matches);

PHALCON_INIT_VAR(pattern);
ZVAL_STRING(pattern, "#\\(([0-9]+)(,[0-9]+)*\\)#", 1);
Z_SET_ISREF_P(matches);

PHALCON_INIT_VAR(r0);
PHALCON_CALL_FUNC_PARAMS_3(r0, "preg_match", pattern, column_type, matches);
Z_UNSET_ISREF_P(matches);
if (zend_is_true(r0)) {
eval_int = phalcon_array_isset_long(matches, 1);
if (eval_int) {
PHALCON_INIT_VAR(r1);
phalcon_array_fetch_long(&r1, matches, 1, PH_NOISY_CC);
phalcon_array_update_string(&definition, SL("size"), &r1, PH_COPY | PH_SEPARATE TSRMLS_CC);
}
}
}

PHALCON_INIT_VAR(status);
phalcon_fast_strpos_str(status, column_type, SL("unsigned") TSRMLS_CC);
if (PHALCON_IS_NOT_FALSE(status)) {
Expand Down
31 changes: 21 additions & 10 deletions dev/db/dialect/postgresql.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,12 @@ PHP_METHOD(Phalcon_Db_Dialect_Postgresql, describeColumns){
}

PHALCON_INIT_VAR(sql);
PHALCON_CONCAT_SVSVS(sql, "SELECT a.attname AS Field, format_type(a.atttypid, a.atttypmod) AS Type, CASE WHEN attnotnull=false THEN 'YES' ELSE 'NO' END AS Null, CASE WHEN (select cc.contype FROM pg_catalog.pg_constraint cc WHERE cc.conrelid = c.oid AND cc.conkey[1] = a.attnum)='p' THEN 'PRI' ELSE '' END AS Key, CASE WHEN t.typname LIKE '%int%' AND (SELECT column_default FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '", table, "' AND column_name = a.attname) LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra FROM pg_catalog.pg_Class c, pg_catalog.pg_attribute a, pg_catalog.pg_type t WHERE c.relname = '", table, "' AND c.oid = a.attrelid AND a.attnum > 0 AND c.relhaspkey = 't' AND t.oid = a.atttypid ORDER BY a.attnum");

if (zend_is_true(schema)) {
PHALCON_CONCAT_SVSVS(sql, "SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) WHERE c.table_schema='", schema, "' AND c.table_name='", table, "' ORDER BY c.ordinal_position");
} else {
PHALCON_CONCAT_SVS(sql, "SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) WHERE c.table_schema='public' AND c.table_name='", table, "' ORDER BY c.ordinal_position");
}

RETURN_CTOR(sql);
}

Expand All @@ -470,10 +474,14 @@ PHP_METHOD(Phalcon_Db_Dialect_Postgresql, listTables){
PHALCON_ALLOC_ZVAL_MM(schema_name);
ZVAL_NULL(schema_name);
}

PHALCON_INIT_VAR(sql);
ZVAL_STRING(sql, "SELECT c.relname AS table_name FROM pg_Class c, pg_user u WHERE c.relowner = u.usesysid AND c.relkind = 'r' AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname) AND c.relname !~ '^(pg_|sql_)' UNION SELECT c.relname AS table_name FROM pg_Class c WHERE c.relkind = 'r' AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname) AND NOT EXISTS (SELECT 1 FROM pg_user WHERE usesysid = c.relowner) AND c.relname !~ '^pg_' ORDER BY 1", 1);

if (zend_is_true(schema_name)) {
PHALCON_CONCAT_SVS(sql, "SELECT table_name FROM information_schema.tables WHERE table_schema = '", schema_name, "' ORDER BY table_name");
} else {
ZVAL_STRING(sql, "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name", 1);
}

RETURN_CTOR(sql);
}

Expand Down Expand Up @@ -501,8 +509,12 @@ PHP_METHOD(Phalcon_Db_Dialect_Postgresql, describeIndexes){
}

PHALCON_INIT_VAR(sql);
PHALCON_CONCAT_SVS(sql, "SELECT t.relname as table_name, i.relname as key_name, a.attname as column_name FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND t.relkind = 'r' AND t.relname = '", table, "' ORDER BY t.relname, i.relname;");

if (zend_is_true(schema)) {
PHALCON_CONCAT_SVSVS(sql, "SELECT n.nspname as table_schema, t.relname as table_name, i.relname as key_name, a.attname as column_name FROM pg_class t, pg_class i, pg_index ix, pg_attribute a, pg_namespace n WHERE t.relnamespace=n.oid AND t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND t.relkind = 'r' AND t.relname = '", table, "' AND n.nspname = '", schema, "' ORDER BY t.relname, i.relname");
} else {
PHALCON_CONCAT_SVS(sql, "SELECT n.nspname as table_schema, t.relname as table_name, i.relname as key_name, a.attname as column_name FROM pg_class t, pg_class i, pg_index ix, pg_attribute a, pg_namespace n WHERE t.relnamespace=n.oid AND t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) AND t.relkind = 'r' AND t.relname = '", table, "' AND n.nspname = 'public' ORDER BY t.relname, i.relname");
}

RETURN_CTOR(sql);
}

Expand Down Expand Up @@ -534,15 +546,14 @@ PHP_METHOD(Phalcon_Db_Dialect_Postgresql, describeReferences){
ZVAL_STRING(sql, "SELECT tc.table_name as TABLE_NAME, kcu.column_name as COLUMN_NAME, tc.constraint_name as CONSTRAINT_NAME, tc.table_catalog as REFERENCED_TABLE_SCHEMA, ccu.table_name AS REFERENCED_TABLE_NAME, ccu.column_name AS REFERENCED_COLUMN_NAME FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name WHERE constraint_type = 'FOREIGN KEY' AND ", 1);
if (zend_is_true(schema)) {
PHALCON_ALLOC_ZVAL_MM(r0);
PHALCON_CONCAT_SVSVS(r0, "tc.table_catalog = '", schema, "' AND tc.table_name='", table, "'");
PHALCON_CONCAT_SVSVS(r0, "tc.table_schema = '", schema, "' AND tc.table_name='", table, "'");
phalcon_concat_self(&sql, r0 TSRMLS_CC);
} else {
PHALCON_ALLOC_ZVAL_MM(r1);
PHALCON_CONCAT_SVS(r1, "tc.table_name='", table, "'");
phalcon_concat_self(&sql, r1 TSRMLS_CC);
}



RETURN_CTOR(sql);
}

Expand Down
10 changes: 5 additions & 5 deletions unit-tests/DbDescribeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public function getExpectedColumns($adapter)
'_schemaName' => NULL,
'_type' => 0,
'_isNumeric' => true,
'_size' => 0,
'_size' => 32,
'_scale' => 0,
'_unsigned' => false,
'_notNull' => true,
Expand Down Expand Up @@ -270,7 +270,7 @@ public function getExpectedColumns($adapter)
'_schemaName' => NULL,
'_type' => 0,
'_isNumeric' => true,
'_size' => 0,
'_size' => 32,
'_scale' => 0,
'_unsigned' => false,
'_notNull' => false,
Expand Down Expand Up @@ -442,7 +442,7 @@ public function testDbPostgresql()
$tables = $connection->listTables();
$this->assertEquals($tables, $expectedTables);

$tables = $connection->listTables('phalcon_test');
$tables = $connection->listTables('public');
$this->assertEquals($tables, $expectedTables);

//Table exist
Expand Down Expand Up @@ -479,7 +479,7 @@ public function testDbPostgresql()
$describeIndexes = $connection->describeIndexes('robots_parts');
$this->assertEquals($describeIndexes, $expectedIndexes);

$describeIndexes = $connection->describeIndexes('robots_parts', 'phalcon_test');
$describeIndexes = $connection->describeIndexes('robots_parts', 'public');
$this->assertEquals($describeIndexes, $expectedIndexes);

//References
Expand All @@ -503,7 +503,7 @@ public function testDbPostgresql()
$describeReferences = $connection->describeReferences('robots_parts');
$this->assertEquals($describeReferences, $expectedReferences);

$describeReferences = $connection->describeReferences('robots_parts', 'phalcon_test');
$describeReferences = $connection->describeReferences('robots_parts', 'public');
$this->assertEquals($describeReferences, $expectedReferences);

/**/
Expand Down

0 comments on commit a03deab

Please sign in to comment.