Qiitaでは初めまして。
SwiftでPostgreSQLに接続しようとして苦戦したのでそのメモを兼ねたサンプルです。
動作確認環境
バージョン | |
---|---|
OS | Ubuntu 16.04.1 LTS |
Swift | swift-3.0.1-RELEASE(公式のビルド済みファイルを使用) |
PostgreSQL | 9.5.5 |
バージョン | |
---|---|
IBM-Swift/Kitura | 1.2.2 |
Zewo/PostgreSQL | 0.14.3 |
下準備
最低限、以下のコマンドを実行しておいてください。
sudo apt-get install clang libicu-dev libcurl4-openssl-dev libssl-dev libpq-dev
SwiftとPostgreSQL自体のセットアップは省略しますが、下記の状態と想定して話をします。
- PostgreSQL
- ロール(ユーザー)名
- swiftsample
- パスワード
- swiftsample
- データベース名
- swiftsample
- データベースサーバーのURL
- localhost
- ロール(ユーザー)名
- Swift
- PATH設定済み
そして、swiftsampleデータベース上で、以下のクエリが実行済みの状態です。
CREATE TABLE IF NOT EXISTS profiles (
user_id INT NOT NULL PRIMARY KEY,
name text NOT NULL
);
INSERT INTO profiles(user_id,name) VALUES
(1,'Taro Tanaka'),
(2,'Jiro Yamada'),
(3,'Saburo Kato'),
(4,'Shiro Sato'),
(5,'Goro Watanabe');
実際にやってみる
Swift Package Managerを利用するために、プロジェクトを作成したいディレクトリへ移動済みのターミナルで
swift package init --type executable
を実行。
実行したらそのディレクトリにPackage.swiftというファイルやSourceディレクトリなどが作成されます。
Package.swiftは下記のようにしてください。
import PackageDescription
let package = Package(
name: "your package name",
dependencies: [
.Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion: 1, minor: 2),
.Package(url: "https://github.com/Zewo/PostgreSQL.git", majorVersion: 0, minor: 14)
]
)
Sourcesディレクトリに移動して、Data.swiftを作成し、次のように書いてみてください。
import SQL
import Foundation
enum SampleField: String, ModelField {
case userId = "user_id"
case name = "name"
static let tableName: String = "profiles"
static let primaryKey: SampleField = .userId
}
struct Sample {
let userId:Int
let name:String
}
extension Sample: ModelProtocol {
typealias Field = SampleField
typealias PrimaryKey = Int
func serialize() -> [Field : ValueConvertible?] {
return [
.userId: userId,
.name: name
]
}
init<Row: RowProtocol>(row: TableRow<Sample, Row>) throws {
userId = try row.value(.userId)
name = try row.value(.name)
}
}
次に同じディレクトリにあるmain.swiftを次のように書き換えてみてください。
import Kitura
import SQL
import PostgreSQL
import SwiftyJSON
import Foundation
let user = "swiftsample"
let password = "swiftsample"
let dbUrl = "localhost"
let dbName = "swiftsample"
enum SampleError: Error {
case urlNilError // URLがnilだったとき
}
do{
guard let url = URL(string: "postgres://\(user):\(password)@\(dbUrl):5432/\(dbName)") else {
throw SampleError.urlNilError
}
let db = try PostgreSQL.Connection(info: .init(url))
try db.open()
let getDatabase:((RouterRequest,RouterResponse)->()) = { request,response in
do{
let fetch:[PersistedEntity<Sample>]
if let id = request.parameters["id"] {
fetch = try Entity<Sample>.fetch(where: SampleField.userId == id,connection: db)
}else{
fetch = try Entity<Sample>.fetchAll(connection: db)
}
var arr:[[String:Any]] = []
fetch.forEach{ entity in
let model = entity.model
let id = model.userId
let name = model.name
arr.append([
"user_id":id,
"name":name
])
}
try response.send(json: JSON(arr)).end()
}catch(let e){
print("[エラーが発生したよ!]")
print(e)
}
}
let router = Router()
router.get("/:id(\\d+)") { request, response, _ in
getDatabase(request,response)
}
router.get("/") { request, response, _ in
getDatabase(request,response)
}
Kitura.addHTTPServer(onPort: 8090, with: router)
Kitura.run()
}catch(let e){
print("[エラーが発生したよ!]")
print(e)
}
あとはプロジェクトのルートディレクトリ(Package.swiftがあるディレクトリ)でビルドコマンドの
swift build -Xcc -I/usr/include/postgresql
を実行して、エラーがなく、正常にビルドされた場合は
(プロジェクトのルートディレクトリ)/.build/debug/(プロジェクト名)
を実行するとHTTPサーバーが8090番ポートで立ち上がります。
実際にアクセスしてみるとJSONが吐き出されるっていう感じになります。
以上です。