Skip to content

[BUG]: liquibase tag fails due to an invalid query #236

Description

@roman-galyaminskiy

Describe the bug
Creating a Liquibase tag due to an invalid query.

To Reproduce

$ liquibase --url=jdbc:ydb:grpc://localhost:2136/local tag test
####################################################
##   _     _             _ _                      ##
##  | |   (_)           (_) |                     ##
##  | |    _  __ _ _   _ _| |__   __ _ ___  ___   ##
##  | |   | |/ _` | | | | | '_ \ / _` / __|/ _ \  ##
##  | |___| | (_| | |_| | | |_) | (_| \__ \  __/  ##
##  \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___|  ##
##              | |                               ##
##              |_|                               ##
##                                                ## 
##  Get documentation at docs.liquibase.com       ##
##  Get certified courses at learn.liquibase.com  ## 
##                                                ##
####################################################
Starting Liquibase at 18:33:59 using Java 21.0.2 (version 5.0.2 #10172 built at 2026-03-04 00:27+0000)
Liquibase Version: 5.0.2

ERROR: Exception Details
ERROR: Exception Primary Class:  UnexpectedResultException
ERROR: Exception Primary Reason:  Unexpected status, code: GENERIC_ERROR, issues: [95:1 - 95:1: Name not found: table1 (S_ERROR)]
ERROR: Exception Primary Source:  YDB 26.1.1.20

Unexpected error running Liquibase: Cannot execute 'STREAM_QUERY >>
UPDATE DATABASECHANGELOG SET TAG = 'test' WHERE DATEEXECUTED = (SELECT MAX(DATEEXECUTED) FROM DATABASECHANGELOG)' with Status{code = GENERIC_ERROR(code=400080), issues = [95:1 - 95:1: Name not found: table1 (S_ERROR)]} [Failed SQL: (400080) UPDATE DATABASECHANGELOG SET TAG = 'test' WHERE DATEEXECUTED = (SELECT MAX(DATEEXECUTED) FROM DATABASECHANGELOG)]
  - Caused by: Unexpected status, code: GENERIC_ERROR, issues: [95:1 - 95:1: Name not found: table1 (S_ERROR)]

Proposed fix

Override TagDatabaseGenerator with a custom implementation:

import liquibase.structure.core.Column;
import tech.ydb.liquibase.database.YdbDatabase;

public class TagDatabaseGeneratorYdb extends TagDatabaseGenerator {
    @Override
    public boolean supports(TagDatabaseStatement statement, Database database) {
        return database instanceof YdbDatabase;
    }

    @Override
    public int getPriority() {
        return PRIORITY_DATABASE;
    }

    @Override
    public Sql[] generateSql(TagDatabaseStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) {
        ObjectQuotingStrategy currentStrategy = database.getObjectQuotingStrategy();
        database.setObjectQuotingStrategy(ObjectQuotingStrategy.LEGACY);
        try {
            String tableNameEscaped = database.escapeTableName(
                    database.getLiquibaseCatalogName(),
                    database.getLiquibaseSchemaName(),
                    database.getDatabaseChangeLogTableName());
            String idColumnEscaped = database.escapeObjectName("ID", Column.class);
            String authorColumnEscaped = database.escapeObjectName("AUTHOR", Column.class);
            String filenameColumnEscaped = database.escapeObjectName("FILENAME", Column.class);
            String tagColumnEscaped = database.escapeObjectName("TAG", Column.class);
            String orderColumnEscaped = database.escapeObjectName("ORDEREXECUTED", Column.class);
            String dateColumnEscaped = database.escapeObjectName("DATEEXECUTED", Column.class);
            String tagEscaped = DataTypeFactory.getInstance()
                    .fromObject(statement.getTag(), database)
                    .objectToSql(statement.getTag(), database);

            return new Sql[]{
                    new UnparsedSql(
                            "UPDATE " + tableNameEscaped +
                                    " ON SELECT * FROM (" +
                                    "SELECT " + idColumnEscaped + ", " + authorColumnEscaped + ", " +
                                    filenameColumnEscaped + ", Utf8(" + tagEscaped + ") AS " + tagColumnEscaped +
                                    " FROM " + tableNameEscaped +
                                    " ORDER BY " + dateColumnEscaped + " DESC, " + orderColumnEscaped + " DESC" +
                                    " LIMIT 1" +
                                    ")")
            };
        } finally {
            database.setObjectQuotingStrategy(currentStrategy);
        }
    }
}

Fix ready (above). OK to open a PR?

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions