mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-03 08:24:19 +01:00
closes #1467 ## Example: Previously as explained in #1449, our parameter binding wasn't working properly because we would essentially assign the first index of whatever was translated first ```console limbo> create table t (id integer primary key, name text, age integer); limbo> explain select * from t where name = ? and id > ? and age between ? and ?; addr opcode p1 p2 p3 p4 p5 comment ---- ----------------- ---- ---- ---- ------------- -- ------- 0 Init 0 20 0 0 Start at 20 1 OpenRead 0 2 0 0 table=t, root=2 2 Variable 1 4 0 0 r[4]=parameter(1) # always 1 3 IsNull 4 19 0 0 if (r[4]==NULL) goto 19 4 SeekGT 0 19 4 0 key=[4..4] 5 Column 0 1 5 0 r[5]=t.name 6 Variable 2 6 0 0 r[6]=parameter(2) # always 2 7 Ne 5 6 18 0 if r[5]!=r[6] goto 18 8 Variable 3 7 0 0 r[7]=parameter(3) # etc... 9 Column 0 2 8 0 r[8]=t.age 10 Gt 7 8 18 0 if r[7]>r[8] goto 18 11 Column 0 2 9 0 r[9]=t.age 12 Variable 4 10 0 0 r[10]=parameter(4) 13 Gt 9 10 18 0 if r[9]>r[10] goto 18 14 RowId 0 1 0 0 r[1]=t.rowid 15 Column 0 1 2 0 r[2]=t.name 16 Column 0 2 3 0 r[3]=t.age 17 ResultRow 1 3 0 0 output=r[1..3] 18 Next 0 5 0 0 19 Halt 0 0 0 0 20 Transaction 0 0 0 0 write=false 21 Goto 0 1 0 0 ``` ## Solution: `rewrite_expr` currently is used to transform `true|false` to `1|0`, so it has been adapted to transform anonymous `Expr::Variable`s to named variables, inserting the appropriate index of the parameter by passing in a counter. ```rust ast::Expr::Variable(var) => { if var.is_empty() { // rewrite anonymous variables only, ensure that the `param_idx` starts at 1 and // all the expressions are rewritten in the order they come in the statement *expr = ast::Expr::Variable(format!("{}{param_idx}", PARAM_PREFIX)); *param_idx += 1; } Ok(()) } ``` # Corrected output: (notice the seek) ```console limbo> explain select * from t where name = ? and id > ? and age between ? and ?; addr opcode p1 p2 p3 p4 p5 comment ---- ----------------- ---- ---- ---- ------------- -- ------- 0 Init 0 20 0 0 Start at 20 1 OpenRead 0 2 0 0 table=t, root=2 2 Variable 2 4 0 0 r[4]=parameter(2) 3 IsNull 4 19 0 0 if (r[4]==NULL) goto 19 4 SeekGT 0 19 4 0 key=[4..4] 5 Column 0 1 5 0 r[5]=t.name 6 Variable 1 6 0 0 r[6]=parameter(1) 7 Ne 5 6 18 0 if r[5]!=r[6] goto 18 8 Variable 3 7 0 0 r[7]=parameter(3) 9 Column 0 2 8 0 r[8]=t.age 10 Gt 7 8 18 0 if r[7]>r[8] goto 18 11 Column 0 2 9 0 r[9]=t.age 12 Variable 4 10 0 0 r[10]=parameter(4) 13 Gt 9 10 18 0 if r[9]>r[10] goto 18 14 RowId 0 1 0 0 r[1]=t.rowid 15 Column 0 1 2 0 r[2]=t.name 16 Column 0 2 3 0 r[3]=t.age 17 ResultRow 1 3 0 0 output=r[1..3] 18 Next 0 5 0 0 19 Halt 0 0 0 0 20 Transaction 0 0 0 0 write=false 21 Goto 0 1 0 0 ``` ## And a `Delete`: ```console limbo> explain delete from t where name = ? and age > ? and id > ?; addr opcode p1 p2 p3 p4 p5 comment ---- ----------------- ---- ---- ---- ------------- -- ------- 0 Init 0 15 0 0 Start at 15 1 OpenWrite 0 2 0 0 2 Variable 3 1 0 0 r[1]=parameter(3) 3 IsNull 1 14 0 0 if (r[1]==NULL) goto 14 4 SeekGT 0 14 1 0 key=[1..1] 5 Column 0 1 2 0 r[2]=t.name 6 Variable 1 3 0 0 r[3]=parameter(1) 7 Ne 2 3 13 0 if r[2]!=r[3] goto 13 8 Column 0 2 4 0 r[4]=t.age 9 Variable 2 5 0 0 r[5]=parameter(2) 10 Le 4 5 13 0 if r[4]<=r[5] goto 13 11 RowId 0 6 0 0 r[6]=t.rowid 12 Delete 0 0 0 0 13 Next 0 5 0 0 14 Halt 0 0 0 0 15 Transaction 0 1 0 0 write=true 16 Goto 0 1 0 0 ``` Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com> Closes #1475