diff --git a/cake/libs/model/datasources/dbo/dbo_postgres.php b/cake/libs/model/datasources/dbo/dbo_postgres.php index 15c405d2f..7d68b6afc 100644 --- a/cake/libs/model/datasources/dbo/dbo_postgres.php +++ b/cake/libs/model/datasources/dbo/dbo_postgres.php @@ -382,7 +382,10 @@ class DboPostgres extends DboSource { * @return string SQL field */ function name($data) { - return parent::name(str_replace('"__"', '__', $data)); + if (is_string($data)) { + $data = str_replace('"__"', '__', $data); + } + return parent::name($data); } /** * Generates the fields list of an SQL query. @@ -423,6 +426,44 @@ class DboPostgres extends DboSource { } return $fields; } +/** + * Returns an array of the indexes in given datasource name. + * + * @param string $model Name of model to inspect + * @return array Fields in table. Keys are column and unique + */ + function index($model) { + $index = array(); + $table = $this->fullTableName($model, false); + if ($table) { + $indexes = $this->query("SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, i.indisvalid, pg_catalog.pg_get_indexdef(i.indexrelid, 0, true) as statement, c2.reltablespace + FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i + WHERE c.oid = ( + SELECT c.oid + FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relname ~ '^(" . $table . ")$' + AND pg_catalog.pg_table_is_visible(c.oid) + AND n.nspname ~ '^(" . $this->config['schema'] . ")$' + ) + AND c.oid = i.indrelid AND i.indexrelid = c2.oid + ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname"); + foreach ($indexes as $i => $info) { + $key = array_pop($info); + if ($key['indisprimary']) { + $key['relname'] = 'PRIMARY'; + } + $col = array(); + preg_match('/\(([^\)]+)\)/', $key['statement'], $indexColumns); + $parsedColumn = $indexColumns[1]; + if (strpos($indexColumns[1], ',') !== false) { + $parsedColumn = explode(', ', $indexColumns[1]); + } + $index[$key['relname']]['unique'] = $key['indisunique']; + $index[$key['relname']]['column'] = $parsedColumn; + } + } + return $index; + } /** * Returns a limit statement in the correct format for the particular database. * diff --git a/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php b/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php index 2fa1e4c2b..ea91814e1 100644 --- a/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo/dbo_postgres.test.php @@ -479,5 +479,37 @@ class DboPostgresTest extends CakeTestCase { $db1->query('DROP TABLE ' . $db1->fullTableName('datatypes')); } + +/** + * Test index generation from table info. + * + * @return void + **/ + function testIndexGeneration() { + $name = $this->db->fullTableName('index_test', false); + $this->db->query('CREATE TABLE ' . $name . ' ("id" serial NOT NULL PRIMARY KEY, "bool" integer, "small_char" varchar(50), "description" varchar(40) )'); + $this->db->query('CREATE INDEX pointless_bool ON ' . $name . '("bool")'); + $this->db->query('CREATE UNIQUE INDEX char_index ON ' . $name . '("small_char")'); + $expected = array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'pointless_bool' => array('column' => 'bool', 'unique' => 0), + 'char_index' => array('column' => 'small_char', 'unique' => 1), + + ); + $result = $this->db->index($name); + $this->assertEqual($expected, $result); + + $this->db->query('DROP TABLE ' . $name); + $name = $this->db->fullTableName('index_test_2', false); + $this->db->query('CREATE TABLE ' . $name . ' ("id" serial NOT NULL PRIMARY KEY, "bool" integer, "small_char" varchar(50), "description" varchar(40) )'); + $this->db->query('CREATE UNIQUE INDEX multi_col ON ' . $name . '("small_char", "bool")'); + $expected = array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'multi_col' => array('column' => array('small_char', 'bool'), 'unique' => 1), + ); + $result = $this->db->index($name); + $this->assertEqual($expected, $result); + $this->db->query('DROP TABLE ' . $name); + } } ?> \ No newline at end of file