/*++ Copyright (c) 2013 Microsoft Corporation Module Name: dl_lazy_table.cpp Abstract: Author: Nikolaj Bjorner (nbjorner) 2013-09-04 Revision History: --*/ #include "muz/rel/dl_lazy_table.h" #include "muz/rel/dl_relation_manager.h" #include namespace datalog { // ------------------ // lazy_table_plugin: symbol lazy_table_plugin::mk_name(table_plugin& p) { std::ostringstream strm; strm << "lazy_" << p.get_name(); return symbol(strm.str()); } table_base * lazy_table_plugin::mk_empty(const table_signature & s) { return alloc(lazy_table, alloc(lazy_table_base, *this, m_plugin.mk_empty(s))); } lazy_table const& lazy_table_plugin::get(table_base const& tb) { return dynamic_cast(tb); } lazy_table& lazy_table_plugin::get(table_base& tb) { return dynamic_cast(tb); } lazy_table const* lazy_table_plugin::get(table_base const* tb) { return dynamic_cast(tb); } lazy_table* lazy_table_plugin::get(table_base* tb) { return dynamic_cast(tb); } // -------------------------- // lazy_table_plugin::join_fn class lazy_table_plugin::join_fn : public convenient_table_join_fn { public: join_fn(table_signature const& s1, table_signature const& s2, unsigned col_cnt, unsigned const* cols1, unsigned const* cols2): convenient_table_join_fn(s1, s2, col_cnt, cols1, cols2) {} table_base* operator()(const table_base& _t1, const table_base& _t2) override { lazy_table const& t1 = get(_t1); lazy_table const& t2 = get(_t2); lazy_table_ref* tr = alloc(lazy_table_join, m_cols1.size(), m_cols1.data(), m_cols2.data(), t1, t2, get_result_signature()); return alloc(lazy_table, tr); } }; table_join_fn * lazy_table_plugin::mk_join_fn( const table_base & t1, const table_base & t2, unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { if (check_kind(t1) && check_kind(t2)) { return alloc(join_fn, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2); } else { return nullptr; } } // ------------------------ // lazy_table_plugin::union class lazy_table_plugin::union_fn : public table_union_fn { public: void operator()(table_base & _tgt, const table_base & _src, table_base * _delta) override { lazy_table& tgt = get(_tgt); lazy_table const& src = get(_src); lazy_table* delta = get(_delta); table_base const* t_src = src.eval(); table_base * t_tgt = tgt.eval(); table_base * t_delta = delta?delta->eval():nullptr; verbose_action _t("union"); table_union_fn* m = tgt.get_lplugin().get_manager().mk_union_fn(*t_tgt, *t_src, t_delta); SASSERT(m); (*m)(*t_tgt, *t_src, t_delta); dealloc(m); } }; table_union_fn* lazy_table_plugin::mk_union_fn( const table_base & tgt, const table_base & src, const table_base * delta) { if (check_kind(tgt) && check_kind(src) && (!delta || check_kind(*delta))) { return alloc(union_fn); } else { return nullptr; } } // -------------------------- // lazy_table_plugin::project class lazy_table_plugin::project_fn : public convenient_table_project_fn { public: project_fn(table_signature const& orig_sig, unsigned cnt, unsigned const* cols): convenient_table_project_fn(orig_sig, cnt, cols) {} table_base* operator()(table_base const& _t) override { lazy_table const& t = get(_t); return alloc(lazy_table, alloc(lazy_table_project, m_removed_cols.size(), m_removed_cols.data(), t, get_result_signature())); } }; table_transformer_fn * lazy_table_plugin::mk_project_fn( const table_base & t, unsigned col_cnt, const unsigned * removed_cols) { if (check_kind(t)) { return alloc(project_fn, t.get_signature(), col_cnt, removed_cols); } else { return nullptr; } } // ------------------------- // lazy_table_plugin::rename class lazy_table_plugin::rename_fn : public convenient_table_rename_fn { public: rename_fn(table_signature const& orig_sig, unsigned cnt, unsigned const* cols): convenient_table_rename_fn(orig_sig, cnt, cols) {} table_base* operator()(table_base const& _t) override { lazy_table const& t = get(_t); return alloc(lazy_table, alloc(lazy_table_rename, m_cycle.size(), m_cycle.data(), t, get_result_signature())); } }; table_transformer_fn * lazy_table_plugin::mk_rename_fn( const table_base & t, unsigned col_cnt, const unsigned * removed_cols) { if (check_kind(t)) { return alloc(rename_fn, t.get_signature(), col_cnt, removed_cols); } else { return nullptr; } } // ----------------------------------- // lazy_table_plugin::filter_identical class lazy_table_plugin::filter_identical_fn : public table_mutator_fn { unsigned_vector m_cols; public: filter_identical_fn(unsigned cnt, unsigned const* cols): m_cols(cnt, cols) {} void operator()(table_base& _t) override { lazy_table& t = get(_t); t.set(alloc(lazy_table_filter_identical, m_cols.size(), m_cols.data(), t)); } }; table_mutator_fn * lazy_table_plugin::mk_filter_identical_fn( const table_base & t, unsigned col_cnt, const unsigned * identical_cols) { if (check_kind(t)) { return alloc(filter_identical_fn, col_cnt, identical_cols); } else { return nullptr; } } // ------------------------------------- // lazy_table_plugin::filter_interpreted class lazy_table_plugin::filter_interpreted_fn : public table_mutator_fn { app_ref m_condition; public: filter_interpreted_fn(app_ref& p): m_condition(p) {} void operator()(table_base& _t) override { lazy_table& t = get(_t); t.set(alloc(lazy_table_filter_interpreted, t, m_condition)); } }; table_mutator_fn * lazy_table_plugin::mk_filter_interpreted_fn( const table_base & t, app* condition) { if (check_kind(t)) { app_ref cond(condition, get_ast_manager()); return alloc(filter_interpreted_fn, cond); } else { return nullptr; } } // ------------------------------------- // lazy_table_plugin::filter_by_negation class lazy_table_plugin::filter_by_negation_fn : public table_intersection_filter_fn { unsigned_vector m_cols1; unsigned_vector m_cols2; public: filter_by_negation_fn(unsigned cnt, unsigned const* cols1, unsigned const* cols2): m_cols1(cnt, cols1), m_cols2(cnt, cols2) {} void operator()(table_base & _t, const table_base & _intersected_obj) override { lazy_table& t = get(_t); lazy_table const& it = get(_intersected_obj); t.set(alloc(lazy_table_filter_by_negation, t, it, m_cols1, m_cols2)); } }; table_intersection_filter_fn * lazy_table_plugin::mk_filter_by_negation_fn( const table_base & t, const table_base & negated_obj, unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * negated_cols) { if (check_kind(t) && check_kind(negated_obj)) { return alloc(filter_by_negation_fn, joined_col_cnt, t_cols, negated_cols); } else { return nullptr; } } // ------------------------------- // lazy_table_plugin::filter_equal class lazy_table_plugin::filter_equal_fn : public table_mutator_fn { table_element m_value; unsigned m_col; public: filter_equal_fn(const table_element & value, unsigned col): m_value(value), m_col(col) { } void operator()(table_base& _t) override { lazy_table& t = get(_t); t.set(alloc(lazy_table_filter_equal, m_col, m_value, t)); } }; table_mutator_fn * lazy_table_plugin::mk_filter_equal_fn( const table_base & t, const table_element & value, unsigned col) { if (check_kind(t)) { return alloc(filter_equal_fn, value, col); } else { return nullptr; } } table_plugin* lazy_table_plugin::mk_sparse(relation_manager& rm) { table_plugin* sp = rm.get_table_plugin(symbol("sparse")); SASSERT(sp); if (sp) { return alloc(lazy_table_plugin, *sp); } else { return nullptr; } } // ---------- // lazy_table table_base * lazy_table::clone() const { table_base* t = eval(); verbose_action _t("clone"); return alloc(lazy_table, alloc(lazy_table_base, get_lplugin(), t->clone())); } table_base * lazy_table::complement(func_decl* p, const table_element * func_columns) const { table_base* t = eval()->complement(p, func_columns); return alloc(lazy_table, alloc(lazy_table_base, get_lplugin(), t)); } bool lazy_table::empty() const { return m_ref->eval()->empty(); } bool lazy_table::contains_fact(const table_fact & f) const { return m_ref->eval()->contains_fact(f); } void lazy_table::remove_fact(table_element const* fact) { m_ref->eval()->remove_fact(fact); } void lazy_table::remove_facts(unsigned fact_cnt, const table_fact * facts) { m_ref->eval()->remove_facts(fact_cnt, facts); } void lazy_table::remove_facts(unsigned fact_cnt, const table_element * facts) { m_ref->eval()->remove_facts(fact_cnt, facts); } void lazy_table::reset() { m_ref = alloc(lazy_table_base, get_lplugin(), get_lplugin().m_plugin.mk_empty(get_signature())); } void lazy_table::add_fact(table_fact const& f) { m_ref->eval()->add_fact(f); } table_base::iterator lazy_table::begin() const { return eval()->begin(); } table_base::iterator lazy_table::end() const { return eval()->end(); } table_base* lazy_table::eval() const { return m_ref->eval(); } // ------------------------- // eval table_base* lazy_table_join::force() { SASSERT(!m_table); table_base* t1 = m_t1->eval(); table_base* t2 = m_t2->eval(); verbose_action _t("join"); table_join_fn* join = rm().mk_join_fn(*t1, *t2, m_cols1.size(), m_cols1.data(), m_cols2.data()); m_table = (*join)(*t1, *t2); dealloc(join); return m_table.get(); } table_base* lazy_table_project::force() { SASSERT(!m_table); switch(m_src->kind()) { case LAZY_TABLE_JOIN: { lazy_table_join& src = dynamic_cast(*m_src); table_base* t1 = src.t1()->eval(); table_base* t2 = src.t2()->eval(); table_join_fn* j_fn = rm().mk_join_project_fn(*t1, *t2, src.cols1(), src.cols2(), m_cols); if (j_fn) { verbose_action _t("join_project"); m_table = (*j_fn)(*t1, *t2); dealloc(j_fn); } break; } case LAZY_TABLE_FILTER_INTERPRETED: { lazy_table_filter_interpreted& src = dynamic_cast(*m_src); table_transformer_fn* tr = rm().mk_filter_interpreted_and_project_fn(*src.eval(), src.condition(), m_cols.size(), m_cols.data()); if (tr) { verbose_action _t("filter_interpreted_project"); m_table = (*tr)(*src.eval()); dealloc(tr); } break; } case LAZY_TABLE_FILTER_EQUAL: { lazy_table_filter_equal& src = dynamic_cast(*m_src); table_base* t = src.eval(); table_transformer_fn* tr = rm().mk_select_equal_and_project_fn(*t, src.value(), src.col()); if (tr) { verbose_action _t("select_equal_project"); m_table = (*tr)(*t); dealloc(tr); } break; } default: break; } if (m_table) { return m_table.get(); } table_base* src = m_src->eval(); verbose_action _t("project"); table_transformer_fn* project = rm().mk_project_fn(*src, m_cols.size(), m_cols.data()); SASSERT(project); m_table = (*project)(*src); dealloc(project); return m_table.get(); } table_base* lazy_table_rename::force() { SASSERT(!m_table); table_base* src = m_src->eval(); verbose_action _t("rename"); table_transformer_fn* rename = rm().mk_rename_fn(*src, m_cols.size(), m_cols.data()); m_table = (*rename)(*src); dealloc(rename); return m_table.get(); } table_base* lazy_table_filter_identical::force() { SASSERT(!m_table); m_table = m_src->eval(); m_src->release_table(); m_src = nullptr; verbose_action _t("filter_identical"); table_mutator_fn* m = rm().mk_filter_identical_fn(*m_table, m_cols.size(), m_cols.data()); SASSERT(m); (*m)(*m_table); dealloc(m); return m_table.get(); } table_base* lazy_table_filter_equal::force() { SASSERT(!m_table); m_table = m_src->eval(); m_src->release_table(); m_src = nullptr; verbose_action _t("filter_equal"); table_mutator_fn* m = rm().mk_filter_equal_fn(*m_table, m_value, m_col); SASSERT(m); (*m)(*m_table); dealloc(m); return m_table.get(); } table_base* lazy_table_filter_interpreted::force() { SASSERT(!m_table); m_table = m_src->eval(); m_src->release_table(); m_src = nullptr; verbose_action _t("filter_interpreted"); table_mutator_fn* m = rm().mk_filter_interpreted_fn(*m_table, m_condition); SASSERT(m); (*m)(*m_table); dealloc(m); return m_table.get(); } table_base* lazy_table_filter_by_negation::force() { SASSERT(!m_table); m_table = m_tgt->eval(); m_tgt->release_table(); m_tgt = nullptr; switch(m_src->kind()) { case LAZY_TABLE_JOIN: { lazy_table_join& src = dynamic_cast(*m_src); table_base* t1 = src.t1()->eval(); table_base* t2 = src.t2()->eval(); verbose_action _t("filter_by_negation_join"); table_intersection_join_filter_fn* jn = rm().mk_filter_by_negated_join_fn(*m_table, *t1, *t2, cols1(), cols2(), src.cols1(), src.cols2()); if (jn) { (*jn)(*m_table, *t1, *t2); dealloc(jn); return m_table.get(); } break; } default: break; } table_base* src = m_src->eval(); verbose_action _t("filter_by_negation"); table_intersection_filter_fn* m = rm().mk_filter_by_negation_fn(*m_table, *src, m_cols1, m_cols2); SASSERT(m); (*m)(*m_table, *src); dealloc(m); return m_table.get(); } }