don't stop believing

Perfect + StORM + PostgreSQL 데이터 처리하기 2 본문

Swift/Perfect

Perfect + StORM + PostgreSQL 데이터 처리하기 2

Tongchun 2017. 10. 9. 16:44

내용이 길어저 나눠서 Post 합니다.

[Perfect + StORM + PostgresSQL 데이터 처리하기 1]을 먼저 확인해 주세요. 이어서 진행합니다.


데이터를 처리한 swift파일을 하나 만들고 DB 데이터를 처리할 함수들을 모아 놓겠습니다.

dataTreat.swift파일을 만들고 xcode을 열어 줍니다.

$ touch ./Sources/dataTreat.swift
$ swift package generate-xcodeproj
$ open nGleServer013.xcodeproj/

dataTreat.swift 파일에 StORM과 PostgresStORM을 import 합니다.

import StORM
import PostgresStORM

 1. obj.save

DB에 새로운 row를 추가합니다.

테이블에 primary key에 속하는 id가 있는 경우 save를 사용합니다.

만약 id가 없을 경우에는 .create 메소드를 사용해야 합니다.

아래와 같이 함수를 만들어 추가해 줍니다. word, means, explans를 받아 저장합니다.

func saveNew(word: String, means: String, explains: String) throws -> Words {

    let obj = Words()
    obj.word = word
    obj.means = means
    obj.example = explains

    do {
        try obj.save {id in obj.equipid = id as! Int }
    } catch {
        throw error
    }

    print("Object created with new id of \(obj.word)")
    return obj
}

main.swift에서 saveNew() 함수를 처리하는 함수를 만들어 줍니다.

func postSaveNew(request: HTTPRequest, response: HTTPResponse) {

    guard let jsonString = request.postBodyString else {
        response.completed(status: .badRequest)
        return
    }

    do {
        let jsonDic = try jsonString.jsonDecode() as! [String: String]
        let strWord = jsonDic["word"]!
        let strMeans = jsonDic["means"]!
        let strExplains = jsonDic["explanins"]!

        let newObj = try saveNew(word: strWord, means: strMeans, explains: strExplains)
        returnJSONMessage(message: "save success : \(newObj.word)", response: response)

    } catch {
        returnJSONMessage(message: "Error handling request: \(error)", response: response)
    }
}

참고로 response의 return 데이터는 Json형태로 반환하도록 returnJSONMessage()를 하나 만들어 사용합니다.

func returnJSONMessage(message: String, response: HTTPResponse) {
    do {
        try response.setBody(json: ["message": message])
            .setHeader(.contentType, value: "application/json")
            .completed()
    } catch {
        response.setBody(string: "Error handling request: \(error)")
            .completed(status: .internalServerError)
    }
}

그리고 routes에 경로를 추가해 줍니다.

routes.add(method: .post, uri: "/saveNew", handler: postSaveNew)

빌드하고 서버를 실행해 줍니다.

그리고 아래와 같이 호출해 봅니다.

이번에는 save하고 해당 id를 확인해 데이터를 불러 오도록 하겠습니다.

dataTreat.swift에 아래와 같이 추가합니다.

func getByID(word: String, means: String, explains: String) throws -> Words {

    let obj = Words()
    obj.word = word
    obj.means = means
    obj.example = explains

    do {
        try obj.save {id in obj.equipid = id as! Int }
    } catch {
        throw error
    }
    print("Object created with id of \(obj.equipid), and word is \(obj.word)")

    let getObj = Words()

    do {
        try getObj.get(obj.equipid)
    } catch {
        throw error
    }
    print("Object fetched with id of \(getObj.equipid), and word is \(getObj.word)")
    
    return getObj
}

main.swift에서 getByID() 함수를 처리할 함수도 만들어 줍니다.

func postGetByID(request: HTTPRequest, response: HTTPResponse) {

    guard let jsonString = request.postBodyString else {
        response.completed(status: .badRequest)
        return
    }

    do {
        let jsonDic = try jsonString.jsonDecode() as! [String: String]
        let strWord = jsonDic["word"]!
        let strMeans = jsonDic["means"]!
        let strExplains = jsonDic["explanins"]!

        let newObj = try getByID(word: strWord, means: strMeans, explains: strExplains)
        returnJSONMessage(message: "save success : \(newObj.word)", response: response)

    } catch {
        returnJSONMessage(message: "Error handling request: \(error)", response: response)
    }
}

routes에 경로를 추가하고 호출해 봅니다.

routes.add(method: .post, uri: "/getByID", handler: postGetByID)

저장하고 데이터를 불러 오는 것을 확인할 수 있습니다.

이번에는 새로운 row를 저장하고 column에 맞는 데이터를 찾아 리턴해 보겠습니다.

dataTreat.swift에 아래와 같이 작성합니다.

func findByStringAny(word: String, means: String, explains: String) throws -> Words {

    let obj = Words()
    obj.word = word
    obj.means = means
    obj.example = explains

    do {
        try obj.save {id in obj.equipid = id as! Int }
    } catch {
        throw error
    }
    print("Object created with id of \(obj.equipid), and word is \(obj.word)")

    let getObj = Words()

    var findObj = [String: Any]()
    findObj["word"] = word

    do {
        try getObj.find(findObj)
    } catch {
        throw error
    }
    print("Object fetched with id of \(getObj.equipid), and word is \(getObj.word)")
    
    return getObj
}

main.swift에 findByStringAny() 함수를 호출할 함수도 작성해 줍니다.

getObj.find()로 데이터를 찾을경우 동일한 데이터는 모두 찾아 집니다. 따라서 for row in newObj.rows()를 사용해 데이터를 모두 저장합니다.

func postFindByStringAny(request: HTTPRequest, response: HTTPResponse) {

    guard let jsonString = request.postBodyString else {
        response.completed(status: .badRequest)
        return
    }

    do {
        let jsonDic = try jsonString.jsonDecode() as! [String: String]
        let strWord = jsonDic["word"]!
        let strMeans = jsonDic["means"]!
        let strExplains = jsonDic["explanins"]!

        let newObj = try findByStringAny(word: strWord, means: strMeans, explains: strExplains)
        var wordDic: [[String: String]] = []

        for row in newObj.rows() {
            wordDic.append(row.asDictionary())
        }

        try response.setBody(json: wordDic)
            .setHeader(.contentType, value: "application/json")
            .completed()

    } catch {
        returnJSONMessage(message: "Error handling request: \(error)", response: response)
    }
}

routes에 경로를 추가하고 호출해 봅니다.

routes.add(method: .post, uri: "/findByString", handler: postFindByStringAny)

입력한 데이터에 해당하는 데이터를 모두 찾아 리턴합니다.

이번에는 where 절을 이용한 검색을 해보겠습니다.

이번엔 get 메소드로 데이터만 호출하는 걸 해보겠습니다. 

dataTreat.swift에 아래 코드를 추가해 봅니다. where 절의 like문을 사용해 데이터를 찾습니다. 주석으로 된 것 처럼 데이터와 일치하는 것도 찾을 수 있습니다.

func findBySelect(searchWord: String) throws -> Words {

    let getObj = Words()

    do {
        //try getObj.select(whereclause: "word = $1", params: [searchWord], orderby: ["equipid"])
        try getObj.select(whereclause: "word like $1", params: ["%\(searchWord)%"], orderby: ["equipid"])

        // Inspect the results cursor
        print("Objects fetched with select: found # \(getObj.results.cursorData.totalRecords)")

        // The response is [StORM.StORMRow] in the rows cursor
        print("Objects fetched with select are type StORM.StORMRow: rows \(getObj.results.rows)")

        // loop through found set in cursor
        for row in getObj.rows() {
            print("Object fetched with select: row id \(row.equipid)")
        }
        
    } catch {
        throw error
    }
    
    return getObj
}

main.swift에 get 메소드로 파라메터를 받아 findBySelect()함수를 실행하는 함수를 만들어 줍니다.

func getFindBySelect(request: HTTPRequest, response: HTTPResponse) {

    guard let searchWord = request.urlVariables["searchWord"] else {
        response.completed(status: .badRequest)
        return
    }

    do {
        let newObj = try findBySelect(searchWord: searchWord)
        var wordDic: [[String: String]] = []

        for row in newObj.rows() {
            wordDic.append(row.asDictionary())
        }

        try response.setBody(json: wordDic)
            .setHeader(.contentType, value: "application/json")
            .completed()

    } catch {
        returnJSONMessage(message: "Error handling request: \(error)", response: response)
    }
}

그리고 routes에 경로를 추가해 줍니다.

routes.add(method: .get, uri: "/findBySelect/{searchWord}", handler: getFindBySelect)

get 메소드로 look에 대한 like 검색을 해보겠습니다.

이번에는 업데이트를 해보겠습니다.

findUpdate() 함수를 만들고 업데이트하려는 데이터가 있다면 업데이트, 없다면 추가하도록 만들겠습니다.

dataTreat.swift에 아래와 같이 작성합니다.

먼저 .find()로 데이터를 찾고 getObj.results.cursorData.totalRecords 가 0이 아니라면 업데이트, 0이라면 추가하도록 합니다.

func findUpdate(word: String, means: String, example: String) throws -> Words {

    let getObj = Words()
    let newObj = Words()

    var findObj = [String: Any]()
    findObj["word"] = word

    do {
        try getObj.find(findObj)
    } catch {
        throw error
    }

    print("Objects fetched with select: found # \(getObj.results.cursorData.totalRecords)")

    if getObj.results.cursorData.totalRecords > 0 {

        do {
            try newObj.update(cols: ["word", "means", "example"],
                              params: [word, means, example],
                              idName: "equipid",
                              idValue: getObj.equipid)
        } catch {
            throw error
        }
        print("Object is changed. \(newObj.word)")

        do {
            try newObj.get(getObj.equipid)
        } catch {
            throw error
        }
        print("Object fetched with id of \(newObj.equipid), and word is \(newObj.word)")
        return newObj

    } else {

        newObj.word = word
        newObj.means = means
        newObj.example = example

        do {
            try newObj.save {id in newObj.equipid = id as! Int }
        } catch {
            throw error
        }
        print("Object created with new id of \(newObj.word)")

        do {
            try newObj.get(newObj.equipid)
        } catch {
            throw error
        }
        print("Object fetched with id of \(newObj.equipid), and word is \(newObj.word)")
        return newObj
    }
}

main.swift 파일에 findUpdate() 함수를 호출하는 함수를 만들어 줍니다.

func postFindUpdate(request: HTTPRequest, response: HTTPResponse) {

    guard let jsonString = request.postBodyString else {
        response.completed(status: .badRequest)
        return
    }

    do {
        let jsonDic = try jsonString.jsonDecode() as! [String: String]
        let strWord = jsonDic["word"]!
        let strMeans = jsonDic["means"]!
        let strExplains = jsonDic["explanins"]!

        let newObj = try findUpdate(word: strWord, means: strMeans, example: strExplains)
        var wordDic: [[String: String]] = []

        for row in newObj.rows() {
            wordDic.append(row.asDictionary())
        }

        try response.setBody(json: wordDic)
            .setHeader(.contentType, value: "application/json")
            .completed()

    } catch {
        returnJSONMessage(message: "Error handling request: \(error)", response: response)
    }
}

그리고 routes에 경로를 추가 합니다.

routes.add(method: .post, uri: "/findUpdate", handler: postFindUpdate)

이제 마지막으로 데이터를 삭제해 보겠습니다.

삭제하려는 데이터가 있는지 먼저 찾고 있다면 삭제합니다. 삭제는 .delete(ojb.id) 로 합니다.

dataTreat.swift에 아래와 같이 작성합니다.

func deleteObjectById(word: String) throws {

    let getObj = Words()
    let delObj = Words()

    var findObj = [String: Any]()
    findObj["word"] = word

    do {
        try getObj.find(findObj)
    } catch {
        throw error
    }

    print("Objects fetched with select: found # \(getObj.results.cursorData.totalRecords)")

    if getObj.results.cursorData.totalRecords > 0 {

        do {
            try delObj.delete(getObj.equipid)
        } catch {
            throw error
        }
        print("Object is deleted. \(getObj.word)")

    } else {
        print("Object is not found.")
    }
}

그리고 main.swift에도 함수를 만들어 줍니다.

func postDelObjByID(request: HTTPRequest, response: HTTPResponse) {

    guard let jsonString = request.postBodyString else {
        response.completed(status: .badRequest)
        return
    }

    do {
        let jsonDic = try jsonString.jsonDecode() as! [String: String]
        let strWord = jsonDic["word"]!

        try deleteObjectById(word: strWord)
        returnJSONMessage(message: "delete success: \(strWord)", response: response)

    } catch {
        returnJSONMessage(message: "Error handling request: \(error)", response: response)
    }
}

그리고 routes에 경로를 추가하고 호출해 봅니다.

routes.add(method: .post, uri: "/findDelete", handler: postDelObjByID)

삭제가 되었습니다.

여기까지 PostgresStORM을 이용한 데이터 처리였습니다.


[참고]: https://github.com/PerfectExamples/PostgreStORM-Demo


Comments