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(())
|
||||
},
|
||||
&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 } => {
|
||||
self.execute(yield_in_fn, &mut |row| {
|
||||
let new_source = Source {
|
||||
@ -303,6 +336,7 @@ where <Storage::Info as DatabaseInfo>::Table: 'a
|
||||
}
|
||||
},
|
||||
&SExpression::Scan { .. } |
|
||||
&SExpression::LeftJoin { .. } |
|
||||
&SExpression::TempGroupBy { .. } |
|
||||
&SExpression::Yield { .. } |
|
||||
&SExpression::If { .. } => {
|
||||
|
@ -193,6 +193,12 @@ where <DB as DatabaseInfo>::Table: 'a
|
||||
table: FromWhereTableOrSubquery<'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>
|
||||
@ -243,6 +249,15 @@ where <DB as DatabaseInfo>::Table: 'a
|
||||
}],
|
||||
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>
|
||||
@ -523,19 +559,38 @@ where DB: 'a, <DB as DatabaseInfo>::Table: 'a
|
||||
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));
|
||||
|
||||
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 {
|
||||
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 {
|
||||
table: fromwhere_table,
|
||||
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());
|
||||
|
||||
|
@ -19,6 +19,13 @@ where <DB as DatabaseInfo>::Table: 'a
|
||||
source_id: u32,
|
||||
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 {
|
||||
source_id: u32,
|
||||
yield_in_fn: Box<SExpression<'a, DB>>,
|
||||
@ -90,6 +97,21 @@ where <DB as DatabaseInfo>::Table: 'a
|
||||
try!(yield_fn.format(f, indent + 1));
|
||||
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 } => {
|
||||
try!(writeln!(f, "(map :source-id {}", source_id));
|
||||
try!(yield_in_fn.format(f, indent + 1));
|
||||
|
Loading…
x
Reference in New Issue
Block a user