HHH-9768 - Maintain explicit list of ANSI SQL keywords

This commit is contained in:
Steve Ebersole 2015-05-01 10:50:29 -05:00
parent 7569355ad8
commit 5c88ccec5c
4 changed files with 323 additions and 17 deletions

View File

@ -26,6 +26,7 @@ package org.hibernate.engine.jdbc.env.internal;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
@ -37,6 +38,8 @@ import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.env.spi.SQLStateType;
import org.hibernate.engine.jdbc.spi.TypeInfo;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Collection;
/**
* Standard implementation of ExtractedDatabaseMetaData
@ -213,10 +216,12 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
}
private Set<String> parseKeywords(String extraKeywordsString) {
final Set<String> keywordSet = new HashSet<String>();
for ( String keyword : extraKeywordsString.split( "," ) ) {
keywordSet.add( keyword.toUpperCase(Locale.ROOT) );
if ( StringHelper.isEmpty( extraKeywordsString ) ) {
return Collections.emptySet();
}
final Set<String> keywordSet = new HashSet<String>();
keywordSet.addAll( Arrays.asList( extraKeywordsString.split( "\\s*,\\s*" ) ) );
return keywordSet;
}

View File

@ -30,6 +30,7 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
@ -37,6 +38,7 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.env.spi.AnsiSqlKeywords;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
@ -67,8 +69,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
private final LobCreatorBuilderImpl lobCreatorBuilder;
private final LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();
// todo : should really maintain a standard list of know ANSI-SQL defined keywords somewhere (currently rely on Dialect)
private final Set<String> reservedWords = new HashSet<String>();
private final Set<String> reservedWords = new TreeSet<String>( String.CASE_INSENSITIVE_ORDER );
/**
* Constructor form used when the JDBC {@link java.sql.DatabaseMetaData} is not available.
@ -88,9 +89,8 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
this.sqlExceptionHelper = buildSqlExceptionHelper( dialect );
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this ).build();
for ( String keyword : dialect.getKeywords() ) {
reservedWords.add( keyword.toUpperCase(Locale.ROOT) );
}
reservedWords.addAll( AnsiSqlKeywords.INSTANCE.sql2003() );
reservedWords.addAll( dialect.getKeywords() );
final boolean globallyQuoteIdentifiers = serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.GLOBALLY_QUOTED_IDENTIFIERS, StandardConverters.BOOLEAN, false );
@ -142,10 +142,8 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
nameQualifierSupport = determineNameQualifierSupport( databaseMetaData );
}
for ( String keyword : dialect.getKeywords() ) {
reservedWords.add( keyword.toUpperCase(Locale.ROOT) );
}
// ExtractedMetaDataSupport already capitalizes them
reservedWords.addAll( AnsiSqlKeywords.INSTANCE.sql2003() );
reservedWords.addAll( dialect.getKeywords() );
reservedWords.addAll( extractedMetaDataSupport.getExtraKeywords() );
final boolean globallyQuoteIdentifiers = false;
@ -219,10 +217,8 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
nameQualifierSupport = determineNameQualifierSupport( databaseMetaData );
}
for ( String keyword : dialect.getKeywords() ) {
reservedWords.add( keyword.toUpperCase(Locale.ROOT) );
}
// ExtractedMetaDataSupport already capitalizes them
reservedWords.addAll( AnsiSqlKeywords.INSTANCE.sql2003() );
reservedWords.addAll( dialect.getKeywords() );
reservedWords.addAll( extractedMetaDataSupport.getExtraKeywords() );
final boolean globallyQuoteIdentifiers = serviceRegistry.getService( ConfigurationService.class )
@ -336,7 +332,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
@Override
public boolean isReservedWord(String word) {
return reservedWords.contains( word.toUpperCase(Locale.ROOT) );
return reservedWords.contains( word );
}
@Override

View File

@ -0,0 +1,304 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Maintains the set of ANSI SQL keywords
*
* @author Steve Ebersole
*/
public class AnsiSqlKeywords {
/**
* Singleton access
*/
public static final AnsiSqlKeywords INSTANCE = new AnsiSqlKeywords();
private final Set<String> keywordsSql2003;
public AnsiSqlKeywords() {
final Set<String> keywordsSql2003 = new HashSet<String>();
keywordsSql2003.add( "ADD" );
keywordsSql2003.add( "ALL" );
keywordsSql2003.add( "ALLOCATE" );
keywordsSql2003.add( "ALTER" );
keywordsSql2003.add( "AND" );
keywordsSql2003.add( "ANY" );
keywordsSql2003.add( "ARE" );
keywordsSql2003.add( "ARRAY" );
keywordsSql2003.add( "AS" );
keywordsSql2003.add( "ASENSITIVE" );
keywordsSql2003.add( "ASYMMETRIC" );
keywordsSql2003.add( "AT" );
keywordsSql2003.add( "ATOMIC" );
keywordsSql2003.add( "AUTHORIZATION" );
keywordsSql2003.add( "BEGIN" );
keywordsSql2003.add( "BETWEEN" );
keywordsSql2003.add( "BIGINT" );
keywordsSql2003.add( "BINARY" );
keywordsSql2003.add( "BLOB" );
keywordsSql2003.add( "BINARY" );
keywordsSql2003.add( "BOTH" );
keywordsSql2003.add( "BY" );
keywordsSql2003.add( "CALL" );
keywordsSql2003.add( "CALLED" );
keywordsSql2003.add( "CASCADED" );
keywordsSql2003.add( "CASE" );
keywordsSql2003.add( "CAST" );
keywordsSql2003.add( "CHAR" );
keywordsSql2003.add( "CHARACTER" );
keywordsSql2003.add( "CHECK" );
keywordsSql2003.add( "CLOB" );
keywordsSql2003.add( "CLOB" );
keywordsSql2003.add( "CLOSE" );
keywordsSql2003.add( "COLLATE" );
keywordsSql2003.add( "COLUMN" );
keywordsSql2003.add( "COMMIT" );
keywordsSql2003.add( "CONDITION" );
keywordsSql2003.add( "CONNECT" );
keywordsSql2003.add( "CONSTRAINT" );
keywordsSql2003.add( "CONTINUE" );
keywordsSql2003.add( "CORRESPONDING" );
keywordsSql2003.add( "CREATE" );
keywordsSql2003.add( "CROSS" );
keywordsSql2003.add( "CUBE" );
keywordsSql2003.add( "CURRENT" );
keywordsSql2003.add( "CURRENT_DATE" );
keywordsSql2003.add( "CURRENT_PATH" );
keywordsSql2003.add( "CURRENT_ROLE" );
keywordsSql2003.add( "CURRENT_TIME" );
keywordsSql2003.add( "CURRENT_TIMESTAMP" );
keywordsSql2003.add( "CURRENT_USER" );
keywordsSql2003.add( "CURSOR" );
keywordsSql2003.add( "CYCLE" );
keywordsSql2003.add( "DATE" );
keywordsSql2003.add( "DAY" );
keywordsSql2003.add( "DEALLOCATE" );
keywordsSql2003.add( "DEC" );
keywordsSql2003.add( "DECIMAL" );
keywordsSql2003.add( "DECLARE" );
keywordsSql2003.add( "DEFAULT" );
keywordsSql2003.add( "DELETE" );
keywordsSql2003.add( "DEREF" );
keywordsSql2003.add( "DESCRIBE" );
keywordsSql2003.add( "DETERMINISTIC" );
keywordsSql2003.add( "DISCONNECT" );
keywordsSql2003.add( "DISTINCT" );
keywordsSql2003.add( "DO" );
keywordsSql2003.add( "DOUBLE" );
keywordsSql2003.add( "DROP" );
keywordsSql2003.add( "DYNAMIC" );
keywordsSql2003.add( "EACH" );
keywordsSql2003.add( "ELEMENT" );
keywordsSql2003.add( "ELSE" );
keywordsSql2003.add( "ELSIF" );
keywordsSql2003.add( "END" );
keywordsSql2003.add( "ESCAPE" );
keywordsSql2003.add( "EXCEPT" );
keywordsSql2003.add( "EXEC" );
keywordsSql2003.add( "EXECUTE" );
keywordsSql2003.add( "EXISTS" );
keywordsSql2003.add( "EXIT" );
keywordsSql2003.add( "EXTERNAL" );
keywordsSql2003.add( "FALSE" );
keywordsSql2003.add( "FETCH" );
keywordsSql2003.add( "FILTER" );
keywordsSql2003.add( "FLOAT" );
keywordsSql2003.add( "FOR" );
keywordsSql2003.add( "FOREIGN" );
keywordsSql2003.add( "FREE" );
keywordsSql2003.add( "FROM" );
keywordsSql2003.add( "FULL" );
keywordsSql2003.add( "FUNCTION" );
keywordsSql2003.add( "GET" );
keywordsSql2003.add( "GLOBAL" );
keywordsSql2003.add( "GRANT" );
keywordsSql2003.add( "GROUP" );
keywordsSql2003.add( "GROUPING" );
keywordsSql2003.add( "HANDLER" );
keywordsSql2003.add( "HAVING" );
keywordsSql2003.add( "HOLD" );
keywordsSql2003.add( "HOUR" );
keywordsSql2003.add( "IDENTITY" );
keywordsSql2003.add( "IF" );
keywordsSql2003.add( "IMMEDIATE" );
keywordsSql2003.add( "IN" );
keywordsSql2003.add( "INDICATOR" );
keywordsSql2003.add( "INNER" );
keywordsSql2003.add( "INOUT" );
keywordsSql2003.add( "INPUT" );
keywordsSql2003.add( "INSENSITIVE" );
keywordsSql2003.add( "INSERT" );
keywordsSql2003.add( "INT" );
keywordsSql2003.add( "INTEGER" );
keywordsSql2003.add( "INTERSECT" );
keywordsSql2003.add( "INTERVAL" );
keywordsSql2003.add( "INTO" );
keywordsSql2003.add( "IS" );
keywordsSql2003.add( "ITERATE" );
keywordsSql2003.add( "JOIN" );
keywordsSql2003.add( "LANGUAGE" );
keywordsSql2003.add( "LARGE" );
keywordsSql2003.add( "LATERAL" );
keywordsSql2003.add( "LEADING" );
keywordsSql2003.add( "LEAVE" );
keywordsSql2003.add( "LEFT" );
keywordsSql2003.add( "LIKE" );
keywordsSql2003.add( "LOCAL" );
keywordsSql2003.add( "LOCALTIME" );
keywordsSql2003.add( "LOCALTIMESTAMP" );
keywordsSql2003.add( "LOOP" );
keywordsSql2003.add( "MATCH" );
keywordsSql2003.add( "MEMBER" );
keywordsSql2003.add( "MERGE" );
keywordsSql2003.add( "METHOD" );
keywordsSql2003.add( "MINUTE" );
keywordsSql2003.add( "MODIFIES" );
keywordsSql2003.add( "MODULE" );
keywordsSql2003.add( "MONTH" );
keywordsSql2003.add( "MULTISET" );
keywordsSql2003.add( "NATIONAL" );
keywordsSql2003.add( "NATURAL" );
keywordsSql2003.add( "NCHAR" );
keywordsSql2003.add( "NCLOB" );
keywordsSql2003.add( "NEW" );
keywordsSql2003.add( "NO" );
keywordsSql2003.add( "NONE" );
keywordsSql2003.add( "NOT" );
keywordsSql2003.add( "NULL" );
keywordsSql2003.add( "NUMERIC" );
keywordsSql2003.add( "OF" );
keywordsSql2003.add( "OLD" );
keywordsSql2003.add( "ON" );
keywordsSql2003.add( "ONLY" );
keywordsSql2003.add( "OPEN" );
keywordsSql2003.add( "OR" );
keywordsSql2003.add( "ORDER" );
keywordsSql2003.add( "OUT" );
keywordsSql2003.add( "OUTER" );
keywordsSql2003.add( "OUTPUT" );
keywordsSql2003.add( "OVER" );
keywordsSql2003.add( "OVERLAPS" );
keywordsSql2003.add( "PARAMETER" );
keywordsSql2003.add( "PARTITION" );
keywordsSql2003.add( "PRECISION" );
keywordsSql2003.add( "PREPARE" );
keywordsSql2003.add( "PRIMARY" );
keywordsSql2003.add( "PROCEDURE" );
keywordsSql2003.add( "RANGE" );
keywordsSql2003.add( "READS" );
keywordsSql2003.add( "REAL" );
keywordsSql2003.add( "RECURSIVE" );
keywordsSql2003.add( "REF" );
keywordsSql2003.add( "REFERENCES" );
keywordsSql2003.add( "REFERENCING" );
keywordsSql2003.add( "RELEASE" );
keywordsSql2003.add( "REPEAT" );
keywordsSql2003.add( "RESIGNAL" );
keywordsSql2003.add( "RESULT" );
keywordsSql2003.add( "RETURN" );
keywordsSql2003.add( "RETURNS" );
keywordsSql2003.add( "REVOKE" );
keywordsSql2003.add( "RIGHT" );
keywordsSql2003.add( "ROLLBACK" );
keywordsSql2003.add( "ROLLUP" );
keywordsSql2003.add( "ROW" );
keywordsSql2003.add( "ROWS" );
keywordsSql2003.add( "SAVEPOINT" );
keywordsSql2003.add( "SCROLL" );
keywordsSql2003.add( "SEARCH" );
keywordsSql2003.add( "SECOND" );
keywordsSql2003.add( "SELECT" );
keywordsSql2003.add( "SENSITIVE" );
keywordsSql2003.add( "SESSION_USE" );
keywordsSql2003.add( "SET" );
keywordsSql2003.add( "SIGNAL" );
keywordsSql2003.add( "SIMILAR" );
keywordsSql2003.add( "SMALLINT" );
keywordsSql2003.add( "SOME" );
keywordsSql2003.add( "SPECIFIC" );
keywordsSql2003.add( "SPECIFICTYPE" );
keywordsSql2003.add( "SQL" );
keywordsSql2003.add( "SQLEXCEPTION" );
keywordsSql2003.add( "SQLSTATE" );
keywordsSql2003.add( "SQLWARNING" );
keywordsSql2003.add( "START" );
keywordsSql2003.add( "STATIC" );
keywordsSql2003.add( "SUBMULTISET" );
keywordsSql2003.add( "SYMMETRIC" );
keywordsSql2003.add( "SYSTEM" );
keywordsSql2003.add( "SYSTEM_USER" );
keywordsSql2003.add( "TABLE" );
keywordsSql2003.add( "TABLESAMPLE" );
keywordsSql2003.add( "THEN" );
keywordsSql2003.add( "TIME" );
keywordsSql2003.add( "TIMESTAMP" );
keywordsSql2003.add( "TIMEZONE_HOUR" );
keywordsSql2003.add( "TIMEZONE_MINUTE" );
keywordsSql2003.add( "TO" );
keywordsSql2003.add( "TRAILING" );
keywordsSql2003.add( "TRANSLATION" );
keywordsSql2003.add( "TREAT" );
keywordsSql2003.add( "TRIGGER" );
keywordsSql2003.add( "TRUE" );
keywordsSql2003.add( "UNDO" );
keywordsSql2003.add( "UNION" );
keywordsSql2003.add( "UNIQUE" );
keywordsSql2003.add( "UNKNOWN" );
keywordsSql2003.add( "UNNEST" );
keywordsSql2003.add( "UNTIL" );
keywordsSql2003.add( "UPDATE" );
keywordsSql2003.add( "USER" );
keywordsSql2003.add( "USING" );
keywordsSql2003.add( "VALUE" );
keywordsSql2003.add( "VALUES" );
keywordsSql2003.add( "VARCHAR" );
keywordsSql2003.add( "VARYING" );
keywordsSql2003.add( "WHEN" );
keywordsSql2003.add( "WHENEVER" );
keywordsSql2003.add( "WHERE" );
keywordsSql2003.add( "WHILE" );
keywordsSql2003.add( "WINDOW" );
keywordsSql2003.add( "WITH" );
keywordsSql2003.add( "WITHIN" );
keywordsSql2003.add( "WITHOUT" );
keywordsSql2003.add( "YEAR" );
this.keywordsSql2003 = Collections.unmodifiableSet( keywordsSql2003 );
}
/**
* Retrieve all keywords defined by ANSI SQL:2003
*
* @return ANSI SQL:2003 keywords
*/
public Set<String> sql2003() {
return keywordsSql2003;
}
}

View File

@ -84,6 +84,7 @@ ext {
//Maven plugin framework
maven_plugin: 'org.apache.maven:maven-plugin-api:3.0.5',
maven_plugin_tools: 'org.apache.maven.plugin-tools:maven-plugin-annotations:3.2',
maven_plugin_tools: 'org.apache.maven.plugin-tools:maven-plugin-annotations:3.2',
// ~~~~~~~~~~~~~~~~~~~~~~~~~~ testing