Przeglądaj źródła

HPCC-8465 Implement THISNODE(dictionary) and serialize to slaves

Also improve the text in error messages for a dictionary

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 12 lat temu
rodzic
commit
a8509653bf

+ 1 - 0
common/deftype/deftype.hpp

@@ -314,6 +314,7 @@ inline bool isFixedSize(ITypeInfo * type) { return type && (type->getSize() != U
 inline bool isUnknownSize(ITypeInfo * type) { return type && (type->getSize() == UNKNOWN_LENGTH); }
 inline bool isAnyType(ITypeInfo * type) { return type && (type->getTypeCode() == type_any); }
 inline bool isDecimalType(ITypeInfo * type) { return type && (type->getTypeCode() == type_decimal); }
+inline bool isDictionaryType(ITypeInfo * type) { return type && (type->getTypeCode() == type_dictionary); }
 
 
 //If casting a value from type before to type after is the value preserved.

+ 14 - 1
ecl/hql/hqlexpr.cpp

@@ -10065,6 +10065,7 @@ IHqlExpression *createDictionary(node_operator op, HqlExprArray & parms)
     case no_catch:
     case no_colon:
     case no_globalscope:
+    case no_thisnode:
         type.set(parms.item(0).queryType());
         break;
     default:
@@ -13914,7 +13915,19 @@ HQL_API StringBuffer& getFriendlyTypeStr(ITypeInfo* type, StringBuffer& s)
                 s.append("<unknown>");
             break;
         }
-
+    case type_dictionary:
+        {
+            s.append(type->queryTypeName()).append(" of ");
+            ITypeInfo * chdType = queryRecordType(type);
+            if (chdType)
+            {
+                if (!queryOriginalName(chdType, s))
+                    chdType->getECLType(s);
+            }
+            else
+                s.append("<unknown>");
+            break;
+        }
     case type_record:
         s.append("Record ");
         if (!queryOriginalName(type, s))

+ 4 - 1
ecl/hql/hqlgram.y

@@ -7117,7 +7117,10 @@ simpleDictionary
                             $$.setExpr(createDictionary(no_nohoist, $3.getExpr(), NULL));
                             $$.setPosition($1);
                         }
-
+    | THISNODE '(' dictionary ')'
+                        {
+                            $$.setExpr(createDictionary(no_thisnode, $3.getExpr()), $1);
+                        }
     | DICTIONARY '(' startTopFilter ',' recordDef ')' endTopFilter
                         {
                             OwnedHqlExpr dataset = $3.getExpr();

+ 1 - 1
ecl/hqlcpp/hqlcppds.cpp

@@ -2615,7 +2615,7 @@ void HqlCppTranslator::buildDatasetAssign(BuildCtx & ctx, const CHqlBoundTarget
     Owned<IHqlCppDatasetBuilder> builder;
     if (targetOutOfLine)
     {
-        if (target.queryType()->getTypeCode() == type_dictionary)
+        if (isDictionaryType(target.queryType()))
         {
             builder.setown(createLinkedDictionaryBuilder(record));
         }

+ 1 - 1
ecl/hqlcpp/hqlresource.cpp

@@ -2566,7 +2566,7 @@ protected:
         case no_thisnode:
             if (allNodesDepth == 0)
             {
-                if (expr->isDataset() || expr->isDatarow())
+                if (expr->isDataset() || expr->isDatarow() || expr->isDictionary())
                     noteDataset(expr, expr->queryChild(0), true);
                 else
                     noteScalar(expr, expr->queryChild(0));

+ 28 - 0
testing/ecl/roxie/dictallnodes.ecl

@@ -0,0 +1,28 @@
+#option ('targetClusterType', 'roxie');
+resistorCodes := dataset([{0, 'Black'},
+                          {1, 'Brown'},
+                          {2, 'Red'},
+                          {3, 'Orange'},
+                          {4, 'Yellow'},
+                          {5, 'Green'},
+                          {6, 'Blue'},
+                          {7, 'Violet'},
+                          {8, 'Grey'},
+                          {9, 'White'}], {unsigned1 value, string color}) : stored('colorMap');
+
+color2code := DICTIONARY(resistorCodes, { color => value});
+
+bands := DATASET([{'Red'},{'Yellow'},{'Blue'}], {string band}) : STORED('bands');
+
+valrec := RECORD
+            unsigned1 value;
+          END;
+
+valrec getValue(bands L) := TRANSFORM
+  SELF.value := color2code[L.band].value;
+END;
+
+results := allnodes(PROJECT(bands, getValue(LEFT)));
+
+ave(results, value);  // Should remain the same regardless of how many slaves there are
+

+ 29 - 0
testing/ecl/roxie/dictallnodes2.ecl

@@ -0,0 +1,29 @@
+#option ('targetClusterType', 'roxie');
+resistorCodes := dataset([{0, 'Black'},
+                          {1, 'Brown'},
+                          {2, 'Red'},
+                          {3, 'Orange'},
+                          {4, 'Yellow'},
+                          {5, 'Green'},
+                          {6, 'Blue'},
+                          {7, 'Violet'},
+                          {8, 'Grey'},
+                          {9, 'White'}], {unsigned1 value, string color}) : stored('colorMap');
+
+color2code := DICTIONARY(resistorCodes, { color => value});
+
+bands := DATASET([{'Red'},{'Yellow'},{'Blue'}], {string band}) : STORED('bands');
+
+valrec := RECORD
+            unsigned1 value;
+          END;
+
+//valrec getValue(bands L, dictionary(recordof(color2code)) mapping) := TRANSFORM
+valrec getValue(bands L, dictionary(recordof(dataset(color2code))) mapping) := TRANSFORM
+  SELF.value := mapping[L.band].value;
+END;
+
+results := allnodes(PROJECT(bands, getValue(LEFT, THISNODE(color2code))));
+
+ave(results, value);  // Should remain the same regardless of how many slaves there are
+

+ 3 - 0
testing/ecl/roxie/key/dictallnodes.xml

@@ -0,0 +1,3 @@
+<Dataset name='Result 1'>
+ <Row><Result_1>4.0</Result_1></Row>
+</Dataset>

+ 3 - 0
testing/ecl/roxie/key/dictallnodes2.xml

@@ -0,0 +1,3 @@
+<Dataset name='Result 1'>
+ <Row><Result_1>4.0</Result_1></Row>
+</Dataset>