test(sql): cover explicitCollateInASetOperationsOrderByOverridesTheCo...
This commit is contained in:
1 parent
fae2af0764
commit
ffb95375fe
1 file changed
+156
@@ -152,3 +152,159 @@ class DiskExecutorColumnCollationTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun explicitCollateInASetOperationsOrderByOverridesTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.seedNames()
|
||||
val result = db.select(
|
||||
"SELECT * FROM people WHERE id <= 2 UNION ALL SELECT * FROM people WHERE id > 2 ORDER BY name COLLATE BINARY"
|
||||
)
|
||||
assertEquals(listOf("Alice", "Bob", "Zoe", "bob"), result.rows.map { (it[1] as Value.TextValue).value })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun declaredCollationDoesNotReachThroughADerivedTableInASetOperationsLeftBranch() {
|
||||
val db = newDatabase()
|
||||
db.seedNames()
|
||||
val result = db.select(
|
||||
"SELECT * FROM (SELECT * FROM people) sub WHERE id <= 2 " +
|
||||
"UNION ALL SELECT * FROM (SELECT * FROM people) sub2 WHERE id > 2 " +
|
||||
"ORDER BY name"
|
||||
)
|
||||
assertEquals(listOf("Alice", "Bob", "Zoe", "bob"), result.rows.map { (it[1] as Value.TextValue).value })
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.groupByDedupsCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun groupByDedupsCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.seedNames()
|
||||
val result = db.select("SELECT name, COUNT(*) FROM people GROUP BY name ORDER BY name")
|
||||
assertEquals(
|
||||
listOf("Alice" to 1L, "Bob" to 2L, "Zoe" to 1L).map { (name, count) -> listOf(Value.TextValue(name), int(count)) },
|
||||
result.rows
|
||||
)
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.selectDistinctDedupsCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun selectDistinctDedupsCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.seedNames()
|
||||
val result = db.select("SELECT DISTINCT name FROM people ORDER BY name")
|
||||
assertEquals(listOf("Alice", "Bob", "Zoe").map { listOf(Value.TextValue(it)) }, result.rows)
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.selectDistinctStarDedupsCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun selectDistinctStarDedupsCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE tags (label TEXT COLLATE NOCASE)")
|
||||
db.run("INSERT INTO tags VALUES ('Bob'), ('bob'), ('Alice')")
|
||||
val result = db.select("SELECT DISTINCT * FROM tags ORDER BY label")
|
||||
assertEquals(listOf("Alice", "Bob").map { listOf(Value.TextValue(it)) }, result.rows)
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.selectDistinctOnDedupsCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun selectDistinctOnDedupsCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE people (id INTEGER PRIMARY KEY, name TEXT COLLATE NOCASE, hits INTEGER)")
|
||||
db.run("INSERT INTO people VALUES (1, 'Bob', 10), (2, 'bob', 20), (3, 'Alice', 5)")
|
||||
val result = db.select("SELECT DISTINCT ON (name) name, hits FROM people ORDER BY name, id")
|
||||
assertEquals(
|
||||
listOf("Alice" to 5L, "Bob" to 10L).map { (name, hits) -> listOf(Value.TextValue(name), int(hits)) },
|
||||
result.rows
|
||||
)
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.countDistinctDedupsCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun countDistinctDedupsCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.seedNames()
|
||||
assertEquals(int(3), db.select("SELECT COUNT(DISTINCT name) FROM people").rows.single().single())
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.plainUnionDedupsCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun plainUnionDedupsCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.seedNames()
|
||||
val result = db.select("SELECT name FROM people WHERE id = 1 UNION SELECT name FROM people WHERE id = 2")
|
||||
assertEquals(listOf(listOf(Value.TextValue("Bob"))), result.rows)
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.intersectMatchesCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun intersectMatchesCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.seedNames()
|
||||
val result = db.select("SELECT name FROM people WHERE id = 1 INTERSECT SELECT name FROM people WHERE id = 2")
|
||||
assertEquals(listOf(listOf(Value.TextValue("Bob"))), result.rows)
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.exceptExcludesCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun exceptExcludesCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.seedNames()
|
||||
val result = db.select("SELECT name FROM people WHERE id IN (1, 4) EXCEPT SELECT name FROM people WHERE id = 2")
|
||||
assertEquals(listOf(listOf(Value.TextValue("Zoe"))), result.rows)
|
||||
}
|
||||
|
||||
/** Mirrors [kestrel.ColumnCollationTest.recursiveCteWithUnionDedupsCaseVariantsThroughTheColumnsDeclaredCollation]. */
|
||||
@Test
|
||||
fun recursiveCteWithUnionDedupsCaseVariantsThroughTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE origin (name TEXT COLLATE NOCASE)")
|
||||
db.run("INSERT INTO origin VALUES ('Bob')")
|
||||
db.run("CREATE TABLE steps (name TEXT COLLATE NOCASE, next_name TEXT COLLATE NOCASE)")
|
||||
db.run("INSERT INTO steps VALUES ('Bob', 'Carol'), ('Carol', 'bob')")
|
||||
val result = db.select(
|
||||
"WITH RECURSIVE walk(name) AS (" +
|
||||
"SELECT name FROM origin " +
|
||||
"UNION " +
|
||||
"SELECT steps.next_name FROM steps JOIN walk ON steps.name = walk.name" +
|
||||
") SELECT name FROM walk ORDER BY name"
|
||||
)
|
||||
assertEquals(listOf(listOf(Value.TextValue("Bob")), listOf(Value.TextValue("Carol"))), result.rows)
|
||||
}
|
||||
|
||||
/**
|
||||
* [DiskTable.rejectDuplicateUniqueConstraints] (declarative `UNIQUE`, heap-scanned on every
|
||||
* write, no backing index) folded through [kestrel.engine.collationFoldedUniquenessKey] -
|
||||
* mirrors [kestrel.ColumnCollationTest.uniqueConstraintHonorsTheColumnsDeclaredCollation].
|
||||
*/
|
||||
@Test
|
||||
fun declarativeUniqueConstraintHonorsTheColumnsDeclaredCollation() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE u1 (id INTEGER PRIMARY KEY, name TEXT COLLATE NOCASE UNIQUE)")
|
||||
db.run("INSERT INTO u1 VALUES (1, 'Bob')")
|
||||
assertFailsWith<DiskTableException> { db.run("INSERT INTO u1 VALUES (2, 'bob')") }
|
||||
}
|
||||
|
||||
/** Control negative: a `UNIQUE` column with no declared `COLLATE` behaves exactly as before this session. */
|
||||
@Test
|
||||
fun declarativeUniqueConstraintWithNoDeclaredCollationStaysBinary() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE u3 (id INTEGER PRIMARY KEY, name TEXT UNIQUE)")
|
||||
db.run("INSERT INTO u3 VALUES (1, 'Bob')")
|
||||
db.run("INSERT INTO u3 VALUES (2, 'bob')")
|
||||
assertEquals(2, db.select("SELECT id FROM u3").rows.size)
|
||||
}
|
||||
|
||||
/**
|
||||
* [DiskTable.backfillSecondaryIndex]'s pre-existing-duplicate check, also folded through
|
||||
* [kestrel.engine.collationFoldedUniquenessKey] - two rows already differing only by case
|
||||
* under a `NOCASE`-declared column must now fail `CREATE UNIQUE INDEX` cleanly instead of
|
||||
* silently building an index that lies about uniqueness.
|
||||
*/
|
||||
@Test
|
||||
fun createUniqueIndexHonorsTheColumnsDeclaredCollationAgainstPreexistingRows() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE u2 (id INTEGER PRIMARY KEY, name TEXT COLLATE NOCASE)")
|
||||
db.run("INSERT INTO u2 VALUES (1, 'Bob'), (2, 'bob')")
|
||||
assertFailsWith<DiskTableException> { db.run("CREATE UNIQUE INDEX idxU2 ON u2 (name)") }
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user