[
  {
    "path": ".circleci/config.yml",
    "content": "version: 2\n\n\njobs:\n  mac-swift5.3:\n    macos:\n      xcode: \"12.3.0\"\n    steps:\n      - checkout\n      - run: brew tap novi/tap && brew install novi/tap/cmysqlmariadb\n      - run: mkdir -p /usr/local/etc/my.cnf.d /usr/local/var/mysql #workaround\n      - run: sh -c \"mysqld_safe --skip-grant-tables & sleep 5\"\n      - run: mysql -u root -e \"create database IF NOT EXISTS test;\"\n      - run: swift build\n      - run: swift test\n  mac-swift5.3-mysql:\n    macos:\n      xcode: \"12.3.0\"\n    steps:\n      - checkout\n      - run: brew tap novi/tap && brew install novi/tap/cmysql\n      - run: mkdir -p /usr/local/var/mysql/data && echo \"datadir=/usr/local/var/mysql/data\" >> /usr/local/etc/my.cnf && mysqld --initialize-insecure\n      - run: mysql.server start\n      - run: mysql -u root -e \"create database IF NOT EXISTS test;\"\n      - run: swift build\n      - run: swift test\n\n  linux-swift5.0:\n    docker:\n      - image: yusukeito/swift-basic:swift5.0\n      - image: mariadb:10.3\n        environment:\n          MYSQL_USER: root\n          MYSQL_DATABASE: \"test\"\n          MYSQL_ALLOW_EMPTY_PASSWORD: yes\n          MYSQL_ROOT_HOST: \"%\"\n          DATABASE_HOST: \"%\"\n    steps:\n      - checkout\n      - run: sleep 10 #wait for mysql\n      - run: swift build\n      - run: swift test\n\n  linux-swift5.1:\n    docker:\n      - image: yusukeito/swift-basic:swift5.1-cgrpc\n      - image: mariadb:10.3\n        environment:\n          MYSQL_USER: root\n          MYSQL_DATABASE: \"test\"\n          MYSQL_ALLOW_EMPTY_PASSWORD: yes\n          MYSQL_ROOT_HOST: \"%\"\n          DATABASE_HOST: \"%\"\n    steps:\n      - checkout\n      - run: sleep 10 #wait for mysql\n      - run: swift build\n      - run: swift test\n\n  linux-swift5.2:\n    docker:\n      - image: yusukeito/swift-basic:swift5.2-grpc-1\n      - image: mariadb:10.3\n        environment:\n          MYSQL_USER: root\n          MYSQL_DATABASE: \"test\"\n          MYSQL_ALLOW_EMPTY_PASSWORD: yes\n          MYSQL_ROOT_HOST: \"%\"\n          DATABASE_HOST: \"%\"\n    steps:\n      - checkout\n      - run: sleep 10 #wait for mysql\n      - run: swift build\n      - run: swift test\n\n  linux-swift5.3:\n    docker:\n      - image: yusukeito/swift-basic:swift5.3-grpc-1\n      - image: mariadb:10.3\n        environment:\n          MYSQL_USER: root\n          MYSQL_DATABASE: \"test\"\n          MYSQL_ALLOW_EMPTY_PASSWORD: yes\n          MYSQL_ROOT_HOST: \"%\"\n          DATABASE_HOST: \"%\"\n    steps:\n      - checkout\n      - run: sleep 10 #wait for mysql\n      - run: swift build\n      - run: swift test\n\nworkflows:\n  version: 2\n  build_and_test:\n    jobs:\n      - mac-swift5.3\n      - mac-swift5.3-mysql\n      - linux-swift5.0\n      - linux-swift5.1\n      - linux-swift5.2\n      - linux-swift5.3"
  },
  {
    "path": ".gitignore",
    "content": "# OS X Finder\n.DS_Store\n\n# Xcode per-user config\n*.mode1\n*.mode1v3\n*.mode2v3\n*.perspective\n*.perspectivev3\n*.pbxuser\n#*.xcworkspace\nxcuserdata\n\n# Build products\nbuild/\n*.o\n*.LinkFileList\n*.hmap\n\n# Automatic backup files\n*~.nib/\n*.swp\n*~\n*.dat\n*.dep\ndocs/\n\nCartfile.resolved\nCarthage/\n.build/\n\nConstants.swift\n/*.xcodeproj\n.swiftpm/\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Copyright (c) 2015-18 Yusuke Ito\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version:4.0\nimport PackageDescription\n\nlet package = Package(\n    name: \"MySQL\",\n    products: [\n        .library(name: \"MySQL\", targets: [\"MySQL\"])\n    ],\n    dependencies: [\n        .package(url: \"https://github.com/novi/cmysql.git\", from: \"2.0.0\"),\n    ],\n    targets: [\n        .target(\n            name: \"SQLFormatter\"\n        ),\n        .target(\n            name: \"MySQL\",\n            dependencies: [\n                \"SQLFormatter\",\n            ]\n        ),\n        .testTarget(\n            name: \"MySQLTests\",\n            dependencies: [\n                \"MySQL\"\n            ]\n        ),\n        .testTarget(\n            name: \"SQLFormatterTests\",\n            dependencies: [\n                \"MySQL\"\n            ]\n        )\n    ],\n    swiftLanguageVersions: [4]\n)\n"
  },
  {
    "path": "Package@swift-5.swift",
    "content": "// swift-tools-version:5.0\nimport PackageDescription\n\nlet package = Package(\n    name: \"mysql-swift\",\n    products: [\n        .library(name: \"MySQL\", targets: [\"MySQL\"])\n    ],\n    targets: [\n        .systemLibrary(\n            name: \"CMySQL\",\n            path: \"Sources/cmysql\",\n            pkgConfig: \"cmysql\",\n            providers: [\n                .brew([\"cmysql\"]),\n                .apt([\"libmysqlclient-dev\"])\n            ]\n        ),\n        .target(\n            name: \"SQLFormatter\"\n        ),\n        .target(\n            name: \"MySQL\",\n            dependencies: [\n                \"CMySQL\",\n                \"SQLFormatter\",\n            ]\n        ),\n        .testTarget(\n            name: \"MySQLTests\",\n            dependencies: [\n                \"MySQL\"\n            ]\n        ),\n        .testTarget(\n            name: \"SQLFormatterTests\",\n            dependencies: [\n                \"MySQL\"\n            ]\n        )\n    ]\n)\n"
  },
  {
    "path": "README.md",
    "content": "mysql-swift\n===========\n\n**This library is obsolete and not maintained. Use [MySQLNIO](https://github.com/vapor/mysql-nio) instead.**\n\n![Platform Linux, macOS](https://img.shields.io/badge/Platforms-Linux%2C%20macOS-lightgray.svg)\n[![CircleCI](https://circleci.com/gh/novi/mysql-swift.svg?style=svg)](https://circleci.com/gh/novi/mysql-swift)\n\n\n\nMySQL client library for Swift.\nThis is inspired by Node.js' [mysql](https://github.com/mysqljs/mysql).\n\n* Based on libmysqlclient\n* Raw SQL query\n* Simple query formatting and escaping (same as Node's)\n* Mapping queried results to `Codable` structs or classes\n\n_Note:_ No asynchronous I/O support currently. It depends libmysqlclient.\n\n```swift\n// Declare a model\n\nstruct User: Codable, QueryParameter {\n    let id: Int\n    let userName: String\n    let age: Int?\n    let status: Status\n    let createdAt: Date\n    \n    enum Status: String, Codable {\n        case created = \"created\"\n        case verified = \"verified\"\n    }\n    \n    private enum CodingKeys: String, CodingKey {\n        case id\n        case userName = \"user_name\"\n        case age\n        case status = \"status\"\n        case createdAt = \"created_at\"\n    }\n}\n    \n// Selecting\nlet nameParam = \"some one\"\nlet ids: [QueryParameter] = [1, 2, 3, 4, 5, 6]\nlet optionalInt: Int? = nil\nlet rows: [User] = try conn.query(\"SELECT id,user_name,status,status,created_at FROM `user` WHERE (age > ? OR age is ?) OR name = ? OR id IN (?)\", [50, optionalInt, nameParam, QueryArray(ids)] ])\n\n// Inserting\nlet age: Int? = 26\nlet user = User(id: 0, userName: \"novi\", age: age, status: .created, createdAt: Date())\nlet status = try conn.query(\"INSERT INTO `user` SET ?\", [user]) as QueryStatus\nlet newId = status.insertedId\n\n// Updating\nlet tableName = \"user\"\nlet defaultAge = 30\ntry conn.query(\"UPDATE ?? SET age = ? WHERE age is NULL;\", [tableName, defaultAge])\n\n``` \n\n# Requirements\n\n* Swift 5.0 or later\n* MariaDB or MySQL Connector/C (libmysqlclient) 2.2.3 or later\n\n## macOS\n\nInstall pkg-config `.pc` file in [cmysql](https://github.com/vapor-community/cmysql) or [cmysql-mariadb](https://github.com/novi/cmysql-mariadb/tree/mariadb).\n\n```sh\n# cmysql\n$ brew tap novi/tap\n$ brew install novi/tap/cmysql\n\n# cmysql-mariadb\n$ brew tap novi/tap\n$ brew install novi/tap/cmysqlmariadb\n```\n\n## Ubuntu\n\n* Install `libmariadbclient`\n* Follow [Setting up MariaDB Repositories](https://downloads.mariadb.org/mariadb/repositories/#mirror=yamagata-university) and set up your repository.\n\n```sh\n$ sudo apt-get install libmariadbclient-dev\n```\n\n# Installation\n\n## Swift Package Manager\n\n* Add `mysql-swift` to `Package.swift` of your project.\n\n```swift\n// swift-tools-version:5.2\nimport PackageDescription\n\nlet package = Package(\n    ...,\n    dependencies: [\n        .package(url: \"https://github.com/novi/mysql-swift.git\", .upToNextMajor(from: \"0.9.0\"))\n    ],\n    targets: [\n        .target(\n            name: \"YourAppOrLibrary\",\n            dependencies: [\n                // add a dependency\n                .product(name: \"MySQL\", package: \"mysql-swift\")\n            ]\n        )\n    ]\n)\n```\n\n# Usage\n\n## Connection & Querying\n\n1. Create a pool with options (hostname, port, password,...).\n2. Use `ConnectionPool.execute()`. It automatically get and release a connection. \n\n```swift\nlet option = Option(host: \"your.mysql.host\"...) // Define and create your option type\nlet pool = ConnectionPool(option: option) // Create a pool with the option\nlet rows: [User] = try pool.execute { conn in\n\t// The connection `conn` is held in this block\n\ttry conn.query(\"SELECT * FROM users;\") // And it returns result to outside execute block\n}\n```\n\n## Transaction\n\n```swift\t\nlet wholeStaus: QueryStatus = try pool.transaction { conn in\n\tlet status = try conn.query(\"INSERT INTO users SET ?;\", [user]) as QueryStatus // Create a user\n\tlet userId = status.insertedId // the user's id\n\ttry conn.query(\"UPDATE info SET some_value = ? WHERE some_key = 'latest_user_id' \", [userId]) // Store user's id that we have created the above\n}\nwholeStaus.affectedRows == 1 // true\n```\n\n\n\n# License\n\nMIT\n"
  },
  {
    "path": "Sources/MySQL/AutoincrementID.swift",
    "content": "//\n//  AutoincrementID.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 6/27/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\nimport SQLFormatter\n\npublic enum AutoincrementID<I: IDType> {\n    case noID\n    case ID(I)\n\n    public var id: I {\n        switch self {\n        case .noID: fatalError(\"\\(self) has no ID\")\n        case .ID(let id): return id\n        }\n    }\n}\n\nextension AutoincrementID: Equatable {\n    static public func ==<I>(lhs: AutoincrementID<I>, rhs: AutoincrementID<I>) -> Bool {\n        switch (lhs, rhs) {\n        case (.noID, .noID): return true\n        case (.ID(let lhs), .ID(let rhs) ): return lhs.id == rhs.id\n        default: return false\n        }\n    }\n}\n\nextension AutoincrementID: CustomStringConvertible {\n    // where I: CustomStringConvertible\n    // is not supported yet\n    public var description: String {\n        switch self {\n        case .noID: return \"noID\"\n        case .ID(let id):\n            if let idVal = id as? CustomStringConvertible {\n                return idVal.description\n            } else {\n                return \"\\(id)\"\n            }\n        }\n    }\n}\n\nextension AutoincrementID {\n    public init(_ id: I) {\n        self = .ID(id)\n    }\n}\n\n/*\nextension AutoincrementID where I: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> AutoincrementID<I> {\n        return AutoincrementID(try I.fromSQLValue(string: string))\n    }\n}*/\n\nextension AutoincrementID: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        switch self {\n        case .noID: return \"\"\n        case .ID(let id): return try id.queryParameter(option: option)\n        }\n    }\n    public var omitOnQueryParameter: Bool {\n        switch self {\n        case .noID: return true\n        case .ID: return false\n        }\n    }\n}\n\n\n\n/// MARK: Codable support\n\nextension AutoincrementID: Decodable where I: Decodable {\n    public init(from decoder: Decoder) throws {\n        self = .ID(try I(from: decoder))\n    }\n}\n\nextension AutoincrementID: Encodable where I: Encodable {\n    public func encode(to encoder: Encoder) throws {\n        switch self {\n        case .noID:\n        break // nothing to encode\n        case .ID(let id):\n            try id.encode(to: encoder)\n        }\n    }\n}\n\n"
  },
  {
    "path": "Sources/MySQL/Blob.swift",
    "content": "//\n//  Blob.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 4/22/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\nimport Foundation\nimport SQLFormatter\n\nextension Data: SQLRawStringDecodable {\n    public static func fromSQLValue(string: String) throws -> Data {\n        fatalError(\"logic error, construct via init(:)\")\n    }\n}\n\nfileprivate let HexTable: [Character] = [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]\n\nextension Data: QueryParameterType {\n    public func escaped() -> String {\n        var buffer = [Character]([\"x\", \"'\"])\n        buffer.reserveCapacity( self.count * 2 + 3 ) // 3 stands for \"x''\", 2 stands for 2 characters per a byte data\n        for byte in self {\n            buffer.append(HexTable[Int((byte >> 4) & 0x0f)])\n            buffer.append(HexTable[Int(byte & 0x0f)])\n        }\n        buffer.append(\"'\")\n        return String(buffer)\n    }\n    \n    public func escapedForID() -> String? {\n        return nil // Data can not be used for ID(?? placeholder).\n    }\n}\n\nextension Data: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        return self\n    }\n}\n\ninternal struct Blob: QueryParameter {\n    let data: Data\n    let dataType: QueryCustomDataParameterDataType\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        return self\n    }\n}\n\nextension Blob: QueryParameterType {\n    public func escaped() -> String {\n        switch dataType {\n        case .blob: return data.escaped()\n        case .json:\n            return \"CONVERT(\" + data.escaped() + \" using utf8mb4)\"\n        }\n    }\n    \n    public func escapedForID() -> String? {\n        return nil // Data can not be used for ID(?? placeholder).\n    }\n}\n\n"
  },
  {
    "path": "Sources/MySQL/Connection.swift",
    "content": "//\n//  Database.swift\n//  MySQL\n//\n//  Created by ito on 2015/10/24.\n//  Copyright © 2015年 Yusuke Ito. All rights reserved.\n//\n\nimport CMySQL\nimport CoreFoundation\nimport Foundation\n\ninternal struct MySQLUtil {\n    internal static func getMySQLError(_ mysql: UnsafeMutablePointer<MYSQL>) -> String {\n        guard let strPtr = mysql_error(mysql) else {\n            return \"unknown error. could not get error with `mysql_error()`.\"\n        }\n        guard let errorString = String(validatingUTF8: strPtr) else {\n            return \"unknown error. could not get error as string.\"\n        }\n        return errorString\n    }\n}\n\n\npublic protocol ConnectionOption {\n    var host: String { get }\n    var port: Int { get }\n    var user: String { get }\n    var password: String { get }\n    var database: String { get }\n    var timeZone: TimeZone { get }\n    var encoding: Connection.Encoding { get }\n    var timeout: Int { get }\n    var reconnect: Bool { get }\n    var omitDetailsOnError: Bool { get }\n}\n\nfileprivate let defaultTimeZone = TimeZone(identifier: \"UTC\")!\n\npublic extension ConnectionOption {\n    // Provide default options\n    var timeZone: TimeZone {\n        return defaultTimeZone\n    }\n    var encoding: Connection.Encoding {\n        return .UTF8MB4\n    }\n    var timeout: Int {\n        return 10\n    }\n    var reconnect: Bool {\n        return true\n    }\n    var omitDetailsOnError: Bool {\n        return true\n    }\n}\n\nextension Connection {\n    public enum Encoding: String {\n        case UTF8 = \"utf8\"\n        case UTF8MB4 = \"utf8mb4\"\n    }\n    \n}\n\npublic enum ConnectionError: Error {\n    case connectionError(String)\n    case connectionPoolGetConnectionTimeoutError\n}\n\npublic final class Connection {\n    \n    internal var isInUse: Bool = false\n    private var mysql_: UnsafeMutablePointer<MYSQL>?\n    \n    internal let pool: ConnectionPool\n    public let option: ConnectionOption\n    \n    internal init(option: ConnectionOption, pool: ConnectionPool) {\n        self.option = option\n        self.pool = pool\n        self.mysql_ = nil\n    }\n    \n    internal func release() {\n        pool.releaseConnection(self)\n    }\n    \n    internal static func setReconnect(_ reconnect: Bool, mysql: UnsafeMutablePointer<MYSQL>) {\n        let reconnectPtr = UnsafeMutablePointer<my_bool>.allocate(capacity: 1)\n        reconnectPtr.pointee = reconnect == false ? 0 : 1\n        mysql_options(mysql, MYSQL_OPT_RECONNECT, reconnectPtr)\n        reconnectPtr.deallocate()\n    }\n    \n    func setReconnect(_ reconnect: Bool) {\n        if let mysql = mysql {\n            Connection.setReconnect(reconnect, mysql: mysql)\n        }\n    }\n    \n    internal func connect() throws -> UnsafeMutablePointer<MYSQL> {\n        dispose()\n        \n        guard let mysql = mysql_init(nil) else {\n            fatalError(\"mysql_init() failed.\")\n        }\n        \n        do {\n            let timeoutPtr = UnsafeMutablePointer<Int>.allocate(capacity: 1)\n            timeoutPtr.pointee = option.timeout\n            mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, timeoutPtr)\n            timeoutPtr.deallocate()\n        }\n        \n        Connection.setReconnect(option.reconnect, mysql: mysql)\n        \n        if mysql_real_connect(mysql,\n            option.host,\n            option.user,\n            option.password,\n            option.database,\n            UInt32(option.port), nil, 0) == nil {\n            // error\n                throw ConnectionError.connectionError(MySQLUtil.getMySQLError(mysql))\n        }\n        mysql_set_character_set(mysql, option.encoding.rawValue)\n        self.mysql_ = mysql\n        return mysql\n    }\n    \n    internal func connectIfNeeded() throws -> UnsafeMutablePointer<MYSQL> {\n        guard let mysql = self.mysql_ else {\n            return try connect()\n        }\n        return mysql\n    }\n    \n    private var mysql: UnsafeMutablePointer<MYSQL>? {\n        guard mysql_ != nil else {\n            return nil\n        }\n        return mysql_\n    }\n    \n    internal func ping() -> Bool {\n        _ = try? connectIfNeeded()\n        guard let mysql = mysql else {\n            return false\n        }\n        return mysql_ping(mysql) == 0\n    }\n    \n    private func dispose() {\n        guard let mysql = mysql else {\n            return\n        }\n        mysql_close(mysql)\n        self.mysql_ = nil\n    }\n    \n    deinit {\n        dispose()\n    }\n}\n\n\n"
  },
  {
    "path": "Sources/MySQL/ConnectionPool.swift",
    "content": "//\n//  ConnectionPool.swift\n//  MySQL\n//\n//  Created by ito on 12/24/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport Dispatch\n#if os(Linux)\n    import Glibc\n#endif\nimport CMySQL\n\nfileprivate var LibraryInitialized: Atomic<Bool> = Atomic(false)\n\nfileprivate func InitializeMySQLLibrary() {\n    LibraryInitialized.syncWriting {\n        guard $0 == false else {\n            return\n        }\n        if mysql_server_init(0, nil, nil) != 0 { // mysql_library_init\n            fatalError(\"could not initialize MySQL library with `mysql_server_init`.\")\n        }\n        $0 = true\n    }\n}\n\nextension Array where Element == Connection {\n    mutating func preparedNewConnection(option: ConnectionOption, pool: ConnectionPool) -> Connection {\n        let newConn = Connection(option: option, pool: pool)\n        _ = try? newConn.connect()\n        append(newConn)\n        return newConn\n    }\n    \n    func getUsableConnection() -> Connection? {\n        for c in self {\n            if c.isInUse == false && c.ping() {\n                c.isInUse = true\n                return c\n            }\n        }\n        return nil\n    }\n    \n    internal var inUseConnections: Int {\n        var count: Int = 0\n        for c in self {\n            if c.isInUse {\n                count += 1\n            }\n        }\n        return count\n    }\n}\n\nfinal public class ConnectionPool: CustomStringConvertible {\n    \n    \n    private var initialConnections_: Atomic<Int> = Atomic(1)\n    \n    public var initialConnections: Int {\n        get {\n            return initialConnections_.sync { $0 }\n        }\n        set {\n            initialConnections_.syncWriting {\n                $0 = newValue\n            }\n            pool.syncWriting {\n                while $0.count < newValue {\n                    _  = $0.preparedNewConnection(option: self.option, pool: self)\n                }\n            }\n        }\n    }\n    \n    public var maxConnections: Int {\n        get {\n            return maxConnections_.sync { $0 }\n        }\n        set {\n            maxConnections_.syncWriting {\n                $0 = newValue\n            }\n        }\n    }\n    \n    private var maxConnections_: Atomic<Int> = Atomic(10)\n    \n    internal private(set) var pool: Atomic<[Connection]> = Atomic([])\n    \n    @available(*, deprecated, renamed: \"option\")\n    public var options: ConnectionOption {\n        return option\n    }\n    \n    public let option: ConnectionOption\n    \n    @available(*, deprecated, renamed: \"init(option:)\")\n    public convenience init(options: ConnectionOption) {\n        self.init(option: options)\n    }\n    \n    public init(option: ConnectionOption) {\n        self.option = option\n        \n        InitializeMySQLLibrary()\n        \n        for _ in 0..<initialConnections {\n            pool.syncWriting {\n                _ = $0.preparedNewConnection(option: option, pool: self)\n            }\n        }\n    }\n    public var timeoutForGetConnection: Int {\n        get {\n            return timeoutForGetConnection_.sync { $0 }\n        }\n        set {\n            timeoutForGetConnection_.syncWriting {\n                $0 = newValue\n            }\n        }\n    }\n    \n    private var timeoutForGetConnection_: Atomic<Int> = Atomic(60)\n    \n    internal func getConnection() throws -> Connection {\n        var connection: Connection? =\n        pool.syncWriting {\n            if let conn = $0.getUsableConnection() {\n                return conn\n            }\n            if $0.count < maxConnections {\n                let conn = $0.preparedNewConnection(option: option, pool: self)\n                conn.isInUse = true\n                return conn\n            }\n            return nil\n        }\n        \n        if let conn = connection {\n            return conn\n        }\n        \n        let tickInMs = 50 // ms\n        var timeoutCount = (timeoutForGetConnection*1000)/tickInMs\n        while timeoutCount > 0 {\n            usleep(useconds_t(1000*tickInMs))\n            connection = pool.sync {\n                $0.getUsableConnection()\n            }\n            if connection != nil {\n                break\n            }\n            timeoutCount -= 1\n        }\n        \n        guard let conn = connection else {\n            throw ConnectionError.connectionPoolGetConnectionTimeoutError\n        }\n        return conn\n    }\n    \n    internal func releaseConnection(_ conn: Connection) {\n        pool.sync { _ in\n            conn.isInUse = false\n        }\n    }\n    \n    public var description: String {\n        let inUseConnections = pool.sync {\n            $0.inUseConnections\n        }\n        return \"connections:\\n\\tinitial:\\(initialConnections), max:\\(maxConnections), in-use:\\(inUseConnections)\"\n    }\n}\n\n\nextension ConnectionPool {\n    \n    public func execute<T>( _ block: (_ conn: Connection) throws -> T  ) throws -> T {\n        let conn = try getConnection()\n        defer {\n            releaseConnection(conn)\n        }\n        return try block(conn)\n    }\n    \n}\n"
  },
  {
    "path": "Sources/MySQL/Date.swift",
    "content": "//\n//  Date.swift\n//  MySQL\n//\n//  Created by ito on 12/16/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\n\nimport Foundation\nimport SQLFormatter\n\ninternal final class SQLDateCalendar {\n    \n    private static var calendars: Atomic<[TimeZone:Calendar]> = Atomic([:])\n    \n    internal static func calendar<T>(forTimezone timeZone: TimeZone, _ block: (_ calendar: Calendar) -> T) -> T {\n        return calendars.syncWriting {\n            if let calendar = $0[timeZone] {\n                return block(calendar)\n            }\n            var calendar = Calendar(identifier: .gregorian)\n            calendar.timeZone = timeZone\n            $0[timeZone] = calendar\n            return block(calendar)\n        }\n    }\n}\n\nfileprivate func pad(num: Int, digits: Int = 2) -> String {\n    var str = String(num)\n    if num < 0 {\n        return str\n    }\n    while str.count < digits {\n        str = \"0\" + str\n    }\n    return str\n}\n\n\nextension Date {\n    \n    internal init(sqlDate: String, timeZone: TimeZone) throws {\n        \n        switch sqlDate.count {\n        case 19:\n            let chars: [Character] = Array(sqlDate)\n            if let year = Int(String(chars[0...3])),\n                let month = Int(String(chars[5...6])),\n                let day = Int(String(chars[8...9])),\n                let hour = Int(String(chars[11...12])),\n                let minute = Int(String(chars[14...15])),\n                let second = Int(String(chars[17...18])), year > 0 && day > 0 && month > 0 {\n                var comps = DateComponents()\n                comps.year = year\n                comps.month = month\n                comps.day = day\n                comps.hour = hour\n                comps.minute = minute\n                comps.second = second\n                let parsedDate: Date? = SQLDateCalendar.calendar(forTimezone: timeZone) { calendar in\n                    calendar.date(from :comps)\n                }\n                if let date = parsedDate {\n                    self = date\n                    return\n                }\n            }\n        default: break\n        }\n        \n        throw QueryError.SQLDateStringError(sqlDate)\n    }\n}\n\nextension Date: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        let comp: DateComponents = SQLDateCalendar.calendar(forTimezone: option.timeZone) { calendar in\n            calendar.dateComponents([ .year, .month,  .day,  .hour, .minute, .second], from: self)\n        }        \n        // YYYY-MM-DD HH:MM:SS\n        return EscapedQueryParameter( \"'\\(pad(num: comp.year ?? 0, digits: 4))-\\(pad(num: comp.month ?? 0))-\\(pad(num: comp.day ?? 0)) \\(pad(num: comp.hour ?? 0)):\\(pad(num: comp.minute ?? 0)):\\(pad(num: comp.second ?? 0))'\" )\n    }\n}\n\nfileprivate func nanosecondsToString(_ nanosec: Int) -> String {\n    let nanosecSecond = Double(nanosec % 1_000_000_000)/1_000_000_000.0\n    var nanosecStr = String(format: \"%.6f\", nanosecSecond)\n    nanosecStr.removeFirst()\n    return String(nanosecStr)\n}\n\nextension DateComponents: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        if let year = self.year, let month = self.month, let day = self.day, let hour = self.hour, let minute = self.minute, let second = self.second {\n            var string = \"'\\(pad(num: year, digits: 4))-\\(pad(num: month))-\\(pad(num: day)) \\(pad(num: hour)):\\(pad(num: minute)):\\(pad(num: second))\"\n            if let nanosec = self.nanosecond {\n                string += nanosecondsToString(nanosec)\n            }\n            return EscapedQueryParameter(string + \"'\")\n        }\n        \n        if let hour = self.hour, let minute = self.minute, let second = self.second {\n            var string = \"'\\(pad(num: hour)):\\(pad(num: minute)):\\(pad(num: second))\"\n            if let nanosec = self.nanosecond {\n                string += nanosecondsToString(nanosec)\n            }\n            return EscapedQueryParameter(string + \"'\")\n        }\n        if let year = self.year {\n            return EscapedQueryParameter(\"'\\(pad(num: year))'\")\n        }\n        throw QueryParameterError.dateComponentsError(self.description)\n    }\n}\n\nfileprivate let DateTimeRegex: NSRegularExpression = {\n    return try! NSRegularExpression(pattern: \"^(\\\\d{4})-(\\\\d{2})-(\\\\d{2}) (\\\\d{2}):(\\\\d{2}):(\\\\d{2})\\\\.?(\\\\d*)$\", options: [])\n}()\n\nfileprivate let TimeRegex: NSRegularExpression = {\n    return try! NSRegularExpression(pattern: \"^(\\\\-?\\\\d{1,3}):(\\\\d{2}):(\\\\d{2})\\\\.?(\\\\d*)$\", options: [])\n}()\n\nfileprivate let DateRegex: NSRegularExpression = {\n    return try! NSRegularExpression(pattern: \"^(\\\\d{4})-(\\\\d{2})-(\\\\d{2})$\", options: [])\n}()\n\n\nfileprivate func stringToNanoseconds<S: StringProtocol>(_ string: S) -> Int? {\n    guard string.count > 0 else {\n        return nil\n    }\n    guard let doubleValue = Double(\"0.\\(string)\") else {\n        return nil\n    }\n    return Int(doubleValue * 1_000_000_000.0)\n}\n\nextension DateComponents: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> DateComponents {\n        if string.count == 4 {\n            // YEAR type\n            return DateComponents(year: Int(string))\n        }\n        \n        let wholeRange = NSRange(string.startIndex..<string.endIndex, in: string)\n        \n        // count of the string will be at least 19...\n        // \"2000-01-23 01:23:45\"\n        if string.count >= 19, let match = DateTimeRegex.firstMatch(in: string, options: [], range: wholeRange) {\n            let year = Int(string[Range(match.range(at: 1), in: string)!])\n            let month = Int(string[Range(match.range(at: 2), in: string)!])\n            let day = Int(string[Range(match.range(at: 3), in: string)!])\n            \n            let hour = Int(string[Range(match.range(at: 4), in: string)!])\n            let minute = Int(string[Range(match.range(at: 5), in: string)!])\n            let second = Int(string[Range(match.range(at: 6), in: string)!])\n            \n            let nanosecond = String(string[Range(match.range(at: 7), in: string)!])\n            return DateComponents(\n                year: year,\n                month: month,\n                day: day,\n                hour: hour,\n                minute: minute,\n                second: second,\n                nanosecond: stringToNanoseconds(nanosecond)\n            )\n        }\n        \n        // \"1:23:45\"\n        if string.count >= 7, let match = TimeRegex.firstMatch(in: string, options: [], range: wholeRange) {\n            let hour = Int(string[Range(match.range(at: 1), in: string)!])\n            let minute = Int(string[Range(match.range(at: 2), in: string)!])\n            let second = Int(string[Range(match.range(at: 3), in: string)!])\n            \n            let nanosecond = string[Range(match.range(at: 4), in: string)!]\n            return DateComponents(\n                hour: hour,\n                minute: minute,\n                second: second,\n                nanosecond: stringToNanoseconds(nanosecond)\n            )\n        }\n        \n        // \"2000-01-23\"\n        if string.count == 10, let match = DateRegex.firstMatch(in: string, options: [], range: wholeRange) {\n            let year = Int(string[Range(match.range(at: 1), in: string)!])\n            let month = Int(string[Range(match.range(at: 2), in: string)!])\n            let day = Int(string[Range(match.range(at: 3), in: string)!])\n            return DateComponents(\n                year: year,\n                month: month,\n                day: day\n            )\n        }\n        throw QueryError.SQLDateStringError(string)\n    }\n}\n"
  },
  {
    "path": "Sources/MySQL/Error.swift",
    "content": "//\n//  Error.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 12/14/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\npublic enum QueryError: Error {\n    \n    case queryExecutionError(message: String, query: String)\n    case resultFetchError(message: String, query: String)\n    case resultNoFieldError(query: String)\n    case resultRowFetchError(query: String)\n    case resultFieldFetchError(query: String)\n    case resultParseError(message: String, result: String)\n    \n    case resultCastError(actualValue: String, expectedType: String, forField: String)\n    case resultDecodeError(rawSQLValue: String, forType: Any)\n    case resultDecodeErrorMessage(message: String)\n    case SQLDateStringError(String)\n    case SQLRawStringDecodeError(error: Error, actualValue: String, expectedType: String, forField: String)\n    \n    case missingField(String)\n}\n\npublic enum QueryParameterError: Error {\n    case dateComponentsError(String)\n}\n"
  },
  {
    "path": "Sources/MySQL/IDType.swift",
    "content": "//\n//  IDType.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 6/27/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\nimport SQLFormatter\n\npublic protocol IDType: QueryParameter, Hashable, Codable {\n    associatedtype T: QueryParameter, Hashable, Codable\n    var id: T { get }\n    init(_ id: T)\n}\n\npublic extension IDType {\n    \n    func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        return try id.queryParameter(option: option)\n    }\n    #if swift(>=4.2)\n    func hash(into hasher: inout Hasher) {\n        hasher.combine(id)\n    }\n    #else\n    var hashValue: Int {\n        return id.hashValue\n    }\n    #endif\n}\n\nextension IDType where Self: SQLRawStringDecodable, Self.T: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Self {\n        return Self(try T.fromSQLValue(string: string))\n    }\n}\n\nextension IDType {\n    public static func ==(lhs: Self, rhs: Self) -> Bool {\n        return lhs.id == rhs.id\n    }\n}\n\n// MARK: Codable type\nextension IDType {\n    \n    public init(from decoder: Decoder) throws {\n        if T.self == Int.self {\n            self.init(try decoder.singleValueContainer().decode(Int.self) as! T)\n        } else if T.self == Int64.self {\n            self.init(try decoder.singleValueContainer().decode(Int64.self) as! T)\n        } else if T.self == UInt.self {\n            self.init(try decoder.singleValueContainer().decode(UInt.self) as! T)\n        } else if T.self == UInt64.self {\n            self.init(try decoder.singleValueContainer().decode(UInt64.self) as! T)\n        } else if T.self == String.self {\n            self.init(try decoder.singleValueContainer().decode(String.self) as! T)\n        } else {\n            fatalError(\"`init(from:)` of \\(Self.self) is not implemented\")\n        }\n    }\n    \n    public func encode(to encoder: Encoder) throws {\n        if T.self == Int.self {\n            var container = encoder.singleValueContainer()\n            try container.encode(id as! Int)\n        } else if T.self == Int64.self {\n            var container = encoder.singleValueContainer()\n            try container.encode(id as! Int64)\n        } else if T.self == UInt.self {\n            var container = encoder.singleValueContainer()\n            try container.encode(id as! UInt)\n        } else if T.self == UInt64.self {\n            var container = encoder.singleValueContainer()\n            try container.encode(id as! UInt64)\n        } else if T.self == String.self {\n            var container = encoder.singleValueContainer()\n            try container.encode(id as! String)\n        } else {\n            fatalError(\"`encode(to:)` of \\(Self.self) is not implemented\")\n        }\n    }\n}\n\n// TODO: this implementation does not work in release build, Swift 4.1\n/*\nextension IDType {\n    \n    public init(from decoder: Decoder) throws {\n        fatalError(\"`init(from:)` of \\(Self.self) is not implemented\")\n    }\n    \n    public func encode(to encoder: Encoder) throws {\n        fatalError(\"`encode(to:)` of \\(Self.self) is not implemented\")\n    }\n}\n\n\nextension IDType where T == Int {\n    public init(from decoder: Decoder) throws {\n        self.init(try decoder.singleValueContainer().decode(Int.self))\n    }\n    \n    public func encode(to encoder: Encoder) throws {\n        var container = encoder.singleValueContainer()\n        try container.encode(id)\n    }\n}\n\nextension IDType where T == Int64 {\n    public init(from decoder: Decoder) throws {\n        self.init(try decoder.singleValueContainer().decode(Int64.self))\n    }\n    \n    public func encode(to encoder: Encoder) throws {\n        var container = encoder.singleValueContainer()\n        try container.encode(id)\n    }\n}\n\nextension IDType where T == UInt {\n    public init(from decoder: Decoder) throws {\n        self.init(try decoder.singleValueContainer().decode(UInt.self))\n    }\n    \n    public func encode(to encoder: Encoder) throws {\n        var container = encoder.singleValueContainer()\n        try container.encode(id)\n    }\n}\n\nextension IDType where T == UInt64 {\n    public init(from decoder: Decoder) throws {\n        self.init(try decoder.singleValueContainer().decode(UInt64.self))\n    }\n    \n    public func encode(to encoder: Encoder) throws {\n        var container = encoder.singleValueContainer()\n        try container.encode(id)\n    }\n}\n\nextension IDType where T == String {\n    public init(from decoder: Decoder) throws {\n        self.init(try decoder.singleValueContainer().decode(String.self))\n    }\n    \n    public func encode(to encoder: Encoder) throws {\n        var container = encoder.singleValueContainer()\n        try container.encode(id)\n    }\n}\n */\n"
  },
  {
    "path": "Sources/MySQL/Query.swift",
    "content": "//\n//  Connection.swift\n//  MySQL\n//\n//  Created by ito on 2015/10/24.\n//  Copyright © 2015年 Yusuke Ito. All rights reserved.\n//\n\nimport CMySQL\nimport SQLFormatter\nimport Foundation\n\npublic struct QueryStatus: CustomStringConvertible {\n    public let affectedRows: UInt64?\n    public let insertedID: UInt64\n    \n    init(mysql: UnsafeMutablePointer<MYSQL>) {\n        self.insertedID = mysql_insert_id(mysql)\n        let arows = mysql_affected_rows(mysql)\n        if arows == (~0) {\n            self.affectedRows = nil // error or select statement\n        } else {\n            self.affectedRows = arows\n        }\n    }\n    \n    public var description: String {\n        return \"insertedID:\\(insertedID), affectedRows:\" + (affectedRows != nil ? (\"\\(affectedRows!)\") : \"nil\")\n    }\n}\n\ninternal extension String {\n    func subString(max: Int) -> String {\n        guard let r = index(startIndex, offsetBy: max, limitedBy: endIndex) else {\n            return self\n        }\n        return String(self[startIndex..<r])\n    }\n}\n\nextension Connection {\n    \n    internal struct NullValue {\n        static let null = NullValue()\n    }\n    \n    internal struct EmptyRowResult: Decodable {\n        static func decodeRow(r: QueryRowResult) throws -> EmptyRowResult {\n            return EmptyRowResult()\n        }\n    }\n    \n    internal struct Field {\n        let name: String\n        let type: enum_field_types\n        init?(f: MYSQL_FIELD) {\n            if f.name == nil {\n                return nil\n            }\n            guard let fs = String(validatingUTF8: f.name) else {\n                return nil\n            }\n            self.name = fs\n            self.type = f.type\n        }\n        var isDate: Bool {\n            return type == MYSQL_TYPE_DATE ||\n                type == MYSQL_TYPE_DATETIME ||\n                type == MYSQL_TYPE_TIME ||\n                type == MYSQL_TYPE_TIMESTAMP\n        }\n        \n    }\n    \n    internal enum FieldValue {\n        case null\n        case binary(Data)\n        case date(dateString: String, timezone: TimeZone)\n        \n        static func makeBinary(ptr: UnsafeMutablePointer<Int8>, length: UInt) -> FieldValue {\n            let data = Data(bytes: UnsafeRawPointer(ptr), count: Int(length))\n            return FieldValue.binary(data)\n        }\n        \n        func string() throws -> String {\n            switch self {\n            case .null:\n                throw QueryError.resultParseError(message: \"the field is not string.\", result: \"null\")\n            case .date(let string, _):\n                return string\n            case .binary(let data):\n                guard let string = String(data: data, encoding: .utf8) else {\n                    throw QueryError.resultParseError(message: \"invalid utf8 string bytes.\", result: \"\")\n                }\n                return string\n            }\n        }\n    }\n    \n    fileprivate func query<T: Decodable>(query formattedQuery: String, option: QueryParameterOption) throws -> ([T], QueryStatus) {\n        let (rows, status) = try self.query(query: formattedQuery, option: option)\n        \n        return try (rows.map({ try T(from: QueryRowResultDecoder(row: $0))}), status)\n    }\n    \n    fileprivate func query(query formattedQuery: String, option: QueryParameterOption) throws -> ([QueryRowResult], QueryStatus) {\n        let mysql = try connectIfNeeded()\n        \n        func queryPrefix() -> String {\n            if self.option.omitDetailsOnError {\n                return \"\"\n            }\n            return formattedQuery.subString(max: 1000)\n        }\n        \n        guard mysql_real_query(mysql, formattedQuery, UInt(formattedQuery.utf8.count)) == 0 else {\n            throw QueryError.queryExecutionError(message: MySQLUtil.getMySQLError(mysql), query: queryPrefix())\n        }\n        let status = QueryStatus(mysql: mysql)\n        \n        let res = mysql_use_result(mysql)\n        guard res != nil else {\n            if mysql_field_count(mysql) == 0 {\n                // actual no result\n                return ([], status)\n            }\n            throw QueryError.resultFetchError(message: MySQLUtil.getMySQLError(mysql), query: queryPrefix())\n        }\n        defer {\n            mysql_free_result(res)\n        }\n        \n        let fieldCount = Int(mysql_num_fields(res))\n        guard fieldCount > 0 else {\n            throw QueryError.resultNoFieldError(query: queryPrefix())\n        }\n        \n        // fetch field info\n        guard let fieldDef = mysql_fetch_fields(res) else {\n            throw QueryError.resultFieldFetchError(query: queryPrefix())\n        }\n        var fields:[Field] = []\n        for i in 0..<fieldCount {\n            guard let f = Field(f: fieldDef[i]) else {\n                throw QueryError.resultFieldFetchError(query: queryPrefix())\n            }\n            fields.append(f)\n        }\n        \n        // fetch rows\n        var rows:[QueryRowResult] = []\n        \n        var rowCount: Int = 0\n        while true {\n            guard let row = mysql_fetch_row(res) else {\n                break // end of rows\n            }\n            \n            guard let lengths = mysql_fetch_lengths(res) else {\n                throw QueryError.resultRowFetchError(query: queryPrefix())\n            }\n            \n            var fieldValues: [FieldValue] = []\n            for i in 0..<fieldCount {\n                let field = fields[i]\n                if let valf = row[i], row[i] != nil {\n                    let binary = FieldValue.makeBinary(ptr: valf, length: lengths[i])\n                    if field.isDate {\n                        fieldValues.append(FieldValue.date(dateString: try binary.string(), timezone: option.timeZone))\n                    } else {\n                        fieldValues.append(binary)\n                    }                    \n                } else {\n                    fieldValues.append(FieldValue.null)\n                }\n                \n            }\n            rowCount += 1\n            if fields.count != fieldValues.count {\n                throw QueryError.resultParseError(message: \"invalid fetched column count\", result: \"\")\n            }\n            rows.append(QueryRowResult(fields: fields, fieldValues: fieldValues))\n        }\n        \n        return (rows, status)\n    }\n}\n\nfileprivate struct QueryParameterDefaultOption: QueryParameterOption {\n    let timeZone: TimeZone\n}\n\n\nextension Connection {\n    \n    internal static func buildParameters(_ params: [QueryParameter], option: QueryParameterOption) throws -> [QueryParameterType] {\n        return try params.map { try $0.queryParameter(option: option) }\n    }\n    \n    public func query<R: Decodable>(_ query: String, _ params: [QueryParameter] = []) throws -> ([R], QueryStatus) {\n        let option = QueryParameterDefaultOption(\n            timeZone: self.option.timeZone\n        )\n        let queryString = try QueryFormatter.format(query: query, parameters: type(of: self).buildParameters(params, option: option))\n        return try self.query(query: queryString, option: option)\n    }\n    \n    public func query<R: Decodable>(_ query: String, _ params: [QueryParameter] = [], option: QueryParameterOption) throws -> ([R], QueryStatus) {\n        let queryString = try QueryFormatter.format(query: query, parameters: type(of: self).buildParameters(params, option: option))\n        return try self.query(query: queryString, option: option)\n    }\n    \n    public func query<R: Decodable>(_ query: String, _ params: [QueryParameter] = []) throws -> [R] {\n        let (rows, _) = try self.query(query, params) as ([R], QueryStatus)\n        return rows\n    }\n    \n    public func query<R: Decodable>(_ query: String, _ params: [QueryParameter] = [], option: QueryParameterOption) throws -> [R] {\n        let (rows, _) = try self.query(query, params, option: option) as ([R], QueryStatus)\n        return rows\n    }\n    \n    public func query(_ query: String, _ params: [QueryParameter] = []) throws -> QueryStatus {\n        let (_, status) = try self.query(query, params) as ([EmptyRowResult], QueryStatus)\n        return status\n    }\n    \n    public func query(_ query: String, _ params: [QueryParameter] = [], option: QueryParameterOption) throws -> QueryStatus {\n        let (_, status) = try self.query(query, params, option: option) as ([EmptyRowResult], QueryStatus)\n        return status\n    }\n}\n"
  },
  {
    "path": "Sources/MySQL/QueryParameter-Data.swift",
    "content": "//\n//  QueryParameter-Data.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 4/29/18.\n//\n\nimport Foundation\n\npublic protocol QueryRowResultCustomData {\n    static func decode(fromRowData data: Data) throws -> Self\n}\n\npublic enum QueryCustomDataParameterDataType {\n    case blob\n    case json\n}\n\npublic protocol QueryCustomDataParameter {\n    func encodeForQueryParameter() throws -> Data\n    var queryParameterDataType: QueryCustomDataParameterDataType { get }\n}\n\npublic extension QueryCustomDataParameter {\n    var queryParameterDataType: QueryCustomDataParameterDataType {\n        return .blob\n    }\n}\n\n"
  },
  {
    "path": "Sources/MySQL/QueryParameterType.swift",
    "content": "//\n//  QueryParameterType.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 12/28/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport SQLFormatter\nimport Foundation\n\npublic protocol QueryParameter {\n    func queryParameter(option: QueryParameterOption) throws -> QueryParameterType\n    var omitOnQueryParameter: Bool { get }\n}\n\npublic extension QueryParameter {\n    var omitOnQueryParameter: Bool {\n        return false\n    }\n}\n\npublic protocol QueryParameterOption {\n    var timeZone: TimeZone { get }\n}\n\ninternal struct QueryParameterNull: QueryParameter {\n    \n    private init() {\n    }\n    \n    static let null = QueryParameterNull()\n    \n    func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( \"NULL\" )\n    }\n}\n\n@available(*, renamed: \"QueryParameterDictionary\")\ntypealias QueryDictionary = QueryParameterDictionary\n\npublic struct QueryParameterDictionary: QueryParameter {\n    private let dict: [String: QueryParameter?]\n    public init(_ dict: [String: QueryParameter?]) {\n        self.dict = dict\n    }\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        var keyVals: [String] = []\n        for (k, v) in dict {\n            if v == nil || v?.omitOnQueryParameter == false {\n                keyVals.append(\"\\(SQLString.escapeForID(k)) = \\(try (v ?? QueryParameterNull.null).queryParameter(option: option).escaped())\")\n            }\n        }\n        return EscapedQueryParameter( keyVals.joined(separator:  \", \") )\n    }\n}\n\nfileprivate protocol QueryParameterArrayType: QueryParameter {\n    \n}\n\n@available(*, renamed: \"QueryParameterArray\")\ntypealias QueryArray = QueryParameterArray\n\npublic struct QueryParameterArray: QueryParameter, QueryParameterArrayType {\n    private let arr: [QueryParameter?]\n    public init(_ arr: [QueryParameter?]) {\n        self.arr = arr\n    }\n    public init(_ arr: [QueryParameter]) {\n        self.arr = arr.map { Optional($0) }\n    }\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        return EscapedQueryParameter( try arr.filter({ val in\n            if let valid = val {\n                return valid.omitOnQueryParameter == false\n            }\n            return true\n        }).map({\n            if let val = $0 as? QueryParameterArrayType {\n                return \"(\" + (try val.queryParameter(option: option).escaped()) + \")\"\n            }\n            return try ($0 ?? QueryParameterNull.null).queryParameter(option: option).escaped()\n        }).joined(separator: \", \") )\n    }\n}\n\nextension Optional: QueryParameter where Wrapped: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        switch self {\n        case .none:\n            return QueryParameterNull.null.queryParameter(option: option)\n        case .some(let value):\n            return try value.queryParameter(option: option)\n        }\n    }\n    public var omitOnQueryParameter: Bool {\n        switch self {\n        case .none:\n            return false\n        case .some(let value):\n            return value.omitOnQueryParameter\n        }\n    }\n}\n\ninternal struct EscapedQueryParameter: QueryParameterType {\n    private let value: String\n    private let idParameter: String?\n    init(_ val: String, idParameter: String? = nil) {\n        self.value = val\n        self.idParameter = idParameter\n    }\n    func escaped() -> String {\n        return value\n    }\n    func escapedForID() -> String? {\n        return idParameter\n    }\n}\n\nextension String: QueryParameterType {\n    public func escaped() -> String {\n        return SQLString.escape(self)\n    }\n    public func escapedForID() -> String? {\n        return SQLString.escapeForID(self)\n    }\n}\n\nextension String: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return self\n    }\n}\n\nextension Int: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension UInt: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension Int64: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension Int32: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension Int16: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension Int8: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension UInt64: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension UInt32: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension UInt16: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension UInt8: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension Double: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension Float: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(self) )\n    }\n}\n\nextension Bool: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( self ? \"true\" : \"false\" )\n    }\n}\n\nextension Decimal: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) -> QueryParameterType {\n        return EscapedQueryParameter( String(describing: self) )\n    }\n}\n\n/// MARK: Codable support\n\nfileprivate final class QueryParameterEncoder: Encoder {\n    let codingPath = [CodingKey]()\n    \n    let userInfo = [CodingUserInfoKey : Any]()\n    \n    var dict: [String: QueryParameter?] = [:]\n    var singleValue: QueryParameter? = nil\n    enum StorageType {\n        case single\n        case dictionary\n    }\n    \n    var storageType: StorageType = .dictionary\n    \n    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {\n        return KeyedEncodingContainer(QueryParameterKeyedEncodingContainer<Key>(encoder: self))\n    }\n    \n    func unkeyedContainer() -> UnkeyedEncodingContainer {\n        fatalError(\"not supported unkeyedContainer in QueryParameter\")\n    }\n    \n    func singleValueContainer() -> SingleValueEncodingContainer {\n        self.storageType = .single\n        return QueryParameterSingleValueEncodingContainer(encoder: self)\n    }\n    \n}\n\n\nfileprivate struct QueryParameterSingleValueEncodingContainer: SingleValueEncodingContainer {\n    let codingPath = [CodingKey]()\n    \n    var encoder: QueryParameterEncoder\n    \n    mutating func encodeNil() throws {\n        encoder.singleValue = nil\n    }\n    \n    mutating func encode(_ value: Bool) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: Int) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: Int8) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: Int16) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: Int32) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: Int64) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: UInt) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: UInt8) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: UInt16) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: UInt32) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: UInt64) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: Float) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: Double) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode(_ value: String) throws {\n        encoder.singleValue = value\n    }\n    \n    mutating func encode<T>(_ value: T) throws where T : Encodable {\n        encoder.singleValue = value as? QueryParameter\n    }\n    \n    \n}\n\nfileprivate struct QueryParameterKeyedEncodingContainer<Key : CodingKey> : KeyedEncodingContainerProtocol {\n    fileprivate let codingPath = [CodingKey]()\n    \n    fileprivate let encoder: QueryParameterEncoder\n    \n    mutating func encodeNil(forKey key: Key) throws {\n        encoder.dict[key.stringValue] = nil\n    }\n    \n    mutating func encode(_ value: Bool, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: Int, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: Int8, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: Int16, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: Int32, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: Int64, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: UInt, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: UInt8, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: UInt16, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: UInt32, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: UInt64, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: Float, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: Double, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode(_ value: String, forKey key: Key) throws {\n        encoder.dict[key.stringValue] = value\n    }\n    \n    mutating func encode<T>(_ value: T, forKey key: Key) throws where T : Encodable {\n        if T.self == Date.self {\n            encoder.dict[key.stringValue] = value as! Date\n        } else if T.self == DateComponents.self {\n            encoder.dict[key.stringValue] = value as! DateComponents\n        } else if T.self == Data.self {\n            encoder.dict[key.stringValue] = value as! Data\n        } else if T.self == URL.self {\n            // encode absoluteString same as JSONEncoder\n            // https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/JSONEncoder.swift\n            encoder.dict[key.stringValue] = (value as! URL).absoluteString\n        } else if T.self == Decimal.self {\n            encoder.dict[key.stringValue] = (value as! Decimal).description\n        } else if let custom = value as? QueryCustomDataParameter {\n            if let param = value as? QueryParameter {\n                if !param.omitOnQueryParameter {\n                    let data = try custom.encodeForQueryParameter()\n                    encoder.dict[key.stringValue] = Blob(data: data, dataType: custom.queryParameterDataType)\n                }\n            } else {\n                let data = try custom.encodeForQueryParameter()\n                encoder.dict[key.stringValue] = Blob(data: data, dataType: custom.queryParameterDataType)\n            }\n        } else {\n            let singleValueEncoder = QueryParameterEncoder()\n            try value.encode(to: singleValueEncoder)\n            if let param = value as? QueryParameter {\n                if !param.omitOnQueryParameter {\n                    encoder.dict[key.stringValue] = singleValueEncoder.singleValue\n                }\n            } else {\n                encoder.dict[key.stringValue] = singleValueEncoder.singleValue\n            }\n        }\n        \n        //fatalError(\"not supported type \\(T.self)\")\n    }\n    \n    mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {\n        fatalError(\"nestedContainer in query parameter is not supported.\")\n    }\n    \n    mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {\n        fatalError(\"nestedUnkeyedContainer in query parameter is not supported.\")\n    }\n    \n    mutating func superEncoder() -> Encoder {\n        fatalError(\"superEncoder in query parameter is not supported.\")\n    }\n    \n    mutating func superEncoder(forKey key: Key) -> Encoder {\n        fatalError(\"superEncoder(forKey:) in query parameter is not supported.\")\n    }\n}\n\n\n\nextension Encodable where Self: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        let encoder = QueryParameterEncoder()\n        try self.encode(to: encoder)\n        switch encoder.storageType {\n        case .dictionary:\n            return try QueryParameterDictionary(encoder.dict).queryParameter(option: option)\n        case .single:\n            return try (encoder.singleValue ?? QueryParameterNull.null).queryParameter(option: option)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/MySQL/RawRepresentableParameter.swift",
    "content": "//\n//  RawRepresentableParameter.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 4/21/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\nimport SQLFormatter\nimport Foundation\n\n\npublic protocol QueryRawRepresentableParameter: RawRepresentable, QueryParameter {\n    \n}\n\n\nextension QueryRawRepresentableParameter where RawValue: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        return try rawValue.queryParameter(option: option)\n    }\n}\n\n/*\nextension RawRepresentable where RawValue: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        return try rawValue.queryParameter(option: option)\n    }\n}*/\n\n"
  },
  {
    "path": "Sources/MySQL/Result-SQLRawStringDecodable.swift",
    "content": "//\n//  ResultTypes.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 12/28/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport Foundation\n\nextension Int: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Int {\n        guard let val = Int(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension UInt: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> UInt {\n        guard let val = UInt(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension Int64: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Int64 {\n        guard let val = Int64(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension Int32: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Int32 {\n        guard let val = Int32(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension Int16: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Int16 {\n        guard let val = Int16(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension Int8: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Int8 {\n        guard let val = Int8(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension UInt64: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> UInt64 {\n        guard let val = UInt64(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension UInt32: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> UInt32 {\n        guard let val = UInt32(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension UInt16: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> UInt16 {\n        guard let val = UInt16(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension UInt8: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> UInt8 {\n        guard let val = UInt8(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension Float: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Float {\n        guard let val = Float(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension Double: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Double {\n        guard let val = Double(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension String: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> String {\n        return string\n    }\n}\n\nextension Bool: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Bool {\n        guard let val = Int(string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return Bool(val == 0 ? false : true )\n    }\n}\n\nextension Decimal: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Decimal {\n        guard let val = Decimal(string: string) else {\n            throw QueryError.resultDecodeError(rawSQLValue: string, forType: self)\n        }\n        return val\n    }\n}\n\nextension Date: SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Date {\n        fatalError(\"invalid constructor (use init instead)\")\n    }\n}\n"
  },
  {
    "path": "Sources/MySQL/Result.swift",
    "content": "//\n//  Result.swift\n//  MySQL\n//\n//  Created by ito on 12/10/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport Foundation\n\ninternal protocol SQLRawStringDecodable {\n    static func fromSQLValue(string: String) throws -> Self\n}\n\ninternal struct QueryRowResult {\n    \n    private let fields: [Connection.Field]\n    private let fieldValues: [Connection.FieldValue]\n    internal let columnMap: [String: Connection.FieldValue] // the key is field name\n    init(fields: [Connection.Field], fieldValues: [Connection.FieldValue]) {\n        self.fields = fields\n        self.fieldValues = fieldValues\n        var map:[String: Connection.FieldValue] = [:]\n        for i in 0..<fieldValues.count {\n            map[fields[i].name] = fieldValues[i]\n        }\n        self.columnMap = map\n    }\n    \n    func isNull(forField field: String) -> Bool {\n        guard let fieldValue = columnMap[field] else {\n            return false\n        }\n        switch fieldValue {\n        case .null:\n            return true\n        case .binary, .date:\n            return false\n        }\n    }\n    \n    private func castOrFail<T: SQLRawStringDecodable>(_ obj: String, field: String) throws -> T {\n        //print(\"casting val \\(obj) to \\(T.self)\")\n        do {\n            return try T.fromSQLValue(string: obj)\n        } catch {\n            throw QueryError.SQLRawStringDecodeError(error: error, actualValue: obj, expectedType: \"\\(T.self)\", forField: field)\n        }\n    }\n    \n    private func getValue<T: SQLRawStringDecodable>(fieldValue: Connection.FieldValue, field: String) throws -> T {\n        switch fieldValue {\n        case .null:\n            throw QueryError.resultCastError(actualValue: \"NULL\", expectedType: \"\\(T.self)\", forField: field)\n        case .date(let string, let timezone):\n            if T.self == Date.self {\n                return try Date(sqlDate: string, timeZone: timezone) as! T\n            } else if T.self == DateComponents.self {\n                return try DateComponents.fromSQLValue(string: string) as! T\n            }\n            throw QueryError.resultCastError(actualValue: \"\\(string)\", expectedType: \"\\(T.self)\", forField: field)\n        case .binary(let data):\n            //print(\"T is \\(T.self)\")\n            if let bin = data as? T {\n                return bin\n            }\n            return try castOrFail(fieldValue.string(), field: field)\n        }\n    }\n    \n    func getValue<T: SQLRawStringDecodable>(forField field: String) throws -> T {\n        guard let fieldValue = columnMap[field] else {\n            throw QueryError.missingField(field)\n        }\n        return try getValue(fieldValue: fieldValue, field: field)\n    }    \n}\n\ninternal struct QueryRowResultDecoder : Decoder {\n    let codingPath = [CodingKey]()\n    let userInfo = [CodingUserInfoKey : Any]()\n    let row: QueryRowResult\n    \n    public func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {\n        return KeyedDecodingContainer(RowKeyedDecodingContainer<Key>(decoder: self))\n    }\n    \n    public func unkeyedContainer() throws -> UnkeyedDecodingContainer {\n        throw QueryError.resultDecodeErrorMessage(message: \"Decoder unkeyedContainer not implemented\")\n    }\n    \n    public func singleValueContainer() throws -> SingleValueDecodingContainer {\n        throw QueryError.resultDecodeErrorMessage(message: \"Decoder singleValueContainer not implemented\")\n    }\n}\n\nfileprivate struct SQLStringDecoder: Decoder {\n    let codingPath =  [CodingKey]()\n    let userInfo = [CodingUserInfoKey : Any]()\n    let sqlString: String\n    \n    struct SingleValue: SingleValueDecodingContainer {\n        let codingPath =  [CodingKey]()\n        let sqlString: String\n        func decodeNil() -> Bool {\n            fatalError()\n        }\n        \n        func decode(_ type: Bool.Type) throws -> Bool {\n            fatalError()\n        }\n        \n        func decode(_ type: Int.Type) throws -> Int {\n            return try Int.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: Int8.Type) throws -> Int8 {\n            return try Int8.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: Int16.Type) throws -> Int16 {\n            return try Int16.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: Int32.Type) throws -> Int32 {\n            return try Int32.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: Int64.Type) throws -> Int64 {\n            return try Int64.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: UInt.Type) throws -> UInt {\n            return try UInt.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: UInt8.Type) throws -> UInt8 {\n            return try UInt8.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: UInt16.Type) throws -> UInt16 {\n            return try UInt16.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: UInt32.Type) throws -> UInt32 {\n            return try UInt32.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: UInt64.Type) throws -> UInt64 {\n            return try UInt64.fromSQLValue(string: sqlString)\n        }\n        \n        func decode(_ type: Float.Type) throws -> Float {\n            fatalError()\n        }\n        \n        func decode(_ type: Double.Type) throws -> Double {\n            fatalError()\n        }\n        \n        func decode(_ type: String.Type) throws -> String {\n            return sqlString\n        }\n        \n        func decode<T>(_ type: T.Type) throws -> T where T : Decodable {\n            fatalError()\n        }\n        \n    }\n\n    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {\n        throw QueryError.resultDecodeErrorMessage(message: \"RawTypeDecoder container(keyedBy:) not implemented, you could implement `QueryRowResultCustomData` \")\n    }\n    \n    func unkeyedContainer() throws -> UnkeyedDecodingContainer {\n        throw QueryError.resultDecodeErrorMessage(message: \"RawTypeDecoder unkeyedContainer not implemented\")\n    }\n    \n    func singleValueContainer() throws -> SingleValueDecodingContainer {\n        return SingleValue(sqlString: sqlString)\n    }\n }\n\nfileprivate struct RowKeyedDecodingContainer<K : CodingKey> : KeyedDecodingContainerProtocol {\n    typealias Key = K\n    \n    let decoder : QueryRowResultDecoder\n    \n    let allKeys = [Key]()\n    \n    let codingPath = [CodingKey]()\n    \n    func decodeNil(forKey key: K) throws -> Bool {\n        return false\n    }\n    \n    func contains(_ key: K) -> Bool {\n        return decoder.row.columnMap[key.stringValue] != nil && !decoder.row.isNull(forField: key.stringValue)\n    }\n    \n    func decode(_ type: Bool.Type, forKey key: K) throws -> Bool {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: Int.Type, forKey key: K) throws -> Int {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: Int8.Type, forKey key: K) throws -> Int8 {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: Int16.Type, forKey key: K) throws -> Int16 {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: Int32.Type, forKey key: K) throws -> Int32 {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: Int64.Type, forKey key: K) throws -> Int64 {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: UInt.Type, forKey key: K) throws -> UInt {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: UInt8.Type, forKey key: K) throws -> UInt8 {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: UInt16.Type, forKey key: K) throws -> UInt16 {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: UInt32.Type, forKey key: K) throws -> UInt32 {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: UInt64.Type, forKey key: K) throws -> UInt64 {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: Float.Type, forKey key: K) throws -> Float {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: Double.Type, forKey key: K) throws -> Double {\n        return try decoder.row.getValue(forField: key.stringValue)\n    }\n    \n    func decode(_ type: String.Type, forKey key: K) throws -> String {\n        return try decoder.row.getValue(forField: key.stringValue) as String\n    }\n    \n    func decode<T>(_ t: T.Type, forKey key: K) throws -> T where T : Decodable {\n        if t == Data.self {\n            return try decoder.row.getValue(forField: key.stringValue) as Data as! T\n        } else if t == Date.self {\n            return try decoder.row.getValue(forField: key.stringValue) as Date as! T\n        } else if t == DateComponents.self {\n            return try decoder.row.getValue(forField: key.stringValue) as DateComponents as! T\n        } else if t == URL.self {\n            let urlString = try decoder.row.getValue(forField: key.stringValue) as String\n            guard let url = URL(string: urlString) else {\n                throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,\n                                                                        debugDescription: \"Invalid URL string.\"))\n            }\n            return url as! T\n        } else if t == Decimal.self {\n            return try decoder.row.getValue(forField: key.stringValue) as Decimal as! T\n        } else if let customType = t as? QueryRowResultCustomData.Type {\n            let data = try decoder.row.getValue(forField: key.stringValue) as Data\n            return try customType.decode(fromRowData: data) as! T\n        }\n        guard let columnValue = decoder.row.columnMap[key.stringValue] else {\n            throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: [key], debugDescription: \"\"))\n        }\n        let d = SQLStringDecoder(sqlString: try columnValue.string())\n        return try T(from: d)\n    }\n    \n    func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: K) throws -> KeyedDecodingContainer<NestedKey> {\n        throw QueryError.resultDecodeErrorMessage(message: \"KeyedDecodingContainer nestedContainer not implemented\")\n    }\n    \n    func nestedUnkeyedContainer(forKey key: K) throws -> UnkeyedDecodingContainer {\n        throw QueryError.resultDecodeErrorMessage(message: \"KeyedDecodingContainer nestedContainer not implemented\")\n    }\n    \n    func superDecoder() throws -> Decoder {\n        throw QueryError.resultDecodeErrorMessage(message: \"KeyedDecodingContainer superDecoder not implemented\")\n    }\n    \n    func superDecoder(forKey key: K) throws -> Decoder {\n        throw QueryError.resultDecodeErrorMessage(message: \"KeyedDecodingContainer superDecoder(forKey) not implemented\")\n    }\n}\n"
  },
  {
    "path": "Sources/MySQL/Sync.swift",
    "content": "//\n//  Sync.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 1/12/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\n#if os(Linux)\n    import Glibc\n#elseif os(OSX)\n    import Darwin.C\n#endif\n\nfileprivate final class Mutex {\n    private var mutex = pthread_mutex_t()\n    init() {\n        pthread_mutex_init(&mutex, nil)\n    }\n    \n    func lock() {\n        pthread_mutex_lock(&mutex)\n    }\n    \n    func unlock() {\n        pthread_mutex_unlock(&mutex)\n    }\n    \n    deinit {\n        pthread_mutex_destroy(&mutex)\n    }\n}\n\ninternal struct Atomic<T> {\n    private var value: T\n    private let mutex = Mutex()\n    init(_ value: T) {\n        self.value = value\n    }\n    mutating func syncWriting<R>( _ block: (inout T) throws -> R) rethrows -> R {\n        mutex.lock()\n        defer {\n            mutex.unlock()\n        }\n        let result = try block(&value)\n        return result\n    }\n    \n    func sync<R>( _ block: (T) throws -> R) rethrows -> R {\n        mutex.lock()\n        defer {\n            mutex.unlock()\n        }\n        let result = try block(value)\n        return result\n    }\n}\n"
  },
  {
    "path": "Sources/MySQL/Transaction.swift",
    "content": "//\n//  Connection-Transaction.swift\n//  MySQL\n//\n//  Created by ito on 12/24/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\n\nextension Connection {\n    \n    func beginTransaction() throws {\n        _ = try query(\"START TRANSACTION;\")\n    }\n\n    func commit() throws {\n        _ = try query(\"COMMIT;\")\n    }\n    \n    func rollback() throws {\n        _ = try query(\"ROLLBACK;\")\n    }\n}\n\nextension ConnectionPool {\n    \n    public func transaction<T>( _ block: (_ conn: Connection) throws -> T  ) throws -> T {\n        let conn = try getConnection()\n        defer {\n            if option.reconnect {\n                conn.setReconnect(true)\n            }\n            releaseConnection(conn)\n        }\n        \n        // disable reconnect option of MySQL while transaction\n        conn.setReconnect(false)\n        \n        try conn.beginTransaction()\n        do {\n            let result = try block(conn)\n            try conn.commit()\n            return result\n        } catch {\n            do {\n                try conn.rollback()\n            } catch {\n                print(\"error while `ROLLBACK`.\", error)\n            }\n            throw error\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SQLFormatter/Error.swift",
    "content": "//\n//  Error.swift\n//  SQLFormatter\n//\n//  Created by Yusuke Ito on 4/5/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\npublic enum QueryFormatError: Error {\n    case placeholderCountMismatch(query: String)\n    case parameterIDTypeError(givenValue: String, query: String)\n}\n"
  },
  {
    "path": "Sources/SQLFormatter/QueryFormatter.swift",
    "content": "//\n//  Query.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 12/14/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport Foundation\n\npublic protocol QueryParameterType {\n    func escaped() -> String\n    func escapedForID() -> String? // returns nil if not supported for query id parameter\n}\n\npublic struct SQLString {\n    \n    public static func escapeForID(_ str: String) -> String {\n        var step1 = \"\"\n        for c in str {\n            switch c {\n            case \"`\":\n                step1 += \"``\"\n            default:\n                step1.append(c)\n            }\n        }\n        var out = \"\"\n        for c in step1 {\n            switch c {\n            case \".\":\n                out += \"`.`\"\n            default:\n                out.append(c)\n            }\n        }\n        return \"`\\(out)`\"\n    }\n    \n    public static func escape(_ str: String) -> String {\n        var out = \"'\"\n        for c in str.unicodeScalars {\n            switch c {\n            case \"\\0\":\n                out += \"\\\\0\"\n            case \"\\n\":\n                out += \"\\\\n\"\n            case \"\\r\":\n                out += \"\\\\r\"\n            case \"\\u{8}\":\n                out += \"\\\\b\"\n            case \"\\t\":\n                out += \"\\\\t\"\n            case \"\\\\\":\n                out += \"\\\\\\\\\"\n            case \"'\":\n                out += \"\\\\'\"\n            case \"\\\"\":\n                out += \"\\\\\\\"\"\n            case \"\\u{1A}\":\n                out += \"\\\\Z\"\n            default:\n                out.append(Character(c))\n            }\n        }\n        out.append(\"'\")\n        return out\n    }\n    \n    public static func escapeForLike(_ str: String, escapingWith: Character = \"\\\\\") -> String {\n        var out = \"\"\n        for c in str.unicodeScalars {\n            switch c {\n            case \"%\", \"_\":\n                out.append(escapingWith)\n            default: break\n            }\n            out.append(Character(c))\n        }\n        return out\n    }\n}\n\npublic struct QueryFormatter {\n    \n    public static func format(query: String, parameters: [QueryParameterType]) throws -> String {\n        \n        var placeHolderCount = 0\n        \n        var formatted = query + \"\"\n        \n        var valArgs: [QueryParameterType] = []\n        var scanRange = formatted.startIndex..<formatted.endIndex\n        \n        // format ??\n        while true {\n            // TODO: use function in Swift.String\n            let r1 = formatted.range(of: \"??\", options: [], range: scanRange, locale: nil)\n            let r2 = formatted.range(of: \"?\", options: [], range: scanRange, locale: nil)\n            let r: Range<String.Index>\n            if let r1 = r1, let r2 = r2 {\n                r = r1.lowerBound <= r2.lowerBound ? r1 : r2\n            } else if let rr = r1 ?? r2 {\n                r = rr\n            } else {\n                break\n            }\n            \n            switch formatted[r] {\n            case \"??\":\n                if placeHolderCount >= parameters.count {\n                    throw QueryFormatError.placeholderCountMismatch(query: query)\n                }\n                guard let escapedVal = parameters[placeHolderCount].escapedForID() else {\n                    throw QueryFormatError.parameterIDTypeError(givenValue: \"\\(parameters[placeHolderCount])\", query: query)\n                }\n                formatted.replaceSubrange(r, with: escapedVal)\n                scanRange = r.upperBound..<formatted.endIndex\n            case \"?\":\n                if placeHolderCount >= parameters.count {\n                    throw QueryFormatError.placeholderCountMismatch(query: query)\n                }\n                valArgs.append(parameters[placeHolderCount])\n                scanRange = r.upperBound..<formatted.endIndex\n            default: break\n            }\n            \n            placeHolderCount += 1\n            \n            if placeHolderCount >= parameters.count {\n                break\n            }\n        }\n        \n        //print(formatted, valArgs)\n        \n        placeHolderCount = 0\n        var formattedChars = Array(formatted)\n        var index = 0\n        while index < formattedChars.count {\n            if formattedChars[index] == \"?\" {\n                if placeHolderCount >= valArgs.count {\n                    throw QueryFormatError.placeholderCountMismatch(query: query)\n                }\n                let val = valArgs[placeHolderCount]\n                formattedChars.remove(at: index)\n                let valStr = val.escaped()\n                formattedChars.insert(contentsOf: valStr, at: index)\n                index += valStr.count - 1\n                placeHolderCount += 1\n            } else {\n                index += 1\n            }\n        }\n        \n        return String(formattedChars)\n    }\n}\n\n"
  },
  {
    "path": "Sources/cmysql/macos.pc",
    "content": "prefix=/usr/local/opt/mysql\nexec_prefix=${prefix}\nlibdir=${exec_prefix}/lib\nincludedir=${prefix}/include\nName: MySQL\nDescription: MySQL client library\nVersion: 2.0\nCflags: -I${includedir}\nLibs: -L${libdir} -lmysqlclient\n"
  },
  {
    "path": "Sources/cmysql/module.modulemap",
    "content": "module CMySQL [system] {\n    header \"shim.h\"\n    link \"mysqlclient\"\n    export *\n}\n"
  },
  {
    "path": "Sources/cmysql/shim.h",
    "content": "#ifndef __CMYSQL_SHIM_H__\n#define __CMYSQL_SHIM_H__\n\n#include <mysql/mysql.h>\n\n#if LIBMYSQL_VERSION_ID >= 80000\ntypedef int my_bool;\n#endif\n\n#endif\n\n"
  },
  {
    "path": "Tests/LinuxMain.swift",
    "content": "import XCTest\n\nimport MySQLTests\nimport SQLFormatterTests\n\nvar tests = [XCTestCaseEntry]()\ntests += MySQLTests.__allTests()\ntests += SQLFormatterTests.__allTests()\n\nXCTMain(tests)\n"
  },
  {
    "path": "Tests/MySQLTests/BlobTests.swift",
    "content": "//\n//  SQLTypeTests.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 4/21/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\n@testable import MySQL\nimport Foundation\n\nextension Row {\n    \n    fileprivate struct BlobTextRow: Codable, QueryParameter {\n        let id: AutoincrementID<BlobTextID>\n        \n        let text1: String\n        let binary1: Data\n    }\n    \n    fileprivate struct JSONDataUser: Codable, Equatable, QueryCustomDataParameter, QueryRowResultCustomData {\n        func encodeForQueryParameter() throws -> Data {\n            let encoder = JSONEncoder()\n            return try encoder.encode(self)\n        }\n        \n        var queryParameterDataType: QueryCustomDataParameterDataType {\n            return .json\n        }\n        \n        static func decode(fromRowData data: Data) throws -> Row.JSONDataUser {\n            let decoder = JSONDecoder()\n            return try decoder.decode(self, from: data)\n        }\n        \n        // this type decoded from and encoded to Data, like JSON, Protobuf...\n        let name: String\n    }\n    \n    fileprivate struct JSONColumnUser: Codable, QueryParameter, Equatable {\n        let userName: String\n        let jsonValue_blob: JSONDataUser\n        let jsonValue_json: JSONDataUser\n    }\n    \n}\n\nfinal class BlobQueryTests: XCTestCase, QueryTestType {\n    \n    var constants: TestConstantsType!\n    var pool: ConnectionPool!\n    \n    override func setUp() {\n        super.setUp()\n        \n        prepare()\n        try! createBlobTable()\n    }\n    \n    func createBinaryBlobTable() throws {\n        try dropTestTable()\n        \n        let conn = try pool.getConnection()\n        let query = \"CREATE TABLE `\\(constants.tableName)` (\" +\n            \"`id` int(11) unsigned NOT NULL AUTO_INCREMENT,\" +\n            \"`text1` mediumtext NOT NULL,\" +\n            \"`binary1` mediumblob NOT NULL,\" +\n            \"PRIMARY KEY (`id`)\" +\n        \") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;\"\n        \n        _ = try conn.query(query)\n    }\n    \n    func createBlobTable() throws {\n        try dropTestTable()\n        \n        let conn = try pool.getConnection()\n        let query = \"CREATE TABLE `\\(constants.tableName)` (\" +\n            \"`id` int(11) unsigned NOT NULL AUTO_INCREMENT,\" +\n            \"`text1` mediumtext NOT NULL,\" +\n            \"`binary1` mediumblob NOT NULL,\" +\n            \"PRIMARY KEY (`id`)\" +\n        \") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\"\n        \n        _ = try conn.query(query)\n    }\n    \n    func testInsertForCombinedUnicodeCharacter() throws {\n        let str = \"'ﾞ and áäèëî , ¥\"\n        \n        let obj = Row.BlobTextRow(id: .noID, text1: str, binary1: Data() )\n        let status: QueryStatus = try pool.execute { conn in\n            try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, obj])\n        }\n        XCTAssertEqual(status.insertedID, 1)\n        \n    }\n    \n    func testBlobAndTextOnBinCollation() throws {\n        \n        try createBinaryBlobTable()\n        \n        let testBinary: [UInt8] = Array( (UInt8(0)...UInt8(255)) )\n        \n        let obj = Row.BlobTextRow(id: .noID, text1: \"\", binary1: Data(testBinary) )\n        let status: QueryStatus = try pool.execute { conn in\n            try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, obj])\n        }\n        XCTAssertEqual(status.insertedID, 1)\n        \n        let rows: [Row.BlobTextRow] = try pool.execute{ conn in\n            try conn.query(\"SELECT * FROM ??\", [constants.tableName])\n        }\n        XCTAssertEqual(rows.count, 1)\n        XCTAssertEqual(rows[0].binary1.count, 256)\n        XCTAssertEqual(rows[0].binary1, Data(testBinary))\n        \n        print(rows[0].binary1, testBinary)\n    }\n    \n    func testEscapeBlob() throws {\n        \n        do {\n            let testBinary: [UInt8] = [0, 0x1, 0x9, 0x10, 0x1f, 0x99, 0xff, 0x00, 0x0a]\n            let str = try Data(testBinary).queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(str, \"x'000109101f99ff000a'\")\n        }\n    }\n    \n    \n    private func createJSONValueTable() throws {\n        try dropTestTable()\n        \n        let conn = try pool.getConnection()\n        let query = \"\"\"\n        CREATE TABLE `\\(constants.tableName)` (\n        `id` int(11) unsigned NOT NULL AUTO_INCREMENT,\n        `userName` mediumtext NOT NULL,\n        `jsonValue_blob` mediumblob NOT NULL,\n        `jsonValue_json` json NOT NULL,\n        PRIMARY KEY (`id`)\n        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n        \"\"\"\n        \n        _ = try conn.query(query)\n    }\n    \n    func testJSONColumnValue() throws {\n        \n        try createJSONValueTable()\n        \n        let jsonValue = Row.JSONDataUser(name: \"name in json value\")\n        let user = Row.JSONColumnUser(userName: \"john\", jsonValue_blob: jsonValue, jsonValue_json: jsonValue)\n        let status: QueryStatus = try pool.execute { conn in\n            try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, user])\n        }\n        XCTAssertEqual(status.insertedID, 1)\n        \n        let rows: [Row.JSONColumnUser] = try pool.execute{ conn in\n            try conn.query(\"SELECT * FROM ??\", [constants.tableName])\n        }\n        XCTAssertEqual(rows.count, 1)\n        XCTAssertEqual(rows[0], user)\n    }\n    \n}\n"
  },
  {
    "path": "Tests/MySQLTests/ConnectionPoolTests.swift",
    "content": "//\n//  ConnectionPoolTests.swift\n//  MySQL\n//\n//  Created by ito on 12/24/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport Foundation\nimport Dispatch\nimport XCTest\n@testable import MySQL\n\nfinal class ConnectionPoolTests: XCTestCase, MySQLTestType {\n\n    \n    var constants: TestConstantsType!\n    var pool: ConnectionPool!\n    \n    override func setUp() {\n        super.setUp()\n        \n        prepare()\n    }\n\n    func testGetConnection() throws {\n        \n        let initialConnection = 1\n        \n        XCTAssertEqual(pool.pool.sync { $0.count }, initialConnection)\n        XCTAssertEqual(pool.pool.sync { $0.inUseConnections }, 0)\n        \n        var connections: [Connection] = []\n        for _ in 0..<initialConnection {\n            let con = try pool.getConnection()\n            connections.append(con)\n        }\n        XCTAssertEqual(connections.count, initialConnection)\n        XCTAssertEqual(pool.pool.sync { $0.inUseConnections }, initialConnection)\n        \n        // increse initial connections\n        pool.initialConnections = 7\n        XCTAssertEqual(pool.pool.sync { $0.count }, 7)\n        \n        // get connection while max connections count\n        while connections.count < pool.maxConnections {\n            let con = try pool.getConnection()\n            connections.append(con)\n        }\n        \n        XCTAssertEqual(connections.count, pool.maxConnections)\n        XCTAssertEqual(pool.pool.sync { $0.count }, pool.maxConnections)\n        XCTAssertEqual(pool.pool.sync { $0.inUseConnections }, pool.maxConnections)\n        \n        // this connection getting failure\n        pool.timeoutForGetConnection = 2\n        XCTAssertThrowsError(try pool.getConnection())\n        \n        for c in connections {\n            // release connections that we have got\n            c.release()\n        }\n        connections.removeAll()\n        XCTAssertEqual(pool.pool.sync { $0.inUseConnections }, 0)\n        XCTAssertEqual(pool.pool.sync { $0.count }, pool.maxConnections)\n    }\n    \n    \n    func testExecutionBlock() throws {\n        \n        var thisConn: Connection!\n        try pool.execute { conn in\n            thisConn = conn\n            XCTAssertEqual(conn.isInUse, true)\n            _ = try conn.query(\"SELECT 1 + 2;\")\n        }\n        XCTAssertEqual(thisConn.isInUse, false)\n    }\n\n    private var errors: [Error?] = []\n    private var errorSemaphore = DispatchSemaphore(value: 0)\n    \n    func testThreadingConnectionPool() throws {\n        \n        pool.maxConnections = 3\n        pool.initialConnections = 3\n        \n        if #available(OSX 10.12, *) {\n            \n            let THREAD_COUNT = 10\n            errors = [Error?](repeating: nil, count: THREAD_COUNT)\n            let semaphore = DispatchSemaphore(value: 0)\n            \n            \n            for i in 0..<THREAD_COUNT {\n                Thread.detachNewThread {\n                    print(Thread.current)\n                    do {\n                        try self.pool.execute { conn in\n                            _ = try conn.query(\"SELECT 1 + 2;\")\n                            sleep(1)\n                        }\n                        print(\"done\", Thread.current)\n                    } catch {\n                        print(\"error while executing\", error)\n                        self.errors[i] = error\n                    }\n                    \n                    semaphore.signal()\n                }\n            }\n            \n            print(\"waiting until thread is done.\")\n            \n            for _ in 0..<THREAD_COUNT {\n                semaphore.wait()\n            }\n            \n            print(\"thread done\", errors)\n            \n            for i in 0..<THREAD_COUNT {\n                if let error = errors[i] {\n                    XCTFail(\"\\(error)\")\n                }\n            }\n            \n        } else {\n            fatalError()\n        }\n    }\n    \n}\n"
  },
  {
    "path": "Tests/MySQLTests/ConnectionTests.swift",
    "content": "//\n//  ConnectionTest.swift\n//  MySQL\n//\n//  Created by ito on 12/20/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\n@testable import MySQL\n\nfinal class ConnectionTests: XCTestCase, MySQLTestType {\n    \n    var constants: TestConstantsType!\n    var pool: ConnectionPool!\n\n    override func setUp() {\n        super.setUp()\n        \n        prepare()\n    }\n    \n    func testConnect() throws {\n        let conn = try pool.getConnection()\n        XCTAssertTrue(conn.ping())\n    }\n    \n    func testConnect2() throws {\n        let conn = try pool.getConnection()\n        _ = try conn.query(\"SELECT 1;\" as String)\n        XCTAssertTrue(conn.ping())\n    }\n    \n    struct Option: ConnectionOption {\n        let host: String = \"dummy\"\n        let port: Int = 3306\n        let user: String = \"dummy\"\n        let password: String = \"dummy\"\n        let database: String = \"dummy\"\n    }\n    \n    func testDefaultConnectionOption() {\n        \n        let option = Option()\n        \n        XCTAssertNotNil(option.timeZone)\n    }\n}\n"
  },
  {
    "path": "Tests/MySQLTests/DateTests.swift",
    "content": "//\n//  DateTests.swift\n//  MySQL\n//\n//  Created by ito on 12/20/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\nimport CoreFoundation\nimport Foundation\n@testable import MySQL\n\nstruct QueryParameterTestOption: QueryParameterOption {\n    let timeZone: TimeZone\n}\n\nextension XCTestCase {\n    var queryOption: QueryParameterOption {\n        return QueryParameterTestOption(timeZone: TimeZone(abbreviation: \"UTC\")!)\n    }\n}\n\nfinal class DateTests : XCTestCase {\n    \n    func testSQLDate() throws {\n        \n        let gmt = QueryParameterTestOption(timeZone: TimeZone(abbreviation: \"UTC\")!)\n        let losAngeles = QueryParameterTestOption(timeZone: TimeZone(identifier: \"America/Los_Angeles\")!)\n        \n        let expected = \"2003-01-02 03:04:05\" // no timezone\n        \n        let date = Date(timeIntervalSince1970: 1041476645) // \"2003-01-02 03:04:05\" at GMT\n        XCTAssertEqual(date.queryParameter(option: gmt).escaped(), \"'\\(expected)'\")\n        \n        let sqlDate = try Date(sqlDate: expected, timeZone: losAngeles.timeZone)\n        let dateAtLos = Date(timeIntervalSince1970: 1041476645 + 3600*8)\n    \n        XCTAssertEqual(sqlDate, dateAtLos, \"create date from sql string\")\n        XCTAssertEqual(sqlDate.queryParameter(option: losAngeles).escaped(), \"'\\(expected)'\")\n        \n        XCTAssertEqual(sqlDate, dateAtLos)\n        \n        XCTAssertNotEqual(try Date(sqlDate: expected, timeZone: losAngeles.timeZone),\n            try Date(sqlDate: expected, timeZone: gmt.timeZone))\n        \n        XCTAssertEqual(try Date(sqlDate: expected, timeZone: losAngeles.timeZone),\n            try Date(sqlDate: expected, timeZone: losAngeles.timeZone))\n    }\n    \n    func testSQLCalendar() {\n        let timeZone = TimeZone(abbreviation: \"PDT\")!\n        let cal1 = SQLDateCalendar.calendar(forTimezone: timeZone, { $0 })\n        let cal2 = SQLDateCalendar.calendar(forTimezone: timeZone, { $0 })\n        XCTAssertEqual(cal1, cal2)\n        XCTAssertEqual(cal1.hashValue, cal2.hashValue)\n    }\n    \n    func testDateComponents() throws {\n        \n        do {\n            // YEAR\n            let comps = try DateComponents.fromSQLValue(string: \"9999\")\n            XCTAssertEqual(comps.year, 9999)\n        }\n        \n        do {\n            // DATETIME\n            // with nanoseconds\n            let comps = try DateComponents.fromSQLValue(string: \"9999-12-31 23:59:58.123456\")\n            XCTAssertEqual(comps.year, 9999)\n            XCTAssertEqual(comps.month, 12)\n            XCTAssertEqual(comps.day, 31)\n            \n            XCTAssertEqual(comps.hour, 23)\n            XCTAssertEqual(comps.minute, 59)\n            XCTAssertEqual(comps.second, 58)\n            \n            XCTAssertEqual(comps.nanosecond, 123456_000)\n        }\n        \n        do {\n            // DATETIME\n            let comps = try DateComponents.fromSQLValue(string: \"9999-12-31 23:59:58\")\n            XCTAssertEqual(comps.year, 9999)\n            XCTAssertEqual(comps.month, 12)\n            XCTAssertEqual(comps.day, 31)\n            \n            XCTAssertEqual(comps.hour, 23)\n            XCTAssertEqual(comps.minute, 59)\n            XCTAssertEqual(comps.second, 58)\n        }\n        \n        do {\n            // TIME\n            // negative hours\n            let comps = try DateComponents.fromSQLValue(string: \"-123:59:58\")\n            \n            XCTAssertEqual(comps.hour, -123)\n            XCTAssertEqual(comps.minute, 59)\n            XCTAssertEqual(comps.second, 58)\n        }\n        \n        do {\n            // TIME\n            // with nanoseconds\n            let comps = try DateComponents.fromSQLValue(string: \"893:59:58.123456\")\n            XCTAssertEqual(comps.hour, 893)\n            XCTAssertEqual(comps.minute, 59)\n            XCTAssertEqual(comps.second, 58)\n            \n            XCTAssertEqual(comps.nanosecond, 123456_000)\n        }\n        \n        do {\n            // DATE\n            let comps = try DateComponents.fromSQLValue(string: \"9999-12-31\")\n            XCTAssertEqual(comps.year, 9999)\n            XCTAssertEqual(comps.month, 12)\n            XCTAssertEqual(comps.day, 31)\n        }\n        \n    }\n}\n"
  },
  {
    "path": "Tests/MySQLTests/EscapeTests.swift",
    "content": "//\n//  EscapeTests.swift\n//  MySQL\n//\n//  Created by ito on 12/20/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\n@testable import MySQL\nimport SQLFormatter\n\nfinal class EscapeTests: XCTestCase {\n\n    // https://github.com/mysqljs/mysql/blob/master/test/unit/protocol/test-SqlString.js\n    func testStringEscape() {\n        XCTAssertEqual(SQLString.escape(\"Sup'er\"), \"'Sup\\\\'er'\")\n        \n        XCTAssertEqual(SQLString.escape(\"\\u{00A5}\"), \"'¥'\")\n        XCTAssertEqual(SQLString.escape(\"\\\\\"), \"'\\\\\\\\'\")\n        \n        // escape combined character\n        XCTAssertEqual(SQLString.escape(\"'ﾞ\"), \"'\\\\'ﾞ'\")\n    }\n    \n    func testBasicTypes() throws {\n        \n        let strVal: String = \"Sup'er\"\n        let strValOptional: String? = \"Sup'er Super\"\n        let strValOptionalNone: String? = nil\n        \n        \n        XCTAssertEqual(strVal.queryParameter(option: queryOption).escaped(), \"'Sup\\\\'er'\")\n        XCTAssertEqual(try strValOptional.queryParameter(option: queryOption).escaped(), \"'Sup\\\\'er Super'\")\n        XCTAssertEqual(try ((strValOptionalNone ?? QueryParameterNull.null) as QueryParameter).queryParameter(option: queryOption).escaped(), \"NULL\")\n    }\n    \n    func testArrayType() throws {\n        \n        let strVal: String = \"Sup'er\"\n        let strValOptional: String? = \"Sup'er Super\"\n        let strValOptionalNone: String? = nil\n        \n        let strs: [QueryParameter] = [strVal, strVal]\n        \n        XCTAssertEqual(try QueryParameterArray(strs).queryParameter(option: queryOption).escaped(), \"'Sup\\\\'er', 'Sup\\\\'er'\")\n        \n        let strsOptional1: [QueryParameter?] = [strVal, strValOptional]\n        XCTAssertEqual(try QueryParameterArray(strsOptional1).queryParameter(option: queryOption).escaped(), \"'Sup\\\\'er', 'Sup\\\\'er Super'\")\n        \n        let strsOptional2: [QueryParameter?] = [strVal, strValOptionalNone]\n        XCTAssertEqual(try QueryParameterArray(strsOptional2).queryParameter(option: queryOption).escaped(), \"'Sup\\\\'er', NULL\")\n        \n        \n        let arr = QueryParameterArray(strs)\n        let arrayOfArr = QueryParameterArray( [arr] )\n        XCTAssertEqual(try arrayOfArr.queryParameter(option: queryOption).escaped(), \"('Sup\\\\'er', 'Sup\\\\'er')\")\n        \n        let strInt:[QueryParameter] = [strVal, 271]\n        XCTAssertEqual(try QueryParameterArray(strInt).queryParameter(option: queryOption).escaped(), \"'Sup\\\\'er', 271\")\n        \n        let strOptionalAndInt:[QueryParameter] = [strValOptional, 3.14]\n        XCTAssertEqual(try QueryParameterArray(strOptionalAndInt).queryParameter(option: queryOption).escaped(), \"'Sup\\\\'er Super', 3.14\")\n    }\n    \n    func testNestedArray() throws {\n        \n        let strVal: String = \"Sup'er\"\n        let strValOptionalNone: String? = nil\n        let child: [QueryParameter] = [strVal, strValOptionalNone]\n        let strs: [QueryParameter] = [strVal, strValOptionalNone, QueryParameterArray(child)]\n        \n        XCTAssertEqual(try QueryParameterArray(strs).queryParameter(option: queryOption).escaped(), \"\\'Sup\\\\\\'er\\', NULL, (\\'Sup\\\\\\'er\\', NULL)\")\n        \n    }\n    \n    func testAutoincrement() throws {\n        let strVal: String = \"Sup'er\"\n        \n        do {\n            let userID: AutoincrementID<UserID> = .ID(UserID(333))\n            XCTAssertEqual(try userID.queryParameter(option: queryOption).escaped(), \"333\")\n            let arr: [QueryParameter] = [strVal, userID]\n            XCTAssertEqual(try QueryParameterArray(arr).queryParameter(option: queryOption).escaped(), \"\\'Sup\\\\\\'er\\', 333\")\n        }\n        \n        do {\n            let stringID: AutoincrementID<SomeStringID> = .ID(SomeStringID(\"id-555@\"))\n            XCTAssertEqual(try stringID.queryParameter(option: queryOption).escaped(), \"\\'id-555@\\'\")\n            let arr: [QueryParameter] = [strVal, stringID]\n            XCTAssertEqual(try QueryParameterArray(arr).queryParameter(option: queryOption).escaped(), \"\\'Sup\\\\\\'er\\', \\'id-555@\\'\")\n        }\n        \n        do {\n            let noID: AutoincrementID<UserID> = .noID\n            XCTAssertEqual(try noID.queryParameter(option: queryOption).escaped(), \"\\'\\'\")\n            \n            let arr: [QueryParameter] = [strVal, noID]\n            XCTAssertEqual(try QueryParameterArray(arr).queryParameter(option: queryOption).escaped(), \"\\'Sup\\\\\\'er\\'\")\n        }\n    }\n    \n    func testDictionary() {\n        \n        \n        let strVal: String = \"Sup'er\"\n        let strValOptional: String? = \"Sup'er Super\"\n        let strValOptionalNone: String? = nil\n        \n        let dict = QueryParameterDictionary([\n            \"string\": strVal,\n            \"stringOptional\": strValOptional,\n            \"stringNone\" : strValOptionalNone\n            ])\n        \n        let expectedResult = Set(arrayLiteral: \"`string` = 'Sup\\\\'er'\", \"`stringOptional` = 'Sup\\\\'er Super'\", \"`stringNone` = NULL\")\n        let escaped = try! dict.queryParameter(option: queryOption).escaped()\n        XCTAssertEqual(Set(escaped.split(separator: \",\").map(String.init).map({ $0.trimmingCharacters(in: .whitespaces) })), expectedResult)\n        \n    }\n    \n}\n"
  },
  {
    "path": "Tests/MySQLTests/Model.swift",
    "content": "//\n//  Model.swift\n//  MySQL\n//\n//  Created by ito on 12/20/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport MySQL\nimport Foundation\n\nstruct UserID: IDType {\n    let id: Int\n    init(_ id: Int) {\n        self.id = id\n    }\n}\n\nstruct BlobTextID: IDType {\n    let id: Int\n    init(_ id: Int) {\n        self.id = id\n    }\n}\n\nstruct SomeStringID: IDType {\n    let id: String\n    init(_ id: String) {\n        self.id = id\n    }\n}\n\n\nfinal class Row {\n    private init() { }\n}\n"
  },
  {
    "path": "Tests/MySQLTests/MySQLConnection.swift",
    "content": "//\n//  MySQLTests.swift\n//  MySQLTests\n//\n//  Created by ito on 2015/10/24.\n//  Copyright © 2015年 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\nimport MySQL\nimport Foundation\n\n/*\n \nstruct TestConstants: TestConstantsType {\n    let host: String = \"\"\n    let port: Int = 3306\n    let user: String = \"\"\n    let password: String = \"\"\n    let database: String = \"test\"\n    let tableName: String = \"unit_test_db_3894\" // Unit test creates a table\n    let encoding: Connection.Encoding = .UTF8MB4\n    let timeZone: Connection.TimeZone = Connection.TimeZone(GMTOffset: 60 * 60 * 9) // JST\n}\n\n*/\n\nstruct DummyConstants: TestConstantsType {\n    let host: String = \"127.0.0.1\"\n    let port: Int = 3306\n    let user: String = \"root\"\n    let password: String = \"\"\n    let database: String = \"test\"\n    let tableName: String = \"unit_test_db_3894\"\n    let encoding: Connection.Encoding = .UTF8MB4\n    let timeZone: TimeZone = TimeZone(abbreviation: \"JST\")! // JST\n    let reconnect: Bool = true\n}\n\nprotocol TestConstantsType: ConnectionOption {\n    var tableName: String { get }\n}\n\nprotocol MySQLTestType: class {\n    var constants: TestConstantsType! { get set }\n    var pool: ConnectionPool! { get set }\n}\n\nextension MySQLTestType {\n    func prepare() {\n        self.constants = DummyConstants() // !!! Replace with your MySQL connection !!!\n        self.pool = ConnectionPool(option: constants)\n        \n        XCTAssertEqual(constants.timeZone, TimeZone(abbreviation: \"JST\"), \"test MySQL's timezone should be JST\")\n    }\n}\n\n\n"
  },
  {
    "path": "Tests/MySQLTests/QueryDecimalTypeTests.swift",
    "content": "//\n//  QueryDecimalTypeTests.swift\n//  MySQLTests\n//\n//  Created by Yusuke Ito on 5/1/18.\n//\n\nimport XCTest\n@testable import MySQL\nimport Foundation\n\nextension Row {\n    fileprivate struct DecimalRow: Codable, QueryParameter, Equatable {\n        let valueDoubleColumn: Decimal\n        let valueTextColumn: Decimal\n        private enum CodingKeys: String, CodingKey {\n            case valueDoubleColumn = \"value_double_col\"\n            case valueTextColumn = \"value_text_col\"\n        }\n    }\n}\n\n\nfinal class QueryDecimalTypeTests: XCTestCase, QueryTestType {\n    var constants: TestConstantsType!\n    var pool: ConnectionPool!\n    \n    override func setUp() {\n        super.setUp()\n        \n        prepare()\n        try! createDecimalTestTable()\n    }\n    \n    private func createDecimalTestTable() throws {\n        try dropTestTable()\n        \n        let conn = try pool.getConnection()\n        let query = \"\"\"\n        CREATE TABLE `\\(constants.tableName)` (\n        `id` int(11) unsigned NOT NULL AUTO_INCREMENT,\n        `value_double_col` DOUBLE NOT NULL DEFAULT 0,\n        `value_text_col` MEDIUMTEXT,\n        PRIMARY KEY (`id`)\n        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n        \"\"\"\n        \n        _ = try conn.query(query)\n    }\n    \n    \n    func testDecimalType() throws {\n        let value = Decimal(string: \"1.549\")!\n        let row = Row.DecimalRow(valueDoubleColumn: value, valueTextColumn: value)\n        \n        try pool.execute { conn in\n            _ = try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, row])\n        }\n        \n        let rows: [Row.DecimalRow] = try pool.execute {\n            try $0.query(\"SELECT * FROM ?? ORDER BY id ASC\", [constants.tableName])\n        }\n        \n        XCTAssertEqual(rows[0], row)\n    }\n    \n    func testDecimalType_largerValue() throws {\n        let value = Decimal(string: \"1.23e100\")!\n        let row = Row.DecimalRow(valueDoubleColumn: value, valueTextColumn: value)\n    \n        try pool.execute { conn in\n            _ = try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, row])\n        }\n        \n        let rows: [Row.DecimalRow] = try pool.execute {\n            try $0.query(\"SELECT * FROM ?? ORDER BY id ASC\", [constants.tableName])\n        }\n        \n        XCTAssertEqual(rows[0], row)\n    }\n}\n"
  },
  {
    "path": "Tests/MySQLTests/QueryFormatterTests.swift",
    "content": "//\n//  QueryFormatterTests.swift\n//  MySQL\n//\n//  Created by ito on 12/20/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\n@testable import MySQL\nimport SQLFormatter\n\n\nfinal class QueryFormatterTests: XCTestCase {\n    \n    fileprivate enum TableName: String, QueryRawRepresentableParameter {\n        case user = \"user\"\n    }\n    \n    func testBasicFormatting() throws {\n        \n        let params: (String, TableName, String, Int, String, Int?) = (\n            \"i.d\",\n            TableName.user,\n            \"id\",\n            1,\n            \"user's\",\n            nil\n        )\n        let args: [QueryParameter] = [\n            params.0,\n            params.1,\n            params.2,\n            params.3,\n            params.4,\n            params.5,\n        ]\n        \n        let formatted = try QueryFormatter.format(query: \"SELECT name,??,id FROM ?? WHERE ?? = ? OR name = ? OR age is ?;\", parameters: Connection.buildParameters(args, option: queryOption) )\n        XCTAssertEqual(formatted, \"SELECT name,`i`.`d`,id FROM `user` WHERE `id` = 1 OR name = 'user\\\\'s' OR age is NULL;\")\n    }\n    \n    func testLikeEscape() {\n        \n        XCTAssertEqual(SQLString.escapeForLike(\"ap%ple_\"), \"ap\\\\%ple\\\\_\")\n        XCTAssertEqual(SQLString.escapeForLike(\"ap\\\\%ple_\"), \"ap\\\\\\\\%ple\\\\_\")\n        \n        XCTAssertEqual(SQLString.escapeForLike(\"ap%ple_\", escapingWith: \"$\"), \"ap$%ple$_\")\n        XCTAssertEqual(SQLString.escapeForLike(\"ap\\\\%ple_\", escapingWith: \"$\"), \"ap\\\\$%ple$_\")\n    }\n    \n    func testPlaceholder() throws {\n        let params: [QueryParameter] = [\"name\", \"message??\", \"col\", \"hello??\", \"hello?\"]\n        let formatted = try QueryFormatter.format(query: \"SELECT ??, ?, ??, ?, ?\", parameters: Connection.buildParameters(params, option: queryOption))\n        XCTAssertEqual(formatted, \"SELECT `name`, 'message??', `col`, 'hello??', 'hello?'\")\n    }\n    \n    func testStringUtil() {\n        let someString = \"abcdefghijklmn12345\"\n        XCTAssertEqual(someString.subString(max: 10), \"abcdefghij\")\n        XCTAssertEqual(someString.subString(max: 1000), someString)\n        \n        XCTAssertEqual(\"\".subString(max: 10), \"\")\n    }\n}\n"
  },
  {
    "path": "Tests/MySQLTests/QueryParameterTests.swift",
    "content": "//\n//  QueryParameterTests.swift\n//  MySQL\n//\n//  Created by Yusuke Ito on 4/21/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\nimport MySQL\nimport SQLFormatter\n\n// the URL as QueryParameter should be\nextension URL: QueryParameter {\n    public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {\n        return self.absoluteString.queryParameter(option: option)\n    }\n}\n\nextension QueryParameterTests {\n    static var allTests : [(String, (QueryParameterTests) -> () throws -> Void)] {\n        return [\n                (\"testIDType\", testIDType),\n                (\"testIDTypeInContainer\", testIDTypeInContainer),\n                (\"testEnumType\", testEnumType),\n                (\"testAutoincrementType\", testAutoincrementType),\n                (\"testDateComponentsType\", testDateComponentsType),\n                (\"testDataAndURLType\", testDataAndURLType),\n                (\"testDecimalType\", testDecimalType),\n                (\"testCodableIDType\", testCodableIDType),\n                (\"testCodableIDType_AutoincrementNoID\", testCodableIDType_AutoincrementNoID)\n        ]\n    }\n}\n\nfinal class QueryParameterTests: XCTestCase {\n    \n    \n    private struct IDInt: IDType {\n        let id: Int\n        init(_ id: Int) {\n            self.id = id\n        }\n    }\n    \n    private struct IDString: IDType {\n        let id: String\n        init(_ id: String) {\n            self.id = id\n        }\n    }\n    \n    private struct ModelWithIDType_StringAutoincrement: Encodable, QueryParameter {\n        let idStringAutoincrement: AutoincrementID<IDString>\n    }\n    \n    private struct ModelWithIDType_IntAutoincrement: Encodable, QueryParameter {\n        let idIntAutoincrement: AutoincrementID<IDInt>\n    }\n    \n    private enum SomeEnumParameter: String, QueryRawRepresentableParameter {\n        case first = \"first 1\"\n        case second = \"second' 2\"\n    }\n    \n    private enum SomeEnumCodable: String, Codable, QueryParameter {\n        case first = \"first 1\"\n        case second = \"second' 2\"\n    }\n    \n    // https://developer.apple.com/documentation/swift/optionset\n    private struct ShippingOptions: OptionSet, QueryRawRepresentableParameter {\n        let rawValue: Int\n        \n        static let nextDay    = ShippingOptions(rawValue: 1 << 0)\n        static let secondDay  = ShippingOptions(rawValue: 1 << 1)\n        static let priority   = ShippingOptions(rawValue: 1 << 2)\n        static let standard   = ShippingOptions(rawValue: 1 << 3)\n        \n        static let express: ShippingOptions = [.nextDay, .secondDay]\n        static let all: ShippingOptions = [.express, .priority, .standard]\n    }\n    \n    private struct ModelWithData: Encodable, QueryParameter {\n        let data: Data\n    }\n    \n    private struct ModelWithDate: Encodable, QueryParameter {\n        let date: Date\n    }\n    \n    private struct ModelWithDateComponents: Encodable, QueryParameter {\n        let dateComponents: DateComponents\n    }\n    \n    private struct ModelWithURL: Encodable, QueryParameter {\n        let url: URL\n    }\n    \n    private struct ModelWithDecimal: Encodable, QueryParameter {\n        let value: Decimal\n    }\n\n    func testIDType() throws {\n        \n        let idInt: QueryParameter = IDInt(1234)\n        XCTAssertEqual(try idInt.queryParameter(option: queryOption).escaped(), \"1234\")\n        \n        //let id: SomeID = try SomeID.fromSQLValue(string: \"5678\")\n        //XCTAssertEqual(id.id, 5678)\n        \n        let idString: QueryParameter = IDString(\"123abc\")\n        XCTAssertEqual(try idString.queryParameter(option: queryOption).escaped(), \"'123abc'\")\n        \n        \n        let idIntAutoincrement: QueryParameter = AutoincrementID(IDInt(1234))\n        XCTAssertEqual(try idIntAutoincrement.queryParameter(option: queryOption).escaped(), \"1234\")\n        \n        let idStringAutoincrement: QueryParameter = AutoincrementID(IDString(\"123abc\"))\n        XCTAssertEqual(try idStringAutoincrement.queryParameter(option: queryOption).escaped(), \"'123abc'\")\n        \n    }\n    \n    func testIDTypeInContainer() throws {\n        \n        do {\n            let param: QueryParameter = ModelWithIDType_IntAutoincrement(idIntAutoincrement: .ID(IDInt(1234)))\n            XCTAssertEqual(try param.queryParameter(option: queryOption).escaped(), \"`idIntAutoincrement` = 1234\")\n        }\n        do {\n            let param: QueryParameter = ModelWithIDType_StringAutoincrement(idStringAutoincrement: .ID(IDString(\"123abc\")))\n            XCTAssertEqual(try param.queryParameter(option: queryOption).escaped(), \"`idStringAutoincrement` = '123abc'\")\n        }\n        \n    }\n    \n    func testEnumType() throws {\n        \n        do {\n            let someVal: QueryParameter = SomeEnumParameter.second\n            let escaped = \"second' 2\".escaped()\n            XCTAssertEqual(try someVal.queryParameter(option: queryOption).escaped() , escaped)\n        }\n        \n        do {\n            let someVal: QueryParameter = SomeEnumCodable.second\n            let escaped = \"second' 2\".escaped()\n            XCTAssertEqual(try someVal.queryParameter(option: queryOption).escaped() , escaped)\n        }\n        \n        do {\n            let someOption: QueryParameter = ShippingOptions.all\n            XCTAssertEqual(try someOption.queryParameter(option: queryOption).escaped() , \"\\(ShippingOptions.all.rawValue)\")\n        }\n    }\n    \n    func testAutoincrementType() throws {\n        \n        let userID: AutoincrementID<UserID> = .ID(UserID(333))\n        XCTAssertEqual(userID, AutoincrementID.ID(UserID(333)))\n        \n        let someStringID: AutoincrementID<SomeStringID> = .ID(SomeStringID(\"id678@\"))\n        XCTAssertEqual(someStringID, AutoincrementID.ID(SomeStringID(\"id678@\")))\n        \n        let noID: AutoincrementID<UserID> = .noID\n        XCTAssertEqual(noID, AutoincrementID.noID)\n    }\n    \n    func testDateComponentsType() throws {\n\n        do {\n            let compsEmpty = DateComponents()\n            let model = ModelWithDateComponents(dateComponents: compsEmpty)\n            let _ = try model.queryParameter(option: queryOption).escaped()\n            XCTFail(\"this should be throws an error\")\n        } catch {\n            // OK\n        }\n        do {\n            // MySQL YEAR type\n            var comps = DateComponents()\n            comps.year = 2155\n            let model = ModelWithDateComponents(dateComponents: comps)\n            \n            let queryString = try model.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(queryString, \"`dateComponents` = '2155'\")\n        }\n        \n        do {\n            // MySQL TIME type\n            var comps = DateComponents()\n            comps.hour = -838\n            comps.minute = 59\n            comps.second = 59\n            let model = ModelWithDateComponents(dateComponents: comps)\n            \n            let queryString = try model.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(queryString, \"`dateComponents` = '-838:59:59'\")\n        }\n        \n        do {\n            // MySQL TIME type\n            // with nanosecond\n            var comps = DateComponents()\n            comps.hour = -838\n            comps.minute = 59\n            comps.second = 59\n            comps.nanosecond = 1234567\n            let model = ModelWithDateComponents(dateComponents: comps)\n            \n            let queryString = try model.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(queryString, \"`dateComponents` = '-838:59:59.001235'\")\n        }\n        \n        do {\n            // MySQL DATETIME, TIMESTAMP type\n            var comps = DateComponents()\n            comps.year = 9999\n            comps.month = 12\n            comps.day = 31\n            comps.hour = 23\n            comps.minute = 59\n            comps.second = 59\n            let model = ModelWithDateComponents(dateComponents: comps)\n            \n            let queryString = try model.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(queryString, \"`dateComponents` = '9999-12-31 23:59:59'\")\n        }\n        \n        do {\n            // MySQL DATETIME, TIMESTAMP type\n            // with nanosecond\n            var comps = DateComponents()\n            comps.year = 9999\n            comps.month = 12\n            comps.day = 31\n            comps.hour = 23\n            comps.minute = 59\n            comps.second = 59\n            comps.nanosecond = 1234567\n            let model = ModelWithDateComponents(dateComponents: comps)\n            \n            let queryString = try model.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(queryString, \"`dateComponents` = '9999-12-31 23:59:59.001235'\")\n        }\n        \n    }\n    \n    func testDataAndURLType() throws {\n        \n        do {\n            let dataModel = ModelWithData(data: Data([0x12, 0x34, 0x56, 0xff, 0x00]))\n            let queryString = try dataModel.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(queryString,\n                           \"`data` = x'123456ff00'\")\n        }\n        \n        do {\n            let urlModel = ModelWithURL(url: URL(string: \"https://apple.com/iphone\")!)\n            let queryString = try urlModel.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(queryString,\n                           \"`url` = 'https://apple.com/iphone'\")\n        }\n        \n        do {\n            let param: QueryParameter = URL(string: \"https://apple.com/iphone\")!\n            let queryString = try param.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(queryString,\n                           \"'https://apple.com/iphone'\")\n        }\n    }\n\n    func testDecimalType() throws {\n        let decimalModel = ModelWithDecimal(value: Decimal(1.2345e100))\n        let queryString = try decimalModel.queryParameter(option: queryOption).escaped()\n        XCTAssertEqual(queryString,\n                       \"`value` = '12345000000000010240000000000000000000000000000000000000000000000000000000000000000000000000000000000'\")\n    }\n    \n    private enum UserType: String, Codable {\n        case user = \"user\"\n        case admin = \"admin\"\n    }\n    \n    private struct CodableModel: Codable, QueryParameter {\n        let id: UserID\n        let name: String\n        let userType: UserType\n    }\n    \n    private struct CodableModelWithAutoincrement: Codable, QueryParameter {\n        let id: AutoincrementID<UserID>\n        let name: String\n        let userType: UserType\n    }\n    \n    func testCodableIDType() throws {\n        \n        \n        let expectedResult = Set(arrayLiteral: \"`id` = 123\", \"`name` = 'test4456'\", \"`userType` = 'user'\")\n        \n        do {\n            let parameter: QueryParameter = CodableModel(id: UserID(123),\n                                                         name: \"test4456\",\n                                                         userType: .user)\n            \n            let result = try parameter.queryParameter(option: queryOption).escaped()\n            \n            XCTAssertEqual(Set(result.split(separator: \",\").map(String.init).map({ $0.trimmingCharacters(in: .whitespaces) })), expectedResult)\n        }\n        \n        do {\n            let parameter: QueryParameter = CodableModelWithAutoincrement(id: AutoincrementID(UserID(123)),\n                                                                          name: \"test4456\",\n                                                                          userType: .user)\n            \n            let result = try parameter.queryParameter(option: queryOption).escaped()\n            XCTAssertEqual(Set(result.split(separator: \",\").map(String.init).map({ $0.trimmingCharacters(in: .whitespaces) })), expectedResult)\n        }\n        \n    }\n    \n    func testCodableIDType_AutoincrementNoID() throws {\n        \n        \n        let expectedResult = Set(arrayLiteral: \"`name` = 'test4456'\", \"`userType` = 'user'\")\n        \n        let parameter: QueryParameter = CodableModelWithAutoincrement(id: .noID,\n                                                                      name: \"test4456\",\n                                                                      userType: .user)\n        \n        let result = try parameter.queryParameter(option: queryOption).escaped()\n        \n        XCTAssertEqual(Set(result.split(separator: \",\").map(String.init).map({ $0.trimmingCharacters(in: .whitespaces) })), expectedResult)\n        \n    }\n}\n"
  },
  {
    "path": "Tests/MySQLTests/QueryTests.swift",
    "content": "//\n//  QueryTests.swift\n//  MySQL\n//\n//  Created by ito on 12/20/15.\n//  Copyright © 2015 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\n@testable import MySQL\nimport Foundation\n\nprotocol QueryTestType: MySQLTestType {\n    func dropTestTable() throws\n}\n\nextension QueryTestType {\n    func dropTestTable() throws {\n        let conn = try pool.getConnection()\n        _ = try conn.query(\"DROP TABLE IF EXISTS \\(constants.tableName)\")\n    }\n}\n\nextension Row {\n    \n    fileprivate struct SimpleUser: Codable, Equatable {\n        let id: UInt\n        let name: String\n        let age: Int\n    }\n    \n    fileprivate enum UserType: String, Codable {\n        case user = \"user\"\n        case admin = \"admin\"\n    }\n    \n    fileprivate struct User: Codable, QueryParameter, Equatable {\n        let id: AutoincrementID<UserID>\n        \n        let name: String\n        let age: Int\n        let createdAt: Date\n        \n        let createdAtDateComponentsOptional: DateComponents?\n        \n        let nameOptional: String?\n        let ageOptional: Int?\n        let createdAtOptional: Date?\n        \n        let done: Bool\n        let doneOptional: Bool?\n        \n        let userType: UserType\n        \n        private enum CodingKeys: String, CodingKey {\n            case id\n            case name\n            case age\n            case createdAt = \"created_at\"\n            \n            case createdAtDateComponentsOptional = \"created_at_datecomponents_Optional\"\n            case nameOptional = \"name_Optional\"\n            case ageOptional = \"age_Optional\"\n            case createdAtOptional = \"created_at_Optional\"\n            case done\n            case doneOptional = \"done_Optional\"\n            case userType = \"user_type\"\n        }\n    }\n}\n\nfinal class QueryTests: XCTestCase, QueryTestType {\n    \n    var constants: TestConstantsType!\n    var pool: ConnectionPool!\n    \n    override func setUp() {\n        super.setUp()\n        \n        prepare()\n        try! createTestTable()\n    }\n    \n    func createTestTable() throws {\n        try dropTestTable()\n        \n        let conn = try pool.getConnection()\n        let query = \"\"\"\n            CREATE TABLE `\\(constants.tableName)` (\n            `id` int(11) unsigned NOT NULL AUTO_INCREMENT,\n            `name` varchar(50) NOT NULL DEFAULT '',\n            `age` int(11) NOT NULL,\n            `created_at` datetime NOT NULL DEFAULT '2001-01-01 00:00:00',\n            `created_at_datecomponents_Optional` datetime(6) DEFAULT NULL,\n            `name_Optional` varchar(50) DEFAULT NULL,\n            `age_Optional` int(11) DEFAULT NULL,\n            `created_at_Optional` datetime DEFAULT NULL,\n            `done` tinyint(1) NOT NULL DEFAULT 0,\n            `done_Optional` tinyint(1) DEFAULT NULL,\n            `user_type` varchar(255) NOT NULL DEFAULT '',\n            PRIMARY KEY (`id`)\n            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n            \"\"\"\n        \n        _ = try conn.query(query)\n    }\n    \n    private var someDate: Date {\n        return try! Date(sqlDate: \"2015-12-27 16:54:00\", timeZone: pool.option.timeZone)\n    }\n    \n    private var anotherDate: Date {\n        return Date(timeIntervalSinceReferenceDate: 60*60*24*67)\n    }\n    \n    func testInsertRowCodable() throws {\n        \n        typealias User = Row.User\n        \n        let name = \"name 's\"\n        let age = 25\n        \n        let dateComponents = DateComponents(year: 2012, month: 3, day: 4, hour: 5, minute: 6, second: 7, nanosecond: 890_000_000)\n        \n        let userNil = User(id: .noID, name: name, age: age, createdAt: someDate, createdAtDateComponentsOptional: dateComponents, nameOptional: nil, ageOptional: nil, createdAtOptional: nil, done: false, doneOptional: nil, userType: .user)\n        let status: QueryStatus = try pool.execute { conn in\n            try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, userNil])\n        }\n        XCTAssertEqual(status.insertedID, 1)\n        \n        let userFill = User(id: .ID(UserID(134)), name: name, age: age, createdAt: someDate, createdAtDateComponentsOptional: dateComponents, nameOptional: \"fuga\", ageOptional: 50, createdAtOptional: anotherDate, done: true, doneOptional: false, userType: .admin)\n        let status2: QueryStatus = try pool.execute { conn in\n            try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, userFill])\n        }\n        XCTAssertEqual(status2.insertedID, 134)\n        \n        let rows:[User] = try pool.execute { conn in\n            try conn.query(\"SELECT id,name,age,created_at,created_at_datecomponents_Optional,name_Optional,age_Optional,created_at_Optional,done,done_Optional,user_type FROM ?? ORDER BY id ASC\", [constants.tableName])\n        }\n        \n        XCTAssertEqual(rows.count, 2)\n        \n        // first row\n        XCTAssertEqual(rows[0].id.id, UserID(Int(status.insertedID)))\n        XCTAssertEqual(rows[0].name, name)\n        XCTAssertEqual(rows[0].age, age)\n        XCTAssertEqual(rows[0].createdAt, someDate)\n        \n        XCTAssertNil(rows[0].nameOptional)\n        XCTAssertNil(rows[0].ageOptional)\n        XCTAssertNil(rows[0].createdAtOptional)\n        \n        XCTAssertFalse(rows[0].done)\n        XCTAssertNil(rows[0].doneOptional)\n        \n        XCTAssertEqual(rows[0].userType, .user)\n        \n        XCTAssertEqual(rows[1], userFill)\n    }\n    \n    func testTransaction() throws {\n        \n        let user = Row.User(id: .noID, name: \"name\", age: 11, createdAt: someDate, createdAtDateComponentsOptional: nil, nameOptional: nil, ageOptional: nil, createdAtOptional: nil, done: false, doneOptional: nil, userType: .user)\n        let status: QueryStatus = try pool.transaction { conn in\n            try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, user])\n        }\n        XCTAssertEqual(status.insertedID, 1)\n    }\n    \n    \n    func testEmojiInserting() throws {\n        \n        typealias User = Row.User\n        \n        \n        let now = Date()\n        let user = User(id: .noID, name: \"日本語123🍣🍺あいう\", age: 123, createdAt: now, createdAtDateComponentsOptional: nil, nameOptional: nil, ageOptional: nil, createdAtOptional: nil, done: false, doneOptional: nil, userType: .user)\n        let status: QueryStatus = try pool.execute { conn in\n            try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, user])\n        }\n        \n        let rows: [User] = try pool.execute{ conn in\n            try conn.query(\"SELECT id,name,age,created_at,name_Optional,age_Optional,created_at_Optional,done,done_Optional,user_type FROM ?? WHERE id = ?\", [constants.tableName, status.insertedID])\n        }\n        XCTAssertEqual(rows.count, 1)\n        XCTAssertEqual(rows[0].name, user.name)\n        XCTAssertEqual(rows[0].age, user.age)\n    }\n    \n    \n    func testBulkInsert() throws {\n        \n        //let now = Date()\n        let users = (1...3).map({ row in\n            Row.SimpleUser(id: UInt(10+row), name: \"name\\(row)\", age: row)\n        })\n    \n        let usersParam: [QueryParameterArray] = users.map { user in\n            QueryParameterArray([user.id, user.name, user.age])\n        }\n        \n        _ = try pool.execute { conn in\n            try conn.query(\"INSERT INTO ??(id,name,age) VALUES ? \", [constants.tableName, QueryParameterArray(usersParam)])\n        }\n        \n        let fetchedUsers: [Row.SimpleUser] = try pool.execute { conn in\n            try conn.query(\"SELECT id,name,age FROM ?? ORDER BY id DESC\", [constants.tableName])\n        }\n        XCTAssertEqual(fetchedUsers.count, 3)\n        \n        for index in (0..<3) {\n            XCTAssertEqual(fetchedUsers[index], users.reversed()[index])\n        }\n    }\n    \n}\n\n"
  },
  {
    "path": "Tests/MySQLTests/QueryURLTypeTests.swift",
    "content": "//\n//  QueryURLTypeTests.swift\n//  MySQLTests\n//\n//  Created by Yusuke Ito on 5/1/18.\n//\n\nimport XCTest\n@testable import MySQL\nimport Foundation\n\nextension Row {\n    fileprivate struct URLRow: Codable, QueryParameter, Equatable {\n        let url: URL\n        let urlOptional: URL?\n        private enum CodingKeys: String, CodingKey {\n            case url = \"url\"\n            case urlOptional = \"url_Optional\"\n        }\n    }\n}\n\n\nfinal class QueryURLTypeTests: XCTestCase, QueryTestType {\n    var constants: TestConstantsType!\n    var pool: ConnectionPool!\n    \n    override func setUp() {\n        super.setUp()\n        \n        prepare()\n        try! createURLTestTable()\n    }\n    \n    private func createURLTestTable() throws {\n        try dropTestTable()\n        \n        let conn = try pool.getConnection()\n        let query = \"\"\"\n        CREATE TABLE `\\(constants.tableName)` (\n        `id` int(11) unsigned NOT NULL AUTO_INCREMENT,\n        `url` mediumtext NOT NULL,\n        `url_Optional` mediumtext,\n        PRIMARY KEY (`id`)\n        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n        \"\"\"\n        \n        _ = try conn.query(query)\n    }\n    \n    \n    \n    func testURLType() throws {\n        \n        let urlRow1 = Row.URLRow(url: URL(string: \"https://apple.com/iphone\")!, urlOptional: nil)\n        let urlRow2 = Row.URLRow(url: URL(string: \"https://apple.com/iphone\")!, urlOptional: URL(string: \"https://apple.com/ipad\")!)\n        \n        try pool.execute { conn in\n            _ = try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, urlRow1])\n            _ = try conn.query(\"INSERT INTO ?? SET ? \", [constants.tableName, urlRow2])\n        }\n        \n        let rows: [Row.URLRow] = try pool.execute {\n            try $0.query(\"SELECT * FROM ?? ORDER BY id ASC\", [constants.tableName])\n        }\n        \n        XCTAssertEqual(rows[0], urlRow1)\n        XCTAssertEqual(rows[1], urlRow2)\n    }\n    \n    func testURLInvalid() throws {\n        \n        try pool.execute { conn in\n            _ = try conn.query(\"INSERT INTO ?? SET `url` = ''\", [constants.tableName])\n        }\n        \n        do {\n            let _: [Row.URLRow] = try pool.execute {\n                try $0.query(\"SELECT * FROM ?? ORDER BY id ASC\", [constants.tableName])\n            }\n        } catch let error as DecodingError {\n            switch error {\n            case .dataCorrupted(let context):\n                print(context)\n            // expected error\n            default:\n                XCTFail(\"unexpected error \\(error)\")\n            }\n        } catch {\n            XCTFail(\"unexpected error \\(error)\")\n        }\n    }\n    \n}\n"
  },
  {
    "path": "Tests/MySQLTests/XCTestManifests.swift",
    "content": "import XCTest\n\nextension BlobQueryTests {\n    static let __allTests = [\n        (\"testBlobAndTextOnBinCollation\", testBlobAndTextOnBinCollation),\n        (\"testEscapeBlob\", testEscapeBlob),\n        (\"testInsertForCombinedUnicodeCharacter\", testInsertForCombinedUnicodeCharacter),\n        (\"testJSONColumnValue\", testJSONColumnValue),\n    ]\n}\n\nextension ConnectionPoolTests {\n    static let __allTests = [\n        (\"testExecutionBlock\", testExecutionBlock),\n        (\"testGetConnection\", testGetConnection),\n        (\"testThreadingConnectionPool\", testThreadingConnectionPool),\n    ]\n}\n\nextension ConnectionTests {\n    static let __allTests = [\n        (\"testConnect2\", testConnect2),\n        (\"testConnect\", testConnect),\n        (\"testDefaultConnectionOption\", testDefaultConnectionOption),\n    ]\n}\n\nextension DateTests {\n    static let __allTests = [\n        (\"testDateComponents\", testDateComponents),\n        (\"testSQLCalendar\", testSQLCalendar),\n        (\"testSQLDate\", testSQLDate),\n    ]\n}\n\nextension EscapeTests {\n    static let __allTests = [\n        (\"testArrayType\", testArrayType),\n        (\"testAutoincrement\", testAutoincrement),\n        (\"testBasicTypes\", testBasicTypes),\n        (\"testDictionary\", testDictionary),\n        (\"testNestedArray\", testNestedArray),\n        (\"testStringEscape\", testStringEscape),\n    ]\n}\n\nextension QueryDecimalTypeTests {\n    static let __allTests = [\n        (\"testDecimalType_largerValue\", testDecimalType_largerValue),\n        (\"testDecimalType\", testDecimalType),\n    ]\n}\n\nextension QueryFormatterTests {\n    static let __allTests = [\n        (\"testBasicFormatting\", testBasicFormatting),\n        (\"testLikeEscape\", testLikeEscape),\n        (\"testPlaceholder\", testPlaceholder),\n        (\"testStringUtil\", testStringUtil),\n    ]\n}\n\nextension QueryParameterTests {\n    static let __allTests = [\n        (\"testAutoincrementType\", testAutoincrementType),\n        (\"testCodableIDType_AutoincrementNoID\", testCodableIDType_AutoincrementNoID),\n        (\"testCodableIDType\", testCodableIDType),\n        (\"testDataAndURLType\", testDataAndURLType),\n        (\"testDateComponentsType\", testDateComponentsType),\n        (\"testDecimalType\", testDecimalType),\n        (\"testEnumType\", testEnumType),\n        (\"testIDType\", testIDType),\n        (\"testIDTypeInContainer\", testIDTypeInContainer),\n    ]\n}\n\nextension QueryTests {\n    static let __allTests = [\n        (\"testBulkInsert\", testBulkInsert),\n        (\"testEmojiInserting\", testEmojiInserting),\n        (\"testInsertRowCodable\", testInsertRowCodable),\n        (\"testTransaction\", testTransaction),\n    ]\n}\n\nextension QueryURLTypeTests {\n    static let __allTests = [\n        (\"testURLInvalid\", testURLInvalid),\n        (\"testURLType\", testURLType),\n    ]\n}\n\n#if !os(macOS)\npublic func __allTests() -> [XCTestCaseEntry] {\n    return [\n        testCase(BlobQueryTests.__allTests),\n        testCase(ConnectionPoolTests.__allTests),\n        testCase(ConnectionTests.__allTests),\n        testCase(DateTests.__allTests),\n        testCase(EscapeTests.__allTests),\n        testCase(QueryDecimalTypeTests.__allTests),\n        testCase(QueryFormatterTests.__allTests),\n        testCase(QueryParameterTests.__allTests),\n        testCase(QueryTests.__allTests),\n        testCase(QueryURLTypeTests.__allTests),\n    ]\n}\n#endif\n"
  },
  {
    "path": "Tests/SQLFormatterTests/SQLFormatterTests.swift",
    "content": "//\n//  SQLFormatterTests.swift\n//  SQLFormatterTests\n//\n//  Created by Yusuke Ito on 4/5/16.\n//  Copyright © 2016 Yusuke Ito. All rights reserved.\n//\n\nimport XCTest\n@testable import SQLFormatter\n\n\nclass SQLFormattingTests: XCTestCase {\n    \n    func testDummy() throws {\n        XCTAssertTrue(true)\n    }\n}\n"
  },
  {
    "path": "Tests/SQLFormatterTests/XCTestManifests.swift",
    "content": "import XCTest\n\nextension SQLFormattingTests {\n    static let __allTests = [\n        (\"testDummy\", testDummy),\n    ]\n}\n\n#if !os(macOS)\npublic func __allTests() -> [XCTestCaseEntry] {\n    return [\n        testCase(SQLFormattingTests.__allTests),\n    ]\n}\n#endif\n"
  }
]