OtterMind/Chat2DB · error · IllegalArgumentException

Unable to rewrite source table reference in DDL batch: {sql}

Error message

Unable to rewrite source table reference in DDL batch: {sql}

What it means

Thrown by SqlServerDBManager.replaceObjectAfterKeyword when the regex built from the keyword pattern plus the source-table reference alternatives finds no in-code match anywhere in the given DDL batch. It walks all matches and returns on the first that sits in executable code (isSqlCodeAt); if none qualifies, it cannot perform the rewrite and fails.

Source

Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-sqlserver/src/main/java/ai/chat2db/plugin/sqlserver/SqlServerDBManager.java:379

    private static boolean isExtendedPropertyBatch(String sql) {
        return Pattern.compile("(?is)^\\s*exec\\s+sp_addextendedproperty\\b").matcher(sql).find();
    }

    private static String replaceObjectAfterKeyword(String sql, String keywordPattern, List<String> sourceReferences,
            String targetReference) {
        String alternatives = sourceReferences.stream()
                .map(Pattern::quote)
                .collect(Collectors.joining("|"));
        Pattern pattern = Pattern.compile("(?i)(\\b" + keywordPattern + ")(?:(?:" + alternatives + "))");
        Matcher matcher = pattern.matcher(sql);
        while (matcher.find()) {
            if (isSqlCodeAt(sql, matcher.start())) {
                return sql.substring(0, matcher.start()) + matcher.group(1) + targetReference
                        + sql.substring(matcher.end());
            }
        }
        throw new IllegalArgumentException("Unable to rewrite source table reference in DDL batch: " + sql);
    }

    private static String rewriteSelfReference(String sql, List<String> sourceReferences, String tableName,
            String targetReference) {
        Set<String> references = new LinkedHashSet<>(sourceReferences);
        references.add(quoteIdentifier(tableName));
        references.add(tableName);
        String alternatives = references.stream()
                .filter(StringUtils::isNotBlank)
                .map(Pattern::quote)
                .collect(Collectors.joining("|"));
        Pattern pattern = Pattern.compile("(?i)(\\breferences\\s+)(?:(?:" + alternatives + "))(?=\\s*\\()");
        Matcher matcher = pattern.matcher(sql);
        StringBuffer rewritten = new StringBuffer();
        while (matcher.find()) {
            if (isSqlCodeAt(sql, matcher.start())) {
                matcher.appendReplacement(rewritten, Matcher.quoteReplacement(matcher.group(1) + targetReference));
            }

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Verify the sourceReferences list passed in covers every form the DDL uses (e.g. [db].[schema].[table], [schema].[table], [table]).
  2. Check that the relevant token is not solely inside a comment or quoted identifier (isSqlCodeAt excludes those).
  3. If the batch genuinely does not reference the source table, exclude it from the rewrite set rather than forcing a match.

Example fix

// before: sourceReferences only had "[dbo].[t]" but DDL uses "[t]"
replaceObjectAfterKeyword(batch, "ON\\s+", List.of("[dbo].[t]"), target);
// -> Unable to rewrite source table reference in DDL batch

// after: include all qualification forms
replaceObjectAfterKeyword(batch, "ON\\s+",
    tableReferences(db, schema, tableName), target);
Defensive patterns

Strategy: validation

Validate before calling

// Build the full set of reference forms the DDL might use
List<String> refs = tableReferences(databaseName, schemaName, tableName);
// Confirm at least one appears in code (not comment/quoted) before rewriting
boolean any = batches.stream().anyMatch(b -> refs.stream().anyMatch(r -> inCodeContains(b, r)));
if (!any) throw new IllegalStateException("No rewritable source reference");

Prevention

When it happens

Trigger: During table-copy DDL rewriting, a batch identified as needing retargeting (e.g. an 'ON <filegroup>' clause or CREATE TABLE) does not contain the expected source table reference token, or the only occurrences are inside comments/quoted identifiers and thus excluded by isSqlCodeAt.

Common situations: The source table reference uses an unexpected qualification (3-part vs 2-part name) not present in sourceReferences; the reference is entirely inside a comment or bracketed identifier; the batch was misclassified as needing rewrite.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/db6ffe5f251d7ef7. Report an issue: GitHub.