Alist_t<Abinop_t> Ajoin_t::Clones (Alognode_t *leftinput, Alognode_t *rightinput) { Alist_t<Abinop_t> clones; if (Aglob_vars()->oopt->left_deep_only && rightinput->GetOp ()->GetNumber () != Aget) return clones; // left deep only. if (Aglob_vars()->oopt->right_deep_only && leftinput->GetOp ()->GetNumber () != Aget) return clones; // right deep only. Aset_t<Aptree_t> leftoprns = leftinput->GetLogProps ()->operations (); leftoprns.Minus (leftinput->GetLogProps ()->need_unnesting ()); Aset_t<Aptree_t> rightoprns = rightinput->GetLogProps ()->operations (); rightoprns.Minus (rightinput->GetLogProps ()->need_unnesting ()); Aset_t<Aptree_t> tupleref_ops = Aglob_vars()->query->tupleref_ops (); Aset_t<Aptree_t> &relref_ops = (Aset_t<Aptree_t> &)Aglob_vars()->query->relref_ops (); // converting a const to a non-const. // will fix this later. // Aset_t<Aptree_t> oprns_intersect = leftoprns; // oprns_intersect.Intersect (rightoprns); // oprns_intersect.Delete (&Aptree_t::null_pred_tree ()); // if (Adont_explore (oprns_intersect)) // return clones; // not joinable. // // this need not be checked here because the // Ajoin_t::Apply function does not send us any that dont // satisfy this... tupleref_ops.Intersect (relref_ops); // we are interested only in those // tuple ref operations which represent // real extents. tupleref_ops.Intersect (leftoprns); tupleref_ops.Intersect (rightoprns); // now tupleref_ops constains those // tupleref operations which are present // in both inputs and which represent // real extents. // now we have a set of tupleref operation each of which signifies // a legal pointer-based join of the two inputs. // now we start looking for other (normal) join operations. Aset_t<Aptree_t> join_ops = Aglob_vars()->query->join_ops (); join_ops.Minus (leftoprns); join_ops.Minus (rightoprns); // now join_ops contains the join ops // which havent yet been applied. for (int eos = join_ops.StartTraversal (); !eos; ) { Aptree_t *oprn = join_ops.CurrentElement (); // this is a join operation only if one of its operands // is present in the left input and the other is // present in the right input. int left_present_in_left = leftoprns.HasElement (oprn->arg (0)) ? 1 : 0; int left_present_in_right = rightoprns.HasElement (oprn->arg (0)) ? 1 : 0; int right_present_in_left = leftoprns.HasElement (oprn->arg (1)) ? 1 : 0; int right_present_in_right = rightoprns.HasElement (oprn->arg (1)) ? 1 : 0; if (left_present_in_left + left_present_in_right == 1 && right_present_in_left + right_present_in_right == 1) eos = join_ops.Advance (); else eos = join_ops.DeleteAndAdvance (); // if this doesnt satisfy, then delete it. } if (Aglob_vars()->oopt->do_mat_to_join) join_ops.Union (tupleref_ops); // now join_ops contains all the // join operations. FOR_EACH_ELEMENT_OF_SET (join_ops) { Aptree_t *oprn = join_ops.CurrentElement (); Ajoin_t *newjoin = (Ajoin_t *)Duplicate (); newjoin->_operations.Insert (oprn); newjoin->_undone_tuplerefs = tupleref_ops; newjoin->_undone_tuplerefs.Delete (oprn); // tuplerefs which have to be done // but which haven't yet been done... clones.Insert (newjoin); // see if we can do a join using an inverse link... if (Aglob_vars()->oopt->do_inverse_links && oprn->is_tupleref ()) { Acat_t::attrid_t tupleref_attrid = ((Atupleref_t *)oprn->func ())->attrid (); if (Aglob_vars()->cat->has_inverse (tupleref_attrid)) { Ajoin_t *inverse_newjoin = (Ajoin_t *)Duplicate (); inverse_newjoin->_operations.Insert (oprn); inverse_newjoin->_undone_tuplerefs = newjoin->_undone_tuplerefs; inverse_newjoin->_inverse = 1; clones.Insert (inverse_newjoin); } } } return clones; }
ON_Hatch* ON_Hatch::DuplicateHatch() const { return Duplicate(); }
_HYEvent::_HYEvent(_HYEvent& he) { Duplicate (&he); }