From b512c2c5c0c9270342a67798b4f370af2b366e8f Mon Sep 17 00:00:00 2001 From: DualFroz Date: Thu, 10 Sep 2026 12:22:36 +0200 Subject: [PATCH] test: cover createViewRoundTripsThroughSqlWriter --- src/test/kotlin/kestrel/SqlWriterTest.kt | 161 +++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/src/test/kotlin/kestrel/SqlWriterTest.kt b/src/test/kotlin/kestrel/SqlWriterTest.kt index 862b3f9..f9a3385 100644 --- a/src/test/kotlin/kestrel/SqlWriterTest.kt +++ b/src/test/kotlin/kestrel/SqlWriterTest.kt @@ -160,3 +160,164 @@ class SqlWriterTest { ) } + @Test + fun createViewRoundTripsThroughSqlWriter() { + seed() + writeThenReplay("CREATE VIEW letters AS SELECT id, category FROM t WHERE category IS NOT NULL") + val result = select("SELECT category FROM letters ORDER BY id ASC") + assertEquals(listOf(listOf(text("a")), listOf(text("b")), listOf(text("c"))), result.rows) + } + + @Test + fun createOrReplaceViewRoundTripsThroughSqlWriter() { + seed() + run("CREATE VIEW letters AS SELECT id FROM t") + writeThenReplay("CREATE OR REPLACE VIEW letters AS SELECT id FROM t WHERE id > 1") + val result = select("SELECT id FROM letters ORDER BY id ASC") + assertEquals(listOf(listOf(Value.IntegerValue(2)), listOf(Value.IntegerValue(3))), result.rows) + } + + @Test + fun createViewOverARollupGroupByRoundTripsThroughSqlWriter() { + run("CREATE TABLE sales (dept TEXT, amount INTEGER)") + run("INSERT INTO sales VALUES ('eng', 100), ('eng', 200), ('ops', 50)") + writeThenReplay("CREATE VIEW dept_totals AS SELECT dept, SUM(amount) AS total FROM sales GROUP BY ROLLUP (dept)") + val result = select("SELECT dept, total FROM dept_totals ORDER BY dept") + assertEquals( + listOf( + listOf(Value.NullValue, Value.IntegerValue(350)), + listOf(text("eng"), Value.IntegerValue(300)), + listOf(text("ops"), Value.IntegerValue(50)) + ), + result.rows + ) + } + + @Test + fun createViewOverStringAggWithASeparatorAndAnInternalOrderByRoundTripsThroughSqlWriter() { + run("CREATE TABLE sales (dept TEXT, region TEXT)") + run("INSERT INTO sales VALUES ('eng', 'us'), ('eng', 'eu')") + writeThenReplay( + "CREATE VIEW dept_regions AS SELECT dept, STRING_AGG(region, '/' ORDER BY region) AS regions " + + "FROM sales GROUP BY dept" + ) + val result = select("SELECT dept, regions FROM dept_regions") + assertEquals(listOf(listOf(text("eng"), text("eu/us"))), result.rows) + } + + @Test + fun createViewOverACountDistinctAggregateRoundTripsThroughSqlWriter() { + run("CREATE TABLE sales (dept TEXT, amount INTEGER)") + run("INSERT INTO sales VALUES ('eng', 100), ('eng', 100), ('eng', 200), ('ops', 100)") + writeThenReplay("CREATE VIEW dept_distinct_amounts AS SELECT dept, COUNT(DISTINCT amount) AS n FROM sales GROUP BY dept") + val result = select("SELECT dept, n FROM dept_distinct_amounts ORDER BY dept") + assertEquals( + listOf(listOf(text("eng"), Value.IntegerValue(2)), listOf(text("ops"), Value.IntegerValue(1))), + result.rows + ) + } + + @Test + fun createViewOverAFilteredAggregateRoundTripsThroughSqlWriter() { + run("CREATE TABLE sales (dept TEXT, amount INTEGER)") + run("INSERT INTO sales VALUES ('eng', 100), ('eng', 100), ('eng', 200), ('ops', 100)") + writeThenReplay( + "CREATE VIEW dept_high_value_counts AS SELECT dept, COUNT(*) FILTER (WHERE amount > 100) AS n " + + "FROM sales GROUP BY dept" + ) + val result = select("SELECT dept, n FROM dept_high_value_counts ORDER BY dept") + assertEquals( + listOf(listOf(text("eng"), Value.IntegerValue(1)), listOf(text("ops"), Value.IntegerValue(0))), + result.rows + ) + } + + @Test + fun createViewOverDistinctRoundTripsThroughSqlWriter() { + run("CREATE TABLE sales (dept TEXT, region TEXT)") + run("INSERT INTO sales VALUES ('eng', 'eu'), ('eng', 'eu'), ('ops', 'eu')") + writeThenReplay("CREATE VIEW depts AS SELECT DISTINCT dept FROM sales") + val result = select("SELECT dept FROM depts ORDER BY dept") + assertEquals(listOf(listOf(text("eng")), listOf(text("ops"))), result.rows) + } + + @Test + fun createViewOverLimitAndOffsetRoundTripsThroughSqlWriter() { + run("CREATE TABLE sales (dept TEXT, amount INTEGER)") + run("INSERT INTO sales VALUES ('eng', 300), ('eng', 200), ('ops', 100)") + writeThenReplay("CREATE VIEW second_highest AS SELECT dept, amount FROM sales ORDER BY amount DESC LIMIT 1 OFFSET 1") + val result = select("SELECT dept, amount FROM second_highest") + assertEquals(listOf(listOf(text("eng"), Value.IntegerValue(200))), result.rows) + } + + @Test + fun createViewOverDistinctOnRoundTripsThroughSqlWriter() { + run("CREATE TABLE sales (dept TEXT, amount INTEGER)") + run("INSERT INTO sales VALUES ('eng', 100), ('eng', 200), ('ops', 50)") + writeThenReplay( + "CREATE VIEW top_per_dept AS SELECT DISTINCT ON (dept) dept, amount FROM sales ORDER BY dept, amount DESC" + ) + val result = select("SELECT dept, amount FROM top_per_dept ORDER BY dept") + assertEquals( + listOf(listOf(text("eng"), Value.IntegerValue(200)), listOf(text("ops"), Value.IntegerValue(50))), + result.rows + ) + } + + @Test + fun createViewOverGroupingSetsRoundTripsThroughSqlWriter() { + run("CREATE TABLE sales (dept TEXT, region TEXT, amount INTEGER)") + run("INSERT INTO sales VALUES ('eng', 'eu', 100), ('eng', 'us', 200), ('ops', 'eu', 50)") + writeThenReplay( + "CREATE VIEW totals AS SELECT dept, region, SUM(amount) AS total FROM sales GROUP BY GROUPING SETS ((dept), (region))" + ) + val result = select("SELECT dept, region, total FROM totals ORDER BY dept, region") + assertEquals( + listOf( + listOf(Value.NullValue, text("eu"), Value.IntegerValue(150)), + listOf(Value.NullValue, text("us"), Value.IntegerValue(200)), + listOf(text("eng"), Value.NullValue, Value.IntegerValue(300)), + listOf(text("ops"), Value.NullValue, Value.IntegerValue(50)) + ), + result.rows + ) + } + + @Test + fun dropViewRoundTripsThroughSqlWriter() { + seed() + run("CREATE VIEW letters AS SELECT id FROM t") + writeThenReplay("DROP VIEW letters") + assertEquals(emptyList(), catalog.viewNames) + } + + @Test + fun createViewOverADerivedTableRoundTripsThroughSqlWriter() { + seed() + writeThenReplay( + "CREATE VIEW letters AS SELECT s.id, s.category FROM (SELECT id, category FROM t WHERE bio IS NULL) AS s" + ) + val result = select("SELECT id FROM letters") + assertEquals(listOf(listOf(Value.IntegerValue(2))), result.rows) + } + + @Test + fun createViewOverALateralJoinRoundTripsThroughSqlWriter() { + run("CREATE TABLE departments (id INTEGER PRIMARY KEY, name TEXT)") + run("CREATE TABLE employees (id INTEGER PRIMARY KEY, deptId INTEGER, name TEXT, salary INTEGER)") + run("INSERT INTO departments VALUES (1, 'eng'), (2, 'sales')") + run( + "INSERT INTO employees VALUES (1, 1, 'ada', 300), (2, 1, 'linus', 250), (3, 2, 'sam', 150)" + ) + val statement = parseOne( + "CREATE VIEW top_earners AS SELECT d.name AS dept, top.name AS emp FROM departments d " + + "JOIN LATERAL (SELECT e.name FROM employees e WHERE e.deptId = d.id " + + "ORDER BY e.salary DESC LIMIT 1) AS top ON TRUE" + ) + val rendered = SqlWriter.write(statement) + assertTrue(rendered.contains("LATERAL ("), rendered) + run(rendered) + val result = select("SELECT dept, emp FROM top_earners ORDER BY dept ASC") + assertEquals(listOf(listOf(text("eng"), text("ada")), listOf(text("sales"), text("sam"))), result.rows) + } +