I had this code working at one time but all of a sudden, it's not working anymore.
I'm creating a table with the following:
// Create Stock Table
func createStockTable() {
let createTableString = """
CREATE TABLE IF NOT EXISTS Stocks (
id INTEGER PRIMARY KEY,
stockName STRING,
status INT,
imgName STRING,
prevClose DOUBLE,
curPrice DOUBLE,
yield DOUBLE,
noShares INT,
capitalization DOUBLE,
lastUpdated String
);
"""
var createTableStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK {
if sqlite3_step(createTableStatement) == SQLITE_DONE {
print("Stock table is created successfully")
} else {
print("Stock table creation failed.")
}
sqlite3_finalize(createTableStatement)
}
}
This is working just fine.
I have the following insert function to insert the rows:
// add entries to Stock table
func insertStocks(id: Int, stockName: String, status: Int, imgName: String, prevClose: Double, curPrice: Double, yield: Double, noShares: Int, capitalization: Double, lastUpdated: String) -> Bool {
let stocks = getAllStocks()
for stock in stocks {
if stock.id == id {
return false
}
}
let insertStatementString = "INSERT INTO Stocks (id, stockName, status, imgName, prevClose, curPrice, yield, noShares, capitalization, lastUpdated) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
var insertStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
sqlite3_bind_int(insertStatement,1,Int32(id))
sqlite3_bind_text(insertStatement, 2, (stockName as NSString).utf8String, -1, nil)
sqlite3_bind_int(insertStatement, 3, Int32(status))
sqlite3_bind_text(insertStatement, 4, (imgName as NSString).utf8String, -1, nil)
sqlite3_bind_double(insertStatement, 5, Double(prevClose))
sqlite3_bind_double(insertStatement, 6, Double(curPrice))
sqlite3_bind_double(insertStatement, 7, Double(yield))
sqlite3_bind_int64(insertStatement,8, Int64(noShares))
sqlite3_bind_double(insertStatement, 9, Double(capitalization))
sqlite3_bind_text(insertStatement, 10, (lastUpdated as NSString).utf8String, -1, nil)
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Stock Entry was created successfully")
sqlite3_finalize(insertStatement)
return true
} else {
print("Stock Entry Insert failed")
return false
}
} else {
print("INSERT Statement has failed")
return false
}
}
When I run the following, it gives me an error that the stock entry insert failed. I cannot seem to determine why.
func addStocks() {
db.insertStocks(id: 1, stockName: "Tulsa Motors", status: 1, imgName: "Tulsa_logo", prevClose: 125.18, curPrice: 125.18, yield: 0.025, noShares: 14357698, capitalization: myFunc.calcMarketCap(curPrice: 128.18, noShares: 14357698), lastUpdated: "2025-05-01 17:00:00")
}
[edit] Tim has raised the question on the creation of the db object, so I'm posting that code as well:
let dataPath: String = "MyDB"
let functions = Functions()
var db: OpaquePointer?
// Create DB
func openDatabase()->OpaquePointer?{
let filePath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent(dataPath)
var db: OpaquePointer? = nil
if sqlite3_open(filePath.path, &db) != SQLITE_OK{
debugPrint("Cannot open DB.")
return nil
}
else{
print("DB successfully created.")
return db
}
}
The only issue I can possibly see is the INT32
and INT64
but those worked before so I'm not sure why that would no longer be working.
Suggestions?
The problem is with the primary key, when you include a column with the type INTEGER PRIMARY KEY
this automatically becomes an alias for a built in type called ROWID
.
This type has an auto increment functionality built in and will generate a new unique id (primary key) every time you do an insert. So the problem here is that you should not include the id
property and a value for it in your insert code since SQLite will handle it for you.
So change the insert statement to
let insertStatementString = "INSERT INTO Stocks (stockName, status, imgName, prevClose, curPrice, yield, noShares, capitalization, lastUpdated) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);"
and remove the line
sqlite3_bind_int(insertStatement,1,Int32(id))
in your insertStocks
method and then update the index column values for the following rows.