mattn/go-sqlite3

Queries with '%w' don't take arguments

ADimeo opened this issue · 2 comments

I'm trying to write queries which return elements based on the weekday of a timestamp, and I'm seeing unexpected results in queries that contain %w. Specifically:
db.Query("SELECT time from reports where '3' = strftime('%w', reports.time, 'unixepoch'") returns items, whereas
db.Query("SELECT time from reports where '?' = strftime('%w', reports.time, 'unixepoch'", 3)doesn't.

I have run a similar test for queries with strftime('%s', 'now'), and I couldn't reproduce the issue (e.g. a query like "SELECT time from reports where strftime('%s','now') - strftime ('%s',time, 'unixepoch', '? days') < 0 works as expected if you pass in an argument.

Additional notes:
Version: v1.14.12
The relevant bit of sqlite documentation is here

Repoduction code:

func ReproductionCode() {
	// Prep DB + Data
	dbPath := "./reproduction_db.db"
	db, _ := sql.Open("sqlite3", dbPath)
	db.Exec("CREATE TABLE IF NOT EXISTS reports (time DATETIME NOT NULL);")
	db.Exec("INSERT INTO reports VALUES (1652262289);")

	a := "SELECT time from reports where '3' = strftime('%w', reports.time, 'unixepoch')"
	b := "SELECT time from reports where '?' = strftime('%w', reports.time, 'unixepoch')"

	var resultA string
	var resultB string

	rowsA, _ := db.Query(a)
	rowsA.Next()
	rowsA.Scan(&resultA)
	fmt.Println("WITHOUT ? RESULT IS " + resultA) // WITHOUT ? RESULT IS 2022-05-11T09:44:49Z

	rowsB, _ := db.Query(b, 3)
	rowsB.Next()
	rowsB.Scan(&resultB)
	fmt.Println("WITH ? RESULT IS " + resultB) // WITH ? RESULT IS
}

'?' literally means the string "?". (In standard SQL, strings are enclosed in single quotes.) You are trying to binding the string "3" as a parameter, so you have to do this:

b := "SELECT time from reports where ? = strftime('%w', reports.time, 'unixepoch')"
...
rowsB, err := db.Query(b, "3")
...

Alternatively, you may perform an explicit cast like so:

b := "SELECT time from reports where CAST(? AS TEXT) = strftime('%w', reports.time, 'unixepoch')"
...
rowsB, err := db.Query(b, 3)
...

Thanks a lot, I probably should have checked something like that first