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