Przeglądaj źródła

WIP: DICTIONARY support - check => consistency

Check the consistency of => in dictionary initializers.

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 13 lat temu
rodzic
commit
cff3f5a388

+ 2 - 0
ecl/hql/hqlerrors.hpp

@@ -458,6 +458,7 @@
 #define HQLWRN_CouldNotConstantFoldIf           3124
 #define HQLERR_UnexpectedOperator               3125
 #define HQLERR_UnexpectedType                   3126
+#define HQLERR_PayloadMismatch                  3127
 
 #define HQLERR_DedupFieldNotFound_Text          "Field removed from dedup could not be found"
 #define HQLERR_CycleWithModuleDefinition_Text   "Module definition contain an illegal cycle/recursive definition %s"
@@ -486,6 +487,7 @@
 #define HQLERR_TooManyInitializers_Text         "Too many initializers (value %s) for inline dataset definition"
 #define HQLERR_IncompatibleTypesForField_Text   "Initializer for field %s has the wrong type"
 #define HQLWRN_CouldNotConstantFoldIf_Text      "Could not constant fold the condition on a IFBLOCK for a inline table"
+#define HQLERR_PayloadMismatch_Text             "Mismatched => in inline dictionary definition"
 
 /* parser error */
 #define ERR_PARSER_CANNOTRECOVER    3005  /* The parser can not recover from previous error(s) */

+ 10 - 1
ecl/hql/hqlgram.y

@@ -9719,6 +9719,14 @@ inlineFieldValue
                         }
     ;
 
+inlineFieldValueGoesTo
+        : GOESTO        {
+                            parser->addListElement(createAttribute(_payload_Atom));
+                            $$.clear();
+                            $$.setPosition($1);
+                        }
+        ;
+
 inlineFieldValues
     : inlineFieldValue
     | inlineFieldValues ';' inlineFieldValue
@@ -9727,7 +9735,7 @@ inlineFieldValues
 
 inlineFieldValuesWithGoesto
     : inlineFieldValues optSemiComma
-    | inlineFieldValues GOESTO inlineFieldValues optSemiComma
+    | inlineFieldValues inlineFieldValueGoesTo  inlineFieldValues optSemiComma
     ;
 
 inlineDatasetValue
@@ -9735,6 +9743,7 @@ inlineDatasetValue
                         {
                             HqlExprArray args;
                             parser->endList(args);
+                            setPayloadAttribute(args);
 //                          args.append(*createLocationAttr($1));           // improves the error reporting, but slows it down, and changes the expression crcs
                             $$.setExpr(createValue(no_rowvalue, makeNullType(), args));
                         }

+ 39 - 0
ecl/hql/hqlutil.cpp

@@ -5069,6 +5069,24 @@ IHqlExpression * TempTableTransformer::createTempTableTransform(IHqlExpression *
     OwnedHqlExpr self = getSelf(record);
     HqlMapTransformer mapping;
     unsigned col = 0;
+    IHqlExpression * rowPayloadAttr = curRow->queryProperty(_payload_Atom);
+    IHqlExpression * recordPayloadAttr = record->queryProperty(_payload_Atom);
+    if (rowPayloadAttr)
+    {
+        unsigned rowPayload =  (unsigned) getIntValue(rowPayloadAttr->queryChild(0));
+        col++;
+        if (recordPayloadAttr)
+        {
+            unsigned recordPayload =  (unsigned) getIntValue(recordPayloadAttr->queryChild(0));
+            if (rowPayload != recordPayload)
+                ERRORAT(curRow->queryProperty(_location_Atom), HQLERR_PayloadMismatch);
+        }
+        else
+            ERRORAT(curRow->queryProperty(_location_Atom), HQLERR_PayloadMismatch);
+    }
+    else if (recordPayloadAttr)
+        ERRORAT(curRow->queryProperty(_location_Atom), HQLERR_PayloadMismatch);
+
     OwnedHqlExpr ret = createTempTableTransform(self, curRow, record, col, self, mapping, true);
     if (queryRealChild(curRow, col))
     {
@@ -5405,6 +5423,27 @@ IHqlExpression * convertTempTableToInlineDictionary(IErrorReceiver * errors, ECL
     return convertTempTableToInline(errors, location, expr, true);
 }
 
+void setPayloadAttribute(HqlExprArray &args)
+{
+    // Locate a payload attribute in  an initializer value list. If found, move it to front and give it a position
+    int payloadPos = -1;
+    ForEachItemIn(idx, args)
+    {
+        IHqlExpression *cur = &args.item(idx);
+        if (cur->isAttribute())
+        {
+            assertex(payloadPos==-1);
+            assertex(cur->queryName()==_payload_Atom);
+            payloadPos = idx;
+        }
+    }
+    if (payloadPos != -1)
+    {
+        args.remove(payloadPos);
+        args.add(*createAttribute(_payload_Atom, createConstant((__int64) args.length()-payloadPos)), 0);
+    }
+}
+
 bool areTypesComparable(ITypeInfo * leftType, ITypeInfo * rightType)
 {
     if (leftType == rightType)

+ 2 - 0
ecl/hql/hqlutil.hpp

@@ -452,6 +452,8 @@ extern HQL_API IHqlExpression * createINDictExpr(IErrorReceiver * errors, ECLloc
 extern HQL_API IHqlExpression * convertTempRowToCreateRow(IErrorReceiver * errors, ECLlocation & location, IHqlExpression * expr);
 extern HQL_API IHqlExpression * convertTempTableToInlineTable(IErrorReceiver * errors, ECLlocation & location, IHqlExpression * expr);
 extern HQL_API IHqlExpression * convertTempTableToInlineDictionary(IErrorReceiver * errors, ECLlocation & location, IHqlExpression * expr);
+extern HQL_API void setPayloadAttribute(HqlExprArray &args);
+
 extern HQL_API bool areTypesComparable(ITypeInfo * leftType, ITypeInfo * rightType);
 extern HQL_API bool arraysMatch(const HqlExprArray & left, const HqlExprArray & right);
 extern HQL_API IHqlExpression * ensureTransformType(IHqlExpression * transform, node_operator op);

+ 8 - 0
ecl/regress/dict3e.ecl

@@ -0,0 +1,8 @@
+// Some invalid dictionary operations...
+
+d1a := dictionary([{1 => 'Richard'}], { integer id, string name });  // mismatch payload position
+d1b := dictionary([{1 => 2, 'Richard'}], { integer id1, integer id2 => string name }); // mismatch payload position
+d1c := dictionary([{1, 2, 'Richard'}], { integer id1, integer id2 => string name }); // mismatch payload position
+
+d1 := dictionary([{5 => 'Richard'}], { integer id => string name });
+'5' in d1;  // wrong type

+ 0 - 4
testing/ecl/dict2.ecl

@@ -11,10 +11,6 @@ d3n := nofold(d3);
 d4n := nofold(d4);
 d5n := nofold(d5);
 
-// Invalid...
-d1a := dictionary([{1 => 'Richard'}], { integer id, string name });
-d2a := dictionary([{1 => 2, 'Richard'}], { integer id1, integer id2 => string name });
-
 d1[5].name = 'Richard';
 5 in d1;
 d1[1].name = '';