Skip to content

Loading…

DBAL-406: PostgreSqlSchemaManager::tablesExist() misses schema-qualified table names if they exist in the first schema on the search path #1599

Open
doctrinebot opened this Issue · 0 comments

2 participants

@doctrinebot

Jira issue originally created by user rhunwicks:

Please see doctrine/migrations#99 for additional background.

To reproduce:

CREATE SCHEMA test_schema;
CREATE TABLE test*schema.test_table (test*column TEXT);

Then in Doctrine:

$connection->executeUpdate('SET search*path=test*schema;');
$result = $connection->getSchemaManager()->tablesExist(array('test*schema.test*table'));

$result is false when it should be true.

The error occurs because PostgreSqlSchemaManager returns the bare table name from getPortableTablesList() if the schema is the first one in the search path.

The full explanation is...

AbstractSchemaManager::tablesExist() calls $this->getPortableTablesList() before checking if the tables exist.

PostgreSqlSchemaManager overrides this in _getPortableTableDefinition() by comparing the schema for the table with the search path for the connection. If the table schema is the first one in the search path, then it returns the bare table name, if it isn't then it returns the schema-qualified table name (i.e. schema.table).

tablesExist() does an array_intersect to check that all the tables in the search array exist in the database.

If one of the tables in the search array was schema-qualified but also in the first schema on the search path, then you end up checking:

array*intersect(array('test_schema.test_table'), array('test*table'))

which fails.

One way to fix it would be to override tablesExist() in PostgreSqlSchemaManager so that it passes the search array through getPortableTableDefinition() before doing the array_intersect:

    /****
     * Return true if all the given tables exist.
     *
     * @param array $tableNames
     * @return bool
     */
    public function tablesExist($tableNames)
    {
        foreach ($tableNames as $key => $tableName) {
            if (strpos($tableName, '.') !== false) {
                $tableName = explode('.', $tableName, 2);
                $tableNames[$key] = $this->*getPortableTableDefinition(array('schema_name'=>$tableName[0], 'table*name'=>$tableName[1]));
            }
        }
        return parent::tablesExist($tableNames);
    }

I'm happy to provide a PR on GitHub if you want.

@doctrinebot doctrinebot added the Bug label
@beberlei beberlei was assigned by doctrinebot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.