HHH-18459 Add SingleStore dialect
This commit is contained in:
parent
5c0058e6bd
commit
ac4931a264
|
@ -211,6 +211,23 @@ public enum CommunityDatabase {
|
||||||
public boolean productNameMatches(String databaseName) {
|
public boolean productNameMatches(String databaseName) {
|
||||||
return databaseName.toLowerCase().startsWith( "timesten" );
|
return databaseName.toLowerCase().startsWith( "timesten" );
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
SINGLESTORE {
|
||||||
|
@Override
|
||||||
|
public Dialect createDialect(DialectResolutionInfo info) {
|
||||||
|
return new SingleStoreDialect( info );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean productNameMatches(String databaseName) {
|
||||||
|
return databaseName.toLowerCase().startsWith( "singlestore" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDriverClassName(String jdbcUrl) {
|
||||||
|
return "com.singlestore.jdbc.Driver";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -118,6 +118,8 @@ public class CommunityDialectSelector implements DialectSelector {
|
||||||
return Teradata14Dialect.class;
|
return Teradata14Dialect.class;
|
||||||
case "TimesTen":
|
case "TimesTen":
|
||||||
return TimesTenDialect.class;
|
return TimesTenDialect.class;
|
||||||
|
case "SingleStore":
|
||||||
|
return SingleStoreDialect.class;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,464 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.community.dialect;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.DialectDelegateWrapper;
|
||||||
|
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
|
||||||
|
import org.hibernate.dialect.MySQLSqlAstTranslator;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.internal.util.collections.Stack;
|
||||||
|
import org.hibernate.query.sqm.ComparisonOperator;
|
||||||
|
import org.hibernate.query.sqm.SetOperator;
|
||||||
|
import org.hibernate.sql.ast.Clause;
|
||||||
|
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.ast.tree.MutationStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
|
import org.hibernate.sql.ast.tree.Statement;
|
||||||
|
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Any;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.CastTarget;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Every;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||||
|
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.from.QueryPartTableReference;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.ConflictClause;
|
||||||
|
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.predicate.BooleanExpressionPredicate;
|
||||||
|
import org.hibernate.sql.ast.tree.predicate.LikePredicate;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||||
|
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||||
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
|
import org.hibernate.sql.ast.tree.update.UpdateStatement;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A SQL AST translator for SingleStore.
|
||||||
|
*
|
||||||
|
* @author Oleksandr Yeliseiev
|
||||||
|
*/
|
||||||
|
public class SingleStoreSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAstTranslator<T> {
|
||||||
|
|
||||||
|
private final SingleStoreDialect dialect;
|
||||||
|
|
||||||
|
public SingleStoreSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement statement) {
|
||||||
|
super( sessionFactory, statement );
|
||||||
|
this.dialect = (SingleStoreDialect) DialectDelegateWrapper.extractRealDialect( super.getDialect() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBinaryArithmeticExpression(BinaryArithmeticExpression arithmeticExpression) {
|
||||||
|
if ( isIntegerDivisionEmulationRequired( arithmeticExpression ) ) {
|
||||||
|
appendSql( OPEN_PARENTHESIS );
|
||||||
|
visitArithmeticOperand( arithmeticExpression.getLeftHandOperand() );
|
||||||
|
appendSql( " div " );
|
||||||
|
visitArithmeticOperand( arithmeticExpression.getRightHandOperand() );
|
||||||
|
appendSql( CLOSE_PARENTHESIS );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.visitBinaryArithmeticExpression( arithmeticExpression );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supportsRowValueConstructorSyntax() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderSelectTupleComparison(
|
||||||
|
List<SqlSelection> lhsExpressions, SqlTuple tuple, ComparisonOperator operator) {
|
||||||
|
emulateSelectTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void visitInsertSource(InsertSelectStatement statement) {
|
||||||
|
if ( statement.getSourceSelectStatement() != null ) {
|
||||||
|
if ( statement.getConflictClause() != null ) {
|
||||||
|
final List<ColumnReference> targetColumnReferences = statement.getTargetColumns();
|
||||||
|
final List<String> columnNames = new ArrayList<>( targetColumnReferences.size() );
|
||||||
|
for ( ColumnReference targetColumnReference : targetColumnReferences ) {
|
||||||
|
columnNames.add( targetColumnReference.getColumnExpression() );
|
||||||
|
}
|
||||||
|
appendSql( "select * from " );
|
||||||
|
emulateQueryPartTableReferenceColumnAliasing( new QueryPartTableReference(
|
||||||
|
new SelectStatement( statement.getSourceSelectStatement() ),
|
||||||
|
"excluded",
|
||||||
|
columnNames,
|
||||||
|
false,
|
||||||
|
getSessionFactory()
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
statement.getSourceSelectStatement().accept( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
visitValuesList( statement.getValuesList() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitColumnReference(ColumnReference columnReference) {
|
||||||
|
final Statement currentStatement;
|
||||||
|
if ( "excluded".equals( columnReference.getQualifier() ) && ( currentStatement = getStatementStack().getCurrent() ) instanceof InsertSelectStatement && ( (InsertSelectStatement) currentStatement ).getSourceSelectStatement() == null ) {
|
||||||
|
// Accessing the excluded row for an insert-values statement in the conflict clause requires the values qualifier
|
||||||
|
appendSql( "values(" );
|
||||||
|
columnReference.appendReadExpression( this, null );
|
||||||
|
append( ')' );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.visitColumnReference( columnReference );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderDeleteClause(DeleteStatement statement) {
|
||||||
|
appendSql( "delete" );
|
||||||
|
final Stack<Clause> clauseStack = getClauseStack();
|
||||||
|
try {
|
||||||
|
clauseStack.push( Clause.DELETE );
|
||||||
|
renderTableReferenceIdentificationVariable( statement.getTargetTable() );
|
||||||
|
if ( statement.getFromClause().getRoots().isEmpty() ) {
|
||||||
|
appendSql( " from " );
|
||||||
|
renderDmlTargetTableExpression( statement.getTargetTable() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
visitFromClause( statement.getFromClause() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
clauseStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderUpdateClause(UpdateStatement updateStatement) {
|
||||||
|
if ( updateStatement.getFromClause().getRoots().isEmpty() ) {
|
||||||
|
super.renderUpdateClause( updateStatement );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendSql( "update " );
|
||||||
|
renderFromClauseSpaces( updateStatement.getFromClause() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderDmlTargetTableExpression(NamedTableReference tableReference) {
|
||||||
|
super.renderDmlTargetTableExpression( tableReference );
|
||||||
|
if ( getClauseStack().getCurrent() != Clause.INSERT ) {
|
||||||
|
renderTableReferenceIdentificationVariable( tableReference );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supportsJoinsInDelete() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||||
|
visitOnDuplicateKeyConflictClause( conflictClause );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String determineColumnReferenceQualifier(ColumnReference columnReference) {
|
||||||
|
final DmlTargetColumnQualifierSupport qualifierSupport = getDialect().getDmlTargetColumnQualifierSupport();
|
||||||
|
final MutationStatement currentDmlStatement;
|
||||||
|
final String dmlAlias;
|
||||||
|
// Since SingleStore does not support aliasing the insert target table,
|
||||||
|
// we must detect column reference that are used in the conflict clause
|
||||||
|
// and use the table expression as qualifier instead
|
||||||
|
if ( getClauseStack().getCurrent() != Clause.SET || !( ( currentDmlStatement = getCurrentDmlStatement() ) instanceof InsertSelectStatement ) || ( dmlAlias = currentDmlStatement.getTargetTable()
|
||||||
|
.getIdentificationVariable() ) == null || !dmlAlias.equals( columnReference.getQualifier() ) ) {
|
||||||
|
return columnReference.getQualifier();
|
||||||
|
}
|
||||||
|
// Qualify the column reference with the table expression also when in subqueries
|
||||||
|
else if ( qualifierSupport != DmlTargetColumnQualifierSupport.NONE || !getQueryPartStack().isEmpty() ) {
|
||||||
|
return getCurrentDmlStatement().getTargetTable().getTableExpression();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supportsWithClauseInSubquery() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderExpressionAsClauseItem(Expression expression) {
|
||||||
|
expression.accept( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
|
||||||
|
final boolean isNegated = booleanExpressionPredicate.isNegated();
|
||||||
|
if ( isNegated ) {
|
||||||
|
appendSql( "not(" );
|
||||||
|
}
|
||||||
|
booleanExpressionPredicate.getExpression().accept( this );
|
||||||
|
if ( isNegated ) {
|
||||||
|
appendSql( CLOSE_PARENTHESIS );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {
|
||||||
|
// Check if current query part is already row numbering to avoid infinite recursion
|
||||||
|
return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart && supportsWindowFunctions() && !isRowsOnlyFetchClauseType(
|
||||||
|
queryPart );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shouldEmulateLateralWithIntersect(QueryPart queryPart) {
|
||||||
|
return supportsSimpleQueryGrouping() || !queryPart.hasOffsetOrFetchClause();
|
||||||
|
}
|
||||||
|
|
||||||
|
//SingleStore doesn't support 'FOR UPDATE' clause with distributed joins
|
||||||
|
@Override
|
||||||
|
protected String getForUpdate() {
|
||||||
|
return dialect.getForUpdateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitAny(Any any) {
|
||||||
|
throw new UnsupportedOperationException( "SingleStore doesn't support ANY clause" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEvery(Every every) {
|
||||||
|
throw new UnsupportedOperationException( "SingleStore doesn't support ALL clause" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supportsNestedSubqueryCorrelation() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitQueryGroup(QueryGroup queryGroup) {
|
||||||
|
if ( shouldEmulateFetchClause( queryGroup ) ) {
|
||||||
|
emulateFetchOffsetWithWindowFunctions( queryGroup, true );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.visitQueryGroup( queryGroup );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitQuerySpec(QuerySpec querySpec) {
|
||||||
|
if ( shouldEmulateFetchClause( querySpec ) ) {
|
||||||
|
emulateFetchOffsetWithWindowFunctions( querySpec, true );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.visitQuerySpec( querySpec );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitQueryPartTableReference(QueryPartTableReference tableReference) {
|
||||||
|
emulateQueryPartTableReferenceColumnAliasing( tableReference );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||||
|
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||||
|
renderCombinedLimitClause( queryPart );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||||
|
if ( operator == ComparisonOperator.DISTINCT_FROM || operator == ComparisonOperator.NOT_DISTINCT_FROM ) {
|
||||||
|
renderDistinct( lhs, operator, rhs );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( operator.sqlText() );
|
||||||
|
rhs.accept( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderDistinct(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||||
|
appendSql( OPEN_PARENTHESIS );
|
||||||
|
appendSql( "case when " );
|
||||||
|
rhs.accept( this );
|
||||||
|
appendSql( " is null then " );
|
||||||
|
if ( operator == ComparisonOperator.DISTINCT_FROM ) {
|
||||||
|
appendSql( OPEN_PARENTHESIS );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( " is not null) else (" );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( "!=" );
|
||||||
|
rhs.accept( this );
|
||||||
|
appendSql( " or " );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( " is null) end)" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendSql( OPEN_PARENTHESIS );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( " is null) else (" );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( "=" );
|
||||||
|
rhs.accept( this );
|
||||||
|
appendSql( ") end)" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void emulateTupleComparison(
|
||||||
|
final List<? extends SqlAstNode> lhsExpressions,
|
||||||
|
final List<? extends SqlAstNode> rhsExpressions,
|
||||||
|
ComparisonOperator operator,
|
||||||
|
boolean indexOptimized) {
|
||||||
|
if ( operator == ComparisonOperator.DISTINCT_FROM || operator == ComparisonOperator.NOT_DISTINCT_FROM ) {
|
||||||
|
final int size = lhsExpressions.size();
|
||||||
|
assert size == rhsExpressions.size();
|
||||||
|
String separator = OPEN_PARENTHESIS + "";
|
||||||
|
for ( int i = 0; i < size; i++ ) {
|
||||||
|
appendSql( separator );
|
||||||
|
renderDistinct( (Expression) lhsExpressions.get( i ), operator, (Expression) rhsExpressions.get( i ) );
|
||||||
|
separator = ") and (";
|
||||||
|
}
|
||||||
|
appendSql( CLOSE_PARENTHESIS );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.emulateTupleComparison( lhsExpressions, rhsExpressions, operator, indexOptimized );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderCombinedLimitClause(Expression offsetExpression, Expression fetchExpression) {
|
||||||
|
if ( offsetExpression != null || fetchExpression != null ) {
|
||||||
|
if ( getCurrentQueryPart() instanceof QueryGroup && ( ( (QueryGroup) getCurrentQueryPart() ).getSetOperator() == SetOperator.UNION || ( (QueryGroup) getCurrentQueryPart() ).getSetOperator() == SetOperator.UNION_ALL ) ) {
|
||||||
|
throw new UnsupportedOperationException( "SingleStore doesn't support UNION/UNION ALL with limit clause" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.renderCombinedLimitClause( offsetExpression, fetchExpression );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderPartitionItem(Expression expression) {
|
||||||
|
if ( expression instanceof Literal ) {
|
||||||
|
appendSql( "'0'" );
|
||||||
|
}
|
||||||
|
else if ( expression instanceof Summarization ) {
|
||||||
|
Summarization summarization = (Summarization) expression;
|
||||||
|
renderCommaSeparated( summarization.getGroupings() );
|
||||||
|
appendSql( " with " );
|
||||||
|
appendSql( summarization.getKind().sqlText() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expression.accept( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//SingleStore like is case insensitive
|
||||||
|
@Override
|
||||||
|
public void visitLikePredicate(LikePredicate likePredicate) {
|
||||||
|
appendSql( "cast( " );
|
||||||
|
likePredicate.getMatchExpression().accept( this );
|
||||||
|
appendSql( " as char) " );
|
||||||
|
if ( likePredicate.isNegated() ) {
|
||||||
|
appendSql( " not" );
|
||||||
|
}
|
||||||
|
appendSql( " like " );
|
||||||
|
renderBackslashEscapedLikePattern( likePredicate.getPattern(), likePredicate.getEscapeCharacter(), false );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderBackslashEscapedLikePattern(
|
||||||
|
Expression pattern, Expression escapeCharacter, boolean noBackslashEscapes) {
|
||||||
|
if ( escapeCharacter != null ) {
|
||||||
|
appendSql( "replace" );
|
||||||
|
appendSql( OPEN_PARENTHESIS );
|
||||||
|
pattern.accept( this );
|
||||||
|
appendSql( "," );
|
||||||
|
escapeCharacter.accept( this );
|
||||||
|
appendSql( ",'\\\\'" );
|
||||||
|
appendSql( CLOSE_PARENTHESIS );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Since escape with empty or null character is ignored we need
|
||||||
|
// four backslashes to render a single one in a like pattern
|
||||||
|
if ( pattern instanceof Literal ) {
|
||||||
|
Object literalValue = ( (Literal) pattern ).getLiteralValue();
|
||||||
|
if ( literalValue == null ) {
|
||||||
|
pattern.accept( this );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendBackslashEscapedLikeLiteral( this, literalValue.toString(), false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appendSql( "replace" );
|
||||||
|
appendSql( OPEN_PARENTHESIS );
|
||||||
|
pattern.accept( this );
|
||||||
|
appendSql( ",'\\\\','\\\\\\\\'" );
|
||||||
|
appendSql( CLOSE_PARENTHESIS );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsRowValueConstructorSyntaxInSet() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean supportsDistinctFromPredicate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDual() {
|
||||||
|
return "dual";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SingleStoreDialect getDialect() {
|
||||||
|
return this.dialect;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean supportsWindowFunctions() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCastTarget(CastTarget castTarget) {
|
||||||
|
String sqlType = MySQLSqlAstTranslator.getSqlType( castTarget, getSessionFactory() );
|
||||||
|
if ( sqlType != null ) {
|
||||||
|
appendSql( sqlType );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.visitCastTarget( castTarget );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,6 +72,7 @@ public class CommunityDialectSelectorTest {
|
||||||
|
|
||||||
testDialectNamingResolution( TeradataDialect.class );
|
testDialectNamingResolution( TeradataDialect.class );
|
||||||
testDialectNamingResolution( TimesTenDialect.class );
|
testDialectNamingResolution( TimesTenDialect.class );
|
||||||
|
testDialectNamingResolution( SingleStoreDialect.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testDialectNamingResolution(final Class<?> dialectClass) {
|
private void testDialectNamingResolution(final Class<?> dialectClass) {
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.community.dialect;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.orm.test.dialect.resolver.TestingDialectResolutionInfo;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.hibernate.dialect.DatabaseVersion.NO_VERSION;
|
||||||
|
|
||||||
|
public class SingleStoreDialectTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSpecificProperties() {
|
||||||
|
final Dialect dialect = resolveDialect( "SingleStore", values -> {
|
||||||
|
values.put( SingleStoreDialect.SINGLE_STORE_TABLE_TYPE, "rowStOre " );
|
||||||
|
values.put( SingleStoreDialect.SINGLE_STORE_FOR_UPDATE_LOCK_ENABLED, "true" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertThat( dialect ).isInstanceOf( SingleStoreDialect.class );
|
||||||
|
SingleStoreDialect singleStoreDialect = (SingleStoreDialect) dialect;
|
||||||
|
assertThat( singleStoreDialect.getExplicitTableType() ).isEqualTo( SingleStoreDialect.SingleStoreTableType.ROWSTORE );
|
||||||
|
assertThat( singleStoreDialect.isForUpdateLockingEnabled() ).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dialect resolveDialect(String productName, Consumer<Map<String, Object>> configurationProvider) {
|
||||||
|
final Map<String, Object> configurationValues = new HashMap<>();
|
||||||
|
configurationProvider.accept( configurationValues );
|
||||||
|
final TestingDialectResolutionInfo info = TestingDialectResolutionInfo.forDatabaseInfo( productName,
|
||||||
|
null,
|
||||||
|
NO_VERSION,
|
||||||
|
NO_VERSION,
|
||||||
|
configurationValues
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat( info.getDatabaseMetadata() ).isNull();
|
||||||
|
|
||||||
|
return new CommunityDialectResolver().resolveDialect( info );
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue