mirror of
https://github.com/fluencelabs/llamadb
synced 2025-05-16 17:21:21 +00:00
parent
c7baa0b0f7
commit
0c02fcd5b3
@ -102,6 +102,39 @@ where <Storage::Info as DatabaseInfo>::Table: 'a
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|
&SExpression::LeftJoin { source_id, ref yield_in_fn, ref predicate, ref yield_out_fn, ref right_rows_if_none } => {
|
||||||
|
let mut one_or_more_rows = false;
|
||||||
|
|
||||||
|
try!(self.execute(yield_in_fn, &mut |row| {
|
||||||
|
let new_source = Source {
|
||||||
|
parent: source,
|
||||||
|
source_id: source_id,
|
||||||
|
source_type: SourceType::Row(row)
|
||||||
|
};
|
||||||
|
|
||||||
|
let pred_result = try!(self.resolve_value(predicate, Some(&new_source)));
|
||||||
|
|
||||||
|
if pred_result.tests_true() {
|
||||||
|
one_or_more_rows = true;
|
||||||
|
self.execute(yield_out_fn, result_cb, Some(&new_source))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}, source));
|
||||||
|
|
||||||
|
if !one_or_more_rows {
|
||||||
|
// no rows were matched
|
||||||
|
let new_source = Source {
|
||||||
|
parent: source,
|
||||||
|
source_id: source_id,
|
||||||
|
source_type: SourceType::Row(right_rows_if_none)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.execute(yield_out_fn, result_cb, Some(&new_source))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
},
|
||||||
&SExpression::Map { source_id, ref yield_in_fn, ref yield_out_fn } => {
|
&SExpression::Map { source_id, ref yield_in_fn, ref yield_out_fn } => {
|
||||||
self.execute(yield_in_fn, &mut |row| {
|
self.execute(yield_in_fn, &mut |row| {
|
||||||
let new_source = Source {
|
let new_source = Source {
|
||||||
@ -303,6 +336,7 @@ where <Storage::Info as DatabaseInfo>::Table: 'a
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
&SExpression::Scan { .. } |
|
&SExpression::Scan { .. } |
|
||||||
|
&SExpression::LeftJoin { .. } |
|
||||||
&SExpression::TempGroupBy { .. } |
|
&SExpression::TempGroupBy { .. } |
|
||||||
&SExpression::Yield { .. } |
|
&SExpression::Yield { .. } |
|
||||||
&SExpression::If { .. } => {
|
&SExpression::If { .. } => {
|
||||||
|
@ -193,6 +193,12 @@ where <DB as DatabaseInfo>::Table: 'a
|
|||||||
table: FromWhereTableOrSubquery<'a, DB>,
|
table: FromWhereTableOrSubquery<'a, DB>,
|
||||||
on: SExpression<'a, DB>
|
on: SExpression<'a, DB>
|
||||||
},
|
},
|
||||||
|
Left {
|
||||||
|
source_id: u32,
|
||||||
|
table: SExpression<'a, DB>,
|
||||||
|
on: SExpression<'a, DB>,
|
||||||
|
right_rows_if_none: Vec<<DB as DatabaseInfo>::ColumnValue>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FromWhereTableOrSubquery<'a, DB: DatabaseInfo>
|
enum FromWhereTableOrSubquery<'a, DB: DatabaseInfo>
|
||||||
@ -243,6 +249,15 @@ where <DB as DatabaseInfo>::Table: 'a
|
|||||||
}],
|
}],
|
||||||
else_: None
|
else_: None
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
FromWhereJoin::Left { source_id, table, on, right_rows_if_none } => {
|
||||||
|
SExpression::LeftJoin {
|
||||||
|
source_id: source_id,
|
||||||
|
yield_in_fn: Box::new(table),
|
||||||
|
predicate: Box::new(on),
|
||||||
|
yield_out_fn: Box::new(nested_expr),
|
||||||
|
right_rows_if_none: right_rows_if_none
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -274,6 +289,27 @@ where <DB as DatabaseInfo>::Table: 'a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn source_id(&self) -> u32 {
|
||||||
|
match self {
|
||||||
|
&FromWhereTableOrSubquery::Table { source_id, .. } => source_id,
|
||||||
|
&FromWhereTableOrSubquery::Subquery { source_id, .. } => source_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn yield_all_columns(self, column_count: u32) -> SExpression<'a, DB> {
|
||||||
|
// TODO: remove column_count parameter, put that information in the type
|
||||||
|
let source_id = self.source_id();
|
||||||
|
|
||||||
|
self.into_sexpr(SExpression::Yield {
|
||||||
|
fields: (0..column_count).map(|column_offset| {
|
||||||
|
SExpression::ColumnField {
|
||||||
|
source_id: source_id,
|
||||||
|
column_offset: column_offset
|
||||||
|
}
|
||||||
|
}).collect()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'z, DB: DatabaseInfo> QueryCompiler<'a, 'z, DB>
|
impl<'a, 'z, DB: DatabaseInfo> QueryCompiler<'a, 'z, DB>
|
||||||
@ -523,19 +559,38 @@ where DB: 'a, <DB as DatabaseInfo>::Table: 'a
|
|||||||
let j = try!(joins.into_iter().map(|join| {
|
let j = try!(joins.into_iter().map(|join| {
|
||||||
let ((source_table, fromwhere_table), alias) = try!(self.ast_table_or_subquery_to(join.table, scope, groups_info));
|
let ((source_table, fromwhere_table), alias) = try!(self.ast_table_or_subquery_to(join.table, scope, groups_info));
|
||||||
|
|
||||||
new_scope.tables.push(source_table);
|
|
||||||
new_scope.table_aliases.push(alias);
|
|
||||||
|
|
||||||
let on = try!(self.ast_expression_to_sexpression(join.on, &new_scope, groups_info));
|
|
||||||
|
|
||||||
match join.operator {
|
match join.operator {
|
||||||
ast::JoinOperator::Inner => {
|
ast::JoinOperator::Inner => {
|
||||||
|
new_scope.tables.push(source_table);
|
||||||
|
new_scope.table_aliases.push(alias);
|
||||||
|
|
||||||
|
let on = try!(self.ast_expression_to_sexpression(join.on, &new_scope, groups_info));
|
||||||
Ok(FromWhereJoin::Inner {
|
Ok(FromWhereJoin::Inner {
|
||||||
table: fromwhere_table,
|
table: fromwhere_table,
|
||||||
on: on
|
on: on
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
ast::JoinOperator::Left => unimplemented!()
|
ast::JoinOperator::Left => {
|
||||||
|
let source_id = self.new_source_id();
|
||||||
|
|
||||||
|
let left_join_source_table = TableOrSubquery {
|
||||||
|
source_id: source_id,
|
||||||
|
out_column_names: source_table.out_column_names
|
||||||
|
};
|
||||||
|
|
||||||
|
let column_count = left_join_source_table.out_column_names.len() as u32;
|
||||||
|
|
||||||
|
new_scope.tables.push(left_join_source_table);
|
||||||
|
new_scope.table_aliases.push(alias);
|
||||||
|
|
||||||
|
let on = try!(self.ast_expression_to_sexpression(join.on, &new_scope, groups_info));
|
||||||
|
Ok(FromWhereJoin::Left {
|
||||||
|
source_id: source_id,
|
||||||
|
table: fromwhere_table.yield_all_columns(column_count),
|
||||||
|
on: on,
|
||||||
|
right_rows_if_none: (0..column_count).map(|_| ColumnValueOpsExt::null()).collect()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).collect());
|
}).collect());
|
||||||
|
|
||||||
|
@ -19,6 +19,13 @@ where <DB as DatabaseInfo>::Table: 'a
|
|||||||
source_id: u32,
|
source_id: u32,
|
||||||
yield_fn: Box<SExpression<'a, DB>>
|
yield_fn: Box<SExpression<'a, DB>>
|
||||||
},
|
},
|
||||||
|
LeftJoin {
|
||||||
|
source_id: u32,
|
||||||
|
yield_in_fn: Box<SExpression<'a, DB>>,
|
||||||
|
predicate: Box<SExpression<'a, DB>>,
|
||||||
|
yield_out_fn: Box<SExpression<'a, DB>>,
|
||||||
|
right_rows_if_none: Vec<<DB as DatabaseInfo>::ColumnValue>
|
||||||
|
},
|
||||||
Map {
|
Map {
|
||||||
source_id: u32,
|
source_id: u32,
|
||||||
yield_in_fn: Box<SExpression<'a, DB>>,
|
yield_in_fn: Box<SExpression<'a, DB>>,
|
||||||
@ -90,6 +97,21 @@ where <DB as DatabaseInfo>::Table: 'a
|
|||||||
try!(yield_fn.format(f, indent + 1));
|
try!(yield_fn.format(f, indent + 1));
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
},
|
},
|
||||||
|
&SExpression::LeftJoin { source_id, ref yield_in_fn, ref predicate, ref yield_out_fn, ref right_rows_if_none } => {
|
||||||
|
try!(writeln!(f, "(left-join :source-id {}", source_id));
|
||||||
|
try!(yield_in_fn.format(f, indent + 1));
|
||||||
|
try!(writeln!(f, ""));
|
||||||
|
try!(predicate.format(f, indent + 1));
|
||||||
|
try!(writeln!(f, ""));
|
||||||
|
try!(yield_out_fn.format(f, indent + 1));
|
||||||
|
try!(writeln!(f, ""));
|
||||||
|
write_indent!(indent + 1);
|
||||||
|
try!(write!(f, "(right-rows-if-none "));
|
||||||
|
for value in right_rows_if_none {
|
||||||
|
try!(write!(f, "{} ", value));
|
||||||
|
}
|
||||||
|
write!(f, "))")
|
||||||
|
},
|
||||||
&SExpression::Map { source_id, ref yield_in_fn, ref yield_out_fn } => {
|
&SExpression::Map { source_id, ref yield_in_fn, ref yield_out_fn } => {
|
||||||
try!(writeln!(f, "(map :source-id {}", source_id));
|
try!(writeln!(f, "(map :source-id {}", source_id));
|
||||||
try!(yield_in_fn.format(f, indent + 1));
|
try!(yield_in_fn.format(f, indent + 1));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user