Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add CREATE and DROP index queries #16

Merged
merged 2 commits into from
Jun 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions Sources/SQL/SQLCreateIndex.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
public protocol SQLCreateIndex: SQLSerializable {
associatedtype Modifier: SQLIndexModifier
associatedtype Identifier: SQLIdentifier
associatedtype TableIdentifier: SQLTableIdentifier

static func createIndex(_ identifier: Identifier, _ table: TableIdentifier, _ columns: [Identifier]) -> Self

var modifier: Modifier? { get set }
}

public struct GenericSQLCreateIndex<Modifier, Identifier, TableIdentifier>: SQLCreateIndex where
Modifier: SQLIndexModifier, Identifier: SQLIdentifier, TableIdentifier: SQLTableIdentifier
{
public typealias `Self` = GenericSQLCreateIndex<Modifier, Identifier, TableIdentifier>

/// See `SQLCreateIndex`.
public static func createIndex(_ identifier: Identifier, _ table: TableIdentifier, _ columns: [Identifier]) -> Self {
return .init(modifier: nil, identifier: identifier, table: table, columns: columns)
}

/// See `SQLCreateIndex`.
public var modifier: Modifier?

public var identifier: Identifier

public var table: TableIdentifier

public var columns: [Identifier]

/// See `SQLSerializable`.
public func serialize(_ binds: inout [Encodable]) -> String {
var sql: [String] = []
sql.append("CREATE")
if let modifier = modifier {
sql.append(modifier.serialize(&binds))
}
sql.append("INDEX")
sql.append(identifier.serialize(&binds))
sql.append("ON")
sql.append(table.serialize(&binds))
sql.append("(" + columns.serialize(&binds) + ")")
return sql.joined(separator: " ")
}
}
80 changes: 80 additions & 0 deletions Sources/SQL/SQLCreateIndexBuilder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
public final class SQLCreateIndexBuilder<Connection>: SQLQueryBuilder
where Connection: DatabaseQueryable, Connection.Query: SQLQuery
{
/// See `SQLColumnBuilder`.
public typealias ColumnDefinition = Connection.Query.AlterTable.ColumnDefinition

/// `AlterTable` query being built.
public var createIndex: Connection.Query.CreateIndex

/// See `SQLQueryBuilder`.
public var connection: Connection

/// See `SQLQueryBuilder`.
public var query: Connection.Query {
return .createIndex(createIndex)
}

public func unique() -> Self {
createIndex.modifier = .unique
return self
}

/// Creates a new `SQLCreateIndexBuilder`.
public init(_ createIndex: Connection.Query.CreateIndex, on connection: Connection) {
self.createIndex = createIndex
self.connection = connection
}
}

// MARK: Connection

extension DatabaseQueryable where Query: SQLQuery {
/// Creates a new `SQLCreateIndexBuilder`.
///
/// conn.create(index: "foo", on: \Planet.name)...
///
/// - parameters:
/// - table: Table to create index on.
/// - returns: `SQLCreateIndexBuilder`.
public func create<T, A>(
index identifier: Query.CreateIndex.Identifier,
on column: KeyPath<T, A>
) -> SQLCreateIndexBuilder<Self>
where T: SQLTable
{
return .init(.createIndex(identifier, .table(T.self), [.keyPath(column)]), on: self)
}

/// Creates a new `SQLCreateIndexBuilder`.
///
/// conn.create(index: "foo", on: \Planet.name, \Planet.id)...
///
/// - parameters:
/// - table: Table to create index on.
/// - returns: `SQLCreateIndexBuilder`.
public func create<T, A, B>(
index identifier: Query.CreateIndex.Identifier,
on a: KeyPath<T, A>, _ b: KeyPath<T, B>
) -> SQLCreateIndexBuilder<Self>
where T: SQLTable
{
return .init(.createIndex(identifier, .table(T.self), [.keyPath(a), .keyPath(b)]), on: self)
}

/// Creates a new `SQLCreateIndexBuilder`.
///
/// conn.create(index: "foo", on: \Planet.name, \Planet.id, \Planet.galaxyID)...
///
/// - parameters:
/// - table: Table to create index on.
/// - returns: `SQLCreateIndexBuilder`.
public func create<T, A, B, C>(
index identifier: Query.CreateIndex.Identifier,
on a: KeyPath<T, A>, _ b: KeyPath<T, B>, _ c: KeyPath<T, C>
) -> SQLCreateIndexBuilder<Self>
where T: SQLTable
{
return .init(.createIndex(identifier, .table(T.self), [.keyPath(a), .keyPath(b), .keyPath(c)]), on: self)
}
}
4 changes: 4 additions & 0 deletions Sources/SQL/SQLDropIndex.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public protocol SQLDropIndex: SQLSerializable { }

// No generic drop index since there is not a standard subset of this query type
// MySQL requires a table name to drop and other SQLs cannot have a table name passed
19 changes: 19 additions & 0 deletions Sources/SQL/SQLIndexModifier.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
public protocol SQLIndexModifier: SQLSerializable {
static var unique: Self { get }
}

public enum GenericSQLIndexModifier: SQLIndexModifier {
/// See `SQLIndexModifier`.
public static var unique: GenericSQLIndexModifier {
return ._unique
}

case _unique

/// See `SQLSerializable`.
public func serialize(_ binds: inout [Encodable]) -> String {
switch self {
case ._unique: return "UNIQUE"
}
}
}
6 changes: 5 additions & 1 deletion Sources/SQL/SQLQuery.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
public protocol SQLQuery: SQLSerializable {
associatedtype AlterTable: SQLAlterTable
associatedtype CreateIndex: SQLCreateIndex
associatedtype CreateTable: SQLCreateTable
associatedtype Delete: SQLDelete
associatedtype DropIndex: SQLDropIndex
associatedtype DropTable: SQLDropTable
associatedtype Insert: SQLInsert
associatedtype Select: SQLSelect
associatedtype Update: SQLUpdate

static func alterTable(_ alterTable: AlterTable) -> Self
static func createIndex(_ createIndex: CreateIndex) -> Self
static func createTable(_ createTable: CreateTable) -> Self
static func delete(_ delete: Delete) -> Self
static func delete(_ delete: Delete) -> Self
static func dropIndex(_ dropIndex: DropIndex) -> Self
static func dropTable(_ dropTable: DropTable) -> Self
static func insert(_ insert: Insert) -> Self
static func select(_ select: Select) -> Self
Expand Down
2 changes: 1 addition & 1 deletion Sources/SQL/SQLTableIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public protocol SQLTableIdentifier: SQLSerializable {
// MARK: Convenience

extension SQLTableIdentifier {
static func table<Table>(_ table: Table.Type) -> Self
public static func table<Table>(_ table: Table.Type) -> Self
where Table: SQLTable
{
return .table(.identifier(Table.sqlTableIdentifierString))
Expand Down
5 changes: 5 additions & 0 deletions Sources/SQLBenchmark/SQLBenchmark+TestPlanets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extension SQLBenchmarker {
.column(for: \Galaxy.id, .primaryKey)
.column(for: \Galaxy.name)
.run().wait()

try conn.create(table: Planet.self)
.ifNotExists()
.column(for: \Planet.id, .primaryKey)
Expand All @@ -23,6 +24,10 @@ extension SQLBenchmarker {
.column(for: \Planet.name, .default(.literal(.string("Unamed Planet"))))
.run().wait()

try conn.create(index: .identifier("test_index"), on: \Planet.name)
.unique()
.run().wait()

try conn.insert(into: Galaxy.self)
.value(Galaxy(name: "Milky Way"))
.run().wait()
Expand Down