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