struct _CreateTableBuilder {} struct _PrimaryKeyBuilder {} struct _ForeignKeyBuilder {} struct _SQLExpressible {} struct _SQLSelectable {} struct _CreateTableSelectBuilder {} struct SQLColumn { var name: String init(name: String) { self.name = name } } enum SQL { static func create( table: String, temp: Bool = false, ifNotExists: Bool = false, withoutRowID: Bool = false) -> _CreateTableBuilder { return _CreateTableBuilder() } static func primaryKey( autoIncrement: Bool? = nil, order: _Order? = nil, onConflict: _ConflictResolution? = nil) -> _PrimaryKeyBuilder { return _PrimaryKeyBuilder() } static func foreignKey( table: String, columns: SQLColumn..., onDelete: _DeleteUpdateAction? = nil, onUpdate: _DeleteUpdateAction? = nil, deferrable: Bool? = nil) -> _ForeignKeyBuilder { return _ForeignKeyBuilder() } } extension _CreateTableBuilder { func column( name: SQLColumn, primaryKey: _PrimaryKeyBuilder = false, affinity: _Affinity = .numeric, notNull: _ConflictClause = false, unique: _ConflictClause = false, check: _SQLExpressible? = nil, default: _DefaultOption? = nil, collate: String? = nil, references: _ForeignKeyBuilder? = nil) -> _CreateTableBuilder { return _CreateTableBuilder() } func foreignKey( columns: SQLColumn..., onConflict: _ConflictResolution = .abort, references: _ForeignKeyBuilder) -> _CreateTableBuilder { return _CreateTableBuilder() } func primaryKey( columns: SQLColumn..., onConflict: _ConflictResolution = .abort) -> _CreateTableBuilder { return _CreateTableBuilder() } func unique( columns: SQLColumn..., onConflict: _ConflictResolution = .abort) -> _CreateTableBuilder { return _CreateTableBuilder() } func check(_ expr: _SQLExpressible) -> _CreateTableBuilder { return _CreateTableBuilder() } func select(_ expr: _SQLSelectable) -> _CreateTableSelectBuilder { return _CreateTableSelectBuilder() } } enum _DefaultOption { case number(Int) case literal(String) case expression(_SQLExpressible) } enum _DeleteUpdateAction { case none case restrict case setNull case setDefault case cascade } enum _ConflictResolution { case rollback case abort case fail case ignore case replace } enum _Order { case asc case desc } enum _ConflictClause { case onConflict(_ConflictResolution) case none } enum _Affinity { case integer case text case double case blob case numeric } protocol _ConflictResolvable { var resolution: _ConflictClause { get } } extension _ConflictClause: BooleanLiteralConvertible { init(booleanLiteral value: Bool) { self = value ? .onConflict(.abort) : .none } } extension _ConflictClause: _ConflictResolvable { var resolution: _ConflictClause { return self } } extension _PrimaryKeyBuilder: BooleanLiteralConvertible { init(booleanLiteral value: Bool) { self = value ? _PrimaryKeyBuilder() : _PrimaryKeyBuilder() } } extension _DefaultOption: IntegerLiteralConvertible { init(integerLiteral value: Int) { self = .number(value) } } extension SQLColumn: StringLiteralConvertible { init(unicodeScalarLiteral value: String) { self = SQLColumn(name: value) } init(extendedGraphemeClusterLiteral value: String) { self = SQLColumn(name: value) } init(stringLiteral value: String) { self = SQLColumn(name: value) } } extension _DefaultOption: StringLiteralConvertible { init(unicodeScalarLiteral value: String) { self = .literal(value) } init(extendedGraphemeClusterLiteral value: String) { self = .literal(value) } init(stringLiteral value: String) { self = .literal(value) } } SQL.create(table: "foo", ifNotExists: true) .column( name: "id", primaryKey: true, affinity: .integer, notNull: true) SQL.create(table: "foo", ifNotExists: true) .column( name: "id", primaryKey: SQL.primaryKey(autoIncrement: true), affinity: .integer, notNull: true) SQL.create(table: "foo", ifNotExists: true) .column( name: "id", primaryKey: SQL.primaryKey( autoIncrement: true, order: .desc, onConflict: .abort), affinity: .integer, notNull: true) SQL.create(table: "foo", ifNotExists: true) .column( name: "id", primaryKey: SQL.primaryKey(onConflict: .abort), affinity: .integer, notNull: true) SQL.create(table: "foo", ifNotExists: true) .column( name: "bar_id", affinity: .integer, references: SQL.foreignKey( table: "bar", columns: "id")) SQL.create(table: "foo", ifNotExists: true) .column( name: "bar_id", affinity: .integer, references: SQL.foreignKey( table: "bar", columns: "id", onDelete: .cascade, onUpdate: .cascade, deferrable: true)) let fooId: SQLColumn = "foo_id" let bazId: SQLColumn = "baz_id" let a: SQLColumn = "a" let b: SQLColumn = "b" let c: SQLColumn = "c" SQL.create(table: "bar", ifNotExists: true) .column(name: fooId, affinity: .integer) .column(name: bazId, affinity: .integer) .column(name: a, affinity: .integer) .column(name: b, affinity: .integer) .column(name: c, affinity: .integer) .unique(columns: fooId, bazId, onConflict: .rollback) .primaryKey(columns: a, b, c, onConflict: .rollback) // runtime error if multiple `primaryKey()` used .foreignKey( columns: fooId, onConflict: .rollback, references: SQL.foreignKey( table: "foo", columns: "id")) .foreignKey( columns: bazId, onConflict: .rollback, references: SQL.foreignKey( table: "baz", columns: "id")) SQL.create(table: "foo", ifNotExists: true) .column(name: "id", affinity: .integer) .column(name: "a", default: 1)