All Downloads are FREE. Search and download functionalities are using the official Maven repository.

liquibase.nosql.executor.NoSqlExecutor Maven / Gradle / Ivy

There is a newer version: 4.30.0
Show newest version
package liquibase.nosql.executor;

/*-
 * #%L
 * Liquibase CosmosDB Extension
 * %%
 * Copyright (C) 2020 Mastercard
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import liquibase.Scope;
import liquibase.changelog.ChangeLogHistoryServiceFactory;
import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.executor.AbstractExecutor;
import liquibase.ext.cosmosdb.database.CosmosLiquibaseDatabase;
import liquibase.logging.Logger;
import liquibase.nosql.changelog.AbstractNoSqlHistoryService;
import liquibase.nosql.database.AbstractNoSqlConnection;
import liquibase.nosql.database.AbstractNoSqlDatabase;
import liquibase.nosql.statement.NoSqlExecuteStatement;
import liquibase.nosql.statement.NoSqlQueryForListStatement;
import liquibase.nosql.statement.NoSqlQueryForLongStatement;
import liquibase.nosql.statement.NoSqlQueryForObjectStatement;
import liquibase.nosql.statement.NoSqlUpdateStatement;
import liquibase.servicelocator.LiquibaseService;
import liquibase.sql.visitor.SqlVisitor;
import liquibase.statement.SqlStatement;
import liquibase.statement.core.UpdateStatement;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;

import static java.util.Collections.emptyList;
import static java.util.Optional.ofNullable;

@LiquibaseService
@NoArgsConstructor
public class NoSqlExecutor extends AbstractExecutor {

    public static final String EXECUTOR_NAME = "jdbc";
    private final Logger log = Scope.getCurrentScope().getLog(getClass());

    @Override
    public void setDatabase(final Database database) {
        super.setDatabase(database);
    }

    @SuppressWarnings("unchecked")
    private  T getDatabase() {
        return (T) database;
    }

    @Override
    public String getName() {
        return EXECUTOR_NAME;
    }

    @Override
    public boolean supports(Database database) {
        return database instanceof CosmosLiquibaseDatabase;
    }

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

    @SuppressWarnings("unchecked")
    protected  C getConnection() {
        return (C) ofNullable(database)
                .map(Database::getConnection).orElse(null);
    }

    @Override
    public  T queryForObject(final SqlStatement sql, final Class requiredType) throws DatabaseException {
        return queryForObject(sql, requiredType, emptyList());
    }

    @Override
    public  T queryForObject(final SqlStatement sql, final Class requiredType, final List sqlVisitors) throws DatabaseException {
        if (sql instanceof NoSqlQueryForObjectStatement) {
            try {
                return ((NoSqlQueryForObjectStatement) sql)
                        .queryForObject(getDatabase(), requiredType);
            } catch (final Exception e) {
                throw new DatabaseException("Could not query for object", e);
            }
        }
        throw new IllegalArgumentException();
    }

    @Override
    public long queryForLong(final SqlStatement sql) throws DatabaseException {
        return queryForLong(sql, emptyList());
    }

    @Override
    public long queryForLong(final SqlStatement sql, final List sqlVisitors) throws DatabaseException {
        if (sql instanceof NoSqlQueryForLongStatement) {
            try {
                return ((NoSqlQueryForLongStatement) sql).queryForLong(getDatabase());
            } catch (final Exception e) {
                throw new DatabaseException("Could not query for long", e);
            }
        }
        throw new IllegalArgumentException();
    }

    @Override
    public int queryForInt(final SqlStatement sql) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int queryForInt(final SqlStatement sql, final List sqlVisitors) {
        throw new UnsupportedOperationException();
    }

    @Override
    public List queryForList(final SqlStatement sql, final Class elementType) throws DatabaseException {
        return queryForList(sql, elementType, emptyList());
    }

    @Override
    @SuppressWarnings("unchecked")
    public List queryForList(final SqlStatement sql, final Class elementType, final List sqlVisitors) throws DatabaseException {
        if (sql instanceof NoSqlQueryForListStatement) {
            try {
                return ((NoSqlQueryForListStatement) sql).queryForList(getDatabase());
            } catch (final Exception e) {
                throw new DatabaseException("Could not query for list", e);
            }
        }
        throw new IllegalArgumentException();
    }

    @Override
    public List> queryForList(final SqlStatement sql) {
        return queryForList(sql, emptyList());
    }

    @Override
    public List> queryForList(final SqlStatement sql, final List sqlVisitors) {
        throw new UnsupportedOperationException();
    }

    /**
     * TODO: Raise with Liquibase why is this used instead of
     * {@link AbstractNoSqlHistoryService#clearAllCheckSums()}
     * in {@link liquibase.Liquibase#clearCheckSums()}
     * @param updateStatement the {@link UpdateStatement} statement with MD5SUM=null
     * @throws DatabaseException in case of a failure
     */
    public void execute(final UpdateStatement updateStatement) throws DatabaseException {
        if(updateStatement.getNewColumnValues().containsKey("MD5SUM")
                && updateStatement.getNewColumnValues().get("MD5SUM") == null) {
            try {
                ChangeLogHistoryServiceFactory.getInstance()
                        .getChangeLogService(getDatabase()).clearAllCheckSums();
            } catch (final Exception e) {
                throw new DatabaseException("Could not execute", e);
            }
        } else {
            throw new IllegalArgumentException();
        }
    }

    @Override
    public void execute(final SqlStatement sql) throws DatabaseException {
        this.execute(sql, emptyList());
    }

    @Override
    public void execute(final SqlStatement sql, final List sqlVisitors) throws DatabaseException {
        if (sql instanceof NoSqlExecuteStatement) {
            try {
                ((NoSqlExecuteStatement) sql).execute(getDatabase());
            } catch (final Exception e) {
                throw new DatabaseException("Could not execute", e);
            }
        } else if (sql instanceof UpdateStatement) {
            execute((UpdateStatement) sql);
        } else {
            throw new IllegalArgumentException();
        }
    }

    @Override
    public int update(final SqlStatement sql) throws DatabaseException {
        return update(sql, emptyList());
    }

    @Override
    public int update(final SqlStatement sql, final List sqlVisitors) throws DatabaseException {
        if (sql instanceof NoSqlUpdateStatement) {
            try {
                return ((NoSqlUpdateStatement) sql).update(getDatabase());
            } catch (final Exception e) {
                throw new DatabaseException("Could not execute", e);
            }
        } else {
            throw new IllegalArgumentException();
        }
    }

    @Override
    public void comment(final String message) {
        log.info(message);
    }

    @Override
    public boolean updatesDatabase() {
        return true;
    }
}