001: /*
002: * Created on Aug 24, 2005
003: * This is the Hibernate dialect for the Unisys 2200 Relational Database (RDMS).
004: * This dialect was developed for use with Hibernate 3.0.5. Other versions may
005: * require modifications to the dialect.
006: *
007: * Version History:
008: * Also change the version displayed below in the constructor
009: * 1.1
010: * 1.0 2005-10-24 CDH - First dated version for use with CP 11
011: */
012: package org.hibernate.dialect;
013:
014: import org.hibernate.dialect.function.NoArgSQLFunction;
015: import org.hibernate.dialect.function.StandardSQLFunction;
016: import org.hibernate.dialect.function.SQLFunctionTemplate;
017: import org.hibernate.dialect.lock.LockingStrategy;
018: import org.hibernate.dialect.lock.UpdateLockingStrategy;
019: import org.hibernate.dialect.lock.SelectLockingStrategy;
020:
021: import java.sql.Types;
022: import org.hibernate.Hibernate;
023: import org.hibernate.LockMode;
024: import org.hibernate.persister.entity.Lockable;
025: import org.hibernate.sql.CaseFragment;
026: import org.hibernate.sql.DecodeCaseFragment;
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029:
030: /**
031: * @author Ploski and Hanson
032: */
033: public class RDMSOS2200Dialect extends Dialect {
034: private static Log log = LogFactory.getLog(RDMSOS2200Dialect.class);
035:
036: public RDMSOS2200Dialect() {
037: super ();
038: // Display the dialect version.
039: log.info("RDMSOS2200Dialect version: 1.0");
040:
041: /**
042: * This section registers RDMS Biult-in Functions (BIFs) with Hibernate.
043: * The first parameter is the 'register' function name with Hibernate.
044: * The second parameter is the defined RDMS SQL Function and it's
045: * characteristics. If StandardSQLFunction(...) is used, the RDMS BIF
046: * name and the return type (if any) is specified. If
047: * SQLFunctionTemplate(...) is used, the return type and a template
048: * string is provided, plus an optional hasParenthesesIfNoArgs flag.
049: */
050: registerFunction("abs", new StandardSQLFunction("abs"));
051: registerFunction("sign", new StandardSQLFunction("sign",
052: Hibernate.INTEGER));
053:
054: registerFunction("ascii", new StandardSQLFunction("ascii",
055: Hibernate.INTEGER));
056: registerFunction("char_length", new StandardSQLFunction(
057: "char_length", Hibernate.INTEGER));
058: registerFunction("character_length", new StandardSQLFunction(
059: "character_length", Hibernate.INTEGER));
060: registerFunction("length", new StandardSQLFunction("length",
061: Hibernate.INTEGER));
062:
063: // The RDMS concat() function only supports 2 parameters
064: registerFunction("concat", new SQLFunctionTemplate(
065: Hibernate.STRING, "concat(?1, ?2)"));
066: registerFunction("instr", new StandardSQLFunction("instr",
067: Hibernate.STRING));
068: registerFunction("lpad", new StandardSQLFunction("lpad",
069: Hibernate.STRING));
070: registerFunction("replace", new StandardSQLFunction("replace",
071: Hibernate.STRING));
072: registerFunction("rpad", new StandardSQLFunction("rpad",
073: Hibernate.STRING));
074: registerFunction("substr", new StandardSQLFunction("substr",
075: Hibernate.STRING));
076:
077: registerFunction("lcase", new StandardSQLFunction("lcase"));
078: registerFunction("lower", new StandardSQLFunction("lower"));
079: registerFunction("ltrim", new StandardSQLFunction("ltrim"));
080: registerFunction("reverse", new StandardSQLFunction("reverse"));
081: registerFunction("rtrim", new StandardSQLFunction("rtrim"));
082:
083: // RDMS does not directly support the trim() function, we use rtrim() and ltrim()
084: registerFunction("trim", new SQLFunctionTemplate(
085: Hibernate.INTEGER, "ltrim(rtrim(?1))"));
086: registerFunction("soundex", new StandardSQLFunction("soundex"));
087: registerFunction("space", new StandardSQLFunction("space",
088: Hibernate.STRING));
089: registerFunction("ucase", new StandardSQLFunction("ucase"));
090: registerFunction("upper", new StandardSQLFunction("upper"));
091:
092: registerFunction("acos", new StandardSQLFunction("acos",
093: Hibernate.DOUBLE));
094: registerFunction("asin", new StandardSQLFunction("asin",
095: Hibernate.DOUBLE));
096: registerFunction("atan", new StandardSQLFunction("atan",
097: Hibernate.DOUBLE));
098: registerFunction("cos", new StandardSQLFunction("cos",
099: Hibernate.DOUBLE));
100: registerFunction("cosh", new StandardSQLFunction("cosh",
101: Hibernate.DOUBLE));
102: registerFunction("cot", new StandardSQLFunction("cot",
103: Hibernate.DOUBLE));
104: registerFunction("exp", new StandardSQLFunction("exp",
105: Hibernate.DOUBLE));
106: registerFunction("ln", new StandardSQLFunction("ln",
107: Hibernate.DOUBLE));
108: registerFunction("log", new StandardSQLFunction("log",
109: Hibernate.DOUBLE));
110: registerFunction("log10", new StandardSQLFunction("log10",
111: Hibernate.DOUBLE));
112: registerFunction("pi", new NoArgSQLFunction("pi",
113: Hibernate.DOUBLE));
114: registerFunction("rand", new NoArgSQLFunction("rand",
115: Hibernate.DOUBLE));
116: registerFunction("sin", new StandardSQLFunction("sin",
117: Hibernate.DOUBLE));
118: registerFunction("sinh", new StandardSQLFunction("sinh",
119: Hibernate.DOUBLE));
120: registerFunction("sqrt", new StandardSQLFunction("sqrt",
121: Hibernate.DOUBLE));
122: registerFunction("tan", new StandardSQLFunction("tan",
123: Hibernate.DOUBLE));
124: registerFunction("tanh", new StandardSQLFunction("tanh",
125: Hibernate.DOUBLE));
126:
127: registerFunction("round", new StandardSQLFunction("round"));
128: registerFunction("trunc", new StandardSQLFunction("trunc"));
129: registerFunction("ceil", new StandardSQLFunction("ceil"));
130: registerFunction("floor", new StandardSQLFunction("floor"));
131:
132: registerFunction("chr", new StandardSQLFunction("chr",
133: Hibernate.CHARACTER));
134: registerFunction("initcap", new StandardSQLFunction("initcap"));
135:
136: registerFunction("user", new NoArgSQLFunction("user",
137: Hibernate.STRING, false));
138:
139: registerFunction("current_date", new NoArgSQLFunction(
140: "current_date", Hibernate.DATE, false));
141: registerFunction("current_time", new NoArgSQLFunction(
142: "current_timestamp", Hibernate.TIME, false));
143: registerFunction("current_timestamp", new NoArgSQLFunction(
144: "current_timestamp", Hibernate.TIMESTAMP, false));
145: registerFunction("curdate", new NoArgSQLFunction("curdate",
146: Hibernate.DATE));
147: registerFunction("curtime", new NoArgSQLFunction("curtime",
148: Hibernate.TIME));
149: registerFunction("days", new StandardSQLFunction("days",
150: Hibernate.INTEGER));
151: registerFunction("dayofmonth", new StandardSQLFunction(
152: "dayofmonth", Hibernate.INTEGER));
153: registerFunction("dayname", new StandardSQLFunction("dayname",
154: Hibernate.STRING));
155: registerFunction("dayofweek", new StandardSQLFunction(
156: "dayofweek", Hibernate.INTEGER));
157: registerFunction("dayofyear", new StandardSQLFunction(
158: "dayofyear", Hibernate.INTEGER));
159: registerFunction("hour", new StandardSQLFunction("hour",
160: Hibernate.INTEGER));
161: registerFunction("last_day", new StandardSQLFunction(
162: "last_day", Hibernate.DATE));
163: registerFunction("microsecond", new StandardSQLFunction(
164: "microsecond", Hibernate.INTEGER));
165: registerFunction("minute", new StandardSQLFunction("minute",
166: Hibernate.INTEGER));
167: registerFunction("month", new StandardSQLFunction("month",
168: Hibernate.INTEGER));
169: registerFunction("monthname", new StandardSQLFunction(
170: "monthname", Hibernate.STRING));
171: registerFunction("now", new NoArgSQLFunction("now",
172: Hibernate.TIMESTAMP));
173: registerFunction("quarter", new StandardSQLFunction("quarter",
174: Hibernate.INTEGER));
175: registerFunction("second", new StandardSQLFunction("second",
176: Hibernate.INTEGER));
177: registerFunction("time", new StandardSQLFunction("time",
178: Hibernate.TIME));
179: registerFunction("timestamp", new StandardSQLFunction(
180: "timestamp", Hibernate.TIMESTAMP));
181: registerFunction("week", new StandardSQLFunction("week",
182: Hibernate.INTEGER));
183: registerFunction("year", new StandardSQLFunction("year",
184: Hibernate.INTEGER));
185:
186: registerFunction("atan2", new StandardSQLFunction("atan2",
187: Hibernate.DOUBLE));
188: registerFunction("mod", new StandardSQLFunction("mod",
189: Hibernate.INTEGER));
190: registerFunction("nvl", new StandardSQLFunction("nvl"));
191: registerFunction("power", new StandardSQLFunction("power",
192: Hibernate.DOUBLE));
193:
194: /**
195: * For a list of column types to register, see section A-1
196: * in 7862 7395, the Unisys JDBC manual.
197: *
198: * Here are column sizes as documented in Table A-1 of
199: * 7831 0760, "Enterprise Relational Database Server
200: * for ClearPath OS2200 Administration Guide"
201: * Numeric - 21
202: * Decimal - 22 (21 digits plus one for sign)
203: * Float - 60 bits
204: * Char - 28000
205: * NChar - 14000
206: * BLOB+ - 4294967296 (4 Gb)
207: * + RDMS JDBC driver does not support BLOBs
208: *
209: * DATE, TIME and TIMESTAMP literal formats are
210: * are all described in section 2.3.4 DATE Literal Format
211: * in 7830 8160.
212: * The DATE literal format is: YYYY-MM-DD
213: * The TIME literal format is: HH:MM:SS[.[FFFFFF]]
214: * The TIMESTAMP literal format is: YYYY-MM-DD HH:MM:SS[.[FFFFFF]]
215: *
216: * Note that $l (dollar-L) will use the length value if provided.
217: * Also new for Hibernate3 is the $p percision and $s (scale) parameters
218: */
219: registerColumnType(Types.BIT, "SMALLINT");
220: registerColumnType(Types.TINYINT, "SMALLINT");
221: registerColumnType(Types.BIGINT, "NUMERIC(21,0)");
222: registerColumnType(Types.SMALLINT, "SMALLINT");
223: registerColumnType(Types.CHAR, "CHARACTER(1)");
224: registerColumnType(Types.DOUBLE, "DOUBLE PRECISION");
225: registerColumnType(Types.FLOAT, "FLOAT");
226: registerColumnType(Types.REAL, "REAL");
227: registerColumnType(Types.INTEGER, "INTEGER");
228: registerColumnType(Types.NUMERIC, "NUMERIC(21,$l)");
229: registerColumnType(Types.DECIMAL, "NUMERIC(21,$l)");
230: registerColumnType(Types.DATE, "DATE");
231: registerColumnType(Types.TIME, "TIME");
232: registerColumnType(Types.TIMESTAMP, "TIMESTAMP");
233: registerColumnType(Types.VARCHAR, "CHARACTER($l)");
234: registerColumnType(Types.BLOB, "BLOB($l)");
235: /*
236: * The following types are not supported in RDMS/JDBC and therefore commented out.
237: * However, in some cases, mapping them to CHARACTER columns works
238: * for many applications, but does not work for all cases.
239: */
240: // registerColumnType(Types.VARBINARY, "CHARACTER($l)");
241: // registerColumnType(Types.BLOB, "CHARACTER($l)" ); // For use prior to CP 11.0
242: // registerColumnType(Types.CLOB, "CHARACTER($l)" );
243: }
244:
245: // Dialect method overrides ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
246:
247: /**
248: * RDMS does not support qualifing index names with the schema name.
249: */
250: public boolean qualifyIndexName() {
251: return false;
252: }
253:
254: /**
255: * The RDMS DB supports the 'FOR UPDATE OF' clause. However, the RDMS-JDBC
256: * driver does not support this feature, so a false is return.
257: * The base dialect also returns a false, but we will leave this over-ride
258: * in to make sure it stays false.
259: */
260: public boolean forUpdateOfColumns() {
261: return false;
262: }
263:
264: /**
265: * Since the RDMS-JDBC driver does not support for updates, this string is
266: * set to an empty string. Whenever, the driver does support this feature,
267: * the returned string should be " FOR UPDATE OF". Note that RDMS does not
268: * support the string 'FOR UPDATE' string.
269: */
270: public String getForUpdateString() {
271: return ""; // Original Dialect.java returns " for update";
272: }
273:
274: /**
275: * RDMS does not support adding Unique constraints via create and alter table.
276: */
277: public boolean supportsUniqueConstraintInCreateAlterTable() {
278: return true;
279: }
280:
281: // Verify the state of this new method in Hibernate 3.0 Dialect.java
282: /**
283: * RDMS does not support Cascade Deletes.
284: * Need to review this in the future when support is provided.
285: */
286: public boolean supportsCascadeDelete() {
287: return false; // Origial Dialect.java returns true;
288: }
289:
290: /**
291: * Currently, RDMS-JDBC does not support ForUpdate.
292: * Need to review this in the future when support is provided.
293: */
294: public boolean supportsOuterJoinForUpdate() {
295: return false;
296: }
297:
298: public String getAddColumnString() {
299: return "add";
300: }
301:
302: public String getNullColumnString() {
303: // The keyword used to specify a nullable column.
304: return " null";
305: }
306:
307: // *** Sequence methods - start. The RDMS dialect needs these
308:
309: // methods to make it possible to use the Native Id generator
310:
311: public boolean supportsSequences() {
312: return true;
313: }
314:
315: public String getSequenceNextValString(String sequenceName) {
316: // The where clause was added to eliminate this statement from Brute Force Searches.
317: return "select permuted_id('NEXT',31) from rdms.rdms_dummy where key_col = 1 ";
318: }
319:
320: public String getCreateSequenceString(String sequenceName) {
321: // We must return a valid RDMS/RSA command from this method to
322: // prevent RDMS/RSA from issuing *ERROR 400
323: return "";
324: }
325:
326: public String getDropSequenceString(String sequenceName) {
327: // We must return a valid RDMS/RSA command from this method to
328: // prevent RDMS/RSA from issuing *ERROR 400
329: return "";
330: }
331:
332: // *** Sequence methods - end
333:
334: public String getCascadeConstraintsString() {
335: // Used with DROP TABLE to delete all records in the table.
336: return " including contents";
337: }
338:
339: public CaseFragment createCaseFragment() {
340: return new DecodeCaseFragment();
341: }
342:
343: public boolean supportsLimit() {
344: return true;
345: }
346:
347: public boolean supportsLimitOffset() {
348: return false;
349: }
350:
351: public String getLimitString(String sql, int offset, int limit) {
352: if (offset > 0)
353: throw new UnsupportedOperationException(
354: "RDMS does not support paged queries");
355: return new StringBuffer(sql.length() + 40).append(sql).append(
356: " fetch first ").append(limit).append(" rows only ")
357: .toString();
358: }
359:
360: public boolean supportsVariableLimit() {
361: return false;
362: }
363:
364: public boolean supportsUnionAll() {
365: // RDMS supports the UNION ALL clause.
366: return true;
367: }
368:
369: public LockingStrategy getLockingStrategy(Lockable lockable,
370: LockMode lockMode) {
371: // RDMS has no known variation of a "SELECT ... FOR UPDATE" syntax...
372: if (lockMode.greaterThan(LockMode.READ)) {
373: return new UpdateLockingStrategy(lockable, lockMode);
374: } else {
375: return new SelectLockingStrategy(lockable, lockMode);
376: }
377: }
378: }
|