bool GeneralComp::compare(GeneralComp::ComparisonOperation operation, AnyAtomicType::Ptr first, AnyAtomicType::Ptr second, Collation* collation, DynamicContext *context, bool xpath1compat, const LocationInfo *info) { // The magnitude relationship between two atomic values is determined as follows: // 1) If either atomic value has the dynamic type xdt:untypedAtomic, that value is cast to a required type, // which is determined as follows: // - If the dynamic type of the other atomic value is a numeric type, the required type is xs:double. // - If the dynamic type of the other atomic value is xdt:untypedAtomic, the required type is xs:string. // - Otherwise, the required type is the dynamic type of the other atomic value. // If the cast to the required type fails, a dynamic error is raised. // 2) If XPath 1.0 compatibility mode is true, and at least one of the atomic values has a numeric type, // then both atomic values are cast to to the type xs:double. // 3) After any necessary casting, the atomic values are compared using one of the value comparison operators // eq, ne, lt, le, gt, or ge, depending on whether the general comparison operator was // =, !=, <, <=, >, or >=. The values have the required magnitude relationship if the result of this // value comparison is true. if(first->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) { if (second->isNumericValue()) { first = first->castAs(AnyAtomicType::DOUBLE, context); } else if(second->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) { first = first->castAs(AnyAtomicType::STRING, context); } else { first = first->castAs(second->getPrimitiveTypeIndex(), second->getTypeURI(), second->getTypeName(), context); } } if(second->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) { if(first->isNumericValue()) { second = second->castAs(AnyAtomicType::DOUBLE, context); } else if(first->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) { second = second->castAs(AnyAtomicType::STRING, context); } else { second = second->castAs(first->getPrimitiveTypeIndex(), first->getTypeURI(), first->getTypeName(), context); } } if(xpath1compat && (first->isNumericValue() || second->isNumericValue())) { first = first->castAs(AnyAtomicType::DOUBLE, context); second = second->castAs(AnyAtomicType::DOUBLE, context); } bool result = false; switch(operation) { case GeneralComp::EQUAL: result = Equals::equals(first,second,collation,context,info); break; case GeneralComp::NOT_EQUAL: result = NotEquals::not_equals(first,second,collation,context,info); break; case GeneralComp::LESS_THAN: result = LessThan::less_than(first,second,collation,context,info); break; case GeneralComp::LESS_THAN_EQUAL: result = LessThanEqual::less_than_equal(first,second,collation,context,info); break; case GeneralComp::GREATER_THAN: result = GreaterThan::greater_than(first,second,collation,context,info); break; case GeneralComp::GREATER_THAN_EQUAL: result = GreaterThanEqual::greater_than_equal(first,second,collation,context,info); break; default: assert(false); } return result; }
AnyAtomicType::Ptr XQCastAs::cast(const AnyAtomicType::Ptr &in, DynamicContext *context) const { try { if(_isPrimitive) { return in->castAs(_typeIndex, 0, 0, context); } else { return in->castAs(_typeIndex, _exprType->getTypeURI(), _exprType->getConstrainingType()->getName(), context); } } catch(XQException &e) { if(e.getXQueryLine() == 0) e.setXQueryPosition(this); throw; } }