001: package liquibase.database;
002:
003: import liquibase.database.sql.RawSqlStatement;
004: import liquibase.database.sql.SqlStatement;
005: import liquibase.exception.JDBCException;
006:
007: import java.sql.Connection;
008: import java.sql.SQLException;
009: import java.text.ParseException;
010: import java.util.HashSet;
011: import java.util.Set;
012:
013: /**
014: * Encapsulates MS-SQL database support.
015: */
016: public class MSSQLDatabase extends AbstractDatabase {
017: public static final String PRODUCT_NAME = "Microsoft SQL Server";
018: protected Set<String> systemTablesAndViews = new HashSet<String>();
019:
020: public String getProductName() {
021: return "Microsoft SQL";
022: }
023:
024: public String getTypeName() {
025: return "mssql";
026: }
027:
028: public MSSQLDatabase() {
029: systemTablesAndViews.add("syscolumns");
030: systemTablesAndViews.add("syscomments");
031: systemTablesAndViews.add("sysdepends");
032: systemTablesAndViews.add("sysfilegroups");
033: systemTablesAndViews.add("sysfiles");
034: systemTablesAndViews.add("sysfiles1");
035: systemTablesAndViews.add("sysforeignkeys");
036: systemTablesAndViews.add("sysfulltextcatalogs");
037: systemTablesAndViews.add("sysfulltextnotify");
038: systemTablesAndViews.add("sysindexes");
039: systemTablesAndViews.add("sysindexkeys");
040: systemTablesAndViews.add("sysmembers");
041: systemTablesAndViews.add("sysobjects");
042: systemTablesAndViews.add("syspermissions");
043: systemTablesAndViews.add("sysproperties");
044: systemTablesAndViews.add("sysprotects");
045: systemTablesAndViews.add("sysreferences");
046: systemTablesAndViews.add("systypes");
047: systemTablesAndViews.add("sysusers");
048:
049: systemTablesAndViews.add("syssegments");
050: systemTablesAndViews.add("sysconstraints");
051: }
052:
053: public Set<String> getSystemTablesAndViews() {
054: return systemTablesAndViews;
055: }
056:
057: public boolean supportsInitiallyDeferrableColumns() {
058: return false;
059: }
060:
061: public boolean supportsSequences() {
062: return false;
063: }
064:
065: public boolean isCorrectDatabaseImplementation(Connection conn)
066: throws JDBCException {
067: return PRODUCT_NAME
068: .equalsIgnoreCase(getDatabaseProductName(conn));
069: }
070:
071: public String getDefaultDriver(String url) {
072: if (url.startsWith("jdbc:sqlserver")) {
073: return "com.microsoft.sqlserver.jdbc.SQLServerDriver";
074: } else if (url.startsWith("jdbc:jtds:sqlserver")) {
075: return "net.sourceforge.jtds.jdbc.Driver";
076: }
077: return null;
078: }
079:
080: public String getDateTimeType() {
081: return "DATETIME";
082: }
083:
084: public String getTimeType() {
085: return "DATETIME";
086: }
087:
088: public String getDateType() {
089: return "SMALLDATETIME";
090: }
091:
092: public String getBooleanType() {
093: return "BIT";
094: }
095:
096: public String getCurrencyType() {
097: return "MONEY";
098: }
099:
100: public String getUUIDType() {
101: return "UNIQUEIDENTIFIER";
102: }
103:
104: public String getClobType() {
105: return "TEXT";
106: }
107:
108: public String getBlobType() {
109: return "IMAGE";
110: }
111:
112: public String getCurrentDateTimeFunction() {
113: return "GETDATE()";
114: }
115:
116: public String getAutoIncrementClause() {
117: return "IDENTITY";
118: }
119:
120: protected String getDefaultDatabaseSchemaName()
121: throws JDBCException {
122: return null;
123: }
124:
125: public String getDefaultCatalogName() throws JDBCException {
126: try {
127: return getConnection().getCatalog();
128: } catch (SQLException e) {
129: throw new JDBCException(e);
130: }
131: }
132:
133: public String getTrueBooleanValue() {
134: return "1";
135: }
136:
137: public String getFalseBooleanValue() {
138: return "0";
139: }
140:
141: public String getConcatSql(String... values) {
142: StringBuffer returnString = new StringBuffer();
143: for (String value : values) {
144: returnString.append(value).append(" + ");
145: }
146:
147: return returnString.toString().replaceFirst(" \\+ $", "");
148: }
149:
150: // protected void dropForeignKeys(Connection conn) throws JDBCException {
151: // Statement dropStatement = null;
152: // PreparedStatement fkStatement = null;
153: // ResultSet rs = null;
154: // try {
155: // dropStatement = conn.createStatement();
156: //
157: // fkStatement = conn.prepareStatement("select TABLE_NAME, CONSTRAINT_NAME from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where CONSTRAINT_TYPE='FOREIGN KEY' AND TABLE_CATALOG=?");
158: // fkStatement.setString(1, getDefaultCatalogName());
159: // rs = fkStatement.executeQuery();
160: // while (rs.next()) {
161: // DropForeignKeyConstraintChange dropFK = new DropForeignKeyConstraintChange();
162: // dropFK.setBaseTableName(rs.getString("TABLE_NAME"));
163: // dropFK.setConstraintName(rs.getString("CONSTRAINT_NAME"));
164: //
165: // try {
166: // dropStatement.execute(dropFK.generateStatements(this)[0]);
167: // } catch (UnsupportedChangeException e) {
168: // throw new JDBCException(e.getMessage());
169: // }
170: // }
171: // } catch (SQLException e) {
172: // throw new JDBCException(e);
173: // } finally {
174: // try {
175: // if (dropStatement != null) {
176: // dropStatement.close();
177: // }
178: // if (fkStatement != null) {
179: // fkStatement.close();
180: // }
181: // if (rs != null) {
182: // rs.close();
183: // }
184: // } catch (SQLException e) {
185: // throw new JDBCException(e);
186: // }
187: // }
188: //
189: // }
190:
191: public boolean supportsTablespaces() {
192: return true;
193: }
194:
195: public boolean isSystemTable(String catalogName, String schemaName,
196: String tableName) {
197: return super .isSystemTable(catalogName, schemaName, tableName)
198: || schemaName.equals("sys");
199: }
200:
201: public boolean isSystemView(String catalogName, String schemaName,
202: String viewName) {
203: return super .isSystemView(catalogName, schemaName, viewName)
204: || schemaName.equals("sys");
205: }
206:
207: public String generateDefaultConstraintName(String tableName,
208: String columnName) {
209: return "DF_" + tableName + "_" + columnName;
210: }
211:
212: public Object convertDatabaseValueToJavaObject(Object defaultValue,
213: int dataType, int columnSize, int decimalDigits)
214: throws ParseException {
215: if (defaultValue == null) {
216: return null;
217: }
218:
219: if (defaultValue instanceof String) {
220: if (((String) defaultValue).startsWith("('")) {
221: defaultValue = ((String) defaultValue).replaceFirst(
222: "^\\('", "").replaceFirst("'\\)$", "");
223: } else if (((String) defaultValue).startsWith("((")) {
224: defaultValue = ((String) defaultValue).replaceFirst(
225: "^\\(\\(", "").replaceFirst("\\)\\)$", "");
226: }
227: }
228:
229: defaultValue = super .convertDatabaseValueToJavaObject(
230: defaultValue, dataType, columnSize, decimalDigits);
231:
232: return defaultValue;
233: }
234:
235: public String escapeTableName(String schemaName, String tableName) {
236: if (schemaName == null) {
237: return "[" + tableName + "]";
238: } else {
239: return "[" + schemaName + "].[" + tableName + "]";
240: }
241: }
242:
243: public String convertRequestedSchemaToCatalog(String requestedSchema)
244: throws JDBCException {
245: return getDefaultCatalogName();
246: }
247:
248: public String convertRequestedSchemaToSchema(String requestedSchema)
249: throws JDBCException {
250: if (requestedSchema == null) {
251: return "dbo";
252: }
253: return requestedSchema;
254: }
255:
256: public SqlStatement getViewDefinitionSql(String schemaName,
257: String viewName) throws JDBCException {
258: String sql = "select view_definition from information_schema.views where upper(table_name)='"
259: + viewName.toUpperCase() + "'";
260: // if (StringUtils.trimToNull(schemaName) != null) {
261: sql += " and table_schema='"
262: + convertRequestedSchemaToSchema(schemaName) + "'";
263: sql += " and table_catalog='" + getDefaultCatalogName() + "'";
264: // }
265:
266: // log.info("GetViewDefinitionSQL: "+sql);
267: return new RawSqlStatement(sql);
268: }
269:
270: public String getColumnType(String columnType, Boolean autoIncrement) {
271: String type = super .getColumnType(columnType, autoIncrement);
272: if (autoIncrement != null && autoIncrement) {
273: type = type.replaceFirst(" identity$", "");
274: }
275: return type;
276: }
277: }
|