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