diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/dataItem/DbXmlContains.cpp dbxml-2.3.10/dbxml/src/dbxml/dataItem/DbXmlContains.cpp --- dbxml-2.3.10-original/dbxml/src/dbxml/dataItem/DbXmlContains.cpp 2006-10-30 17:45:54.000000000 +0000 +++ dbxml-2.3.10/dbxml/src/dbxml/dataItem/DbXmlContains.cpp 2007-08-07 16:49:44.000000000 +0100 @@ -24,10 +24,11 @@ using namespace DbXml; using namespace std; -DbXmlContains::DbXmlContains(ASTNode *arg, XPath2MemoryManager* memMgr) +DbXmlContains::DbXmlContains(ASTNode *arg, bool caseDiacriticInsensitive, XPath2MemoryManager* memMgr) : DbXmlASTNode(DBXML_CONTAINS, memMgr), joinType_(Join::SELF), nodeTest_(0), + cdInsens_(caseDiacriticInsensitive), arg_(arg) { staticTyping(0); @@ -37,6 +38,7 @@ : DbXmlASTNode(DBXML_CONTAINS, memMgr), joinType_(join), nodeTest_(cnt->nodeTest_), + cdInsens_(cnt->cdInsens_), arg_(cnt->arg_) { setQueryPlanHolder(cnt); @@ -48,6 +50,7 @@ : DbXmlASTNode(DBXML_CONTAINS, memMgr), joinType_(join), nodeTest_(nodeTest), + cdInsens_(cnt->cdInsens_), arg_(cnt->arg_) { setQueryPlanHolder(cnt); @@ -193,7 +196,14 @@ if(container == 0 || *container == 0) continue; - if(XMLString::patternMatch(container, pattern) > -1) + if(contains_->isCaseAndDiacriticInsensitive()) { + XMLBuffer buf1, buf2; + Normalizer::caseFoldAndRemoveDiacritics(container, buf1); + Normalizer::caseFoldAndRemoveDiacritics(pattern, buf2); + + if(XMLString::patternMatch(buf1.getRawBuffer(), buf2.getRawBuffer()) > -1) + return item; + } else if(XMLString::patternMatch(container, pattern) > -1) return item; } @@ -221,3 +231,53 @@ { _src.copy(comp->getStaticResolutionContext()); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const XMLCh DbXmlFunContainsCD::name[] = { + chLatin_c, chLatin_o, chLatin_n, + chLatin_t, chLatin_a, chLatin_i, + chLatin_n, chLatin_s, chNull +}; +const unsigned int DbXmlFunContainsCD::minArgs = 2; +const unsigned int DbXmlFunContainsCD::maxArgs = 2; + +DbXmlFunContainsCD::DbXmlFunContainsCD(const VectorOfASTNodes &args, XPath2MemoryManager *memMgr) + : DbXmlFunction(name, minArgs, maxArgs, "string?, string?", args, memMgr) +{ +} + +ASTNode *DbXmlFunContainsCD::staticResolution(StaticContext *context) +{ + return resolveArguments(context); +} + +ASTNode *DbXmlFunContainsCD::staticTyping(StaticContext *context) +{ + _src.clear(); + + _src.getStaticType().flags = StaticType::BOOLEAN_TYPE; + return calculateSRCForArguments(context); +} + +Sequence DbXmlFunContainsCD::collapseTreeInternal(DynamicContext *context, int flags) const +{ + Item::Ptr item1 = getParamNumber(1,context)->next(context); + Item::Ptr item2 = getParamNumber(2,context)->next(context); + + const XMLCh *str1 = item1.isNull() ? XMLUni::fgZeroLenString : item1->asString(context); + const XMLCh *str2 = item2.isNull() ? XMLUni::fgZeroLenString : item2->asString(context); + + bool result; + if(str2 == 0 || *str2 == 0) result = true; + else if(str1 == 0 || *str1 == 0) result = false; + else { + XMLBuffer buf1, buf2; + Normalizer::caseFoldAndRemoveDiacritics(str1, buf1); + Normalizer::caseFoldAndRemoveDiacritics(str2, buf2); + + result = XMLString::patternMatch(buf1.getRawBuffer(), buf2.getRawBuffer()) > -1; + } + + return Sequence(context->getItemFactory()->createBoolean(result, context), context->getMemoryManager()); +} diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/dataItem/DbXmlContains.hpp dbxml-2.3.10/dbxml/src/dbxml/dataItem/DbXmlContains.hpp --- dbxml-2.3.10-original/dbxml/src/dbxml/dataItem/DbXmlContains.hpp 2006-11-21 18:49:43.000000000 +0000 +++ dbxml-2.3.10/dbxml/src/dbxml/dataItem/DbXmlContains.hpp 2007-08-07 16:49:00.000000000 +0100 @@ -13,6 +13,7 @@ #include "QueryPlanResultImpl.hpp" #include "DbXmlASTNode.hpp" #include "Join.hpp" +#include "DbXmlFunction.hpp" #include #include @@ -35,7 +36,7 @@ const DbXmlContains *contains_; }; - DbXmlContains(ASTNode *arg, XPath2MemoryManager* memMgr); + DbXmlContains(ASTNode *arg, bool caseDiacriticInsensitive, XPath2MemoryManager* memMgr); DbXmlContains(Join::Type join, const DbXmlContains *cnt, XPath2MemoryManager* memMgr); DbXmlContains(Join::Type join, DbXmlNodeTest *nodeTest, const DbXmlContains *cnt, XPath2MemoryManager* memMgr); @@ -47,6 +48,8 @@ Join::Type getJoinType() const { return joinType_; } const DbXmlNodeTest *getNodeTest() const { return nodeTest_; } + bool isCaseAndDiacriticInsensitive() const { return cdInsens_; } + const ASTNode *getArgument() const { return arg_; } void setArgument(ASTNode *a) { arg_ = a; } @@ -63,6 +66,7 @@ Join::Type joinType_; DbXmlNodeTest *nodeTest_; + bool cdInsens_; ASTNode *arg_; }; @@ -77,6 +81,24 @@ QueryPlanHolder arg0qph_; }; +class DbXmlFunContainsCD : public DbXmlFunction +{ +public: + static const XMLCh name[]; + static const unsigned int minArgs, maxArgs; + + DbXmlFunContainsCD(const VectorOfASTNodes &args, XPath2MemoryManager* memMgr); + + virtual ASTNode *staticResolution(StaticContext* context); + virtual ASTNode *staticTyping(StaticContext *context); + virtual Sequence collapseTreeInternal(DynamicContext* context, int flags=0) const; + + QueryPlanHolder &getArg0QPH() { return arg0qph_; } + +private: + QueryPlanHolder arg0qph_; +}; + } #endif diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/dataItem/DbXmlFunction.cpp dbxml-2.3.10/dbxml/src/dbxml/dataItem/DbXmlFunction.cpp --- dbxml-2.3.10-original/dbxml/src/dbxml/dataItem/DbXmlFunction.cpp 2006-10-30 17:45:55.000000000 +0000 +++ dbxml-2.3.10/dbxml/src/dbxml/dataItem/DbXmlFunction.cpp 2007-08-07 17:23:56.000000000 +0100 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,13 @@ chNull }; +DbXmlFunction::DbXmlFunction(const XMLCh* name, unsigned int argsFrom, unsigned int argsTo, + const char* paramDecl, const VectorOfASTNodes &args, XPath2MemoryManager* memMgr) + : XQFunction(name, argsFrom, argsTo, paramDecl, args, memMgr) +{ + _fURI = XMLChFunctionURI; +} + void DbXmlFunction::getQNameArg(unsigned int argNum, const XMLCh *&uri, const XMLCh *&name, DynamicContext *context) const { // Convert the string to a qname, thus checking it's syntax @@ -87,6 +95,10 @@ XQThrow(FunctionException,X("DbXmlFunction::getQNameArg"), X("No namespace binding for prefix in argument to a DB XML extension function.")); } + catch(StaticErrorException &e) { + XQThrow(FunctionException,X("DbXmlFunction::getQNameArg"), + X("No namespace binding for prefix in argument to a DB XML extension function.")); + } } bool DbXmlFunction::getConstantQNameArg(unsigned int argNum, const XMLCh *&uri, const XMLCh *&name, DynamicContext *context) const diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/dataItem/DbXmlFunction.hpp dbxml-2.3.10/dbxml/src/dbxml/dataItem/DbXmlFunction.hpp --- dbxml-2.3.10-original/dbxml/src/dbxml/dataItem/DbXmlFunction.hpp 2007-01-12 18:05:49.000000000 +0000 +++ dbxml-2.3.10/dbxml/src/dbxml/dataItem/DbXmlFunction.hpp 2007-08-07 17:24:09.000000000 +0100 @@ -27,8 +27,7 @@ protected: DbXmlFunction(const XMLCh* name, unsigned int argsFrom, unsigned int argsTo, - const char* paramDecl, const VectorOfASTNodes &args, XPath2MemoryManager* memMgr) - : XQFunction(name, argsFrom, argsTo, paramDecl, args, memMgr) {} + const char* paramDecl, const VectorOfASTNodes &args, XPath2MemoryManager* memMgr); }; template diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/ASTRewriteOptimizer.cpp dbxml-2.3.10/dbxml/src/dbxml/optimizer/ASTRewriteOptimizer.cpp --- dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/ASTRewriteOptimizer.cpp 2006-10-30 17:45:58.000000000 +0000 +++ dbxml-2.3.10/dbxml/src/dbxml/optimizer/ASTRewriteOptimizer.cpp 2007-08-07 17:19:56.000000000 +0100 @@ -643,7 +643,7 @@ return item; } -ASTNode *ASTRewriteOptimizer::createDbXmlContains(DbXmlFunContains *item) +ASTNode *ASTRewriteOptimizer::createDbXmlContains(XQFunction *item, QueryPlanHolder *qph, bool caseDiacriticInsensitive) { VectorOfASTNodes &args = const_cast(item->getArguments()); @@ -663,9 +663,9 @@ nav->addStep(arg0); } - DbXmlContains *contains = new (mm) DbXmlContains(arg1, mm); + DbXmlContains *contains = new (mm) DbXmlContains(arg1, caseDiacriticInsensitive, mm); contains->setLocationInfo(item); - contains->setQueryPlanHolder(&item->getArg0QPH()); + contains->setQueryPlanHolder(qph); nav->addStep(contains); nav->recalculateSRC(); @@ -695,7 +695,13 @@ if(uri == XQFunction::XMLChFunctionURI) { if(name == FunctionContains::name) { - return createDbXmlContains((DbXmlFunContains*)item); + return createDbXmlContains(item, &((DbXmlFunContains*)item)->getArg0QPH(), /*caseDiacriticInsensitive*/false); + } + } + + else if(uri == DbXmlFunction::XMLChFunctionURI) { + if(name == DbXmlFunContainsCD::name) { + return createDbXmlContains(item, &((DbXmlFunContainsCD*)item)->getArg0QPH(), /*caseDiacriticInsensitive*/true); } } diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/ASTRewriteOptimizer.hpp dbxml-2.3.10/dbxml/src/dbxml/optimizer/ASTRewriteOptimizer.hpp --- dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/ASTRewriteOptimizer.hpp 2006-10-30 17:45:59.000000000 +0000 +++ dbxml-2.3.10/dbxml/src/dbxml/optimizer/ASTRewriteOptimizer.hpp 2007-08-07 16:55:40.000000000 +0100 @@ -51,7 +51,7 @@ private: ASTNode *createDbXmlCompare(XQOperator *item, GeneralComp::ComparisonOperation op, bool generalComp, QueryPlanHolder *arg0qph, QueryPlanHolder *arg1qph); - ASTNode *createDbXmlContains(DbXmlFunContains *item); + ASTNode *createDbXmlContains(XQFunction *item, QueryPlanHolder *qph, bool caseDiacriticInsensitive); ASTNode *createDbXmlIntersect(Intersect *item); ASTNode *optimizeFLOWRToNav(VectorOfVariableBinding *bindings, XQFLWOR *item, bool quantified); diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/CostBasedOptimizer.cpp dbxml-2.3.10/dbxml/src/dbxml/optimizer/CostBasedOptimizer.cpp --- dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/CostBasedOptimizer.cpp 2007-04-18 10:05:23.000000000 +0100 +++ dbxml-2.3.10/dbxml/src/dbxml/optimizer/CostBasedOptimizer.cpp 2007-08-07 17:02:17.000000000 +0100 @@ -424,7 +424,7 @@ case ((ASTNode::whichType)DbXmlASTNode::DBXML_CONTAINS): { DbXmlContains *oldCnt = (DbXmlContains*)item; DbXmlContains *cnt = new (mm) - DbXmlContains(const_cast(oldCnt->getArgument()), mm); + DbXmlContains(const_cast(oldCnt->getArgument()), oldCnt->isCaseAndDiacriticInsensitive(), mm); cnt->setLocationInfo(oldCnt); forward->addStep(cnt); break; diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/QueryPlanGenerator.cpp dbxml-2.3.10/dbxml/src/dbxml/optimizer/QueryPlanGenerator.cpp --- dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/QueryPlanGenerator.cpp 2007-04-18 10:05:24.000000000 +0100 +++ dbxml-2.3.10/dbxml/src/dbxml/optimizer/QueryPlanGenerator.cpp 2007-08-07 17:03:28.000000000 +0100 @@ -1057,6 +1057,12 @@ generateLookup(fun, ImpliedSchemaNode::METADATA, fun->getChildURIName(), fun->getParentURIName(), result); } + + else if(name == DbXmlFunContainsCD::name) { + DbXmlFunContainsCD *db = (DbXmlFunContainsCD*)item; + generateSubstring(ImpliedSchemaNode::SUBSTRING, args, result, ids, + &db->getArg0QPH()); + } } else { diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/QueryPlanOptimizer.cpp dbxml-2.3.10/dbxml/src/dbxml/optimizer/QueryPlanOptimizer.cpp --- dbxml-2.3.10-original/dbxml/src/dbxml/optimizer/QueryPlanOptimizer.cpp 2006-10-30 17:45:59.000000000 +0000 +++ dbxml-2.3.10/dbxml/src/dbxml/optimizer/QueryPlanOptimizer.cpp 2007-08-07 17:13:30.000000000 +0100 @@ -37,6 +37,10 @@ } else if(funName == FunctionContains::name) { ((DbXmlFunContains*)item)->getArg0QPH().generateQueryPlan(mgr_, txn_, xpc_); } + } else if(funUri == DbXmlFunction::XMLChFunctionURI) { + if(funName == DbXmlFunContainsCD::name) { + ((DbXmlFunContainsCD*)item)->getArg0QPH().generateQueryPlan(mgr_, txn_, xpc_); + } } return item; diff -ur dbxml-2.3.10-original/dbxml/src/dbxml/QueryContext.cpp dbxml-2.3.10/dbxml/src/dbxml/QueryContext.cpp --- dbxml-2.3.10-original/dbxml/src/dbxml/QueryContext.cpp 2007-01-12 18:05:49.000000000 +0000 +++ dbxml-2.3.10/dbxml/src/dbxml/QueryContext.cpp 2007-08-07 16:48:16.000000000 +0100 @@ -21,6 +21,7 @@ #include "dataItem/MetaDataFunction.hpp" #include "dataItem/NodeHandleFunction.hpp" #include "dataItem/LookupIndexFunction.hpp" +#include "dataItem/DbXmlContains.hpp" #include @@ -358,6 +359,7 @@ context->addCustomFunction(new (memMgr) DbXmlFuncFactory(memMgr)); context->addCustomFunction(new (memMgr) DbXmlFuncFactory(memMgr)); context->addCustomFunction(new (memMgr) DbXmlFuncFactory(memMgr)); + context->addCustomFunction(new (memMgr) DbXmlFuncFactory(memMgr)); } DbXmlContext *QueryContext::createDynamicContext(Transaction *txn, const DynamicContext *staticContext)