Manoj Monga
Manoj Monga

Reputation: 3083

Unable to execute commands against an offline database when I am trying to connect Oracle offline

I am using the below code:

private static String file="create-table.yml";
public static void main(String[] args) throws Exception {
    Database database =createOfflineDatabase("offline:oracle");
    Liquibase liquibase = new Liquibase(file, new ClassLoaderResourceAccessor(), database);
    liquibase.update("test");
    liquibase.dropAll();
}

private static Database createOfflineDatabase(String url) throws Exception {
    DatabaseConnection databaseConnection = new OfflineConnection(url, new ClassLoaderResourceAccessor());
    return DatabaseFactory.getInstance().openDatabase(url, null, null, null, null);
}

Getting this exception :

Exception in thread "main" liquibase.exception.MigrationFailedException: Migration failed for change set create-table.yml::create-table.yml::vishwakarma:
 Reason: liquibase.exception.DatabaseException: Cannot execute commands against an offline database
at liquibase.changelog.ChangeSet.execute(ChangeSet.java:619)
at liquibase.changelog.visitor.UpdateVisitor.visit(UpdateVisitor.java:51)
at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:79)
at liquibase.Liquibase.update(Liquibase.java:214)
at liquibase.Liquibase.update(Liquibase.java:192)
at liquibase.Liquibase.update(Liquibase.java:188)
at liquibase.Liquibase.update(Liquibase.java:181)
at com.test.liquibase.LiquibaseTest.main(LiquibaseTest.java:27)

Am I doing something wrong or missing something? Please help.

Thanks in Advance

Upvotes: 4

Views: 2360

Answers (2)

simbo1905
simbo1905

Reputation: 6832

The Liquibase class you are using and that is in most example code doesn't seem to have an "updateSQL". You can programmatically invoke the main method passing in the necessary --url parameters to get it to do the work. for example:

        liquibase.integration.commandline.Main.main(new String[]{"--changeLogFile=src/test/resources/db.changelog.xml"
                ,"--outputFile=target/updateSql.txt"
                ,"--url=offline:unknown?outputLiquibaseSql=true"
                , "updateSQL"});

Will generate:

-- *********************************************************************
-- Update Database Script
-- *********************************************************************
-- Change Log: src/test/resources/db.changelog.xml
-- Ran at: 12/04/20 11:51
-- Against: null@offline:unknown?outputLiquibaseSql=true
-- Liquibase version: 3.8.9
-- *********************************************************************

CREATE TABLE DATABASECHANGELOG (ID VARCHAR(255) NOT NULL, AUTHOR VARCHAR(255) NOT NULL, FILENAME VARCHAR(255) NOT NULL, DATEEXECUTED datetime NOT NULL, ORDEREXECUTED INT NOT NULL, EXECTYPE VARCHAR(10) NOT NULL, MD5SUM VARCHAR(35), DESCRIPTION VARCHAR(255), COMMENTS VARCHAR(255), TAG VARCHAR(255), LIQUIBASE VARCHAR(20), CONTEXTS VARCHAR(255), LABELS VARCHAR(255), DEPLOYMENT_ID VARCHAR(10));

-- Changeset src/test/resources/db.changelog.xml::createTable-example::liquibase-docs
CREATE TABLE public.person (address VARCHAR(255));

INSERT INTO DATABASECHANGELOG (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, DESCRIPTION, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE, DEPLOYMENT_ID) VALUES ('createTable-example', 'liquibase-docs', 'src/test/resources/db.changelog.xml', CURRENT_TIMESTAMP, 1, '8:49e8eb557129b33d282c4ad2fdc5d4d9', 'createTable tableName=person', '', 'EXECUTED', NULL, NULL, '3.8.9', '6688703163');

And also outputs a databasechangelog.csv that tracks what should be the state of the DATABASECHANGELOG for subsequent runs.

If you edit the code to load "db.changelog2.xml" with something new in it with a different ID and tell it to write out the sql to a new file that will only have the second change set in it. This is because the databasechangelog.csv will be used to know what was previously run. The CSV will then be updated for the next time:

"ID","AUTHOR","FILENAME","DATEEXECUTED","ORDEREXECUTED","EXECTYPE","MD5SUM","DESCRIPTION","COMMENTS","TAG","LIQUIBASE","CONTEXTS","LABELS","DEPLOYMENT_ID"
"createTable-example","liquibase-docs","src/test/resources/db.changelog.xml","2020-04-12T12:10:16.989","2","EXECUTED","8:49e8eb557129b33d282c4ad2fdc5d4d9","createTable tableName=person","","","3.8.9","()","","6689816939"
"createTable-example2","liquibase-docs","src/test/resources/db.changelog2.xml","2020-04-12T12:26:56.664","4","EXECUTED","8:3740614394b969eeb1edcc9fd0187bdb","createTable tableName=person2",,"","3.8.9","()","","6690816645"

Warning: It seems that if you call the main method directly it will internally call System.exit() so if you really wanted to run updateSQL inside a tool you will need to look at the code inside that main class to figure out how to do it without the JVM being terminated by System.exit().

Upvotes: 2

SteveDonie
SteveDonie

Reputation: 9016

Offline databases are something that Liquibase came up with to allow you to generate SQL for updating a database that the liquibase user is not able to update directly - they are not able to be updated. See this documentation for more details about offline databases.

Upvotes: 0

Related Questions