That’s a valid point, I updated my pull request regards oracle fixes with a more simpler quoting approach for QUOTE_ALL_OBJECTs. The reasoning for smart quoting of the objects is no longer relevant.
Regards not simply quoting everything, this would break backwards compatibility for I imagine most users of Liquibase.
I feel that the handling of case-sensitivity and special characters is generally incorrect in Liquibase. Here’s a sample implementation from Liquibase’s PostgresDatabase:
public String escapeDatabaseObject(String objectName) {
if (objectName == null) {
return null;
}
if (objectName.contains("-") || hasMixedCase(objectName) || startsWithNumeric(objectName) || isReservedWord(objectName)) {
return "\"" + objectName + "\"";
} else {
return super.escapeDatabaseObject(objectName);
}
}
I strongly recommend that you do not implement such “clever” rules like “hasMixedCase()”, etc, as these will not include all the corner cases. From my experience, case-sensitivity is not something that you can “discover” with such rules. Hence it is best to treat ALL literals as case-sensitive. Do note that, you should also escape the literals that you quote.
I think it’s worth investing a little time to handle these things correctly. I’m the developer of jOOQ and I have gathered experience with 14 database dialects. My experience lead to the following rules:
It is best to always escape ALL literals (except for the SQLite database, which is a bit buggy)
MySQL supports different ways of escaping. Using backticks ( ` ) works best, though.
What if the actual table name “test table” was case-sensitive as in:
CREATE TABLE "test table" (
"a" INT,
"B" INT
)
Funny, that QUOTE_ALL_OBJECTS would only quote some objects, though
I don’t understand the aversion against quoted literals. Some people may find them a bit unreadable, so it might make sense to introduce a QUOTE_NO_OBJECTS or QUOTE_SOME_OBJECTS strategy for them. But if you quote ALL objects by default, you cannot run into these kinds of bugs…
I think it’s better to have two different modes, one is implemented for now and one you suggested.
The reason for current mode: for example, i work with oracle DB and postgres DB. And i write SQL queries by hands, aligning table names like i wish - MyCoolNameA A inner join MyCoolNameB B etc.
But in PostgreSQL it will be converted internally by DB engine to mycoolname, and in Oracle to MYCOOLNAME.
But i want to have one changeset for both DBs and I can write it or in uppercase, or in lowercase
The reason for mode you suggested: ORM frameworks of different types who automatically quotes table and column names when generating SQLs, so if I write in changeset MYCOOLNAME or mycoolname - both won’t work on the same time on Oracle and Postgres.
Another point in favor quoting/escaping is that some words are reserved words. I currently have a changeset written like this:
because it turns out that MySQL sees the naked word ORDER in the generated SQL and panics.
Manually putting in backticks is ugly, and it will break someday when Liquibase starts doing the right thing, so I would very much rather not have to do it in the first place.