sqlite: sqlite3_column_count всегда возвращает 0

Я использую sqlite в проекте iOS. Однако sqlite3_column_count всегда возвращает 0, хотя я уверен, что запрос возвращает некоторые столбцы (я даже не думаю, что запрос SELECT в SQL возможен с нулевыми столбцами вывода). Странная вещь – это изменение поведения в зависимости от версии библиотеки, с которой я ссылаюсь, и, в частности, какие параметры времени компиляции использовались для этой библиотеки.

Это параметры времени компиляции, используемые для версии библиотеки, которая не работает:

COMPILER=clang-8.0.0 (clang-800.2.34) ENABLE_API_ARMOR ENABLE_FTS3 ENABLE_FTS3_PARENTHESIS ENABLE_JSON1 ENABLE_LOCKING_STYLE=1 ENABLE_RTREE ENABLE_UPDATE_DELETE_LIMIT HAS_CODEC HAVE_ISNAN MAX_MMAP_SIZE=20971520 OMIT_AUTORESET OMIT_BUILTIN_TEST OMIT_LOAD_EXTENSION SYSTEM_MALLOC THREADSAFE=2 

Вот флагов для версии, которая работает:

 COMPILER=clang-8.0.0 SYSTEM_MALLOC THREADSAFE=1 

Что может вызвать такое поведение?

ОБНОВЛЕНИЕ 2016/12/01

Вот проект, который можно использовать для воссоздания проблемы: https://github.com/iannewson/Stackoverflow40895740.git

ViewController.swift содержит этот код:

 Test.doDbStuff() 

Эта функция содержит следующее:

 public static func doDbStuff() { do { var db :OpaquePointer? let dbPath = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) .appendingPathComponent("\(Date.init().timeIntervalSince1970)".replacingOccurrences(of: ".", with: "") + ".db") .path var returnCode :Int32 = sqlite3_open(dbPath, &db) if SQLITE_OK != returnCode { preconditionFailure("Failed to open db") } var stmt :OpaquePointer? returnCode = sqlite3_prepare_v2(db, "CREATE TABLE Things (name TEXT)", -1, &stmt, nil) if SQLITE_OK != returnCode { preconditionFailure("Failed to prepare table creation SQL") } returnCode = sqlite3_step(stmt) if SQLITE_DONE != returnCode { preconditionFailure("Failed to execute tbl creation SQL") } returnCode = sqlite3_prepare_v2(db, "SELECT name FROM sqlite_master WHERE type ='table'", -1, &stmt, nil) if SQLITE_OK != returnCode { preconditionFailure("Failed to prepare count SQL") } returnCode = sqlite3_step(stmt) if SQLITE_ROW != returnCode { preconditionFailure("Failed to execute count SQL") } else { let columnCount = sqlite3_column_count(stmt) print("columnCount: \(columnCount)") let name = String(cString: sqlite3_column_text(stmt, 0)) //print("Num tables: \(count)") print("Table name: \(name)") } } catch let error { preconditionFailure(error.localizedDescription) } } 

Эта функция отлично работает во всех случаях и всегда создает таблицу и извлекает ее имя из sqlite_master без ошибок.

ViewController.swift также содержит этот код:

  Database.instance().executeSql("CREATE TABLE IF NOT EXISTS Things (name TEXT)") Database.instance().printTableNames() Database.instance().withStatementFromSql("SELECT name FROM sqlite_master WHERE type ='table'", callback: {statement in while SQLITE_ROW == sqlite3_step(statement) { print("Column index: \(sqlite3_column_count(statement))") let name = SqlHelper.toString(statement, columnName: "name") print("Table: \(name)") } }) 

Этот код создает таблицу, а затем пытается извлечь ее имя из sqlite_master. Это отлично работает с проектом, настроенным в настоящее время в репо, поэтому для воспроизведения ошибки вам необходимо установить модуль Google Analytics. Вы можете сделать это, раскомментировав pod 'Google/Analytics' в Podfile и выполнив pod install . Теперь, когда вы Test.doDbStuff() запустить этот проект, первый набор кода ( Test.doDbStuff() ) все равно будет работать нормально, но второй набор кода, который использует Database , будет либо ошибкой с EXC_BAD_ACCESS, либо возвратит SQLITE_MISUSE из sqlite3_step .

PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.