All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cds.jdbc.postgresql.PostgreSqlStatementResolver Maven / Gradle / Ivy

There is a newer version: 3.4.0
Show newest version
/*******************************************************************
 * © 2022 SAP SE or an SAP affiliate company. All rights reserved. *
 *******************************************************************/
package com.sap.cds.jdbc.postgresql;

import static com.sap.cds.impl.sql.SQLHelper.commaSeparated;
import static java.util.stream.Collectors.joining;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.sap.cds.jdbc.spi.StatementResolver;
import com.sap.cds.ql.cqn.CqnLock;
import com.sap.cds.ql.cqn.CqnLock.Mode;

public class PostgreSqlStatementResolver implements StatementResolver {

	/**
	 * PostgreSQL: INSERT INTO with ON CONFLICT DO UPDATE
	 *
	 * ON CONFLICT can be used to specify an alternative action to raising a unique
	 * constraint or exclusion constraint violation error. For each individual row
	 * proposed for insertion, either the insertion proceeds, or, if an arbiter
	 * constraint or index specified by conflict_target is violated, the alternative
	 * conflict_action is taken. ON CONFLICT DO UPDATE updates the existing row that
	 * conflicts with the row proposed for insertion as its alternative action.
	 *
	 * ON CONFLICT DO UPDATE guarantees an atomic INSERT or UPDATE outcome; provided
	 * there is no independent error, one of those two outcomes is guaranteed, even
	 * under high concurrency. This is also known as UPSERT — “UPDATE or INSERT”.
	 *
	 * https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT
	 */
	@Override
	public String upsert(String table, Stream keyColumns, Stream upsertColumns,
			Stream upsertValues) {
		List col = upsertColumns.collect(Collectors.toList());
		String columns = commaSeparated(col.stream());
		String insertValues = commaSeparated(upsertValues);
		String conflictTarget = commaSeparated(keyColumns);
		String updateValues = commaSeparated(col.stream().map(c -> "EXCLUDED." + c));

		return Stream.of("INSERT INTO", table, columns, "VALUES", insertValues, "ON CONFLICT", conflictTarget,
				"DO UPDATE SET", columns, "= ROW", updateValues).collect(joining(" "));
	}

	// https://www.postgresql.org/docs/current/explicit-locking.html
	@Override
	public String lockMode(Mode mode) {
		return mode == CqnLock.Mode.SHARED ? "FOR SHARE" : "FOR UPDATE";
	}

	@Override
	public Optional timeoutClause(int timeoutSeconds) {
		if (timeoutSeconds == 0) {
			return Optional.of("NOWAIT");
		}

		return Optional.empty();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy