1 /*++ 2 Copyright (c) 2006 Microsoft Corporation 3 4 Module Name: 5 6 dl_relation_manager.cpp 7 8 Abstract: 9 10 <abstract> 11 12 Author: 13 14 Krystof Hoder (t-khoder) 2010-09-14. 15 16 Revision History: 17 18 --*/ 19 20 21 #include <sstream> 22 #include "ast/ast_pp.h" 23 #include "muz/rel/dl_check_table.h" 24 #include "muz/base/dl_context.h" 25 #include "muz/rel/dl_finite_product_relation.h" 26 #include "muz/rel/dl_product_relation.h" 27 #include "muz/rel/dl_sieve_relation.h" 28 #include "muz/rel/dl_table_relation.h" 29 #include "muz/rel/dl_relation_manager.h" 30 31 namespace datalog { 32 ~relation_manager()33 relation_manager::~relation_manager() { 34 reset(); 35 } 36 37 reset_relations()38 void relation_manager::reset_relations() { 39 for (auto const& kv : m_relations) { 40 func_decl * pred = kv.m_key; 41 get_context().get_manager().dec_ref(pred); //inc_ref in get_relation 42 kv.m_value->deallocate(); 43 } 44 m_relations.reset(); 45 } 46 reset()47 void relation_manager::reset() { 48 reset_relations(); 49 50 m_favourite_table_plugin = static_cast<table_plugin *>(nullptr); 51 m_favourite_relation_plugin = static_cast<relation_plugin *>(nullptr); 52 dealloc_ptr_vector_content(m_table_plugins); 53 m_table_plugins.reset(); 54 dealloc_ptr_vector_content(m_relation_plugins); 55 m_relation_plugins.reset(); 56 m_next_table_fid = 0; 57 m_next_relation_fid = 0; 58 } 59 get_decl_util() const60 dl_decl_util & relation_manager::get_decl_util() const { 61 return get_context().get_decl_util(); 62 } 63 get_next_relation_fid(relation_plugin & claimer)64 family_id relation_manager::get_next_relation_fid(relation_plugin & claimer) { 65 unsigned res = m_next_relation_fid++; 66 m_kind2plugin.insert(res, &claimer); 67 return res; 68 } 69 set_predicate_kind(func_decl * pred,family_id kind)70 void relation_manager::set_predicate_kind(func_decl * pred, family_id kind) { 71 SASSERT(!m_relations.contains(pred)); 72 m_pred_kinds.insert(pred, kind); 73 } 74 get_requested_predicate_kind(func_decl * pred)75 family_id relation_manager::get_requested_predicate_kind(func_decl * pred) { 76 family_id res; 77 if(m_pred_kinds.find(pred, res)) { 78 return res; 79 } 80 else { 81 return null_family_id; 82 } 83 } 84 get_relation(func_decl * pred)85 relation_base & relation_manager::get_relation(func_decl * pred) { 86 relation_base * res = try_get_relation(pred); 87 if(!res) { 88 relation_signature sig; 89 from_predicate(pred, sig); 90 family_id rel_kind = get_requested_predicate_kind(pred); 91 res = mk_empty_relation(sig, rel_kind); 92 store_relation(pred, res); 93 } 94 return *res; 95 } 96 try_get_relation(func_decl * pred) const97 relation_base * relation_manager::try_get_relation(func_decl * pred) const { 98 relation_base * res = nullptr; 99 if(!m_relations.find(pred, res)) { 100 return nullptr; 101 } 102 SASSERT(res); 103 return res; 104 } 105 store_relation(func_decl * pred,relation_base * rel)106 void relation_manager::store_relation(func_decl * pred, relation_base * rel) { 107 SASSERT(rel); 108 auto& value = m_relations.insert_if_not_there(pred, 0); 109 if (value) { 110 value->deallocate(); 111 } 112 else { 113 get_context().get_manager().inc_ref(pred); //dec_ref in reset 114 } 115 value = rel; 116 } 117 collect_predicates() const118 decl_set relation_manager::collect_predicates() const { 119 decl_set res; 120 for (auto const& kv : m_relations) { 121 res.insert(kv.m_key); 122 } 123 return res; 124 } 125 collect_non_empty_predicates(decl_set & res) const126 void relation_manager::collect_non_empty_predicates(decl_set & res) const { 127 for (auto const& kv : m_relations) { 128 if (!kv.m_value->fast_empty()) { 129 res.insert(kv.m_key); 130 } 131 } 132 } 133 restrict_predicates(const decl_set & preds)134 void relation_manager::restrict_predicates(const decl_set & preds) { 135 ptr_vector<func_decl> to_remove; 136 137 for (auto const& kv : m_relations) { 138 func_decl* pred = kv.m_key; 139 if (!preds.contains(pred)) { 140 to_remove.insert(pred); 141 } 142 } 143 144 for (func_decl* pred : to_remove) { 145 m_relations.find(pred)->deallocate(); 146 m_relations.remove(pred); 147 get_context().get_manager().dec_ref(pred); 148 } 149 150 set_intersection(m_saturated_rels, preds); 151 } 152 register_plugin(table_plugin * plugin)153 void relation_manager::register_plugin(table_plugin * plugin) { 154 plugin->initialize(get_next_table_fid()); 155 m_table_plugins.push_back(plugin); 156 157 if(plugin->get_name()==get_context().default_table()) { 158 m_favourite_table_plugin = plugin; 159 } 160 161 table_relation_plugin * tr_plugin = alloc(table_relation_plugin, *plugin, *this); 162 register_relation_plugin_impl(tr_plugin); 163 m_table_relation_plugins.insert(plugin, tr_plugin); 164 165 if (plugin->get_name()==get_context().default_table()) { 166 m_favourite_table_plugin = plugin; 167 m_favourite_relation_plugin = tr_plugin; 168 } 169 170 symbol checker_name = get_context().default_table_checker(); 171 if (get_context().default_table_checked() && get_table_plugin(checker_name)) { 172 if( m_favourite_table_plugin && 173 (plugin==m_favourite_table_plugin || plugin->get_name()==checker_name) ) { 174 symbol checked_name = get_context().default_table(); 175 //the plugins we need to create the checking plugin were just added 176 SASSERT(m_favourite_table_plugin->get_name()==get_context().default_table()); 177 table_plugin * checking_plugin = alloc(check_table_plugin, *this, checker_name, checked_name); 178 register_plugin(checking_plugin); 179 m_favourite_table_plugin = checking_plugin; 180 } 181 if (m_favourite_relation_plugin && m_favourite_relation_plugin->from_table()) { 182 table_relation_plugin * fav_rel_plugin = 183 static_cast<table_relation_plugin *>(m_favourite_relation_plugin); 184 if(&fav_rel_plugin->get_table_plugin()==plugin || plugin->get_name()==checker_name) { 185 //the plugins we need to create the checking table_relation_plugin were just added 186 SASSERT(m_favourite_relation_plugin->get_name() == 187 get_context().default_relation()); 188 symbol checked_name = fav_rel_plugin->get_table_plugin().get_name(); 189 table_plugin * checking_plugin = alloc(check_table_plugin, *this, checker_name, checked_name); 190 register_plugin(checking_plugin); 191 192 table_relation_plugin * checking_tr_plugin = 193 alloc(table_relation_plugin, *checking_plugin, *this); 194 register_relation_plugin_impl(checking_tr_plugin); 195 m_table_relation_plugins.insert(checking_plugin, checking_tr_plugin); 196 m_favourite_relation_plugin = checking_tr_plugin; 197 } 198 } 199 } 200 201 } 202 register_relation_plugin_impl(relation_plugin * plugin)203 void relation_manager::register_relation_plugin_impl(relation_plugin * plugin) { 204 TRACE("dl", tout << "register: " << plugin->get_name() << "\n";); 205 m_relation_plugins.push_back(plugin); 206 plugin->initialize(get_next_relation_fid(*plugin)); 207 if (plugin->get_name() == get_context().default_relation()) { 208 m_favourite_relation_plugin = plugin; 209 } 210 if(plugin->is_finite_product_relation()) { 211 finite_product_relation_plugin * fprp = static_cast<finite_product_relation_plugin *>(plugin); 212 relation_plugin * inner = &fprp->get_inner_plugin(); 213 m_finite_product_relation_plugins.insert(inner, fprp); 214 } 215 } 216 try_get_appropriate_plugin(const relation_signature & s)217 relation_plugin * relation_manager::try_get_appropriate_plugin(const relation_signature & s) { 218 if(m_favourite_relation_plugin && m_favourite_relation_plugin->can_handle_signature(s)) { 219 return m_favourite_relation_plugin; 220 } 221 for (auto * r : m_relation_plugins) { 222 if (r->can_handle_signature(s)) { 223 return r; 224 } 225 } 226 return nullptr; 227 } 228 get_appropriate_plugin(const relation_signature & s)229 relation_plugin & relation_manager::get_appropriate_plugin(const relation_signature & s) { 230 relation_plugin * res = try_get_appropriate_plugin(s); 231 if (!res) { 232 throw default_exception("no suitable plugin found for given relation signature"); 233 } 234 return *res; 235 } 236 try_get_appropriate_plugin(const table_signature & t)237 table_plugin * relation_manager::try_get_appropriate_plugin(const table_signature & t) { 238 if (m_favourite_table_plugin && m_favourite_table_plugin->can_handle_signature(t)) { 239 return m_favourite_table_plugin; 240 } 241 for (auto * a : m_table_plugins) { 242 if (a->can_handle_signature(t)) { 243 return a; 244 } 245 } 246 return nullptr; 247 } 248 get_appropriate_plugin(const table_signature & t)249 table_plugin & relation_manager::get_appropriate_plugin(const table_signature & t) { 250 table_plugin * res = try_get_appropriate_plugin(t); 251 if(!res) { 252 throw default_exception("no suitable plugin found for given table signature"); 253 } 254 return *res; 255 } 256 get_relation_plugin(symbol const & s)257 relation_plugin * relation_manager::get_relation_plugin(symbol const& s) { 258 for (auto* r : m_relation_plugins) { 259 if(r->get_name() == s) { 260 return r; 261 } 262 } 263 return nullptr; 264 } 265 get_relation_plugin(family_id kind)266 relation_plugin & relation_manager::get_relation_plugin(family_id kind) { 267 SASSERT(kind>=0); 268 SASSERT(kind<m_next_relation_fid); 269 relation_plugin * res = nullptr; 270 VERIFY(m_kind2plugin.find(kind, res)); 271 return *res; 272 } 273 get_table_plugin(symbol const & k)274 table_plugin * relation_manager::get_table_plugin(symbol const& k) { 275 for (table_plugin * tp : m_table_plugins) { 276 if (tp->get_name()==k) { 277 return tp; 278 } 279 } 280 return nullptr; 281 } 282 get_table_relation_plugin(table_plugin & tp)283 table_relation_plugin & relation_manager::get_table_relation_plugin(table_plugin & tp) { 284 table_relation_plugin * res = nullptr; 285 VERIFY( m_table_relation_plugins.find(&tp, res) ); 286 return *res; 287 } 288 try_get_finite_product_relation_plugin(const relation_plugin & inner,finite_product_relation_plugin * & res)289 bool relation_manager::try_get_finite_product_relation_plugin(const relation_plugin & inner, 290 finite_product_relation_plugin * & res) { 291 return m_finite_product_relation_plugins.find(&inner, res); 292 } 293 mk_empty_table(const table_signature & s)294 table_base * relation_manager::mk_empty_table(const table_signature & s) { 295 return get_appropriate_plugin(s).mk_empty(s); 296 } 297 298 is_non_explanation(relation_signature const & s) const299 bool relation_manager::is_non_explanation(relation_signature const& s) const { 300 dl_decl_util & decl_util = get_context().get_decl_util(); 301 unsigned n = s.size(); 302 for(unsigned i = 0; i < n; i++) { 303 if(decl_util.is_rule_sort(s[i])) { 304 return false; 305 } 306 } 307 return true; 308 } 309 mk_empty_relation(const relation_signature & s,func_decl * pred)310 relation_base * relation_manager::mk_empty_relation(const relation_signature & s, func_decl* pred) { 311 return mk_empty_relation(s, get_requested_predicate_kind(pred)); 312 } 313 mk_empty_relation(const relation_signature & s,family_id kind)314 relation_base * relation_manager::mk_empty_relation(const relation_signature & s, family_id kind) { 315 if (kind != null_family_id) { 316 relation_plugin & plugin = get_relation_plugin(kind); 317 if (plugin.can_handle_signature(s, kind)) 318 return plugin.mk_empty(s, kind); 319 } 320 relation_base * res; 321 relation_plugin* p = m_favourite_relation_plugin; 322 323 if (p && p->can_handle_signature(s)) { 324 return p->mk_empty(s); 325 } 326 327 if (mk_empty_table_relation(s, res)) { 328 return res; 329 } 330 331 for (relation_plugin* p1 : m_relation_plugins) { 332 if (p1->can_handle_signature(s)) { 333 return p1->mk_empty(s); 334 } 335 } 336 337 //If there is no plugin to handle the signature, we just create an empty product relation and 338 //stuff will be added to it by later operations. 339 TRACE("dl", s.output(get_context().get_manager(), tout << "empty product relation"); tout << "\n";); 340 return product_relation_plugin::get_plugin(*this).mk_empty(s); 341 } 342 343 /** 344 The newly created object takes ownership of the \c table object. 345 */ mk_table_relation(const relation_signature & s,table_base * table)346 relation_base * relation_manager::mk_table_relation(const relation_signature & s, table_base * table) { 347 SASSERT(s.size()==table->get_signature().size()); 348 return get_table_relation_plugin(table->get_plugin()).mk_from_table(s, table); 349 } 350 mk_empty_table_relation(const relation_signature & s,relation_base * & result)351 bool relation_manager::mk_empty_table_relation(const relation_signature & s, relation_base * & result) { 352 table_signature tsig; 353 if(!relation_signature_to_table(s, tsig)) { 354 return false; 355 } 356 table_base * table = mk_empty_table(tsig); 357 result = mk_table_relation(s, table); 358 return true; 359 } 360 361 mk_full_relation(const relation_signature & s,func_decl * p,family_id kind)362 relation_base * relation_manager::mk_full_relation(const relation_signature & s, func_decl* p, family_id kind) { 363 if (kind != null_family_id) { 364 relation_plugin & plugin = get_relation_plugin(kind); 365 if (plugin.can_handle_signature(s, kind)) { 366 return plugin.mk_full(p, s, kind); 367 } 368 } 369 return get_appropriate_plugin(s).mk_full(p, s, null_family_id); 370 } 371 mk_full_relation(const relation_signature & s,func_decl * pred)372 relation_base * relation_manager::mk_full_relation(const relation_signature & s, func_decl* pred) { 373 family_id kind = get_requested_predicate_kind(pred); 374 return mk_full_relation(s, pred, kind); 375 } 376 relation_to_table(const relation_sort & sort,const relation_element & from,table_element & to)377 void relation_manager::relation_to_table(const relation_sort & sort, const relation_element & from, 378 table_element & to) { 379 SASSERT(from->get_num_args()==0); 380 VERIFY(get_context().get_decl_util().is_numeral_ext(from, to)); 381 } 382 table_to_relation(const relation_sort & sort,const table_element & from,relation_element & to)383 void relation_manager::table_to_relation(const relation_sort & sort, const table_element & from, 384 relation_element & to) { 385 to = get_decl_util().mk_numeral(from, sort); 386 } 387 table_to_relation(const relation_sort & sort,const table_element & from,relation_element_ref & to)388 void relation_manager::table_to_relation(const relation_sort & sort, const table_element & from, 389 relation_element_ref & to) { 390 relation_element rel_el; 391 table_to_relation(sort, from, rel_el); 392 to = rel_el; 393 } 394 table_to_relation(const relation_sort & sort,const table_element & from,const relation_fact::el_proxy & to)395 void relation_manager::table_to_relation(const relation_sort & sort, const table_element & from, 396 const relation_fact::el_proxy & to) { 397 relation_element rel_el; 398 table_to_relation(sort, from, rel_el); 399 to = rel_el; 400 } 401 relation_sort_to_table(const relation_sort & from,table_sort & to)402 bool relation_manager::relation_sort_to_table(const relation_sort & from, table_sort & to) { 403 return get_context().get_decl_util().try_get_size(from, to); 404 } 405 from_predicate(func_decl * pred,unsigned arg_index,relation_sort & result)406 void relation_manager::from_predicate(func_decl * pred, unsigned arg_index, relation_sort & result) { 407 result = pred->get_domain(arg_index); 408 } 409 from_predicate(func_decl * pred,relation_signature & result)410 void relation_manager::from_predicate(func_decl * pred, relation_signature & result) { 411 result.reset(); 412 unsigned arg_num=pred->get_arity(); 413 for(unsigned i=0;i<arg_num; i++) { 414 relation_sort rel_srt; 415 from_predicate(pred, i, rel_srt); 416 result.push_back(rel_srt); 417 } 418 } 419 420 relation_signature_to_table(const relation_signature & from,table_signature & to)421 bool relation_manager::relation_signature_to_table(const relation_signature & from, table_signature & to) { 422 unsigned n=from.size(); 423 to.resize(n); 424 for(unsigned i=0; i<n; i++) { 425 if(!relation_sort_to_table(from[i], to[i])) { 426 return false; 427 } 428 } 429 return true; 430 } 431 relation_fact_to_table(const relation_signature & s,const relation_fact & from,table_fact & to)432 void relation_manager::relation_fact_to_table(const relation_signature & s, const relation_fact & from, 433 table_fact & to) { 434 SASSERT(s.size()==from.size()); 435 unsigned n=from.size(); 436 to.resize(n); 437 for(unsigned i=0;i<n;i++) { 438 relation_to_table(s[i], from[i], to[i]); 439 } 440 } 441 table_fact_to_relation(const relation_signature & s,const table_fact & from,relation_fact & to)442 void relation_manager::table_fact_to_relation(const relation_signature & s, const table_fact & from, 443 relation_fact & to) { 444 SASSERT(s.size()==from.size()); 445 unsigned n=from.size(); 446 to.resize(n); 447 for(unsigned i=0;i<n;i++) { 448 table_to_relation(s[i], from[i], to[i]); 449 } 450 } 451 to_nice_string(const relation_element & el) const452 std::string relation_manager::to_nice_string(const relation_element & el) const { 453 uint64_t val; 454 std::stringstream stm; 455 if(get_context().get_decl_util().is_numeral_ext(el, val)) { 456 stm << val; 457 } 458 else { 459 stm << mk_pp(el, get_context().get_manager()); 460 } 461 return stm.str(); 462 } 463 to_nice_string(const relation_sort & s,const relation_element & el) const464 std::string relation_manager::to_nice_string(const relation_sort & s, const relation_element & el) const { 465 std::stringstream stm; 466 uint64_t val; 467 if(get_context().get_decl_util().is_numeral_ext(el, val)) { 468 get_context().print_constant_name(s, val, stm); 469 } 470 else { 471 stm << mk_pp(el, get_context().get_manager()); 472 } 473 return stm.str(); 474 } 475 to_nice_string(const relation_sort & s) const476 std::string relation_manager::to_nice_string(const relation_sort & s) const { 477 std::ostringstream strm; 478 strm << mk_pp(s, get_context().get_manager()); 479 return strm.str(); 480 } 481 to_nice_string(const relation_signature & s) const482 std::string relation_manager::to_nice_string(const relation_signature & s) const { 483 std::string res("["); 484 bool first = true; 485 for (auto const& sig : s) { 486 if (first) { 487 first = false; 488 } 489 else { 490 res += ','; 491 } 492 res += to_nice_string(sig); 493 } 494 res += ']'; 495 496 return res; 497 } 498 display(std::ostream & out) const499 void relation_manager::display(std::ostream & out) const { 500 for (auto const& kv : m_relations) { 501 out << "Table " << kv.m_key->get_name() << "\n"; 502 kv.m_value->display(out); 503 } 504 } 505 display_relation_sizes(std::ostream & out) const506 void relation_manager::display_relation_sizes(std::ostream & out) const { 507 for (auto const& kv : m_relations) { 508 out << "Relation " << kv.m_key->get_name() << " has size " 509 << kv.m_value->get_size_estimate_rows() << "\n"; 510 } 511 } 512 display_output_tables(rule_set const & rules,std::ostream & out) const513 void relation_manager::display_output_tables(rule_set const& rules, std::ostream & out) const { 514 const decl_set & output_preds = rules.get_output_predicates(); 515 for (func_decl * pred : output_preds) { 516 relation_base * rel = try_get_relation(pred); 517 if (!rel) { 518 out << "Tuples in " << pred->get_name() << ": \n"; 519 continue; 520 } 521 rel->display_tuples(*pred, out); 522 } 523 } 524 525 526 // ----------------------------------- 527 // 528 // relation operations 529 // 530 // ----------------------------------- 531 532 class relation_manager::empty_signature_relation_join_fn : public relation_join_fn { 533 public: operator ()(const relation_base & r1,const relation_base & r2)534 relation_base * operator()(const relation_base & r1, const relation_base & r2) override { 535 TRACE("dl", tout << r1.get_plugin().get_name() << " " << r2.get_plugin().get_name() << "\n";); 536 if(r1.get_signature().empty()) { 537 if(r1.empty()) { 538 return r2.get_manager().mk_empty_relation(r2.get_signature(), r2.get_kind()); 539 } 540 else { 541 return r2.clone(); 542 } 543 } 544 else { 545 SASSERT(r2.get_signature().empty()); 546 if(r2.empty()) { 547 return r1.get_manager().mk_empty_relation(r1.get_signature(), r1.get_kind()); 548 } 549 else { 550 return r1.clone(); 551 } 552 } 553 } 554 }; 555 mk_join_fn(const relation_base & t1,const relation_base & t2,unsigned col_cnt,const unsigned * cols1,const unsigned * cols2,bool allow_product_relation)556 relation_join_fn * relation_manager::mk_join_fn(const relation_base & t1, const relation_base & t2, 557 unsigned col_cnt, const unsigned * cols1, const unsigned * cols2, bool allow_product_relation) { 558 relation_plugin * p1 = &t1.get_plugin(); 559 relation_plugin * p2 = &t2.get_plugin(); 560 561 relation_join_fn * res = p1->mk_join_fn(t1, t2, col_cnt, cols1, cols2); 562 563 if(!res && p1!=p2) { 564 res = p2->mk_join_fn(t1, t2, col_cnt, cols1, cols2); 565 } 566 567 if(!res && (t1.get_signature().empty() || t2.get_signature().empty())) { 568 res = alloc(empty_signature_relation_join_fn); 569 } 570 571 finite_product_relation_plugin * fprp; 572 if(!res && p1->from_table() && try_get_finite_product_relation_plugin(*p2, fprp)) { 573 //we downcast here to relation_plugin so that we don't have to declare 574 //relation_manager as a friend class of finite_product_relation_plugin 575 res = static_cast<relation_plugin *>(fprp)->mk_join_fn(t1, t2, col_cnt, cols1, cols2); 576 } 577 if(!res && p2->from_table() && try_get_finite_product_relation_plugin(*p1, fprp)) { 578 res = static_cast<relation_plugin *>(fprp)->mk_join_fn(t1, t2, col_cnt, cols1, cols2); 579 } 580 581 if(!res && allow_product_relation) { 582 relation_plugin & product_plugin = product_relation_plugin::get_plugin(*this); 583 res = product_plugin.mk_join_fn(t1, t2, col_cnt, cols1, cols2); 584 } 585 586 return res; 587 } 588 mk_project_fn(const relation_base & t,unsigned col_cnt,const unsigned * removed_cols)589 relation_transformer_fn * relation_manager::mk_project_fn(const relation_base & t, unsigned col_cnt, 590 const unsigned * removed_cols) { 591 return t.get_plugin().mk_project_fn(t, col_cnt, removed_cols); 592 } 593 594 class relation_manager::default_relation_filter_interpreted_and_project_fn : public relation_transformer_fn { 595 scoped_ptr<relation_mutator_fn> m_filter; 596 scoped_ptr<relation_transformer_fn> m_project; 597 unsigned_vector m_removed_cols; 598 public: 599 /** 600 This constructor should be used only if we know that the projection operation 601 exists for the result of the join. 602 */ default_relation_filter_interpreted_and_project_fn(relation_mutator_fn * filter,unsigned removed_col_cnt,const unsigned * removed_cols)603 default_relation_filter_interpreted_and_project_fn( 604 relation_mutator_fn* filter, 605 unsigned removed_col_cnt, 606 const unsigned * removed_cols) 607 : m_filter(filter), 608 m_project(nullptr), 609 m_removed_cols(removed_col_cnt, removed_cols) {} 610 operator ()(const relation_base & t)611 relation_base * operator()(const relation_base & t) override { 612 scoped_rel<relation_base> t1 = t.clone(); 613 (*m_filter)(*t1); 614 if( !m_project) { 615 relation_manager & rmgr = t1->get_plugin().get_manager(); 616 m_project = rmgr.mk_project_fn(*t1, m_removed_cols.size(), m_removed_cols.data()); 617 if (!m_project) { 618 throw default_exception("projection does not exist"); 619 } 620 } 621 return (*m_project)(*t1); 622 } 623 }; 624 mk_filter_interpreted_and_project_fn(const relation_base & t,app * condition,unsigned removed_col_cnt,const unsigned * removed_cols)625 relation_transformer_fn * relation_manager::mk_filter_interpreted_and_project_fn( 626 const relation_base & t, app * condition, 627 unsigned removed_col_cnt, const unsigned * removed_cols) { 628 629 relation_transformer_fn* res = 630 t.get_plugin().mk_filter_interpreted_and_project_fn( 631 t, 632 condition, 633 removed_col_cnt, 634 removed_cols); 635 636 if (!res) { 637 relation_mutator_fn* filter_fn = mk_filter_interpreted_fn(t, condition); 638 if (filter_fn) { 639 res = alloc(default_relation_filter_interpreted_and_project_fn, 640 filter_fn, 641 removed_col_cnt, 642 removed_cols); 643 } 644 } 645 return res; 646 } 647 648 class relation_manager::default_relation_apply_sequential_fn : public relation_mutator_fn { 649 ptr_vector<relation_mutator_fn> m_mutators; 650 public: default_relation_apply_sequential_fn(unsigned n,relation_mutator_fn ** mutators)651 default_relation_apply_sequential_fn(unsigned n, relation_mutator_fn ** mutators): 652 m_mutators(n, mutators) { 653 } ~default_relation_apply_sequential_fn()654 ~default_relation_apply_sequential_fn() override { 655 std::for_each(m_mutators.begin(), m_mutators.end(), delete_proc<relation_mutator_fn>()); 656 } 657 operator ()(relation_base & t)658 void operator()(relation_base& t) override { 659 for (unsigned i = 0; i < m_mutators.size(); ++i) { 660 if (t.empty()) return; 661 (*(m_mutators[i]))(t); 662 } 663 } 664 }; 665 mk_apply_sequential_fn(unsigned n,relation_mutator_fn ** mutators)666 relation_mutator_fn * relation_manager::mk_apply_sequential_fn(unsigned n, relation_mutator_fn ** mutators) { 667 return alloc(default_relation_apply_sequential_fn, n, mutators); 668 } 669 670 class relation_manager::default_relation_join_project_fn : public relation_join_fn { 671 scoped_ptr<relation_join_fn> m_join; 672 scoped_ptr<relation_transformer_fn> m_project; 673 674 unsigned_vector m_removed_cols; 675 public: 676 /** 677 This constructor should be used only if we know that the projection operation 678 exists for the result of the join. 679 */ default_relation_join_project_fn(join_fn * join,unsigned removed_col_cnt,const unsigned * removed_cols)680 default_relation_join_project_fn(join_fn * join, unsigned removed_col_cnt, 681 const unsigned * removed_cols) 682 : m_join(join), m_project(nullptr), m_removed_cols(removed_col_cnt, removed_cols) {} 683 operator ()(const relation_base & t1,const relation_base & t2)684 relation_base * operator()(const relation_base & t1, const relation_base & t2) override { 685 scoped_rel<relation_base> aux = (*m_join)(t1, t2); 686 if(!m_project) { 687 relation_manager & rmgr = aux->get_plugin().get_manager(); 688 m_project = rmgr.mk_project_fn(*aux, m_removed_cols.size(), m_removed_cols.data()); 689 if(!m_project) { 690 throw default_exception("projection does not exist"); 691 } 692 } 693 relation_base * res = (*m_project)(*aux); 694 return res; 695 } 696 }; 697 698 mk_join_project_fn(const relation_base & t1,const relation_base & t2,unsigned joined_col_cnt,const unsigned * cols1,const unsigned * cols2,unsigned removed_col_cnt,const unsigned * removed_cols,bool allow_product_relation_join)699 relation_join_fn * relation_manager::mk_join_project_fn(const relation_base & t1, const relation_base & t2, 700 unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, 701 unsigned removed_col_cnt, const unsigned * removed_cols, bool allow_product_relation_join) { 702 relation_join_fn * res = t1.get_plugin().mk_join_project_fn(t1, t2, joined_col_cnt, cols1, cols2, 703 removed_col_cnt, removed_cols); 704 if(!res && &t1.get_plugin()!=&t2.get_plugin()) { 705 res = t2.get_plugin().mk_join_project_fn(t1, t2, joined_col_cnt, cols1, cols2, removed_col_cnt, 706 removed_cols); 707 } 708 if(!res) { 709 relation_join_fn * join = mk_join_fn(t1, t2, joined_col_cnt, cols1, cols2, allow_product_relation_join); 710 if(join) { 711 res = alloc(default_relation_join_project_fn, join, removed_col_cnt, removed_cols); 712 } 713 } 714 return res; 715 716 } 717 mk_rename_fn(const relation_base & t,unsigned permutation_cycle_len,const unsigned * permutation_cycle)718 relation_transformer_fn * relation_manager::mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len, 719 const unsigned * permutation_cycle) { 720 return t.get_plugin().mk_rename_fn(t, permutation_cycle_len, permutation_cycle); 721 } 722 mk_permutation_rename_fn(const relation_base & t,const unsigned * permutation)723 relation_transformer_fn * relation_manager::mk_permutation_rename_fn(const relation_base & t, 724 const unsigned * permutation) { 725 relation_transformer_fn * res = t.get_plugin().mk_permutation_rename_fn(t, permutation); 726 if(!res) { 727 res = alloc(default_relation_permutation_rename_fn, t, permutation); 728 } 729 return res; 730 } 731 732 mk_union_fn(const relation_base & tgt,const relation_base & src,const relation_base * delta)733 relation_union_fn * relation_manager::mk_union_fn(const relation_base & tgt, const relation_base & src, 734 const relation_base * delta) { 735 relation_union_fn * res = tgt.get_plugin().mk_union_fn(tgt, src, delta); 736 if(!res && &tgt.get_plugin()!=&src.get_plugin()) { 737 res = src.get_plugin().mk_union_fn(tgt, src, delta); 738 } 739 if(!res && delta && &tgt.get_plugin()!=&delta->get_plugin() && &src.get_plugin()!=&delta->get_plugin()) { 740 res = delta->get_plugin().mk_union_fn(tgt, src, delta); 741 } 742 // TRACE("dl", tout << src.get_plugin().get_name() << " " << tgt.get_plugin().get_name() << " " << (res?"created":"not created") << "\n";); 743 return res; 744 } 745 mk_widen_fn(const relation_base & tgt,const relation_base & src,const relation_base * delta)746 relation_union_fn * relation_manager::mk_widen_fn(const relation_base & tgt, const relation_base & src, 747 const relation_base * delta) { 748 relation_union_fn * res = tgt.get_plugin().mk_widen_fn(tgt, src, delta); 749 if(!res && &tgt.get_plugin()!=&src.get_plugin()) { 750 res = src.get_plugin().mk_widen_fn(tgt, src, delta); 751 } 752 if(!res && delta && &tgt.get_plugin()!=&delta->get_plugin() && &src.get_plugin()!=&delta->get_plugin()) { 753 res = delta->get_plugin().mk_widen_fn(tgt, src, delta); 754 } 755 if(!res) { 756 res = mk_union_fn(tgt, src, delta); 757 } 758 return res; 759 } 760 mk_filter_identical_fn(const relation_base & t,unsigned col_cnt,const unsigned * identical_cols)761 relation_mutator_fn * relation_manager::mk_filter_identical_fn(const relation_base & t, unsigned col_cnt, 762 const unsigned * identical_cols) { 763 return t.get_plugin().mk_filter_identical_fn(t, col_cnt, identical_cols); 764 } 765 mk_filter_equal_fn(const relation_base & t,const relation_element & value,unsigned col)766 relation_mutator_fn * relation_manager::mk_filter_equal_fn(const relation_base & t, 767 const relation_element & value, unsigned col) { 768 769 return t.get_plugin().mk_filter_equal_fn(t, value, col); 770 } 771 mk_filter_interpreted_fn(const relation_base & t,app * condition)772 relation_mutator_fn * relation_manager::mk_filter_interpreted_fn(const relation_base & t, app * condition) { 773 return t.get_plugin().mk_filter_interpreted_fn(t, condition); 774 } 775 776 class relation_manager::default_relation_select_equal_and_project_fn : public relation_transformer_fn { 777 scoped_ptr<relation_mutator_fn> m_filter; 778 scoped_ptr<relation_transformer_fn> m_project; 779 public: default_relation_select_equal_and_project_fn(relation_mutator_fn * filter,relation_transformer_fn * project)780 default_relation_select_equal_and_project_fn(relation_mutator_fn * filter, relation_transformer_fn * project) 781 : m_filter(filter), m_project(project) {} 782 operator ()(const relation_base & t1)783 relation_base * operator()(const relation_base & t1) override { 784 TRACE("dl", tout << t1.get_plugin().get_name() << "\n";); 785 scoped_rel<relation_base> aux = t1.clone(); 786 (*m_filter)(*aux); 787 relation_base * res = (*m_project)(*aux); 788 return res; 789 } 790 }; 791 mk_select_equal_and_project_fn(const relation_base & t,const relation_element & value,unsigned col)792 relation_transformer_fn * relation_manager::mk_select_equal_and_project_fn(const relation_base & t, 793 const relation_element & value, unsigned col) { 794 relation_transformer_fn * res = t.get_plugin().mk_select_equal_and_project_fn(t, value, col); 795 if(!res) { 796 relation_mutator_fn * selector = mk_filter_equal_fn(t, value, col); 797 if(selector) { 798 relation_transformer_fn * projector = mk_project_fn(t, 1, &col); 799 if(projector) { 800 res = alloc(default_relation_select_equal_and_project_fn, selector, projector); 801 } 802 else { 803 dealloc(selector); 804 } 805 } 806 } 807 return res; 808 } 809 810 811 class relation_manager::default_relation_intersection_filter_fn : public relation_intersection_filter_fn { 812 scoped_ptr<relation_join_fn> m_join_fun; 813 scoped_ptr<relation_union_fn> m_union_fun; 814 public: 815 default_relation_intersection_filter_fn(relation_join_fn * join_fun,relation_union_fn * union_fun)816 default_relation_intersection_filter_fn(relation_join_fn * join_fun, relation_union_fn * union_fun) 817 : m_join_fun(join_fun), m_union_fun(union_fun) {} 818 operator ()(relation_base & tgt,const relation_base & intersected_obj)819 void operator()(relation_base & tgt, const relation_base & intersected_obj) override { 820 scoped_rel<relation_base> filtered_rel = (*m_join_fun)(tgt, intersected_obj); 821 TRACE("dl", 822 tgt.display(tout << "tgt:\n"); 823 intersected_obj.display(tout << "intersected:\n"); 824 filtered_rel->display(tout << "filtered:\n"); 825 ); 826 if(!m_union_fun) { 827 SASSERT(tgt.can_swap(*filtered_rel)); 828 tgt.swap(*filtered_rel); 829 } 830 tgt.reset(); 831 TRACE("dl", tgt.display(tout << "target reset:\n"); ); 832 (*m_union_fun)(tgt, *filtered_rel); 833 TRACE("dl", tgt.display(tout << "intersected target:\n"); ); 834 } 835 836 }; 837 try_mk_default_filter_by_intersection_fn(const relation_base & tgt,const relation_base & src,unsigned joined_col_cnt,const unsigned * tgt_cols,const unsigned * src_cols)838 relation_intersection_filter_fn * relation_manager::try_mk_default_filter_by_intersection_fn( 839 const relation_base & tgt, const relation_base & src, unsigned joined_col_cnt, 840 const unsigned * tgt_cols, const unsigned * src_cols) { 841 TRACE("dl_verbose", tout << tgt.get_plugin().get_name() << "\n";); 842 unsigned_vector join_removed_cols; 843 add_sequence(tgt.get_signature().size(), src.get_signature().size(), join_removed_cols); 844 scoped_rel<relation_join_fn> join_fun = mk_join_project_fn(tgt, src, joined_col_cnt, tgt_cols, src_cols, 845 join_removed_cols.size(), join_removed_cols.data(), false); 846 if(!join_fun) { 847 return nullptr; 848 } 849 //we perform the join operation here to see what the result is 850 scoped_rel<relation_base> join_res = (*join_fun)(tgt, src); 851 if(tgt.can_swap(*join_res)) { 852 return alloc(default_relation_intersection_filter_fn, join_fun.release(), nullptr); 853 } 854 if(join_res->get_plugin().is_product_relation()) { 855 //we cannot have the product relation here, since it uses the intersection operation 856 //for unions and therefore we would get into an infinite recursion 857 return nullptr; 858 } 859 scoped_rel<relation_union_fn> union_fun = mk_union_fn(tgt, *join_res); 860 if(!union_fun) { 861 return nullptr; 862 } 863 return alloc(default_relation_intersection_filter_fn, join_fun.release(), union_fun.release()); 864 } 865 866 mk_filter_by_intersection_fn(const relation_base & t,const relation_base & src,unsigned joined_col_cnt,const unsigned * t_cols,const unsigned * src_cols)867 relation_intersection_filter_fn * relation_manager::mk_filter_by_intersection_fn(const relation_base & t, 868 const relation_base & src, unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * src_cols) { 869 TRACE("dl_verbose", tout << t.get_plugin().get_name() << "\n";); 870 relation_intersection_filter_fn * res = t.get_plugin().mk_filter_by_intersection_fn(t, src, joined_col_cnt, 871 t_cols, src_cols); 872 if(!res && &t.get_plugin()!=&src.get_plugin()) { 873 res = src.get_plugin().mk_filter_by_intersection_fn(t, src, joined_col_cnt, t_cols, src_cols); 874 } 875 if(!res) { 876 res = try_mk_default_filter_by_intersection_fn(t, src, joined_col_cnt, t_cols, src_cols); 877 } 878 return res; 879 } 880 mk_filter_by_intersection_fn(const relation_base & tgt,const relation_base & src)881 relation_intersection_filter_fn * relation_manager::mk_filter_by_intersection_fn(const relation_base & tgt, 882 const relation_base & src) { 883 TRACE("dl_verbose", tout << tgt.get_plugin().get_name() << "\n";); 884 SASSERT(tgt.get_signature()==src.get_signature()); 885 unsigned sz = tgt.get_signature().size(); 886 unsigned_vector cols; 887 add_sequence(0, sz, cols); 888 return mk_filter_by_intersection_fn(tgt, src, cols, cols); 889 } 890 891 mk_filter_by_negation_fn(const relation_base & t,const relation_base & negated_obj,unsigned joined_col_cnt,const unsigned * t_cols,const unsigned * negated_cols)892 relation_intersection_filter_fn * relation_manager::mk_filter_by_negation_fn(const relation_base & t, 893 const relation_base & negated_obj, unsigned joined_col_cnt, 894 const unsigned * t_cols, const unsigned * negated_cols) { 895 TRACE("dl", tout << t.get_plugin().get_name() << "\n";); 896 relation_intersection_filter_fn * res = t.get_plugin().mk_filter_by_negation_fn(t, negated_obj, joined_col_cnt, 897 t_cols, negated_cols); 898 if(!res && &t.get_plugin()!=&negated_obj.get_plugin()) { 899 res = negated_obj.get_plugin().mk_filter_by_negation_fn(t, negated_obj, joined_col_cnt, t_cols, 900 negated_cols); 901 } 902 return res; 903 } 904 905 906 907 908 909 // ----------------------------------- 910 // 911 // table operations 912 // 913 // ----------------------------------- 914 915 class relation_manager::default_table_join_fn : public convenient_table_join_fn { 916 unsigned m_col_cnt; 917 public: default_table_join_fn(const table_signature & t1_sig,const table_signature & t2_sig,unsigned col_cnt,const unsigned * cols1,const unsigned * cols2)918 default_table_join_fn(const table_signature & t1_sig, const table_signature & t2_sig, unsigned col_cnt, 919 const unsigned * cols1, const unsigned * cols2) 920 : convenient_table_join_fn(t1_sig, t2_sig, col_cnt, cols1, cols2), m_col_cnt(col_cnt) {} 921 operator ()(const table_base & t1,const table_base & t2)922 table_base * operator()(const table_base & t1, const table_base & t2) override { 923 table_plugin * plugin = &t1.get_plugin(); 924 925 const table_signature & res_sign = get_result_signature(); 926 if (!plugin->can_handle_signature(res_sign)) { 927 plugin = &t2.get_plugin(); 928 if (!plugin->can_handle_signature(res_sign)) { 929 plugin = &t1.get_manager().get_appropriate_plugin(res_sign); 930 } 931 } 932 SASSERT(plugin->can_handle_signature(res_sign)); 933 table_base * res = plugin->mk_empty(res_sign); 934 935 unsigned t1cols = t1.get_signature().size(); 936 unsigned t2cols = t2.get_signature().size(); 937 unsigned t1first_func = t1.get_signature().first_functional(); 938 unsigned t2first_func = t2.get_signature().first_functional(); 939 940 table_base::iterator els1it = t1.begin(); 941 table_base::iterator els1end = t1.end(); 942 table_base::iterator els2end = t2.end(); 943 944 table_fact acc; 945 946 for(; els1it!=els1end; ++els1it) { 947 const table_base::row_interface & row1 = *els1it; 948 949 table_base::iterator els2it = t2.begin(); 950 for(; els2it!=els2end; ++els2it) { 951 const table_base::row_interface & row2 = *els2it; 952 953 bool match=true; 954 for(unsigned i=0; i<m_col_cnt; i++) { 955 if(row1[m_cols1[i]]!=row2[m_cols2[i]]) { 956 match=false; 957 break; 958 } 959 } 960 if(!match) { 961 continue; 962 } 963 964 acc.reset(); 965 for(unsigned i=0; i<t1first_func; i++) { 966 acc.push_back(row1[i]); 967 } 968 for(unsigned i=0; i<t2first_func; i++) { 969 acc.push_back(row2[i]); 970 } 971 for(unsigned i=t1first_func; i<t1cols; i++) { 972 acc.push_back(row1[i]); 973 } 974 for(unsigned i=t2first_func; i<t2cols; i++) { 975 acc.push_back(row2[i]); 976 } 977 res->add_fact(acc); 978 } 979 } 980 return res; 981 } 982 }; 983 mk_join_fn(const table_base & t1,const table_base & t2,unsigned col_cnt,const unsigned * cols1,const unsigned * cols2)984 table_join_fn * relation_manager::mk_join_fn(const table_base & t1, const table_base & t2, 985 unsigned col_cnt, const unsigned * cols1, const unsigned * cols2) { 986 table_join_fn * res = t1.get_plugin().mk_join_fn(t1, t2, col_cnt, cols1, cols2); 987 if(!res && &t1.get_plugin()!=&t2.get_plugin()) { 988 res = t2.get_plugin().mk_join_fn(t1, t2, col_cnt, cols1, cols2); 989 } 990 if(!res) { 991 table_signature sig; 992 table_signature::from_join(t1.get_signature(), t2.get_signature(), 993 col_cnt, cols1, cols2, sig); 994 res = alloc(default_table_join_fn, t1.get_signature(), t2.get_signature(), col_cnt, cols1, cols2); 995 } 996 return res; 997 } 998 999 class relation_manager::auxiliary_table_transformer_fn { 1000 table_fact m_row; 1001 public: ~auxiliary_table_transformer_fn()1002 virtual ~auxiliary_table_transformer_fn() {} 1003 virtual const table_signature & get_result_signature() const = 0; 1004 virtual void modify_fact(table_fact & f) const = 0; 1005 operator ()(const table_base & t)1006 table_base * operator()(const table_base & t) { 1007 table_plugin & plugin = t.get_plugin(); 1008 const table_signature & res_sign = get_result_signature(); 1009 SASSERT(plugin.can_handle_signature(res_sign)); 1010 table_base * res = plugin.mk_empty(res_sign); 1011 1012 for (table_base::row_interface& a : t) { 1013 a.get_fact(m_row); 1014 modify_fact(m_row); 1015 res->add_fact(m_row); 1016 } 1017 return res; 1018 } 1019 }; 1020 1021 class relation_manager::default_table_project_fn 1022 : public convenient_table_project_fn, auxiliary_table_transformer_fn { 1023 public: default_table_project_fn(const table_signature & orig_sig,unsigned removed_col_cnt,const unsigned * removed_cols)1024 default_table_project_fn(const table_signature & orig_sig, unsigned removed_col_cnt, 1025 const unsigned * removed_cols) 1026 : convenient_table_project_fn(orig_sig, removed_col_cnt, removed_cols) { 1027 SASSERT(removed_col_cnt>0); 1028 } 1029 get_result_signature() const1030 const table_signature & get_result_signature() const override { 1031 return convenient_table_project_fn::get_result_signature(); 1032 } 1033 modify_fact(table_fact & f) const1034 void modify_fact(table_fact & f) const override { 1035 project_out_vector_columns(f, m_removed_cols); 1036 } 1037 operator ()(const table_base & t)1038 table_base * operator()(const table_base & t) override { 1039 return auxiliary_table_transformer_fn::operator()(t); 1040 } 1041 }; 1042 1043 class relation_manager::null_signature_table_project_fn : public table_transformer_fn { 1044 const table_signature m_empty_sig; 1045 public: null_signature_table_project_fn()1046 null_signature_table_project_fn() : m_empty_sig() {} operator ()(const table_base & t)1047 table_base * operator()(const table_base & t) override { 1048 relation_manager & m = t.get_plugin().get_manager(); 1049 table_base * res = m.mk_empty_table(m_empty_sig); 1050 if(!t.empty()) { 1051 table_fact el; 1052 res->add_fact(el); 1053 } 1054 return res; 1055 } 1056 }; 1057 1058 1059 mk_project_fn(const table_base & t,unsigned col_cnt,const unsigned * removed_cols)1060 table_transformer_fn * relation_manager::mk_project_fn(const table_base & t, unsigned col_cnt, 1061 const unsigned * removed_cols) { 1062 table_transformer_fn * res = t.get_plugin().mk_project_fn(t, col_cnt, removed_cols); 1063 if(!res && col_cnt==t.get_signature().size()) { 1064 //all columns are projected out 1065 res = alloc(null_signature_table_project_fn); 1066 } 1067 if(!res) { 1068 res = alloc(default_table_project_fn, t.get_signature(), col_cnt, removed_cols); 1069 } 1070 return res; 1071 } 1072 1073 1074 class relation_manager::default_table_join_project_fn : public convenient_table_join_project_fn { 1075 scoped_ptr<table_join_fn> m_join; 1076 scoped_ptr<table_transformer_fn> m_project; 1077 1078 unsigned_vector m_removed_cols; 1079 public: default_table_join_project_fn(join_fn * join,const table_base & t1,const table_base & t2,unsigned joined_col_cnt,const unsigned * cols1,const unsigned * cols2,unsigned removed_col_cnt,const unsigned * removed_cols)1080 default_table_join_project_fn(join_fn * join, const table_base & t1, const table_base & t2, 1081 unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, unsigned removed_col_cnt, 1082 const unsigned * removed_cols) 1083 : convenient_table_join_project_fn(t1.get_signature(), t2.get_signature(), joined_col_cnt, cols1, 1084 cols2, removed_col_cnt, removed_cols), 1085 m_join(join), 1086 m_removed_cols(removed_col_cnt, removed_cols) {} 1087 1088 class unreachable_reducer : public table_row_pair_reduce_fn { operator ()(table_element * func_columns,const table_element * merged_func_columns)1089 void operator()(table_element * func_columns, const table_element * merged_func_columns) override { 1090 //we do project_with_reduce only if we are sure there will be no reductions 1091 //(see code of the table_signature::from_join_project function) 1092 UNREACHABLE(); 1093 } 1094 }; 1095 operator ()(const table_base & t1,const table_base & t2)1096 table_base * operator()(const table_base & t1, const table_base & t2) override { 1097 table_base * aux = (*m_join)(t1, t2); 1098 if(m_project==0) { 1099 relation_manager & rmgr = aux->get_plugin().get_manager(); 1100 if(get_result_signature().functional_columns()!=0) { 1101 //to preserve functional columns we need to do the project_with_reduction 1102 unreachable_reducer * reducer = alloc(unreachable_reducer); 1103 m_project = rmgr.mk_project_with_reduce_fn(*aux, m_removed_cols.size(), m_removed_cols.data(), reducer); 1104 } 1105 else { 1106 m_project = rmgr.mk_project_fn(*aux, m_removed_cols); 1107 } 1108 if(!m_project) { 1109 throw default_exception("projection for table does not exist"); 1110 } 1111 } 1112 table_base * res = (*m_project)(*aux); 1113 aux->deallocate(); 1114 return res; 1115 } 1116 }; 1117 mk_join_project_fn(const table_base & t1,const table_base & t2,unsigned joined_col_cnt,const unsigned * cols1,const unsigned * cols2,unsigned removed_col_cnt,const unsigned * removed_cols)1118 table_join_fn * relation_manager::mk_join_project_fn(const table_base & t1, const table_base & t2, 1119 unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, 1120 unsigned removed_col_cnt, const unsigned * removed_cols) { 1121 table_join_fn * res = t1.get_plugin().mk_join_project_fn(t1, t2, joined_col_cnt, cols1, cols2, 1122 removed_col_cnt, removed_cols); 1123 if(!res && &t1.get_plugin()!=&t2.get_plugin()) { 1124 res = t2.get_plugin().mk_join_project_fn(t1, t2, joined_col_cnt, cols1, cols2, removed_col_cnt, 1125 removed_cols); 1126 } 1127 if(!res) { 1128 table_join_fn * join = mk_join_fn(t1, t2, joined_col_cnt, cols1, cols2); 1129 if(join) { 1130 res = alloc(default_table_join_project_fn, join, t1, t2, joined_col_cnt, cols1, cols2, 1131 removed_col_cnt, removed_cols); 1132 } 1133 } 1134 return res; 1135 1136 } 1137 1138 class relation_manager::default_table_rename_fn 1139 : public convenient_table_rename_fn, auxiliary_table_transformer_fn { 1140 public: default_table_rename_fn(const table_signature & orig_sig,unsigned permutation_cycle_len,const unsigned * permutation_cycle)1141 default_table_rename_fn(const table_signature & orig_sig, unsigned permutation_cycle_len, 1142 const unsigned * permutation_cycle) 1143 : convenient_table_rename_fn(orig_sig, permutation_cycle_len, permutation_cycle) { 1144 SASSERT(permutation_cycle_len>=2); 1145 } 1146 get_result_signature() const1147 const table_signature & get_result_signature() const override { 1148 return convenient_table_rename_fn::get_result_signature(); 1149 } 1150 modify_fact(table_fact & f) const1151 void modify_fact(table_fact & f) const override { 1152 permutate_by_cycle(f, m_cycle); 1153 } 1154 operator ()(const table_base & t)1155 table_base * operator()(const table_base & t) override { 1156 return auxiliary_table_transformer_fn::operator()(t); 1157 } 1158 1159 }; 1160 mk_rename_fn(const table_base & t,unsigned permutation_cycle_len,const unsigned * permutation_cycle)1161 table_transformer_fn * relation_manager::mk_rename_fn(const table_base & t, unsigned permutation_cycle_len, 1162 const unsigned * permutation_cycle) { 1163 table_transformer_fn * res = t.get_plugin().mk_rename_fn(t, permutation_cycle_len, permutation_cycle); 1164 if(!res) { 1165 res = alloc(default_table_rename_fn, t.get_signature(), permutation_cycle_len, permutation_cycle); 1166 } 1167 return res; 1168 } 1169 mk_permutation_rename_fn(const table_base & t,const unsigned * permutation)1170 table_transformer_fn * relation_manager::mk_permutation_rename_fn(const table_base & t, 1171 const unsigned * permutation) { 1172 table_transformer_fn * res = t.get_plugin().mk_permutation_rename_fn(t, permutation); 1173 if(!res) { 1174 res = alloc(default_table_permutation_rename_fn, t, permutation); 1175 } 1176 return res; 1177 } 1178 1179 1180 class relation_manager::default_table_union_fn : public table_union_fn { 1181 table_fact m_row; 1182 public: operator ()(table_base & tgt,const table_base & src,table_base * delta)1183 void operator()(table_base & tgt, const table_base & src, table_base * delta) override { 1184 for (table_base::row_interface& a : src) { 1185 a.get_fact(m_row); 1186 1187 if (delta) { 1188 if(!tgt.contains_fact(m_row)) { 1189 tgt.add_new_fact(m_row); 1190 delta->add_fact(m_row); 1191 } 1192 } 1193 else { 1194 //if there's no delta, we don't need to know whether we are actually adding a new fact 1195 tgt.add_fact(m_row); 1196 } 1197 } 1198 } 1199 }; 1200 mk_union_fn(const table_base & tgt,const table_base & src,const table_base * delta)1201 table_union_fn * relation_manager::mk_union_fn(const table_base & tgt, const table_base & src, 1202 const table_base * delta) { 1203 table_union_fn * res = tgt.get_plugin().mk_union_fn(tgt, src, delta); 1204 if(!res && &tgt.get_plugin()!=&src.get_plugin()) { 1205 res = src.get_plugin().mk_union_fn(tgt, src, delta); 1206 } 1207 if(!res && delta && &tgt.get_plugin()!=&delta->get_plugin() && &src.get_plugin()!=&delta->get_plugin()) { 1208 res = delta->get_plugin().mk_union_fn(tgt, src, delta); 1209 } 1210 if(!res) { 1211 res = alloc(default_table_union_fn); 1212 } 1213 return res; 1214 } 1215 mk_widen_fn(const table_base & tgt,const table_base & src,const table_base * delta)1216 table_union_fn * relation_manager::mk_widen_fn(const table_base & tgt, const table_base & src, 1217 const table_base * delta) { 1218 table_union_fn * res = tgt.get_plugin().mk_widen_fn(tgt, src, delta); 1219 if(!res && &tgt.get_plugin()!=&src.get_plugin()) { 1220 res = src.get_plugin().mk_widen_fn(tgt, src, delta); 1221 } 1222 if(!res && delta && &tgt.get_plugin()!=&delta->get_plugin() && &src.get_plugin()!=&delta->get_plugin()) { 1223 res = delta->get_plugin().mk_widen_fn(tgt, src, delta); 1224 } 1225 if(!res) { 1226 res = mk_union_fn(tgt, src, delta); 1227 } 1228 return res; 1229 } 1230 1231 1232 /** 1233 An auixiliary class for functors that perform filtering. It performs the table traversal 1234 and only asks for each individual row whether it should be removed. 1235 1236 When using this class in multiple inheritance, this class should not be inherited publicly 1237 and should be mentioned as last. This should ensure that deteletion of the object will 1238 go well when initiated from a pointer to the first ancestor. 1239 */ 1240 class relation_manager::auxiliary_table_filter_fn { 1241 table_fact m_row; 1242 svector<table_element> m_to_remove; 1243 public: ~auxiliary_table_filter_fn()1244 virtual ~auxiliary_table_filter_fn() {} 1245 virtual bool should_remove(const table_fact & f) const = 0; 1246 operator ()(table_base & r)1247 void operator()(table_base & r) { 1248 m_to_remove.reset(); 1249 unsigned sz = 0; 1250 for (table_base::row_interface& a : r) { 1251 a.get_fact(m_row); 1252 if (should_remove(m_row)) { 1253 m_to_remove.append(m_row.size(), m_row.data()); 1254 ++sz; 1255 } 1256 } 1257 r.remove_facts(sz, m_to_remove.data()); 1258 } 1259 }; 1260 1261 class relation_manager::default_table_filter_identical_fn : public table_mutator_fn, auxiliary_table_filter_fn { 1262 const unsigned m_col_cnt; 1263 const unsigned_vector m_identical_cols; 1264 public: default_table_filter_identical_fn(unsigned col_cnt,const unsigned * identical_cols)1265 default_table_filter_identical_fn(unsigned col_cnt, const unsigned * identical_cols) 1266 : m_col_cnt(col_cnt), 1267 m_identical_cols(col_cnt, identical_cols) { 1268 SASSERT(col_cnt>=2); 1269 } 1270 should_remove(const table_fact & f) const1271 bool should_remove(const table_fact & f) const override { 1272 table_element val=f[m_identical_cols[0]]; 1273 for(unsigned i=1; i<m_col_cnt; i++) { 1274 if(f[m_identical_cols[i]]!=val) { 1275 return true; 1276 } 1277 } 1278 return false; 1279 } 1280 operator ()(table_base & t)1281 void operator()(table_base & t) override { 1282 auxiliary_table_filter_fn::operator()(t); 1283 } 1284 1285 }; 1286 mk_filter_identical_fn(const table_base & t,unsigned col_cnt,const unsigned * identical_cols)1287 table_mutator_fn * relation_manager::mk_filter_identical_fn(const table_base & t, unsigned col_cnt, 1288 const unsigned * identical_cols) { 1289 table_mutator_fn * res = t.get_plugin().mk_filter_identical_fn(t, col_cnt, identical_cols); 1290 if(!res) { 1291 res = alloc(default_table_filter_identical_fn, col_cnt, identical_cols); 1292 } 1293 return res; 1294 } 1295 1296 1297 1298 class relation_manager::default_table_filter_equal_fn : public table_mutator_fn, auxiliary_table_filter_fn { 1299 const table_element m_value; 1300 const unsigned m_col; 1301 public: default_table_filter_equal_fn(const table_element & value,unsigned col)1302 default_table_filter_equal_fn(const table_element & value, unsigned col) 1303 : m_value(value), 1304 m_col(col) {} 1305 should_remove(const table_fact & f) const1306 bool should_remove(const table_fact & f) const override { 1307 return f[m_col]!=m_value; 1308 } 1309 operator ()(table_base & t)1310 void operator()(table_base & t) override { 1311 auxiliary_table_filter_fn::operator()(t); 1312 } 1313 }; 1314 mk_filter_equal_fn(const table_base & t,const table_element & value,unsigned col)1315 table_mutator_fn * relation_manager::mk_filter_equal_fn(const table_base & t, 1316 const table_element & value, unsigned col) { 1317 table_mutator_fn * res = t.get_plugin().mk_filter_equal_fn(t, value, col); 1318 if(!res) { 1319 res = alloc(default_table_filter_equal_fn, value, col); 1320 } 1321 return res; 1322 } 1323 1324 class relation_manager::default_table_filter_not_equal_fn 1325 : public table_mutator_fn, auxiliary_table_filter_fn { 1326 unsigned m_column; 1327 uint64_t m_value; 1328 public: default_table_filter_not_equal_fn(context & ctx,unsigned column,uint64_t value)1329 default_table_filter_not_equal_fn(context & ctx, unsigned column, uint64_t value) 1330 : m_column(column), 1331 m_value(value) { 1332 } 1333 should_remove(const table_fact & f) const1334 bool should_remove(const table_fact & f) const override { 1335 return f[m_column] == m_value; 1336 } 1337 operator ()(table_base & t)1338 void operator()(table_base & t) override { 1339 auxiliary_table_filter_fn::operator()(t); 1340 } 1341 mk(context & ctx,expr * condition)1342 static table_mutator_fn* mk(context& ctx, expr* condition) { 1343 ast_manager& m = ctx.get_manager(); 1344 if (!m.is_not(condition)) { 1345 return nullptr; 1346 } 1347 condition = to_app(condition)->get_arg(0); 1348 if (!m.is_eq(condition)) { 1349 return nullptr; 1350 } 1351 expr* x = to_app(condition)->get_arg(0); 1352 expr* y = to_app(condition)->get_arg(1); 1353 if (!is_var(x)) { 1354 std::swap(x, y); 1355 } 1356 if (!is_var(x)) { 1357 return nullptr; 1358 } 1359 dl_decl_util decl_util(m); 1360 uint64_t value = 0; 1361 if (!decl_util.is_numeral_ext(y, value)) { 1362 return nullptr; 1363 } 1364 return alloc(default_table_filter_not_equal_fn, ctx, to_var(x)->get_idx(), value); 1365 } 1366 }; 1367 1368 1369 1370 class relation_manager::default_table_filter_interpreted_fn 1371 : public table_mutator_fn, auxiliary_table_filter_fn { 1372 ast_manager & m_ast_manager; 1373 var_subst & m_vs; 1374 dl_decl_util & m_decl_util; 1375 th_rewriter & m_simp; 1376 app_ref m_condition; 1377 expr_free_vars m_free_vars; 1378 mutable expr_ref_vector m_args; 1379 public: default_table_filter_interpreted_fn(context & ctx,unsigned col_cnt,app * condition)1380 default_table_filter_interpreted_fn(context & ctx, unsigned col_cnt, app* condition) 1381 : m_ast_manager(ctx.get_manager()), 1382 m_vs(ctx.get_var_subst()), 1383 m_decl_util(ctx.get_decl_util()), 1384 m_simp(ctx.get_rewriter()), 1385 m_condition(condition, ctx.get_manager()), 1386 m_args(ctx.get_manager()) { 1387 m_free_vars(m_condition); 1388 } 1389 should_remove(const table_fact & f) const1390 bool should_remove(const table_fact & f) const override { 1391 expr_ref_vector& args = m_args; 1392 1393 args.reset(); 1394 //arguments need to be in reverse order for the substitution 1395 unsigned col_cnt = f.size(); 1396 for(int i = col_cnt; i-- > 0;) { 1397 if (!m_free_vars.contains(i)) { 1398 args.push_back(nullptr); 1399 continue; //this variable does not occur in the condition; 1400 } 1401 1402 table_element el = f[i]; 1403 args.push_back(m_decl_util.mk_numeral(el, m_free_vars[i])); 1404 } 1405 1406 expr_ref ground = m_vs(m_condition.get(), args); 1407 m_simp(ground); 1408 1409 return m_ast_manager.is_false(ground); 1410 } 1411 operator ()(table_base & t)1412 void operator()(table_base & t) override { 1413 auxiliary_table_filter_fn::operator()(t); 1414 } 1415 }; 1416 mk_filter_interpreted_fn(const table_base & t,app * condition)1417 table_mutator_fn * relation_manager::mk_filter_interpreted_fn(const table_base & t, app * condition) { 1418 context & ctx = get_context(); 1419 table_mutator_fn * res = t.get_plugin().mk_filter_interpreted_fn(t, condition); 1420 if (!res) { 1421 res = default_table_filter_not_equal_fn::mk(ctx, condition); 1422 } 1423 if(!res) { 1424 res = alloc(default_table_filter_interpreted_fn, ctx, t.get_signature().size(), condition); 1425 } 1426 return res; 1427 } 1428 1429 1430 class relation_manager::default_table_filter_interpreted_and_project_fn 1431 : public table_transformer_fn { 1432 scoped_ptr<table_mutator_fn> m_filter; 1433 scoped_ptr<table_transformer_fn> m_project; 1434 app_ref m_condition; 1435 unsigned_vector m_removed_cols; 1436 public: default_table_filter_interpreted_and_project_fn(context & ctx,table_mutator_fn * filter,app * condition,unsigned removed_col_cnt,const unsigned * removed_cols)1437 default_table_filter_interpreted_and_project_fn(context & ctx, table_mutator_fn * filter, 1438 app * condition, unsigned removed_col_cnt, const unsigned * removed_cols) 1439 : m_filter(filter), m_condition(condition, ctx.get_manager()), 1440 m_removed_cols(removed_col_cnt, removed_cols) {} 1441 operator ()(const table_base & tb)1442 table_base* operator()(const table_base & tb) override { 1443 scoped_rel<table_base> t2 = tb.clone(); 1444 (*m_filter)(*t2); 1445 if (!m_project) { 1446 relation_manager & rmgr = t2->get_plugin().get_manager(); 1447 m_project = rmgr.mk_project_fn(*t2, m_removed_cols.size(), m_removed_cols.data()); 1448 if (!m_project) { 1449 throw default_exception("projection does not exist"); 1450 } 1451 } 1452 return (*m_project)(*t2); 1453 } 1454 }; 1455 mk_filter_interpreted_and_project_fn(const table_base & t,app * condition,unsigned removed_col_cnt,const unsigned * removed_cols)1456 table_transformer_fn * relation_manager::mk_filter_interpreted_and_project_fn(const table_base & t, 1457 app * condition, unsigned removed_col_cnt, const unsigned * removed_cols) { 1458 table_transformer_fn * res = t.get_plugin().mk_filter_interpreted_and_project_fn(t, condition, removed_col_cnt, removed_cols); 1459 if (res) 1460 return res; 1461 1462 table_mutator_fn * filter = mk_filter_interpreted_fn(t, condition); 1463 SASSERT(filter); 1464 res = alloc(default_table_filter_interpreted_and_project_fn, get_context(), filter, condition, removed_col_cnt, removed_cols); 1465 return res; 1466 } 1467 1468 mk_filter_by_intersection_fn(const table_base & t,const table_base & src,unsigned joined_col_cnt,const unsigned * t_cols,const unsigned * src_cols)1469 table_intersection_filter_fn * relation_manager::mk_filter_by_intersection_fn(const table_base & t, 1470 const table_base & src, unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * src_cols) { 1471 table_intersection_filter_fn * res = t.get_plugin().mk_filter_by_negation_fn(t, src, joined_col_cnt, 1472 t_cols, src_cols); 1473 if(!res && &t.get_plugin()!=&src.get_plugin()) { 1474 res = src.get_plugin().mk_filter_by_negation_fn(t, src, joined_col_cnt, t_cols, src_cols); 1475 } 1476 return res; 1477 } 1478 1479 1480 1481 class relation_manager::default_table_negation_filter_fn : public convenient_table_negation_filter_fn, 1482 auxiliary_table_filter_fn { 1483 const table_base * m_negated_table; 1484 mutable table_fact m_aux_fact; 1485 public: default_table_negation_filter_fn(const table_base & tgt,const table_base & neg_t,unsigned joined_col_cnt,const unsigned * t_cols,const unsigned * negated_cols)1486 default_table_negation_filter_fn(const table_base & tgt, const table_base & neg_t, 1487 unsigned joined_col_cnt, const unsigned * t_cols, const unsigned * negated_cols) 1488 : convenient_table_negation_filter_fn(tgt, neg_t, joined_col_cnt, t_cols, negated_cols), 1489 m_negated_table(nullptr) { 1490 m_aux_fact.resize(neg_t.get_signature().size()); 1491 } 1492 should_remove(const table_fact & f) const1493 bool should_remove(const table_fact & f) const override { 1494 if(!m_all_neg_bound || m_overlap) { 1495 table_base::iterator nit = m_negated_table->begin(); 1496 table_base::iterator nend = m_negated_table->end(); 1497 for(; nit!=nend; ++nit) { 1498 const table_base::row_interface & nrow = *nit; 1499 if(bindings_match(nrow, f)) { 1500 return true; 1501 } 1502 } 1503 return false; 1504 } 1505 else { 1506 make_neg_bindings<datalog::table_fact>(m_aux_fact, f); 1507 return m_negated_table->contains_fact(m_aux_fact); 1508 } 1509 } 1510 operator ()(table_base & tgt,const table_base & negated_table)1511 void operator()(table_base & tgt, const table_base & negated_table) override { 1512 SASSERT(m_negated_table==0); 1513 flet<const table_base *> flet_neg_table(m_negated_table, &negated_table); 1514 auxiliary_table_filter_fn::operator()(tgt); 1515 } 1516 1517 }; 1518 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)1519 table_intersection_filter_fn * relation_manager::mk_filter_by_negation_fn(const table_base & t, 1520 const table_base & negated_obj, unsigned joined_col_cnt, 1521 const unsigned * t_cols, const unsigned * negated_cols) { 1522 table_intersection_filter_fn * res = t.get_plugin().mk_filter_by_negation_fn(t, negated_obj, joined_col_cnt, 1523 t_cols, negated_cols); 1524 if(!res && &t.get_plugin()!=&negated_obj.get_plugin()) { 1525 res = negated_obj.get_plugin().mk_filter_by_negation_fn(t, negated_obj, joined_col_cnt, t_cols, 1526 negated_cols); 1527 } 1528 if(!res) { 1529 res = alloc(default_table_negation_filter_fn, t, negated_obj, joined_col_cnt, t_cols, negated_cols); 1530 } 1531 return res; 1532 } 1533 1534 mk_filter_by_negated_join_fn(const table_base & t,const table_base & src1,const table_base & src2,unsigned_vector const & t_cols,unsigned_vector const & src_cols,unsigned_vector const & src1_cols,unsigned_vector const & src2_cols)1535 table_intersection_join_filter_fn* relation_manager::mk_filter_by_negated_join_fn( 1536 const table_base & t, 1537 const table_base & src1, 1538 const table_base & src2, 1539 unsigned_vector const& t_cols, 1540 unsigned_vector const& src_cols, 1541 unsigned_vector const& src1_cols, 1542 unsigned_vector const& src2_cols) { 1543 return t.get_plugin().mk_filter_by_negated_join_fn(t, src1, src2, t_cols, src_cols, src1_cols, src2_cols); 1544 } 1545 1546 1547 1548 class relation_manager::default_table_select_equal_and_project_fn : public table_transformer_fn { 1549 scoped_ptr<table_mutator_fn> m_filter; 1550 scoped_ptr<table_transformer_fn> m_project; 1551 public: default_table_select_equal_and_project_fn(table_mutator_fn * filter,table_transformer_fn * project)1552 default_table_select_equal_and_project_fn(table_mutator_fn * filter, table_transformer_fn * project) 1553 : m_filter(filter), m_project(project) {} 1554 operator ()(const table_base & t1)1555 table_base * operator()(const table_base & t1) override { 1556 TRACE("dl", tout << t1.get_plugin().get_name() << "\n";); 1557 scoped_rel<table_base> aux = t1.clone(); 1558 (*m_filter)(*aux); 1559 return (*m_project)(*aux); 1560 } 1561 }; 1562 mk_select_equal_and_project_fn(const table_base & t,const table_element & value,unsigned col)1563 table_transformer_fn * relation_manager::mk_select_equal_and_project_fn(const table_base & t, 1564 const table_element & value, unsigned col) { 1565 table_transformer_fn * res = t.get_plugin().mk_select_equal_and_project_fn(t, value, col); 1566 if(!res) { 1567 table_mutator_fn * selector = mk_filter_equal_fn(t, value, col); 1568 SASSERT(selector); 1569 table_transformer_fn * projector = mk_project_fn(t, 1, &col); 1570 SASSERT(projector); 1571 res = alloc(default_table_select_equal_and_project_fn, selector, projector); 1572 } 1573 return res; 1574 } 1575 1576 1577 class relation_manager::default_table_map_fn : public table_mutator_fn { 1578 scoped_ptr<table_row_mutator_fn> m_mapper; 1579 unsigned m_first_functional; 1580 scoped_rel<table_base> m_aux_table; 1581 scoped_ptr<table_union_fn> m_union_fn; 1582 table_fact m_curr_fact; 1583 public: default_table_map_fn(const table_base & t,table_row_mutator_fn * mapper)1584 default_table_map_fn(const table_base & t, table_row_mutator_fn * mapper) 1585 : m_mapper(mapper), m_first_functional(t.get_signature().first_functional()) { 1586 SASSERT(t.get_signature().functional_columns()>0); 1587 table_plugin & plugin = t.get_plugin(); 1588 m_aux_table = plugin.mk_empty(t.get_signature()); 1589 m_union_fn = plugin.mk_union_fn(t, *m_aux_table, static_cast<table_base *>(nullptr)); 1590 } 1591 ~default_table_map_fn()1592 ~default_table_map_fn() override {} 1593 operator ()(table_base & t)1594 void operator()(table_base & t) override { 1595 SASSERT(t.get_signature()==m_aux_table->get_signature()); 1596 if(!m_aux_table->empty()) { 1597 m_aux_table->reset(); 1598 } 1599 1600 for (table_base::row_interface& a : t) { 1601 a.get_fact(m_curr_fact); 1602 if((*m_mapper)(m_curr_fact.data()+m_first_functional)) { 1603 m_aux_table->add_fact(m_curr_fact); 1604 } 1605 } 1606 1607 t.reset(); 1608 (*m_union_fn)(t, *m_aux_table, static_cast<table_base *>(nullptr)); 1609 } 1610 }; 1611 mk_map_fn(const table_base & t,table_row_mutator_fn * mapper)1612 table_mutator_fn * relation_manager::mk_map_fn(const table_base & t, table_row_mutator_fn * mapper) { 1613 SASSERT(t.get_signature().functional_columns()>0); 1614 table_mutator_fn * res = t.get_plugin().mk_map_fn(t, mapper); 1615 if(!res) { 1616 res = alloc(default_table_map_fn, t, mapper); 1617 } 1618 return res; 1619 } 1620 1621 1622 class relation_manager::default_table_project_with_reduce_fn : public convenient_table_transformer_fn { 1623 unsigned_vector m_removed_cols; 1624 const unsigned m_inp_col_cnt; 1625 const unsigned m_removed_col_cnt; 1626 const unsigned m_result_col_cnt; 1627 scoped_ptr<table_row_pair_reduce_fn> m_reducer; 1628 unsigned m_res_first_functional; 1629 table_fact m_row; 1630 table_fact m_former_row; 1631 public: default_table_project_with_reduce_fn(const table_signature & orig_sig,unsigned removed_col_cnt,const unsigned * removed_cols,table_row_pair_reduce_fn * reducer)1632 default_table_project_with_reduce_fn(const table_signature & orig_sig, unsigned removed_col_cnt, 1633 const unsigned * removed_cols, table_row_pair_reduce_fn * reducer) 1634 : m_removed_cols(removed_col_cnt, removed_cols), 1635 m_inp_col_cnt(orig_sig.size()), 1636 m_removed_col_cnt(removed_col_cnt), 1637 m_result_col_cnt(orig_sig.size()-removed_col_cnt), 1638 m_reducer(reducer) { 1639 SASSERT(removed_col_cnt>0); 1640 table_signature::from_project_with_reduce(orig_sig, removed_col_cnt, removed_cols, 1641 get_result_signature()); 1642 m_res_first_functional = get_result_signature().first_functional(); 1643 m_row.resize(get_result_signature().size()); 1644 m_former_row.resize(get_result_signature().size()); 1645 } 1646 ~default_table_project_with_reduce_fn()1647 ~default_table_project_with_reduce_fn() override {} 1648 modify_fact(table_fact & f) const1649 virtual void modify_fact(table_fact & f) const { 1650 unsigned ofs=1; 1651 unsigned r_i=1; 1652 for(unsigned i=m_removed_cols[0]+1; i<m_inp_col_cnt; i++) { 1653 if(r_i!=m_removed_col_cnt && m_removed_cols[r_i]==i) { 1654 r_i++; 1655 ofs++; 1656 continue; 1657 } 1658 f[i-ofs]=f[i]; 1659 } 1660 SASSERT(r_i==m_removed_col_cnt); 1661 f.resize(m_result_col_cnt); 1662 } 1663 mk_project(table_base::iterator & it)1664 void mk_project(table_base::iterator& it) { 1665 for (unsigned i = 0, j = 0, r_i = 0; i < m_inp_col_cnt; ++i) { 1666 if (r_i < m_removed_col_cnt && m_removed_cols[r_i] == i) { 1667 ++r_i; 1668 } 1669 else { 1670 m_row[j] = m_former_row[j] = (*it)[i]; 1671 ++j; 1672 } 1673 } 1674 } 1675 operator ()(const table_base & t)1676 table_base * operator()(const table_base & t) override { 1677 table_plugin & plugin = t.get_plugin(); 1678 const table_signature & res_sign = get_result_signature(); 1679 SASSERT(plugin.can_handle_signature(res_sign)); 1680 table_base * res = plugin.mk_empty(res_sign); 1681 1682 table_base::iterator it = t.begin(), end = t.end(); 1683 for (; it != end; ++it) { 1684 mk_project(it); 1685 if (!res->suggest_fact(m_former_row)) { 1686 (*m_reducer)(m_former_row.data()+m_res_first_functional, m_row.data()+m_res_first_functional); 1687 res->ensure_fact(m_former_row); 1688 } 1689 } 1690 return res; 1691 } 1692 }; 1693 mk_project_with_reduce_fn(const table_base & t,unsigned col_cnt,const unsigned * removed_cols,table_row_pair_reduce_fn * reducer)1694 table_transformer_fn * relation_manager::mk_project_with_reduce_fn(const table_base & t, unsigned col_cnt, 1695 const unsigned * removed_cols, table_row_pair_reduce_fn * reducer) { 1696 SASSERT(t.get_signature().functional_columns()>0); 1697 table_transformer_fn * res = t.get_plugin().mk_project_with_reduce_fn(t, col_cnt, removed_cols, reducer); 1698 if(!res) { 1699 res = alloc(default_table_project_with_reduce_fn, t.get_signature(), col_cnt, removed_cols, reducer); 1700 } 1701 return res; 1702 } 1703 1704 }; 1705 1706