Skip to content

Commit 802961f

Browse files
committed
Create table from select
1 parent ffd6224 commit 802961f

7 files changed

Lines changed: 63 additions & 33 deletions

File tree

Sources/Compiler/Gen/Rewriter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ struct Rewriter {
108108
extension Rewriter: StmtSyntaxVisitor {
109109
func visit(_ stmt: borrowing CreateTableStmtSyntax) -> [Range<Substring.Index>] {
110110
switch stmt.kind {
111-
case .columns(let columns):
111+
case .columns(let columns, _, _):
112112
return columns.values.compactMap { $0.type.alias?.location.range }
113113
case .select:
114114
return []

Sources/Compiler/Parse/Parsers.swift

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ enum Parsers {
963963
}
964964

965965
static func windowDef(state: inout ParserState) -> WindowDefinitionSyntax {
966-
fatalError("TODO")
966+
fatalError("Not yet implemented")
967967
}
968968

969969
enum JoinClauseOrTableOrSubqueries {
@@ -1294,12 +1294,20 @@ enum Parsers {
12941294
state.consume(.table)
12951295

12961296
let ifNotExists = ifNotExists(state: &state)
1297+
let (schema, table) = tableAndSchemaName(state: &state)
12971298

1298-
if state.is(of: .as) {
1299-
fatalError("Implement SELECT statement")
1299+
if state.take(if: .as) {
1300+
let select = try selectStmt(state: &state)
1301+
return CreateTableStmtSyntax(
1302+
id: state.nextId(),
1303+
name: table,
1304+
schemaName: schema,
1305+
isTemporary: isTemporary,
1306+
onlyIfExists: ifNotExists,
1307+
kind: .select(select),
1308+
location: create.location.spanning(state.current.location)
1309+
)
13001310
} else {
1301-
let (schema, table) = tableAndSchemaName(state: &state)
1302-
13031311
let (columns, constraints) = try parens(state: &state) { state in
13041312
let columns = try createTableStmtColumns(state: &state)
13051313
let constraints = try tableConstraints(state: &state)
@@ -1314,9 +1322,7 @@ enum Parsers {
13141322
schemaName: schema,
13151323
isTemporary: isTemporary,
13161324
onlyIfExists: ifNotExists,
1317-
kind: .columns(columns),
1318-
constraints: constraints,
1319-
options: options,
1325+
kind: .columns(columns, constraints: constraints, options: options),
13201326
location: create.location.spanning(state.current.location)
13211327
)
13221328
}

Sources/Compiler/Sema/StmtTypeChecker.swift

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -937,15 +937,6 @@ extension StmtTypeChecker {
937937
}
938938

939939
mutating func typeCheck(createTable: CreateTableStmtSyntax) {
940-
if pragmas.contains(.requireStrictTables)
941-
&& !createTable.options.kind.contains(.strict) {
942-
diagnostics.add(.init(
943-
"Missing STRICT table option",
944-
at: createTable.location,
945-
suggestion: .append(" STRICT")
946-
))
947-
}
948-
949940
switch createTable.kind {
950941
case let .select(selectStmt):
951942
let signature = signature(for: selectStmt)
@@ -956,7 +947,7 @@ extension StmtTypeChecker {
956947
primaryKey: primaryKey(of: createTable, columns: columns),
957948
kind: .normal
958949
)
959-
case let .columns(columnsDefs):
950+
case let .columns(columnsDefs, constraints, options):
960951
var columns: Columns = [:]
961952
for (name, def) in columnsDefs {
962953
columns[name.value] = typeFor(
@@ -966,13 +957,27 @@ extension StmtTypeChecker {
966957
)
967958
}
968959

969-
validateTableConstraints(of: createTable, columns: columns)
960+
validateTableConstraints(
961+
of: createTable,
962+
columns: columns,
963+
constraints: constraints
964+
)
965+
970966
schema[createTable.name.value] = Table(
971967
name: createTable.name.value,
972968
columns: columns,
973969
primaryKey: primaryKey(of: createTable, columns: columns),
974970
kind: .normal
975971
)
972+
973+
if pragmas.contains(.requireStrictTables)
974+
&& !options.kind.contains(.strict) {
975+
diagnostics.add(.init(
976+
"Missing STRICT table option",
977+
at: createTable.location,
978+
suggestion: .append(" STRICT")
979+
))
980+
}
976981
}
977982
}
978983

@@ -1138,15 +1143,15 @@ extension StmtTypeChecker {
11381143
columns: Columns
11391144
) -> [Substring] {
11401145
// Any PK define by table constraints
1141-
let byTableConstraints: [([IndexedColumnSyntax], TableConstraintSyntax)] = stmt.constraints
1146+
let byTableConstraints: [([IndexedColumnSyntax], TableConstraintSyntax)] = stmt.constraints?
11421147
.compactMap { constraint -> ([IndexedColumnSyntax], TableConstraintSyntax)? in
11431148
guard case let .primaryKey(columns, _) = constraint.kind else { return nil }
11441149
return (columns, constraint)
1145-
}
1150+
} ?? []
11461151

11471152
// Any PK defined at the column level
11481153
let byColumnConstraints: [IdentifierSyntax]
1149-
if case let .columns(columns) = stmt.kind {
1154+
if case let .columns(columns, _, _) = stmt.kind {
11501155
byColumnConstraints = columns.values
11511156
.filter{ $0.constraints.contains(where: \.isPkConstraint) }
11521157
.map(\.name)
@@ -1194,9 +1199,10 @@ extension StmtTypeChecker {
11941199

11951200
private mutating func validateTableConstraints(
11961201
of stmt: CreateTableStmtSyntax,
1197-
columns: Columns
1202+
columns: Columns,
1203+
constraints: [TableConstraintSyntax]
11981204
) {
1199-
for constraint in stmt.constraints {
1205+
for constraint in constraints {
12001206
switch constraint.kind {
12011207
case .check(let expr):
12021208
inNewEnvironment { typeChecker in

Sources/Compiler/Syntax/Statements/CreateTableStmtSyntax.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,23 @@ struct CreateTableStmtSyntax: StmtSyntax {
1414
let isTemporary: Bool
1515
let onlyIfExists: Bool
1616
let kind: Kind
17-
let constraints: [TableConstraintSyntax]
18-
let options: TableOptionsSyntax
1917
let location: SourceLocation
2018

2119
typealias Columns = OrderedDictionary<IdentifierSyntax, ColumnDefSyntax>
2220

21+
var constraints: [TableConstraintSyntax]? {
22+
guard case let .columns(_, constraints, _) = kind else { return nil }
23+
return constraints
24+
}
25+
26+
var options: TableOptionsSyntax? {
27+
guard case let .columns(_, _, options) = kind else { return nil }
28+
return options
29+
}
30+
2331
enum Kind {
2432
case select(SelectStmtSyntax)
25-
case columns(Columns)
33+
case columns(Columns, constraints: [TableConstraintSyntax], options: TableOptionsSyntax)
2634
}
2735

2836
func accept<V>(visitor: inout V) -> V.StmtOutput where V : StmtSyntaxVisitor {

Tests/CompilerTests/Compiler/CompileCreateTable.sql

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ PRAGMA feather_require_strict_tables = TRUE;
4040
-- CHECK: PRIMARY_KEY
4141
-- CHECK: foo
4242
-- CHECK: KIND normal
43-
-- CHECK-ERROR: Missing STRICT table option
4443
-- CHECK-ERROR: Invalid type 'DECIMAL'
4544
-- CHECK-ERROR: Column 'bar' does not exist
45+
-- CHECK-ERROR: Missing STRICT table option
4646
CREATE TABLE baz (
4747
foo DECIMAL,
4848
PRIMARY KEY (foo, bar)
@@ -139,3 +139,13 @@ CREATE TABLE hasTableCheck (
139139
FOREIGN KEY (typo) REFERENCES doesNotExist (meh),
140140
FOREIGN KEY (foo) REFERENCES hasGenerated (foo)
141141
) STRICT;
142+
143+
-- CHECK: TABLE
144+
-- CHECK: NAME fromSelect
145+
-- CHECK: COLUMNS
146+
-- CHECK: KEY bar
147+
-- CHECK: VALUE INTEGER
148+
-- CHECK: KEY baz
149+
-- CHECK: VALUE TEXT?
150+
-- CHECK: KIND normal
151+
CREATE TABLE fromSelect AS SELECT * FROM foo;

Tests/CompilerTests/CompilerTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ class CompilerTests: XCTestCase {
3939
}
4040

4141
func testView() throws {
42-
try checkSchema(compile: "CompileView", prefix: "CHECK-SCHEMA", dump: true)
43-
try checkQueries(compile: "CompileView", prefix: "CHECK-QUERIES", dump: true)
42+
try checkSchema(compile: "CompileView", prefix: "CHECK-SCHEMA")
43+
try checkQueries(compile: "CompileView", prefix: "CHECK-QUERIES")
4444
}
4545

4646
func testFTS5() throws {
@@ -66,7 +66,7 @@ class CompilerTests: XCTestCase {
6666
}
6767

6868
func testTriggers() throws {
69-
try checkErrors(compile: "CompileTriggers", dump: true)
69+
try checkErrors(compile: "CompileTriggers")
7070
}
7171
}
7272

Tests/CompilerTests/ParserTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ final class ParserTests: XCTestCase {
5252
}
5353

5454
func testBindParameter() throws {
55-
try check(sqlFile: "ParseBindParameter", parser: Parsers.bindParameter, dump: true)
55+
try check(sqlFile: "ParseBindParameter", parser: Parsers.bindParameter)
5656
}
5757

5858
func testOpertators() throws {

0 commit comments

Comments
 (0)