Code Monkey home page Code Monkey logo

Comments (8)

Tybion avatar Tybion commented on June 2, 2024 1

Thanks, I will look into that.

from grdb.swift.

Tybion avatar Tybion commented on June 2, 2024

Sample code

The trails.sqlite file is unencrypted, so SQLCipher is not used.

import Foundation
import GRDB
import MapKit
import CSV
 :  :
    // Table = 'trail'
    struct Trail: Codable, FetchableRecord, PersistableRecord {
        var id: Int
        var title: String
        var descr: String
        var colour: String
    }

    // Table = 'coord'
    struct Coord: Codable, FetchableRecord, PersistableRecord {
        //var seqno: Int - auto-incremented primary key
        var trailid: Int
        var latitude: Double
        var longitude: Double
        var speed: Double
    }
    
    // Table = 'location'
    struct Location: Codable, FetchableRecord, PersistableRecord {
        var id: Int
        var title: String
        var descr: String
        var colour: String
        var longitude: Double
        var latitude: Double
    }
    
    // If these 4 values are the same in 2 trails or 2 locations, then assume they are duplicates
    // Although, theoretically the 2 trails could be different, it is exteremely unlikely
    struct UniqFeature {
        var title : String
        var descr : String
        var longitude : Double  // first longitude in a trail
        var latitude : Double   // first latitude in a trail
    }

    // ***************************
    init() throws {

        let folder = MyUtils.getAppFolder("trails")
        let filemgr = FileManager.default
        var isDir = ObjCBool(true)
        
        let exists = filemgr.fileExists(atPath: folder, isDirectory: &isDir)
        if !exists {
            // create folder and SQLite file
            do {
                try filemgr.createDirectory(atPath: folder, withIntermediateDirectories: true, attributes: nil)
            } catch let error as NSError {
                let str = "Unable to create trails directory: \(error.debugDescription)"
                throw myError(str)
            }
        }
        
        // Create SQLite file if it doesn't exist, else just connect ..
        do {
            let path = folder + "trails.sqlite"
            //trailsDB = try Connection(folder + "trails.sqlite")
            dbQueue = try DatabaseQueue(path: path)
            MyUtils.Log(TAG, "Opened trails.sqlite (un-encrypted)")
            
        } catch let error as NSError {
            let str = "Unable to create trails SQLite file: \(error.debugDescription)"
            throw myError(str)
        }

        // Create 'location' table if it doesn't exist
        /*
        let location = Table("location")
        let id = Expression<Int>("id")
        let title = Expression<String>("title")
        let descr = Expression<String>("descr")
        let colour = Expression<String>("colour")
        let longitude = Expression<Double>("longitude")
        let latitude = Expression<Double>("latitude")
        */

        do {
            try dbQueue!.write { db in
                try db.create(table: "location", ifNotExists: true) { t in
                    t.column("id", .integer)
                    t.column("title", .text)
                    t.column("descr", .text)
                    t.column("longitude", .double)
                    t.column("latitude", .double)
                    t.primaryKey(["id"])
                }
                try db.execute(sql: "CREATE INDEX IF NOT EXISTS index_location_on_longitude_latitude ON location(longitude, latitude)")
            }
          
        } catch let error as NSError {
            let str = "Unable to create 'location' table: \(error.debugDescription)"
            throw myError(str)
        }

        // Add 'colour' table to hold RGB value
        // Been tested on iPhone 7 - colour(TEXT) field is created.
        do {
            try dbQueue!.write { db in
                try db.execute(sql: "ALTER TABLE location ADD COLUMN colour text")
            }
        } catch let error as NSError {
            let str = "Unable to add 'colour' column to 'location' table: \(error.debugDescription)"
            MyUtils.Log(TAG, str)
        }

        // Create 'trail' and 'coord' tables if they don't exist
        /*
        let trail = Table("trail")
        let id = Expression<Int>("id")
        let title = Expression<String>("title")
        let descr = Expression<String>("descr")
        */
 
        do {
            try dbQueue!.write { db in
                try db.create(table: "trail", ifNotExists: true) { t in
                    t.column("id", .integer)
                    t.column("title", .text)
                    t.column("descr", .text)
                    t.primaryKey(["id"])
                }
            }
            /*
            try trailsDB.run(trail.create(ifNotExists: true) { t in
                t.column(id, primaryKey: true)        // "id" INTEGER PRIMARY KEY NOT NULL,
                t.column(title)
                t.column(descr)
            }) */
        } catch let error as NSError {
            let str = "Unable to create 'trail' table: \(error.debugDescription)"
            throw myError(str)
            //return
        }
        
        // Add 'colour' to trail
        do {
            try dbQueue!.write { db in
                try db.execute(sql: "ALTER TABLE trail ADD COLUMN colour text")
            }
        } catch let error as NSError {
            let str = "Unable to add 'colour' column to 'trail' table: \(error.debugDescription)"
            MyUtils.Log(TAG, str)
        }

        /*
        let coord = Table("coord")
        let seqno = Expression<Int>("seqno")
        let trailid = Expression<Int>("trailid")
        let speed = Expression<Double>("speed")
        */

        do {
            try dbQueue!.write { db in
                try db.create(table: "coord", ifNotExists: true) { t in
                    t.autoIncrementedPrimaryKey("seqno")
                    t.column("trailid", .integer)
                    t.column("latitude", .double)
                    t.column("longitude", .double)
                    t.column("speed", .double)
                }
                try db.execute(sql: "CREATE INDEX IF NOT EXISTS index_coord_on_trailid  ON coord(trailid)")
            }
            /*
            try trailsDB.run(coord.create(ifNotExists: true) { t in
                t.column(seqno, primaryKey: .autoincrement) // "seqno" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
                t.column(trailid)
                t.column(latitude)
                t.column(longitude)
                t.column(speed)
            })
            try trailsDB.run(coord.createIndex(trailid, ifNotExists: true))
            */
        } catch let error as NSError {
            let str = "Unable to create 'coord' table: \(error.debugDescription)"
            throw myError(str)
        }
    }
    // ***************************
    // ***************************
    func readTrails(trails: inout [trailGPS], idStart: Int, idFinish: Int) throws -> Int {
        
        // Read IDs between idStart and idFinish inclusive
        
        if (dbQueue == nil) {return -1}
            
        /*
        let trail = Table("trail")
        let id = Expression<Int>("id")
        let coord = Table("coord")
        let trailid = Expression<Int>("trailid")
        let seqno = Expression<Int>("seqno")
        let title = Expression<String>("title")
        let descr = Expression<String>("descr")
        let speed = Expression<Double>("speed")
        let latitude = Expression<Double>("latitude")
        let longitude = Expression<Double>("longitude")
        */
        
        // Read data - one SELECT statement
        var oldid: Int = 0
        var coords: Int = 0
        var trailGps: trailGPS!
        do {
            try dbQueue!.read { db in
                // Fetch database rows - always build SQL in DB Browser for Sqlite
                let rows = try Row.fetchCursor(db, sql: """
                    SELECT * FROM trail
                    INNER JOIN coord on trail.id = coord.trailid
                    WHERE id>=? AND id<=?
                    ORDER BY id, seqno
                """, arguments: [idStart, idFinish])
                
                while let row = try rows.next() {
                    
                    // If CSV has 'colour' column, then get colour as TrailColour
                    var color = TrailColour.MAGENTA
                    if let colr = row["colour"] {
                        color = TrailColour(rawValue: colr as! String) ?? .MAGENTA
                    }
                    
                    //print("id: \(user[id]), email: \(user[email]), name: \(user[name])")
                    if oldid == 0 || oldid != row["id"] {
                        if oldid != 0 {
                            // append complete trail to array
                            trails.append(trailGps)
                        }
                        // next trail ..
                        trailGps = trailGPS(trailid: row["id"])
                        trailGps.title = row["title"]
                        trailGps.descr = row["descr"]
                        trailGps.colour = color
                    }
                    
                    coords += 1
                    trailGps.add(coord: CLLocationCoordinate2D(
                        latitude: row["latitude"], longitude: row["longitude"]),
                        speed: row["speed"])
                    oldid = row["id"]
                }
            }
            
            // LAST trail read (unless database is empty) ..
            if oldid != 0 {trails.append(trailGps)}
            
        } catch let error as NSError {
            let str = "Unable to read trails from SQLite: \(error.debugDescription)"
            throw myError(str)
            //return
        }

        MyUtils.getSQLiteTableCount(dbQueue: dbQueue!, tablename: "trail")
        MyUtils.getSQLiteTableCount(dbQueue: dbQueue!, tablename: "coord")

        return coords
    }
    
    // ***************************

   

from grdb.swift.

KimGiay avatar KimGiay commented on June 2, 2024

I'm facing the same problem.
My app crashes when I try to write data into db.

3e4f225f39679739ce76

from grdb.swift.

groue avatar groue commented on June 2, 2024

Hello @Tybion,

I'm sorry for those crashes.

There's insufficient information in your report:

  • The crashlytics report looks mutilated. If there is a crash, there must be some error code or message visible somewhere. It is your task to read the crash report and its context and share the information that is relevant to the issue. Pasting without reading is not enough.
  • The pasted code in unrelated to the crashlytics excerpt. Again, it is your task to provide information that is relevant to the issue.
  • You did not provide the results of your own inquiry.

from grdb.swift.

Tybion avatar Tybion commented on June 2, 2024

Thanks, Gwendal.

Sorry, yes, I accidentally pasted the wrong crashlytics report. I have attached this one for the readTrails() crash - this is the function where I have pasted the code above.

I picked this because 13 users at this stage have experienced this, so is quite representative. Crashlytics says 92% of these are running iOS 17.4.1. (5% 17.2.1, 2% 17.3.0)

Line 576 is ..

try dbQueue!.read { db in

.. so the that is not very useful - just means somewhere in the closure.

ios17_4_1crash.txt

I am really under pressure at the moment and have to travel over the next 24 hours, which is really bad timing. Sorry, I do not have huge skills in this low level stuff, and I am in a team of one. When I created this ticket, I thought maybe I had done something dumb that you could point out, but sounds more serious than that.

from grdb.swift.

Tybion avatar Tybion commented on June 2, 2024

By the way, for a TestFlight app, I have upgraded to GRDB 6.24.1, but am still waiting for Apple to approve the build.

from grdb.swift.

groue avatar groue commented on June 2, 2024

Something is strange in the stack trace:

Crashed: GRDB.DatabaseQueue
0  libsqlite3.dylib                  0x9a10c sqlite3_sourceid + 36940
1  libsqlite3.dylib                  0x52a7c sqlite3_column_type + 104

sqlite3_column_type does not call sqlite3_sourceid. And sqlite3_sourceid returns a static C string: it can't crash. Either Crashlytics symbolication is wrong, either we're witnessing a big linker mess.

Could it be that your application is linked against two different and competing SQLite libraries? For example, did you introduce a new framework in your app? The problem would not be with GRDB, but with the way Xcode deals with the interaction of GRDB with this framework. I unfortunately don't have a straight answer to this kind of linker problem.

from grdb.swift.

groue avatar groue commented on June 2, 2024

@Tybion please reopen if anything new happens.

from grdb.swift.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.