When using dynamic select with both IN operator and other conditions (e.g., age >= ?), the ORM generates a SQL query that causes a "column index out of range" error.
// vtest retry: 3
import db.sqlite
@[table: 'dynamic_members']
struct DynamicMember {
mut:
id int @[primary; sql: serial]
name string
email string
age int
status string
}
fn dynamic_select_with_in_operator() ! {
mut db := sqlite.connect(':memory:')!
defer {
db.close() or { panic(err) }
}
sql db {
create table DynamicMember
}!
members := [
DynamicMember{ name: 'Alice', email: 'alice@example.com', age: 31, status: 'active' },
DynamicMember{ name: 'Bob', email: 'bob@example.com', age: 24, status: 'pending' },
DynamicMember{ name: 'Charlie', email: 'charlie@example.com', age: 29, status: 'active' },
DynamicMember{ name: 'Diana', email: 'diana@example.com', age: 35, status: 'inactive' },
DynamicMember{ name: 'Eve', email: 'eve@example.com', age: 22, status: 'pending' },
]
for member in members {
sql db {
insert member into DynamicMember
}!
}
// 1: IN
status_list := ['active', 'pending']
rows1 := sql db {
dynamic select from DynamicMember where {
if status_list.len > 0 {
status in status_list
}
} order by id
}!
println('IN test (status in [active, pending]): ${rows1.len} rows')
assert rows1.len == 4 // Alice(active), Bob(pending), Charlie(active), Eve(pending)
for row in rows1 {
println(' - ${row.name}: ${row.status}')
assert row.status in status_list
}
// 2: !IN
exclude_status := ['inactive']
rows2 := sql db {
dynamic select from DynamicMember where {
if exclude_status.len > 0 {
status !in exclude_status
}
} order by id
}!
println('!IN test (status not in [inactive]): ${rows2.len} rows')
assert rows2.len == 4 // 排除 Diana(inactive)
for row in rows2 {
println(' - ${row.name}: ${row.status}')
assert row.status !in exclude_status
}
// 3: name IN + status
valid_names := ['Alice', 'Charlie', 'Eve']
min_age := 25
rows3 := sql db {
dynamic select from DynamicMember where {
if valid_names.len > 0 {
name in valid_names
},
if min_age > 0 {
age >= min_age
}
} order by id
}!
println('Combined test (name in [Alice,Charlie,Eve] AND age >= 25): ${rows3.len} rows')
assert rows3.len == 2 // Alice(31), Charlie(29)
for row in rows3 {
println(' - ${row.name}: age ${row.age}')
assert row.name in valid_names
assert row.age >= min_age
}
println('All IN/!IN tests passed!')
}
fn dynamic_update_with_in_condition() ! {
mut db := sqlite.connect(':memory:')!
defer {
db.close() or { panic(err) }
}
sql db {
create table DynamicMember
}!
initial_members := [
DynamicMember{ name: 'Alice', email: 'alice@example.com', age: 31, status: 'pending' },
DynamicMember{ name: 'Bob', email: 'bob@example.com', age: 24, status: 'pending' },
DynamicMember{ name: 'Charlie', email: 'charlie@example.com', age: 29, status: 'active' },
]
for member in initial_members {
sql db {
insert member into DynamicMember
}!
}
// status IN [pending]
pending_statuses := ['pending']
new_status := 'approved'
before_rows := sql db {
select from DynamicMember where status in pending_statuses
}!
println('Before update: ${before_rows.len} pending records')
update_expr := {
status == new_status
}
sql db {
dynamic update DynamicMember set update_expr where {
if pending_statuses.len > 0 {
status in pending_statuses
}
}
}!
after_rows := sql db {
select from DynamicMember where status == new_status
}!
println('After update: ${after_rows.len} records updated to ${new_status}')
assert after_rows.len == before_rows.len
for row in after_rows {
println(' - ${row.name}: ${row.status}')
assert row.status == new_status
}
active_rows := sql db {
select from DynamicMember where name == 'Charlie'
}!
assert active_rows[0].status == 'active'
println('Charlie remains ${active_rows[0].status} (correct)')
println('Dynamic update with IN condition test passed!')
}
fn main() {
println('=== Testing IN and !IN operators ===')
println('')
dynamic_select_with_in_operator() or {
println('Error in select tests: ${err}')
return
}
println('')
dynamic_update_with_in_condition() or {
println('Error in update test: ${err}')
return
}
println('')
println('✅ All IN/!IN tests passed successfully!')
}
The query should execute successfully, returning records that match both conditions (name IN (...) AND age >= ...).
Describe the bug
When using dynamic select with both IN operator and other conditions (e.g., age >= ?), the ORM generates a SQL query that causes a "column index out of range" error.
Reproduction Steps
Expected Behavior
The query should execute successfully, returning records that match both conditions (name IN (...) AND age >= ...).
Current Behavior
column index out of range (25) (SELECT
id,name,email,age,statusFROMdynamic_membersWHEREnameIN (?1, ?2, ?3) ANDage>= ?4 ORDER BYidASC;); code: 25Possible Solution
No response
Additional Information/Context
No response
V version
V 0.5.1 1b3385c
Environment details (OS name and version, etc.)
Note
You can use the 👍 reaction to increase the issue's priority for developers.
Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.