hibernate/hibernate-orm · error · IllegalQueryOperationException

Insert conflict 'do update' clause with constraint name is n

Error message

Insert conflict 'do update' clause with constraint name is not supported

What it means

SybaseSqlAstTranslator (SQL Anywhere family) visitConflictClause rejects the constraint-name form of the HQL upsert conflict clause: a DO UPDATE clause with a non-null constraint name ('on conflict on constraint <name> do update') throws IllegalQueryOperationException during translation, since the dialect rendering cannot anchor an upsert conflict to a named constraint.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/sql/ast/SybaseSqlAstTranslator.java:99

			clauseStack.push( Clause.DELETE );
			renderDmlTargetTableExpression( statement.getTargetTable() );
		}
		finally {
			clauseStack.pop();
		}
		visitFromClause( statement.getFromClause() );
	}

	@Override
	protected void renderFromClauseAfterUpdateSet(UpdateStatement statement) {
		visitFromClause( statement.getFromClause() );
	}

	@Override
	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" );
			}
		}
	}

	// Sybase does not allow CASE expressions where all result arms contain plain parameters.
	// At least one result arm must provide some type context for inference,
	// so we cast the first result arm if we encounter this condition

	@Override
	protected void visitAnsiCaseSearchedExpression(
			CaseSearchedExpression caseSearchedExpression,
			Consumer<Expression> resultRenderer) {
		if ( getParameterRenderingMode() == SqlAstNodeRenderingMode.DEFAULT
				&& areAllResultsParameters( caseSearchedExpression ) ) {
			final List<CaseSearchedExpression.WhenFragment> whenFragments = caseSearchedExpression.getWhenFragments();
			final Expression firstResult = whenFragments.get( 0 ).getResult();
			super.visitAnsiCaseSearchedExpression(
					caseSearchedExpression,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Switch to 'on conflict (col1, col2) do update set ...'
  2. Make sure the column list equals the unique constraint's columns so behavior is identical
  3. Use a native SQL Anywhere upsert/MERGE for dialect-specific behavior
  4. Keep a dialect-specific HQL branch for the constraint-name variant

Example fix

// before
"insert into Tag t (t.name,t.hits) values (:n,:h) on conflict on constraint uk_tag_name do update set t.hits = excluded.hits"

// after
"insert into Tag t (t.name,t.hits) values (:n,:h) on conflict (name) do update set t.hits = excluded.hits"
Defensive patterns

Strategy: validation

Validate before calling

static boolean supportsConstraintNameConflictTarget(Dialect dialect) {
    return dialect instanceof PostgreSQLDialect; // Sybase translator rejects it
}

String target = supportsConstraintNameConflictTarget(dialect)
    ? "on constraint " + constraintName
    : "(" + String.join(",", constraintColumns) + ")";
String hql = "insert into ... on conflict " + target + " do update set ...";

Try / catch

try {
    em.createQuery(hql).executeUpdate();
} catch (IllegalQueryOperationException e) {
    if (e.getMessage().contains("constraint name is not supported")) {
        em.createQuery(withColumnTarget(hql)).executeUpdate();
        return;
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL 'insert into ... on conflict on constraint <name> do update set ...' executed against SQLAnywhereDialect (or another dialect using SybaseSqlAstTranslator); throws from createQuery/executeUpdate during SQL generation.

Common situations: Sharing upsert HQL between PostgreSQL and SQL Anywhere deployments; copying the Hibernate 6.6+ 'on conflict' documentation examples; migration projects that keep PostgreSQL idioms.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/665a83f67388c750. Report an issue: GitHub.