SQL Adapter conformance




Swift Zewo Platform License Slack Travis Codebeat

SQL provides base conformance for SQL adapters.


The SQL module is bundled with the SQL adapters of Zewo

import PackageDescription

let package = Package(
    dependencies: [
        .Package(url: "", majorVersion: 0, minor: 5),


Use this package with one of the supported drivers listed above.

Connecting to a database

let connection = try PostgreSQL.Connection(URI("postgres://localhost:5432/swift_test"))

Executing raw queries

try connection.execute("SELECT * FROM artists")
let result = try connection.execute("SELECT * FROM artists WHERE name = %@", parameters: "Josh Rouse")

Getting results from queries

let result = try connection.execute("SELECT * FROM artists")

for row in result {
    let name: String = try result.value("name")
    let genre: String? = try result.value("genre")

In the above example, an error will be thrown if name and genre is not present in the rows returned. An error will also be thrown if a name is NULL in any row, as the inferred type is non-optional. Note how genre will allow for a NULL value.


You can define tables as such:

public class Artist: Table {
    enum Field: String {
        case id = "id"
        case name = "name"
        case artistId = "artist_id"

    static let tableName: String = "artists"
} == "Josh Rouse")
Artist.insert([.name: "AC/DC"])
Artist.update([.name: "AC/DC"]).filter(Artist.field(.genre) == "Rock")
Artist.delete().filter(Artist.field(.genre) == "Rock")
try connection.execute(


You can define models, by extending Table like so:

public final class Artist {
    let id: Int?
    let name: String
    let genre: String

    init(name: String, genre: String) { = name
        self.genre = genre

extension Artist: Model {
    // Just like `Table`
    enum Field: String {
        case id = "id"
        case name = "name"
        case genre = "genre"

    // Specify a table name
    static let tableName: String = "artists"

    // Specify which field is primary
    static var primaryKeyField: Field = .id

    // Provide a getter and setter for the primary key
    var primaryKey: Int? {
        get {
            return id
        set {
            id = newValue

    // Specify the values to be persisted
    var serialize: [Field: ValueConvertible?] {
        return [.name: name, .genre: genre]

    // Provide an initializer for the model taking a row 
    convenience init(row: Row) throws {
        try self.init(
            name: row.value(Artist.field(.name)),
            genre: row.value(Artist.field(.genre))
        id = try row.value(Artist.field(.id))
let rockArtists = try Artist.fetch(where: Artist.field(.genre) == "Rock", connection: connection)

for artist in rockArtists {
    artist.genre = "Rock 'n Roll"

let newArtist = Artist(name: "Elijah Blake", genre: "Hip-hop")
try newArtist.create(connection: connection) // save() also works


If you need any help you can join our Slack and go to the #help channel. Or you can create a Github issue in our main repository. When stating your issue be sure to add enough details, specify what module is causing the problem and reproduction steps.



The entire Zewo code base is licensed under MIT. By contributing to Zewo you are contributing to an open and engaged community of brilliant Swift programmers. Join us on Slack to get to know us!


This project is released under the MIT license. See LICENSE for details.