fix constraint name extraction and 'on constraint' on MySQL
This commit is contained in:
parent
a84ba5c8c9
commit
115ddffdbc
|
@ -383,7 +383,7 @@ public class DB2LegacySqlAstTranslator<T extends JdbcOperation> extends Abstract
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ public class H2LegacySqlAstTranslator<T extends JdbcOperation> extends AbstractS
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ public class HSQLLegacySqlAstTranslator<T extends JdbcOperation> extends Abstrac
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ public class MariaDBLegacySqlAstTranslator<T extends JdbcOperation> extends Abst
|
|||
getSql(),
|
||||
getParameterBinders(),
|
||||
getAffectedTableNames(),
|
||||
null
|
||||
getUniqueConstraintNameThatMayFail(sqlAst)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ 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.function.AbstractSqmSelfRenderingFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
||||
|
@ -162,7 +160,7 @@ public class MySQLLegacySqlAstTranslator<T extends JdbcOperation> extends Abstra
|
|||
getSql(),
|
||||
getParameterBinders(),
|
||||
getAffectedTableNames(),
|
||||
null
|
||||
getUniqueConstraintNameThatMayFail(sqlAst)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ public class OracleLegacySqlAstTranslator<T extends JdbcOperation> extends Abstr
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ public class SQLServerLegacySqlAstTranslator<T extends JdbcOperation> extends Ab
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ public class SybaseASELegacySqlAstTranslator<T extends JdbcOperation> extends Ab
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ public class SybaseLegacySqlAstTranslator<T extends JdbcOperation> extends Abstr
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -382,7 +382,7 @@ public class DB2SqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAst
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ public class H2SqlAstTranslator<T extends JdbcOperation> extends SqlAstTranslato
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ public class HANASqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAs
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ public class HSQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAs
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ public class MariaDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSq
|
|||
getSql(),
|
||||
getParameterBinders(),
|
||||
getAffectedTableNames(),
|
||||
null
|
||||
getUniqueConstraintNameThatMayFail(sqlAst)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
|||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.LockAcquisitionException;
|
||||
import org.hibernate.exception.LockTimeoutException;
|
||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||
|
@ -1200,6 +1201,16 @@ public class MySQLDialect extends Dialect {
|
|||
case 1207:
|
||||
case 1206:
|
||||
return new LockAcquisitionException( message, sqlException, sql );
|
||||
case 1062:
|
||||
// Unique constraint violation
|
||||
String constraintName = getViolatedConstraintNameExtractor().extractConstraintName(sqlException);
|
||||
return new ConstraintViolationException(
|
||||
message,
|
||||
sqlException,
|
||||
sql,
|
||||
ConstraintViolationException.ConstraintKind.UNIQUE,
|
||||
constraintName
|
||||
);
|
||||
}
|
||||
|
||||
final String sqlState = JdbcExceptionHelper.extractSqlState( sqlException );
|
||||
|
|
|
@ -224,7 +224,7 @@ public class MySQLSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
|
|||
getSql(),
|
||||
getParameterBinders(),
|
||||
getAffectedTableNames(),
|
||||
null
|
||||
getUniqueConstraintNameThatMayFail(sqlAst)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends SqlAstTrans
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -708,11 +708,12 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
|||
case 2627:
|
||||
case 2601:
|
||||
String message = sqle.getMessage();
|
||||
int i = message.indexOf("unique index ");
|
||||
if (i>0) {
|
||||
message = message.substring(i);
|
||||
if ( message.contains("unique index ") ) {
|
||||
return extractUsingTemplate( "unique index '", "'", message);
|
||||
}
|
||||
else {
|
||||
return extractUsingTemplate( "'", "'", message);
|
||||
}
|
||||
return extractUsingTemplate( "'", "'", message);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ public class SQLServerSqlAstTranslator<T extends JdbcOperation> extends SqlAstTr
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ public class SybaseASESqlAstTranslator<T extends JdbcOperation> extends Abstract
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public class SybaseSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
|
|||
protected void visitConflictClause(ConflictClause conflictClause) {
|
||||
if ( conflictClause != null ) {
|
||||
if ( conflictClause.isDoUpdate() && conflictClause.getConstraintName() != null ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict do update clause with constraint name is not supported" );
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ public class TiDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlAs
|
|||
getSql(),
|
||||
getParameterBinders(),
|
||||
getAffectedTableNames(),
|
||||
null
|
||||
getUniqueConstraintNameThatMayFail(sqlAst)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -846,26 +846,26 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
protected JdbcOperationQueryInsert translateInsert(InsertSelectStatement sqlAst) {
|
||||
visitInsertStatement( sqlAst );
|
||||
|
||||
return new JdbcOperationQueryInsertImpl(
|
||||
getSql(),
|
||||
getParameterBinders(),
|
||||
getAffectedTableNames(),
|
||||
getUniqueConstraintNameThatMayFail(sqlAst)
|
||||
);
|
||||
}
|
||||
|
||||
protected String getUniqueConstraintNameThatMayFail(InsertSelectStatement sqlAst) {
|
||||
final ConflictClause conflictClause = sqlAst.getConflictClause();
|
||||
final String uniqueConstraintNameThatMayFail;
|
||||
if ( conflictClause == null || !conflictClause.getConstraintColumnNames().isEmpty() ) {
|
||||
uniqueConstraintNameThatMayFail = null;
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
if ( sqlAst.getSourceSelectStatement() != null && !isFetchFirstRowOnly( sqlAst.getSourceSelectStatement() )
|
||||
|| sqlAst.getValuesList().size() > 1 ) {
|
||||
throw new IllegalQueryOperationException( "Can't emulate conflict clause with constraint name for more than one row to insert" );
|
||||
}
|
||||
uniqueConstraintNameThatMayFail = conflictClause.getConstraintName() == null
|
||||
? ""
|
||||
: conflictClause.getConstraintName();
|
||||
return conflictClause.getConstraintName() == null ? "" : conflictClause.getConstraintName();
|
||||
}
|
||||
return new JdbcOperationQueryInsertImpl(
|
||||
getSql(),
|
||||
getParameterBinders(),
|
||||
getAffectedTableNames(),
|
||||
uniqueConstraintNameThatMayFail
|
||||
);
|
||||
}
|
||||
|
||||
protected JdbcOperationQuerySelect translateSelect(SelectStatement selectStatement) {
|
||||
|
@ -2059,7 +2059,12 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
// propagated, but instead will run the respective conflict action.
|
||||
final String constraintName = conflictClause.getConstraintName();
|
||||
if ( constraintName != null ) {
|
||||
throw new IllegalQueryOperationException( "Dialect does not support constraint name in conflict clause" );
|
||||
if ( conflictClause.isDoUpdate() ) {
|
||||
throw new IllegalQueryOperationException( "Insert conflict 'do update' clause with constraint name is not supported" );
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// final List<String> constraintColumnNames = conflictClause.getConstraintColumnNames();
|
||||
// if ( !constraintColumnNames.isEmpty() ) {
|
||||
|
|
|
@ -5,6 +5,8 @@ import jakarta.persistence.GeneratedValue;
|
|||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
|
@ -31,6 +33,7 @@ public class InsertConflictOnConstraintTest {
|
|||
@RequiresDialect( PostgreSQLDialect.class )
|
||||
@RequiresDialect( OracleDialect.class )
|
||||
@RequiresDialect( SQLServerDialect.class )
|
||||
@RequiresDialect( MySQLDialect.class )
|
||||
@Test void testDoNothing(SessionFactoryScope scope) {
|
||||
scope.getSessionFactory().getSchemaManager().truncateMappedObjects();
|
||||
scope.inTransaction( s -> s.persist(new Constrained()));
|
||||
|
@ -38,6 +41,14 @@ public class InsertConflictOnConstraintTest {
|
|||
scope.inSession( s -> assertEquals(69, s.createSelectionQuery("select count from Constrained", int.class).getSingleResult()));
|
||||
}
|
||||
|
||||
@RequiresDialect( H2Dialect.class )
|
||||
@Test void testDoNothing2(SessionFactoryScope scope) {
|
||||
scope.getSessionFactory().getSchemaManager().truncateMappedObjects();
|
||||
scope.inTransaction( s -> s.persist(new Constrained()));
|
||||
scope.inTransaction( s -> s.createMutationQuery("insert into Constrained(id, name, count) values (4,'Gavin',69) on conflict on constraint count_name_key_index_2 do nothing").executeUpdate());
|
||||
scope.inSession( s -> assertEquals(69, s.createSelectionQuery("select count from Constrained", int.class).getSingleResult()));
|
||||
}
|
||||
|
||||
@Entity(name = "Constrained")
|
||||
@Table(uniqueConstraints = @UniqueConstraint(name = "count_name_key", columnNames = {"count","name"}))
|
||||
static class Constrained {
|
||||
|
|
Loading…
Reference in New Issue