Open Alxspb opened 1 year ago
Thanks, the issue makes sense. We auto-quote index names that need to be quoted like index_-id
in the create etc, but must not have that same logic for the query we come up with in indexExists. We just switch it to the database-stored capitalization and do an equality check in there.
You can work around the issue for now by switching indexExists to a sqlCheck where you write a custom query against the metadata and correctly case the index name.
Otherwise, if someone is looking to provide a fix, the problem code is likely in how IndexExistsPrecondition just does a correctObjectName()
on the index instead of checking the database.mustQuoteObjectName()
function
Hello, I will try to look at it. Hi @nvoxland I'm new to liquibase source code and can't seemed to find maven command to execute liquibase using project source code, is there any of this command?
This patch actually works in our fork:
Index: liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java
--- a/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java (revision 9553d6a9b01a79118e66ec4cb0c7aa8eedeaaaf7)
+++ b/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java (revision 569fac2686463ccb0eac9337764406eed95a3e6f)
@@ -277,6 +277,10 @@
@Override
public String correctObjectName(final String objectName, final Class<? extends DatabaseObject> objectType) {
+ if (objectType == Index.class && mustQuoteObjectName(objectName, objectType)) {
+ return objectName;
+ }
+
if (quotingStrategy == ObjectQuotingStrategy.QUOTE_ALL_OBJECTS || unquotedObjectsAreUppercased == null
|| objectName == null || (objectName.startsWith(quotingStartCharacter) && objectName.endsWith(
quotingEndCharacter))) {
@@ -998,7 +1002,8 @@
}
protected boolean mustQuoteObjectName(String objectName, Class<? extends DatabaseObject> objectType) {
- return objectName.contains("-") || startsWithNumeric(objectName) || isReservedWord(objectName) || objectName.matches(".*\\W.*");
+ return objectName != null &&
+ (objectName.contains("-") || startsWithNumeric(objectName) || isReservedWord(objectName) || objectName.matches(".*\\W.*"));
}
public String quoteObject(final String objectName, final Class<? extends DatabaseObject> objectType) {
I took a look at this issue and after some investigation it seems the existence of the index is checked using a query on ALL_IND_COLUMNS
which stores index names in a VARCHAR2
field, unquoted and case-sensitive. When checking whether the index exists in JdbcDatabaseSnapshot
the index name has been converted to uppercase (though indeed not quoted), so the index is not found.
I tried running the test with index name INDEX_-ID
(so uppercase) which works fine, as well as using index_id
(lowercase, but without the -
to prevent quoting) which also works.
My conclusion is that the combination of lowercase with quoting causes the issue.
The solution is unclear to me though. When passing the index name down the call stack to be used in the SQL query on ALL_IND_COLUMNS
there are various places where the index name is converted to uppercase using a call to database.correctObjectName
.
I don’t see an easy way to use the original index name in the query, plus am not sure whether changing this will work on all databases.
Another option would be to change the way we check for index existence to use the actual object rather than query a table, in which case we can presumably use the escaped and quoted index name. A comment in the relevant code suggests querying the ALL_IND_COLUMNS
view was implemented to work around a bug in Oracle’s getIIndexInfo
code so that also does not seem like a good option.
My recommendation would be to document that the combination of a lowercase index name with the need to quote the name don’t work with the IndexExistsPrecondition
.
Search first
Description
For oracledb index name in indexExist request is always in uppercase, but create index name is quoted. This changeset generates error after second run:
Steps To Reproduce
1) Create oracle db (I have used https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance) 2) Create changelog_test.xml with content:
3) Run in latest liquibase container twice:
Actual Behavior
Got output:
Expected/Desired Behavior
Every time
changelog
is processed,indexExist
precondition checks that index exists and if it doesn't it should create itLiquibase Version
4.19.0
Database Vendor & Version
Oracle 19.3.0 EE
Liquibase Integration
No response
Liquibase Extensions
No response
OS and/or Infrastructure Type/Provider
Ubuntu 22.04 + liquibase docker image
Additional Context
No response
Are you willing to submit a PR?