Warm tip: This article is reproduced from stackoverflow.com, please click
sqlite swift

How to create a dictionary from data extracted from a sqlite database

发布于 2020-03-28 23:15:11

I make a call to an API which returns a sqlite file containing a database. Connection is ok and i can read data inside data tables.

Tables from this database are all similar :

TableName = "id": 265946161, json: {key: value, key: value, key: value...}

I want to extract all the tables in a dictionary formated like this :

[String: [Int, JSON]] = [TableName: [id: json]]

This my code for now:

   //Take all the table names
   var tablesName: [String] = []

   var queryStatement: OpaquePointer?
   var testStatement: OpaquePointer?
   let queryStatementString = "SELECT * FROM sqlite_master where type='table';"

   if sqlite3_prepare_v2(db, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {

   if sqlite3_step(queryStatement) == SQLITE_ROW {
       while (sqlite3_step(queryStatement) == SQLITE_ROW) {

         let id = sqlite3_column_int(queryStatement, 0)
         guard let queryResultCol1 = sqlite3_column_text(queryStatement, 1) else {
           print("Query result is nil.")
           return
         }
         let tableName = String(cString: queryResultCol1)
         print("Query Result:")
         print("(tableName)")
         self.tablesName.append(tableName)
       } 
   } else {
       print("\nQuery returned no results.")
   }

   //Test query for one table
   for name in tableNames {
     let queryTest = "SELECT * FROM \(name);"

     if sqlite3_prepare_v2(db, queryTest, -1, &testStatement, nil) == SQLITE_OK {
        while (sqlite3_step(testStatement) == SQLITE_ROW) {
            let id = sqlite3_column_int(testStatement, 0)
            guard let queryResultCol1 = sqlite3_column_text(testStatement, 1) else {
              print("Query result is nil.")
              return
            }
            let json = String(cString: queryResultCol1)
            print("Query Result on \(name):")
            print("\(id) | \(json)")
            //create dictionary or maybe something else???
        }          
      }
   }
} else {
  let errorMessage = String(cString: sqlite3_errmsg(db))
  print("\nQuery is not prepared \(errorMessage)")
}
sqlite3_finalize(queryStatement)
      sqlite3_finalize(testStatement)

I want to use a dictionary to collect data like this : dict[tableName][id][json][key][value] on my vc to avoid making calls to the database every time.

I'm stuck ... if you can help me on this path or maybe on a better approach to achieve this.

Thanks in advance

Questioner
factragnar
Viewed
37
Joakim Danielson 2020-01-31 18:32

Here is one way to do it, create your main dictionary first and then inside the loop create a new dictionary for each table using JSONSerialization to create a dictionary of your json data.

var tableData: [String: [Int: [String: Any]]]

for name in tableNames {
    let queryTest = "SELECT * FROM \(name);"

    if sqlite3_prepare_v2(db, queryTest, -1, &testStatement, nil) == SQLITE_OK {
        while (sqlite3_step(testStatement) == SQLITE_ROW) {
            var dict = [Int: [String: Any]]
            let id = sqlite3_column_int(testStatement, 0)
            guard let queryResultCol1 = sqlite3_column_text(testStatement, 1) else {
                print("Query result is nil.")
                return
            }
            let json = String(cString: queryResultCol1)
            let data = Data(json.utf8)
            do {
                 if let jsonDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                    dict[id] = jsonDict
                 }
             } catch let error as NSError {
                 print(error)            
             }
          }
          tableData[name] = dict
      }
 }

Note that I have not been able to compile or run this so it might contain some issues but the suggested solution should be clear.