mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-08 09:44:21 +01:00
add support for SELECT DISTINCT
This commit is contained in:
@@ -773,6 +773,11 @@ pub fn group_by_emit_row_phase<'a>(
|
||||
labels.label_group_by_end_without_emitting_row,
|
||||
program.offset(),
|
||||
);
|
||||
// SELECT DISTINCT also jumps here if there is a duplicate.
|
||||
if let Distinctness::Distinct { ctx } = &plan.distinctness {
|
||||
let distinct_agg_ctx = ctx.as_ref().expect("distinct context must exist");
|
||||
program.resolve_label(distinct_agg_ctx.label_on_conflict, program.offset());
|
||||
}
|
||||
program.emit_insn(Insn::Return {
|
||||
return_reg: registers.reg_subrtn_acc_output_return_offset,
|
||||
});
|
||||
|
||||
@@ -92,14 +92,20 @@ pub fn init_distinct(program: &mut ProgramBuilder, plan: &mut SelectPlan) {
|
||||
unique: false,
|
||||
has_rowid: false,
|
||||
});
|
||||
let cursor_id = program.alloc_cursor_id(
|
||||
Some(index_name.clone()),
|
||||
CursorType::BTreeIndex(index.clone()),
|
||||
);
|
||||
*ctx = Some(DistinctCtx {
|
||||
cursor_id: program.alloc_cursor_id(
|
||||
Some(index_name.clone()),
|
||||
CursorType::BTreeIndex(index.clone()),
|
||||
),
|
||||
cursor_id,
|
||||
ephemeral_index_name: index_name,
|
||||
label_on_conflict: program.allocate_label(),
|
||||
});
|
||||
|
||||
program.emit_insn(Insn::OpenEphemeral {
|
||||
cursor_id,
|
||||
is_table: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,16 +778,25 @@ fn emit_loop_source<'a>(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
LoopEmitTarget::OrderBySorter => order_by_sorter_insert(
|
||||
program,
|
||||
&t_ctx.resolver,
|
||||
t_ctx
|
||||
.meta_sort
|
||||
.as_ref()
|
||||
.expect("sort metadata must exist for ORDER BY"),
|
||||
&mut t_ctx.result_column_indexes_in_orderby_sorter,
|
||||
plan,
|
||||
),
|
||||
LoopEmitTarget::OrderBySorter => {
|
||||
order_by_sorter_insert(
|
||||
program,
|
||||
&t_ctx.resolver,
|
||||
t_ctx
|
||||
.meta_sort
|
||||
.as_ref()
|
||||
.expect("sort metadata must exist for ORDER BY"),
|
||||
&mut t_ctx.result_column_indexes_in_orderby_sorter,
|
||||
plan,
|
||||
)?;
|
||||
|
||||
if let Distinctness::Distinct { ctx } = &plan.distinctness {
|
||||
let distinct_agg_ctx = ctx.as_ref().expect("distinct context must exist");
|
||||
program.preassign_label_to_next_insn(distinct_agg_ctx.label_on_conflict);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
LoopEmitTarget::AggStep => {
|
||||
let num_aggs = plan.aggregates.len();
|
||||
let start_reg = program.alloc_registers(num_aggs);
|
||||
@@ -871,6 +886,11 @@ fn emit_loop_source<'a>(
|
||||
t_ctx.reg_limit_offset_sum,
|
||||
)?;
|
||||
|
||||
if let Distinctness::Distinct { ctx } = &plan.distinctness {
|
||||
let distinct_agg_ctx = ctx.as_ref().expect("distinct context must exist");
|
||||
program.preassign_label_to_next_insn(distinct_agg_ctx.label_on_conflict);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
util::exprs_are_equivalent,
|
||||
vdbe::{
|
||||
builder::{CursorType, ProgramBuilder},
|
||||
insn::Insn,
|
||||
insn::{IdxInsertFlags, Insn},
|
||||
},
|
||||
Result,
|
||||
};
|
||||
@@ -16,7 +16,7 @@ use crate::{
|
||||
use super::{
|
||||
emitter::{Resolver, TranslateCtx},
|
||||
expr::translate_expr,
|
||||
plan::{ResultSetColumn, SelectPlan, TableReference},
|
||||
plan::{Distinctness, ResultSetColumn, SelectPlan, TableReference},
|
||||
result_row::{emit_offset, emit_result_row_and_limit},
|
||||
};
|
||||
|
||||
@@ -227,6 +227,7 @@ pub fn order_by_sorter_insert(
|
||||
}
|
||||
let mut cur_reg = start_reg + order_by_len;
|
||||
let mut cur_idx_in_orderby_sorter = order_by_len;
|
||||
let mut translated_result_col_count = 0;
|
||||
for (i, rc) in result_columns.iter().enumerate() {
|
||||
if let Some(ref v) = result_columns_to_skip {
|
||||
let found = v.iter().find(|(skipped_idx, _)| *skipped_idx == i);
|
||||
@@ -243,11 +244,38 @@ pub fn order_by_sorter_insert(
|
||||
cur_reg,
|
||||
resolver,
|
||||
)?;
|
||||
translated_result_col_count += 1;
|
||||
res_col_indexes_in_orderby_sorter.insert(i, cur_idx_in_orderby_sorter);
|
||||
cur_idx_in_orderby_sorter += 1;
|
||||
cur_reg += 1;
|
||||
}
|
||||
|
||||
// Handle SELECT DISTINCT deduplication
|
||||
if let Distinctness::Distinct { ctx } = &plan.distinctness {
|
||||
let distinct_agg_ctx = ctx.as_ref().expect("distinct context must exist");
|
||||
let num_regs = order_by_len + translated_result_col_count;
|
||||
program.emit_insn(Insn::Found {
|
||||
cursor_id: distinct_agg_ctx.cursor_id,
|
||||
target_pc: distinct_agg_ctx.label_on_conflict,
|
||||
record_reg: start_reg,
|
||||
num_regs,
|
||||
});
|
||||
let record_reg = program.alloc_register();
|
||||
program.emit_insn(Insn::MakeRecord {
|
||||
start_reg,
|
||||
count: num_regs,
|
||||
dest_reg: record_reg,
|
||||
index_name: Some(distinct_agg_ctx.ephemeral_index_name.to_string()),
|
||||
});
|
||||
program.emit_insn(Insn::IdxInsert {
|
||||
cursor_id: distinct_agg_ctx.cursor_id,
|
||||
record_reg: record_reg,
|
||||
unpacked_start: None,
|
||||
unpacked_count: None,
|
||||
flags: IdxInsertFlags::new(),
|
||||
});
|
||||
}
|
||||
|
||||
let SortMetadata {
|
||||
sort_cursor,
|
||||
reg_sorter_data,
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
use crate::{
|
||||
vdbe::{builder::ProgramBuilder, insn::Insn, BranchOffset},
|
||||
vdbe::{
|
||||
builder::ProgramBuilder,
|
||||
insn::{IdxInsertFlags, Insn},
|
||||
BranchOffset,
|
||||
},
|
||||
Result,
|
||||
};
|
||||
|
||||
use super::{
|
||||
emitter::Resolver,
|
||||
expr::translate_expr,
|
||||
plan::{SelectPlan, SelectQueryType},
|
||||
plan::{Distinctness, SelectPlan, SelectQueryType},
|
||||
};
|
||||
|
||||
/// Emits the bytecode for:
|
||||
@@ -49,6 +53,33 @@ pub fn emit_select_result(
|
||||
resolver,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Handle SELECT DISTINCT deduplication
|
||||
if let Distinctness::Distinct { ctx } = &plan.distinctness {
|
||||
let distinct_agg_ctx = ctx.as_ref().expect("distinct context must exist");
|
||||
let num_regs = plan.result_columns.len();
|
||||
program.emit_insn(Insn::Found {
|
||||
cursor_id: distinct_agg_ctx.cursor_id,
|
||||
target_pc: distinct_agg_ctx.label_on_conflict,
|
||||
record_reg: reg_result_cols_start,
|
||||
num_regs,
|
||||
});
|
||||
let record_reg = program.alloc_register();
|
||||
program.emit_insn(Insn::MakeRecord {
|
||||
start_reg: reg_result_cols_start,
|
||||
count: num_regs,
|
||||
dest_reg: record_reg,
|
||||
index_name: Some(distinct_agg_ctx.ephemeral_index_name.to_string()),
|
||||
});
|
||||
program.emit_insn(Insn::IdxInsert {
|
||||
cursor_id: distinct_agg_ctx.cursor_id,
|
||||
record_reg: record_reg,
|
||||
unpacked_start: None,
|
||||
unpacked_count: None,
|
||||
flags: IdxInsertFlags::new(),
|
||||
});
|
||||
}
|
||||
|
||||
emit_result_row_and_limit(
|
||||
program,
|
||||
plan,
|
||||
|
||||
Reference in New Issue
Block a user