1 | |
package liquibase.database.core; |
2 | |
|
3 | |
import liquibase.database.AbstractDatabase; |
4 | |
import liquibase.database.DatabaseConnection; |
5 | |
import liquibase.exception.DatabaseException; |
6 | |
import liquibase.exception.DateParseException; |
7 | |
import liquibase.statement.DatabaseFunction; |
8 | |
import liquibase.util.ISODateFormat; |
9 | |
|
10 | |
import java.text.DateFormat; |
11 | |
import java.text.ParseException; |
12 | |
import java.text.SimpleDateFormat; |
13 | |
import java.util.Arrays; |
14 | |
import java.util.Date; |
15 | |
import java.util.List; |
16 | |
|
17 | 3 | public class HsqlDatabase extends AbstractDatabase { |
18 | 1 | private static String START_CONCAT = "CONCAT("; |
19 | 1 | private static String END_CONCAT = ")"; |
20 | 1 | private static String SEP_CONCAT = ", "; |
21 | |
|
22 | |
public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException { |
23 | 0 | return "HSQL Database Engine".equalsIgnoreCase(conn.getDatabaseProductName()); |
24 | |
} |
25 | |
|
26 | |
public String getDefaultDriver(String url) { |
27 | 2 | if (url.startsWith("jdbc:hsqldb:")) { |
28 | 1 | return "org.hsqldb.jdbcDriver"; |
29 | |
} |
30 | 1 | return null; |
31 | |
} |
32 | |
|
33 | |
public int getPriority() { |
34 | 0 | return PRIORITY_DEFAULT; |
35 | |
} |
36 | |
|
37 | |
public String getTypeName() { |
38 | 56 | return "hsqldb"; |
39 | |
} |
40 | |
|
41 | |
@Override |
42 | |
public boolean supportsSequences() { |
43 | 14 | return true; |
44 | |
} |
45 | |
|
46 | |
public boolean supportsInitiallyDeferrableColumns() { |
47 | 0 | return false; |
48 | |
} |
49 | |
|
50 | |
@Override |
51 | |
protected String getDefaultDatabaseSchemaName() throws DatabaseException { |
52 | 0 | return "PUBLIC"; |
53 | |
} |
54 | |
|
55 | |
public String getCurrentDateTimeFunction() { |
56 | 0 | if (currentDateTimeFunction != null) { |
57 | 0 | return currentDateTimeFunction; |
58 | |
} |
59 | |
|
60 | 0 | return "NOW"; |
61 | |
} |
62 | |
|
63 | |
@Override |
64 | |
public String getAutoIncrementClause() { |
65 | 0 | return "GENERATED BY DEFAULT AS IDENTITY"; |
66 | |
} |
67 | |
|
68 | |
@Override |
69 | |
public String getConcatSql(String... values) { |
70 | 3 | if (values == null) { |
71 | 1 | return null; |
72 | |
} |
73 | |
|
74 | 2 | return getConcatSql(Arrays.asList(values)); |
75 | |
} |
76 | |
|
77 | |
|
78 | |
|
79 | |
|
80 | |
|
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | |
private String getConcatSql(List<String> values) { |
86 | 5 | if (values.size() == 1) { |
87 | 2 | return values.get(0); |
88 | |
} else { |
89 | 3 | return START_CONCAT + values.get(0) + SEP_CONCAT + getConcatSql(values.subList(1, values.size())) |
90 | |
+ END_CONCAT; |
91 | |
} |
92 | |
} |
93 | |
|
94 | |
@Override |
95 | |
public String getDateLiteral(String isoDate) { |
96 | 0 | String returnString = isoDate; |
97 | |
try { |
98 | 0 | if (isDateTime(isoDate)) { |
99 | 0 | ISODateFormat isoTimestampFormat = new ISODateFormat(); |
100 | 0 | DateFormat dbTimestampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S"); |
101 | 0 | returnString = dbTimestampFormat.format(isoTimestampFormat.parse(isoDate)); |
102 | |
} |
103 | 0 | } catch (ParseException e) { |
104 | 0 | throw new RuntimeException("Unexpected date format: " + isoDate, e); |
105 | 0 | } |
106 | 0 | return "'" + returnString + "'"; |
107 | |
} |
108 | |
|
109 | |
@Override |
110 | |
public Date parseDate(String dateAsString) throws DateParseException { |
111 | |
try { |
112 | 0 | if (dateAsString.indexOf(" ") > 0) { |
113 | 0 | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S").parse(dateAsString); |
114 | |
} else { |
115 | 0 | if (dateAsString.indexOf(":") > 0) { |
116 | 0 | return new SimpleDateFormat("HH:mm:ss").parse(dateAsString); |
117 | |
} else { |
118 | 0 | return new SimpleDateFormat("yyyy-MM-dd").parse(dateAsString); |
119 | |
} |
120 | |
} |
121 | 0 | } catch (ParseException e) { |
122 | 0 | throw new DateParseException(dateAsString); |
123 | |
} |
124 | |
} |
125 | |
|
126 | |
public boolean supportsTablespaces() { |
127 | 0 | return false; |
128 | |
} |
129 | |
|
130 | |
@Override |
131 | |
public String convertRequestedSchemaToSchema(String requestedSchema) throws DatabaseException { |
132 | 0 | return super.convertRequestedSchemaToSchema(requestedSchema).toUpperCase(); |
133 | |
} |
134 | |
|
135 | |
@Override |
136 | |
public String escapeDatabaseObject(String objectName) { |
137 | 10 | if (objectName != null) { |
138 | 4 | if (keywords.contains(objectName.toUpperCase())) { |
139 | 0 | return "\"" + objectName + "\""; |
140 | |
} |
141 | |
} |
142 | 10 | return objectName; |
143 | |
} |
144 | |
|
145 | 1 | private static List keywords = Arrays.asList("ADD", "ALL", "ALLOCATE", "ALTER", "AND", "ANY", "ARE", "ARRAY", "AS", |
146 | |
"ASENSITIVE", "ASYMMETRIC", "AT", "ATOMIC", "AUTHORIZATION", "AVG", "BEGIN", "BETWEEN", "BIGINT", "BINARY", |
147 | |
"BLOB", "BOOLEAN", "BOTH", "BY", "CALL", "CALLED", "CASCADED", "CASE", "CAST", "CHAR", "CHARACTER", |
148 | |
"CHECK", "CLOB", "CLOSE", "COLLATE", "COLUMN", "COMMIT", "CONDITION", "CONNECT", "CONSTRAINT", "CONTINUE", |
149 | |
"CORRESPONDING", "COUNT", "CREATE", "CROSS", "CUBE", "CURRENT", "CURRENT_DATE", |
150 | |
"CURRENT_DEFAULT_TRANSFORM_GRO", "CURRENT_PATH", "CURRENT_ROLE", "CURRENT_TIME", "CURRENT_TIMESTAMP", |
151 | |
"CURRENT_TRANSFORM_GROUP_FOR_T", "CURRENT_USER", "CURSOR", "DATE", "DAY", "DEALLOCATE", "DEC", "DECIMAL", |
152 | |
"DECLARE", "DEFAULT", "DELETE", "DEREF", "DESCRIBE", "DETERMINISTIC", "DISCONNECT", "DISTINCT", "DO", |
153 | |
"DOUBLE", "DROP", "DYNAMIC", "EACH", "ELEMENT", "ELSE", "ELSEIF", "END", "ESCAPE", "EXCEPT", "EXEC", |
154 | |
"EXECUTE", "EXISTS", "EXIT", "EXTERNAL", "FALSE", "FETCH", "FILTER", "FLOAT", "FOR", "FOREIGN", "FREE", |
155 | |
"FROM", "FULL", "FUNCTION", "GET", "GLOBAL", "GRANT", "GROUP", "HAVING", "HOLD", "HOUR", "IDENTITY", "IF", |
156 | |
"IMMEDIATE", "IN", "INDICATOR", "INNER", "INOUT", "INPUT", "INSENSITIVE", "INSERT", "INT", "INTEGER", |
157 | |
"INTERSECT", "INTERVAL", "INTO", "IS", "ITERATE", "JOIN", "LANGUAGE", "LARGE", "LEADING", "LEAVE", "LEFT", |
158 | |
"LIKE", "LOCAL", "LOCALTIME", "LOCALTIMESTAMP", "LOOP", "MATCH", "MAX", "MEMBER", "MERGE", "METHOD", "MIN", |
159 | |
"MINUTE", "MODIFIES", "MODULE", "MONTH", "MULTISET", "NATIONAL", "NATURAL", "NCHAR", "NCLOB", "NEW", "NO", |
160 | |
"NONE", "NOT", "NULL", "NUMERIC", "OF", "ON", "ONLY", "OPEN", "OR", "ORDER", "OUT", "OUTER", "OUTPUT", |
161 | |
"OVER", "OVERLAPS", "PARAMETER", "PARTITION", "PRECISION", "PREPARE", "PRIMARY", "PROCEDURE", "RANGE", |
162 | |
"READS", "REAL", "RECURSIVE", "REF", "REFERENCES", "REFERENCING", "RELEASE", "REPEAT", "RESIGNAL", |
163 | |
"RESULT", "RETURN", "RETURNS", "REVOKE", "RIGHT", "ROLLBACK", "ROLLUP", "ROW", "ROWS", "SAVEPOINT", |
164 | |
"SCOPE", "SCROLL", "SEARCH", "SELECT", "SENSITIVE", "SESSION_USER", "SET", "SIGNAL", "SIMILAR", "SMALLINT", |
165 | |
"SOME", "SPECIFIC", "SPECIFICTYPE", "SQL", "SQLEXCEPTION", "SQLSTATE", "SQLWARNING", "START", "STATIC", |
166 | |
"SUBMULTISET", "SYMMETRIC", "SYSTEM", "SYSTEM_USER", "TABLE", "TABLESAMPLE", "THEN", "TIME", "TIMESTAMP", |
167 | |
"TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO", "TRAILING", "TREAT", "TRIGGER", "TRUE", "UNDO", "UNION", |
168 | |
"UNIQUE", "UNNEST", "UNTIL", "UPDATE", "USER", "USING", "VALUE", "VALUES", "VARCHAR", "VARYING", "WHEN", |
169 | |
"WHENEVER", "WHERE", "WHILE", "WINDOW", "WITHIN", "WITHOUT", "YEAR", "ALIAS", "AUTOCOMMIT", "CACHED", |
170 | |
"CHECKPOINT", "EXPLAIN", "IGNORECASE", "INDEX", "LOGSIZE", "MATCHED", "MAXROWS", "MEMORY", "MINUS", "NEXT", |
171 | |
"OPENBRACKET", "PLAN", "PROPERTY", "READONLY", "REFERENTIAL_INTEGRITY", "RENAME", "RESTART", "SCRIPT", |
172 | |
"SCRIPTFORMAT", "SEMICOLON", "SEQUENCE", "SHUTDOWN", "SOURCE", "TEMP", "TEXT", "VIEW", "WRITE_DELAY", |
173 | |
"VAR_POP", "VAR_SAMP", "STDDEV_POP", "STDDEV_SAMP", "DEFRAG", "INCREMENT", "TOCHAR", "DATABASE", "SCHEMA", |
174 | |
"ROLE", "DOW", "INITIAL"); |
175 | |
} |