1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.spring.hibernate;
24  
25  import com.liferay.util.dao.DataAccess;
26  import com.liferay.util.dao.hibernate.DB2Dialect;
27  
28  import java.sql.CallableStatement;
29  import java.sql.Connection;
30  import java.sql.DatabaseMetaData;
31  import java.sql.ResultSet;
32  import java.sql.SQLException;
33  
34  import java.util.Enumeration;
35  import java.util.Map;
36  import java.util.Properties;
37  import java.util.Set;
38  
39  import org.apache.commons.logging.Log;
40  import org.apache.commons.logging.LogFactory;
41  
42  import org.hibernate.HibernateException;
43  import org.hibernate.LockMode;
44  import org.hibernate.MappingException;
45  import org.hibernate.dialect.DB2400Dialect;
46  import org.hibernate.dialect.Dialect;
47  import org.hibernate.dialect.DialectFactory;
48  import org.hibernate.dialect.SybaseDialect;
49  import org.hibernate.dialect.lock.LockingStrategy;
50  import org.hibernate.exception.SQLExceptionConverter;
51  import org.hibernate.exception.ViolatedConstraintNameExtracter;
52  import org.hibernate.persister.entity.Lockable;
53  import org.hibernate.sql.CaseFragment;
54  import org.hibernate.sql.JoinFragment;
55  
56  /**
57   * <a href="DynamicDialect.java.html"><b><i>View Source</i></b></a>
58   *
59   * @author Brian Wing Shun Chan
60   * @author Bruno Farache
61   *
62   */
63  public class DynamicDialect extends Dialect {
64  
65      public DynamicDialect() {
66  
67          // Instantiate the proper dialect
68  
69          Connection con = null;
70  
71          try {
72              con = HibernateUtil.getConnection();
73  
74              DatabaseMetaData metaData = con.getMetaData();
75  
76              String dbName = metaData.getDatabaseProductName();
77              int dbMajorVersion = metaData.getDatabaseMajorVersion();
78  
79              if (_log.isInfoEnabled()) {
80                  _log.info(
81                      "Determining dialect for " + dbName + " " + dbMajorVersion);
82              }
83  
84              if (dbName.startsWith("HSQL")) {
85                  if (_log.isWarnEnabled()) {
86                      _log.warn(
87                          "Liferay is configured to use Hypersonic as its " +
88                              "database. Do NOT use Hypersonic in production. " +
89                                  "Hypersonic is an embedded database useful " +
90                                      "for development and demo'ing purposes.");
91                  }
92              }
93  
94              if (dbName.equals("ASE") && (dbMajorVersion == 15)) {
95                  _dialect = new SybaseDialect();
96              }
97              else if (dbName.startsWith("DB2") && (dbMajorVersion == 9)){
98                  _dialect = new DB2Dialect();
99              }
100             else {
101                 _dialect = DialectFactory.determineDialect(
102                     dbName, dbMajorVersion);
103             }
104 
105             if (_log.isInfoEnabled()) {
106                 _log.info("Using dialect " + _dialect.getClass().getName());
107             }
108         }
109         catch (Exception e) {
110             String msg = e.getMessage();
111 
112             if (msg.indexOf("explicitly set for database: DB2") != -1) {
113                 _dialect = new DB2400Dialect();
114 
115                 if (_log.isWarnEnabled()) {
116                     _log.warn(
117                         "DB2400Dialect was dynamically chosen as the " +
118                             "Hibernate dialect for DB2. This can be " +
119                                 "overriden in portal.properties");
120                 }
121             }
122             else {
123                 _log.error(e, e);
124             }
125         }
126         finally {
127             DataAccess.cleanUp(con);
128         }
129 
130         if (_dialect == null) {
131             throw new RuntimeException("No dialect found");
132         }
133 
134         // Synchorize default properties
135 
136         Properties dynamicDefaultProps = getDefaultProperties();
137         Properties dialectDefaultProps = _dialect.getDefaultProperties();
138 
139         dynamicDefaultProps.clear();
140 
141         Enumeration<String> enu =
142             (Enumeration<String>)dialectDefaultProps.propertyNames();
143 
144         while (enu.hasMoreElements()) {
145             String key = enu.nextElement();
146 
147             String value = dialectDefaultProps.getProperty(key);
148 
149             dynamicDefaultProps.setProperty(key, value);
150         }
151     }
152 
153     public Dialect getWrappedDialect() {
154         return _dialect;
155     }
156 
157     public String appendIdentitySelectToInsert(String insertSQL) {
158         return _dialect.appendIdentitySelectToInsert(insertSQL);
159     }
160 
161     public String appendLockHint(LockMode mode, String tableName) {
162         return _dialect.appendLockHint(mode, tableName);
163     }
164 
165     public String applyLocksToSql(
166         String sql, Map aliasedLockModes, Map keyColumnNames) {
167 
168         return _dialect.applyLocksToSql(sql, aliasedLockModes, keyColumnNames);
169     }
170 
171     public boolean areStringComparisonsCaseInsensitive() {
172         return _dialect.areStringComparisonsCaseInsensitive();
173     }
174 
175     public boolean bindLimitParametersFirst() {
176         return _dialect.bindLimitParametersFirst();
177     }
178 
179     public boolean bindLimitParametersInReverseOrder() {
180         return _dialect.bindLimitParametersInReverseOrder();
181     }
182 
183     public SQLExceptionConverter buildSQLExceptionConverter() {
184         return _dialect.buildSQLExceptionConverter();
185     }
186 
187     public char closeQuote() {
188         return _dialect.closeQuote();
189     }
190 
191     public CaseFragment createCaseFragment() {
192         return _dialect.createCaseFragment();
193     }
194 
195     public JoinFragment createOuterJoinFragment() {
196         return _dialect.createOuterJoinFragment();
197     }
198 
199     public boolean doesReadCommittedCauseWritersToBlockReaders() {
200         return _dialect.doesReadCommittedCauseWritersToBlockReaders();
201     }
202 
203     public boolean doesRepeatableReadCauseReadersToBlockWriters() {
204         return _dialect.doesRepeatableReadCauseReadersToBlockWriters();
205     }
206 
207     public boolean dropConstraints() {
208         return _dialect.dropConstraints();
209     }
210 
211     public boolean dropTemporaryTableAfterUse() {
212         return _dialect.dropTemporaryTableAfterUse();
213     }
214 
215     public boolean forUpdateOfColumns() {
216         return _dialect.forUpdateOfColumns();
217     }
218 
219     public String generateTemporaryTableName(String baseTableName) {
220         return _dialect.generateTemporaryTableName(baseTableName);
221     }
222 
223     public String getAddColumnString() {
224         return _dialect.getAddColumnString();
225     }
226 
227     public String getAddForeignKeyConstraintString(
228         String constraintName, String[] foreignKey, String referencedTable,
229         String[] primaryKey, boolean referencesPrimaryKey) {
230 
231         return _dialect.getAddForeignKeyConstraintString(
232             constraintName, foreignKey, referencedTable, primaryKey,
233             referencesPrimaryKey);
234     }
235 
236     public String getAddPrimaryKeyConstraintString(String constraintName) {
237         return _dialect.getAddPrimaryKeyConstraintString(constraintName);
238     }
239 
240     public String getCascadeConstraintsString() {
241         return _dialect.getCascadeConstraintsString();
242     }
243 
244     public String getCastTypeName(int code) {
245         return _dialect.getCastTypeName(code);
246     }
247 
248     public String getColumnComment(String comment) {
249         return _dialect.getColumnComment(comment);
250     }
251 
252     public String getCreateMultisetTableString() {
253         return _dialect.getCreateMultisetTableString();
254     }
255 
256     /**
257      * @deprecated
258      */
259     public String[] getCreateSequenceStrings(String sequenceName)
260         throws MappingException {
261 
262         return _dialect.getCreateSequenceStrings(sequenceName);
263     }
264 
265     public String[] getCreateSequenceStrings(
266             String sequenceName, int initialValue, int incrementSize)
267         throws MappingException {
268 
269         return _dialect.getCreateSequenceStrings(
270             sequenceName, initialValue, incrementSize);
271     }
272 
273     public String getCreateTableString() {
274         return _dialect.getCreateTableString();
275     }
276 
277     public String getCreateTemporaryTablePostfix() {
278         return _dialect.getCreateTemporaryTablePostfix();
279     }
280 
281     public String getCreateTemporaryTableString() {
282         return _dialect.getCreateTemporaryTableString();
283     }
284 
285     public String getCurrentTimestampSelectString() {
286         return _dialect.getCurrentTimestampSelectString();
287     }
288 
289     public String getCurrentTimestampSQLFunctionName() {
290         return _dialect.getCurrentTimestampSQLFunctionName();
291     }
292 
293     public String getDropForeignKeyString() {
294         return _dialect.getDropForeignKeyString();
295     }
296 
297     public String[] getDropSequenceStrings(String sequenceName)
298         throws MappingException {
299 
300         return _dialect.getDropSequenceStrings(sequenceName);
301     }
302 
303     public String getForUpdateNowaitString() {
304         return _dialect.getForUpdateNowaitString();
305     }
306 
307     public String getForUpdateNowaitString(String aliases) {
308         return _dialect.getForUpdateNowaitString(aliases);
309     }
310 
311     public String getForUpdateString() {
312         return _dialect.getForUpdateString();
313     }
314 
315     public String getForUpdateString(LockMode lockMode) {
316         return _dialect.getForUpdateString(lockMode);
317     }
318 
319     public String getForUpdateString(String aliases) {
320         return _dialect.getForUpdateString(aliases);
321     }
322 
323     public String getHibernateTypeName(int code) throws HibernateException {
324         return _dialect.getHibernateTypeName(code);
325     }
326 
327     public String getHibernateTypeName(
328             int code, int length, int precision, int scale)
329         throws HibernateException {
330 
331         return _dialect.getHibernateTypeName(code, length, precision, scale);
332     }
333 
334     public String getIdentityColumnString(int type) throws MappingException {
335         return _dialect.getIdentityColumnString(type);
336     }
337 
338     public String getIdentityInsertString() {
339         return _dialect.getIdentityInsertString();
340     }
341 
342     public String getIdentitySelectString(String table, String column, int type)
343         throws MappingException {
344 
345         return _dialect.getIdentitySelectString(table, column, type);
346     }
347 
348     public Set<String> getKeywords() {
349         return _dialect.getKeywords();
350     }
351 
352     public String getLimitString(String querySelect, int hasOffset, int limit) {
353         return _dialect.getLimitString(querySelect, hasOffset, limit);
354     }
355 
356     public LockingStrategy getLockingStrategy(
357         Lockable lockable, LockMode lockMode) {
358 
359         return _dialect.getLockingStrategy(lockable, lockMode);
360     }
361 
362     public String getLowercaseFunction() {
363         return _dialect.getLowercaseFunction();
364     }
365 
366     public int getMaxAliasLength() {
367         return _dialect.getMaxAliasLength();
368     }
369 
370     public Class<?> getNativeIdentifierGeneratorClass() {
371         return _dialect.getNativeIdentifierGeneratorClass();
372     }
373 
374     public String getNoColumnsInsertString() {
375         return _dialect.getNoColumnsInsertString();
376     }
377 
378     public String getNullColumnString() {
379         return _dialect.getNullColumnString();
380     }
381 
382     public String getQuerySequencesString() {
383         return _dialect.getQuerySequencesString();
384     }
385 
386     public ResultSet getResultSet(CallableStatement ps) throws SQLException {
387         return _dialect.getResultSet(ps);
388     }
389 
390     public String getSelectClauseNullString(int sqlType) {
391         return _dialect.getSelectClauseNullString(sqlType);
392     }
393 
394     public String getSelectGUIDString() {
395         return _dialect.getSelectGUIDString();
396     }
397 
398     public String getSelectSequenceNextValString(String sequenceName)
399         throws MappingException {
400 
401         return _dialect.getSelectSequenceNextValString(sequenceName);
402     }
403 
404     public String getSequenceNextValString(String sequenceName)
405         throws MappingException {
406 
407         return _dialect.getSequenceNextValString(sequenceName);
408     }
409 
410     public String getTableComment(String comment) {
411         return _dialect.getTableComment(comment);
412     }
413 
414     public String getTableTypeString() {
415         return _dialect.getTableTypeString();
416     }
417 
418     public String getTypeName(int code) throws HibernateException {
419         return _dialect.getTypeName(code);
420     }
421 
422     public String getTypeName(int code, int length, int precision, int scale)
423         throws HibernateException {
424 
425         return _dialect.getTypeName(code, length, precision, scale);
426     }
427 
428     public ViolatedConstraintNameExtracter
429         getViolatedConstraintNameExtracter() {
430 
431         return _dialect.getViolatedConstraintNameExtracter();
432     }
433 
434     public boolean hasAlterTable() {
435         return _dialect.hasAlterTable();
436     }
437 
438     public boolean hasDataTypeInIdentityColumn() {
439         return _dialect.hasDataTypeInIdentityColumn();
440     }
441 
442     public boolean hasSelfReferentialForeignKeyBug() {
443         return _dialect.hasSelfReferentialForeignKeyBug();
444     }
445 
446     public boolean isCurrentTimestampSelectStringCallable() {
447         return _dialect.isCurrentTimestampSelectStringCallable();
448     }
449 
450     public char openQuote() {
451         return _dialect.openQuote();
452     }
453 
454     public Boolean performTemporaryTableDDLInIsolation() {
455         return _dialect.performTemporaryTableDDLInIsolation();
456     }
457 
458     public boolean qualifyIndexName() {
459         return _dialect.qualifyIndexName();
460     }
461 
462     public int registerResultSetOutParameter(
463             CallableStatement statement, int col)
464         throws SQLException {
465 
466         return _dialect.registerResultSetOutParameter(statement, col);
467     }
468 
469     public boolean supportsBindAsCallableArgument() {
470         return _dialect.supportsBindAsCallableArgument();
471     }
472 
473     public boolean supportsCascadeDelete() {
474         return _dialect.supportsCascadeDelete();
475     }
476 
477     public boolean supportsCircularCascadeDeleteConstraints() {
478         return _dialect.supportsCircularCascadeDeleteConstraints();
479     }
480 
481     public boolean supportsColumnCheck() {
482         return _dialect.supportsColumnCheck();
483     }
484 
485     public boolean supportsCommentOn() {
486         return _dialect.supportsCommentOn();
487     }
488 
489     public boolean supportsCurrentTimestampSelection() {
490         return _dialect.supportsCurrentTimestampSelection();
491     }
492 
493     public boolean supportsEmptyInList() {
494         return _dialect.supportsEmptyInList();
495     }
496 
497     public boolean supportsExistsInSelect() {
498         return _dialect.supportsExistsInSelect();
499     }
500 
501     public boolean supportsExpectedLobUsagePattern() {
502         return _dialect.supportsExpectedLobUsagePattern();
503     }
504 
505     public boolean supportsIdentityColumns() {
506         return _dialect.supportsIdentityColumns();
507     }
508 
509     public boolean supportsIfExistsAfterTableName() {
510         return _dialect.supportsIfExistsAfterTableName();
511     }
512 
513     public boolean supportsIfExistsBeforeTableName() {
514         return _dialect.supportsIfExistsBeforeTableName();
515     }
516 
517     public boolean supportsInsertSelectIdentity() {
518         return _dialect.supportsInsertSelectIdentity();
519     }
520 
521     public boolean supportsLimit() {
522         return _dialect.supportsLimit();
523     }
524 
525     public boolean supportsLimitOffset() {
526         return _dialect.supportsLimitOffset();
527     }
528 
529     public boolean supportsLobValueChangePropogation() {
530         return _dialect.supportsLobValueChangePropogation();
531     }
532 
533     public boolean supportsNotNullUnique() {
534         return _dialect.supportsNotNullUnique();
535     }
536 
537     public boolean supportsOuterJoinForUpdate() {
538         return _dialect.supportsOuterJoinForUpdate();
539     }
540 
541     public boolean supportsParametersInInsertSelect() {
542         return _dialect.supportsParametersInInsertSelect();
543     }
544 
545     public boolean supportsPooledSequences() {
546         return _dialect.supportsPooledSequences();
547     }
548 
549     public boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() {
550         return _dialect.
551             supportsResultSetPositionQueryMethodsOnForwardOnlyCursor();
552     }
553 
554     public boolean supportsRowValueConstructorSyntax() {
555         return _dialect.supportsRowValueConstructorSyntax();
556     }
557 
558     public boolean supportsRowValueConstructorSyntaxInInList() {
559         return _dialect.supportsRowValueConstructorSyntaxInInList();
560     }
561 
562     public boolean supportsSequences() {
563         return _dialect.supportsSequences();
564     }
565 
566     public boolean supportsSubqueryOnMutatingTable() {
567         return _dialect.supportsSubqueryOnMutatingTable();
568     }
569 
570     public boolean supportsSubselectAsInPredicateLHS() {
571         return _dialect.supportsSubselectAsInPredicateLHS();
572     }
573 
574     public boolean supportsTableCheck() {
575         return _dialect.supportsTableCheck();
576     }
577 
578     public boolean supportsTemporaryTables() {
579         return _dialect.supportsTemporaryTables();
580     }
581 
582     public boolean supportsUnboundedLobLocatorMaterialization() {
583         return _dialect.supportsUnboundedLobLocatorMaterialization();
584     }
585 
586     public boolean supportsUnionAll() {
587         return _dialect.supportsUnionAll();
588     }
589 
590     public boolean supportsUnique() {
591         return _dialect.supportsUnique();
592     }
593 
594     public boolean supportsUniqueConstraintInCreateAlterTable() {
595         return _dialect.supportsUniqueConstraintInCreateAlterTable();
596     }
597 
598     public boolean supportsVariableLimit() {
599         return _dialect.supportsVariableLimit();
600     }
601 
602     public String toBooleanValueString(boolean bool) {
603         return _dialect.toBooleanValueString(bool);
604     }
605 
606     public String toString() {
607         if (_dialect != null) {
608             return _dialect.toString();
609         }
610         else {
611             return null;
612         }
613     }
614 
615     public String transformSelectString(String select) {
616         return _dialect.transformSelectString(select);
617     }
618 
619     public boolean useInputStreamToInsertBlob() {
620         return _dialect.useInputStreamToInsertBlob();
621     }
622 
623     public boolean useMaxForLimit() {
624         return _dialect.useMaxForLimit();
625     }
626 
627     private static Log _log = LogFactory.getLog(DynamicDialect.class);
628 
629     private Dialect _dialect;
630 
631 }