mirror of
https://github.com/silverstripe/silverstripe-postgresql
synced 2024-10-22 17:05:45 +02:00
BUG Fix constraints ignoring schema
This commit is contained in:
parent
e46a37090c
commit
3780d1b152
@ -171,9 +171,9 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
public function schemaList()
|
public function schemaList()
|
||||||
{
|
{
|
||||||
return $this->query("
|
return $this->query("
|
||||||
SELECT nspname
|
SELECT nspname
|
||||||
FROM pg_catalog.pg_namespace
|
FROM pg_catalog.pg_namespace
|
||||||
WHERE nspname <> 'information_schema' AND nspname !~ E'^pg_'"
|
WHERE nspname <> 'information_schema' AND nspname !~ E'^pg_'"
|
||||||
)->column();
|
)->column();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,10 +233,10 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->query("CREATE TABLE \"$table\" (
|
$this->query("CREATE TABLE \"$table\" (
|
||||||
$fieldSchemas
|
$fieldSchemas
|
||||||
$fulltexts
|
$fulltexts
|
||||||
primary key (\"ID\")
|
primary key (\"ID\")
|
||||||
)$tableSpace; $indexSchemas $addOptions");
|
)$tableSpace; $indexSchemas $addOptions");
|
||||||
|
|
||||||
if ($triggers!='') {
|
if ($triggers!='') {
|
||||||
$this->query($triggers);
|
$this->query($triggers);
|
||||||
@ -454,9 +454,9 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
//Now we can run a long query to get the clustered status:
|
//Now we can run a long query to get the clustered status:
|
||||||
//If anyone knows a better way to get the clustered status, then feel free to replace this!
|
//If anyone knows a better way to get the clustered status, then feel free to replace this!
|
||||||
$clustered = $this->preparedQuery("
|
$clustered = $this->preparedQuery("
|
||||||
SELECT c2.relname, i.indisclustered
|
SELECT c2.relname, i.indisclustered
|
||||||
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
|
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i
|
||||||
WHERE c.oid = ? AND c.oid = i.indrelid AND i.indexrelid = c2.oid AND indisclustered='t';",
|
WHERE c.oid = ? AND c.oid = i.indrelid AND i.indexrelid = c2.oid AND indisclustered='t';",
|
||||||
array($oid)
|
array($oid)
|
||||||
)->first();
|
)->first();
|
||||||
|
|
||||||
@ -478,7 +478,7 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
{
|
{
|
||||||
// First, we split the column specifications into parts
|
// First, we split the column specifications into parts
|
||||||
// TODO: this returns an empty array for the following string: int(11) not null auto_increment
|
// TODO: this returns an empty array for the following string: int(11) not null auto_increment
|
||||||
// on second thoughts, why is an auto_increment field being passed through?
|
// on second thoughts, why is an auto_increment field being passed through?
|
||||||
|
|
||||||
$pattern = '/^([\w(\,)]+)\s?((?:not\s)?null)?\s?(default\s[\w\.\']+)?\s?(check\s[\w()\'",\s]+)?$/i';
|
$pattern = '/^([\w(\,)]+)\s?((?:not\s)?null)?\s?(default\s[\w\.\']+)?\s?(check\s[\w()\'",\s]+)?$/i';
|
||||||
preg_match($pattern, $colSpec, $matches);
|
preg_match($pattern, $colSpec, $matches);
|
||||||
@ -506,7 +506,8 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SET check constraint (The constraint HAS to be dropped)
|
// SET check constraint (The constraint HAS to be dropped)
|
||||||
$existing_constraint=$this->query("SELECT conname FROM pg_constraint WHERE conname='{$tableName}_{$colName}_check';")->value();
|
$constraintName = "{$tableName}_{$colName}_check";
|
||||||
|
$constraintExists = $this->constraintExists($constraintName, false);
|
||||||
if (isset($matches[4])) {
|
if (isset($matches[4])) {
|
||||||
//Take this new constraint and see what's outstanding from the target table:
|
//Take this new constraint and see what's outstanding from the target table:
|
||||||
$constraint_bits=explode('(', $matches[4]);
|
$constraint_bits=explode('(', $matches[4]);
|
||||||
@ -529,13 +530,13 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
//First, delete any existing constraint on this column, even if it's no longer an enum
|
//First, delete any existing constraint on this column, even if it's no longer an enum
|
||||||
if ($existing_constraint) {
|
if ($constraintExists) {
|
||||||
$alterCol .= ",\nDROP CONSTRAINT \"{$tableName}_{$colName}_check\"";
|
$alterCol .= ",\nDROP CONSTRAINT \"{$constraintName}\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
//Now create the constraint (if we've asked for one)
|
//Now create the constraint (if we've asked for one)
|
||||||
if (!empty($matches[4])) {
|
if (!empty($matches[4])) {
|
||||||
$alterCol .= ",\nADD CONSTRAINT \"{$tableName}_{$colName}_check\" $matches[4]";
|
$alterCol .= ",\nADD CONSTRAINT \"{$constraintName}\" $matches[4]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,10 +591,10 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
|
|
||||||
//if(!isset(self::$cached_fieldlists[$table])){
|
//if(!isset(self::$cached_fieldlists[$table])){
|
||||||
$fields = $this->preparedQuery("
|
$fields = $this->preparedQuery("
|
||||||
SELECT ordinal_position, column_name, data_type, column_default,
|
SELECT ordinal_position, column_name, data_type, column_default,
|
||||||
is_nullable, character_maximum_length, numeric_precision, numeric_scale
|
is_nullable, character_maximum_length, numeric_precision, numeric_scale
|
||||||
FROM information_schema.columns WHERE table_name = ? and table_schema = ?
|
FROM information_schema.columns WHERE table_name = ? and table_schema = ?
|
||||||
ORDER BY ordinal_position;",
|
ORDER BY ordinal_position;",
|
||||||
array($table, $this->database->currentSchema())
|
array($table, $this->database->currentSchema())
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -676,7 +677,7 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// self::$cached_fieldlists[$table]=$output;
|
// self::$cached_fieldlists[$table]=$output;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//return self::$cached_fieldlists[$table];
|
//return self::$cached_fieldlists[$table];
|
||||||
@ -859,9 +860,9 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
{
|
{
|
||||||
//Retrieve a list of indexes for the specified table
|
//Retrieve a list of indexes for the specified table
|
||||||
$indexes = $this->preparedQuery("
|
$indexes = $this->preparedQuery("
|
||||||
SELECT tablename, indexname, indexdef
|
SELECT tablename, indexname, indexdef
|
||||||
FROM pg_catalog.pg_indexes
|
FROM pg_catalog.pg_indexes
|
||||||
WHERE tablename = ? AND schemaname = ?;",
|
WHERE tablename = ? AND schemaname = ?;",
|
||||||
array($table, $this->database->currentSchema())
|
array($table, $this->database->currentSchema())
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -886,7 +887,7 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
|
|
||||||
//TODO: Fix me: btree is the default index type:
|
//TODO: Fix me: btree is the default index type:
|
||||||
//if(strpos(strtolower($index['indexdef']), 'using btree ')!==false)
|
//if(strpos(strtolower($index['indexdef']), 'using btree ')!==false)
|
||||||
// $prefix='using btree ';
|
// $prefix='using btree ';
|
||||||
|
|
||||||
if (strpos(strtolower($index['indexdef']), 'using rtree ')!==false) {
|
if (strpos(strtolower($index['indexdef']), 'using rtree ')!==false) {
|
||||||
$type = 'rtree';
|
$type = 'rtree';
|
||||||
@ -933,16 +934,26 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
* query all over again.
|
* query all over again.
|
||||||
*
|
*
|
||||||
* @param string $constraint
|
* @param string $constraint
|
||||||
|
* @param bool $cache Flag whether a cached version should be used. Set to false to cache bust.
|
||||||
|
* @return false|array Either false, if the constraint doesn't exist, or an array
|
||||||
|
* with the keys conname and pg_get_constraintdef
|
||||||
*/
|
*/
|
||||||
protected function constraintExists($constraint)
|
protected function constraintExists($constraint, $cache = true)
|
||||||
{
|
{
|
||||||
if (!isset(self::$cached_constraints[$constraint])) {
|
if (!$cache || !isset(self::$cached_constraints[$constraint])) {
|
||||||
$exists = $this->preparedQuery("
|
$value = $this->preparedQuery("
|
||||||
SELECT conname,pg_catalog.pg_get_constraintdef(r.oid, true)
|
SELECT conname,pg_catalog.pg_get_constraintdef(r.oid, true)
|
||||||
FROM pg_catalog.pg_constraint r WHERE r.contype = 'c' AND conname = ? ORDER BY 1;",
|
FROM pg_catalog.pg_constraint r
|
||||||
array($constraint)
|
INNER JOIN pg_catalog.pg_namespace n
|
||||||
|
ON r.connamespace = n.oid
|
||||||
|
WHERE r.contype = 'c' AND conname = ? AND n.nspname = ?
|
||||||
|
ORDER BY 1;",
|
||||||
|
array($constraint, $this->database->currentSchema())
|
||||||
)->first();
|
)->first();
|
||||||
self::$cached_constraints[$constraint]=$exists;
|
if (!$cache) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
self::$cached_constraints[$constraint] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$cached_constraints[$constraint];
|
return self::$cached_constraints[$constraint];
|
||||||
@ -957,18 +968,21 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
public function tableDetails($tableName)
|
public function tableDetails($tableName)
|
||||||
{
|
{
|
||||||
$query = "SELECT a.attname as \"Column\", pg_catalog.format_type(a.atttypid, a.atttypmod) as \"Datatype\"
|
$query = "SELECT a.attname as \"Column\", pg_catalog.format_type(a.atttypid, a.atttypmod) as \"Datatype\"
|
||||||
FROM pg_catalog.pg_attribute a
|
FROM pg_catalog.pg_attribute a
|
||||||
WHERE a.attnum > 0 AND NOT a.attisdropped AND a.attrelid = (
|
WHERE a.attnum > 0 AND NOT a.attisdropped AND a.attrelid = (
|
||||||
SELECT c.oid
|
SELECT c.oid
|
||||||
FROM pg_catalog.pg_class c
|
FROM pg_catalog.pg_class c
|
||||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
||||||
WHERE c.relname = ? AND pg_catalog.pg_table_is_visible(c.oid) AND n.nspname = ?
|
WHERE c.relname = ? AND pg_catalog.pg_table_is_visible(c.oid) AND n.nspname = ?
|
||||||
);";
|
);";
|
||||||
|
|
||||||
$result = $this->preparedQuery($query, $tableName, $this->database->currentSchema());
|
$result = $this->preparedQuery(
|
||||||
|
$query,
|
||||||
|
array($tableName, $this->database->currentSchema())
|
||||||
|
);
|
||||||
|
|
||||||
$table = array();
|
$table = array();
|
||||||
while ($row = pg_fetch_assoc($result)) {
|
foreach ($result as $row) {
|
||||||
$table[] = array(
|
$table[] = array(
|
||||||
'Column' => $row['Column'],
|
'Column' => $row['Column'],
|
||||||
'DataType' => $row['DataType']
|
'DataType' => $row['DataType']
|
||||||
@ -988,9 +1002,9 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
protected function dropTrigger($triggerName, $tableName)
|
protected function dropTrigger($triggerName, $tableName)
|
||||||
{
|
{
|
||||||
$exists = $this->preparedQuery("
|
$exists = $this->preparedQuery("
|
||||||
SELECT trigger_name
|
SELECT trigger_name
|
||||||
FROM information_schema.triggers
|
FROM information_schema.triggers
|
||||||
WHERE trigger_name = ? AND trigger_schema = ?;",
|
WHERE trigger_name = ? AND trigger_schema = ?;",
|
||||||
array($triggerName, $this->database->currentSchema())
|
array($triggerName, $this->database->currentSchema())
|
||||||
)->first();
|
)->first();
|
||||||
if ($exists) {
|
if ($exists) {
|
||||||
@ -1333,8 +1347,8 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
|
|
||||||
$this->dropTrigger($triggerName, $tableName);
|
$this->dropTrigger($triggerName, $tableName);
|
||||||
$triggers = "CREATE TRIGGER \"$triggerName\" BEFORE INSERT OR UPDATE
|
$triggers = "CREATE TRIGGER \"$triggerName\" BEFORE INSERT OR UPDATE
|
||||||
ON \"$tableName\" FOR EACH ROW EXECUTE PROCEDURE
|
ON \"$tableName\" FOR EACH ROW EXECUTE PROCEDURE
|
||||||
tsvector_update_trigger(\"ts_$name\", 'pg_catalog.$language', $columns);";
|
tsvector_update_trigger(\"ts_$name\", 'pg_catalog.$language', $columns);";
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
@ -1433,7 +1447,7 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
|
|
||||||
//If a tablespace with this name exists, but the location has changed, then drop the current one
|
//If a tablespace with this name exists, but the location has changed, then drop the current one
|
||||||
//if($existing && $location!=$existing['spclocation'])
|
//if($existing && $location!=$existing['spclocation'])
|
||||||
// DB::query("DROP TABLESPACE $name;");
|
// DB::query("DROP TABLESPACE $name;");
|
||||||
|
|
||||||
//If this is a new tablespace, or we have dropped the current one:
|
//If this is a new tablespace, or we have dropped the current one:
|
||||||
if (!$existing || ($existing && $location != $existing['spclocation'])) {
|
if (!$existing || ($existing && $location != $existing['spclocation'])) {
|
||||||
@ -1471,12 +1485,10 @@ class PostgreSQLSchemaManager extends DBSchemaManager
|
|||||||
$this->query("CREATE TABLE \"$partition_name\" (CHECK (" . str_replace('NEW.', '', $partition_value) . ")) INHERITS (\"$tableName\")$tableSpace;");
|
$this->query("CREATE TABLE \"$partition_name\" (CHECK (" . str_replace('NEW.', '', $partition_value) . ")) INHERITS (\"$tableName\")$tableSpace;");
|
||||||
} else {
|
} else {
|
||||||
//Drop the constraint, we will recreate in in the next line
|
//Drop the constraint, we will recreate in in the next line
|
||||||
$existing_constraint = $this->preparedQuery(
|
$constraintName = "{$partition_name}_pkey";
|
||||||
"SELECT conname FROM pg_constraint WHERE conname = ?;",
|
$constraintExists = $this->constraintExists($constraintName, false);
|
||||||
array("{$partition_name}_pkey")
|
if ($constraintExists) {
|
||||||
);
|
$this->query("ALTER TABLE \"$partition_name\" DROP CONSTRAINT \"{$constraintName}\";");
|
||||||
if ($existing_constraint) {
|
|
||||||
$this->query("ALTER TABLE \"$partition_name\" DROP CONSTRAINT \"{$partition_name}_pkey\";");
|
|
||||||
}
|
}
|
||||||
$this->dropTrigger(strtolower('trigger_' . $tableName . '_insert'), $tableName);
|
$this->dropTrigger(strtolower('trigger_' . $tableName . '_insert'), $tableName);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user