← Back to team overview

zorba-coders team mailing list archive

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

 

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

Commit message:
Implementation of features requested in bug1064978 xqxq: add new bind-variable signature
* Added to the DynamicContext API getVariableType function.
* Added xqxq module function xqxq:variable-type.
* Added xqxq module function xqxq:set-variable.

Requested reviews:
  Sorin Marian Nasoi (sorin.marian.nasoi)
Related bugs:
  Bug #1064978 in Zorba: "xqxq: add new bind-variable signature"
  https://bugs.launchpad.net/zorba/+bug/1064978

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

Implementation of features requested in bug1064978 xqxq: add new bind-variable signature
* Added to the DynamicContext API getVariableType function.
* Added xqxq module function xqxq:variable-type.
* Added xqxq module function xqxq:set-variable.
-- 
https://code.launchpad.net/~zorba-coders/zorba/bug1064978/+merge/150696
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'include/zorba/dynamic_context.h'
--- include/zorba/dynamic_context.h	2012-10-22 17:08:12 +0000
+++ include/zorba/dynamic_context.h	2013-02-26 23:49:25 +0000
@@ -312,6 +312,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-02-15 06:11:20 +0000
+++ modules/xqxq/xqxq.xq	2013-02-26 23:49:25 +0000
@@ -286,6 +286,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 set 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:set-variable($query-key as xs:anyURI, $var-name as 
+  xs:QName, $value as xs:string*) as empty-sequence()
+  {
+    let $type := xqxq:variable-type($query-key, $var-name)
+    let $casted-value :=                                                         
+      if ($type eq "xs:integer" or $type eq "xs:integer*") then 
+        for $val in $value return xs:integer($val) 
+      else if ($type eq "xs:int" or $type eq "xs:int*") then 
+        for $val in $value return xs:int($val)   
+      else if ($type eq "xs:long" or $type eq "xs:long*") then 
+        for $val in $value return xs:long($val)  
+      else if ($type eq "xs:short" or $type eq "xs:short*") then 
+        for $val in $value return xs:short($val)   
+      else if ($type eq "xs:decimal" or $type eq "xs:decimal*") then 
+        for $val in $value return xs:decimal($val)  
+      else if ($type eq "xs:double" or $type eq "xs:double*") then 
+        for $val in $value return xs:double($val)
+      else if ($type eq "xs:float" or $type eq "xs:float*") then 
+        for $val in $value return xs:float($val)
+      else if ($type eq "xs:date" or $type eq "xs:date*") then 
+        for $val in $value return xs:date($val) 
+      else if ($type eq "xs:time" or $type eq "xs:time*") then 
+        for $val in $value return xs:time($val)  
+      else if ($type eq "xs:dateTime" or $type eq "xs:dateTime") then 
+        for $val in $value return xs:dateTime($val)    
+      else if ($type eq "object()" or $type eq "object()*") then
+        for $val in $value return jn:parse-json($val)    
+      else if ($type eq "array()" or $type eq "array()*") then
+        for $val in $value return jn:parse-json($val)
+      else if (fn:contains($type, "document-node(")) then
+        for $val in $value return fn:parse-xml($val)  
+      else if (fn:contains($type, "element(")) then
+        for $val in $value return fn:parse-xml($val)/element()  
+      else $value                       
+    return xqxq:bind-variable($query-key, $var-name, $casted-value)
+  };    
 
 (:~
  : Evaluates the given prepared query and returns the result
@@ -387,6 +447,23 @@
 declare function xqxq:variable-value($query-key as xs:anyURI, $var-name as 
   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;                               
 
 (:~
  : Internal helper function. Only necessary because of incomplete HOF

=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.cpp'
--- modules/xqxq/xqxq.xq.src/xqxq.cpp	2013-02-22 17:09:54 +0000
+++ modules/xqxq/xqxq.xq.src/xqxq.cpp	2013-02-26 23:49:25 +0000
@@ -85,6 +85,10 @@
     {
       lFunc = new VariableValueFunction(this);
     }
+    else if (localName == "variable-type")
+    {
+      lFunc = new VariableTypeFunction(this);
+    }
   }
   
   return lFunc;
@@ -964,6 +968,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("UnboundVariable", 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*/
 

=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.h'
--- modules/xqxq/xqxq.xq.src/xqxq.h	2013-02-15 06:11:20 +0000
+++ modules/xqxq/xqxq.xq.src/xqxq.h	2013-02-26 23:49:25 +0000
@@ -528,38 +528,62 @@
            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;
+};
 
 
 }/*xqxq namespace*/}/*zorba namespace*/

=== modified file 'src/api/dynamiccontextimpl.cpp'
--- src/api/dynamiccontextimpl.cpp	2013-01-08 08:34:08 +0000
+++ src/api/dynamiccontextimpl.cpp	2013-02-26 23:49:25 +0000
@@ -183,7 +183,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	2012-10-22 17:08:12 +0000
+++ src/api/dynamiccontextimpl.h	2013-02-26 23:49:25 +0000
@@ -162,6 +162,9 @@
   virtual bool
   isBoundContextItem() const;
 
+  virtual bool 
+  getVariableType(const String& inNamespace, const String& inLocalname, String& outType);
+
 protected:
   void checkNoIterators() const;
 


Follow ups