Greetings from the frigid midwest USA!
The SQLite documentation at
https://www.sqlite.org/tclsqlite.html says that [db eval] does variable substitution "in any position where it is legal to put a string or number literal". I'm learning that that means, for example, that column names aren't substituted. But I've got a case that clearly meets the "number literal" criterion, yet the substitution either doesn't occur, or occurs incorrectly! I'm using SQLite 3.13.0.
For this illustration I'm using a table called "plan" which has columns called "row" and "size"; they are explicit INTEGER columns, and "row" is not the PRIMARY KEY column. For what it's worth, I've tried this with and without an INDEX on "row", and also using another column "a".
A query with a hard-coded 5 gives the correct expected result:
() 4 % db eval {select row from plan where 5 between row+1 and row+size}
4 3 1
Replacing the 5 with a variable DOESN'T WORK!:
() 5 % set x 5
5
() 6 % db eval {select row from plan where :x between row+1 and row+size}
But it you do a no-op modification of the variable, it does work:
() 7 % db eval {select row from plan where :x+0 between row+1 and row+size}
4 3 1
() 8 % db eval {select row from plan where abs(:x) between row+1 and row+size}
4 3 1
I thought maybe it was a peculiarity of BETWEEN, so I expanded it:
() 47 % db eval {select row from plan where 5 >= row+1 and 5 <= row+size}
4 3 1
Replacing the first 5 with a variable gives the WRONG RESULT!:
() 48 % db eval {select row from plan where :x >= row+1 and 5 <= row+size}
5 6 7 8 9 10 11 12 13 4 14 3 15 1
But doing a no-op on it makes it work correctly:
() 49 % db eval {select row from plan where :x+0 >= row+1 and 5 <= row+size}
4 3 1
Replacing the second 5 doesn't work, but a no-op mod does:
() 54 % db eval {select row from plan where :x+0 >= row+1 and :x <= row+size}
() 55 % db eval {select row from plan where :x+0 >= row+1 and :x+0 <= row+size}
4 3 1
Understanding when variable substitution is or isn't done is one thing, but command 48 seems plain wrong. Is it a bug? Is there a more detailed discussion of the nuances of variable substitution somewhere? Google searches only turned up cases, like substituting table or column names, where you need to do the substitution in Tcl before passing it to [db eval]. Is this such a case?