test: cover tableName and parsesCreateTableWithoutTempIsNotTemporary
This commit is contained in:
1 parent
4a817d0837
commit
1e0560573b
1 file changed
+187
-2
@@ -1,29 +1,91 @@
|
||||
package kestrel
|
||||
|
||||
import kestrel.catalog.ForeignKeyAction
|
||||
import kestrel.sql.ast.AddColumn
|
||||
import kestrel.sql.ast.AlterSequenceStatement
|
||||
import kestrel.sql.ast.AlterTableStatement
|
||||
import kestrel.sql.ast.Assignment
|
||||
import kestrel.sql.ast.BetweenExpression
|
||||
import kestrel.sql.ast.BinaryExpression
|
||||
import kestrel.sql.ast.BinaryOperator
|
||||
import kestrel.sql.ast.CallExpression
|
||||
import kestrel.sql.ast.CaseExpression
|
||||
import kestrel.sql.ast.CastExpression
|
||||
import kestrel.sql.ast.ChangeColumnType
|
||||
import kestrel.sql.ast.CollateExpression
|
||||
import kestrel.sql.ast.ColumnExpression
|
||||
import kestrel.sql.ast.CreateIndexStatement
|
||||
import kestrel.sql.ast.CreateSequenceStatement
|
||||
import kestrel.sql.ast.CreateTableStatement
|
||||
import kestrel.sql.ast.CreateTriggerStatement
|
||||
import kestrel.sql.ast.CreateViewStatement
|
||||
import kestrel.sql.ast.CubeSpec
|
||||
import kestrel.sql.ast.CurrentValueExpression
|
||||
import kestrel.sql.ast.DeallocateStatement
|
||||
import kestrel.sql.ast.DeleteStatement
|
||||
import kestrel.sql.ast.DropColumn
|
||||
import kestrel.sql.ast.DropMode
|
||||
import kestrel.sql.ast.DropSequenceStatement
|
||||
import kestrel.sql.ast.DropTableStatement
|
||||
import kestrel.sql.ast.DropTriggerStatement
|
||||
import kestrel.sql.ast.DropViewStatement
|
||||
import kestrel.sql.ast.ExecuteStatement
|
||||
import kestrel.sql.ast.ExistsExpression
|
||||
import kestrel.sql.ast.ExplainStatement
|
||||
import kestrel.sql.ast.Expression
|
||||
import kestrel.sql.ast.ExpressionProjection
|
||||
import kestrel.sql.ast.FrameBoundType
|
||||
import kestrel.sql.ast.FrameExclude
|
||||
import kestrel.sql.ast.FrameUnit
|
||||
import kestrel.sql.ast.FunctionExpression
|
||||
import kestrel.sql.ast.GroupingSetsSpec
|
||||
import kestrel.sql.ast.InExpression
|
||||
import kestrel.sql.ast.InSubqueryExpression
|
||||
import kestrel.sql.ast.InsertStatement
|
||||
import kestrel.sql.ast.IsNullExpression
|
||||
import kestrel.sql.ast.JoinType
|
||||
import kestrel.sql.ast.LikeExpression
|
||||
import kestrel.sql.ast.LiteralExpression
|
||||
import kestrel.sql.ast.MergeActionExpression
|
||||
import kestrel.sql.ast.MergeMatchedDelete
|
||||
import kestrel.sql.ast.MergeMatchedUpdate
|
||||
import kestrel.sql.ast.MergeNotMatchedInsert
|
||||
import kestrel.sql.ast.MergeStatement
|
||||
import kestrel.sql.ast.NextValueExpression
|
||||
import kestrel.sql.ast.OrderKey
|
||||
import kestrel.sql.ast.ParameterExpression
|
||||
import kestrel.sql.ast.PrepareStatement
|
||||
import kestrel.sql.ast.QueryStatement
|
||||
import kestrel.sql.ast.RenameColumn
|
||||
import kestrel.sql.ast.RenameTable
|
||||
import kestrel.sql.ast.RollupSpec
|
||||
import kestrel.sql.ast.ScalarSubqueryExpression
|
||||
import kestrel.sql.ast.SelectStatement
|
||||
import kestrel.sql.ast.SetOperationStatement
|
||||
import kestrel.sql.ast.SetOperator
|
||||
import kestrel.sql.ast.StarProjection
|
||||
import kestrel.sql.ast.Statement
|
||||
import kestrel.sql.ast.SubquerySource
|
||||
import kestrel.sql.ast.TableSource
|
||||
import kestrel.sql.ast.TriggerEvent
|
||||
import kestrel.sql.ast.TriggerTiming
|
||||
import kestrel.sql.ast.TruncateTableStatement
|
||||
import kestrel.sql.ast.UnaryExpression
|
||||
import kestrel.sql.ast.UnaryOperator
|
||||
import kestrel.sql.ast.UpdateStatement
|
||||
import kestrel.sql.ast.WindowExpression
|
||||
import kestrel.sql.ast.WindowFunctionKind
|
||||
import kestrel.sql.ast.WithQuery
|
||||
import kestrel.sql.lexer.Lexer
|
||||
import kestrel.sql.parser.Parser
|
||||
import kestrel.storage.Collation
|
||||
import kestrel.storage.ColumnType
|
||||
import kestrel.storage.Value
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@@ -36,6 +98,8 @@ class ParserTest {
|
||||
|
||||
private fun whereOf(sql: String): Expression = (parseOne(sql) as SelectStatement).where!!
|
||||
|
||||
private fun tableName(select: QueryStatement): String = ((select as SelectStatement).from as TableSource).name
|
||||
|
||||
private fun firstProjection(sql: String): Expression =
|
||||
((parseOne(sql) as SelectStatement).projection as ExpressionProjection).items.first().expression
|
||||
|
||||
@@ -55,6 +119,38 @@ class ParserTest {
|
||||
assertTrue(!statement.columns[2].notNull)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesCreateTableWithoutTempIsNotTemporary() {
|
||||
val statement = parseOne("CREATE TABLE users (id INTEGER PRIMARY KEY)") as CreateTableStatement
|
||||
assertTrue(!statement.temporary)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesCreateTempTable() {
|
||||
val statement = parseOne("CREATE TEMP TABLE scratch (id INTEGER PRIMARY KEY, note TEXT)") as CreateTableStatement
|
||||
assertTrue(statement.temporary)
|
||||
assertEquals("scratch", statement.tableName)
|
||||
assertEquals(2, statement.columns.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesCreateTemporaryTable() {
|
||||
val statement = parseOne("CREATE TEMPORARY TABLE scratch (id INTEGER PRIMARY KEY)") as CreateTableStatement
|
||||
assertTrue(statement.temporary)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun tempKeywordIsCaseInsensitive() {
|
||||
val statement = parseOne("create temp table scratch (id integer primary key)") as CreateTableStatement
|
||||
assertTrue(statement.temporary)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun tempOnAnythingOtherThanTableIsAParseError() {
|
||||
assertFailsWith<ParseException> { parse("CREATE TEMP VIEW v AS SELECT 1") }
|
||||
assertFailsWith<ParseException> { parse("CREATE TEMP INDEX idx ON t (a)") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesInsertWithoutColumnList() {
|
||||
val statement = parseOne("INSERT INTO users VALUES (1, 'ada', 36)")
|
||||
@@ -71,11 +167,20 @@ class ParserTest {
|
||||
assertEquals(3, statement.rows.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesInsertValuesWithLiteralDefaultKeyword() {
|
||||
val statement = parseOne("INSERT INTO t (a, b, c) VALUES (1, DEFAULT, 3)") as InsertStatement
|
||||
assertEquals(3, statement.rows[0].size)
|
||||
assertNotNull(statement.rows[0][0])
|
||||
assertNull(statement.rows[0][1])
|
||||
assertNotNull(statement.rows[0][2])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesSelectStar() {
|
||||
val statement = parseOne("SELECT * FROM users") as SelectStatement
|
||||
assertEquals(StarProjection, statement.projection)
|
||||
assertEquals("users", statement.tableName)
|
||||
assertEquals("users", tableName(statement))
|
||||
assertNull(statement.where)
|
||||
assertNull(statement.orderBy)
|
||||
assertNull(statement.limit)
|
||||
@@ -88,10 +193,90 @@ class ParserTest {
|
||||
) as SelectStatement
|
||||
val projection = statement.projection as ExpressionProjection
|
||||
assertEquals("who", projection.items[0].alias)
|
||||
assertEquals(true, statement.orderBy!!.descending)
|
||||
assertEquals(true, statement.orderBy!!.keys.single().descending)
|
||||
assertEquals(5, statement.limit)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesLimitFollowedByOffset() {
|
||||
val statement = parseOne("SELECT id FROM users LIMIT 10 OFFSET 20") as SelectStatement
|
||||
assertEquals(10, statement.limit)
|
||||
assertEquals(20, statement.offset)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesOffsetFollowedByLimitInEitherOrder() {
|
||||
val statement = parseOne("SELECT id FROM users OFFSET 20 LIMIT 10") as SelectStatement
|
||||
assertEquals(10, statement.limit)
|
||||
assertEquals(20, statement.offset)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesOffsetAloneWithoutLimit() {
|
||||
val statement = parseOne("SELECT id FROM users OFFSET 5") as SelectStatement
|
||||
assertNull(statement.limit)
|
||||
assertEquals(5, statement.offset)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun offsetDefaultsToNullWhenAbsent() {
|
||||
val statement = parseOne("SELECT id FROM users LIMIT 5") as SelectStatement
|
||||
assertNull(statement.offset)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rejectsARepeatedLimitOrOffsetClause() {
|
||||
assertFailsWith<ParseException> { parse("SELECT id FROM users LIMIT 5 LIMIT 10") }
|
||||
assertFailsWith<ParseException> { parse("SELECT id FROM users OFFSET 5 OFFSET 10") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rejectsANonIntegerAfterOffset() {
|
||||
assertFailsWith<ParseException> { parse("SELECT id FROM users OFFSET 'five'") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesOrderByWithMultipleKeysAndIndependentDirections() {
|
||||
val statement = parseOne("SELECT name FROM users ORDER BY dept ASC, age DESC, id") as SelectStatement
|
||||
val keys = statement.orderBy!!.keys
|
||||
assertEquals(3, keys.size)
|
||||
assertEquals("dept", (keys[0].expression as ColumnExpression).name)
|
||||
assertEquals(false, keys[0].descending)
|
||||
assertEquals("age", (keys[1].expression as ColumnExpression).name)
|
||||
assertEquals(true, keys[1].descending)
|
||||
assertEquals("id", (keys[2].expression as ColumnExpression).name)
|
||||
assertEquals(false, keys[2].descending)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesOrderByWithExplicitNullsFirstAndNullsLastPerKey() {
|
||||
val statement = parseOne(
|
||||
"SELECT name FROM users ORDER BY dept NULLS FIRST, age DESC NULLS LAST, id"
|
||||
) as SelectStatement
|
||||
val keys = statement.orderBy!!.keys
|
||||
assertEquals(3, keys.size)
|
||||
assertEquals(false, keys[0].descending)
|
||||
assertEquals(true, keys[0].nullsFirst)
|
||||
assertEquals(true, keys[1].descending)
|
||||
assertEquals(false, keys[1].nullsFirst)
|
||||
assertEquals(false, keys[2].descending)
|
||||
assertNull(keys[2].nullsFirst)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nullsAndFirstAndLastRemainUsableAsOrdinaryColumnNamesOutsideTheNullsClause() {
|
||||
val statement = parseOne("SELECT id FROM users ORDER BY nulls DESC") as SelectStatement
|
||||
val key = statement.orderBy!!.keys.single()
|
||||
assertEquals(ColumnExpression("nulls"), key.expression)
|
||||
assertEquals(true, key.descending)
|
||||
assertNull(key.nullsFirst)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nullsClauseWithoutFirstOrLastFailsToParse() {
|
||||
assertFailsWith<ParseException> { parseOne("SELECT id FROM users ORDER BY age NULLS") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesDeleteAndDropAndUpdate() {
|
||||
assertTrue(parseOne("DELETE FROM t WHERE id = 1") is DeleteStatement)
|
||||
|
||||
Reference in new issue
Block a user