I have an SQLite table that holds a fund name, as a string, a time stamp, as an iso8601 string, and a close, as a double. SQLite appears to call strings text and a double a real. In the function below, I query this table with a select statement to return the last year of data based on the latest date in the table. To get the latest date I have a separate function that finds the latest date, converts if from a string to a date, subtracts 1 year from the date then converts it back to an iso8601 date string. It is this date string that is being passed into the function below as the variable startingDate. The function below works just fine and is relatively fast. What I am trying to determine is there a way to modify the select statement in the function below such that it does everything and I will no longer have to separately calculate the starting date and pass it in?
func QuerySQLiteData(db: OpaquePointer?, fundName: String, startingDate: String) -> [TradingDay] {
var queryResults: [TradingDay] = []
let timeStampFormatter = ISO8601DateFormatter()
let queryTradingDaysStatement = """
Select
FundName,
TimeStamp,
Close
FROM
TradingDays
WHERE
FundName = '\(fundName)'
AND
TimeStamp >= '\(startingDate)'
ORDER By
TimeStamp ASC
;
"""
var queryTradingDaysCPtr: OpaquePointer?
var tradingDay: TradingDay = TradingDay(fundName: "", timeStamp: Date(), close: 0.0)
if sqlite3_prepare_v2(db, queryTradingDaysStatement, -1, &queryTradingDaysCPtr, nil) == SQLITE_OK {
while (sqlite3_step(queryTradingDaysCPtr) == SQLITE_ROW) {
let fundName = sqlite3_column_text(queryTradingDaysCPtr, 0)
let timeStamp = sqlite3_column_text(queryTradingDaysCPtr, 1)
let close = sqlite3_column_double(queryTradingDaysCPtr, 2)
let fundNameAsString = String(cString: fundName!)
let timeStampAsString = String(cString: timeStamp!)
let timeStampAsDate = timeStampFormatter.date(from: timeStampAsString)!
tradingDay.fundName = fundNameAsString
tradingDay.timeStamp = timeStampAsDate
tradingDay.close = close
queryResults.append(tradingDay)
} // end while loop
} else {
let errorMessage = String(cString: sqlite3_errmsg(db))
print("\nQuery is not prepared \(errorMessage)")
}
sqlite3_finalize(queryTradingDaysCPtr)
return queryResults
}
Turns out that SQLite supports a case statement. So I incorporated that and strftime into my query to adjust the date back to Friday if the current date is Saturday '6' or Sunday '0'. Works.
let queryTradingDaysStatement = """
Select
FundName,
TimeStamp,
Close
FROM
TradingDays
WHERE
FundName = '\(fundName)'
AND
CASE strftime('%w')
WHEN '0' then TimeStamp >= date('now', '-2 days', 'start of day', '-\(numYears) year')
WHEN '6' then TimeStamp >= date('now', '-1 days','start of day', '-\(numYears) year')
ELSE TimeStamp >= date('now', 'start of day', '-\(numYears) year')
END
ORDER By
TimeStamp ASC
;
"""