FMDB update version number doesn't work - ios

I know how to use FMDB for the basic functions like create database table etc.
When i want to update my table like add a new column i need to update the user version number.
FMDB has a userVersion property should be sqlite's user_version. I used below code:
if let db = DBManager.shared.database, db.userVersion == 0, db.open() {
addColumnsToSomeTable()
db.userVersion = 1
}
But run the project, the userVersion still 0. It should be 1 and this if block shouldn't be entered in.
Why the userVersion can't be upgraded?
I also tried:
let string = "PRAGMA user_version = 1"
do {
try db.executeUpdate(string, values: nil)
} catch {
}
Still the same problem.
I searched some tutorials, most of them has the fileExists check like below:
if !FileManager.default.fileExists(atPath: dbPath) {
database = FMDatabase(path: dbPath)
}
What's the sense here? If file exist what's the correct way to get it?
Not the same as : database = FMDatabase(path: dbPath) ?

I opened the sqlite software DB Browser for SQLite at the same time. Close it, then works fine.

Related

Filtering Realm object returns nil when there is a 100% value

I am stucked in situation when I am trying to .filter Realm objects with predicate and it returns nil, but I do the same query in Realm studio and it DOES work there.
I can return idFolder, but can't query the object using it
folders = realm.objects(Folder.self)
currentFolder = String(describing: folders?.first?.idFolder)
My code of querying:
if let idFolder = currentFolder {
let folderName = folders?.filter("idFolder = '\(String(describing: idFolder))'").first?.name
let name = callAlert(title: "Add new well for folder \(String(describing: folderName))")
}
The problem is that folderName = nil
I double checked the value of currentFolder and it is equal to what I have in my Realm database. Here is a screenshot:
Realm database
Does anybody know what I am doing wrong?
I also tried to use new querying instead of chaining request, didn't work.
the problem is on the query
"idFolder = '\(String(describing: idFolder))'"
the correct one should be like that
update
"idFolder == \(idFolder)"

FMDB - How can I assign query result to variable?

I'm using FMDB module to work with SQLite in my swift project.
Now I can add new records to database. But also I want to show some query results in textField or even in label.
Here's my part of code that I'm trying to use. But it doesn't works.
Please help me
DataBaseModel.swift:
func getElectr100() -> String {
sharedInstance.database?.open()
let tarElectr100:FMResultSet! = sharedInstance.database!.executeQuery("SELECT tarif_value FROM tarifs WHERE tarif_name = ?", withArgumentsIn: ["electr100"])
sharedInstance.database!.close()
let resultItem = String(describing: tarElectr100)
print(resultItem)
return resultItem
}
ViewController.swift:
resultLabel.text = databaseModel.getElectr100(????)
What should I write in ViewController.swift to get the value? How to do it correctly?

Restrict duplicate entries while inserting in core data using magical records

I saw some post related to this topic but nothing comes handy for me in this case. I am using Magical Records for storing data. Data is saving fine for the first time as I map it after coming from server.
class func fnsConversationmapper(conversationJson: [JSON]) -> [Conversation] {
var conversationArray = [Conversation]()
for conversationDict in conversationJson {
print(conversationDict)
// let check = Conversation.mr_find(byAttribute: "id", withValue: conversationDict["id"].stringValue)
let check = Conversation.mr_findFirst(byAttribute: "id", withValue: conversationDict["id"].stringValue)
let conversationObj = Conversation.mr_createEntity()
conversationObj?.name = conversationDict["name"].stringValue
conversationObj?.id = conversationDict["id"].stringValue
conversationObj?.image = conversationDict["avatar"].stringValue
conversationObj?.type = conversationDict["type"].stringValue
conversationObj?.role = conversationDict["postedBy"]["role"]["name"].stringValue
conversationObj?.postedOn = (conversationDict["postedOn"].stringValue).dateFromString() as NSDate?
conversationArray.append(conversationObj!)
if check == nil {
NSManagedObjectContext.mr_default().mr_saveToPersistentStoreAndWait()
}
print("Saved data", Conversation.mr_findAll()!)
}
return conversationArray
}
I also have a check to see if the record is already present in db, but somehow when I again run the app from certain scenario (coming back and forth from some screens), entries get doubled in db. I am not understanding how this is happening. Any Help will be appreciated.
Thanks.

How to get a list of column names with Sqlite.swift?

For debugging purposes I am trying to get a simple list of the column names in my SQLite table. I am using the SQLite.swift framework.
My question is more specific than How to get a list of column names on sqlite3 / iPhone? so I am creating a new question.
Using
try db.execute("PRAGMA table_info(table_name);")
by applying this answer to the documentation didn't work for me (nothing happened).
Assuming you already have a database connection called db set up, to get a list of the column names, you can use the following code:
do {
let tableInfo = Array(try db.prepare("PRAGMA table_info(table_name)"))
for line in tableInfo {
print(line[1]!, terminator: " ")
}
print()
} catch _ { }
where table_name is replaced with the literal string of your table's name.
You can also add
print(tableInfo)
to see more pragma info about your table.
Credits
Thanks to this answer for clues of how to do this.
Example Function
Tested routine from Joe Blow to save a little typing:
func findColumns(_ tableName:String) {
var asAnArray:[String] = []
do {
let s = try db!.prepare("PRAGMA table_info(" + tableName + ")" )
for row in s { asAnArray.append(row[1]! as! String) }
}
catch { print("some woe in findColumns for \(tableName) \(error)") }
let asAString = asAnArray.joined(separator: ",")
print(asAnArray)
print(asAString)
}

Firebase overwrite existing record

With the following code that is used to create a new user into Firebase BaaS, but when it is launched it overwrite the existing user.
let test = Firebase(url: "https://dr-freud.firebaseio.com/users")
ref.createUser(email.text, password: password.text,
withValueCompletionBlock: { error, result in
if error != nil {
print(error)
} else {
let uid = result["uid"] as? String
let nome = self.nome.text!
let cognome = self.cognome.text!
let utente = ["Nome": nome, "Cognome": cognome]
let users = ["\(self.nome.text!)": utente]
test.setValue(users)
}
})
You're calling setValue() on the same location, so you'll indeed overwrite the existing data at that location.
To prevent this, you'll need to call setValue() on a user-specific location:
let currentUser = test.childByAppendingPath(uid)
currentUser.setValue(users)
By calling childByAppendingPath() we end up with a reference to a database location that is specific to this user.
This and much more is covered in Firebase's programming guide for iOS. I highly recommend that you spend some time in that guide. A few hours there will save you many problems and questions down the line.
It's overwriting due to this line
test.setValue(users)
You need to create a separate child for each user that you write to the users node.
Since this is the users node, you should use the uid that the createUser provides. Frank's answer is correct so the below is more of a general case answer.
If it was some other node where you are not provided a natural key, using autoId will help you do this; here's an example.
let pizzaRef = ref.childByAppendingPath("pizzas")
let thisPizzaRef = pizzaRef.childByAutoId()
let pizzaData = ["crustType": "Thick"]
thisPizzaRef.setValue(pizzaData)
this will create a new node within the users node each time it's called
pizzas
-J1092uf8n0293i
crustType: "Thick"
-J989jijsoissds
crustType: "Thick"

Resources