test: cover rowsFrameShorthandIsWrittenBackOutInCanonicalBetweenForm
This commit is contained in:
1 parent
b5f8b44728
commit
310a2f10dc
1 file changed
+159
@@ -802,3 +802,162 @@ class SqlWriterTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rowsFrameShorthandIsWrittenBackOutInCanonicalBetweenForm() {
|
||||
run("CREATE TABLE employees (id INTEGER PRIMARY KEY, salary INTEGER)")
|
||||
run("INSERT INTO employees VALUES (1, 400), (2, 300)")
|
||||
val statement = parseOne(
|
||||
"CREATE VIEW shorthand AS SELECT id, SUM(salary) OVER (ORDER BY id ROWS 1 PRECEDING) AS s FROM employees"
|
||||
)
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("ROWS BETWEEN 1 PRECEDING AND CURRENT ROW"), rendered)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unboundedFrameBoundsRoundTripThroughSqlWriter() {
|
||||
run("CREATE TABLE employees (id INTEGER PRIMARY KEY, salary INTEGER)")
|
||||
run("INSERT INTO employees VALUES (1, 400), (2, 300)")
|
||||
val statement = parseOne(
|
||||
"CREATE VIEW wholePartition AS SELECT id, " +
|
||||
"SUM(salary) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS s FROM employees"
|
||||
)
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING"), rendered)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createViewOverAnExplicitRangeFrameRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE sales (id INTEGER PRIMARY KEY, amount INTEGER)")
|
||||
run("INSERT INTO sales VALUES (1, 10), (2, 20), (3, 20), (4, 30), (5, 50)")
|
||||
val statement = parseOne(
|
||||
"CREATE VIEW valueTotals AS SELECT id, " +
|
||||
"SUM(amount) OVER (ORDER BY amount RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWING) AS s FROM sales"
|
||||
)
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("OVER (ORDER BY amount RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWING)"), rendered)
|
||||
run(rendered)
|
||||
val result = select("SELECT id, s FROM valueTotals ORDER BY id ASC")
|
||||
assertEquals(
|
||||
listOf(50L, 80L, 80L, 70L, 50L),
|
||||
result.rows.map { (it[1] as Value.IntegerValue).value }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createViewOverAnExcludeCurrentRowFrameRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE sales (id INTEGER PRIMARY KEY, amount INTEGER)")
|
||||
run("INSERT INTO sales VALUES (1, 10), (2, 20), (3, 20), (4, 30), (5, 50)")
|
||||
val statement = parseOne(
|
||||
"CREATE VIEW excludingSelf AS SELECT id, SUM(amount) OVER (" +
|
||||
"ORDER BY amount ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW" +
|
||||
") AS s FROM sales"
|
||||
)
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(
|
||||
rendered.contains("ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW"),
|
||||
rendered
|
||||
)
|
||||
run(rendered)
|
||||
val result = select("SELECT id, s FROM excludingSelf ORDER BY id ASC")
|
||||
assertEquals(
|
||||
listOf(120L, 110L, 110L, 100L, 80L),
|
||||
result.rows.map { (it[1] as Value.IntegerValue).value }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createViewOverAnExplicitGroupsFrameRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE sales (id INTEGER PRIMARY KEY, amount INTEGER)")
|
||||
run("INSERT INTO sales VALUES (1, 10), (2, 20), (3, 20), (4, 30), (5, 50)")
|
||||
val statement = parseOne(
|
||||
"CREATE VIEW groupTotals AS SELECT id, " +
|
||||
"SUM(amount) OVER (ORDER BY amount GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS s FROM sales"
|
||||
)
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("OVER (ORDER BY amount GROUPS BETWEEN 1 PRECEDING AND 1 FOLLOWING)"), rendered)
|
||||
run(rendered)
|
||||
val result = select("SELECT id, s FROM groupTotals ORDER BY id ASC")
|
||||
assertEquals(
|
||||
listOf(50L, 80L, 80L, 120L, 80L),
|
||||
result.rows.map { (it[1] as Value.IntegerValue).value }
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun excludeNoOthersIsOmittedFromRenderedSqlSinceItIsTheDefault() {
|
||||
run("CREATE TABLE sales (id INTEGER PRIMARY KEY, amount INTEGER)")
|
||||
run("INSERT INTO sales VALUES (1, 10), (2, 20)")
|
||||
val statement = parseOne(
|
||||
"CREATE VIEW totals AS SELECT id, SUM(amount) OVER (" +
|
||||
"ORDER BY amount ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS" +
|
||||
") AS s FROM sales"
|
||||
)
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(!rendered.contains("EXCLUDE"), rendered)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertOnConflictDoNothingRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)")
|
||||
run("INSERT INTO accounts VALUES (1, 100)")
|
||||
val statement = parseOne("INSERT INTO accounts VALUES (1, 999) ON CONFLICT (id) DO NOTHING")
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("ON CONFLICT (id) DO NOTHING"), rendered)
|
||||
run(rendered)
|
||||
assertEquals(listOf(listOf(Value.IntegerValue(100))), select("SELECT balance FROM accounts WHERE id = 1").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertOnConflictDoUpdateWithExcludedAndWhereRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)")
|
||||
run("INSERT INTO accounts VALUES (1, 100)")
|
||||
val statement = parseOne(
|
||||
"INSERT INTO accounts VALUES (1, 50) ON CONFLICT (id) DO UPDATE SET balance = accounts.balance + excluded.balance WHERE excluded.balance > 0"
|
||||
)
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("ON CONFLICT (id) DO UPDATE SET balance = (accounts.balance + excluded.balance) WHERE (excluded.balance > 0)"), rendered)
|
||||
run(rendered)
|
||||
assertEquals(listOf(listOf(Value.IntegerValue(150))), select("SELECT balance FROM accounts WHERE id = 1").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createTriggerRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE orders (id INTEGER PRIMARY KEY, amount INTEGER)")
|
||||
run("CREATE TABLE audit (order_id INTEGER)")
|
||||
val statement = parseOne(
|
||||
"CREATE TRIGGER log_insert AFTER INSERT ON orders FOR EACH ROW WHEN NEW.amount > 0 " +
|
||||
"BEGIN INSERT INTO audit VALUES (NEW.id); END"
|
||||
)
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("CREATE TRIGGER log_insert AFTER INSERT ON orders FOR EACH ROW WHEN"), rendered)
|
||||
assertTrue(rendered.contains("INSERT INTO audit VALUES (NEW.id)"), rendered)
|
||||
run(rendered)
|
||||
run("INSERT INTO orders VALUES (1, 50)")
|
||||
assertEquals(listOf(listOf(Value.IntegerValue(1))), select("SELECT order_id FROM audit").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dropTriggerRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE t (id INTEGER)")
|
||||
run("CREATE TRIGGER log AFTER INSERT ON t FOR EACH ROW BEGIN DELETE FROM t WHERE 1 = 0; END")
|
||||
val rendered = SqlWriter.write(parseOne("DROP TRIGGER log"))
|
||||
assertEquals("DROP TRIGGER log;", rendered)
|
||||
run(rendered)
|
||||
assertFailsWith<KestrelException> { run("DROP TRIGGER log") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createSequenceRoundTripsThroughSqlWriter() {
|
||||
val statement = parseOne("CREATE SEQUENCE seq START WITH 5 INCREMENT BY 2 MAXVALUE 100 CYCLE")
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("CREATE SEQUENCE seq"), rendered)
|
||||
assertTrue(rendered.contains("INCREMENT BY 2"), rendered)
|
||||
assertTrue(rendered.contains("MAXVALUE 100"), rendered)
|
||||
assertTrue(rendered.contains("START WITH 5"), rendered)
|
||||
assertTrue(rendered.contains("CYCLE"), rendered)
|
||||
run(rendered)
|
||||
run("CREATE TABLE t (id INTEGER)")
|
||||
run("INSERT INTO t VALUES (NEXTVAL('seq'))")
|
||||
assertEquals(listOf(listOf(Value.IntegerValue(5))), select("SELECT id FROM t").rows)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user