Swift 4 + SQLite при вставке - PullRequest
       3

Swift 4 + SQLite при вставке

0 голосов
/ 27 сентября 2018

Я использую «сырые» функции C для доступа к моей базе данных SQLite и получаю 2 проблемы с полями даты и текста, мой код, учитывая, что все уже работает:

let queryString = "INSERT INTO LOG (field1, field2, field3, field4) VALUES (?, ?, ?, ?);" 
if sqlitePrepare(database: &db, query: queryString, statement: &insertStatement) == SQLITE_OK {
    sqlite3_bind_int(insertStatement, 1, intVar)
    sqlite3_bind_double(insertStatement, 2, Date().timeIntervalSinceReferenceDate)
    sqlite3_bind_text(insertStatement, 3, strVar1, -1, nil)
    sqlite3_bind_text(insertStatement, 4, strVar2, -1, nil)
    if sqlite3_step(insertStatement) != SQLITE_DONE {
          let errmsg = String(cString: sqlite3_errmsg(db)!)
         print("failure insert: \(errmsg)")
     }
    sqlite3_finalize(insertStatement)
}

Проблема № 1Как заполнить поле Дата в качестве действительной отметки времени SQLite?Проблема №2 и, что более важно, значения, которые обновляются в таблице со строковыми полями (field3 / field4), неверны.Только последнее значение используется для заполнения обоих (strVar1 / strVar2), поэтому, если strVar1 = "A" и strVar2 = "B", и field3, и field4 сохраняются как "B", значение strVar2.Это очень странно, потому что все примеры, которые я нашел, не имеют здесь никакой разницы.

1 Ответ

0 голосов
/ 27 сентября 2018

# 1 - как заполнить поле Date как допустимую временную метку SQLite?

SQLite3 не имеет ни типа DATETIME, ни типа TIMESTAMP.Таким образом, вам нужно сохранить временную метку в виде ТЕКСТА или ЧИСЛА.

Когда вы выбираете ЧИСЛО, вам лучше использовать время эпохи UNIX.

sqlite3_bind_double(insertStatement, 2, Date().timeIntervalSince1970)

# 2

Swift выделяет временную область для хранения представления UTF-8 при передаче String параметру типа UnsafePointer<Int8>.И регион освобождается сразу после вызова функции и может быть использован повторно.

Попробуйте это:

sqlite3_bind_text(insertStatement, 3, strdup(strVar1), -1, free)
sqlite3_bind_text(insertStatement, 4, strdup(strVar2), -1, free)

strdup выделяет стабильный регион, который доступен до freed.

Или (благодаря rmaddy и Martin R "SQLITE_TRANSIENT не определен в Swift" ) вы можете использовать SQLITE_TRANSIENT.

Определить где-нибудь в вашем коде:

let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)

и используйте его:

sqlite3_bind_text(insertStatement, 3, strVar1, -1, SQLITE_TRANSIENT)
sqlite3_bind_text(insertStatement, 4, strVar2, -1, SQLITE_TRANSIENT)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...