Bläddra i källkod

HPCC-12781 Add an ONFAIL attribute to FROMXML/FROMJSON

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Gavin Halliday 10 år sedan
förälder
incheckning
7c95721c07

+ 21 - 4
ecl/hql/hqlgram.y

@@ -3586,11 +3586,22 @@ outputWuFlag
                         }
     ;
 
-optCommaTrim
+fromXmlOptions
     :                   {   $$.setExpr(NULL); }
-    | ',' TRIM          {
+    | fromXmlOptions ',' fromXmlOption
+                        {
+                            $$.setExpr(createComma($1.getExpr(), $3.getExpr()));
+                        }
+    ;
+
+fromXmlOption
+    : TRIM              {
                             $$.setExpr(createAttribute(trimAtom), $1);
                         }
+    | ONFAIL '(' transform ')'
+                        {
+                            $$.setExpr(createExprAttribute(onFailAtom, $3.getExpr()), $1);
+                        }
     ;
     
 applyActions
@@ -7329,14 +7340,20 @@ simpleDataRow
 
                             $$.setExpr(createRow(no_matchrow, LINK(record), $3.getExpr())); //, parser->createUniqueId())));
                         }
-    | FROMXML '(' recordDef ',' expression optCommaTrim ')'
+    | FROMXML '(' recordDef ',' expression fromXmlOptions ')'
                         {
                             parser->normalizeExpression($5, type_stringorunicode, false);
+                            IHqlExpression * onFail = queryAttributeInList(onFailAtom, $6.queryExpr());
+                            if (onFail)
+                                parser->checkRecordTypesMatch($3.queryExpr(), onFail->queryChild(0), $6);
                             $$.setExpr(createRow(no_fromxml, $3.getExpr(), createComma($5.getExpr(), $6.getExpr())), $1);
                         }
-    | FROMJSON '(' recordDef ',' expression optCommaTrim ')'
+    | FROMJSON '(' recordDef ',' expression fromXmlOptions ')'
                         {
                             parser->normalizeExpression($5, type_stringorunicode, false);
+                            IHqlExpression * onFail = queryAttributeInList(onFailAtom, $6.queryExpr());
+                            if (onFail)
+                                parser->checkRecordTypesMatch($3.queryExpr(), onFail->queryChild(0), $6);
                             $$.setExpr(createRow(no_fromjson, $3.getExpr(), createComma($5.getExpr(), $6.getExpr())), $1);
                         }
     | WHEN '(' dataRow ',' action sideEffectOptions ')'

+ 32 - 9
ecl/hqlcpp/hqlcppds.cpp

@@ -321,6 +321,8 @@ void HqlCppTranslator::buildNullRow(BuildCtx & ctx, IHqlExpression * expr, CHqlB
 
 IReferenceSelector * HqlCppTranslator::doBuildRowFromXMLorJSON(BuildCtx & ctx, IHqlExpression * expr)
 {
+    IHqlExpression * onFail = expr->queryAttribute(onFailAtom);
+
 //  assertex(supportsLinkCountedRows);
     Owned<ITypeInfo> overrideType = setLinkCountedAttr(expr->queryType(), true);
     Owned<ITypeInfo> utf8Type = makeUtf8Type(UNKNOWN_LENGTH, NULL);
@@ -362,18 +364,39 @@ IReferenceSelector * HqlCppTranslator::doBuildRowFromXMLorJSON(BuildCtx & ctx, I
     else
         function.setown(bindFunctionCall(createRowFromXmlId, args, overrideType));
 
-    CHqlBoundExpr bound;
-    buildExpr(ctx, function, bound);
+    Owned<BoundRow> result;
+    if (onFail)
+    {
+        result.setown(declareTempRow(ctx, ctx, expr));
+        BuildCtx tryctx(ctx);
+        tryctx.addTry();
+        buildRowAssign(tryctx, result, function);
 
-    Owned<ITypeInfo> rowType = makeReferenceModifier(LINK(overrideType));
-    OwnedHqlExpr rowExpr = ctx.getTempDeclare(rowType, NULL);
-    Owned<BoundRow> row = createBoundRow(expr, rowExpr);
-    ctx.associate(*row);                                    // associate here because it is compared inside the loop
+        HqlExprArray dummyArgs;
+        OwnedHqlExpr exception = createParameter(createIdAtom("e"), 0, makePointerType(makeClassType("IException")), dummyArgs);
+        BuildCtx catchctx(ctx);
+        catchctx.addCatch(exception);
+        catchctx.addQuoted("Owned<IException> _e = e;");    // ensure that the exception is released
+
+        associateLocalFailure(catchctx, "e");
+        OwnedHqlExpr row = createRow(no_createrow, LINK(onFail->queryChild(0)));
+        buildRowAssign(catchctx, result, row);
+    }
+    else
+    {
+        CHqlBoundExpr bound;
+        buildExpr(ctx, function, bound);
 
-    OwnedHqlExpr defaultRowPtr = getPointer(bound.expr);
-    ctx.addAssign(rowExpr, defaultRowPtr);
+        Owned<ITypeInfo> rowType = makeReferenceModifier(LINK(overrideType));
+        OwnedHqlExpr rowExpr = ctx.getTempDeclare(rowType, NULL);
+        result.setown(createBoundRow(expr, rowExpr));
 
-    return createReferenceSelector(row);
+        OwnedHqlExpr defaultRowPtr = getPointer(bound.expr);
+        ctx.addAssign(rowExpr, defaultRowPtr);
+    }
+
+    ctx.associate(*result);
+    return createReferenceSelector(result);
 }
 
 

+ 1 - 0
ecl/hqlcpp/hqlwcpp.cpp

@@ -1796,6 +1796,7 @@ void HqlCppWriter::generateStmtAssign(IHqlStmt * assign, bool link)
         case type_pointer:
         case type_enumerated:
         case type_record:
+        case type_class:
             generateSimpleAssign(target, source);
             break;
         case type_varstring:

+ 2 - 2
ecl/regress/fromxml.ecl

@@ -1,6 +1,6 @@
 /*##############################################################################
 
-    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
+    HPCC SYSTEMS software Copyright (C) 2015 HPCC Systems.
 
     This program is free software: you can redistribute it and/or modify
     you may not use this file except in compliance with the License.
@@ -59,4 +59,4 @@ namesTable := dataset([
     ], { utf8 text; });
 
 output(namesTable, { FROMXML(personRecord, text, TRIM); });
-output(1);
+output(1);

+ 69 - 0
ecl/regress/fromxml5err.ecl

@@ -0,0 +1,69 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2015 HPCC Systems.
+
+    This program is free software: you can redistribute it and/or modify
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+phoneRecord :=
+            RECORD
+string5         areaCode{xpath('@areaCode')};
+udecimal12      number{xpath('@number')};
+            END;
+
+contactrecord :=
+            RECORD
+phoneRecord     phone;
+boolean         hasemail{xpath('@hasEmail')};
+                ifblock(self.hasemail)
+string              email;
+                end;
+            END;
+
+bookRec :=
+    RECORD
+unicode     title;
+string      author;
+    END;
+
+personRecord :=
+            RECORD
+unicode20       surname;
+unicode10       forename;
+phoneRecord     homePhone;
+boolean         hasMobile;
+                ifblock(self.hasMobile)
+phoneRecord         mobilePhone;
+                end;
+contactRecord   contact;
+dataset(bookRec) books;
+set of string    colours;
+string2         endmarker := '$$';
+            END;
+
+namesTable := dataset([
+    u8'<Row><surname>Hälliday</surname><forename>Gavin</forename><homephone areaCode="09876" number="123987"/><hasmobile>true</hasmobile><mobilephone areaCode="07967" number="123987"/>' +
+        u8'<contact hasEmail="true"><phone areaCode="n/a" number="0"/><email>gavin@edata.com</email></contact>' +
+        u8'<books><Row><title>εν αρχη ην ο λογος</title><author>john</author></Row><Row><title>To kill a mocking bird</title><author>Lee</author></Row><Row><title>Zen and the art of motorcycle maintainence</title><author>Pirsig</author></Row></books><colours><All/></colours><endmarker>$$</endmarker></Row>',
+    u8'<Row><unmatchedtag></Row>',
+    u8'<Row><surname>Halliday</surname><forename>Abigäil</forename><homephone areaCode="09876" number="123987"/><hasmobile>false</hasmobile><contact hasEmail="false"><phone areaCode="" number="0"/></contact><books><Row><title>The cat in the hat</title><author>Suess</author></Row><Row><title>Wolly the sheep</title><author></author></Row></books><colours><Item>Red</Item><Item>Yellow</Item></colours><endmarker>$$</endmarker></Row>'
+    ], { utf8 text; });
+
+contactRecord createFailure() := TRANSFORM
+    SELF.hasemail := TRUE;
+    SELF.email := FAILMESSAGE;
+    SELF := [];
+END;
+
+output(namesTable, { FROMXML(personRecord, text, TRIM, ONFAIL(createFailure())); });
+output(1);

+ 71 - 0
testing/regress/ecl/fromxml5.ecl

@@ -0,0 +1,71 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
+
+    This program is free software: you can redistribute it and/or modify
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+phoneRecord :=
+            RECORD
+string5         areaCode{xpath('@areaCode')};
+udecimal12      number{xpath('@number')};
+            END;
+
+contactrecord :=
+            RECORD
+phoneRecord     phone;
+boolean         hasemail{xpath('@hasEmail')};
+                ifblock(self.hasemail)
+string              email;
+                end;
+            END;
+
+bookRec :=
+    RECORD
+unicode     title;
+string      author;
+    END;
+
+personRecord :=
+            RECORD
+unicode20       surname;
+unicode10       forename;
+phoneRecord     homePhone;
+boolean         hasMobile;
+                ifblock(self.hasMobile)
+phoneRecord         mobilePhone;
+                end;
+contactRecord   contact;
+dataset(bookRec) books;
+set of string    colours;
+string2         endmarker := '$$';
+            END;
+
+namesTable := dataset([
+    u8'<Row><surname>Hälliday</surname><forename>Gavin</forename><homephone areaCode="09876" number="123987"/><hasmobile>true</hasmobile><mobilephone areaCode="07967" number="123987"/>' +
+        u8'<contact hasEmail="true"><phone areaCode="n/a" number="0"/><email>gavin@edata.com</email></contact>' +
+        u8'<books><Row><title>εν αρχη ην ο λογος</title><author>john</author></Row><Row><title>To kill a mocking bird</title><author>Lee</author></Row><Row><title>Zen and the art of motorcycle maintainence</title><author>Pirsig</author></Row></books><colours><All/></colours><endmarker>$$</endmarker></Row>',
+    u8'<Row><unmatchedtag></Row>',
+    u8'<Row><surname>Halliday</surname><forename>Abigäil</forename><homephone areaCode="09876" number="123987"/><hasmobile>false</hasmobile><contact hasEmail="false"><phone areaCode="" number="0"/></contact><books><Row><title>The cat in the hat</title><author>Suess</author></Row><Row><title>Wolly the sheep</title><author></author></Row></books><colours><Item>Red</Item><Item>Yellow</Item></colours><endmarker>$$</endmarker></Row>'
+    ], { utf8 text; });
+
+personRecord createFailure() := TRANSFORM
+    SELF.surname := '**FAIL**';
+    SELF.forename := (UNICODE)FAILCODE;
+    SELF.contact.hasemail := TRUE;
+    SELF.contact.email := FAILMESSAGE;
+    SELF := [];
+END;
+
+output(namesTable, { FROMXML(personRecord, text, TRIM, ONFAIL(createFailure())); });
+output(1);

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 9 - 0
testing/regress/ecl/key/fromxml5.xml