1 package org.hibernate.dialect; 3 4 import java.sql.CallableStatement ; 5 import java.sql.ResultSet ; 6 import java.sql.SQLException ; 7 import java.sql.Types ; 8 import java.util.HashMap ; 9 import java.util.Map ; 10 import java.util.Properties ; 11 12 import org.apache.commons.logging.Log; 13 import org.apache.commons.logging.LogFactory; 14 import org.hibernate.Hibernate; 15 import org.hibernate.HibernateException; 16 import org.hibernate.LockMode; 17 import org.hibernate.MappingException; 18 import org.hibernate.QueryException; 19 import org.hibernate.cfg.Environment; 20 import org.hibernate.dialect.function.CastFunction; 21 import org.hibernate.dialect.function.SQLFunction; 22 import org.hibernate.dialect.function.SQLFunctionTemplate; 23 import org.hibernate.dialect.function.StandardSQLFunction; 24 import org.hibernate.engine.Mapping; 25 import org.hibernate.exception.SQLExceptionConverter; 26 import org.hibernate.exception.SQLStateConverter; 27 import org.hibernate.exception.ViolatedConstraintNameExtracter; 28 import org.hibernate.id.IdentityGenerator; 29 import org.hibernate.id.SequenceGenerator; 30 import org.hibernate.id.TableHiLoGenerator; 31 import org.hibernate.mapping.Column; 32 import org.hibernate.sql.ANSICaseFragment; 33 import org.hibernate.sql.ANSIJoinFragment; 34 import org.hibernate.sql.CaseFragment; 35 import org.hibernate.sql.JoinFragment; 36 import org.hibernate.type.Type; 37 import org.hibernate.util.ReflectHelper; 38 import org.hibernate.util.StringHelper; 39 40 51 public abstract class Dialect { 52 53 private static final Log log = LogFactory.getLog( Dialect.class ); 54 55 static final String DEFAULT_BATCH_SIZE = "15"; 56 static final String NO_BATCH = "0"; 57 58 private static final Map STANDARD_AGGREGATE_FUNCTIONS = new HashMap (); 59 60 static { 61 STANDARD_AGGREGATE_FUNCTIONS.put( "count", new StandardSQLFunction("count") { 62 public Type getReturnType(Type columnType, Mapping mapping) { 63 return Hibernate.INTEGER; 64 } 65 } ); 66 67 STANDARD_AGGREGATE_FUNCTIONS.put( "avg", new StandardSQLFunction("avg") { 68 public Type getReturnType(Type columnType, Mapping mapping) throws QueryException { 69 int[] sqlTypes; 70 try { 71 sqlTypes = columnType.sqlTypes( mapping ); 72 } 73 catch ( MappingException me ) { 74 throw new QueryException( me ); 75 } 76 if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in avg()" ); 77 int sqlType = sqlTypes[0]; 78 if ( sqlType == Types.INTEGER || sqlType == Types.BIGINT || sqlType == Types.TINYINT ) { 79 return Hibernate.FLOAT; 80 } 81 else { 82 return columnType; 83 } 84 } 85 } ); 86 87 STANDARD_AGGREGATE_FUNCTIONS.put( "max", new StandardSQLFunction("max") ); 88 STANDARD_AGGREGATE_FUNCTIONS.put( "min", new StandardSQLFunction("min") ); 89 STANDARD_AGGREGATE_FUNCTIONS.put( "sum", new StandardSQLFunction("sum") ); 90 } 91 92 protected Dialect() { 93 log.info( "Using dialect: " + this ); 94 sqlFunctions.putAll( STANDARD_AGGREGATE_FUNCTIONS ); 95 96 registerFunction( "substring", new SQLFunctionTemplate( Hibernate.STRING, "substring(?1, ?2, ?3)" ) ); 98 registerFunction( "locate", new SQLFunctionTemplate( Hibernate.INTEGER, "locate(?1, ?2, ?3)" ) ); 99 registerFunction( "trim", new SQLFunctionTemplate( Hibernate.STRING, "trim(?1 ?2 ?3 ?4)" ) ); 100 registerFunction( "length", new StandardSQLFunction( "length", Hibernate.INTEGER ) ); 101 registerFunction( "bit_length", new StandardSQLFunction( "bit_length", Hibernate.INTEGER ) ); 102 registerFunction( "coalesce", new StandardSQLFunction( "coalesce" ) ); 103 registerFunction( "nullif", new StandardSQLFunction( "nullif" ) ); 104 registerFunction( "abs", new StandardSQLFunction( "abs" ) ); 105 registerFunction( "mod", new StandardSQLFunction( "mod", Hibernate.INTEGER) ); 106 registerFunction( "sqrt", new StandardSQLFunction( "sqrt", Hibernate.DOUBLE) ); 107 registerFunction( "upper", new StandardSQLFunction("upper") ); 108 registerFunction( "lower", new StandardSQLFunction("lower") ); 109 registerFunction( "cast", new CastFunction() ); 110 registerFunction( "extract", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(?1 ?2 ?3)") ); 111 112 registerFunction( "second", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(second from ?1)") ); 114 registerFunction( "minute", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(minute from ?1)") ); 115 registerFunction( "hour", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(hour from ?1)") ); 116 registerFunction( "day", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(day from ?1)") ); 117 registerFunction( "month", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(month from ?1)") ); 118 registerFunction( "year", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(year from ?1)") ); 119 120 registerFunction( "str", new SQLFunctionTemplate(Hibernate.STRING, "cast(?1 as char)") ); 121 122 } 123 124 public String toString() { 125 return getClass().getName(); 126 } 127 128 private final TypeNames typeNames = new TypeNames(); 129 private final Properties properties = new Properties (); 130 private final Map sqlFunctions = new HashMap (); 131 132 135 public static final String QUOTE = "`\"["; 136 public static final String CLOSED_QUOTE = "`\"]"; 137 138 139 147 public String getTypeName(int code) throws HibernateException { 148 String result = typeNames.get( code ); 149 if ( result == null ) { 150 throw new HibernateException( "No default type mapping for (java.sql.Types) " + code ); 151 } 152 return result; 153 } 154 155 166 public String getTypeName(int code, int length, int precision, int scale) throws HibernateException { 167 String result = typeNames.get( code, length, precision, scale ); 168 if ( result == null ) { 169 throw new HibernateException( 170 "No type mapping for java.sql.Types code: " + 171 code + 172 ", length: " + 173 length 174 ); 175 } 176 return result; 177 } 178 179 public String getCastTypeName(int code) { 180 return getTypeName( 181 code, 182 Column.DEFAULT_LENGTH, 183 Column.DEFAULT_PRECISION, 184 Column.DEFAULT_SCALE 185 ); 186 } 187 188 protected void registerFunction(String name, SQLFunction function) { 189 sqlFunctions.put( name, function ); 190 } 191 192 201 protected void registerColumnType(int code, int capacity, String name) { 202 typeNames.put( code, capacity, name ); 203 } 204 205 212 protected void registerColumnType(int code, String name) { 213 typeNames.put( code, name ); 214 } 215 216 221 public boolean hasAlterTable() { 222 return true; 223 } 224 225 230 public boolean dropConstraints() { 231 return true; 232 } 233 234 239 public boolean qualifyIndexName() { 240 return true; 241 } 242 243 247 public boolean forUpdateOfColumns() { 248 return false; 249 } 250 251 256 public String getForUpdateString(String aliases) { 257 return getForUpdateString(); 258 } 259 260 266 public String getForUpdateNowaitString(String aliases) { 267 return getForUpdateString( aliases ); 268 } 269 270 275 public String getForUpdateString() { 276 return " for update"; 277 } 278 279 284 public String getForUpdateNowaitString() { 285 return getForUpdateString(); 286 } 287 288 293 public boolean supportsUnique() { 294 return true; 295 } 296 297 298 302 public boolean supportsUniqueConstraintInCreateAlterTable() { 303 return true; 304 } 305 306 307 310 public String getAddColumnString() { 311 throw new UnsupportedOperationException ( "No add column syntax supported by Dialect" ); 312 } 313 314 public String getDropForeignKeyString() { 315 return " drop constraint "; 316 } 317 318 public String getTableTypeString() { 319 return ""; 320 } 321 322 330 public String getAddForeignKeyConstraintString( 331 String constraintName, 332 String [] foreignKey, 333 String referencedTable, 334 String [] primaryKey, 335 boolean referencesPrimaryKey 336 ) { 337 StringBuffer res = new StringBuffer ( 30 ); 338 339 res.append( " add constraint " ) 340 .append( constraintName ) 341 .append( " foreign key (" ) 342 .append( StringHelper.join( ", ", foreignKey ) ) 343 .append( ") references " ) 344 .append( referencedTable ); 345 346 if(!referencesPrimaryKey) { 347 res.append(" (") 348 .append( StringHelper.join(", ", primaryKey) ) 349 .append(')'); 350 } 351 352 return res.toString(); 353 } 354 355 360 public String getAddPrimaryKeyConstraintString(String constraintName) { 361 return " add constraint " + constraintName + " primary key "; 362 } 363 364 369 public String getNullColumnString() { 370 return ""; 371 } 372 373 378 public boolean supportsIdentityColumns() { 379 return false; 380 } 381 382 387 public boolean supportsSequences() { 388 return false; 389 } 390 391 public boolean supportsInsertSelectIdentity() { 392 return false; 393 } 394 395 399 public String appendIdentitySelectToInsert(String insertString) { 400 return insertString; 401 } 402 403 protected String getIdentitySelectString() throws MappingException { 404 throw new MappingException( "Dialect does not support identity key generation" ); 405 } 406 407 414 public String getIdentitySelectString(String table, String column, int type) 415 throws MappingException { 416 return getIdentitySelectString(); 417 } 418 419 protected String getIdentityColumnString() throws MappingException { 420 throw new MappingException( "Dialect does not support identity key generation" ); 421 } 422 423 430 public String getIdentityColumnString(int type) throws MappingException { 431 return getIdentityColumnString(); 432 } 433 434 439 public String getIdentityInsertString() { 440 return null; 441 } 442 443 446 public String getNoColumnsInsertString() { 447 return "values ( )"; 448 } 449 450 460 public String getSequenceNextValString(String sequenceName) throws MappingException { 461 throw new MappingException( "Dialect does not support sequences" ); 462 } 463 464 475 public String getSelectSequenceNextValString(String sequenceName) throws MappingException { 476 throw new MappingException( "Dialect does not support sequences" ); 477 } 478 479 486 protected String getCreateSequenceString(String sequenceName) throws MappingException { 487 throw new MappingException( "Dialect does not support sequences" ); 488 } 489 490 497 public String [] getCreateSequenceStrings(String sequenceName) throws MappingException { 498 return new String []{getCreateSequenceString( sequenceName )}; 499 } 500 501 508 protected String getDropSequenceString(String sequenceName) throws MappingException { 509 throw new MappingException( "Dialect does not support sequences" ); 510 } 511 512 519 public String [] getDropSequenceStrings(String sequenceName) throws MappingException { 520 return new String []{getDropSequenceString( sequenceName )}; 521 } 522 523 528 public String getQuerySequencesString() { 529 return null; 530 } 531 532 538 public static Dialect getDialect() throws HibernateException { 539 String dialectName = Environment.getProperties().getProperty( Environment.DIALECT ); 540 if ( dialectName == null ) throw new HibernateException( "The dialect was not set. Set the property hibernate.dialect." ); 541 try { 542 return ( Dialect ) ReflectHelper.classForName( dialectName ).newInstance(); 543 } 544 catch ( ClassNotFoundException cnfe ) { 545 throw new HibernateException( "Dialect class not found: " + dialectName ); 546 } 547 catch ( Exception e ) { 548 throw new HibernateException( "Could not instantiate dialect class", e ); 549 } 550 } 551 552 553 560 public static Dialect getDialect(Properties props) throws HibernateException { 561 String dialectName = props.getProperty( Environment.DIALECT ); 562 if ( dialectName == null ) return getDialect(); 563 try { 564 return ( Dialect ) ReflectHelper.classForName( dialectName ).newInstance(); 565 } 566 catch ( ClassNotFoundException cnfe ) { 567 throw new HibernateException( "Dialect class not found: " + dialectName ); 568 } 569 catch ( Exception e ) { 570 throw new HibernateException( "Could not instantiate dialect class", e ); 571 } 572 } 573 574 579 public final Properties getDefaultProperties() { 580 return properties; 581 } 582 583 588 public String getCascadeConstraintsString() { 589 return ""; 590 } 591 592 597 public JoinFragment createOuterJoinFragment() { 598 return new ANSIJoinFragment(); 599 } 600 601 606 public CaseFragment createCaseFragment() { 607 return new ANSICaseFragment(); 608 } 609 610 616 public String getLowercaseFunction() { 617 return "lower"; 618 } 619 620 623 public boolean supportsLimit() { 624 return false; 625 } 626 627 630 public boolean supportsLimitOffset() { 631 return supportsLimit(); 632 } 633 634 639 public String getLimitString(String querySelect, boolean hasOffset) { 640 throw new UnsupportedOperationException ( "paged queries not supported" ); 641 } 642 643 public String getLimitString(String querySelect, int offset, int limit) { 644 return getLimitString( querySelect, offset>0 ); 645 } 646 647 public boolean supportsVariableLimit() { 648 return supportsLimit(); 649 } 650 651 657 public boolean bindLimitParametersInReverseOrder() { 658 return false; 659 } 660 661 667 public boolean bindLimitParametersFirst() { 668 return false; 669 } 670 671 675 public boolean useMaxForLimit() { 676 return false; 677 } 678 679 682 public char openQuote() { 683 return '"'; 684 } 685 686 689 public char closeQuote() { 690 return '"'; 691 } 692 693 697 public final Map getFunctions() { 698 return sqlFunctions; 699 } 700 701 public boolean supportsIfExistsBeforeTableName() { 702 return false; 703 } 704 705 public boolean supportsIfExistsAfterTableName() { 706 return false; 707 } 708 709 712 public char getSchemaSeparator() { 713 return '.'; 714 } 715 716 719 public boolean supportsColumnCheck() { 720 return true; 721 } 722 723 726 public boolean supportsTableCheck() { 727 return true; 728 } 729 730 736 public boolean hasDataTypeInIdentityColumn() { 737 return true; 738 } 739 740 public boolean supportsCascadeDelete() { 741 return true; 742 } 743 744 757 public String appendLockHint(LockMode mode, String tableName) { 758 return tableName; 759 } 760 761 public Class getNativeIdentifierGeneratorClass() { 762 if ( supportsIdentityColumns() ) { 763 return IdentityGenerator.class; 764 } 765 else if ( supportsSequences() ) { 766 return SequenceGenerator.class; 767 } 768 else { 769 return TableHiLoGenerator.class; 770 } 771 } 772 773 public String getSelectGUIDString() { 774 throw new UnsupportedOperationException ( "dialect does not support GUIDs" ); 775 } 776 777 public boolean supportsOuterJoinForUpdate() { 778 return true; 779 } 780 781 public String getSelectClauseNullString(int sqlType) { 782 return "null"; 783 } 784 785 public boolean supportsNotNullUnique() { 786 return true; 787 } 788 789 801 public SQLExceptionConverter buildSQLExceptionConverter() { 802 return new SQLStateConverter( getViolatedConstraintNameExtracter() ); 806 } 807 808 private static final ViolatedConstraintNameExtracter EXTRACTER = new ViolatedConstraintNameExtracter() { 809 public String extractConstraintName(SQLException sqle) { 810 return null; 811 } 812 }; 813 814 public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() { 815 return EXTRACTER; 816 } 817 818 public final String quote(String column) { 819 if ( column.charAt( 0 ) == '`' ) { 820 return openQuote() + column.substring( 1, column.length() - 1 ) + closeQuote(); 821 } 822 else { 823 return column; 824 } 825 } 826 827 public boolean hasSelfReferentialForeignKeyBug() { 828 return false; 829 } 830 831 832 public boolean useInputStreamToInsertBlob() { 833 return true; 834 } 835 836 public int registerResultSetOutParameter(CallableStatement statement, int col) throws SQLException { 837 throw new UnsupportedOperationException ( 838 getClass().getName() + 839 " does not support resultsets via stored procedures" 840 ); 841 } 842 843 public ResultSet getResultSet(CallableStatement ps) throws SQLException { 844 throw new UnsupportedOperationException ( 845 getClass().getName() + 846 " does not support resultsets via stored procedures" 847 ); 848 } 849 850 public boolean supportsUnionAll() { 851 return false; 852 } 853 854 public boolean supportsCommentOn() { 855 return false; 856 } 857 858 public String getTableComment(String comment) { 859 return ""; 860 } 861 862 public String getColumnComment(String comment) { 863 return ""; 864 } 865 866 public String transformSelectString(String select) { 867 return select; 868 } 869 870 public boolean supportsTemporaryTables() { 871 return false; 872 } 873 874 public String generateTemporaryTableName(String baseTableName) { 875 return "HT_" + baseTableName; 876 } 877 878 public String getTemporaryTableCreationCommand() { 879 return ""; 880 } 881 882 public String getTemporaryTableCreationPostfix() { 883 return ""; 884 } 885 886 public boolean dropTemporaryTableAfterUse() { 887 return true; 888 } 889 890 public String getForUpdateString(LockMode lockMode) { 891 if ( lockMode==LockMode.UPGRADE ) { 892 return getForUpdateString(); 893 } 894 else if ( lockMode==LockMode.UPGRADE_NOWAIT ) { 895 return getForUpdateNowaitString(); 896 } 897 else { 898 return ""; 899 } 900 } 901 902 public int getMaxAliasLength() { 903 return 10; 904 } 905 } 906 | Popular Tags |