From 58a152db4467f215c09b5945fea317c0554cec0a Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 14 May 2024 11:17:46 +0200 Subject: [PATCH] [jOOQ/jOOQ#16675] SQLite "Cannot parse or interpret sql for table" error with both unique columns and foreign key constraints --- .../src/main/java/org/jooq/impl/MetaImpl.java | 77 ++++++++++++------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java b/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java index 08cea683a6..802f76ca35 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java @@ -607,6 +607,7 @@ final class MetaImpl extends AbstractMeta { private final void initUksSQLite(String catalog, String schema) { ukCache = new LinkedHashMap<>(); + Map tables = dsl().resultQuery( """ select m.tbl_name, m.sql @@ -620,38 +621,60 @@ final class MetaImpl extends AbstractMeta { order by m.tbl_name """ ) - .fetchMap(field("tbl_name", VARCHAR), field("sql", VARCHAR)) - .forEach((table, sql) -> { - try { - Field fCatalogName = field("catalog_name", VARCHAR); - Field fSchemaName = field("schema_name", VARCHAR); - Field fTableName = field("table_name", VARCHAR); - Field fConstraintName = field("constraint_name", VARCHAR); - Field fColumnName = field("column_name", VARCHAR); - Field fSequenceNo = field("sequence_no", INTEGER); + .fetchMap(field("tbl_name", VARCHAR), field("sql", VARCHAR)); - Field[] fields = { - fCatalogName, fSchemaName, fTableName, fConstraintName, fColumnName, fSequenceNo - }; + // [#16675] Attempt to interpret the entire schema DDL in one go, to resolve foreign keys correctly + StringBuilder sb = new StringBuilder(); + for (String sql : tables.values()) + sb.append(sql).append(';'); - for (Table t : dsl().meta(Source.of(sql)).getTables(table)) { - Result result = dsl().newResult(fields); + Meta m = null; - int i = 0; - for (UniqueKey uk : t.getUniqueKeys()) - for (Field ukField : uk.getFields()) - result.add(dsl() - .newRecord(fCatalogName, fSchemaName, fTableName, fConstraintName, fColumnName, fSequenceNo) - .values(catalog, schema, table, uk.getName(), ukField.getName(), i++) - ); + try { + m = dsl() + .configuration() + .deriveSettings(s -> s.withInterpreterDelayForeignKeyDeclarations(true)) + .dsl() + .meta(sb.toString()); + } + catch (ParserException | DataDefinitionException e) { + log.info("Cannot parse or interpret sql: " + sb.toString(), e); + } - ukCache.put(name(catalog, schema, table), result); - } + Meta meta = m; + + tables.forEach((table, sql) -> { + try { + Field fCatalogName = field("catalog_name", VARCHAR); + Field fSchemaName = field("schema_name", VARCHAR); + Field fTableName = field("table_name", VARCHAR); + Field fConstraintName = field("constraint_name", VARCHAR); + Field fColumnName = field("column_name", VARCHAR); + Field fSequenceNo = field("sequence_no", INTEGER); + + Field[] fields = { + fCatalogName, fSchemaName, fTableName, fConstraintName, fColumnName, fSequenceNo + }; + + // [#16675] If the previous schema wide DDL interpretation failed, fall back to table-by table interpretation + for (Table t : (meta != null ? meta : dsl().meta(sql)).getTables(table)) { + Result result = dsl().newResult(fields); + + int i = 0; + for (UniqueKey uk : t.getUniqueKeys()) + for (Field ukField : uk.getFields()) + result.add(dsl() + .newRecord(fCatalogName, fSchemaName, fTableName, fConstraintName, fColumnName, fSequenceNo) + .values(catalog, schema, table, uk.getName(), ukField.getName(), i++) + ); + + ukCache.put(name(catalog, schema, table), result); } - catch (ParserException | DataDefinitionException e) { - log.info("Cannot parse or interpret sql for table " + table + ": " + sql, e); - } - }); + } + catch (ParserException | DataDefinitionException e) { + log.info("Cannot parse or interpret sql for table " + table + ": " + sql, e); + } + }); }