HHH-15665 - Fix and added test for issue
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
1078caa19f
commit
38ec412e61
|
@ -75,6 +75,64 @@ public class Identifier implements Comparable<Identifier> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Means to generate an {@link Identifier} instance from its simple text form.
|
||||
* <p>
|
||||
* If passed text is {@code null}, {@code null} is returned.
|
||||
* <p>
|
||||
* If passed text is surrounded in quote markers, the generated Identifier
|
||||
* is considered quoted. Quote markers include back-ticks (`),
|
||||
* double-quotes (") and brackets ([ and ]).
|
||||
*
|
||||
* @param text The text form
|
||||
* @param quote Whether to quote unquoted text forms
|
||||
* @param quoteOnNonIdentifierChar Controls whether to treat the result as quoted if text contains characters that are invalid for identifiers
|
||||
*
|
||||
* @return The identifier form, or {@code null} if text was {@code null}
|
||||
*/
|
||||
public static Identifier toIdentifier(String text, boolean quote, boolean quoteOnNonIdentifierChar) {
|
||||
if ( StringHelper.isEmpty( text ) ) {
|
||||
return null;
|
||||
}
|
||||
int start = 0;
|
||||
int end = text.length();
|
||||
while ( start < end ) {
|
||||
if ( !Character.isWhitespace( text.charAt( start ) ) ) {
|
||||
break;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
while ( start < end ) {
|
||||
if ( !Character.isWhitespace( text.charAt( end - 1 ) ) ) {
|
||||
break;
|
||||
}
|
||||
end--;
|
||||
}
|
||||
if ( isQuoted( text, start, end ) ) {
|
||||
start++;
|
||||
end--;
|
||||
quote = true;
|
||||
}
|
||||
else if ( quoteOnNonIdentifierChar && !quote ) {
|
||||
// Check the letters to determine if we must quote the text
|
||||
char c = text.charAt( start );
|
||||
if ( !Character.isLetter( c ) && c != '_' ) {
|
||||
// SQL identifiers must begin with a letter or underscore
|
||||
quote = true;
|
||||
}
|
||||
else {
|
||||
for ( int i = start + 1; i < end; i++ ) {
|
||||
c = text.charAt( i );
|
||||
if ( !Character.isLetterOrDigit( c ) && c != '_' ) {
|
||||
quote = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Identifier( text.substring( start, end ), quote );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the given identifier text considered quoted. The following patterns are
|
||||
* recognized as quoted:<ul>
|
||||
|
@ -96,6 +154,20 @@ public class Identifier implements Comparable<Identifier> {
|
|||
|| ( name.startsWith( "\"" ) && name.endsWith( "\"" ) );
|
||||
}
|
||||
|
||||
public static boolean isQuoted(String name, int start, int end) {
|
||||
if ( start + 2 < end ) {
|
||||
switch ( name.charAt( start ) ) {
|
||||
case '`':
|
||||
return name.charAt( end - 1 ) == '`';
|
||||
case '[':
|
||||
return name.charAt( end - 1 ) == ']';
|
||||
case '"':
|
||||
return name.charAt( end - 1 ) == '"';
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an identifier instance.
|
||||
*
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.QualifiedSequenceName;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
|
||||
|
@ -28,7 +29,7 @@ public class SequenceInformationExtractorMariaDBDatabaseImpl extends SequenceInf
|
|||
|
||||
// SQL to get metadata from individual sequence
|
||||
private static final String SQL_SEQUENCE_QUERY =
|
||||
"SELECT '%1$s' as sequence_name, minimum_value, maximum_value, start_value, increment, cache_size FROM %1$s ";
|
||||
"SELECT '%1$s' as sequence_name, minimum_value, maximum_value, start_value, increment, cache_size FROM %2$s ";
|
||||
|
||||
private static final String UNION_ALL =
|
||||
"UNION ALL ";
|
||||
|
@ -56,7 +57,7 @@ public class SequenceInformationExtractorMariaDBDatabaseImpl extends SequenceInf
|
|||
if ( sequenceInfoQueryBuilder.length() > 0 ) {
|
||||
sequenceInfoQueryBuilder.append( UNION_ALL );
|
||||
}
|
||||
sequenceInfoQueryBuilder.append( String.format( SQL_SEQUENCE_QUERY, sequenceName ) );
|
||||
sequenceInfoQueryBuilder.append( String.format( SQL_SEQUENCE_QUERY, sequenceName, Identifier.toIdentifier( sequenceName, false, true ) ) );
|
||||
}
|
||||
return extractionContext.getQueryResults(
|
||||
sequenceInfoQueryBuilder.toString(),
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
package org.hibernate.test.dialect.functional;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.MariaDBDialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorMariaDBDatabaseImpl;
|
||||
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInAutoCommit;
|
||||
|
||||
/**
|
||||
* @author Jan Schatteman
|
||||
*/
|
||||
@RequiresDialect(value = MariaDBDialect.class)
|
||||
public class MariaDBExtractSequenceInformationTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
private final static String hhh15665SeqName = "HHH-15665-seq";
|
||||
|
||||
private final static Map<String, Object> settings = new HashMap<>(3);
|
||||
|
||||
static {
|
||||
settings.put( AvailableSettings.URL, Environment.getProperties().getProperty( AvailableSettings.URL ) );
|
||||
settings.put( AvailableSettings.USER, Environment.getProperties().getProperty( AvailableSettings.USER ) );
|
||||
settings.put( AvailableSettings.PASS, Environment.getProperties().getProperty( AvailableSettings.PASS ) );
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
doInAutoCommit( settings, "CREATE SEQUENCE IF NOT EXISTS `" + hhh15665SeqName + "`" );
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws SQLException {
|
||||
doInAutoCommit( settings, "DROP SEQUENCE IF EXISTS `" + hhh15665SeqName + "`" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-15665" )
|
||||
public void testExtractSequenceInformationForSqlServerWithCaseSensitiveCollation() {
|
||||
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().applySettings( settings ).build();
|
||||
JdbcEnvironment jdbcEnvironment = ssr.getService( JdbcEnvironment.class );
|
||||
JdbcConnectionAccess bootstrapJdbcConnectionAccess = ssr.getService( JdbcServices.class ).getBootstrapJdbcConnectionAccess();
|
||||
|
||||
try ( Connection connection = bootstrapJdbcConnectionAccess.obtainConnection() ) {
|
||||
Iterable<SequenceInformation> sequenceInformations = SequenceInformationExtractorMariaDBDatabaseImpl.INSTANCE.extractMetadata(
|
||||
new ExtractionContext.EmptyExtractionContext() {
|
||||
@Override
|
||||
public Connection getJdbcConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcEnvironment getJdbcEnvironment() {
|
||||
return jdbcEnvironment;
|
||||
}
|
||||
} );
|
||||
|
||||
Assert.assertNotNull( sequenceInformations );
|
||||
|
||||
Optional<SequenceInformation> seq = StreamSupport.stream( sequenceInformations.spliterator(), false )
|
||||
.filter(
|
||||
sequence -> hhh15665SeqName.equals( sequence.getSequenceName()
|
||||
.getSequenceName()
|
||||
.getText() )
|
||||
)
|
||||
.findFirst();
|
||||
|
||||
Assert.assertTrue( hhh15665SeqName + " not found", seq.isPresent() );
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
Assert.fail( "Sequence information for " + hhh15665SeqName + " was not retrieved: " + e.getMessage() );
|
||||
}
|
||||
finally {
|
||||
StandardServiceRegistryBuilder.destroy( ssr );
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue