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);
}
Example #2
0
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);
			}
		}
	}
}
Example #3
0
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);
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
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);
	}
}
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();
	}
}