Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,11 @@ public FeatureTransactions.MutationResult assertNoConflictingVersion(
return builder.build();
}

// Batch variant of the versioned-Insert pre-flight: one SELECT on the main table for all ids, the
// ids found are returned in `ids`.
// Batch variant of the versioned-Insert pre-flight: one query for all ids, the ids of which a
// version exists are returned in `ids`, as they were given. Each id is checked for existence as
// in the single-id check and the query returns the given literal, not the column value: the text
// form of the column value can differ from the given id, e.g. 7 for '007' in an integer column, a
// UUID in lower case or a char(n) value with padding.
@Override
public FeatureTransactions.MutationResult findConflictingVersions(
String featureType, Collection<String> featureIds) {
Expand All @@ -533,20 +536,26 @@ public FeatureTransactions.MutationResult findConflictingVersions(
+ "' has no id column; cannot run the versioned-insert pre-flight."))
.build();
}
String mainTableName = idColumn.get().first().getName();
String idCol = idColumn.get().second().getName();
String sql =
"SELECT DISTINCT "
+ idCol
+ SQL_FROM
+ idColumn.get().first().getName()
+ SQL_WHERE
+ idCol
+ " IN ("
+ featureIds.stream()
featureIds.stream()
.distinct()
.map(SqlMutationSession::sqlString)
.collect(Collectors.joining(", "))
+ ");";
.map(
id ->
SQL_SELECT
+ id
+ " WHERE EXISTS (SELECT 1"
+ SQL_FROM
+ mainTableName
+ SQL_WHERE
+ idCol
+ SQL_EQ
+ id
+ ")")
.collect(Collectors.joining(" UNION ALL "))
+ ";";
try {
builder.ids(sqlSession.runReturning(sql));
} catch (RuntimeException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,53 @@ class VersionedMutationSqlSpec extends Specification {
}) >> []
}

def 'Insert pre-flight for a batch: findConflictingVersions checks all ids with one SELECT'() {
def 'Insert pre-flight for a batch: findConflictingVersions checks all ids with one query'() {
when:
FeatureTransactions.MutationResult result = session.findConflictingVersions(
FEATURE_TYPE, ['DEABCDEF12345678', 'DEABCDEF00000001', 'DEABCDEF12345678'])

then:
1 * sqlSession.runReturning({ String sql ->
sql == "SELECT DISTINCT ${COL_ID} FROM ${TABLE} WHERE ${COL_ID} IN " +
"('DEABCDEF12345678', 'DEABCDEF00000001');"
sql == "SELECT 'DEABCDEF12345678' WHERE EXISTS " +
"(SELECT 1 FROM ${TABLE} WHERE ${COL_ID} = 'DEABCDEF12345678')" +
" UNION ALL SELECT 'DEABCDEF00000001' WHERE EXISTS " +
"(SELECT 1 FROM ${TABLE} WHERE ${COL_ID} = 'DEABCDEF00000001');"
}) >> ['DEABCDEF12345678']
result.ids == ['DEABCDEF12345678']
result.error.isEmpty()
}

def 'Insert pre-flight for a batch: an id is found also in another text form of the database: #given'() {
when:
FeatureTransactions.MutationResult result = session.findConflictingVersions(FEATURE_TYPE, given)

then:
1 * sqlSession.runReturning(_) >> { String sql -> integerColumnWithSeven(sql) }
result.ids as Set == found as Set

where:
given | found
['007', '8'] | ['007']
['7', '007'] | ['7', '007']
['8'] | []
}

/**
* Answers the query as PostgreSQL does for an integer id column with the row 7: a literal is
* compared as a number, the column value is returned as '7'.
*/
private static List<String> integerColumnWithSeven(String sql) {
def isSeven = { String literal -> literal.isInteger() && literal.toInteger() == 7 }
def inList = sql =~ /^SELECT DISTINCT \w+ FROM \w+ WHERE \w+ IN \((.*)\);$/
if (inList.matches()) {
def literals = (inList.group(1) =~ /'([^']*)'/).collect { it[1] }
return literals.any(isSeven) ? ['7'] : []
}
return (sql =~ /SELECT '([^']*)' WHERE EXISTS \(SELECT 1 FROM \w+ WHERE \w+ = '([^']*)'\)/)
.findAll { isSeven(it[2]) }
.collect { it[1] }
}

def 'Insert pre-flight for a batch: no ids, no query'() {
when:
FeatureTransactions.MutationResult result = session.findConflictingVersions(FEATURE_TYPE, [])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,11 @@ default MutationResult assertNoConflictingVersion(String featureType, String fea

/**
* Batch variant of {@link #assertNoConflictingVersion(String, String)}: returns in {@code ids}
* those of the {@code featureIds} of which a version already exists (open or retired), with one
* query instead of one per id. {@code error} is set when the check itself fails. The default
* implementation returns no ids (no check) for providers that have not adopted the API.
* those of the {@code featureIds} of which a version already exists (open or retired), as they
* were given, also when the stored id has another text form (e.g. {@code 7} for {@code 007} in
* an integer column), with one query instead of one per id. {@code error} is set when the check
* itself fails. The default implementation returns no ids (no check) for providers that have
* not adopted the API.
*/
default MutationResult findConflictingVersions(
String featureType, Collection<String> featureIds) {
Expand Down
Loading