← Back to team overview

zorba-coders team mailing list archive

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

 

Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/markos2 into lp:zorba.

Requested reviews:
  Matthias Brantner (matthias-brantner)
  Markos Zaharioudakis (markos-za)

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

Groupby optimization: If possible, use directly the store Item::equals method to compare groupby tuples.  
-- 
https://code.launchpad.net/~zorba-coders/zorba/markos2/+merge/80129
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/compiler/codegen/plan_visitor.cpp'
--- src/compiler/codegen/plan_visitor.cpp	2011-09-16 19:36:18 +0000
+++ src/compiler/codegen/plan_visitor.cpp	2011-10-22 15:51:27 +0000
@@ -199,7 +199,10 @@
 
 
 /*******************************************************************************
-
+  A FlworClauseVarMap is created for each flwor clause that defines variables.
+  If M is such a clause, then for each variable Vi defined by M, theVarExprs[i]
+  and theVarRebinds[i] contain an entry for Vi. theVarExprs[i] contains the
+  var_expr representing the Vi definition. 
 ********************************************************************************/
 class FlworClauseVarMap : public SimpleRCObject
 {
@@ -207,7 +210,7 @@
   bool                          theIsGeneral;
   const flwor_clause          * theClause;
 
-  std::vector<const var_expr*>  theVarExprs;
+  std::vector<var_expr*>        theVarExprs;
   std::vector<VarRebind_t>      theVarRebinds;
 
 public:
@@ -222,8 +225,8 @@
 
   long find_var(const var_expr* var) const
   {
-    ulong numVars = (ulong)theVarExprs.size();
-    for (ulong i = 0; i < numVars; ++i)
+    csize numVars = theVarExprs.size();
+    for (csize i = 0; i < numVars; ++i)
     {
       if (theVarExprs[i] == var)
         return i;
@@ -759,7 +762,7 @@
         {
           varRebind = new VarRebind;
 
-          clauseVarMap->theVarExprs.push_back(&var);
+          clauseVarMap->theVarExprs.push_back(const_cast<var_expr*>(&var));
           clauseVarMap->theVarRebinds.push_back(varRebind);
 
           varRebind->theInputVar = varIter;
@@ -1189,14 +1192,14 @@
     const group_clause::rebind_list_t& grouping_vars = gbc->get_grouping_vars();
     const group_clause::rebind_list_t& nongrouping_vars = gbc->get_nongrouping_vars();
 
-    for (unsigned i = 0; i < grouping_vars.size(); i++)
+    for (unsigned i = 0; i < grouping_vars.size(); ++i)
     {
       VarRebind_t varRebind = new VarRebind;
       clauseVarMap->theVarExprs.push_back(grouping_vars[i].second.getp());
       clauseVarMap->theVarRebinds.push_back(varRebind);
     }
 
-    for (unsigned i = 0; i < nongrouping_vars.size(); i++)
+    for (unsigned i = 0; i < nongrouping_vars.size(); ++i)
     {
       VarRebind_t varRebind = new VarRebind;
       clauseVarMap->theVarExprs.push_back(nongrouping_vars[i].second.getp());
@@ -1363,22 +1366,17 @@
 
   xqtref_t colType = colExpr->get_return_type();
 
-  if (TypeOps::is_subtype(tm, *colType, *rtm.STRING_TYPE_STAR, loc) ||
-      TypeOps::is_subtype(tm, *colType, *rtm.DOUBLE_TYPE_STAR, loc) ||
-      TypeOps::is_subtype(tm, *colType, *rtm.FLOAT_TYPE_STAR, loc) ||
-      TypeOps::is_subtype(tm, *colType, *rtm.LONG_TYPE_STAR, loc) ||
-      TypeOps::is_subtype(tm, *colType, *rtm.UNSIGNED_LONG_TYPE_STAR, loc) ||
-      TypeOps::is_equal(tm,
-                        *TypeOps::prime_type(tm, *colType),
-                        *rtm.DECIMAL_TYPE_ONE,
-                        loc) ||
-      TypeOps::is_equal(tm,
-                        *TypeOps::prime_type(tm, *colType),
-                        *rtm.INTEGER_TYPE_ONE,
-                        loc) ||
-      TypeOps::is_subtype(tm, *colType, *rtm.DATE_TYPE_STAR, loc) ||
-      TypeOps::is_subtype(tm, *colType, *rtm.TIME_TYPE_STAR, loc) ||
-      TypeOps::is_subtype(tm, *colType, *rtm.DATETIME_TYPE_STAR, loc))
+  if (TypeOps::is_subtype(tm, *colType, *rtm.ANY_NODE_TYPE_STAR, loc))
+  {
+    colType = static_cast<const NodeXQType*>(colType.getp())->get_content_type();
+  }
+
+  if (colType != NULL &&
+      TypeOps::is_subtype(tm, *colType, *rtm.ANY_ATOMIC_TYPE_STAR, loc) &&
+      !TypeOps::is_equal(tm, 
+                         *TypeOps::prime_type(tm, *colType),
+                         *rtm.ANY_ATOMIC_TYPE_ONE,
+                         loc))
   {
     return true;
   }
@@ -1669,7 +1667,7 @@
     if (c.get_kind() != flwor_clause::where_clause)
     {
       ZORBA_ASSERT(!theClauseStack.empty());
-      ulong stackSize = (ulong)theClauseStack.size();
+      csize stackSize = theClauseStack.size();
 
       clauseVarMap = theClauseStack[stackSize-1];
       theClauseStack.resize(stackSize - 1);
@@ -1878,9 +1876,12 @@
     std::vector<flwor::NonGroupingSpec>& ngspecs)
 {
   const group_clause* gbc = static_cast<const group_clause*>(clauseVarMap->theClause);
+
   const group_clause::rebind_list_t& gvars = gbc->get_grouping_vars();
   const group_clause::rebind_list_t& ngvars = gbc->get_nongrouping_vars();
+
   const std::vector<std::string>& collations = gbc->get_collations();
+
   long numVars = (long)(gvars.size() + ngvars.size());
   long numGroupVars = (long)gvars.size();
   long i = numVars - 1;
@@ -1900,7 +1901,12 @@
 
     const std::vector<PlanIter_t>& varRefs = varRebind->theOutputVarRefs;
 
-    gspecs.push_back(flwor::GroupingSpec(pop_itstack(), varRefs, collations[i]));
+    bool fastComparison = nativeColumnSort(clauseVarMap->theVarExprs[i]);
+
+    gspecs.push_back(flwor::GroupingSpec(pop_itstack(),
+                                         varRefs,
+                                         collations[i],
+                                         fastComparison));
   }
 }
 

=== modified file 'src/compiler/expression/flwor_expr.cpp'
--- src/compiler/expression/flwor_expr.cpp	2011-08-15 14:17:09 +0000
+++ src/compiler/expression/flwor_expr.cpp	2011-10-22 15:51:27 +0000
@@ -616,26 +616,26 @@
   theNonGroupVars(ngvars),
   theCollations(collations)
 {
-  ulong numGVars = (ulong)theGroupVars.size();
-  ulong numNGVars = (ulong)theNonGroupVars.size();
+  csize numGVars = theGroupVars.size();
+  csize numNGVars = theNonGroupVars.size();
 
-  for (ulong i = 0; i < numGVars; ++i)
+  for (csize i = 0; i < numGVars; ++i)
     theGroupVars[i].second->set_flwor_clause(this);
 
-  for (ulong i = 0; i < numNGVars; ++i)
+  for (csize i = 0; i < numNGVars; ++i)
     theNonGroupVars[i].second->set_flwor_clause(this);
 }
 
 
 group_clause::~group_clause()
 {
-  ulong numGVars = (ulong)theGroupVars.size();
-  ulong numNGVars = (ulong)theNonGroupVars.size();
+  csize numGVars = theGroupVars.size();
+  csize numNGVars = theNonGroupVars.size();
 
-  for (ulong i = 0; i < numGVars; ++i)
+  for (csize i = 0; i < numGVars; ++i)
     theGroupVars[i].second->set_flwor_clause(NULL);
 
-  for (ulong i = 0; i < numNGVars; ++i)
+  for (csize i = 0; i < numNGVars; ++i)
     theNonGroupVars[i].second->set_flwor_clause(NULL);
 }
 
@@ -651,8 +651,8 @@
 
 expr* group_clause::get_input_for_group_var(const var_expr* var)
 {
-  ulong numVars = (ulong)theGroupVars.size();
-  for (ulong i = 0; i < numVars; ++i)
+  csize numVars = theGroupVars.size();
+  for (csize i = 0; i < numVars; ++i)
   {
     if (theGroupVars[i].second.getp() == var)
       return theGroupVars[i].first.getp();
@@ -664,8 +664,8 @@
 
 expr* group_clause::get_input_for_nongroup_var(const var_expr* var)
 {
-  ulong numVars = (ulong)theNonGroupVars.size();
-  for (ulong i = 0; i < numVars; ++i)
+  csize numVars = theNonGroupVars.size();
+  for (csize i = 0; i < numVars; ++i)
   {
     if (theNonGroupVars[i].second.getp() == var)
       return theNonGroupVars[i].first.getp();
@@ -677,20 +677,20 @@
 
 flwor_clause_t group_clause::clone(expr::substitution_t& subst) const
 {
-  ulong numGroupVars = (ulong)theGroupVars.size();
-  ulong numNonGroupVars = (ulong)theNonGroupVars.size();
+  csize numGroupVars = theGroupVars.size();
+  csize numNonGroupVars = theNonGroupVars.size();
 
   rebind_list_t cloneGroupVars(numGroupVars);
   rebind_list_t cloneNonGroupVars(numNonGroupVars);
 
-  for (ulong i = 0; i < numGroupVars; ++i)
+  for (csize i = 0; i < numGroupVars; ++i)
   {
     cloneGroupVars[i].first = theGroupVars[i].first->clone(subst);
     cloneGroupVars[i].second = new var_expr(*theGroupVars[i].second);
     subst[theGroupVars[i].second.getp()] = cloneGroupVars[i].second.getp();
   }
 
-  for (ulong i = 0; i < numNonGroupVars; ++i)
+  for (csize i = 0; i < numNonGroupVars; ++i)
   {
     cloneNonGroupVars[i].first = theNonGroupVars[i].first->clone(subst);
     cloneNonGroupVars[i].second = new var_expr(*theNonGroupVars[i].second);

=== modified file 'src/runtime/core/flwor_iterator.cpp'
--- src/runtime/core/flwor_iterator.cpp	2011-06-28 15:07:06 +0000
+++ src/runtime/core/flwor_iterator.cpp	2011-10-22 15:51:27 +0000
@@ -18,6 +18,7 @@
 #include "zorbautils/fatal.h"
 #include "diagnostics/assert.h"
 #include "diagnostics/xquery_diagnostics.h"
+#include "diagnostics/util_macros.h"
 
 #include "context/static_context.h"
 
@@ -1474,9 +1475,9 @@
           store::Item_t temp;
           if (typedValueIter->next(temp))
           {
-            throw XQUERY_EXCEPTION(err::XPTY0004,
-                                   ERROR_PARAMS(ZED(SingletonExpected_2o),
-                                                ZED(AtomizationHasMoreThanOneValue)));
+            RAISE_ERROR(err::XPTY0004, loc,
+            ERROR_PARAMS(ZED(SingletonExpected_2o),
+                         ZED(AtomizationHasMoreThanOneValue)));
           }
         }
       }
@@ -1485,9 +1486,7 @@
       store::Item_t temp;
       if (consumeNext(temp, specIter->theInput, planState))
       {
-        throw XQUERY_EXCEPTION(
-          err::XPTY0004, ERROR_PARAMS(ZED(SingletonExpected_2o))
-        );
+        RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(SingletonExpected_2o)));
       }
     }
 

=== modified file 'src/runtime/core/gflwor/common.cpp'
--- src/runtime/core/gflwor/common.cpp	2011-06-14 17:26:33 +0000
+++ src/runtime/core/gflwor/common.cpp	2011-10-22 15:51:27 +0000
@@ -43,11 +43,13 @@
 GroupingSpec::GroupingSpec(
     PlanIter_t inputVar,
     const std::vector<PlanIter_t>& varRefs,
-    const std::string& collation)
+    const std::string& collation,
+    bool doFastComparison)
   :
   theInput(inputVar),
   theCollation(collation),
-  theCollator(NULL)
+  theCollator(NULL),
+  theDoFastComparison(doFastComparison)
 {
   castIterVector<ForVarIterator>(theVarRefs, varRefs);
 }
@@ -59,6 +61,7 @@
   ar & theVarRefs;
   ar & theCollation;
   ar & theCollator;
+  ar & theDoFastComparison;
 }
 
 
@@ -170,7 +173,7 @@
     const QueryLoc& loc,
     dynamic_context* dctx,
     const TypeManager* tm,
-    std::vector<GroupingSpec>* groupingSpecs) 
+    std::vector<GroupingSpec>* groupingSpecs)
   :
   theLocation(loc),
   theGroupingSpecs(groupingSpecs),
@@ -184,9 +187,9 @@
 {
   uint32_t hash = 0;
 
-  ulong numCols = (ulong)theGroupingSpecs->size();
+  csize numCols = theGroupingSpecs->size();
 
-  for (ulong i = 0; i < numCols; i++)
+  for (csize i = 0; i < numCols; i++)
   {
     if (t->theTypedValues[i] != NULL)
     {
@@ -229,19 +232,30 @@
 
       try
       {
-        if (!CompareIterator::valueEqual(theLocation,
-                                         item1,
-                                         item2,
-                                         theTypeManager,
-                                         theTimezone,
-                                         (*theGroupingSpecs)[i].theCollator))
-        {
-          return false;                                 
+        if ((*theGroupingSpecs)[i].theDoFastComparison)
+        {
+          if (!item1->equals(item2, theTimezone, (*theGroupingSpecs)[i].theCollator))
+          {
+            return false;
+          }
+        }
+        else
+        {
+          if (!CompareIterator::valueEqual(theLocation,
+                                           item1,
+                                           item2,
+                                           theTypeManager,
+                                           theTimezone,
+                                           (*theGroupingSpecs)[i].theCollator))
+          {
+            return false;                                 
+          }
         }
       }
       catch (ZorbaException const& e)
       {
-        if (e.diagnostic() == err::XPTY0004)
+        if (e.diagnostic() == err::XPTY0004 ||
+            e.diagnostic() == zerr::ZSTR0040_TYPE_ERROR)
           return false;
         else
           throw;

=== modified file 'src/runtime/core/gflwor/common.h'
--- src/runtime/core/gflwor/common.h	2011-06-14 17:26:33 +0000
+++ src/runtime/core/gflwor/common.h	2011-10-22 15:51:27 +0000
@@ -107,6 +107,7 @@
   std::vector<ForVarIter_t> theVarRefs;
   std::string               theCollation;
   XQPCollator             * theCollator;
+  bool                      theDoFastComparison;
 
 public:
   SERIALIZABLE_CLASS(GroupingSpec)
@@ -119,7 +120,8 @@
   GroupingSpec(
         PlanIter_t inputVar,
         const std::vector<PlanIter_t>& varRefs,
-        const std::string& aCollation);
+        const std::string& aCollation,
+        bool doFastComparison);
 
   virtual ~GroupingSpec() {}
 

=== modified file 'src/runtime/core/gflwor/groupby_iterator.cpp'
--- src/runtime/core/gflwor/groupby_iterator.cpp	2011-06-14 17:26:33 +0000
+++ src/runtime/core/gflwor/groupby_iterator.cpp	2011-10-22 15:51:27 +0000
@@ -18,6 +18,7 @@
 #include "zorbautils/fatal.h"
 #include "diagnostics/assert.h"
 #include "diagnostics/xquery_diagnostics.h"
+#include "diagnostics/util_macros.h"
 
 #include "context/static_context.h"
 
@@ -358,10 +359,10 @@
   std::vector<store::Item_t>& groupTupleItems = groupTuple->theItems;
   std::vector<store::Item_t>& groupTupleValues = groupTuple->theTypedValues;
 
-  ulong numVars = (ulong)theGroupingSpecs.size();
+  csize numVars = theGroupingSpecs.size();
 
   // For each grouping variable
-  for (ulong i = 0; i < numVars; ++i)
+  for (csize i = 0; i < numVars; ++i)
   {
     groupTupleItems.push_back(NULL);
     groupTupleValues.push_back(NULL);
@@ -379,11 +380,8 @@
       // than 1 item.
       if (consumeNext(temp, theGroupingSpecs[i].theInput.getp(), aPlanState)) 
       {
-        throw XQUERY_EXCEPTION(
-          err::XPTY0004,
-          ERROR_PARAMS( ZED( GroupByVarHasMoreThanOneItem_2 ) ),
-          ERROR_LOC( loc )
-        );
+        RAISE_ERROR(err::XPTY0004, loc,
+        ERROR_PARAMS(ZED(GroupByVarHasMoreThanOneItem_2)));
       }
 
       store::Iterator_t typedValueIter;
@@ -405,11 +403,8 @@
             
             if (typedValueIter->next(temp))
             {
-              throw XQUERY_EXCEPTION(
-                err::XPTY0004,
-                ERROR_PARAMS( ZED( AtomizationOfGroupByMakesMoreThanOneItem ) ),
-                ERROR_LOC( loc )
-              );
+              RAISE_ERROR(err::XPTY0004, loc,
+              ERROR_PARAMS(ZED(AtomizationOfGroupByMakesMoreThanOneItem)));
             }
           }
         }

=== modified file 'src/store/naive/atomic_items.cpp'
--- src/store/naive/atomic_items.cpp	2011-09-30 14:06:33 +0000
+++ src/store/naive/atomic_items.cpp	2011-10-22 15:51:27 +0000
@@ -562,6 +562,18 @@
 }
 
 
+bool UntypedAtomicItem::equals(
+    const store::Item* other,
+    long timezone,
+    const XQPCollator* collation) const
+{
+  if (collation == NULL || collation->doMemCmp())
+    return theValue == other->getString();
+
+  return (utf8::compare(theValue, other->getString(), collation) == 0);
+}
+
+
 store::Item_t UntypedAtomicItem::getEBV() const
 {
   bool b = ! ( theValue == "" );
@@ -598,11 +610,13 @@
   GET_STORE().getQNamePool().remove(this);
 }
 
+
 QNameItem* QNameItem::getNormalized() const
 {
   return (isNormalized() ? const_cast<QNameItem*>(this) : theNormQName.getp());
 }
 
+
 uint32_t QNameItem::hash(long timezone, const XQPCollator* aCollation) const
 {
   const void* tmp = getNormalized();
@@ -618,22 +632,20 @@
 
 store::Item_t QNameItem::getEBV() const
 {
-  throw XQUERY_EXCEPTION(
-    err::FORG0006,
-    ERROR_PARAMS(
-      ZED( OperationNotDef_23 ), ZED( EffectiveBooleanValue ), "QName"
-    )
-  );
+  throw XQUERY_EXCEPTION(err::FORG0006,
+  ERROR_PARAMS(ZED(OperationNotDef_23), ZED(EffectiveBooleanValue), "QName"));
 }
 
+
 bool QNameItem::equals(
-        const store::Item* item,
-        long timezone,
-        const XQPCollator* aCollation) const
+    const store::Item* item,
+    long timezone,
+    const XQPCollator* aCollation) const
 {
   return (getNormalized() == static_cast<const QNameItem*>(item)->getNormalized());
 }
 
+
 zstring QNameItem::getStringValue() const
 {
   if (thePrefix.empty())
@@ -742,7 +754,8 @@
                           long timezone,
                           const XQPCollator* aCollation) const
 {
-  return (theQName->getNormalized() == static_cast<const NotationItem*>(item)->theQName->getNormalized());
+  return (theQName->getNormalized() == 
+          static_cast<const NotationItem*>(item)->theQName->getNormalized());
 }
 
 
@@ -849,6 +862,8 @@
     long timezone,
     const XQPCollator* aCollation) const
 {
+  // Note: utf8::compare does byte comparison if the collation is null or
+  // requires byte comparison.
   return utf8::compare(theValue, other->getString(), aCollation);
 }
 
@@ -871,10 +886,11 @@
 }
 
 #ifndef ZORBA_NO_FULL_TEXT
-FTTokenIterator_t
-StringItem::getTokens( TokenizerProvider const &provider,
-                       Tokenizer::Numbers &numbers, iso639_1::type lang,
-                       bool wildcards ) const
+FTTokenIterator_t StringItem::getTokens( 
+    TokenizerProvider const &provider,
+    Tokenizer::Numbers &numbers,
+    iso639_1::type lang,
+    bool wildcards ) const
 {
   typedef NaiveFTTokenIterator::container_type tokens_t;
   unique_ptr<tokens_t> tokens( new tokens_t );
@@ -893,7 +909,8 @@
 ********************************************************************************/
 void StreamableStringItem::appendStringValue(zstring& aBuf) const
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   aBuf += theValue;
@@ -905,7 +922,8 @@
     long aTimezone,
     const XQPCollator* aCollator) const
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   return StringItem::compare(aOther, aTimezone, aCollator);
@@ -917,7 +935,8 @@
     long aTimezone,
     XQPCollator const* aCollator) const 
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   return StringItem::equals(aItem, aTimezone, aCollator);
@@ -926,7 +945,8 @@
 
 store::Item_t StreamableStringItem::getEBV() const
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   return StringItem::getEBV();
@@ -935,7 +955,8 @@
 
 zstring const& StreamableStringItem::getString() const
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   return theValue;
@@ -944,7 +965,8 @@
 
 zstring StreamableStringItem::getStringValue() const
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   return theValue;
@@ -953,7 +975,8 @@
 
 void StreamableStringItem::getStringValue2(zstring &val) const
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   val = theValue;
@@ -964,7 +987,8 @@
     long aTimezone,
     XQPCollator const* aCollator) const
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   return StringItem::hash(aTimezone, aCollator);
@@ -973,7 +997,8 @@
 
 zstring StreamableStringItem::show() const
 {
-  if (!theIsMaterialized) {
+  if (!theIsMaterialized) 
+  {
     materialize();
   }
   return StringItem::show();
@@ -1016,11 +1041,13 @@
   return theIstream;
 }
 
+
 StreamReleaser StreamableStringItem::getStreamReleaser()
 {
   return theStreamReleaser;
 }
 
+
 void StreamableStringItem::setStreamReleaser(StreamReleaser aReleaser)
 {
   theStreamReleaser = aReleaser;

=== modified file 'src/store/naive/atomic_items.h'
--- src/store/naive/atomic_items.h	2011-09-30 14:06:33 +0000
+++ src/store/naive/atomic_items.h	2011-10-22 15:51:27 +0000
@@ -308,12 +308,9 @@
   bool equals(
         const store::Item* other,
         long timezone = 0,
-        const XQPCollator* aCollation = 0) const
-  {
-    return theValue == other->getString();
-  }
+        const XQPCollator* collation = 0) const;
 
-  store::Item_t getEBV( ) const;
+  store::Item_t getEBV() const;
 
   zstring getStringValue() const { return theValue; }
 
@@ -637,7 +634,8 @@
 
   ~StreamableStringItem()
   {
-    if (theStreamReleaser) {
+    if (theStreamReleaser) 
+    {
       theStreamReleaser(&theIstream);
     }
   }

=== modified file 'src/types/casting.cpp'
--- src/types/casting.cpp	2011-07-29 22:38:19 +0000
+++ src/types/casting.cpp	2011-10-22 15:51:27 +0000
@@ -25,6 +25,7 @@
 
 #include "diagnostics/xquery_diagnostics.h"
 #include "diagnostics/assert.h"
+#include "diagnostics/util_macros.h"
 
 #include "context/namespace_context.h"
 
@@ -64,13 +65,18 @@
 
 struct ErrorInfo
 {
-  const XQType* theSourceType;
-  const XQType* theTargetType;
+  const XQType   * theSourceType;
+  const XQType   * theTargetType;
+  const QueryLoc & theLoc;
 };
 
 
-#define TYPE_EXCEPTION( ERROR_CODE, ERROR_INFO ) \
-  XQUERY_EXCEPTION( ERROR_CODE, ERROR_PARAMS( *(ERROR_INFO).theSourceType, ZED( NoCastTo_34o ), *(ERROR_INFO).theTargetType ) )
+#define TYPE_EXCEPTION( ERROR_CODE, ERROR_INFO )  \
+  XQUERY_EXCEPTION(ERROR_CODE,                    \
+  ERROR_PARAMS(*(ERROR_INFO).theSourceType,       \
+               ZED( NoCastTo_34o ),               \
+               *(ERROR_INFO).theTargetType ),     \
+  ERROR_LOC(ERROR_INFO.theLoc) )
 
 
 /*******************************************************************************
@@ -136,41 +142,49 @@
 
 T1_TO_T2(str, flt)
 {
-  try {
+  try 
+  {
     xs_float const n(strval.c_str());
     return aFactory->createFloat(result, n);
   }
-  catch ( std::invalid_argument const& ) {
-    throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  catch (std::invalid_argument const&) 
+  {
+    throw TYPE_EXCEPTION(err::FORG0001, aErrorInfo);
   }
-  catch ( std::range_error const& ) {
-    throw XQUERY_EXCEPTION( err::FOAR0002, ERROR_PARAMS( strval ) );
+  catch ( std::range_error const& ) 
+  {
+    throw XQUERY_EXCEPTION(err::FOAR0002, ERROR_PARAMS(strval));
   }
 }
 
 
 T1_TO_T2(str, dbl)
 {
-  try {
+  try 
+  {
     xs_double const n(strval.c_str());
     return aFactory->createDouble(result, n);
   }
-  catch ( std::invalid_argument const& ) {
+  catch (std::invalid_argument const& ) 
+  {
     throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
   }
-  catch ( std::range_error const& ) {
-    throw XQUERY_EXCEPTION( err::FOAR0002, ERROR_PARAMS( strval ) );
+  catch (std::range_error const& ) 
+  {
+    throw XQUERY_EXCEPTION(err::FOAR0002, ERROR_PARAMS(strval));
   }
 }
 
 
 T1_TO_T2(str, dec)
 {
-  try {
+  try 
+  {
     xs_decimal const n(strval.c_str());
     return aFactory->createDecimal(result, n);
   }
-  catch ( std::exception const& ) {
+  catch ( std::exception const& ) 
+  {
     throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
   }
 }
@@ -178,14 +192,17 @@
 
 T1_TO_T2(str, int)
 {
-  try {
+  try 
+  {
     xs_integer const n(strval.c_str());
     return aFactory->createInteger(result, n);
   }
-  catch ( std::invalid_argument const& ) {
+  catch ( std::invalid_argument const& ) 
+  {
     throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
   }
-  catch ( std::range_error const& ) {
+  catch ( std::range_error const& ) 
+  {
     throw TYPE_EXCEPTION( err::FOAR0002, aErrorInfo );
   }
 }
@@ -199,7 +216,7 @@
   if (0 == (err = Duration::parseDuration(strval.c_str(), strval.size(), d)))
     return aFactory->createDuration(result, &d);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throw TYPE_EXCEPTION(err::FORG0001, aErrorInfo);
 }
 
 
@@ -1669,7 +1686,7 @@
 
   const XQType* sourceType = rtm.STRING_TYPE_ONE.getp();
 
-  ErrorInfo lErrorInfo = {&*sourceType, aTargetType};
+  ErrorInfo lErrorInfo = {&*sourceType, aTargetType, loc};
 
   if (!TypeOps::is_atomic(tm, *aTargetType))
     throw XQUERY_EXCEPTION( err::XPST0051, ERROR_PARAMS( aTargetType ) );
@@ -1740,112 +1757,110 @@
 
 
 /*******************************************************************************
-  Cast, if possible, a given item SI to an atomic item TI of a given type TT.
-  If I1 is not
+  Cast, if possible, a given atomic item SI to an atomic item TI of a given 
+  type TT. If the cast is not allowed, the method raises an error. If the cast
+  is not possible, the method may raise an error or return false (TODO fix 
+  this!). Otherwise, it returns true.
 ********************************************************************************/
 bool GenericCast::castToAtomic(
     store::Item_t&       result,
     store::Item_t&       aItem,
-    const XQType*        aTargetType,
+    const XQType*        targetType,
     const TypeManager*   tm,
-    namespace_context*   aNCtx,
+    namespace_context*   nsCtx,
     const QueryLoc&      loc)
 {
   RootTypeManager& rtm = GENV_TYPESYSTEM;
-  store::ItemFactory* lFactory = GENV_ITEMFACTORY;
-
-  xqtref_t lSourceType = tm->create_named_type(aItem->getType(),
-                                               TypeConstants::QUANT_ONE,
-                                               QueryLoc::null,
-                                               err::XPTY0004);
+  store::ItemFactory* factory = GENV_ITEMFACTORY;
 
   ZORBA_ASSERT(aItem->isAtomic());
-  ZORBA_ASSERT(lSourceType != NULL);
-  ZORBA_ASSERT(TypeOps::is_atomic(tm, *lSourceType));
+
+  xqtref_t sourceType = tm->create_named_type(aItem->getType(),
+                                              TypeConstants::QUANT_ONE,
+                                              QueryLoc::null,
+                                              err::XPTY0004);
+  ZORBA_ASSERT(sourceType != NULL);
+  assert(TypeOps::is_atomic(tm, *sourceType));
 
   // std::cout << "-castToAtomic: " << aItem.getp()->getStringValue()->c_str()
-  //           << " srcType: " << lSourceType->get_qname()->getLocalName()->c_str()
-  //           << " @ " << lSourceType->get_qname()->getNamespace()->c_str() << "\n";
+  //           << " srcType: " << sourceType->get_qname()->getLocalName()->c_str()
+  //           << " @ " << sourceType->get_qname()->getNamespace()->c_str() << "\n";
   // std::cout << "\t\t  tgtType: " << aTargetType->get_qname()->getLocalName()->c_str()
   //           << " @ " << aTargetType->get_qname()->getNamespace()->c_str() << "\n";
 
-  ErrorInfo lErrorInfo = {&*lSourceType, aTargetType};
+  ErrorInfo errorInfo = {&*sourceType, targetType, loc};
 
-  if (!TypeOps::is_atomic(tm, *aTargetType))
-    throw XQUERY_EXCEPTION(err::XPST0051, ERROR_PARAMS(aTargetType));
+  if (!TypeOps::is_atomic(tm, *targetType))
+    RAISE_ERROR(err::XPST0051, loc, ERROR_PARAMS(targetType));
 
 #ifndef ZORBA_NO_XMLSCHEMA
-  if (aTargetType->type_kind() == XQType::USER_DEFINED_KIND)
+  if (targetType->type_kind() == XQType::USER_DEFINED_KIND)
   {
-    castToUserDefinedType(result, aItem, lSourceType.getp(), aTargetType, loc);
+    castToUserDefinedType(result, aItem, sourceType.getp(), targetType, loc);
     return result != NULL;
   }
 #endif // ZORBA_NO_XMLSCHEMA
 
+  sourceType = sourceType->getBaseBuiltinType();
+
   zstring sourceString;
-  ATOMIC_CODE_T lSourceTypeCode;
-  ATOMIC_CODE_T lTargetTypeCode = TypeOps::get_atomic_type_code(*aTargetType);
-
-  lSourceType = lSourceType->getBaseBuiltinType();
-
-  ZORBA_ASSERT(TypeOps::is_builtin_atomic(tm, *lSourceType));
-
-  lSourceTypeCode = TypeOps::get_atomic_type_code(*lSourceType);
-
-  if (lSourceTypeCode == lTargetTypeCode)
+  ATOMIC_CODE_T sourceTypeCode = TypeOps::get_atomic_type_code(*sourceType);
+  ATOMIC_CODE_T targetTypeCode = TypeOps::get_atomic_type_code(*targetType);
+
+  if (sourceTypeCode == targetTypeCode)
   {
     result.transfer(aItem);
     return true;
   }
 
-  if (theMapping[lSourceTypeCode] == theMapping[TypeConstants::XS_STRING])
+  if (targetTypeCode == TypeConstants::XS_NOTATION ||
+      targetTypeCode == TypeConstants::XS_ANY_ATOMIC)
+  {
+    RAISE_ERROR(err::XPST0080, loc,
+    ERROR_PARAMS(*errorInfo.theTargetType));
+  }
+
+  if (sourceTypeCode == TypeConstants::XS_ANY_ATOMIC)
+    throw TYPE_EXCEPTION(err::XPTY0004, errorInfo);
+
+  if (targetTypeCode == TypeConstants::XS_NCNAME &&
+      sourceTypeCode != TypeConstants::XS_STRING &&
+      sourceTypeCode != TypeConstants::XS_NCNAME &&
+      sourceTypeCode != TypeConstants::XS_UNTYPED_ATOMIC)
+    throw TYPE_EXCEPTION(err::XPTY0004, errorInfo);
+
+  CastFunc castFunc = theCastMatrix[theMapping[sourceTypeCode]]
+                                    [theMapping[targetTypeCode]];
+  if (castFunc == 0)
+    throw TYPE_EXCEPTION(err::XPTY0004, errorInfo);
+
+  if (theMapping[sourceTypeCode] == theMapping[TypeConstants::XS_STRING])
   {
     aItem->getStringValue2(sourceString);
   }
 
-  if (lTargetTypeCode == TypeConstants::XS_NOTATION ||
-      lTargetTypeCode == TypeConstants::XS_ANY_ATOMIC)
-  {
-    throw XQUERY_EXCEPTION(err::XPST0080,
-                           ERROR_PARAMS(*lErrorInfo.theTargetType),
-                           ERROR_LOC(loc));
-  }
-
-  if (lSourceTypeCode == TypeConstants::XS_ANY_ATOMIC)
-    throw TYPE_EXCEPTION(err::XPTY0004, lErrorInfo);
-
-  if (lTargetTypeCode == TypeConstants::XS_NCNAME &&
-      lSourceTypeCode != TypeConstants::XS_STRING &&
-      lSourceTypeCode != TypeConstants::XS_NCNAME &&
-      lSourceTypeCode != TypeConstants::XS_UNTYPED_ATOMIC)
-    throw TYPE_EXCEPTION(err::XPTY0004, lErrorInfo);
-
-  CastFunc lCastFunc = theCastMatrix[theMapping[lSourceTypeCode]]
-                                    [theMapping[lTargetTypeCode]];
-  if (lCastFunc == 0)
-    throw TYPE_EXCEPTION(err::XPTY0004, lErrorInfo);
-
-  bool valid = (*lCastFunc)(result,
-                            aItem,
-                            sourceString,
-                            lFactory,
-                            aNCtx,
-                            lErrorInfo);
-
-  DownCastFunc lDownCastFunc = theDownCastMatrix[theMapping[lTargetTypeCode]];
-
-  if (lDownCastFunc != 0 &&
-      lTargetTypeCode != TypeConstants::XS_STRING &&
-      lTargetTypeCode != TypeConstants::XS_INTEGER)
-  {
-    valid = (*lDownCastFunc)(result,
-                             &*result,
-                             rtm,
-                             lTargetTypeCode,
-                             lFactory,
-                             lErrorInfo);
-  }
-
+  bool valid = (*castFunc)(result,
+                           aItem,
+                           sourceString,
+                           factory,
+                           nsCtx,
+                           errorInfo);
+
+  DownCastFunc downCastFunc = theDownCastMatrix[theMapping[targetTypeCode]];
+
+  if (downCastFunc != 0 &&
+      targetTypeCode != TypeConstants::XS_STRING &&
+      targetTypeCode != TypeConstants::XS_INTEGER)
+  {
+    valid = (*downCastFunc)(result,
+                            &*result,
+                            rtm,
+                            targetTypeCode,
+                            factory,
+                            errorInfo);
+  }
+
+  assert(valid);
   return valid;
 }
 
@@ -1860,7 +1875,7 @@
     const XQType* aTargetType,
     const QueryLoc& loc)
 {
-  ErrorInfo lErrorInfo = {aSourceType, aTargetType};
+  ErrorInfo lErrorInfo = {aSourceType, aTargetType, loc};
 
   // std::cout << "-castToUserDefinedType: " << aItem.getp()->getStringValue()->c_str()
   //           << " srcType: " << aSourceType->get_qname()->getLocalName()->c_str()
@@ -1875,7 +1890,7 @@
   if (aSourceType->type_kind() != XQType::ATOMIC_TYPE_KIND ||
       (TypeOps::get_atomic_type_code(*aSourceType) != TypeConstants::XS_STRING))
   {
-    throw TYPE_EXCEPTION( err::FORG0001, lErrorInfo );
+    throw TYPE_EXCEPTION(err::FORG0001, lErrorInfo);
   }
 
   const UserDefinedXQType* udt =
@@ -1971,7 +1986,7 @@
     );
   }
 
-  ErrorInfo errorInfo = { sourceType.getp(), rtm.QNAME_TYPE_ONE.getp() };
+  ErrorInfo errorInfo = { sourceType.getp(), rtm.QNAME_TYPE_ONE.getp(), loc };
 
   zstring strval;
   item->getStringValue2(strval);
@@ -2405,14 +2420,15 @@
   if (TypeOps::is_equal(tm, *lItemType, *rtm.UNTYPED_ATOMIC_TYPE_ONE) &&
       ! TypeOps::is_equal(tm, *TypeOps::prime_type(tm, *aTargetType), *rtm.QNAME_TYPE_ONE))
   {
-    return GenericCast::castToAtomic(result, aItem, aTargetType, tm, NULL, loc);
+    // untyped --> target type
+    return castToAtomic(result, aItem, aTargetType, tm, NULL, loc);
   }
   else if (TypeOps::is_subtype(tm, *aTargetType, *rtm.FLOAT_TYPE_ONE))
   {
     // decimal --> xs:float
     if (TypeOps::is_subtype(tm, *lItemType, *rtm.DECIMAL_TYPE_ONE))
     {
-      return GenericCast::castToAtomic(result, aItem, aTargetType, tm, NULL, loc);
+      return castToAtomic(result, aItem, aTargetType, tm, NULL, loc);
     }
   }
   else if (TypeOps::is_subtype(tm, *aTargetType, *rtm.DOUBLE_TYPE_ONE))
@@ -2421,7 +2437,7 @@
     if (TypeOps::is_subtype(tm, *lItemType, *rtm.DECIMAL_TYPE_ONE) ||
         TypeOps::is_subtype(tm, *lItemType, *rtm.FLOAT_TYPE_ONE))
     {
-      return GenericCast::castToAtomic(result, aItem, aTargetType, tm, NULL, loc);
+      return castToAtomic(result, aItem, aTargetType, tm, NULL, loc);
     }
   }
   else if (TypeOps::is_subtype(tm, *aTargetType, *rtm.STRING_TYPE_ONE))
@@ -2429,7 +2445,7 @@
     // URI --> xs:String Promotion
     if (TypeOps::is_subtype(tm, *lItemType, *rtm.ANY_URI_TYPE_ONE))
     {
-      return GenericCast::castToAtomic(result, aItem, &*rtm.STRING_TYPE_ONE, tm, NULL, loc);
+      return castToAtomic(result, aItem, &*rtm.STRING_TYPE_ONE, tm, NULL, loc);
     }
   }
 


Follow ups