Browse Source

HPCC-13134 Updated based on review

Signed-off-by: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
Anthony Fishbeck 10 years ago
parent
commit
6db9c93138

+ 1 - 1
ecl/hqlcpp/hqlcpp.ipp

@@ -1013,7 +1013,7 @@ public:
 
     IHqlExpression * getRtlFieldKey(IHqlExpression * expr, IHqlExpression * ownerRecord);
     unsigned buildRtlField(StringBuffer * instanceName, IHqlExpression * fieldKey);
-    unsigned buildRtlType(StringBuffer & instanceName, ITypeInfo * type);
+    unsigned buildRtlType(StringBuffer & instanceName, ITypeInfo * type, unsigned typeFlags);
     unsigned buildRtlRecordFields(StringBuffer & instanceName, IHqlExpression * record, IHqlExpression * rowRecord);
     unsigned expandRtlRecordFields(StringBuffer & fieldListText, IHqlExpression * record, IHqlExpression * rowRecord);
     unsigned buildRtlIfBlockField(StringBuffer & instanceName, IHqlExpression * ifblock, IHqlExpression * rowRecord);

+ 31 - 26
ecl/hqlcpp/hqlhtcpp.cpp

@@ -3527,22 +3527,6 @@ unsigned HqlCppTranslator::buildRtlField(StringBuffer * instanceName, IHqlExpres
             break;
         }
 
-        StringBuffer typeName;
-        typeFlags = buildRtlType(typeName, fieldType);
-
-        StringBuffer lowerName;
-        lowerName.append(field->queryName()).toLowerCase();
-
-        if (options.debugGeneratedCpp)
-        {
-            name.append("rf_");
-            convertToValidLabel(name, lowerName.str(), lowerName.length());
-            name.append("_").append(++nextFieldId);
-        }
-        else
-            name.append("rf").append(++nextFieldId);
-
-
         StringBuffer xpathName, xpathItem;
         switch (fieldType->getTypeCode())
         {
@@ -3562,8 +3546,28 @@ unsigned HqlCppTranslator::buildRtlField(StringBuffer * instanceName, IHqlExpres
             break;
         }
 
-        if (xpathName.length() && (xpathName.charAt(0) == '@'))
-            typeFlags |= RFTMhasxmlattr;
+        if (xpathName.length())
+        {
+            if (xpathName.charAt(0) == '@')
+                typeFlags |= RFTMhasxmlattr;
+            if (!strpbrk(xpathName, "/?*[]<>"))
+                typeFlags |= RFTMxpathscalar;
+        }
+
+        StringBuffer typeName;
+        typeFlags = buildRtlType(typeName, fieldType, typeFlags); //benefit to adding other flags to generated code as well?
+
+        StringBuffer lowerName;
+        lowerName.append(field->queryName()).toLowerCase();
+
+        if (options.debugGeneratedCpp)
+        {
+            name.append("rf_");
+            convertToValidLabel(name, lowerName.str(), lowerName.length());
+            name.append("_").append(++nextFieldId);
+        }
+        else
+            name.append("rf").append(++nextFieldId);
 
         //Format of the xpath field is (nested-item 0x01 repeated-item)
         StringBuffer xpathFull, xpathCppText;
@@ -3714,14 +3718,15 @@ unsigned HqlCppTranslator::getRtlFieldInfo(StringBuffer & fieldInfoName, IHqlExp
     return buildRtlField(&fieldInfoName, fieldKey);
 }
 
-unsigned HqlCppTranslator::buildRtlType(StringBuffer & instanceName, ITypeInfo * type)
+unsigned HqlCppTranslator::buildRtlType(StringBuffer & instanceName, ITypeInfo * type, unsigned typeFlags)
 {
     assertex(type);
     type_t tc = type->getTypeCode();
     if (tc == type_record)
         type = queryUnqualifiedType(type);
 
-    OwnedHqlExpr search = createVariable("t", LINK(type));
+    VStringBuffer searchKey("t%d", typeFlags);
+    OwnedHqlExpr search = createVariable(searchKey, LINK(type));
     BuildCtx declarectx(*code, declareAtom);
     HqlExprAssociation * match = declarectx.queryMatchExpr(search);
     if (match)
@@ -3743,7 +3748,7 @@ unsigned HqlCppTranslator::buildRtlType(StringBuffer & instanceName, ITypeInfo *
     else
         name.append("ty").append(++nextTypeId);
 
-    unsigned fieldType= 0;
+    unsigned fieldType = typeFlags;
     if (tc == type_alien)
     {
         ITypeInfo * physicalType = queryAlienType(type)->queryPhysicalType();
@@ -3852,7 +3857,7 @@ unsigned HqlCppTranslator::buildRtlType(StringBuffer & instanceName, ITypeInfo *
         {
             className.clear().append("RtlRowTypeInfo");
             arguments.append(",&");
-            childType = buildRtlType(arguments, ::queryRecordType(type));
+            childType = buildRtlType(arguments, ::queryRecordType(type), 0);
 //          fieldType |= (childType & RFTMcontainsifblock);
             if (hasLinkCountedModifier(type))
                 fieldType |= RFTMlinkcounted;
@@ -3863,7 +3868,7 @@ unsigned HqlCppTranslator::buildRtlType(StringBuffer & instanceName, ITypeInfo *
         {
             className.clear().append("RtlDatasetTypeInfo");
             arguments.append(",&");
-            childType = buildRtlType(arguments, ::queryRecordType(type));
+            childType = buildRtlType(arguments, ::queryRecordType(type), 0);
             if (hasLinkCountedModifier(type))
                 fieldType |= RFTMlinkcounted;
             break;
@@ -3872,7 +3877,7 @@ unsigned HqlCppTranslator::buildRtlType(StringBuffer & instanceName, ITypeInfo *
         {
             className.clear().append("RtlDictionaryTypeInfo");
             arguments.append(",&");
-            childType = buildRtlType(arguments, ::queryRecordType(type));
+            childType = buildRtlType(arguments, ::queryRecordType(type), 0);
             if (hasLinkCountedModifier(type))
                 fieldType |= RFTMlinkcounted;
             StringBuffer lookupHelperName;
@@ -3883,7 +3888,7 @@ unsigned HqlCppTranslator::buildRtlType(StringBuffer & instanceName, ITypeInfo *
     case type_set:
         className.clear().append("RtlSetTypeInfo");
         arguments.append(",&");
-        childType = buildRtlType(arguments, type->queryChildType());
+        childType = buildRtlType(arguments, type->queryChildType(), 0);
         break;
     case type_unicode:
         className.clear().append("RtlUnicodeTypeInfo");
@@ -4100,7 +4105,7 @@ void HqlCppTranslator::buildMetaInfo(MetaInstance & instance)
             assertex(!instance.isGrouped());
 
             StringBuffer typeName;
-            unsigned recordTypeFlags = buildRtlType(typeName, record->queryType());
+            unsigned recordTypeFlags = buildRtlType(typeName, record->queryType(), 0);
             s.clear().append("virtual const RtlTypeInfo * queryTypeInfo() const { return &").append(typeName).append("; }");
             metactx.addQuoted(s);
 

+ 2 - 3
rtl/eclrtl/rtlfield.cpp

@@ -41,10 +41,9 @@ static const char * queryXPath(const RtlFieldInfo * field)
 
 static const char * queryScalarXPath(const RtlFieldInfo * field)
 {
-    const char *xpath = queryXPath(field);
-    if (strchr(xpath, '/'))
+    if (field->type && !field->type->xpathIsScalar())
         return field->name->str();
-    return xpath;
+    return queryXPath(field);
 }
 
 static bool hasOuterXPath(const RtlFieldInfo * field)

+ 2 - 1
rtl/include/eclhelper.hpp

@@ -326,6 +326,7 @@ enum RtlFieldTypeMask
 
     RFTMalien               = 0x00000800,                   // this is the physical format of a user defined type, if unknown size we can't calculate it
     RFTMcontainsifblock     = 0x00000800,                   // contains an if block - if set on a record then it contains ifblocks, so can't work out field offsets.
+    RFTMxpathscalar         = 0x00001000,                   // field xpath contains only one node, and is therefore usable for naming scalar fields
 
     RFTMcontainsunknown     = 0x10000000,                   // contains a field of unknown type that we can't process properly
     RFTMinvalidxml          = 0x20000000,                   // cannot be called to generate xml
@@ -363,6 +364,7 @@ struct RtlTypeInfo : public RtlITypeInfo
     inline bool isFixedSize() const { return (fieldType & RFTMunknownsize) == 0; }
     inline bool isLinkCounted() const { return (fieldType & RFTMlinkcounted) != 0; }
     inline bool isUnsigned() const { return (fieldType & RFTMunsigned) != 0; }
+    inline bool xpathIsScalar() const { return (fieldType & RFTMxpathscalar) != 0; }
     inline unsigned getDecimalDigits() const { return (length & 0xffff); }
     inline unsigned getDecimalPrecision() const { return (length >> 16); }
     inline unsigned getBitfieldIntSize() const { return (length & 0xff); }
@@ -376,7 +378,6 @@ public:
                                     // if RFTMunknownsize then maxlength (records) [maxcount(datasets)]
 };
 
-
 //Core struct used for representing meta for a field.
 struct RtlFieldInfo
 {

+ 8 - 0
testing/regress/ecl/key/xmloutScalarXpath.xml

@@ -0,0 +1,8 @@
+<Dataset name='OriginalReadRow'>
+ <Row><L1><L2><fname>MOE</fname><lname>DOE</lname><pr>1</pr><st>11TH</st><zi>11</zi><ag>31</ag><ix>315367</ix></L2><L2><fname>JOE</fname><lname>POE</lname><pr>2</pr><st>22ND</st><zi>11</zi><ag>32</ag><ix>315370</ix></L2><L2><fname>XOE</fname><lname>ROE</lname><pr>3</pr><st>33RD</st><zi>11</zi><ag>33</ag><ix>315204</ix></L2></L1></Row>
+</Dataset>
+<Dataset name='Result 2'>
+</Dataset>
+<Dataset name='readWrittenDataset'>
+ <Row><L1><L2><fname>MOE</fname><lname>DOE</lname><pr>1</pr><st>11TH</st><zi>11</zi><ag>31</ag><ix>315367</ix></L2><L2><fname>JOE</fname><lname>POE</lname><pr>2</pr><st>22ND</st><zi>11</zi><ag>32</ag><ix>315370</ix></L2><L2><fname>XOE</fname><lname>ROE</lname><pr>3</pr><st>33RD</st><zi>11</zi><ag>33</ag><ix>315204</ix></L2></L1></Row>
+</Dataset>

+ 50 - 0
testing/regress/ecl/xmloutScalarXpath.ecl

@@ -0,0 +1,50 @@
+origReadRec :=       RECORD
+   string fn {xpath('fname')};
+   string ln {xpath('lname')};
+   string pr {xpath('Rec/prange')};
+   string st {xpath('Rec/street')};
+   string zi {xpath('Rec/zips')};
+   string ag {xpath('Rec/age')};
+   integer8 ix {xpath('Rec/id')};
+END;
+
+L1rec := RECORD
+   DATASET(origReadRec) deep{xpath('L1/L2')};
+END;
+
+
+x := u8'<root><L1>' +
+       u8'<L2><fname>MOE</fname><lname>DOE</lname>' +
+         u8'<Rec><prange>1</prange><street>11TH</street><zips>11</zips><age>31</age><id>315367</id></Rec>' +
+       u8'</L2>' +
+       u8'<L2><fname>JOE</fname><lname>POE</lname>' +
+         u8'<Rec><prange>2</prange><street>22ND</street><zips>11</zips><age>32</age><id>315370</id></Rec>' +
+       u8'</L2>' +
+       u8'<L2><fname>XOE</fname><lname>ROE</lname>' +
+         u8'<Rec><prange>3</prange><street>33RD</street><zips>11</zips><age>33</age><id>315204</id></Rec>' +
+       u8'</L2>' +
+     u8'</L1></root>';
+
+
+xrow := FROMXML(L1Rec, x);
+output(xrow, named('OriginalReadRow'));
+
+
+
+scalarReadRec :=       RECORD
+   string fn {xpath('fname')};
+   string ln {xpath('lname')};
+   string pr;
+   string st;
+   string zi;
+   string ag;
+   integer8 ix;
+END;
+
+readL1rec := RECORD
+   DATASET(scalarReadRec) deep{xpath('L1/L2')};
+END;
+
+output(Dataset(xrow),,'~REGRESS::TEMP::output_scalar_xpath.xml',overwrite, xml);
+readWrittenXml := dataset(DYNAMIC('~REGRESS::TEMP::output_scalar_xpath.xml'), readL1Rec, xml('Dataset/Row'));
+output(readWrittenXml, named('readWrittenDataset'));