001: package liquibase.database;
002:
003: import liquibase.database.sql.RawSqlStatement;
004: import liquibase.database.sql.SqlStatement;
005: import liquibase.exception.DateParseException;
006: import liquibase.exception.JDBCException;
007: import liquibase.util.ISODateFormat;
008:
009: import java.sql.Connection;
010: import java.text.DateFormat;
011: import java.text.ParseException;
012: import java.text.SimpleDateFormat;
013: import java.util.Arrays;
014: import java.util.Date;
015: import java.util.List;
016:
017: public class HsqlDatabase extends AbstractDatabase {
018: private static String START_CONCAT = "CONCAT(";
019: private static String END_CONCAT = ")";
020: private static String SEP_CONCAT = ", ";
021:
022: public boolean isCorrectDatabaseImplementation(Connection conn)
023: throws JDBCException {
024: return "HSQL Database Engine"
025: .equalsIgnoreCase(getDatabaseProductName(conn));
026: }
027:
028: public String getDefaultDriver(String url) {
029: if (url.startsWith("jdbc:hsqldb:")) {
030: return "org.hsqldb.jdbcDriver";
031: }
032: return null;
033: }
034:
035: public String getProductName() {
036: return "Hsqldb";
037: }
038:
039: public String getTypeName() {
040: return "hsqldb";
041: }
042:
043: public boolean supportsSequences() {
044: return true;
045: }
046:
047: public boolean supportsInitiallyDeferrableColumns() {
048: return false;
049: }
050:
051: protected String getDefaultDatabaseSchemaName()
052: throws JDBCException {
053: return "PUBLIC";
054: }
055:
056: public String getBooleanType() {
057: return "BOOLEAN";
058: }
059:
060: public String getCurrencyType() {
061: return "DECIMAL";
062: }
063:
064: public String getUUIDType() {
065: return "VARCHAR(36)";
066: }
067:
068: public String getClobType() {
069: return "LONGVARCHAR";
070: }
071:
072: public String getBlobType() {
073: return "LONGVARBINARY";
074: }
075:
076: public String getDateTimeType() {
077: return "DATETIME";
078: }
079:
080: public String getCurrentDateTimeFunction() {
081: return "NOW()";
082: }
083:
084: public String getAutoIncrementClause() {
085: return "GENERATED BY DEFAULT AS IDENTITY IDENTITY";
086: }
087:
088: public String getConcatSql(String... values) {
089: if (values == null) {
090: return null;
091: }
092:
093: return getConcatSql(Arrays.asList(values));
094: }
095:
096: /**
097: * Recursive way of building CONCAT instruction
098: *
099: * @param values a non null List of String
100: * @return a String containing the CONCAT instruction with all elements, or only a value if there is only one element in the list
101: */
102: private String getConcatSql(List<String> values) {
103: if (values.size() == 1) {
104: return values.get(0);
105: } else {
106: return START_CONCAT + values.get(0) + SEP_CONCAT
107: + getConcatSql(values.subList(1, values.size()))
108: + END_CONCAT;
109: }
110: }
111:
112: public String getDateLiteral(String isoDate) {
113: String returnString = isoDate;
114: try {
115: if (isDateTime(isoDate)) {
116: ISODateFormat isoTimestampFormat = new ISODateFormat();
117: DateFormat dbTimestampFormat = new SimpleDateFormat(
118: "yyyy-MM-dd HH:mm:ss.S");
119: returnString = dbTimestampFormat
120: .format(isoTimestampFormat.parse(isoDate));
121: }
122: } catch (ParseException e) {
123: throw new RuntimeException("Unexpected date format: "
124: + isoDate, e);
125: }
126: return "'" + returnString + "'";
127: }
128:
129: protected Date parseDate(String dateAsString)
130: throws DateParseException {
131: try {
132: if (dateAsString.indexOf(" ") > 0) {
133: return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S")
134: .parse(dateAsString);
135: } else {
136: if (dateAsString.indexOf(":") > 0) {
137: return new SimpleDateFormat("HH:mm:ss")
138: .parse(dateAsString);
139: } else {
140: return new SimpleDateFormat("yyyy-MM-dd")
141: .parse(dateAsString);
142: }
143: }
144: } catch (ParseException e) {
145: throw new DateParseException(dateAsString);
146: }
147: }
148:
149: public SqlStatement createFindSequencesSQL(String schema)
150: throws JDBCException {
151: return new RawSqlStatement(
152: "SELECT SEQUENCE_NAME FROM INFORMATION_SCHEMA.SYSTEM_SEQUENCES WHERE SEQUENCE_SCHEMA = '"
153: + convertRequestedSchemaToSchema(schema) + "'");
154: }
155:
156: public boolean supportsTablespaces() {
157: return false;
158: }
159:
160: public void setConnection(Connection conn) {
161: super .setConnection(new HsqlConnectionDelegate(conn));
162: }
163:
164: public SqlStatement getViewDefinitionSql(String schemaName,
165: String name) throws JDBCException {
166: return new RawSqlStatement(
167: "SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.SYSTEM_VIEWS WHERE TABLE_NAME = '"
168: + name
169: + "' AND TABLE_SCHEMA='"
170: + convertRequestedSchemaToSchema(schemaName)
171: + "'");
172: }
173:
174: public String convertRequestedSchemaToSchema(String requestedSchema)
175: throws JDBCException {
176: return super.convertRequestedSchemaToSchema(requestedSchema)
177: .toUpperCase();
178: }
179: }
|