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