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

liquibase.database.core.H2Database Maven / Gradle / Ivy

There is a newer version: 4.30.0
Show newest version
package liquibase.database.core;

import liquibase.database.DatabaseConnection;
import liquibase.database.AbstractDatabase;
import liquibase.exception.DatabaseException;
import liquibase.exception.DateParseException;
import liquibase.statement.DatabaseFunction;
import liquibase.util.ISODateFormat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Date;
import java.util.Arrays;
import java.util.List;

public class H2Database extends AbstractDatabase {

    private static String START_CONCAT = "CONCAT(";
    private static String END_CONCAT = ")";
    private static String SEP_CONCAT = ", ";

    public H2Database() {
        this.databaseFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP()"));
    }

    public String getTypeName() {
        return "h2";
    }

    public String getDefaultDriver(String url) {
        if (url.startsWith("jdbc:h2")) {
            return "org.h2.Driver";
        }
        return null;
    }

    public int getPriority() {
        return PRIORITY_DATABASE;
    }

    public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
        return "H2".equals(conn.getDatabaseProductName());
    }

    //    public void dropDatabaseObjects(String schema) throws DatabaseException {
//        DatabaseConnection conn = getConnection();
//        Statement dropStatement = null;
//        try {
//            dropStatement = conn.createStatement();
//            dropStatement.executeUpdate("DROP ALL OBJECTS");
//            changeLogTableExists = false;
//            changeLogLockTableExists = false;
//            changeLogCreateAttempted = false;
//            changeLogLockCreateAttempted = false;
//        } catch (SQLException e) {
//            throw new DatabaseException(e);
//        } finally {
//            try {
//                if (dropStatement != null) {
//                    dropStatement.close();
//                }
//                conn.commit();
//            } catch (SQLException e) {
//                ;
//            }
//        }
//
//    }

    public boolean supportsTablespaces() {
        return false;
    }

    @Override
    public String getViewDefinition(String schemaName, String name) throws DatabaseException {
        String definition = super.getViewDefinition(schemaName, name);
        if (!definition.startsWith("SELECT")) {
            definition = definition.replaceFirst(".*?\n", ""); //some h2 versions return "create view....as\nselect
        }

        definition = definition.replaceFirst("/\\*.*",""); //sometimes includes comments at the end
        return definition;
    }


    @Override
    public Date parseDate(String dateAsString) throws DateParseException {
        try {
            if (dateAsString.indexOf(' ') > 0) {
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSSSS").parse(dateAsString);
            } else {
                if (dateAsString.indexOf(':') > 0) {
                    return new SimpleDateFormat("HH:mm:ss").parse(dateAsString);
                } else {
                    return new SimpleDateFormat("yyyy-MM-dd").parse(dateAsString);
                }
            }
        } catch (ParseException e) {
            throw new DateParseException(dateAsString);
        }
    }

    @Override
    public boolean isLocalDatabase() throws DatabaseException {
        String url = getConnection().getURL();
        boolean isLocalURL = (
                super.isLocalDatabase()
                        || url.startsWith("jdbc:h2:file:")
                        || url.startsWith("jdbc:h2:mem:")
                        || url.startsWith("jdbc:h2:zip:")
                        || url.startsWith("jdbc:h2:~")
        );
        return isLocalURL;
    }

//    @Override
//    public String convertRequestedSchemaToSchema(String requestedSchema) throws DatabaseException {
//        return super.convertRequestedSchemaToSchema(requestedSchema).toLowerCase();
//    }

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

    @Override
    protected String getDefaultDatabaseSchemaName() throws DatabaseException {
        return "PUBLIC";
    }

    @Override
    public String getAutoIncrementClause() {
        return "GENERATED BY DEFAULT AS IDENTITY IDENTITY";
    }

    @Override
    public String getConcatSql(String... values) {
        if (values == null) {
            return null;
        }

        return getConcatSql(Arrays.asList(values));
    }

    /**
     * Recursive way of building CONCAT instruction
     *
     * @param values a non null List of String
     * @return a String containing the CONCAT instruction with all elements, or only a value if there is only one element in the list
     */
    private String getConcatSql(List values) {
        if (values.size() == 1) {
            return values.get(0);
        } else {
            return START_CONCAT + values.get(0) + SEP_CONCAT + getConcatSql(values.subList(1, values.size())) + END_CONCAT;
        }
    }

    @Override
    public String getDateLiteral(String isoDate) {
        String returnString = isoDate;
        try {
            if (isDateTime(isoDate)) {
                ISODateFormat isoTimestampFormat = new ISODateFormat();
                DateFormat dbTimestampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
                returnString = dbTimestampFormat.format(isoTimestampFormat.parse(isoDate));
            }
        } catch (ParseException e) {
            throw new RuntimeException("Unexpected date format: " + isoDate, e);
        }
        return "'" + returnString + "'";
    }

    @Override
    public String convertRequestedSchemaToSchema(String requestedSchema) throws DatabaseException {
        return super.convertRequestedSchemaToSchema(requestedSchema).toUpperCase();
    }

    @Override
    public String escapeDatabaseObject(String objectName) {
    	if (objectName != null) {
            if (isReservedWord(objectName)) {
                return "\""+objectName+"\"";
            }
    	}
        return objectName;
    }

    @Override
    public boolean isReservedWord(String objectName) {
        return keywords.contains(objectName.toUpperCase());
    }

    private static List keywords = Arrays.asList(
//            "ADD",
//            "ALL",
//            "ALLOCATE",
//            "ALTER",
//            "AND",
//            "ANY",
//            "ARE",
//            "ARRAY",
//            "AS",
//            "ASENSITIVE",
//            "ASYMMETRIC",
//            "AT",
//            "ATOMIC",
//            "AUTHORIZATION",
//            "BEGIN",
//            "BETWEEN",
//            "BIGINT",
//            "BINARY",
//            "BLOB",
//            "BOOLEAN",
//            "BOTH",
//            "BY",
//            "CALL",
//            "CALLED",
//            "CASCADED",
//            "CASE",
//            "CAST",
//            "CHAR",
//            "CHARACTER",
//            "CHECK",
//            "CLOB",
//            "CLOSE",
//            "COLLATE",
//            "COLUMN",
//            "COMMIT",
//            "CONDITION",
//            "CONNECT",
//            "CONSTRAINT",
//            "CONTINUE",
//            "CORRESPONDING",
//            "CREATE",
//            "CROSS",
//            "CUBE",
//            "CURRENT",
//            "CURRENT_DATE",
//            "CURRENT_DEFAULT_TRANSFORM_GRO",
//            "CURRENT_PATH",
//            "CURRENT_ROLE",
//            "CURRENT_TIME",
//            "CURRENT_TIMESTAMP",
//            "CURRENT_TRANSFORM_GROUP_FOR_T",
//            "CURRENT_USER",
//            "CURSOR",
//            "CYCLE",
//            "DATE",
//            "DAY",
//            "DEALLOCATE",
//            "DEC",
//            "DECIMAL",
//            "DECLARE",
//            "DEFAULT",
//            "DELETE",
//            "DEREF",
//            "DESCRIBE",
//            "DETERMINISTIC",
//            "DISCONNECT",
//            "DISTINCT",
//            "DO",
//            "DOUBLE",
//            "DROP",
//            "DYNAMIC",
//            "EACH",
//            "ELEMENT",
//            "ELSE",
//            "ELSEIF",
//            "END",
//            "ESCAPE",
//            "EXCEPT",
//            "EXEC",
//            "EXECUTE",
//            "EXISTS",
//            "EXIT",
//            "EXTERNAL",
//            "FALSE",
//            "FETCH",
//            "FILTER",
//            "FLOAT",
//            "FOR",
//            "FOREIGN",
//            "FREE",
//            "FROM",
//            "FULL",
//            "FUNCTION",
//            "GET",
//            "GLOBAL",
//            "GRANT",
//            "GROUP",
//            "GROUPING",
//            "HANDLER",
//            "HAVING",
//            "HOLD",
//            "HOUR",
//            "IDENTITY",
//            "IF",
//            "IMMEDIATE",
//            "IN",
//            "INDICATOR",
//            "INNER",
//            "INOUT",
//            "INPUT",
//            "INSENSITIVE",
//            "INSERT",
//            "INT",
//            "INTEGER",
//            "INTERSECT",
//            "INTERVAL",
//            "INTO",
//            "IS",
//            "ITERATE",
//            "JOIN",
//            "LANGUAGE",
//            "LARGE",
//            "LATERAL",
//            "LEADING",
//            "LEAVE",
//            "LEFT",
//            "LIKE",
//            "LOCAL",
//            "LOCALTIME",
//            "LOCALTIMESTAMP",
//            "LOOP",
//            "MATCH",
//            "MEMBER",
//            "MERGE",
//            "METHOD",
//            "MINUTE",
//            "MODIFIES",
//            "MODULE",
//            "MONTH",
//            "MULTISET",
//            "NATIONAL",
//            "NATURAL",
//            "NCHAR",
//            "NCLOB",
//            "NEW",
//            "NO",
//            "NONE",
//            "NOT",
//            "NULL",
//            "NUMERIC",
//            "OF",
//            "OLD",
//            "ON",
//            "ONLY",
//            "OPEN",
//            "OR",
//            "ORDER",
//            "OUT",
//            "OUTER",
//            "OUTPUT",
//            "OVER",
//            "OVERLAPS",
//            "PARAMETER",
//            "PARTITION",
//            "PRECISION",
//            "PREPARE",
//            "PRIMARY",
//            "PROCEDURE",
//            "RANGE",
//            "READS",
//            "REAL",
//            "RECURSIVE",
//            "REF",
//            "REFERENCES",
//            "REFERENCING",
//            "RELEASE",
//            "REPEAT",
//            "RESIGNAL",
//            "RESULT",
//            "RETURN",
//            "RETURNS",
//            "REVOKE",
//            "RIGHT",
//            "ROLLBACK",
//            "ROLLUP",
//            "ROW",
//            "ROWS",
//            "SAVEPOINT",
//            "SCOPE",
//            "SCROLL",
//            "SEARCH",
//            "SECOND",
//            "SELECT",
//            "SENSITIVE",
//            "SESSION_USER",
//            "SET",
//            "SIGNAL",
//            "SIMILAR",
//            "SMALLINT",
//            "SOME",
//            "SPECIFIC",
//            "SPECIFICTYPE",
//            "SQL",
//            "SQLEXCEPTION",
//            "SQLSTATE",
//            "SQLWARNING",
//            "START",
//            "STATIC",
//            "SUBMULTISET",
//            "SYMMETRIC",
//            "SYSTEM",
//            "SYSTEM_USER",
//            "TABLE",
//            "TABLESAMPLE",
//            "THEN",
//            "TIME",
//            "TIMESTAMP",
//            "TIMEZONE_HOUR",
//            "TIMEZONE_MINUTE",
//            "TO",
//            "TRAILING",
//            "TRANSLATION",
//            "TREAT",
//            "TRIGGER",
//            "TRUE",
//            "UNDO",
//            "UNION",
//            "UNIQUE",
//            "UNKNOWN",
//            "UNNEST",
//            "UNTIL",
//            "UPDATE",
//            "USER",
//            "USING",
//            "VALUE",
//            "VALUES",
//            "VARCHAR",
//            "VARYING",
//            "WHEN",
//            "WHENEVER",
//            "WHERE",
//            "WHILE",
//            "WINDOW",
//            "WITH",
//            "WITHIN",
//            "WITHOUT",
//            "YEAR",
//            "ALIAS",
//            "AUTOCOMMIT",
//            "CACHED",
//            "CHECKPOINT",
//            "EXPLAIN",
//            "IGNORECASE",
//            "INDEX",
//            "LOGSIZE",
//            "MATCHED",
//            "MAXROWS",
//            "MEMORY",
//            "MINUS",
//            "NEXT",
//            "OPENBRACKET",
//            "PASSWORD",
//            "PLAN",
//            "PROPERTY",
//            "READONLY",
//            "REFERENTIAL_INTEGRITY",
//            "RENAME",
//            "RESTART",
//            "SCRIPT",
//            "SCRIPTFORMAT",
//            "SEMICOLON",
//            "SEQUENCE",
//            "SHUTDOWN",
//            "SOURCE",
//            "TEMP",
//            "TEXT",
//            "VIEW",
//            "WRITE_DELAY",
//            "VAR_POP",
//            "VAR_SAMP",
//            "STDDEV_POP",
//            "STDDEV_SAMP",
//            "DEFRAG",
//            "INCREMENT",
//            "TOCHAR",
//            "DATABASE",
//            "SCHEMA",
//            "ROLE",
//            "DOW",
//            "INITIAL"
    );

    public boolean supportsInitiallyDeferrableColumns() {
        return false;
    }

    public String getCurrentDateTimeFunction() {
        if (currentDateTimeFunction != null) {
            return currentDateTimeFunction;
        }

        return "NOW()";
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy