Skip to content

Commit

Permalink
Fix database command warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
Ioannis committed Sep 1, 2025
1 parent 25b3e17 commit fe7fd36
Showing 1 changed file with 79 additions and 8 deletions.
87 changes: 79 additions & 8 deletions app/src/Lib/Util/SchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -327,14 +327,16 @@ protected function processSchema(
}

// This is the SQL that represents the desired state of the database
// XXX This never used
$toSql = $schema->toSql($this->conn->getDatabasePlatform());

// SchemaManager provides info about the database
$sm = $this->conn->createSchemaManager();

// The is the current database representation
$curSchema = $sm->createSchema();

// This is the current database representation
$curSchema = $sm->introspectSchema();

// XXX This is never used
$fromSql = $curSchema->toSql($this->conn->getDatabasePlatform());

try {
Expand All @@ -359,12 +361,43 @@ protected function processSchema(
// Remove the DROP SEQUENCE statements in $fromSql because they're Postgres automagic
// being misinterpreted. (Note toSaveSql might mask this now.)
// XXX Maybe debug and file a PR to not emit DROP SEQUENCE on PG for autoincrementesque fields?
if($this->io) $io->out("Skipping sequence drop");
} else {
if($this->io) $this->io->out("Skipping sequence drop");
continue;
}

// PostgreSQL: translate DROP INDEX for names that are actually unique constraints
if($this->conn->driver == 'Cake\Database\Driver\Postgres'
&& preg_match('/^DROP INDEX\s+"?([a-zA-Z0-9_\.]+)"?/i', $sql, $m)) {
$idxOrConstraint = $m[1];

// Resolve if this name is a constraint and on which table
$qualifiedTable = $this->resolvePgConstraintTable($idxOrConstraint);

if($qualifiedTable !== null) {
// We will skip this index if it's bound to a constraint
if($this->io) $this->io->out('Skipping index drop since it is bound to a constraint');
continue;
}
}

// PostgreSQL: make index renames idempotent and tolerant using IF EXISTS
if($this->conn->driver == 'Cake\Database\Driver\Postgres'
&& preg_match('/^ALTER INDEX\s+([^\s]+)\s+RENAME\s+TO\s+([^\s]+)$/i', trim($sql), $m)) {
$oldName = $m[1];
$newName = $m[2];

// Use IF EXISTS to avoid error if the old index name doesn't exist in this environment
$translated = 'ALTER INDEX IF EXISTS ' . $oldName . ' RENAME TO ' . $newName;
if($this->io) $this->io->out($translated . ' -- added IF EXISTS for PostgreSQL resilience');
if(!$diffOnly) {
$stmt = $this->conn->executeQuery($sql);
// $stmt just returns the query string so we don't bother examining it
$this->conn->executeQuery($translated);
}
continue;
}

if(!$diffOnly) {
$stmt = $this->conn->executeQuery($sql);
// $stmt just returns the query string so we don't bother examining it
}
}

Expand All @@ -380,4 +413,42 @@ protected function processSchema(
// but so far we don't have an example indicating it's needed.
}

}
/**
* Resolve a PostgreSQL constraint's owning table (schema-qualified) by constraint name.
* Returns null if the given name is not found as a constraint.
*
* @param string $constraintName
* @return ?string Schema-qualified table name or null if constraint not found
* @since COmanage Registry v5.2.0
*/

protected function resolvePgConstraintTable(string $constraintName): ?string {
if($this->conn->driver !== 'Cake\\Database\\Driver\\Postgres') {
return null;
}

// Query pg catalogs to find the table for this constraint name
// We return schema-qualified name: schema.table
$sql = <<<CATALOG
SELECT n.nspname AS schema, c.relname AS table
FROM pg_constraint co
JOIN pg_class c ON c.oid = co.conrelid
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE co.conname = :name
LIMIT 1
CATALOG;

try {
$stmt = $this->conn->executeQuery($sql, ['name' => $constraintName]);
$row = $stmt->fetchAssociative();
if(!$row || empty($row['schema']) || empty($row['table'])) {
return null;
}
// Quote/qualify as schema.table (matching how other statements look)
return $row['schema'] . '.' . $row['table'];
} catch(\Throwable $e) {
// On any error, fail open by returning null so caller uses original SQL
return null;
}
}
}

0 comments on commit fe7fd36

Please sign in to comment.