Пример #1
0
QueryPlan *AttributeOrChildJoinQP::staticTyping(StaticContext *context, StaticTyper *styper)
{
	StructuralJoinQP::staticTyping(context, styper);

	XPath2MemoryManager *mm = context->getMemoryManager();

	if(right_->getStaticAnalysis().getStaticType().isType(StaticType::ATTRIBUTE_TYPE)) {
		// Convert to a AttributeJoinQP
		QueryPlan *result = new (mm) AttributeJoinQP(left_, right_, flags_, mm);
		result->setLocationInfo(this);

		logTransformation((Manager&)GET_CONFIGURATION(context)->getManager(),
			"More specific join", this, result);
		return result->staticTyping(context, styper);
	}

	if(!right_->getStaticAnalysis().getStaticType().containsType(StaticType::ATTRIBUTE_TYPE)) {
		// Convert to a ChildJoinQP
		QueryPlan *result = new (mm) ChildJoinQP(left_, right_, flags_, mm);
		result->setLocationInfo(this);

		logTransformation((Manager&)GET_CONFIGURATION(context)->getManager(),
			"More specific join", this, result);
		return result->staticTyping(context, styper);
	}

	return this;
}
Пример #2
0
QueryPlan *AttributeOrChildJoinQP::optimize(OptimizationContext &opt)
{
	QueryPlan *result = StructuralJoinQP::optimize(opt);
	if(result != this) return result;

	XPath2MemoryManager *mm = opt.getMemoryManager();

	ImpliedSchemaNode::Type type = findType(right_);
	if(type == ImpliedSchemaNode::ATTRIBUTE) {
		// Convert to a AttributeJoinQP
		QueryPlan *result = new (mm) AttributeJoinQP(left_, right_, flags_, mm);
		result->setLocationInfo(this);

		logTransformation(opt.getLog(), "More specific join", this, result);
		return result->optimize(opt);
	}

	if(type != -1) {
		// Convert to a ChildJoinQP
		QueryPlan *result = new (mm) ChildJoinQP(left_, right_, flags_, mm);
		result->setLocationInfo(this);

		logTransformation(opt.getLog(), "More specific join", this, result);
		return result->optimize(opt);
	}

	return this;
}
Пример #3
0
QueryPlan *AttributeOrChildJoinQP::copy(XPath2MemoryManager *mm) const
{
	if(!mm) mm = memMgr_;
	QueryPlan *result = new (mm) AttributeOrChildJoinQP(left_->copy(mm), right_->copy(mm), flags_, mm);
	result->setLocationInfo(this);
	return result;
}
Пример #4
0
QueryPlan *DescendantOrSelfJoinQP::copy(XPath2MemoryManager *mm) const
{
	if(!mm) mm = memMgr_;

	QueryPlan *result = new (mm) DescendantOrSelfJoinQP(left_->copy(mm), right_->copy(mm), flags_, mm);
	result->setLocationInfo(this);
	return result;
}
Пример #5
0
QueryPlan *EmptyQP::copy(XPath2MemoryManager *mm) const
{
	if(!mm) {
		mm = memMgr_;
	}

	QueryPlan *result = new (mm) EmptyQP(flags_, mm);
	result->setLocationInfo(this);
	return result;
}
Пример #6
0
QueryPlan *DescendantOrSelfJoinQP::optimize(OptimizationContext &opt)
{
	XPath2MemoryManager *mm = opt.getMemoryManager();

	QueryPlan *qp = StructuralJoinQP::optimize(opt);
	if(qp != this) return qp;

	if(findType(left_) == ImpliedSchemaNode::METADATA) {
		switch(right_->getType()) {
		case DESCENDANT_OR_SELF: {
			DescendantOrSelfJoinQP *rsj = (DescendantOrSelfJoinQP*)right_;
			if(findType(rsj->left_) == ImpliedSchemaNode::METADATA) {
				string before = logBefore(this);

				left_ = new (mm) IntersectQP(left_, rsj->left_, 0, mm);
				left_->setLocationInfo(rsj);
				right_ = rsj->right_;
				flags_ |= rsj->flags_;

				logTransformation(opt.getLog(), "Combine document join", before, this);
				return optimize(opt);
			}
			break;
		}
		default: {
			if(findType(right_) == ImpliedSchemaNode::METADATA) {
				string before = logBefore(this);

				QueryPlan *result = new (mm) IntersectQP(left_, right_, flags_, mm);
				result->setLocationInfo(this);

				logTransformation(opt.getLog(), "Combine document join", this, result);
				return result->optimize(opt);
			}
			break;
		}
		}
	}

	if(opt.getPhase() < OptimizationContext::REMOVE_REDUNDENTS)
		return this;

	if(findType(left_) == ImpliedSchemaNode::METADATA) {
		switch(right_->getType()) {
		case STEP: {
			string before = logBefore(this);

			StepQP *step = (StepQP*)right_;
			right_ = step->getArg();
			step->setArg(this);

			logTransformation(opt.getLog(), "Push back document join", before, step);
			return step->optimize(opt);
		}
		case DESCENDANT:
		case DESCENDANT_OR_SELF:
		case ATTRIBUTE:
		case CHILD:
		case ATTRIBUTE_OR_CHILD: {
			string before = logBefore(this);

			StructuralJoinQP *sj = (StructuralJoinQP*)right_;
			right_ = sj->getLeftArg();
			sj->setLeftArg(this);

			logTransformation(opt.getLog(), "Push back document join", before, sj);
			return sj->optimize(opt);
		}
		case ANCESTOR:
		case ANCESTOR_OR_SELF:
		case PARENT:
		case PARENT_OF_ATTRIBUTE:
		case PARENT_OF_CHILD: {
			string before = logBefore(this);

			StructuralJoinQP *sj = (StructuralJoinQP*)right_;
			right_ = sj->getRightArg();
			sj->setRightArg(this);

			logTransformation(opt.getLog(), "Push back document join", before, sj);
			return sj->optimize(opt);
		}
		case EXCEPT: {
			string before = logBefore(this);

			// Add to both arguments of ExceptQP

			ExceptQP *ex = (ExceptQP*)right_;
			right_ = ex->getLeftArg();
			ex->setLeftArg(this);

			QueryPlan *copy = new (mm) DescendantOrSelfJoinQP(left_->copy(mm), ex->getRightArg(), flags_, mm);
			copy->setLocationInfo(this);
			ex->setRightArg(copy);

			logTransformation(opt.getLog(), "Push back document join", before, ex);
			return ex->optimize(opt);
		}
		default: break;
		}
	}

	// 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());

	// Remove this document index join if it's unlikely to be useful
	if(isDocumentIndex(left_, /*toBeRemoved*/true) && isSuitableForDocumentIndexComparison(right_)) {
		Cost rCost = right_->cost(opt.getOperationContext(), qec);
		Cost lCost = left_->cost(opt.getOperationContext(), qec);

		// TBD Calculate these constants? - jpcs
		static const double KEY_RATIO_THRESHOLD = 2.0;
		static const double KEYS_PER_PAGE_THRESHOLD = 2.0;

		if((lCost.keys / rCost.keys) > KEY_RATIO_THRESHOLD ||
			(lCost.keys / lCost.totalPages()) > KEYS_PER_PAGE_THRESHOLD) {

			logTransformation(opt.getLog(), "Remove document join", this, right_);
			right_->logCost(qec, rCost, 0);
			left_->logCost(qec, lCost, 0);
			return right_;
		}
	}

	return this;
}