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

InformixSqlAstTranslator.visitConflictClause() rejects HQL INSERT ... ON CONFLICT clauses whose conflict target is a named constraint with a DO UPDATE action. Informix upserts are emulated via MERGE (visitInsertStatementEmulateMerge), and a constraint-name target cannot be translated into that MERGE, so Hibernate throws IllegalQueryOperationException.

Source

Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java:214

	@Override
	protected void renderInsertIntoNoColumns(TableInsertStandard tableInsert) {
		renderIntoIntoAndTable( tableInsert );
		appendSql( "values (0)" );
	}

	private boolean supportsParameterOffsetFetchExpression() {
		return getDialect().getVersion().isSameOrAfter( 11 );
	}

	private boolean supportsSkipFirstClause() {
		return getDialect().getVersion().isSameOrAfter( 11 );
	}

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

	@Override
	protected void visitInsertStatementOnly(InsertSelectStatement statement) {
		if ( statement.getConflictClause() == null || statement.getConflictClause().isDoNothing() ) {
			// Render plain insert statement and possibly run into unique constraint violation
			super.visitInsertStatementOnly( statement );
		}
		else {
			visitInsertStatementEmulateMerge( statement );
		}
	}

	@Override
	public void visitValuesTableReference(ValuesTableReference tableReference) {
		emulateValuesTableReferenceColumnAliasing( tableReference );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use a column list as the conflict target: 'on conflict (cols) do update set ...'
  2. On Informix, write the upsert as a native MERGE statement
  3. Drop the conflict clause and handle the unique-violation exception with a compensating UPDATE

Example fix

// before (fails on Informix)
insert into Customer (id, email) values (:id, :email)
  on conflict on constraint uk_customer_email do update set email = excluded.email

// after
insert into Customer (id, email) values (:id, :email)
  on conflict (email) do update set email = excluded.email
Defensive patterns

Strategy: validation

Validate before calling

static boolean usesConstraintConflictTarget(String hql) {
    return hql.toLowerCase().matches("(?s).*on\\s+conflict\\s+on\\s+constraint.*");
}
if ( session.getJdbcServices().getDialect() instanceof InformixDialect
        && usesConstraintConflictTarget(hql) ) {
    throw new IllegalArgumentException("Informix upsert supports only column conflict targets");
}

Type guard

static boolean isInformix(Dialect d) { return d instanceof InformixDialect; }

Try / catch

try {
    session.createQuery(hql).executeUpdate();
} catch (IllegalQueryOperationException e) {
    if ( String.valueOf(e.getMessage()).contains("constraint name") ) {
        // switch to 'on conflict (cols)' or a native MERGE statement
    }
    throw e;
}

Prevention

When it happens

Trigger: Running 'insert into T (...) values/select ... on conflict on constraint <name> do update set ...' on InformixDialect. The check fires only when conflictClause.isDoUpdate() and getConstraintName() != null; column-list targets and do-nothing clauses are handled.

Common situations: Copy-pasting PostgreSQL/SQLite upsert statements into an Informix deployment; test fixtures using named constraints; shared repository code where the conflict target was written as a constraint to survive column renames.

Related errors


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