tarantool / tarantool/tarantool
Strange behavior of SQL bind variables
@ImeevMA is already working on this.
Since May 25, 2026.
- Dominant language
- Lua
- Stars
- 3.7k
- Forks
- 419
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 88
Description
Reproducer
tarantool> box.execute([[select :a, $1;]], {{[':a'] = 123}})
---
- metadata:
- name: COLUMN_1
type: integer
- name: COLUMN_2
type: boolean
rows:
- [123, 123]
...
tarantool> box.execute([[select $1, :a;]], {{[':a'] = 123}})
---
- metadata:
- name: COLUMN_1
type: boolean
- name: COLUMN_2
type: integer
rows:
- [null, 123]
...
tarantool> box.execute([[select $2, :a;]], {321, {[':a'] = 123}})
---
- metadata:
- name: COLUMN_1
type: integer
- name: COLUMN_2
type: boolean
rows:
- [null, 123]
...
tarantool> box.execute([[select :a, $2;]], {321, {[':a'] = 123}})
---
- metadata:
- name: COLUMN_1
type: integer
- name: COLUMN_2
type: boolean
rows:
- [123, null]
...
tarantool> box.execute([[select :a, $1;]], {321, {[':a'] = 123}})
---
- metadata:
- name: COLUMN_1
type: integer
- name: COLUMN_2
type: boolean
rows:
- [123, 123]
...
tarantool> box.execute([[select $2, $1;]], {321, {['a'] = 123}})
---
- null
- Parameter 'a' was not found in the statement
...
tarantool> box.execute([[select #a, ?, :a;]], {111, {['#a'] = 222}, {[':a'] = 333}})
---
- metadata:
- name: COLUMN_1
type: integer
- name: COLUMN_2
type: boolean
- name: COLUMN_3
type: integer
rows:
- [222, null, 333]
...
We see that positional bindings behave unexpectedly. It is proposed to fix these issues using the following rules:
-
Binding variables must be provided as an array, each element of which is a 'positional' variable, and some of them may be 'named' variables.
-
If a variable is a Lua table with a single field, and the key of this field is a string consisting of '#' or ':' concatenated with the corresponding ID, then this key is the name of the binding variable, and the corresponding value is the value of the binding variable in the case of
namedandpositionalvariables. -
Any variable that does not check condition 2 is not considered a 'named' variable.
-
If '?' is used to get the value of the next positional variable, then the position of the last variable should be used to calculate the position of the next positional variable with
0being used if there were no last variable in the statement.
For example, this
vars = {
{[':asd' = 11}, -- integer, position 1, name ':asd'
{asd = 22}, -- map, position 2, not named
33, -- integer, position 3, not named
{['#qwe'] = '44'}, -- string, position 4, name '#qwe'
{[':asd'] = 5, ['#qwe'] = 5} -- map, position 5, not named
66, -- integer, position 6, not named
}
box.execute([[SELECT :asd, $1, #qwe, ?, ?, $2, ?;]], vars)
should return
{11, 11, '44', {[':asd'] = 5, ['#qwe'] = 5}, 66, {asd = 22}, 33}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.