From 7739e7114af8f5a6724cdd27c849f0cf91f7795b Mon Sep 17 00:00:00 2001 From: DualFroz Date: Thu, 10 Sep 2026 16:35:18 +0200 Subject: [PATCH] test: cover SubqueryTest and run --- src/test/kotlin/kestrel/SubqueryTest.kt | 164 ++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/test/kotlin/kestrel/SubqueryTest.kt diff --git a/src/test/kotlin/kestrel/SubqueryTest.kt b/src/test/kotlin/kestrel/SubqueryTest.kt new file mode 100644 index 0000000..4a250dd --- /dev/null +++ b/src/test/kotlin/kestrel/SubqueryTest.kt @@ -0,0 +1,164 @@ +package kestrel + +import kestrel.catalog.Catalog +import kestrel.engine.Executor +import kestrel.engine.SelectResult +import kestrel.engine.StatementResult +import kestrel.sql.lexer.Lexer +import kestrel.sql.parser.Parser +import kestrel.storage.Value +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +class SubqueryTest { + private val catalog = Catalog() + private val executor = Executor(catalog) + + private fun run(sql: String): List = + Parser(Lexer(sql).tokenize()).parseProgram().map { executor.execute(it) } + + private fun select(sql: String): SelectResult = run(sql).single() as SelectResult + + private fun int(value: Long) = Value.IntegerValue(value) + private fun text(value: String) = Value.TextValue(value) + + private fun seed() { + run("CREATE TABLE departments (id INTEGER PRIMARY KEY, name TEXT NOT NULL, budget INTEGER)") + run("CREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT NOT NULL, department_id INTEGER, salary INTEGER)") + run("INSERT INTO departments VALUES (1, 'eng', 1000), (2, 'sales', 500), (3, 'ops', 0)") + run( + "INSERT INTO employees VALUES " + + "(1, 'ada', 1, 120), (2, 'linus', 1, 90), (3, 'grace', 2, 80), (4, 'guido', 2, 70)" + ) + } + + @Test + fun scalarSubqueryComparesAgainstAggregateOfAnotherQuery() { + seed() + val result = select("SELECT name FROM employees WHERE salary > (SELECT AVG(salary) FROM employees) ORDER BY name") + assertEquals(listOf(listOf(text("ada"))), result.rows) + } + + @Test + fun scalarSubqueryReturningNoRowsEvaluatesToNull() { + seed() + val result = select("SELECT (SELECT id FROM departments WHERE name = 'nope') FROM departments WHERE id = 1") + assertEquals(listOf(listOf(Value.NullValue)), result.rows) + } + + @Test + fun scalarSubqueryReturningMultipleRowsFails() { + seed() + assertFailsWith { + select("SELECT (SELECT salary FROM employees) FROM departments WHERE id = 1") + } + } + + @Test + fun scalarSubqueryReturningMultipleColumnsFails() { + seed() + assertFailsWith { + select("SELECT (SELECT id, name FROM departments) FROM departments WHERE id = 1") + } + } + + @Test + fun correlatedScalarSubqueryInProjectionCountsPerRow() { + seed() + val result = select( + "SELECT d.name, (SELECT COUNT(*) FROM employees e WHERE e.department_id = d.id) " + + "FROM departments d ORDER BY d.id ASC" + ) + assertEquals( + listOf( + listOf(text("eng"), int(2)), + listOf(text("sales"), int(2)), + listOf(text("ops"), int(0)) + ), + result.rows + ) + } + + @Test + fun correlatedScalarSubqueryInWhereComparesAgainstOwnGroupAverage() { + seed() + val result = select( + "SELECT name FROM employees e WHERE e.salary > " + + "(SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = e.department_id) ORDER BY name ASC" + ) + assertEquals(listOf(listOf(text("ada")), listOf(text("grace"))), result.rows) + } + + @Test + fun inSubqueryMatchesUncorrelatedResultSet() { + seed() + val result = select("SELECT name FROM departments WHERE id IN (SELECT department_id FROM employees) ORDER BY name ASC") + assertEquals(listOf(listOf(text("eng")), listOf(text("sales"))), result.rows) + } + + @Test + fun notInSubqueryExcludesMatchingRows() { + seed() + val result = select("SELECT name FROM departments WHERE id NOT IN (SELECT department_id FROM employees)") + assertEquals(listOf(listOf(text("ops"))), result.rows) + } + + @Test + fun notInSubqueryWithNullInResultSetExcludesEverythingByThreeValuedLogic() { + run("CREATE TABLE d (id INTEGER)") + run("CREATE TABLE e (dept INTEGER)") + run("INSERT INTO d VALUES (1), (2)") + run("INSERT INTO e VALUES (1), (NULL)") + val result = select("SELECT id FROM d WHERE id NOT IN (SELECT dept FROM e)") + assertEquals(emptyList(), result.rows) + } + + @Test + fun inSubqueryRequiresExactlyOneColumn() { + seed() + assertFailsWith { + select("SELECT name FROM departments WHERE id IN (SELECT id, name FROM departments)") + } + } + + @Test + fun existsWithoutCorrelationChecksWhetherSubqueryHasAnyRows() { + seed() + val result = select("SELECT name FROM departments WHERE EXISTS (SELECT 1 FROM employees) ORDER BY name ASC") + assertEquals(listOf(listOf(text("eng")), listOf(text("ops")), listOf(text("sales"))), result.rows) + } + + @Test + fun correlatedExistsFindsDepartmentsWithEmployees() { + seed() + val result = select( + "SELECT name FROM departments d WHERE EXISTS " + + "(SELECT 1 FROM employees e WHERE e.department_id = d.id) ORDER BY name ASC" + ) + assertEquals(listOf(listOf(text("eng")), listOf(text("sales"))), result.rows) + } + + @Test + fun correlatedNotExistsFindsDepartmentsWithoutEmployees() { + seed() + val result = select( + "SELECT name FROM departments d WHERE NOT EXISTS " + + "(SELECT 1 FROM employees e WHERE e.department_id = d.id)" + ) + assertEquals(listOf(listOf(text("ops"))), result.rows) + } + + @Test + fun correlatedScalarSubqueryUsableInUpdateSet() { + seed() + run("CREATE TABLE dept_stats (id INTEGER PRIMARY KEY, headcount INTEGER)") + run("INSERT INTO dept_stats VALUES (1, 0), (2, 0), (3, 0)") + run( + "UPDATE dept_stats SET headcount = " + + "(SELECT COUNT(*) FROM employees WHERE employees.department_id = dept_stats.id)" + ) + val result = select("SELECT headcount FROM dept_stats ORDER BY id ASC") + assertEquals(listOf(listOf(int(2)), listOf(int(2)), listOf(int(0))), result.rows) + } +