Skip to content

Commit b4ba655

Browse files
committed
Dont require default columns
1 parent 07d1aec commit b4ba655

6 files changed

Lines changed: 90 additions & 38 deletions

File tree

Sources/Compiler/Columns.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,20 @@ extension Columns {
2323
public struct Column: Equatable, Sendable {
2424
public let type: Type
2525
public let isGenerated: Bool
26+
public let hasDefault: Bool
2627

27-
public init(type: Type, isGenerated: Bool = false) {
28+
public init(
29+
type: Type,
30+
hasDefault: Bool = false,
31+
isGenerated: Bool = false
32+
) {
2833
self.type = type
34+
self.hasDefault = hasDefault
2935
self.isGenerated = isGenerated
3036
}
3137

3238
public var isRequired: Bool {
33-
guard !isGenerated else { return false }
34-
return !type.isOptional
39+
return !isGenerated && !hasDefault && !type.isOptional
3540
}
3641

3742
public func mapType(_ transform: (Type) -> Type) -> Column {

Sources/Compiler/Sema/StmtTypeChecker.swift

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,13 +1165,7 @@ extension StmtTypeChecker {
11651165
case let .columns(columnsDefs, constraints, options):
11661166
var columns: Columns = [:]
11671167
for (name, def) in columnsDefs {
1168-
let type = typeFor(
1169-
column: def,
1170-
tableColumns: columns,
1171-
tableName: createTable.name.value
1172-
)
1173-
let isGenerated = def.constraints.contains { $0.isGenerated }
1174-
let column = Column(type: type, isGenerated: isGenerated)
1168+
let column = column(for: def, columns: columns, tableName: createTable.name.value)
11751169
columns.append(column, for: name.value)
11761170
}
11771171

@@ -1200,6 +1194,37 @@ extension StmtTypeChecker {
12001194
}
12011195
}
12021196

1197+
mutating func column(
1198+
for columnDef: ColumnDefSyntax,
1199+
columns: Columns,
1200+
tableName: Substring
1201+
) -> Column {
1202+
let type = typeFor(
1203+
column: columnDef,
1204+
tableColumns: columns,
1205+
tableName: tableName
1206+
)
1207+
1208+
var isGenerated = false
1209+
var hasDefault = false
1210+
1211+
for constraint in columnDef.constraints {
1212+
isGenerated = constraint.isGenerated || isGenerated
1213+
hasDefault = constraint.isDefault || isGenerated
1214+
1215+
switch constraint.kind {
1216+
case .primaryKey(_, _, true), .default:
1217+
hasDefault = true
1218+
case .generated:
1219+
isGenerated = true
1220+
default:
1221+
break
1222+
}
1223+
}
1224+
1225+
return Column(type: type, hasDefault: hasDefault, isGenerated: isGenerated)
1226+
}
1227+
12031228
mutating func typeCheck(alterTable: AlterTableStmtSyntax) {
12041229
var tableName = qualifedName(for: alterTable.name, in: alterTable.schemaName)
12051230

@@ -1229,15 +1254,9 @@ extension StmtTypeChecker {
12291254
table.name = tableName
12301255
case let .renameColumn(oldName, newName):
12311256
table.columns.rename(oldName.value, to: newName.value)
1232-
case let .addColumn(column):
1233-
let newType = typeFor(
1234-
column: column,
1235-
tableColumns: table.columns,
1236-
tableName: table.name.name
1237-
)
1238-
let isGenerated = column.constraints.contains { $0.isGenerated }
1239-
let newColumn = Column(type: newType, isGenerated: isGenerated)
1240-
table.columns.append(newColumn, for: column.name.value)
1257+
case let .addColumn(def):
1258+
let column = column(for: def, columns: table.columns, tableName: table.name.name)
1259+
table.columns.append(column, for: def.name.value)
12411260
case let .dropColumn(column):
12421261
table.columns = Columns(table.columns.filter { $0.key != column.value })
12431262
}

Sources/Compiler/Syntax/ColumnConstraintSyntax.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,11 @@ struct ColumnConstraintSyntax: Syntax {
4747
default: return false
4848
}
4949
}
50+
51+
var isDefault: Bool {
52+
switch kind {
53+
case .default: return true
54+
default: return false
55+
}
56+
}
5057
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// GenCommand.swift
2+
// GenerateCommand.swift
33
// Otter
44
//
55
// Created by Wes Wickwire on 5/21/25.
@@ -10,8 +10,8 @@ import Compiler
1010
import Foundation
1111
import SwiftSyntax
1212

13-
struct GenCommand: AsyncParsableCommand {
14-
static let configuration = CommandConfiguration(commandName: "gen")
13+
struct GenerateCommand: AsyncParsableCommand {
14+
static let configuration = CommandConfiguration(commandName: "generate")
1515

1616
@Option(name: .shortAndLong, help: "The root directory of the Otter sources")
1717
var path: String = FileManager.default.currentDirectoryPath

Sources/OtterCLI/Otter.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import SwiftSyntax
1313
@main
1414
struct Otter: AsyncParsableCommand {
1515
static let configuration = CommandConfiguration(
16-
subcommands: [GenCommand.self, InitCommand.self, MigrateCommand.self, QueriesCommand.self],
17-
defaultSubcommand: GenCommand.self
16+
subcommands: [GenerateCommand.self, InitCommand.self, MigrateCommand.self, QueriesCommand.self],
17+
defaultSubcommand: GenerateCommand.self
1818
)
1919
}
2020

Tests/CompilerTests/Compiler/CompileInsert.sql

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
CREATE TABLE user (
2-
id INTEGER,
2+
id INTEGER PRIMARY KEY AUTOINCREMENT,
33
name TEXT,
4+
age INTEGER NOT NULL DEFAULT 0,
45
description TEXT GENERATED ALWAYS AS (name || 'is a user')
56
);
67

78
-- CHECK: SIGNATURE
89
-- CHECK: PARAMETERS
910
-- CHECK: PARAMETER
10-
-- CHECK: TYPE INTEGER?
11+
-- CHECK: TYPE INTEGER
1112
-- CHECK: INDEX 1
1213
-- CHECK: NAME id
1314
-- CHECK: PARAMETER
1415
-- CHECK: TYPE TEXT?
1516
-- CHECK: INDEX 2
1617
-- CHECK: NAME name
18+
-- CHECK: PARAMETER
19+
-- CHECK: TYPE INTEGER
20+
-- CHECK: INDEX 3
21+
-- CHECK: NAME age
1722
-- CHECK: TABLES
1823
-- CHECK: user
19-
INSERT INTO user (id, name) VALUES (?, ?);
24+
INSERT INTO user (id, name, age) VALUES (?, ?, ?);
2025

2126
-- CHECK: SIGNATURE
2227
-- CHECK: PARAMETERS
2328
-- CHECK: PARAMETER
24-
-- CHECK: TYPE INTEGER?
29+
-- CHECK: TYPE INTEGER
2530
-- CHECK: INDEX 1
2631
-- CHECK: NAME id
2732
-- CHECK: PARAMETER
@@ -31,8 +36,9 @@ INSERT INTO user (id, name) VALUES (?, ?);
3136
-- CHECK: OUTPUT_CHUNKS
3237
-- CHECK: CHUNK
3338
-- CHECK: OUTPUT
34-
-- CHECK: id INTEGER?
39+
-- CHECK: id INTEGER
3540
-- CHECK: name TEXT?
41+
-- CHECK: age INTEGER
3642
-- CHECK: description TEXT?
3743
-- CHECK: TABLES
3844
-- CHECK: user
@@ -41,23 +47,23 @@ INSERT INTO user (id, name) VALUES (?, ?) RETURNING *;
4147
-- CHECK: SIGNATURE
4248
-- CHECK: PARAMETERS
4349
-- CHECK: PARAMETER
44-
-- CHECK: TYPE INTEGER?
50+
-- CHECK: TYPE INTEGER
4551
-- CHECK: INDEX 1
4652
-- CHECK: NAME id
4753
-- CHECK: PARAMETER
4854
-- CHECK: TYPE TEXT?
4955
-- CHECK: INDEX 2
5056
-- CHECK: NAME name
5157
-- CHECK: PARAMETER
52-
-- CHECK: TYPE INTEGER?
58+
-- CHECK: TYPE INTEGER
5359
-- CHECK: INDEX 3
5460
-- CHECK: NAME id2
5561
-- CHECK: PARAMETER
5662
-- CHECK: TYPE TEXT?
5763
-- CHECK: INDEX 4
5864
-- CHECK: NAME name2
5965
-- CHECK: PARAMETER
60-
-- CHECK: TYPE INTEGER?
66+
-- CHECK: TYPE INTEGER
6167
-- CHECK: INDEX 5
6268
-- CHECK: NAME id3
6369
-- CHECK: PARAMETER
@@ -67,8 +73,9 @@ INSERT INTO user (id, name) VALUES (?, ?) RETURNING *;
6773
-- CHECK: OUTPUT_CHUNKS
6874
-- CHECK: CHUNK
6975
-- CHECK: OUTPUT
70-
-- CHECK: id INTEGER?
76+
-- CHECK: id INTEGER
7177
-- CHECK: name TEXT?
78+
-- CHECK: age INTEGER
7279
-- CHECK: description TEXT?
7380
-- CHECK: TABLES
7481
-- CHECK: user
@@ -77,21 +84,25 @@ INSERT INTO user (id, name) VALUES (?, ?), (?, ?), (?, ?) RETURNING *;
7784
-- CHECK: SIGNATURE
7885
-- CHECK: PARAMETERS
7986
-- CHECK: PARAMETER
80-
-- CHECK: TYPE INTEGER?
87+
-- CHECK: TYPE INTEGER
8188
-- CHECK: INDEX 1
8289
-- CHECK: NAME id
8390
-- CHECK: PARAMETER
8491
-- CHECK: TYPE TEXT?
8592
-- CHECK: INDEX 2
8693
-- CHECK: NAME name
94+
-- CHECK: PARAMETER
95+
-- CHECK: TYPE INTEGER
96+
-- CHECK: INDEX 3
97+
-- CHECK: NAME age
8798
-- CHECK: TABLES
8899
-- CHECK: user
89-
INSERT INTO user VALUES (?, ?);
100+
INSERT INTO user VALUES (?, ?, ?);
90101

91102
-- CHECK: SIGNATURE
92103
-- CHECK: PARAMETERS
93104
-- CHECK: PARAMETER
94-
-- CHECK: TYPE INTEGER?
105+
-- CHECK: TYPE INTEGER
95106
-- CHECK: INDEX 1
96107
-- CHECK: NAME id
97108
-- CHECK: PARAMETER
@@ -114,7 +125,7 @@ INSERT INTO user (id, name, description) VALUES (?, ?, ?);
114125
-- CHECK: INDEX 1
115126
-- CHECK: NAME name
116127
-- CHECK: PARAMETER
117-
-- CHECK: TYPE INTEGER?
128+
-- CHECK: TYPE INTEGER
118129
-- CHECK: INDEX 2
119130
-- CHECK: NAME id
120131
-- CHECK: TABLES
@@ -124,7 +135,17 @@ INSERT INTO user (name, id) VALUES (?, ?);
124135
-- CHECK: SIGNATURE
125136
-- CHECK: PARAMETERS
126137
-- CHECK: PARAMETER
127-
-- CHECK: TYPE INTEGER?
138+
-- CHECK: TYPE TEXT?
139+
-- CHECK: INDEX 1
140+
-- CHECK: NAME name
141+
-- CHECK: TABLES
142+
-- CHECK: user
143+
INSERT INTO user (name) VALUES (?);
144+
145+
-- CHECK: SIGNATURE
146+
-- CHECK: PARAMETERS
147+
-- CHECK: PARAMETER
148+
-- CHECK: TYPE INTEGER
128149
-- CHECK: INDEX 1
129150
-- CHECK: NAME id
130151
-- CHECK: PARAMETER

0 commit comments

Comments
 (0)