I have an sqlite3 table, every time I run my code, it adds multiple entries. How can I change this query to add only one entry?
CREATE TABLE "GroupTable" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"memberId" TEXT NOT NULL,
"adminId" TEXT NOT NULL,
"name" TEXT NOT NULL
);
The method below shows how I am adding data:
func addDatatoList(info: ListModel ) -> Bool
{
sharedInstance.database!.open()
let isInserted = sharedInstance.database!.executeUpdate("INSERT or REPLACE INTO GroupTable(adminId, memberId, name) VALUES (?,?,?)", withArgumentsIn: [ info.adminId,info. memberId,info.name])
sharedInstance.database!.close()
return isInserted
}
You’re not supplying an id value, so INSERT OR REPLACE will never replace. You theoretically could add id parameter, passing NSNull() if the id value is NULL
func addDatatoList(info: ListModel) -> Bool {
guard let db = sharedInstance.database else { return false }
db.open()
defer { db.close() }
let sql = "INSERT or REPLACE INTO GroupTable(id, adminId, memberId, name) VALUES (?, ?, ?, ?)"
let values: [Any] = [info.id ?? NSNull(), info.adminId, info.memberId, info.name]
let isInserted = sharedInstance.database!.executeUpdate(sql, withArgumentsIn: values)
return isInserted
}
That having been said, if you did INSERT, you probably want to retrieve the row’s auto increment id value:
func addDatatoList(info: ListModel) -> Bool {
guard let db = sharedInstance.database else { return false }
db.open()
defer { db.close() }
let sql = "INSERT or REPLACE INTO GroupTable(id, adminId, memberId, name) VALUES (?, ?, ?, ?)"
let values: [Any] = [info.id ?? NSNull(), info.adminId, info.memberId, info.name]
let isInserted = sharedInstance.database!.executeUpdate(sql, withArgumentsIn: values)
if isInserted, info.id == nil {
let id = db.lastInsertRowId
// e.g., if `ListModel` is a reference type and `id` is mutable,
// you might update the value, e.g.
info.id = Int(id)
}
return isInserted
}
But, then again, if you're now programmatically determining whether you inserted or updated, you might as well have two SQL statements, one for INSERT and one for UPDATE.
Related
I have this RTDB I am trying to search my users in, from a path called users -> UID -> and then the user key/values. One of them being "username". I want to append these to an array to return in my table view but no matter what I do, I keep getting back nothing.
var userRef = Database.database().reference(withPath: "users")
func queryText(_ text: String, inField child: String) {
print(text)
userRef.queryOrdered(byChild: child)
.queryStarting(atValue: text)
.queryEnding(atValue: text+"\u{f8ff}")
.observeSingleEvent(of: .value) { [weak self] (snapshot) in
for case let item as DataSnapshot in snapshot.children {
//Don't show the current user in search results
if self?.currentUser?.uid == item.key {
continue
}
if var itemData = item.value as? [String:String] {
itemData["uid"] = item.key
self?.resultsArray.append(itemData)
print(self?.resultsArray)
}
}
self?.tableView.reloadData()
}
}
Edit: I have verified I am able to print out the snapshot, I am just not getting the usernames added to my resultsArray. Anyone have a clue why?
bio = " dfdf";
displayname = chattest4;
email = "test#test.com";
"first_name" = chattest4;
followers = 0;
following = 0;
"join_date" = "June 28, 2021";
languages = English;
"last_name" = test;
location = "United States";
profileImageURL = "hidjkfsf";
username = chattest4;
So I found out the issue. Some of the values in my database were not strings, but I had coded it to only look for Strings. Username was stored after these non-string values, so it never reached it. I just changed the array to [String:Any] and then it worked!
if var itemData = item.value as? [String:Any]
When updating FirebaseStorage, I make processing to change only by change.
Instead of sending the value of textField as it is, we create an optional variable called newOO separately, so that the value entered in newOO is changed, and nil is entered if it is not.
Here is the process of adding to the dictionary when there is a change in that variable (if it is not nil) and not adding it to the dictionary if there is no change (nil).
var newName: String? = "name"
var newAge: Int? = 20
var newID: String? = "123456789"
var dict = [String: Any]()
if let newName = newName {
dict["newName"] = newName
}
if let newAge = newAge {
dict["newAge"] = newAge
}
if let newID = newID {
dict["newID"] = newID
}
However, the more items there are, the more descriptions there are.
Is there a way to write this process more concisely?
private var contactsWithSections = [[WPH]]()
WPH have following properties:
class WPH: NSObject {
var fName: String? = nil
var lName: String? = nil
var number: String? = nil
var email: String? = nil
}
I want to search based on fName i.e. in array have fname = alex, fname = alena, fname = flora
let searchStr = "al"
Then result should return objects for alex and alena
Found the more relevant solution that is a perfect match for my problem
let filtered = MasterList!.filter { (data) -> Bool in
return data.fName?.range(of: Key, options: String.CompareOptions.caseInsensitive) != nil || data.lName?.range(of: Key, options: String.CompareOptions.caseInsensitive) != nil
}
You can just use flat map then Filter
FlatMap will join all section filter will filter it with your key
let results = contactsWithSections.flatMap {$0}.filter { (obj) -> Bool in
guard let keyValue = obj.fName else {return false}
return keyValue == searchStr
}
I am using RealmSwift. What is the best / canonical way to generate ids for objects?
Here is what I came up with:
class MyObject: Object {
dynamic var id = ""
dynamic var createdAt = NSDate()
override class func primaryKey() -> String {
return "id"
}
func save() {
let realm = try! Realm()
if(self.id == "") {
while(true) {
let newId = NSUUID().UUIDString
let saying = realm.objectForPrimaryKey(MyObject.self, key: newId)
if(saying == nil) {
self.id = newId
break
}
}
}
try! realm.write {
realm.add(self)
}
}
}
I wanted a function that persists the object to Realm and either overwrites or creates a new one based on the id. This seems to work ok, but I wasn't sure if there was something built into realm to do this. Or is there a better way?
Thanks.
I know this is a few months old, but this is how I implement auto incrementing Primary Keys.
This code is untested, but you'll get the general idea
class MyObject: Object {
/**
Primary Key
Since you can't change the primary key after the object is saved,
we'll use 0 to signify an unsaved object. When we set the primary key,
we'll never use 0.
*/
dynamic var id: Int = 0
/**
Some persisted value
*/
dynamic var someString: String?
var nextID: Int {
do {
let realm = try Realm()
/// I would use .max() but Realm only supports String and signed Int for primary keys
/// so using overflow protection, the `next` primary key would be Int.min if the
/// current value is Int.max
var id = realm.objects(MyObject.self).sorted("id", ascending: true).last?.id ?? 0
/// add 1 to id until we find one that's not in use... skip 0
repeat {
id = Int.addWithOverflow(id, 1).0 /// Add with overflow in case we hit Int.max
} while id == 0 || realm.objectForPrimaryKey(MyObject.self, key: id) != nil
return id
} catch let error as NSError {
/// Oops
fatal(error: error.localizedDescription)
}
}
convenience init(someString: String?) {
self.init()
id = nextID
self.someString = someString
save()
}
override class func primaryKey() -> String? {
return "id"
}
func save() {
/// Gotta check this in case the object was created without using the convenience init
if id == 0 { id = nextID }
do {
let realm = try Realm()
try realm.write {
/// Add... or update if already exists
realm.add(self, update: true)
}
} catch let error as NSError {
fatalError(error.localizedDescription)
}
}
}
The process for creating a unique string ID (IE: a UUID) is very similar:
class MyObject: Object {
/**
Primary Key
*/
dynamic var id: String = ""
/**
Some persisted value
*/
dynamic var someString: String?
var nextID: String {
do {
let realm = try Realm()
var id: String = NSUUID().UUIDString
/// NSUUID().UUIDString almost always makes a unique ID on the first try
/// but we'll check after we generate the first one just to be sure
while realm.objectForPrimaryKey(MyObject.self, key: id) != nil {
id = NSUUID().UUIDString
}
return id
} catch let error as NSError {
/// Oops
fatal(error: error.localizedDescription)
}
}
convenience init(someString: String?) {
self.init()
id = nextID
self.someString = someString
save()
}
override class func primaryKey() -> String? {
return "id"
}
func save() {
/// Gotta check this in case the object was created without using the convenience init
if id == "" { id = nextID }
do {
let realm = try Realm()
try realm.write {
/// Add... or update if already exists
realm.add(self, update: true)
}
} catch let error as NSError {
fatalError(error.localizedDescription)
}
}
}
Realm(Swift) does not currently support auto-incrementing primary keys. You can set a primary like you are above, but for auto-incrementing and unique keys, there are a couple routes that you can go:
UUID (like you have above)
Query the max "id" (primary key) of your object and set the object to be inserted as id + 1. Something like...
let id = realm.objects(MyObject).max("id") + 1
Create your own hash signature (one potential example: SHA256(epoch timestamp + SHA256(object.values))
im using parse in my project, put i faceing issue
here is my code :
func getIdByItemName (name:String) -> String
{
let Query = PFQuery(className: "Class")
.whereKey("name", equalTo: name)
var QueryObject = Query.findObjects()
var findId:String = "????"
for quer in QueryObject!
{
findId = String(quer.objectId)
}
print("The object id id : \(findId)")
return findId
}
my issue is the returned values will be like this :
Optional("l7wpt4slip")
my question is how can i remove optional and keep only object id as String like this ?? :
l7wpt4slip
Here is the safe way to unwrap an optional values:
for quer in QueryObject!
{
//unwrap it with if let.
if let temp = String?(quer.objectId){
findId = temp
}
}