ORA-01450 error for index IDX_CLIENT_ATT_BY_NAME_VALUE in oracle when MAX_STRING_SIZE is EXTENDED

Closes #27967

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2024-03-20 22:15:46 +01:00 committed by Pedro Igor
parent 8cbd39083e
commit 220564c7ba
3 changed files with 27 additions and 10 deletions

View file

@ -865,12 +865,13 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, ClientSc
Predicate attrNamePredicate = builder.equal(attributeJoin.get("name"), key); Predicate attrNamePredicate = builder.equal(attributeJoin.get("name"), key);
if (dbProductName.equals("Oracle")) { if (dbProductName.equals("Oracle")) {
// Use the dbms_lob.substr index and the full comparison in oracle // SELECT * FROM client_attributes WHERE ... DBMS_LOB.COMPARE(value, '0') = 0 ...;
Predicate attrValuePredicate1 = builder.equal( // Oracle is not able to compare a CLOB with a VARCHAR unless it being converted with TO_CHAR
builder.function("dbms_lob.substr", Integer.class, attributeJoin.get("value"), builder.literal(255), builder.literal(1)), // But for this all values in the table need to be smaller than 4K, otherwise the cast will fail with
builder.function("substr", Integer.class, builder.literal(value), builder.literal(1), builder.literal(255))); // "ORA-22835: Buffer too small for CLOB to CHAR" (even if it is in another row).
Predicate attrValuePredicate2 = builder.equal(builder.function("dbms_lob.compare", Integer.class, attributeJoin.get("value"), builder.literal(value)), 0); // This leaves DBMS_LOB.COMPARE as the option to compare the CLOB with the value.
predicates.add(builder.and(attrNamePredicate, attrValuePredicate1, attrValuePredicate2)); Predicate attrValuePredicate = builder.equal(builder.function("DBMS_LOB.COMPARE", Integer.class, attributeJoin.get("value"), builder.literal(value)), 0);
predicates.add(builder.and(attrNamePredicate, attrValuePredicate));
} else if (dbProductName.equals("PostgreSQL")) { } else if (dbProductName.equals("PostgreSQL")) {
// use the substr comparison and the full comparison in postgresql // use the substr comparison and the full comparison in postgresql
Predicate attrValuePredicate1 = builder.equal( Predicate attrValuePredicate1 = builder.equal(

View file

@ -66,12 +66,12 @@
</changeSet> </changeSet>
<changeSet author="keycloak" id="24.0.0-26618-reindex"> <changeSet author="keycloak" id="24.0.0-26618-reindex">
<validCheckSum>9:bd2bd0fc7768cf0845ac96a8786fa735</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN"> <preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<or> <or>
<dbms type="mysql"/> <dbms type="mysql"/>
<dbms type="mariadb"/> <dbms type="mariadb"/>
<dbms type="postgresql"/> <dbms type="postgresql"/>
<dbms type="oracle"/>
</or> </or>
</preConditions> </preConditions>
<createIndex tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE"> <createIndex tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE">
@ -81,9 +81,6 @@
<modifySql dbms="postgresql"> <modifySql dbms="postgresql">
<replace replace="VALUE(255)" with="substr(VALUE,1,255)" /> <replace replace="VALUE(255)" with="substr(VALUE,1,255)" />
</modifySql> </modifySql>
<modifySql dbms="oracle">
<replace replace="VALUE(255)" with="dbms_lob.substr(VALUE,255,1)" />
</modifySql>
</changeSet> </changeSet>
</databaseChangeLog> </databaseChangeLog>

View file

@ -21,4 +21,23 @@
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.JpaUpdate24_0_2_FederatedTermsAndConditionsRequiredAction"/> <customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.JpaUpdate24_0_2_FederatedTermsAndConditionsRequiredAction"/>
</changeSet> </changeSet>
<changeSet author="keycloak" id="24.0.2-27967-drop-index-if-present">
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<and>
<dbms type="oracle"/>
<indexExists tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE" />
</and>
</preConditions>
<dropIndex tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE"/>
</changeSet>
<changeSet author="keycloak" id="24.0.2-27967-reindex">
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="oracle"/>
</preConditions>
<createIndex tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE">
<column name="NAME" type="VARCHAR(255)"/>
</createIndex>
</changeSet>
</databaseChangeLog> </databaseChangeLog>