@@ -3,7 +3,7 @@ use sqlite3_parser::ast::{self, Expr, UnaryOperator};
3
3
4
4
use crate :: {
5
5
function:: { Func , SingleRowFunc } ,
6
- schema:: { Column , Schema , Table } ,
6
+ schema:: { Schema , Table , Type } ,
7
7
select:: { ColumnInfo , Select , SrcTable } ,
8
8
util:: normalize_ident,
9
9
vdbe:: { BranchOffset , Insn , ProgramBuilder } ,
@@ -78,6 +78,7 @@ pub fn build_select<'a>(schema: &Schema, select: &'a ast::Select) -> Result<Sele
78
78
column_info,
79
79
src_tables : joins,
80
80
limit : & select. limit ,
81
+ order_by : & select. order_by ,
81
82
exist_aggregation,
82
83
where_clause,
83
84
loops : Vec :: new ( ) ,
@@ -98,6 +99,7 @@ pub fn build_select<'a>(schema: &Schema, select: &'a ast::Select) -> Result<Sele
98
99
column_info,
99
100
src_tables : Vec :: new ( ) ,
100
101
limit : & select. limit ,
102
+ order_by : & select. order_by ,
101
103
where_clause,
102
104
exist_aggregation,
103
105
loops : Vec :: new ( ) ,
@@ -112,14 +114,15 @@ pub fn translate_expr(
112
114
select : & Select ,
113
115
expr : & ast:: Expr ,
114
116
target_register : usize ,
117
+ cursor_hint : Option < usize > ,
115
118
) -> Result < usize > {
116
119
match expr {
117
120
ast:: Expr :: Between { .. } => todo ! ( ) ,
118
121
ast:: Expr :: Binary ( e1, op, e2) => {
119
122
let e1_reg = program. alloc_register ( ) ;
120
123
let e2_reg = program. alloc_register ( ) ;
121
- let _ = translate_expr ( program, select, e1, e1_reg) ?;
122
- let _ = translate_expr ( program, select, e2, e2_reg) ?;
124
+ let _ = translate_expr ( program, select, e1, e1_reg, cursor_hint ) ?;
125
+ let _ = translate_expr ( program, select, e2, e2_reg, cursor_hint ) ?;
123
126
124
127
match op {
125
128
ast:: Operator :: NotEquals => {
@@ -250,7 +253,13 @@ pub fn translate_expr(
250
253
// whenever a not null check succeeds, we jump to the end of the series
251
254
let label_coalesce_end = program. allocate_label ( ) ;
252
255
for ( index, arg) in args. iter ( ) . enumerate ( ) {
253
- let reg = translate_expr ( program, select, arg, target_register) ?;
256
+ let reg = translate_expr (
257
+ program,
258
+ select,
259
+ arg,
260
+ target_register,
261
+ cursor_hint,
262
+ ) ?;
254
263
if index < args. len ( ) - 1 {
255
264
program. emit_insn_with_label_dependency (
256
265
Insn :: NotNull {
@@ -282,7 +291,7 @@ pub fn translate_expr(
282
291
} ;
283
292
for arg in args {
284
293
let reg = program. alloc_register ( ) ;
285
- let _ = translate_expr ( program, select, & arg, reg) ?;
294
+ let _ = translate_expr ( program, select, & arg, reg, cursor_hint ) ?;
286
295
match arg {
287
296
ast:: Expr :: Literal ( _) => program. mark_last_insn_constant ( ) ,
288
297
_ => { }
@@ -315,7 +324,7 @@ pub fn translate_expr(
315
324
} ;
316
325
317
326
let regs = program. alloc_register ( ) ;
318
- translate_expr ( program, select, & args[ 0 ] , regs) ?;
327
+ translate_expr ( program, select, & args[ 0 ] , regs, cursor_hint ) ?;
319
328
program. emit_insn ( Insn :: Function {
320
329
start_reg : regs,
321
330
dest : target_register,
@@ -356,7 +365,7 @@ pub fn translate_expr(
356
365
357
366
for arg in args. iter ( ) {
358
367
let reg = program. alloc_register ( ) ;
359
- translate_expr ( program, select, arg, reg) ?;
368
+ translate_expr ( program, select, arg, reg, cursor_hint ) ?;
360
369
if let ast:: Expr :: Literal ( _) = arg {
361
370
program. mark_last_insn_constant ( ) ;
362
371
}
@@ -378,8 +387,9 @@ pub fn translate_expr(
378
387
ast:: Expr :: FunctionCallStar { .. } => todo ! ( ) ,
379
388
ast:: Expr :: Id ( ident) => {
380
389
// let (idx, col) = table.unwrap().get_column(&ident.0).unwrap();
381
- let ( idx, col, cursor_id) = resolve_ident_table ( program, & ident. 0 , select) ?;
382
- if col. primary_key {
390
+ let ( idx, col_type, cursor_id, is_primary_key) =
391
+ resolve_ident_table ( program, & ident. 0 , select, cursor_hint) ?;
392
+ if is_primary_key {
383
393
program. emit_insn ( Insn :: RowId {
384
394
cursor_id,
385
395
dest : target_register,
@@ -391,7 +401,7 @@ pub fn translate_expr(
391
401
cursor_id,
392
402
} ) ;
393
403
}
394
- maybe_apply_affinity ( col , target_register, program) ;
404
+ maybe_apply_affinity ( col_type , target_register, program) ;
395
405
Ok ( target_register)
396
406
}
397
407
ast:: Expr :: InList { .. } => todo ! ( ) ,
@@ -439,8 +449,9 @@ pub fn translate_expr(
439
449
ast:: Expr :: NotNull ( _) => todo ! ( ) ,
440
450
ast:: Expr :: Parenthesized ( _) => todo ! ( ) ,
441
451
ast:: Expr :: Qualified ( tbl, ident) => {
442
- let ( idx, col, cursor_id) = resolve_ident_qualified ( program, & tbl. 0 , & ident. 0 , select) ?;
443
- if col. primary_key {
452
+ let ( idx, col_type, cursor_id, is_primary_key) =
453
+ resolve_ident_qualified ( program, & tbl. 0 , & ident. 0 , select, cursor_hint) ?;
454
+ if is_primary_key {
444
455
program. emit_insn ( Insn :: RowId {
445
456
cursor_id,
446
457
dest : target_register,
@@ -452,7 +463,7 @@ pub fn translate_expr(
452
463
cursor_id,
453
464
} ) ;
454
465
}
455
- maybe_apply_affinity ( col , target_register, program) ;
466
+ maybe_apply_affinity ( col_type , target_register, program) ;
456
467
Ok ( target_register)
457
468
}
458
469
ast:: Expr :: Raise ( _, _) => todo ! ( ) ,
@@ -563,7 +574,8 @@ pub fn resolve_ident_qualified<'a>(
563
574
table_name : & String ,
564
575
ident : & String ,
565
576
select : & ' a Select ,
566
- ) -> Result < ( usize , & ' a Column , usize ) > {
577
+ cursor_hint : Option < usize > ,
578
+ ) -> Result < ( usize , Type , usize , bool ) > {
567
579
for join in & select. src_tables {
568
580
match join. table {
569
581
Table :: BTree ( ref table) => {
@@ -579,8 +591,8 @@ pub fn resolve_ident_qualified<'a>(
579
591
. find ( |( _, col) | col. name == * ident) ;
580
592
if res. is_some ( ) {
581
593
let ( idx, col) = res. unwrap ( ) ;
582
- let cursor_id = program. resolve_cursor_id ( & table_identifier) ;
583
- return Ok ( ( idx, col, cursor_id) ) ;
594
+ let cursor_id = program. resolve_cursor_id ( & table_identifier, cursor_hint ) ;
595
+ return Ok ( ( idx, col. ty , cursor_id, col . primary_key ) ) ;
584
596
}
585
597
}
586
598
}
@@ -598,7 +610,8 @@ pub fn resolve_ident_table<'a>(
598
610
program : & ProgramBuilder ,
599
611
ident : & String ,
600
612
select : & ' a Select ,
601
- ) -> Result < ( usize , & ' a Column , usize ) > {
613
+ cursor_hint : Option < usize > ,
614
+ ) -> Result < ( usize , Type , usize , bool ) > {
602
615
let mut found = Vec :: new ( ) ;
603
616
for join in & select. src_tables {
604
617
match join. table {
@@ -611,11 +624,29 @@ pub fn resolve_ident_table<'a>(
611
624
. columns
612
625
. iter ( )
613
626
. enumerate ( )
614
- . find ( |( _, col) | col. name == * ident) ;
627
+ . find ( |( _, col) | col. name == * ident)
628
+ . map ( |( idx, col) | ( idx, col. ty , col. primary_key ) ) ;
629
+ let mut idx;
630
+ let mut col_type;
631
+ let mut is_primary_key;
615
632
if res. is_some ( ) {
616
- let ( idx, col) = res. unwrap ( ) ;
617
- let cursor_id = program. resolve_cursor_id ( & table_identifier) ;
618
- found. push ( ( idx, col, cursor_id) ) ;
633
+ ( idx, col_type, is_primary_key) = res. unwrap ( ) ;
634
+ // overwrite if cursor hint is provided
635
+ if let Some ( cursor_hint) = cursor_hint {
636
+ let cols = & program. cursor_ref [ cursor_hint] . 1 ;
637
+ if let Some ( res) = cols. as_ref ( ) . and_then ( |res| {
638
+ res. columns ( )
639
+ . iter ( )
640
+ . enumerate ( )
641
+ . find ( |x| x. 1 . name == * ident)
642
+ } ) {
643
+ idx = res. 0 ;
644
+ col_type = res. 1 . ty ;
645
+ is_primary_key = res. 1 . primary_key ;
646
+ }
647
+ }
648
+ let cursor_id = program. resolve_cursor_id ( & table_identifier, cursor_hint) ;
649
+ found. push ( ( idx, col_type, cursor_id, is_primary_key) ) ;
619
650
}
620
651
}
621
652
Table :: Pseudo ( _) => todo ! ( ) ,
@@ -631,8 +662,8 @@ pub fn resolve_ident_table<'a>(
631
662
anyhow:: bail!( "Parse error: ambiguous column name {}" , ident. as_str( ) ) ;
632
663
}
633
664
634
- pub fn maybe_apply_affinity ( col : & Column , target_register : usize , program : & mut ProgramBuilder ) {
635
- if col . ty == crate :: schema:: Type :: Real {
665
+ pub fn maybe_apply_affinity ( col_type : Type , target_register : usize , program : & mut ProgramBuilder ) {
666
+ if col_type == crate :: schema:: Type :: Real {
636
667
program. emit_insn ( Insn :: RealAffinity {
637
668
register : target_register,
638
669
} )
0 commit comments