2016-08-13 3 views
3

Я пытаюсь запросить таблицу FTS с помощью SQLite.swift. Previously I have done it in Android. Суть того, что я пытаюсь сделать, это this:Как получить доступ к таблице FTS в SQLite.swift с использованием условия IN

SELECT * 
FROM t2 
WHERE id IN (SELECT docid 
      FROM fts_table 
      WHERE col_text MATCH 'something') 

Из SQLite.swift documentation я вижу IN condition можно записать как this:

users.filter([1, 2, 3, 4, 5].contains(id)) 
// SELECT * FROM "users" WHERE ("id" IN (1, 2, 3, 4, 5)) 

и виртуальные столы могут быть запрошены как this:

let wonderfulEmails = emails.match("wonder*") 
// SELECT * FROM "emails" WHERE "emails" MATCH 'wonder*' 

let replies = emails.filter(subject.match("Re:*")) 
// SELECT * FROM "emails" WHERE "subject" MATCH 'Re:*' 

Однако я не могу понять, как их объединить. Я действительно не хочу иметь execute arbitrary SQL (хотя теперь это работает благодаря помощи от this answer).

Update

Вот мой последний попробовать, что не работает:

let tableText = Table("t2") 
let id = Expression<Int64>("id") 
let someColumn = Expression<String>("someColumn") 

let tableFts = VirtualTable("fts_table") 
let columnDocId = Expression<Int64>("docId") 


let ftsQuery = tableFts 
    .select(columnDocId) 
    .filter(tableFts.match("something")) 
let tableQuery = tableText 
    .filter((try db.prepare(ftsQuery)) 
     .contains(id))      // <-- error 

for row in try db.prepare(tableQuery) { 
    print(row[someColumn]) 
} 

, где линия с contains(id) бросает ошибку:

Cannot convert value of type 'Expression' to expected argument type '@noescape (Row) throws -> Bool'

+0

У вас есть пример фрагмента кода и сбой? Что вы пытаетесь сделать, это не работает? – stephencelis

+0

@stephencelis, я добавил обновление. В этой последней попытке я попытался разбить ее на два запроса, так как я не знаю, как это сделать в одном запросе. – Suragch

+0

Я не верю, что вы сможете использовать выражения в запросе таблиц FTS. Если вы посмотрите на схему db таблицы fts, вы заметите, что столбец типа пуст, а не показывает ожидаемые типы (как указано в обычной таблице). Невзирая на то, почему sqlite работает так, но единственное, что мне удалось получить, - это цикл через возвращаемые строки операторов. Хотелось бы узнать, смогли ли вы продвинуться дальше. –

ответ

1

Я в конечном итоге просто работает необработанная команда SQL. Это точно не отвечает на то, что я задавал в вопросе (поскольку он не использует чистый API SQLite.swift), но для тех, кому просто нужно что-то работать, ... он работает.

Вот приведенный пример, который я извлек из некоторого исходного кода.

static func findLinesContaining(_ searchTerms: String, forSearchScope scope: SearchScope) throws -> [TextLines] { 

    guard let db = SQLiteDataStore.sharedInstance.TextDB else { 
     throw DataAccessError.datastore_Connection_Error 
    } 

    // TODO: convert to SQLite.swift syntax rather than using a SQL string 
    var statement: Statement? = nil 
    switch scope { 
    case .wholeCollection: 
     statement = try db.run("SELECT bookId, chapterId, lineId, lineText" + 
      " FROM lines" + 
      " WHERE rowid IN (SELECT docid FROM fts_table" + 
      " WHERE fts_table MATCH ?);", searchTerms) 

    case .singleBook(let chosenBookId): 
     statement = try db.run("SELECT bookId, chapterId, lineId, lineText" + 
      " FROM lines" + 
      " WHERE rowid IN (SELECT docid FROM fts_table" + 
      " WHERE fts_table MATCH ?) AND bookId = ?;", [searchTerms, chosenBookId]) 
    } 


    var returnList: [TextLine] = [] 
    for row in statement! { 

     let line = TextLine() 
     if let bookId = row[0] as? Int64, 
      let chapterId = row[1] as? Int64, 
      let lineId = row[2] as? Int64, 
      let text = row[3] as? String { 

      line.bookId = Int(bookId) 
      line.chapterId = Int(chapterId) 
      line.lineId = Int(lineId) 
      line.lineText = text 
     } 

     returnList.append(line) 
    } 

    return returnList 
} 

Приведенный выше код не проверен после переименования переменных и классов для использования на SO. У вас есть разрешение на редактирование кода, если вы обнаружили ошибку.

+0

Спасибо! Я попробовал что-то подобное, но не использовал параметр placeholders (?); который я буду продвигаться вперед. +1 за полезную акцию. –