Skip to content

Quote parts of the table name#12088

Merged
greg0ire merged 3 commits intodoctrine:3.5.xfrom
greg0ire:quote-parts
Aug 5, 2025
Merged

Quote parts of the table name#12088
greg0ire merged 3 commits intodoctrine:3.5.xfrom
greg0ire:quote-parts

Conversation

@greg0ire
Copy link
Copy Markdown
Member

@greg0ire greg0ire commented Jul 29, 2025

In #11811, I wrongly assumed that
$tableName would never contain a dot as I was not able to write a test
that caused that to happen.

The secret recipe appears to be to define a schema and to quote the
table name.

Fixes #12041

@greg0ire
Copy link
Copy Markdown
Member Author

Fails on Postgres with:

1) Doctrine\Tests\ORM\Functional\GH12041Test::testSchemaGenerationWithQuotedTableNameAndSchemaName
Doctrine\DBAL\Exception\TableNotFoundException: An exception occurred while executing a query: SQLSTATE[42P01]: Undefined table: 7 ERROR:  relation "myschema.file" does not exist
LINE 1: INSERT INTO "myschema.file" (id) VALUES (DEFAULT)
                    ^

/home/runner/work/orm/orm/vendor/doctrine/dbal/src/Driver/API/PostgreSQL/ExceptionConverter.php:72
/home/runner/work/orm/orm/vendor/doctrine/dbal/src/Connection.php:1456
/home/runner/work/orm/orm/vendor/doctrine/dbal/src/Connection.php:1392
/home/runner/work/orm/orm/vendor/doctrine/dbal/src/Statement.php:108
/home/runner/work/orm/orm/vendor/doctrine/dbal/src/Statement.php:133
/home/runner/work/orm/orm/src/Persisters/Entity/BasicEntityPersister.php:261
/home/runner/work/orm/orm/src/UnitOfWork.php:1057
/home/runner/work/orm/orm/src/UnitOfWork.php:402
/home/runner/work/orm/orm/src/EntityManager.php:268
/home/runner/work/orm/orm/tests/Tests/ORM/Functional/GH12041Test.php:31

https://github.com/doctrine/orm/actions/runs/16606300367/job/46978995125?pr=12088#step:7:162

Now let's attempt a fix.

@greg0ire
Copy link
Copy Markdown
Member Author

Huh so now the test is fixed, bug another test introduced in 54b3c05 is broken.

@greg0ire greg0ire force-pushed the quote-parts branch 2 times, most recently from 27eaf43 to d0d1a71 Compare July 29, 2025 20:55
@greg0ire
Copy link
Copy Markdown
Member Author

I'm temporarily reverting #11811 to see if that gives me a green build, I'm starting to have doubts about that.

@greg0ire
Copy link
Copy Markdown
Member Author

🤯 it doesn't… what the hell?

@greg0ire
Copy link
Copy Markdown
Member Author

Ah no, the revert works, but for some reason, the test I'm adding has a side effect 🤔

@greg0ire
Copy link
Copy Markdown
Member Author

Ah that's because the same schema name (myschema) is used in both tests.

@greg0ire
Copy link
Copy Markdown
Member Author

Instead of altering my new test to change the schema, I'm adding a new test case to the existing test, since it tests more things.

@@ -41,9 +44,17 @@ public function getTableName(ClassMetadata $class, AbstractPlatform $platform):
$tableName = $class->table['schema'] . '.' . $class->table['name'];
}
Copy link
Copy Markdown
Member Author

@greg0ire greg0ire Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realized this is what's causing the infamous dot. Instead of inlining quoteIdentifier(), let me try to modify this.

@greg0ire
Copy link
Copy Markdown
Member Author

Reproduced the failure by downgrading DBAL to v3.

@greg0ire greg0ire added the Bug label Jul 30, 2025
@greg0ire greg0ire marked this pull request as ready for review July 30, 2025 08:41
SenseException
SenseException previously approved these changes Jul 30, 2025
{
return isset($definition['quoted'])
? $platform->quoteSingleIdentifier($definition['sequenceName'])
? implode('.', array_map(
Copy link
Copy Markdown
Member

@morozov morozov Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have little understanding of what tradeoffs are acceptable here, so I cannot provide a reasonable feedback.

Every implode('.', $name) is a potential bug, which is why quoteIdentifier() was deprecated in the first place.

Assuming that it fixes the reported issue (which is covered by a new test), the patch looks good.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially wrote a separate test just for the reported issue, and the other part of the patch fixed it. This is here to fix another issue found when I decided to reuse the existing test, if I recall correctly. In any case, I think that on a patch branch, doing this is the right thing, but that on the next minor, we might want deprecate relying on that implode. This will require further analysis as to the ramification of the deprecation though.

Comment on lines 48 to 54
if ($this->_em->getConnection()->getDatabasePlatform()->supportsSchemas()) {
$fullTableName = sprintf('%s.%s', $expectedSchemaName, $expectedTableName);
$fullTableName = sprintf(
$isQuoted ? '"%s"."%s"' : '%s.%s',
$expectedSchemaName,
$expectedTableName,
);
} else {
Copy link
Copy Markdown
Member

@morozov morozov Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of test looks... not really useful. On the one hand, it's an integration test that that covers implementation details, which in turn depend on the environment, so it's hard to reason whether it provides the right feedback or not. On the other, there are two levels of code branching (if and ?), but a proper test shouldn't have any conditional logic.

Would it make sense to convert it to a unit test and make the expected values explicit?

Also, the dependency of the result on supportsSchemas() looks a bit inadequate. The result should depend only on the input (i.e. the class metadata).

Copy link
Copy Markdown
Member Author

@greg0ire greg0ire Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good points. To elaborate on your last point, the test is skipped unless the database supports schemas:

if (! $platform->supportsSchemas()) {
self::markTestSkipped('This test is only useful for databases that support schemas or can emulate them.');
}

So it makes no sense to have this if statement:

if ($this->_em->getConnection()->getDatabasePlatform()->supportsSchemas()) {
$fullTableName = sprintf('%s.%s', $expectedSchemaName, $expectedTableName);
} else {
$fullTableName = sprintf('%s__%s', $expectedSchemaName, $expectedTableName);
}
, since a41c6d3

This test definitely needs some love, and I will start by removing this if statement.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look into doing the improvements you mentioned, but for now, here is a PR that addresses the issue in my last message. #12094

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@morozov I did the conversion to unit tests, please take another look.

morozov
morozov previously approved these changes Jul 31, 2025
greg0ire added 3 commits July 31, 2025 21:49
In aa141bf, I wrongly assumed that
$tableName would never contain a dot as I was not able to write a test
that caused that to happen.

The secret recipe appears to be to define a schema and to quote the
table name.

To fix it for the table name, I am calling quoteSingleIdentifier()
before doing the concatenation between schema name and table name.

To fix it for the sequence name, which seems only useful when using DBAL
3 for some reason, I reuse some of the logic of the deprecated method.

Fixes doctrine#12041
That test was testing too many thing and not really making it clear what
the expected output was, given some output. Instead, let us create 2
tests, each pertaining to the class under test.
This comment is rendered useless by the phpdoc comment below it.
Instead, we can comment on what exactly "quoted" means.
@greg0ire greg0ire dismissed stale reviews from morozov and SenseException via 85d66de July 31, 2025 20:55
Copy link
Copy Markdown
Member

@morozov morozov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much better. Thanks!

@stlrnz
Copy link
Copy Markdown

stlrnz commented Aug 5, 2025

Hey, coming from #12041, I just wanted to say thank you for your hard work to fix the issue! I really appreciate this :)

@greg0ire greg0ire merged commit 64444dc into doctrine:3.5.x Aug 5, 2025
85 checks passed
@greg0ire greg0ire deleted the quote-parts branch August 5, 2025 06:05
@greg0ire greg0ire added this to the 3.5.1 milestone Aug 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Invalid quoting syntax for table names/schema in SQL Server

5 participants