zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #20454
[Merge] lp:~zorba-coders/zorba/bug11369_xqxq_bind_cast_variable into lp:zorba
Juan Zacarias has proposed merging lp:~zorba-coders/zorba/bug11369_xqxq_bind_cast_variable into lp:zorba.
Commit message:
Added Implementation and test for xqxq module functions xqxq:variable-type and xqxq:bind-cast-variable.
Also added function getVariable to the Dynamic Context Implementation and API.
Requested reviews:
Juan Zacarias (juan457)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug11369_xqxq_bind_cast_variable/+merge/158480
Added Implementation and test for xqxq module functions xqxq:variable-type and xqxq:bind-cast-variable.
Also added function getVariable to the Dynamic Context Implementation and API.
--
https://code.launchpad.net/~zorba-coders/zorba/bug11369_xqxq_bind_cast_variable/+merge/158480
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'include/zorba/dynamic_context.h'
--- include/zorba/dynamic_context.h 2013-03-13 16:17:38 +0000
+++ include/zorba/dynamic_context.h 2013-04-11 20:40:28 +0000
@@ -348,6 +348,21 @@
virtual bool
isBoundContextItem() const = 0;
+ /** \brief Returns the type of an external variable.
+ *
+ * The named external variable may be located in the main query or in any
+ * modules imported directly or indirectly by the query.
+ *
+ * @param aNamespace the namespace URI of the variable's expanded QName
+ * @param aLocalname the local name of the variable's expanded QName
+ * @param outType a String representing the type of
+ * the external variable.
+ * @return true if the variable has been retrieved successfully, false otherwise.
+ * @throw ZorbaException if an error occured.
+ */
+ virtual bool
+ getVariableType(const String& aNamespace, const String& aLocalname, String& outType) = 0;
+
protected:
/** \brief Destructor
*/
=== modified file 'modules/xqxq/xqxq.xq'
--- modules/xqxq/xqxq.xq 2013-04-09 14:22:41 +0000
+++ modules/xqxq/xqxq.xq 2013-04-11 20:40:28 +0000
@@ -23,7 +23,9 @@
: @author Juan Zacarias
: @project Zorba/Programming Languages/XQuery
:)
-module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';
+module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';
+import module namespace parse-xml = "http://www.zorba-xquery.com/modules/xml";
+import schema namespace opt = "http://www.zorba-xquery.com/modules/xml-options";
declare namespace an = "http://www.zorba-xquery.com/annotations";
declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
@@ -285,6 +287,66 @@
declare %an:sequential function xqxq:bind-variable($query-key as xs:anyURI,
$var as xs:QName, $value as item()*) as empty-sequence() external ;
+(:~
+ : This function uses a string value to bind the value of an external variable
+ : by trying to cast the string to the corresponding type defined in the query.
+ : Currently the types supported for automatic casting are: xs:string*, xs:integer*,
+ : xs:int*, xs:long*, xs:short*, xs:decimal*, xs:double*, xs:float*, xs:date*,
+ : xs:time*, xs:dateTime*, object()*, array()*, document-node()* and element()*.
+ : If the variable doesn't have a defined type xs:string is assumed.
+ :
+ : NOTE: if the user wants to set the variable using an item() the use of
+ : xqxq:bind-variable is suggested.
+ :
+ : @param $query-key the identifier for a compiled query
+ : @param $name the name of the external variable to bind
+ : @param $value the sequence of strings to which the external variable $name
+ : should be casted and set
+ :
+ : @return the function has side effects and returns the empty
+ : sequence.
+ :
+ : @error xqxq:NoQueryMatch if no query with the given identifier
+ : was prepared.
+ : @error xqxq:UndeclaredVariable if the given variable is not declared
+ : in the query.
+ :)
+declare %an:sequential function xqxq:bind-cast-variable($query-key as xs:anyURI, $var-name as
+ xs:QName, $value as xs:string*) as empty-sequence()
+{
+ variable $type := xqxq:variable-type($query-key, $var-name);
+ variable $unquanttype := fn:replace($type, "[*+?]$", "");
+ let $casted-value :=
+ if (fn:contains($unquanttype, "object")) then
+ for $val in $value return jn:parse-json($val)
+ else if (fn:contains($unquanttype, "array")) then
+ for $val in $value return jn:parse-json($val)
+ else if (fn:contains($unquanttype, "document-node")) then
+ for $val in $value return fn:parse-xml($val)
+ else if (fn:contains($unquanttype, "element")) then
+ for $val in $value return parse-xml:parse($val,
+ <opt:options>
+ <opt:parse-external-parsed-entity/>
+ </opt:options>)
+ else
+ if ($unquanttype eq "xs:anyType")
+ then $value
+ else xqxq:caster($unquanttype, $value)
+ return xqxq:bind-variable($query-key, $var-name, $casted-value)
+};
+
+declare %private %an:sequential function xqxq:caster($unquanttype as xs:string,
+ $value as xs:string*) as item()*
+{
+ variable $caster := xqxq:prepare-main-module(
+ fn:concat("declare variable $val as xs:string* external; ",
+ "for $v in $val return $v cast as ",
+ $unquanttype));
+ xqxq:bind-variable($caster, xs:QName("val"), $value);
+ variable $casted := xqxq:evaluate($caster);
+ xqxq:delete-query($caster);
+ $casted
+};
(:~
: Evaluates the given prepared query and returns the result
@@ -387,6 +449,24 @@
xs:QName) as item()* external;
(:~
+ : This function returns the type of a variable that is bound in the
+ : given query.
+ :
+ : @param $query-key the identifier of a compiled query.
+ : @param $var-name the name of the variable whose value should be returned.
+ :
+ : @return the type of the given variable.
+ :
+ : @error xqxq:NoQueryMatch if no query with the given identifier
+ : was prepared.
+ : @error xqxq:UndeclaredVariable if the given variable is not declared
+ : in the query.
+ : @error xqxq:UnboundVariable if the given variable doesn't have a value.
+ :)
+declare function xqxq:variable-type($query-key as xs:anyURI, $var-name as
+ xs:QName) as xs:string external;
+
+(:~
: Returns the compiled query identified by the given query-key
: as binary data.
:
=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.cpp'
--- modules/xqxq/xqxq.xq.src/xqxq.cpp 2013-03-25 19:01:32 +0000
+++ modules/xqxq/xqxq.xq.src/xqxq.cpp 2013-04-11 20:40:28 +0000
@@ -85,6 +85,10 @@
{
lFunc = new VariableValueFunction(this);
}
+ else if (localName == "variable-type")
+ {
+ lFunc = new VariableTypeFunction(this);
+ }
else if (localName == "query-plan")
{
lFunc = new QueryPlanFunction(this);
@@ -975,6 +979,47 @@
/*******************************************************************************
********************************************************************************/
+zorba::ItemSequence_t VariableTypeFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+{
+ String lQueryID = XQXQFunction::getOneStringArgument(aArgs,0);
+
+ QueryMap* lQueryMap;
+ if (!(lQueryMap= dynamic_cast<QueryMap*>(aDctx->getExternalFunctionParameter("xqxqQueryMap"))))
+ {
+ throwError("NoQueryMatch", "String identifying query does not exists.");
+ }
+
+ XQuery_t lQuery = getQuery(aDctx, lQueryID);
+
+ Item lVarQName = XQXQFunction::getItemArgument(aArgs, 1);
+
+ zorba::DynamicContext* lCtx = lQuery->getDynamicContext();
+ zorba::String lNS = lVarQName.getNamespace(), lLocal = lVarQName.getLocalName();
+ zorba::String lType;
+ try
+ {
+ if(!lCtx->getVariableType(lNS, lLocal, lType))
+ {
+ std::ostringstream lMsg;
+ lMsg << lLocal << ": variable not bound";
+ XQXQFunction::throwError("UndeclaredVariable", lMsg.str());
+ }
+ }
+ catch (ZorbaException& ze)
+ {
+ if (ze.diagnostic() == zerr::ZAPI0011_VARIABLE_NOT_DECLARED)
+ XQXQFunction::throwError("UndeclaredVariable", ze.what());
+ throw; // should not happen
+ }
+ return ItemSequence_t(new SingletonItemSequence(XQXQModule::getItemFactory()->createString(lType)));
+}
+
+/*******************************************************************************
+
+********************************************************************************/
zorba::ItemSequence_t QueryPlanFunction::evaluate(
const Arguments_t& aArgs,
const zorba::StaticContext* aSctx,
=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.h'
--- modules/xqxq/xqxq.xq.src/xqxq.h 2013-03-22 00:09:14 +0000
+++ modules/xqxq/xqxq.xq.src/xqxq.h 2013-04-11 20:40:28 +0000
@@ -529,38 +529,61 @@
const zorba::DynamicContext*) const;
};
- class VariableValueFunction : public XQXQFunction{
- protected:
- class ValueItemSequence : public ItemSequence
- {
- protected:
- Iterator_t theIterator;
-
- public:
- ValueItemSequence(Iterator_t& aIter)
- : theIterator(aIter)
- {
- }
-
- virtual ~ValueItemSequence(){}
-
- Iterator_t
- getIterator() { return theIterator; }
-
- };
- public:
- VariableValueFunction(const XQXQModule* aModule) : XQXQFunction(aModule) {}
-
- virtual ~VariableValueFunction() {}
-
- virtual zorba::String
- getLocalName() const {return "variable-value"; }
-
- virtual zorba::ItemSequence_t
- evaluate(const Arguments_t&,
- const zorba::StaticContext*,
- const zorba::DynamicContext*) const;
- };
+
+/*******************************************************************************
+
+********************************************************************************/
+class VariableValueFunction : public XQXQFunction{
+ protected:
+ class ValueItemSequence : public ItemSequence
+ {
+ protected:
+ Iterator_t theIterator;
+
+ public:
+ ValueItemSequence(Iterator_t& aIter)
+ : theIterator(aIter)
+ {
+ }
+
+ virtual ~ValueItemSequence(){}
+
+ Iterator_t
+ getIterator() { return theIterator; }
+
+ };
+ public:
+ VariableValueFunction(const XQXQModule* aModule) : XQXQFunction(aModule) {}
+
+ virtual ~VariableValueFunction() {}
+
+ virtual zorba::String
+ getLocalName() const {return "variable-value"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+};
+
+/*******************************************************************************
+
+********************************************************************************/
+class VariableTypeFunction : public XQXQFunction
+{
+public:
+ VariableTypeFunction(const XQXQModule* aModule) : XQXQFunction(aModule) {}
+
+ virtual ~VariableTypeFunction() {}
+
+ virtual zorba::String
+ getLocalName() const {return "variable-type"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+};
/*******************************************************************************
@@ -643,6 +666,7 @@
getURLResolver(size_t i) const { return theUrlResolvers.size() < i? NULL : theUrlResolvers[i]; }
};
};
+
}/*xqxq namespace*/}/*zorba namespace*/
=== modified file 'src/api/dynamiccontextimpl.cpp'
--- src/api/dynamiccontextimpl.cpp 2013-03-13 16:17:38 +0000
+++ src/api/dynamiccontextimpl.cpp 2013-04-11 20:40:28 +0000
@@ -184,6 +184,50 @@
return var;
}
+/****************************************************************************//**
+
+********************************************************************************/
+bool DynamicContextImpl::getVariableType(
+ const String& inNamespace,
+ const String& inLocalname,
+ String& outType)
+{
+ ZORBA_DCTX_TRY
+ {
+ checkNoIterators();
+
+ const zstring& nameSpace = Unmarshaller::getInternalString(inNamespace);
+ const zstring& localName = Unmarshaller::getInternalString(inLocalname);
+
+ VarInfo* var = NULL;
+
+ try
+ {
+ var = get_var_info(nameSpace, localName);
+
+ const XQType* varType = var->getType();
+
+ if (!varType)
+ outType = "xs:anyType";
+ else
+ outType = varType->toSchemaString();
+ }
+ catch (ZorbaException const& e)
+ {
+ // Normally, we should be throwing an exception if the variable has not
+ // been declared inside the xquery program, but this cases many failures
+ // with the w3c XQTS.
+ if (e.diagnostic() == err::XPST0008)
+ {
+ return false;
+ }
+ throw;
+ }
+ return true;
+ }
+ ZORBA_DCTX_CATCH
+ return false;
+}
/****************************************************************************//**
=== modified file 'src/api/dynamiccontextimpl.h'
--- src/api/dynamiccontextimpl.h 2013-03-13 16:17:38 +0000
+++ src/api/dynamiccontextimpl.h 2013-04-11 20:40:28 +0000
@@ -83,6 +83,9 @@
public:
+ virtual bool
+ getVariableType(const String& inNamespace, const String& inLocalname, String& outType);
+
virtual bool
getVariable(
const String& inNamespace,
=== added file 'test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable.xml.res'
--- test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable.xml.res 2013-04-11 20:40:28 +0000
@@ -0,0 +1,1 @@
+2 3
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable2.xml.res 2013-04-11 20:40:28 +0000
@@ -0,0 +1,1 @@
+2
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable3.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/xqxq/bind-cast-variable3.xml.res 2013-04-11 20:40:28 +0000
@@ -0,0 +1,1 @@
+success
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/xqxq/variable-type.xml.res'
--- test/rbkt/ExpQueryResults/zorba/xqxq/variable-type.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/xqxq/variable-type.xml.res 2013-04-11 20:40:28 +0000
@@ -0,0 +1,1 @@
+xs:integer xs:string xs:dateTime object() element(*, xs:anyType?)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/xqxq/bind-cast-variable.xq'
--- test/rbkt/Queries/zorba/xqxq/bind-cast-variable.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/xqxq/bind-cast-variable.xq 2013-04-11 20:40:28 +0000
@@ -0,0 +1,4 @@
+import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';
+variable $queryID := xqxq:prepare-main-module('declare variable $ext as xs:integer* external; for $i in $ext return $i+1');
+xqxq:bind-cast-variable( $queryID, xs:QName("ext"), ('1', '2'));
+xqxq:evaluate($queryID)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/xqxq/bind-cast-variable2.xq'
--- test/rbkt/Queries/zorba/xqxq/bind-cast-variable2.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/xqxq/bind-cast-variable2.xq 2013-04-11 20:40:28 +0000
@@ -0,0 +1,4 @@
+import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';
+variable $queryID := xqxq:prepare-main-module('declare variable $ext as object() external; $ext("value")+1');
+xqxq:bind-cast-variable( $queryID, xs:QName("ext"), '{ "value" : 1}');
+xqxq:evaluate($queryID)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/xqxq/bind-cast-variable3.xq'
--- test/rbkt/Queries/zorba/xqxq/bind-cast-variable3.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/xqxq/bind-cast-variable3.xq 2013-04-11 20:40:28 +0000
@@ -0,0 +1,4 @@
+import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';
+variable $queryID := xqxq:prepare-main-module('declare variable $ext as element() external; $ext//b[@id = 131]/text()');
+xqxq:bind-cast-variable( $queryID, xs:QName("ext"), '<a><b id="131">success</b><b id="2">foo</b></a>');
+xqxq:evaluate($queryID)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/xqxq/bind-cast-variable4.spec'
--- test/rbkt/Queries/zorba/xqxq/bind-cast-variable4.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/xqxq/bind-cast-variable4.spec 2013-04-11 20:40:28 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/xqxq:UndeclaredVariable
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/xqxq/bind-cast-variable4.xq'
--- test/rbkt/Queries/zorba/xqxq/bind-cast-variable4.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/xqxq/bind-cast-variable4.xq 2013-04-11 20:40:28 +0000
@@ -0,0 +1,4 @@
+import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';
+variable $queryID := xqxq:prepare-main-module('declare variable $ext external; $ext');
+xqxq:bind-cast-variable( $queryID, xs:QName("ext2"), '2');
+xqxq:evaluate($queryID)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/xqxq/variable-type.xq'
--- test/rbkt/Queries/zorba/xqxq/variable-type.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/xqxq/variable-type.xq 2013-04-11 20:40:28 +0000
@@ -0,0 +1,13 @@
+import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';
+
+variable $queryID := xqxq:prepare-main-module('declare variable $ext as xs:integer external; $ext');
+variable $queryID2 := xqxq:prepare-main-module('declare variable $ext as xs:string external; $ext');
+variable $queryID3 := xqxq:prepare-main-module('declare variable $ext as xs:dateTime external; $ext');
+variable $queryID4 := xqxq:prepare-main-module('declare variable $ext as object() external; $ext');
+variable $queryID5 := xqxq:prepare-main-module('declare variable $ext as element() external; $ext');
+
+xqxq:variable-type($queryID, xs:QName('ext')),
+xqxq:variable-type($queryID2, xs:QName('ext')),
+xqxq:variable-type($queryID3, xs:QName('ext')),
+xqxq:variable-type($queryID4, xs:QName('ext')),
+xqxq:variable-type($queryID5, xs:QName('ext'))
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/xqxq/variable-type2.spec'
--- test/rbkt/Queries/zorba/xqxq/variable-type2.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/xqxq/variable-type2.spec 2013-04-11 20:40:28 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/modules/xqxq:UndeclaredVariable
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/xqxq/variable-type2.xq'
--- test/rbkt/Queries/zorba/xqxq/variable-type2.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/xqxq/variable-type2.xq 2013-04-11 20:40:28 +0000
@@ -0,0 +1,5 @@
+import module namespace xqxq = 'http://www.zorba-xquery.com/modules/xqxq';
+
+variable $queryID := xqxq:prepare-main-module('declare variable $ext as xs:integer external; $ext');
+
+xqxq:variable-type($queryID, xs:QName('ext2'))
\ No newline at end of file
Follow ups
-
[Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-22
-
Re: [Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-22
-
[Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-22
-
[Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba
From: Juan Zacarias, 2013-04-22
-
[Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-19
-
Re: [Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-19
-
[Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-19
-
[Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba
From: Juan Zacarias, 2013-04-19
-
[Merge] lp:~zorba-coders/zorba/bug11369_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-11
-
Re: [Merge] lp:~zorba-coders/zorba/bug11369_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-11
-
[Merge] lp:~zorba-coders/zorba/bug11369_xqxq_bind_cast_variable into lp:zorba
From: Zorba Build Bot, 2013-04-11
-
[Merge] lp:~zorba-coders/zorba/bug11369_xqxq_bind_cast_variable into lp:zorba
From: Juan Zacarias, 2013-04-11