【问题标题】:How to chain conditions in with SQLite.swift type safe API?如何使用 SQLite.swift 类型安全 API 链接条件?
【发布时间】:2020-10-05 06:03:31
【问题描述】:

我正在使用SQLite.swift,我想在类型安全的 API 中表示具有多个动态过滤条件的 SQL 语句。我发现了类似的问题,但没有一个提供任何关于如何实现这一点的见解。

到目前为止,我基本上会像这样构建我的查询(请注意,我的部分或全部 TextFields 可能是空的):

var filters: [String] = ["id != 0"]
if nameFilterTextField.text?.count ?? 0 > 0 {
  filters.append("(firstName LIKE '\(nameFilterTextField.text ?? "")' OR lastName LIKE '\(nameFilterTextField.text ?? ""))'")
}
if(dateFromTextField.text?.count ?? 0 > 0 && dateToTextField.text?.count ?? 0 > 0){
  let startdate = germanDateFormatter.date(from: dateFromTextField.text ?? "")!
  let enddate = germanDateFormatter.date(from: dateToTextField.text ?? "")!

  filters.append("savedAt BETWEEN datetime('\(sqlDateFormatter.string(from: startdate))') AND datetime('\(sqlDateFormatter.string(from: enddate))')")
}
if companyFilterTextField.text?.count ?? 0 > 0 {
  filters.append("fromCompany LIKE '\(companyFilterTextField.text ?? "")'")
}
if contactPersonFilterTextField.text?.count ?? 0 > 0 {
  filters.append("contactPoint LIKE '\(contactPersonFilterTextField.text ?? "")'")
}
if visitedFilterSegmentedControl.selectedSegmentIndex == 1 {
  filters.append("visitedCompany = 'company1'")
}
else if visitedFilterSegmentedControl.selectedSegmentIndex == 2{
  filters.append("visitedCompany = 'company2'")
}
let filterString = filters.joined(separator: " AND ")

然后我会以某种方式将该字符串附加到我的 SQL 语句中:

public func getData(limit: Int) -> [Visitor]{
    var visitors = [Visitor]()
    do{
        for row in try db.prepare("SELECT * FROM visitors WHERE \(filterString) LIMIT \(limit) ORDER BY id DESC") {
            let visitor: Visitor = Visitor(
               id: row[id],
               firstName: row[firstName],
               lastName: row[lastName],
               visitedCompany: row[visitedCompany],
               savedAt: row[date],
               fromCompany: row[fromCompany],
               contactPoint: row[contactPoint])

            visitors.append(visitor)
        }
    }
    catch {
        print("Could not get row: \(error)")
    }
    return visitors
}

但是上面的例子不起作用(我认为编译器无法键入检查该语句?/ Xcode 冻结...)。

但我仍然想要使用原始 SQL 方法,而是希望使用 SQLite.swift 提供的类型安全 API,这样我的(不完整的)示例基本上看起来更像这个:

public func getData(limit: Int) -> [Visitor]{
    var visitors = [Visitor]()
    do{
        for row in try db.prepare(visitorsTable.filter(/*what in here?*/).limit(limit, offset: 0).order(id.desc)) {
            let visitor: Visitor = Visitor(
               id: row[id],
               firstName: row[firstName],
               lastName: row[lastName],
               visitedCompany: row[visitedCompany],
               savedAt: row[date],
               fromCompany: row[fromCompany],
               contactPoint: row[contactPoint])

            visitors.append(visitor)
        }
    }
    catch {
        print("Could not get row: \(error)")
    }
    return visitors
}

显然,我之前已经为我的示例定义了所有需要的变量...

【问题讨论】:

    标签: ios swift sqlite sqlite.swift


    【解决方案1】:

    我只想分享我的解决方案,这显然没有回答问题,因为我无法使用类型安全的 API。 我改为执行原始 SQL 查询,然后将所有列转换为相应的数据类型:

    public func getDataNew(limit: Int, offset: Int, filter: String) -> [Visitor]{
        var visitors = [Visitor]()
        do{
            let statement: Statement = try db.run("SELECT * FROM visitors WHERE \(filter) ORDER BY id DESC LIMIT \(limit) OFFSET \(offset)")
            for row in statement {
                print(row[0] as! Int64)
                let visitor: Visitor = Visitor(id: Int(row[0] as! Int64),
                                               firstName: row[1] as! String,
                                               lastName: row[2] as! String,
                                               profileImage: Data.fromDatatypeValue(row[3] as! Blob),
                                               visitedCompany: row[4] as! String,
                                               savedAt: Date.fromDatatypeValue(row[5] as! String),
                                               fromCompany: row[6] as! String,
                                               contactPoint: row[9] as! String)
                visitors.append(visitor)
            }
        }
        catch {
            print("Could not get row: \(error)")
        }
        return visitors
    }
    

    我希望这对尝试从数据库中检索 BLOB 或 DATETIME 对象的人有所帮助。

    【讨论】:

      猜你喜欢
      • 2016-01-04
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      • 2021-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多