Skip to content

Commit

Permalink
Fix compile time verification performance regression for sqlite (#1946)
Browse files Browse the repository at this point in the history
* add instruction, register, and cursor state memorization

* fix: fixed formating
  • Loading branch information
liningpan authored Sep 15, 2022
1 parent 280e65f commit 1379eb6
Showing 1 changed file with 69 additions and 6 deletions.
75 changes: 69 additions & 6 deletions sqlx-core/src/sqlite/connection/explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::sqlite::connection::{execute, ConnectionState};
use crate::sqlite::type_info::DataType;
use crate::sqlite::SqliteTypeInfo;
use crate::HashMap;
use std::collections::HashSet;
use std::str::from_utf8;

// affinity
Expand Down Expand Up @@ -121,7 +122,7 @@ const OP_CONCAT: &str = "Concat";
const OP_RESULT_ROW: &str = "ResultRow";
const OP_HALT: &str = "Halt";

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
struct ColumnType {
pub datatype: DataType,
pub nullable: Option<bool>,
Expand All @@ -145,7 +146,7 @@ impl ColumnType {
}
}

#[derive(Debug, Clone, Eq, PartialEq)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
enum RegDataType {
Single(ColumnType),
Record(Vec<ColumnType>),
Expand Down Expand Up @@ -341,6 +342,49 @@ struct QueryState {
pub result: Option<Vec<(Option<SqliteTypeInfo>, Option<bool>)>>,
}

#[derive(Debug, Hash, PartialEq, Eq)]
struct BranchStateHash {
instruction: usize,
registers: Vec<(i64, RegDataType)>,
cursors: Vec<(i64, i64, Option<ColumnType>)>,
}

impl BranchStateHash {
pub fn from_query_state(st: &QueryState) -> Self {
let mut reg = vec![];
for (k, v) in &st.r {
reg.push((*k, v.clone()));
}
reg.sort_by_key(|v| v.0);

let mut cur = vec![];
for (k, v) in &st.p {
match v {
CursorDataType::Normal(hm) => {
for (i, col) in hm {
cur.push((*k, *i, Some(col.clone())));
}
}
CursorDataType::Pseudo(i) => {
cur.push((*k, *i, None));
}
}
}
cur.sort_by(|a, b| {
if a.0 == b.0 {
a.1.cmp(&b.1)
} else {
a.0.cmp(&b.0)
}
});
Self {
instruction: st.program_i,
registers: reg,
cursors: cur,
}
}
}

// Opcode Reference: https://sqlite.org/opcode.html
pub(super) fn explain(
conn: &mut ConnectionState,
Expand All @@ -366,6 +410,8 @@ pub(super) fn explain(
result: None,
}];

let mut visited_branch_state: HashSet<BranchStateHash> = HashSet::new();

let mut result_states = Vec::new();

while let Some(mut state) = states.pop() {
Expand Down Expand Up @@ -407,7 +453,12 @@ pub(super) fn explain(

let mut branch_state = state.clone();
branch_state.program_i = p2 as usize;
states.push(branch_state);

let bs_hash = BranchStateHash::from_query_state(&branch_state);
if !visited_branch_state.contains(&bs_hash) {
visited_branch_state.insert(bs_hash);
states.push(branch_state);
}

state.program_i += 1;
continue;
Expand Down Expand Up @@ -520,15 +571,27 @@ pub(super) fn explain(

let mut branch_state = state.clone();
branch_state.program_i = p1 as usize;
states.push(branch_state);
let bs_hash = BranchStateHash::from_query_state(&branch_state);
if !visited_branch_state.contains(&bs_hash) {
visited_branch_state.insert(bs_hash);
states.push(branch_state);
}

let mut branch_state = state.clone();
branch_state.program_i = p2 as usize;
states.push(branch_state);
let bs_hash = BranchStateHash::from_query_state(&branch_state);
if !visited_branch_state.contains(&bs_hash) {
visited_branch_state.insert(bs_hash);
states.push(branch_state);
}

let mut branch_state = state.clone();
branch_state.program_i = p3 as usize;
states.push(branch_state);
let bs_hash = BranchStateHash::from_query_state(&branch_state);
if !visited_branch_state.contains(&bs_hash) {
visited_branch_state.insert(bs_hash);
states.push(branch_state);
}
}

OP_COLUMN => {
Expand Down

0 comments on commit 1379eb6

Please sign in to comment.