void NegativeNodePredicateFilterQP::applyConversionRules(unsigned int maxAlternatives, OptimizationContext &opt, QueryPlans &alternatives) { XPath2MemoryManager *mm = opt.getMemoryManager(); // Dissolve useless predicates if(pred_->getType() == VARIABLE) { VariableQP *var = (VariableQP*)pred_; if(XPath2Utils::equals(name_, var->getName()) && XPath2Utils::equals(uri_, var->getURI())) { EmptyQP *empty = new (mm) EmptyQP(0, mm); empty->setLocationInfo(this); alternatives.push_back(empty); return; } } // Dissolve predicates in our predicate expression if(pred_->getType() == NODE_PREDICATE_FILTER) { NodePredicateFilterQP *npf = (NodePredicateFilterQP*)pred_; ContextNodeAndVarReplacer replacer(npf->getURI(), npf->getName()); if((npf->getFlags() & QueryPlan::SKIP_NESTED_PREDICATES) == 0 && replacer.test(npf->getPred())) { string before = logBefore(this); unsigned int bufferId = GET_CONFIGURATION(opt.getContext())->allocateBufferID(); BufferQP *buffer = new (mm) BufferQP(npf->getArg()->copy(mm), 0, bufferId, 0, mm); buffer->setLocationInfo(npf->getArg()); buffer->setArg(replacer.run(npf->getPred()->copy(mm), buffer, mm)); pred_ = buffer; logTransformation(opt.getLog(), "Nested predicates", before, this); pred_ = npf; QueryPlans bufferAlts; buffer->applyConversionRules(maxAlternatives, opt, bufferAlts); for(QueryPlans::iterator it = bufferAlts.begin(); it != bufferAlts.end(); ++it) { NegativeNodePredicateFilterQP *result = new (mm) NegativeNodePredicateFilterQP(arg_->copy(mm), *it, uri_, name_, flags_, mm); result->setLocationInfo(this); result->applyConversionRules(maxAlternatives, opt, alternatives); } release(); return; } } alternatives.push_back(this); { AutoRelease<QueryPlan> result(ReverseJoin().run(this, opt, mm)); if(result.get() != 0) result->createAlternatives(maxAlternatives, opt, alternatives); } addFlag(SKIP_REVERSE_JOIN); }
void IntersectQP::applyConversionRules(unsigned int maxAlternatives, OptimizationContext &opt, QueryPlans &alternatives) { XPath2MemoryManager *mm = opt.getMemoryManager(); removeSupersets(opt); // Return if we only have one argument if(args_.size() == 1) { alternatives.push_back(args_[0]); return; } // TBD remove the need for QueryExecutionContext here - jpcs QueryExecutionContext qec(GET_CONFIGURATION(opt.getContext())->getQueryContext(), /*debugging*/false); qec.setContainerBase(opt.getContainerBase()); qec.setDynamicContext(opt.getContext()); // Sort the arguments based on how many keys we think they'll return sort(args_.begin(), args_.end(), keys_compare_less(opt.getOperationContext(), qec)); alternatives.push_back(this); for(Vector::const_iterator it = args_.begin(); it != args_.end(); ++it) { for(Vector::const_iterator it2 = it + 1; it2 != args_.end(); ++it2) { QueryPlans alts; applyConversionRules2Args(maxAlternatives, *it, *it2, opt, alts); for(QueryPlans::iterator it3 = alts.begin(); it3 != alts.end(); ++it3) { IntersectQP *newIntersect = new (mm) IntersectQP(flags_, mm); newIntersect->setLocationInfo(this); Vector::const_iterator it4; // Copy args before "it" for(it4 = args_.begin(); it4 != it; ++it4) { newIntersect->addArg((*it4)->copy(mm)); } // Add new alternative newIntersect->addArg(*it3); // Copy args from after "it" to before "it2" for(++it4; it4 != it2; ++it4) { newIntersect->addArg((*it4)->copy(mm)); } // Copy args from after "it2" for(++it4; it4 != args_.end(); ++it4) { newIntersect->addArg((*it4)->copy(mm)); } newIntersect->applyConversionRules(maxAlternatives, opt, alternatives); } } } }
void NegativeNodePredicateFilterQP::createCombinations(unsigned int maxAlternatives, OptimizationContext &opt, QueryPlans &combinations) const { XPath2MemoryManager *mm = opt.getMemoryManager(); // Generate the alternatives for the arguments QueryPlans argAltArgs; arg_->createReducedAlternatives(ARGUMENT_CUTOFF_FACTOR, maxAlternatives, opt, argAltArgs); QueryPlans predAltArgs; pred_->createReducedAlternatives(ARGUMENT_CUTOFF_FACTOR, maxAlternatives, opt, predAltArgs); // Generate the combinations of all the alternatives for the arguments QueryPlans::iterator it; for(it = argAltArgs.begin(); it != argAltArgs.end(); ++it) { for(QueryPlans::iterator it2 = predAltArgs.begin(); it2 != predAltArgs.end(); ++it2) { NegativeNodePredicateFilterQP *newPred = new (mm) NegativeNodePredicateFilterQP((*it)->copy(mm), (*it2)->copy(mm), uri_, name_, flags_, mm); newPred->setLocationInfo(this); combinations.push_back(newPred); } } // Release the alternative arguments, since they've been copied for(it = argAltArgs.begin(); it != argAltArgs.end(); ++it) { (*it)->release(); } for(it = predAltArgs.begin(); it != predAltArgs.end(); ++it) { (*it)->release(); } }
void DecisionPointQP::createCombinations(unsigned int maxAlternatives, OptimizationContext &opt, QueryPlans &combinations) const { // DecisionPointQP doesn't participate in any of the optimisations of it's parents, // so we make the decision of what to pick here. XPath2MemoryManager *mm = opt.getMemoryManager(); DecisionPointQP *result = new (mm) DecisionPointQP(this, opt, mm); result->setLocationInfo(this); combinations.push_back(result); }
void DescendantOrSelfJoinQP::applyConversionRules(unsigned int maxAlternatives, OptimizationContext &opt, QueryPlans &alternatives) { XPath2MemoryManager *mm = opt.getMemoryManager(); if(containsAllDocumentNodes(left_)) { // Any node is a descendant-or-self of all document nodes logTransformation(opt.getLog(), "Redundant descendant-or-self", this, right_); alternatives.push_back(right_->copy(mm)); } StructuralJoinQP::applyConversionRules(maxAlternatives, opt, alternatives); }
void DescendantJoinQP::applyConversionRules(unsigned int maxAlternatives, OptimizationContext &opt, QueryPlans &alternatives) { XPath2MemoryManager *mm = opt.getMemoryManager(); if(containsAllDocumentNodes(left_)) { ImpliedSchemaNode::Type rType = findType(right_); if(rType != (ImpliedSchemaNode::Type)-1 && rType != ImpliedSchemaNode::METADATA) { // Any node except a document node is a descendant of all document nodes logTransformation(opt.getLog(), "Redundant descendant", this, right_); alternatives.push_back(right_->copy(mm)); } } StructuralJoinQP::applyConversionRules(maxAlternatives, opt, alternatives); }
void IntersectQP::combineAltArgs(vector<QueryPlans>::iterator argIt, vector<QueryPlans>::iterator argEnd, vector<QueryPlan*> &newArgs, OptimizationContext &opt, QueryPlans &combinations) const { XPath2MemoryManager *mm = opt.getMemoryManager(); if(argIt != argEnd) { for(QueryPlans::iterator it3 = argIt->begin(); it3 != argIt->end(); ++it3) { newArgs.push_back(*it3); combineAltArgs(argIt + 1, argEnd, newArgs, opt, combinations); newArgs.pop_back(); } } else { // Construct the new IntersectQP IntersectQP *newIntersect = new (mm) IntersectQP(flags_, mm); newIntersect->setLocationInfo(this); for(vector<QueryPlan*>::iterator it = newArgs.begin(); it != newArgs.end(); ++it) { newIntersect->addArg((*it)->copy(mm)); } // Add this IntersectQP to the combinations vector combinations.push_back(newIntersect); } }