← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba

 

Juan Zacarias has proposed merging lp:~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable into lp:zorba.

Commit message:
*Implementation of Dynamic Context function getVariableType.
*Included new Function getVariableType to the dynamicContext API.
*Implementation of new xqxq functions: xqxq:variable-type 
and xqxq:bind-cast-variable.


Requested reviews:
  Juan Zacarias (juan457)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable/+merge/160214

*Implementation of Dynamic Context function getVariableType.
*Included new Function getVariableType to the dynamicContext API.
*Implementation of new xqxq functions: xqxq:variable-type 
and xqxq:bind-cast-variable.

-- 
https://code.launchpad.net/~zorba-coders/zorba/bug1064978_xqxq_bind_cast_variable/+merge/160214
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-22 21:33:28 +0000
@@ -133,6 +133,21 @@
                Item& aItem,
                Iterator_t& aIterator) 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;
+
   /** \brief Defines the context item.
    *
    * @param aItem the Item that is used as value for the context item.

=== modified file 'modules/xqxq/xqxq.xq'
--- modules/xqxq/xqxq.xq	2013-04-09 14:22:41 +0000
+++ modules/xqxq/xqxq.xq	2013-04-22 21:33:28 +0000
@@ -25,6 +25,9 @@
  :)
 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";;
 declare namespace op = "http://www.zorba-xquery.com/options/features";;
@@ -462,6 +465,81 @@
   $resolver as item()?, $mapper as item()?) as xs:anyURI 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;
+
+(:~
+ : 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, "[*+?]$", "");
+  variable $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 
+        {
+          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);
+          xqxq:evaluate($caster)
+        };
+
+  xqxq:bind-variable($query-key, $var-name, $casted-value)
+};
+
+(:~
  : Internal helper function. Only necessary because of incomplete HOF
  : support in Zorba.
  :)

=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.cpp'
--- modules/xqxq/xqxq.xq.src/xqxq.cpp	2013-04-15 12:07:41 +0000
+++ modules/xqxq/xqxq.xq.src/xqxq.cpp	2013-04-22 21:33:28 +0000
@@ -93,6 +93,10 @@
     {
       lFunc = new LoadFromQueryPlanFunction(this);
     }
+    else if (localName == "variable-type")
+    {
+      lFunc = new VariableTypeFunction(this);
+    }
   }
   
   return lFunc;
@@ -1093,6 +1097,47 @@
   return ItemSequence_t(new SingletonItemSequence(XQXQModule::getItemFactory()->createAnyURI(lStrUUID)));
 }
 
+/*******************************************************************************
+ 
+ ********************************************************************************/
+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)));
+}
+
 }/*namespace xqxq*/ }/*namespace zorba*/
 
 #ifdef WIN32

=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.h'
--- modules/xqxq/xqxq.xq.src/xqxq.h	2013-04-15 12:07:41 +0000
+++ modules/xqxq/xqxq.xq.src/xqxq.h	2013-04-22 21:33:28 +0000
@@ -645,6 +645,26 @@
     getURLResolver(size_t i) const { return theUrlResolvers.size() < i? NULL : theUrlResolvers[i]; }
   };
 };
+
+/*******************************************************************************
+
+********************************************************************************/
+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;
+};
+
 }/*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-22 21:33:28 +0000
@@ -225,7 +225,50 @@
   return false;
 }
 
-
+/****************************************************************************//**
+
+********************************************************************************/
+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-22 21:33:28 +0000
@@ -90,6 +90,12 @@
       Item& outItem,
       Iterator_t& outIterator) const;
 
+  virtual bool 
+  getVariableType(
+      const String& inNamespace, 
+      const String& inLocalname, 
+      String& outType);
+
   virtual bool
   setVariable(
       const String& inVarName,

=== 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-22 21:33: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-22 21:33: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-22 21:33: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-22 21:33: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-22 21:33: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-22 21:33: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-22 21:33: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-22 21:33: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-22 21:33: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

=== modified file 'test/rbkt/Queries/zorba/xqxq/query-plan3.xq'
--- test/rbkt/Queries/zorba/xqxq/query-plan3.xq	2013-03-22 23:09:40 +0000
+++ test/rbkt/Queries/zorba/xqxq/query-plan3.xq	2013-04-22 21:33:28 +0000
@@ -26,3 +26,4 @@
 variable $query-plan := xqxq:query-plan($queryID); 
 variable $queryID2 := xqxq:load-from-query-plan($query-plan, resolver:url-resolver#2, mapper:uri-mapper#2);
 xqxq:evaluate ($queryID2)
+

=== 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-22 21:33: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-22 21:33: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-22 21:33: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