Skip to content

Commit fed33b9

Browse files
authored
avoids multiple runs on where clause, now it is MlogN instead of M*N (#156)
1 parent 5cff949 commit fed33b9

File tree

1 file changed

+94
-63
lines changed

1 file changed

+94
-63
lines changed

woori-db/src/controllers/clauses.rs

Lines changed: 94 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::collections::{BTreeMap, HashMap};
22

3-
use futures::{future, stream, StreamExt};
43
use rayon::prelude::*;
54
use uuid::Uuid;
65
use wql::{Algebra, Clause, ToSelect, Types, Value};
@@ -68,73 +67,105 @@ async fn filter_where_clauses(
6867
clauses: &[Clause],
6968
) -> BTreeMap<Uuid, HashMap<String, Types>> {
7069
let default = String::new();
71-
stream::iter(states)
72-
.filter(|(_, state)| {
73-
future::ready(
74-
clauses
75-
.par_iter()
76-
.map(|clause| match clause {
77-
Clause::ValueAttribution(_, _, _) => true,
78-
Clause::Or(_, inner_clauses) => {
79-
or_clauses(state, &args_to_key, inner_clauses)
70+
let mut states = states.clone();
71+
for clause in clauses {
72+
match clause {
73+
Clause::ValueAttribution(_, _, _) => {}
74+
Clause::Or(_, inner_clauses) => {
75+
for (id, state) in states.clone() {
76+
if !or_clauses(&state, &args_to_key, &inner_clauses) {
77+
states.remove(&id);
78+
}
79+
}
80+
}
81+
Clause::ContainsKeyValue(_, key, value) => {
82+
for (id, state) in states.clone() {
83+
if !state.get(key).map_or(false, |v| value == v) {
84+
states.remove(&id);
85+
}
86+
}
87+
}
88+
Clause::SimpleComparisonFunction(f, key, value) => {
89+
let key = args_to_key.get(key).unwrap_or(&default);
90+
for (id, state) in states.clone() {
91+
state.get(key).map(|v| match f {
92+
wql::Function::Eq => {
93+
if !(v == value) {
94+
states.remove(&id);
95+
}
8096
}
81-
Clause::ContainsKeyValue(_, key, value) => {
82-
state.get(key).map_or(false, |v| value == v)
97+
wql::Function::NotEq => {
98+
if !(v != value) {
99+
states.remove(&id);
100+
}
83101
}
84-
Clause::SimpleComparisonFunction(f, key, value) => {
85-
let key = args_to_key.get(key).unwrap_or(&default);
86-
state.get(key).map_or(false, |v| match f {
87-
wql::Function::Eq => v == value,
88-
wql::Function::NotEq => v != value,
89-
wql::Function::GEq => v >= value,
90-
wql::Function::G => v > value,
91-
wql::Function::LEq => v <= value,
92-
wql::Function::L => {
93-
println!("{:?} < {:?} = {}", v, value, v < value);
94-
v < value
95-
}
96-
wql::Function::Like => {
97-
if let (Types::String(content), Types::String(regex)) =
98-
(v, value)
99-
{
100-
let pattern = regex.replace("%", "");
101-
if regex.starts_with('%') && regex.ends_with('%') {
102-
content.contains(&pattern)
103-
} else if regex.starts_with('%') {
104-
content.ends_with(&pattern)
105-
} else if regex.ends_with('%') {
106-
content.starts_with(&pattern)
107-
} else {
108-
content.contains(&pattern)
109-
}
110-
} else {
111-
false
112-
}
113-
}
114-
_ => false,
115-
})
102+
wql::Function::GEq => {
103+
if !(v >= &value) {
104+
states.remove(&id);
105+
}
116106
}
117-
Clause::ComplexComparisonFunctions(wql::Function::In, key, set) => {
118-
let key = args_to_key.get(key).unwrap_or(&default);
119-
state.get(key).map_or(false, |v| set.contains(v))
107+
wql::Function::G => {
108+
if !(v > &value) {
109+
states.remove(&id);
110+
}
120111
}
121-
Clause::ComplexComparisonFunctions(
122-
wql::Function::Between,
123-
key,
124-
start_end,
125-
) => {
126-
let key = args_to_key.get(key).unwrap_or(&default);
127-
state
128-
.get(key)
129-
.map_or(false, |v| v >= &start_end[0] && v <= &start_end[1])
112+
wql::Function::LEq => {
113+
if !(v <= &value) {
114+
states.remove(&id);
115+
}
130116
}
131-
_ => false,
132-
})
133-
.all(|f| f),
134-
)
135-
})
136-
.collect::<BTreeMap<Uuid, HashMap<String, Types>>>()
137-
.await
117+
wql::Function::L => {
118+
if !(v < &value) {
119+
states.remove(&id);
120+
}
121+
}
122+
wql::Function::Like => {
123+
if let (Types::String(content), Types::String(regex)) = (v, value) {
124+
let pattern = regex.replace("%", "");
125+
126+
if (regex.starts_with('%')
127+
&& regex.ends_with('%')
128+
&& content.contains(&pattern))
129+
|| (regex.starts_with('%') && content.ends_with(&pattern))
130+
|| (regex.ends_with('%') && content.starts_with(&pattern))
131+
|| content.contains(&pattern)
132+
{
133+
()
134+
} else {
135+
states.remove(&id);
136+
}
137+
} else {
138+
states.remove(&id);
139+
}
140+
}
141+
_ => {}
142+
});
143+
}
144+
}
145+
Clause::ComplexComparisonFunctions(wql::Function::In, key, set) => {
146+
let key = args_to_key.get(key).unwrap_or(&default);
147+
for (id, state) in states.clone() {
148+
if !state.get(key).map_or(false, |v| set.contains(v)) {
149+
states.remove(&id);
150+
}
151+
}
152+
}
153+
Clause::ComplexComparisonFunctions(wql::Function::Between, key, start_end) => {
154+
let key = args_to_key.get(key).unwrap_or(&default);
155+
for (id, state) in states.clone() {
156+
if !state
157+
.get(key)
158+
.map_or(false, |v| v >= &start_end[0] && v <= &start_end[1])
159+
{
160+
states.remove(&id);
161+
}
162+
}
163+
}
164+
_ => (),
165+
}
166+
}
167+
168+
states
138169
}
139170

140171
fn or_clauses(

0 commit comments

Comments
 (0)