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.ArrayList;
024: import java.util.List;
025:
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.TableColumnInfo;
030:
031: /**
032: * An extension to the standard Hibernate Firebird dialect
033: */
034: public class FirebirdDialect extends
035: org.hibernate.dialect.FirebirdDialect implements
036: HibernateDialect {
037:
038: public FirebirdDialect() {
039: super ();
040: registerColumnType(Types.BIGINT, "bigint");
041: registerColumnType(Types.BINARY, "blob sub_type 0");
042: registerColumnType(Types.BIT, "char(1)");
043: registerColumnType(Types.BLOB, "blob sub_type -1");
044: registerColumnType(Types.BOOLEAN, "char(1)");
045: registerColumnType(Types.CHAR, 32767, "char($l)");
046: registerColumnType(Types.CHAR, "char(32767)");
047: registerColumnType(Types.CLOB, "blob sub_type text");
048: registerColumnType(Types.DATE, "date");
049: registerColumnType(Types.DECIMAL, "decimal($p,$s)");
050: registerColumnType(Types.DOUBLE, "double precision");
051: registerColumnType(Types.FLOAT, "double precision");
052: registerColumnType(Types.INTEGER, "integer");
053: registerColumnType(Types.LONGVARBINARY, "blob sub_type 0");
054: registerColumnType(Types.LONGVARCHAR, "blob sub_type 1");
055: registerColumnType(Types.NUMERIC, 18, "numeric($p,$s)");
056: registerColumnType(Types.NUMERIC, "double precision");
057: registerColumnType(Types.REAL, "double precision");
058: registerColumnType(Types.SMALLINT, "smallint");
059: registerColumnType(Types.TIME, "time");
060: registerColumnType(Types.TIMESTAMP, "timestamp");
061: registerColumnType(Types.TINYINT, "smallint");
062: registerColumnType(Types.VARBINARY, "blob sub_type -1");
063: registerColumnType(Types.VARCHAR, 32765, "varchar($l)");
064: registerColumnType(Types.VARCHAR, "varchar(32765)");
065: }
066:
067: /* (non-Javadoc)
068: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#canPasteTo(net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType)
069: */
070: public boolean canPasteTo(IDatabaseObjectInfo info) {
071: // TODO Auto-generated method stub
072: return true;
073: }
074:
075: /* (non-Javadoc)
076: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#supportsSchemasInTableDefinition()
077: */
078: public boolean supportsSchemasInTableDefinition() {
079: return false;
080: }
081:
082: /* (non-Javadoc)
083: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getLengthFunction()
084: */
085: public String getLengthFunction(int dataType) {
086: return "strlen";
087: }
088:
089: /* (non-Javadoc)
090: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getMaxFunction()
091: */
092: public String getMaxFunction() {
093: return "max";
094: }
095:
096: /* (non-Javadoc)
097: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getMaxPrecision(int)
098: */
099: public int getMaxPrecision(int dataType) {
100: return 18;
101: }
102:
103: /* (non-Javadoc)
104: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getMaxScale(int)
105: */
106: public int getMaxScale(int dataType) {
107: return getMaxPrecision(dataType);
108: }
109:
110: /* (non-Javadoc)
111: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getPrecisionDigits(int, int)
112: */
113: public int getPrecisionDigits(int columnSize, int dataType) {
114: return columnSize * 2;
115: }
116:
117: /* (non-Javadoc)
118: * @see net.sourceforge.squirrel_sql.plugins.dbcopy.dialects.HibernateDialect#getColumnLength(int, int)
119: */
120: public int getColumnLength(int columnSize, int dataType) {
121: if (dataType == Types.BIGINT || dataType == Types.DECIMAL
122: || dataType == Types.DOUBLE || dataType == Types.FLOAT
123: || dataType == Types.NUMERIC || dataType == Types.REAL) {
124: return getMaxPrecision(dataType);
125: }
126: if (dataType == Types.BLOB || dataType == Types.LONGVARBINARY
127: || dataType == Types.LONGVARCHAR) {
128: return 2147483647;
129: }
130: return columnSize;
131: }
132:
133: /**
134: * The string which identifies this dialect in the dialect chooser.
135: *
136: * @return a descriptive name that tells the user what database this dialect
137: * is design to work with.
138: */
139: public String getDisplayName() {
140: return "Firebird";
141: }
142:
143: /**
144: * Returns boolean value indicating whether or not this dialect supports the
145: * specified database product/version.
146: *
147: * @param databaseProductName the name of the database as reported by
148: * DatabaseMetaData.getDatabaseProductName()
149: * @param databaseProductVersion the version of the database as reported by
150: * DatabaseMetaData.getDatabaseProductVersion()
151: * @return true if this dialect can be used for the specified product name
152: * and version; false otherwise.
153: */
154: public boolean supportsProduct(String databaseProductName,
155: String databaseProductVersion) {
156: if (databaseProductName == null) {
157: return false;
158: }
159: if (databaseProductName.trim().startsWith("Firebird")) {
160: // We don't yet have the need to discriminate by version.
161: return true;
162: }
163: return false;
164: }
165:
166: /**
167: * Returns the SQL statement to use to add a column to the specified table
168: * using the information about the new column specified by info.
169: * @param info information about the new column such as type, name, etc.
170: *
171: * @return
172: * @throws UnsupportedOperationException if the database doesn't support
173: * adding columns after a table has already been created.
174: */
175: public String[] getColumnAddSQL(TableColumnInfo info)
176: throws UnsupportedOperationException {
177: return new String[] { DialectUtils.getColumnAddSQL(info, this ,
178: true, false, true) };
179: }
180:
181: /**
182: * Returns a boolean value indicating whether or not this database dialect
183: * supports dropping columns from tables.
184: *
185: * @return true if the database supports dropping columns; false otherwise.
186: */
187: public boolean supportsDropColumn() {
188: return true;
189: }
190:
191: /**
192: * Returns the SQL that forms the command to drop the specified colum in the
193: * specified table.
194: *
195: * @param tableName the name of the table that has the column
196: * @param columnName the name of the column to drop.
197: * @return
198: * @throws UnsupportedOperationException if the database doesn't support
199: * dropping columns.
200: */
201: public String getColumnDropSQL(String tableName, String columnName) {
202: return DialectUtils.getColumnDropSQL(tableName, columnName);
203: }
204:
205: /**
206: * Returns the SQL that forms the command to drop the specified table. If
207: * cascade contraints is supported by the dialect and cascadeConstraints is
208: * true, then a drop statement with cascade constraints clause will be
209: * formed.
210: *
211: * @param iTableInfo the table to drop
212: * @param cascadeConstraints whether or not to drop any FKs that may
213: * reference the specified table.
214: * @return the drop SQL command.
215: */
216: public List<String> getTableDropSQL(ITableInfo iTableInfo,
217: boolean cascadeConstraints, boolean isMaterializedView) {
218: return DialectUtils.getTableDropSQL(iTableInfo, false,
219: cascadeConstraints, false, DialectUtils.CASCADE_CLAUSE,
220: false);
221: }
222:
223: /**
224: * Returns the SQL that forms the command to add a primary key to the
225: * specified table composed of the given column names.
226: *
227: * ALTER TABLE table_name ADD CONSTRAINT constraint_name PRIMARY KEY (column_name);
228: *
229: * @param pkName the name of the constraint
230: * @param columnNames the columns that form the key
231: * @return
232: */
233: public String[] getAddPrimaryKeySQL(String pkName,
234: TableColumnInfo[] columns, ITableInfo ti) {
235: StringBuffer result = new StringBuffer();
236: result.append("ALTER TABLE ");
237: result.append(ti.getQualifiedName());
238: result.append(" ADD CONSTRAINT ");
239: result.append(pkName);
240: result.append(" PRIMARY KEY (");
241: for (int i = 0; i < columns.length; i++) {
242: result.append(columns[i].getColumnName());
243: if (i + 1 < columns.length) {
244: result.append(", ");
245: }
246: }
247: result.append(")");
248: return new String[] { result.toString() };
249: }
250:
251: /**
252: * Returns a boolean value indicating whether or not this dialect supports
253: * adding comments to columns.
254: *
255: * @return true if column comments are supported; false otherwise.
256: */
257: public boolean supportsColumnComment() {
258: return false;
259: }
260:
261: /**
262: * Returns the SQL statement to use to add a comment to the specified
263: * column of the specified table.
264: * @param info information about the column such as type, name, etc.
265: * @return
266: * @throws UnsupportedOperationException if the database doesn't support
267: * annotating columns with a comment.
268: */
269: public String getColumnCommentAlterSQL(TableColumnInfo info)
270: throws UnsupportedOperationException {
271: int featureId = DialectUtils.COLUMN_COMMENT_ALTER_TYPE;
272: String msg = DialectUtils
273: .getUnsupportedMessage(this , featureId);
274: throw new UnsupportedOperationException(msg);
275: }
276:
277: /**
278: * Returns a boolean value indicating whether or not this database dialect
279: * supports changing a column from null to not-null and vice versa.
280: *
281: * @return true if the database supports dropping columns; false otherwise.
282: */
283: public boolean supportsAlterColumnNull() {
284: // Firebird doesn't natively support altering a columns nullable
285: // property. Will have to simulate in a future release.
286: return false;
287: }
288:
289: /**
290: * Returns the SQL used to alter the specified column to not allow null
291: * values
292: *
293: * @param info the column to modify
294: * @return the SQL to execute
295: */
296: public String getColumnNullableAlterSQL(TableColumnInfo info) {
297: int featureId = DialectUtils.COLUMN_NULL_ALTER_TYPE;
298: String msg = DialectUtils
299: .getUnsupportedMessage(this , featureId);
300: throw new UnsupportedOperationException(msg);
301: }
302:
303: /**
304: * Returns a boolean value indicating whether or not this database dialect
305: * supports renaming columns.
306: *
307: * @return true if the database supports changing the name of columns;
308: * false otherwise.
309: */
310: public boolean supportsRenameColumn() {
311: return true;
312: }
313:
314: /**
315: * Returns the SQL that is used to change the column name.
316: *
317: * ALTER TABLE table ALTER [COLUMN] column_name TO new_col_name
318: *
319: * @param from the TableColumnInfo as it is
320: * @param to the TableColumnInfo as it wants to be
321: *
322: * @return the SQL to make the change
323: */
324: public String getColumnNameAlterSQL(TableColumnInfo from,
325: TableColumnInfo to) {
326: String alterClause = DialectUtils.ALTER_COLUMN_CLAUSE;
327: String renameToClause = DialectUtils.TO_CLAUSE;
328: return DialectUtils.getColumnNameAlterSQL(from, to,
329: alterClause, renameToClause);
330: }
331:
332: /**
333: * Returns a boolean value indicating whether or not this dialect supports
334: * modifying a columns type.
335: *
336: * @return true if supported; false otherwise
337: */
338: public boolean supportsAlterColumnType() {
339: return true;
340: }
341:
342: /**
343: * Returns the SQL that is used to change the column type.
344: *
345: * alter table table_name alter column column_name type varchar(10)
346: *
347: * @param from the TableColumnInfo as it is
348: * @param to the TableColumnInfo as it wants to be
349: *
350: * @return the SQL to make the change
351: * @throw UnsupportedOperationException if the database doesn't support
352: * modifying column types.
353: */
354: public List<String> getColumnTypeAlterSQL(TableColumnInfo from,
355: TableColumnInfo to) throws UnsupportedOperationException {
356: StringBuffer result = new StringBuffer();
357: result.append("ALTER TABLE ");
358: result.append(from.getTableName());
359: result.append(" ALTER COLUMN ");
360: result.append(from.getColumnName());
361: result.append(" TYPE ");
362: result.append(DialectUtils.getTypeName(to, this ));
363: ArrayList<String> list = new ArrayList<String>();
364: list.add(result.toString());
365: return list;
366: }
367:
368: /**
369: * Returns a boolean value indicating whether or not this database dialect
370: * supports changing a column's default value.
371: *
372: * @return true if the database supports modifying column defaults; false
373: * otherwise
374: */
375: public boolean supportsAlterColumnDefault() {
376: return false;
377: }
378:
379: /**
380: * Returns the SQL command to change the specified column's default value
381: *
382: * @param info the column to modify and it's default value.
383: * @return SQL to make the change
384: */
385: public String getColumnDefaultAlterSQL(TableColumnInfo info) {
386: int featureId = DialectUtils.COLUMN_DEFAULT_ALTER_TYPE;
387: String msg = DialectUtils
388: .getUnsupportedMessage(this , featureId);
389: throw new UnsupportedOperationException(msg);
390: }
391:
392: /**
393: * Returns the SQL command to drop the specified table's primary key.
394: *
395: * alter table table_name drop constraint pk_constraint_name
396: *
397: * @param pkName the name of the primary key that should be dropped
398: * @param tableName the name of the table whose primary key should be
399: * dropped
400: * @return
401: */
402: public String getDropPrimaryKeySQL(String pkName, String tableName) {
403: return DialectUtils.getDropPrimaryKeySQL(pkName, tableName,
404: true, false);
405: }
406:
407: /**
408: * Returns the SQL command to drop the specified table's foreign key
409: * constraint.
410: *
411: * @param fkName the name of the foreign key that should be dropped
412: * @param tableName the name of the table whose foreign key should be
413: * dropped
414: * @return
415: */
416: public String getDropForeignKeySQL(String fkName, String tableName) {
417: return DialectUtils.getDropForeignKeySQL(fkName, tableName);
418: }
419:
420: /**
421: * Returns the SQL command to create the specified table.
422: *
423: * @param tables the tables to get create statements for
424: * @param md the metadata from the ISession
425: * @param prefs preferences about how the resultant SQL commands should be
426: * formed.
427: * @param isJdbcOdbc whether or not the connection is via JDBC-ODBC bridge.
428: *
429: * @return the SQL that is used to create the specified table
430: */
431: public List<String> getCreateTableSQL(List<ITableInfo> tables,
432: ISQLDatabaseMetaData md, CreateScriptPreferences prefs,
433: boolean isJdbcOdbc) throws SQLException {
434: return DialectUtils.getCreateTableSQL(tables, md, this, prefs,
435: isJdbcOdbc);
436: }
437:
438: }
|