001: /*
002: * Copyright (C) 2006 Rob Manning
003: * manningr@users.sourceforge.net
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: */
019: package net.sourceforge.squirrel_sql.fw.dialects;
020:
021: import java.sql.SQLException;
022: import java.sql.Types;
023: import java.util.List;
024:
025: import net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType;
026: import net.sourceforge.squirrel_sql.fw.sql.IDatabaseObjectInfo;
027: import net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData;
028: import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
029: import net.sourceforge.squirrel_sql.fw.sql.JDBCTypeMapper;
030: import net.sourceforge.squirrel_sql.fw.sql.TableColumnInfo;
031:
032: /**
033: * An extension to the standard Hibernate MySQL dialect
034: */
035:
036: public class HSQLDialect extends org.hibernate.dialect.HSQLDialect
037: implements HibernateDialect {
038:
039: public HSQLDialect() {
040: super ();
041: registerColumnType(Types.BIGINT, "bigint");
042: registerColumnType(Types.BINARY, "binary");
043: registerColumnType(Types.BIT, "bit");
044: registerColumnType(Types.BLOB, "longvarbinary");
045: //registerColumnType(Types.BOOLEAN, "bit");
046: registerColumnType(Types.BOOLEAN, "boolean");
047: registerColumnType(Types.CHAR, "char($l)");
048: registerColumnType(Types.CLOB, "longvarchar");
049: registerColumnType(Types.DATE, "date");
050: registerColumnType(Types.DECIMAL, "decimal");
051: registerColumnType(Types.DOUBLE, "double");
052: registerColumnType(Types.FLOAT, "float");
053: registerColumnType(Types.INTEGER, "integer");
054: registerColumnType(Types.LONGVARBINARY, "longvarbinary");
055: registerColumnType(Types.LONGVARCHAR, "longvarchar");
056: registerColumnType(Types.NUMERIC, "numeric");
057: registerColumnType(Types.REAL, "real");
058: registerColumnType(Types.SMALLINT, "smallint");
059: registerColumnType(Types.TIME, "time");
060: registerColumnType(Types.TIMESTAMP, "timestamp");
061: registerColumnType(Types.TINYINT, "tinyint");
062: registerColumnType(Types.VARBINARY, "varbinary");
063: registerColumnType(Types.VARCHAR, "varchar");
064: }
065:
066: /* (non-Javadoc)
067: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#canPasteTo(net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType)
068: */
069: public boolean canPasteTo(IDatabaseObjectInfo info) {
070: boolean result = true;
071: DatabaseObjectType type = info.getDatabaseObjectType();
072: if (type.getName().equalsIgnoreCase("database")) {
073: result = false;
074: }
075: return result;
076: }
077:
078: /* (non-Javadoc)
079: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#supportsSchemasInTableDefinition()
080: */
081: public boolean supportsSchemasInTableDefinition() {
082: return false;
083: }
084:
085: /* (non-Javadoc)
086: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getLengthFunction()
087: */
088: public String getLengthFunction(int dataType) {
089: return "length";
090: }
091:
092: /* (non-Javadoc)
093: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getMaxFunction()
094: */
095: public String getMaxFunction() {
096: return "max";
097: }
098:
099: /* (non-Javadoc)
100: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getMaxPrecision(int)
101: */
102: public int getMaxPrecision(int dataType) {
103: return Integer.MAX_VALUE;
104: }
105:
106: /* (non-Javadoc)
107: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getMaxScale(int)
108: */
109: public int getMaxScale(int dataType) {
110: return getMaxPrecision(dataType);
111: }
112:
113: /* (non-Javadoc)
114: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getPrecisionDigits(int, int)
115: */
116: public int getPrecisionDigits(int columnSize, int dataType) {
117: return columnSize;
118: }
119:
120: /* (non-Javadoc)
121: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getColumnLength(int, int)
122: */
123: public int getColumnLength(int columnSize, int dataType) {
124: return columnSize;
125: }
126:
127: /**
128: * The string which identifies this dialect in the dialect chooser.
129: *
130: * @return a descriptive name that tells the user what database this dialect
131: * is design to work with.
132: */
133: public String getDisplayName() {
134: return "HSQL";
135: }
136:
137: /**
138: * Returns boolean value indicating whether or not this dialect supports the
139: * specified database product/version.
140: *
141: * @param databaseProductName the name of the database as reported by
142: * DatabaseMetaData.getDatabaseProductName()
143: * @param databaseProductVersion the version of the database as reported by
144: * DatabaseMetaData.getDatabaseProductVersion()
145: * @return true if this dialect can be used for the specified product name
146: * and version; false otherwise.
147: */
148: public boolean supportsProduct(String databaseProductName,
149: String databaseProductVersion) {
150: if (databaseProductName == null) {
151: return false;
152: }
153: if (databaseProductName.trim().startsWith("HSQL")) {
154: // We don't yet have the need to discriminate by version.
155: return true;
156: }
157: return false;
158: }
159:
160: /**
161: * Returns the SQL statement to use to add a column to the specified table
162: * using the information about the new column specified by info.
163: * @param info information about the new column such as type, name, etc.
164: *
165: * @return
166: * @throws UnsupportedOperationException if the database doesn't support
167: * adding columns after a table has already been created.
168: */
169: public String[] getColumnAddSQL(TableColumnInfo info)
170: throws UnsupportedOperationException {
171:
172: // HSQL doesn't allow setting default value when adding a column.
173:
174: String addSQL = DialectUtils.getColumnAddSQL(info, this , false,
175: true, true);
176: if (info.getDefaultValue() != null
177: && !"".equals(info.getDefaultValue())) {
178: StringBuffer defaultSQL = new StringBuffer();
179: defaultSQL.append("ALTER TABLE ");
180: defaultSQL.append(info.getTableName());
181: defaultSQL.append(" ALTER COLUMN ");
182: defaultSQL.append(info.getColumnName());
183: defaultSQL.append(" SET DEFAULT ");
184: if (JDBCTypeMapper.isNumberType(info.getDataType())) {
185: defaultSQL.append(info.getDefaultValue());
186: } else {
187: defaultSQL.append("'");
188: defaultSQL.append(info.getDefaultValue());
189: defaultSQL.append("'");
190: }
191: return new String[] { addSQL, defaultSQL.toString() };
192: } else {
193: return new String[] { addSQL };
194: }
195: }
196:
197: /**
198: * Returns a boolean value indicating whether or not this dialect supports
199: * adding comments to columns.
200: *
201: * @return true if column comments are supported; false otherwise.
202: */
203: public boolean supportsColumnComment() {
204: return false;
205: }
206:
207: /**
208: * Returns the SQL statement to use to add a comment to the specified
209: * column of the specified table.
210: *
211: * @param tableName the name of the table to create the SQL for.
212: * @param columnName the name of the column to create the SQL for.
213: * @param comment the comment to add.
214: * @return
215: * @throws UnsupportedOperationException if the database doesn't support
216: * annotating columns with a comment.
217: */
218: @SuppressWarnings("unused")
219: public String getColumnCommentAlterSQL(String tableName,
220: String columnName, String comment)
221: throws UnsupportedOperationException {
222: throw new UnsupportedOperationException(
223: "HSQLDB doesn't support adding comments to columns");
224: }
225:
226: /**
227: * Returns a boolean value indicating whether or not this database dialect
228: * supports dropping columns from tables.
229: *
230: * @return true if the database supports dropping columns; false otherwise.
231: */
232: public boolean supportsDropColumn() {
233: return true;
234: }
235:
236: /**
237: * Returns the SQL that forms the command to drop the specified colum in the
238: * specified table.
239: *
240: * @param tableName the name of the table that has the column
241: * @param columnName the name of the column to drop.
242: * @return
243: * @throws UnsupportedOperationException if the database doesn't support
244: * dropping columns.
245: */
246: public String getColumnDropSQL(String tableName, String columnName) {
247: return DialectUtils.getColumnDropSQL(tableName, columnName);
248: }
249:
250: /**
251: * Returns the SQL that forms the command to drop the specified table. If
252: * cascade contraints is supported by the dialect and cascadeConstraints is
253: * true, then a drop statement with cascade constraints clause will be
254: * formed.
255: *
256: * @param iTableInfo the table to drop
257: * @param cascadeConstraints whether or not to drop any FKs that may
258: * reference the specified table.
259: * @return the drop SQL command.
260: */
261: public List<String> getTableDropSQL(ITableInfo iTableInfo,
262: boolean cascadeConstraints, boolean isMaterializedView) {
263: return DialectUtils.getTableDropSQL(iTableInfo, true,
264: cascadeConstraints, false, DialectUtils.CASCADE_CLAUSE,
265: false);
266: }
267:
268: /**
269: * Returns the SQL that forms the command to add a primary key to the
270: * specified table composed of the given column names.
271: *
272: * ALTER TABLE <tablename> ADD [CONSTRAINT <constraintname>] PRIMARY KEY (<column list>);
273: *
274: * @param pkName the name of the constraint
275: * @param columnNames the columns that form the key
276: * @return
277: */
278: public String[] getAddPrimaryKeySQL(String pkName,
279: TableColumnInfo[] columns, ITableInfo ti) {
280: StringBuffer result = new StringBuffer();
281: result.append("ALTER TABLE ");
282: result.append(ti.getQualifiedName());
283: result.append(" ADD CONSTRAINT ");
284: result.append(pkName);
285: result.append(" PRIMARY KEY (");
286: for (int i = 0; i < columns.length; i++) {
287: result.append(columns[i].getColumnName());
288: if (i + 1 < columns.length) {
289: result.append(", ");
290: }
291: }
292: result.append(")");
293: return new String[] { result.toString() };
294: }
295:
296: /**
297: * Returns the SQL statement to use to add a comment to the specified
298: * column of the specified table.
299: * @param info information about the column such as type, name, etc.
300: * @return
301: * @throws UnsupportedOperationException if the database doesn't support
302: * annotating columns with a comment.
303: */
304: public String getColumnCommentAlterSQL(TableColumnInfo info)
305: throws UnsupportedOperationException {
306: throw new UnsupportedOperationException(
307: "HSQLDB doesn't support column comments");
308: }
309:
310: /**
311: * Returns a boolean value indicating whether or not this database dialect
312: * supports changing a column from null to not-null and vice versa.
313: *
314: * @return true if the database supports dropping columns; false otherwise.
315: */
316: public boolean supportsAlterColumnNull() {
317: return true;
318: }
319:
320: /**
321: * Returns the SQL used to alter the specified column to not allow null
322: * values
323: *
324: * ALTER TABLE <tablename> ALTER COLUMN <columnname> SET [NOT] NULL
325: *
326: * @param info the column to modify
327: * @return the SQL to execute
328: */
329: public String getColumnNullableAlterSQL(TableColumnInfo info) {
330: StringBuffer result = new StringBuffer();
331: result.append("ALTER TABLE ");
332: result.append(info.getTableName());
333: result.append(" ALTER COLUMN ");
334: result.append(info.getColumnName());
335: result.append(" SET ");
336: if (info.isNullable().equalsIgnoreCase("YES")) {
337: result.append(" NULL");
338: } else {
339: result.append(" NOT NULL");
340: }
341: return result.toString();
342: }
343:
344: /**
345: * Returns a boolean value indicating whether or not this database dialect
346: * supports renaming columns.
347: *
348: * @return true if the database supports changing the name of columns;
349: * false otherwise.
350: */
351: public boolean supportsRenameColumn() {
352: return true;
353: }
354:
355: /**
356: * Returns the SQL that is used to change the column name.
357: *
358: * ALTER TABLE <tablename> ALTER COLUMN <columnname> RENAME TO <newname>
359: *
360: * @param from the TableColumnInfo as it is
361: * @param to the TableColumnInfo as it wants to be
362: *
363: * @return the SQL to make the change
364: */
365: public String getColumnNameAlterSQL(TableColumnInfo from,
366: TableColumnInfo to) {
367: String alterClause = DialectUtils.ALTER_COLUMN_CLAUSE;
368: String renameToClause = DialectUtils.RENAME_TO_CLAUSE;
369: return DialectUtils.getColumnNameAlterSQL(from, to,
370: alterClause, renameToClause);
371:
372: }
373:
374: /**
375: * Returns a boolean value indicating whether or not this dialect supports
376: * modifying a columns type.
377: *
378: * @return true if supported; false otherwise
379: */
380: public boolean supportsAlterColumnType() {
381: return true;
382: }
383:
384: /**
385: * Returns the SQL that is used to change the column type.
386: *
387: * ALTER TABLE table_name ALTER COLUMN column_name data_type;
388: *
389: * @param from the TableColumnInfo as it is
390: * @param to the TableColumnInfo as it wants to be
391: *
392: * @return the SQL to make the change
393: * @throw UnsupportedOperationException if the database doesn't support
394: * modifying column types.
395: */
396: public List<String> getColumnTypeAlterSQL(TableColumnInfo from,
397: TableColumnInfo to) throws UnsupportedOperationException {
398: String alterClause = DialectUtils.ALTER_COLUMN_CLAUSE;
399: String setClause = "";
400: return DialectUtils.getColumnTypeAlterSQL(this , alterClause,
401: setClause, false, from, to);
402: }
403:
404: /**
405: * Returns a boolean value indicating whether or not this database dialect
406: * supports changing a column's default value.
407: *
408: * @return true if the database supports modifying column defaults; false
409: * otherwise
410: */
411: public boolean supportsAlterColumnDefault() {
412: return true;
413: }
414:
415: /**
416: * Returns the SQL command to change the specified column's default value
417: *
418: * @param info the column to modify and it's default value.
419: * @return SQL to make the change
420: */
421: public String getColumnDefaultAlterSQL(TableColumnInfo info) {
422: String alterClause = DialectUtils.ALTER_COLUMN_CLAUSE;
423: String defaultClause = DialectUtils.SET_DEFAULT_CLAUSE;
424: return DialectUtils.getColumnDefaultAlterSQL(this , info,
425: alterClause, false, defaultClause);
426: }
427:
428: /**
429: * Returns the SQL command to drop the specified table's primary key.
430: *
431: * @param pkName the name of the primary key that should be dropped
432: * @param tableName the name of the table whose primary key should be
433: * dropped
434: * @return
435: */
436: public String getDropPrimaryKeySQL(String pkName, String tableName) {
437: return DialectUtils.getDropPrimaryKeySQL(pkName, tableName,
438: false, false);
439: }
440:
441: /**
442: * Returns the SQL command to drop the specified table's foreign key
443: * constraint.
444: *
445: * @param fkName the name of the foreign key that should be dropped
446: * @param tableName the name of the table whose foreign key should be
447: * dropped
448: * @return
449: */
450: public String getDropForeignKeySQL(String fkName, String tableName) {
451: return DialectUtils.getDropForeignKeySQL(fkName, tableName);
452: }
453:
454: /**
455: * Returns the SQL command to create the specified table.
456: *
457: * @param tables the tables to get create statements for
458: * @param md the metadata from the ISession
459: * @param prefs preferences about how the resultant SQL commands should be
460: * formed.
461: * @param isJdbcOdbc whether or not the connection is via JDBC-ODBC bridge.
462: *
463: * @return the SQL that is used to create the specified table
464: */
465: public List<String> getCreateTableSQL(List<ITableInfo> tables,
466: ISQLDatabaseMetaData md, CreateScriptPreferences prefs,
467: boolean isJdbcOdbc) throws SQLException {
468: return DialectUtils.getCreateTableSQL(tables, md, this, prefs,
469: isJdbcOdbc);
470: }
471:
472: }
|