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
|
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.Assignment
|
||||||
|
import kestrel.sql.ast.BetweenExpression
|
||||||
import kestrel.sql.ast.BinaryExpression
|
import kestrel.sql.ast.BinaryExpression
|
||||||
import kestrel.sql.ast.BinaryOperator
|
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.ColumnExpression
|
||||||
|
import kestrel.sql.ast.CreateIndexStatement
|
||||||
|
import kestrel.sql.ast.CreateSequenceStatement
|
||||||
import kestrel.sql.ast.CreateTableStatement
|
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.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.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.Expression
|
||||||
import kestrel.sql.ast.ExpressionProjection
|
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.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.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.SelectStatement
|
||||||
|
import kestrel.sql.ast.SetOperationStatement
|
||||||
|
import kestrel.sql.ast.SetOperator
|
||||||
import kestrel.sql.ast.StarProjection
|
import kestrel.sql.ast.StarProjection
|
||||||
import kestrel.sql.ast.Statement
|
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.UnaryExpression
|
||||||
import kestrel.sql.ast.UnaryOperator
|
import kestrel.sql.ast.UnaryOperator
|
||||||
import kestrel.sql.ast.UpdateStatement
|
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.lexer.Lexer
|
||||||
import kestrel.sql.parser.Parser
|
import kestrel.sql.parser.Parser
|
||||||
|
import kestrel.storage.Collation
|
||||||
import kestrel.storage.ColumnType
|
import kestrel.storage.ColumnType
|
||||||
import kestrel.storage.Value
|
import kestrel.storage.Value
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
import kotlin.test.assertFalse
|
||||||
|
import kotlin.test.assertNotNull
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
@@ -36,6 +98,8 @@ class ParserTest {
|
|||||||
|
|
||||||
private fun whereOf(sql: String): Expression = (parseOne(sql) as SelectStatement).where!!
|
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 =
|
private fun firstProjection(sql: String): Expression =
|
||||||
((parseOne(sql) as SelectStatement).projection as ExpressionProjection).items.first().expression
|
((parseOne(sql) as SelectStatement).projection as ExpressionProjection).items.first().expression
|
||||||
|
|
||||||
@@ -55,6 +119,38 @@ class ParserTest {
|
|||||||
assertTrue(!statement.columns[2].notNull)
|
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
|
@Test
|
||||||
fun parsesInsertWithoutColumnList() {
|
fun parsesInsertWithoutColumnList() {
|
||||||
val statement = parseOne("INSERT INTO users VALUES (1, 'ada', 36)")
|
val statement = parseOne("INSERT INTO users VALUES (1, 'ada', 36)")
|
||||||
@@ -71,11 +167,20 @@ class ParserTest {
|
|||||||
assertEquals(3, statement.rows.size)
|
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
|
@Test
|
||||||
fun parsesSelectStar() {
|
fun parsesSelectStar() {
|
||||||
val statement = parseOne("SELECT * FROM users") as SelectStatement
|
val statement = parseOne("SELECT * FROM users") as SelectStatement
|
||||||
assertEquals(StarProjection, statement.projection)
|
assertEquals(StarProjection, statement.projection)
|
||||||
assertEquals("users", statement.tableName)
|
assertEquals("users", tableName(statement))
|
||||||
assertNull(statement.where)
|
assertNull(statement.where)
|
||||||
assertNull(statement.orderBy)
|
assertNull(statement.orderBy)
|
||||||
assertNull(statement.limit)
|
assertNull(statement.limit)
|
||||||
@@ -88,10 +193,90 @@ class ParserTest {
|
|||||||
) as SelectStatement
|
) as SelectStatement
|
||||||
val projection = statement.projection as ExpressionProjection
|
val projection = statement.projection as ExpressionProjection
|
||||||
assertEquals("who", projection.items[0].alias)
|
assertEquals("who", projection.items[0].alias)
|
||||||
assertEquals(true, statement.orderBy!!.descending)
|
assertEquals(true, statement.orderBy!!.keys.single().descending)
|
||||||
assertEquals(5, statement.limit)
|
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
|
@Test
|
||||||
fun parsesDeleteAndDropAndUpdate() {
|
fun parsesDeleteAndDropAndUpdate() {
|
||||||
assertTrue(parseOne("DELETE FROM t WHERE id = 1") is DeleteStatement)
|
assertTrue(parseOne("DELETE FROM t WHERE id = 1") is DeleteStatement)
|
||||||
|
|||||||
Reference in new issue
Block a user