Sfoglia il codice sorgente

Merge branch 'candidate-7.12.x'

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 4 anni fa
parent
commit
ecb502aa14

+ 31 - 1
dali/dfu/dfuutil.cpp

@@ -1043,7 +1043,7 @@ public:
         return out;
     }
 
-    void addFileXML(const char *lfn, const StringBuffer &xml, IUserDescriptor *user)
+    virtual void addFileXML(const char *lfn, const StringBuffer &xml, const char * cluster, IUserDescriptor *user) override
     {
         Owned<IPropertyTree> t = createPTreeFromXMLString(xml);
         IDistributedFileDirectory &dfd = queryDistributedFileDirectory();
@@ -1062,6 +1062,36 @@ public:
         else if (0 == strcmp(nodeName, queryDfsXmlBranchName(DXB_File)))
         {
             // Logical file map
+            //Patch the cluster before the file is created
+            if (!isEmptyString(cluster))
+            {
+                //In containerized mode the directory is configured somewhere else...
+                //replace @directory with a directory calculated from the storage plane
+                //prefix and the scope of the logical filename
+                //MORE: This could should be commoned up with similar code elsewhere
+                Owned<IStoragePlane> plane = getStoragePlane(cluster, true);
+                StringBuffer location(plane->queryPrefix());
+                const char * temp = lfn;
+                for (;;)
+                {
+                    const char * sep = strstr(temp, "::");
+                    if (!sep)
+                        break;
+                    addPathSepChar(location);
+                    location.appendLower(sep - temp, temp);
+                    temp = sep + 2;
+                }
+                t->setProp("@directory", location);
+
+                //Remove any clusters in the incoming definition, and replace it with a single entry
+                while (t->removeProp("Cluster"))
+                {
+                    //Loop again incase there are any other matches - currently removeProp() appears to remove the whole
+                    //list, but when qualified it would only remove the 1st...
+                }
+                IPropertyTree * entry = t->addPropTree("Cluster", createPTree());
+                entry->setProp("@name", cluster);
+            }
 
             Owned<IFileDescriptor> fdesc = deserializeFileDescriptorTree(t, &queryNamedGroupStore(), 0);
             file.setown(dfd.createNew(fdesc));

+ 1 - 1
dali/dfu/dfuutil.hpp

@@ -44,7 +44,7 @@ interface IDFUhelper: extends IInterface
     virtual void removeSuper(const char *superfname, IUserDescriptor *user, unsigned numtodelete=0, const char **subfiles=NULL, bool delsub=false, bool removesuperfile=true) = 0;
     virtual void listSubFiles(const char *superfname,StringAttrArray &out, IUserDescriptor *user) = 0;
     virtual StringBuffer &getFileXML(const char *lfn,StringBuffer &out, IUserDescriptor *user) = 0;
-    virtual void addFileXML(const char *lfn,const StringBuffer &xml, IUserDescriptor *user) = 0;
+    virtual void addFileXML(const char *lfn,const StringBuffer &xml, const char * cluster, IUserDescriptor *user) = 0;
     virtual void addFileRemote(const char *lfn,SocketEndpoint &srcdali,const char *srclfn,IUserDescriptor *srcuser,IUserDescriptor *user) = 0;
     virtual void superForeignCopy(const char *lfn,SocketEndpoint &srcdali,const char *srclfn,IUserDescriptor *srcuser,IUserDescriptor *user, bool overwrite, IDfuFileCopier *copier) = 0;
 

+ 4 - 3
dali/dfuplus/dfuplus.cpp

@@ -728,8 +728,6 @@ int CDfuPlusHelper::despray()
     MemoryBuffer xmlbuf;
     if(dstxml == nullptr)
     {
-        if(dstfile == nullptr)
-            throw MakeStringException(-1, "dstfile not specified");
         if(dstip == nullptr) {
 #ifdef DAFILESRV_LOCAL
             progress("dstip not specified - assuming spray from local machine\n");
@@ -750,7 +748,7 @@ int CDfuPlusHelper::despray()
     }
 
     if(dstxml == nullptr)
-        info("\nDespraying %s to host %s file %s\n", srcname, dstip, dstfile);
+        info("\nDespraying %s to host %s file %s\n", srcname, dstip, dstfile ? dstfile : "");
     else
         info("\nDespraying %s\n", srcname);
 
@@ -1427,9 +1425,12 @@ int CDfuPlusHelper::add()
         int len = buf.length();
         xmlbuf.setBuffer(len, buf.detach(), true);
 
+        const char* dstcluster = globals->queryProp("dstcluster");
+
         Owned<IClientAddRequest> req = dfuclient->createAddRequest();
         req->setDstname(lfn);
         req->setXmlmap(xmlbuf);
+        req->setDstcluster(dstcluster);
 
         Owned<IClientAddResponse> resp = dfuclient->Add(req);
 

+ 2 - 1
dali/dfuplus/main.cpp

@@ -160,6 +160,7 @@ void handleSyntax()
     out.append("        dstname=<destination-logical-name>\n");
     out.append("            -- To add remote files from another dali directly, use these\n");
     out.append("               options instead of srcxml:\n");
+    out.append("        dstcluster=<destination-cluster> -- which cluster contains the files\n");
     out.append("        srcname=<source-logical-name>\n");
     out.append("        srcdali=<source-dali-ip>\n");
     out.append("        srcusername=<user-name-for-source-dali>\n");
@@ -268,7 +269,7 @@ int main(int argc, const char* argv[])
     if(!action || !*action)
     {
         handleSyntax();
-        fprintf(stderr, "\nERROR: please specify one action");
+        fprintf(stderr, "\nERROR: please specify one action\n");
         releaseAtoms();
         return DFUERR_TooFewArguments;
     }

+ 4 - 3
dockerfiles/startall.sh

@@ -85,9 +85,10 @@ fi
 [[ -z ${LABEL} ]] && LABEL=$(docker image ls | fgrep "${DOCKER_REPO}/platform-core" | head -n 1 | awk '{print $2}')
 
 if [[ -n ${PERSIST} ]] ; then
-  mkdir -p ${PERSIST}/dlls
-  mkdir -p ${PERSIST}/dali
-  mkdir -p ${PERSIST}/data
+  PERSIST_PATH=$(echo $PERSIST | sed 's/\\//g')
+  mkdir -p ${PERSIST_PATH}/dlls
+  mkdir -p ${PERSIST_PATH}/dali
+  mkdir -p ${PERSIST_PATH}/data
   helm ${CMD} localfile $scriptdir/../helm/examples/local/hpcc-localfile --set common.hostpath=${PERSIST} | grep -A100 storage > localstorage.yaml && \
   helm ${CMD} mycluster $scriptdir/../helm/hpcc/ --set global.image.root="${DOCKER_REPO}" --set global.image.version=$LABEL --set global.privileged=true -f localstorage.yaml $DEP_UPDATE_ARG ${restArgs[@]}
 else

+ 3 - 2
esp/scm/ws_dfu.ecm

@@ -473,6 +473,7 @@ ESPrequest AddRequest
 {
     string dstname;
     [http_content("text/xml")] binary xmlmap;
+    [min_ver("1.57")] string dstcluster;
 };
 
 ESPresponse [exceptions_inline, nil_remove] AddResponse
@@ -965,8 +966,8 @@ ESPresponse [exceptions_inline, nil_remove] DFUFilePublishResponse
 //  ===========================================================================
 ESPservice [
     auth_feature("DEFERRED"),
-    version("1.56"),
-    default_client_version("1.56"),
+    version("1.57"),
+    default_client_version("1.57"),
     noforms,
     exceptions_inline("./smc_xslt/exceptions.xslt")] WsDfu
 {

+ 1 - 1
esp/services/ws_dfu/ws_dfuService.cpp

@@ -3963,7 +3963,7 @@ bool CWsDfuEx::onAdd(IEspContext &context, IEspAddRequest &req, IEspAddResponse
 
         Owned<IDFUhelper> dfuhelper = createIDFUhelper();
         StringBuffer xmlstr(req.getXmlmap().length(),(const char*)req.getXmlmap().bufferBase());
-        dfuhelper->addFileXML(req.getDstname(), xmlstr, userdesc.get());
+        dfuhelper->addFileXML(req.getDstname(), xmlstr, req.getDstcluster(), userdesc.get());
     }
     catch(IException* e)
     {

+ 25 - 1
esp/services/ws_fs/ws_fsService.cpp

@@ -2328,6 +2328,24 @@ void CFileSprayEx::getDropZoneInfoByIP(double clientVersion, const char* ip, con
     }
 }
 
+static StringBuffer & expandLogicalAsPhysical(StringBuffer & target, const char * name, const char * separator)
+{
+    const char * cur = name;
+    for (;;)
+    {
+        const char * colon = strstr(cur, "::");
+        if (!colon)
+            break;
+
+        //MORE: Process special characters?
+        target.append(colon - cur, cur);
+        target.append(separator);
+        cur = colon + 2;
+    }
+
+    return target.append(cur);
+}
+
 bool CFileSprayEx::onDespray(IEspContext &context, IEspDespray &req, IEspDesprayResponse &resp)
 {
     try
@@ -2342,6 +2360,7 @@ bool CFileSprayEx::onDespray(IEspContext &context, IEspDespray &req, IEspDespray
         double version = context.getClientVersion();
         const char* destip = req.getDestIP();
         StringBuffer destPath;
+        StringBuffer implicitDestFile;
         const char* destfile = getStandardPosixPath(destPath, req.getDestPath()).str();
 
         MemoryBuffer& dstxml = (MemoryBuffer&)req.getDstxml();
@@ -2349,8 +2368,13 @@ bool CFileSprayEx::onDespray(IEspContext &context, IEspDespray &req, IEspDespray
         {
             if(!destip || !*destip)
                 throw MakeStringException(ECLWATCH_INVALID_INPUT, "Destination network IP not specified.");
+
+            //If the destination filename is not provided, calculate a relative filename from the logical filename
             if(!destfile || !*destfile)
-                throw MakeStringException(ECLWATCH_INVALID_INPUT, "Destination file not specified.");
+            {
+                expandLogicalAsPhysical(implicitDestFile, srcname, "/");
+                destfile = implicitDestFile;
+            }
         }
 
         StringBuffer srcTitle;

+ 1 - 0
plugins/kafka/CMakeLists.txt

@@ -66,6 +66,7 @@ if(KAFKA)
             COMMAND if [ ! -f ${LIBRDKAFKA_BUILD_DIR}/src/Makefile.config ]\; then echo "Configuring librdkafka" && cd ${LIBRDKAFKA_BUILD_DIR}/src && ./configure --prefix=${LIBRDKAFKA_BUILD_DIR}\; fi
             # If either there is no checksum file or if the checksums are different, re-make librdkafka
             COMMAND if [ ! -f ${LIBRDKAFKA_BUILD_DIR}/src/_md5.txt ] || ! md5sum --quiet --status -c ${LIBRDKAFKA_BUILD_DIR}/src/_md5.txt\; then echo "Building librdkafka" && cd ${LIBRDKAFKA_BUILD_DIR}/src && make libs && make install\; fi
+            COMMAND rm -f ${LIBRDKAFKA_BUILD_DIR}/src/_md5.txt
             COMMENT Copying and building librdkafka)
 
         install(CODE "set(ENV{LD_LIBRARY_PATH} \"\$ENV{LD_LIBRARY_PATH}:${LIBRDKAFKA_BUILD_DIR}/lib\")")

+ 2 - 2
roxie/ccd/ccdactivities.cpp

@@ -2430,7 +2430,7 @@ public:
             datafile.setown(queryFactory.queryPackage().lookupFileName(indexName, isOpt, true, true, queryFactory.queryWorkUnit(), true, isCodeSigned));
             if (datafile)
             {
-                translators.setown(datafile->getTranslators(projectedCrc, projectedMeta, expectedCrc, expectedMeta, queryFactory.queryOptions().enableFieldTranslation, FileFormatMode::index, queryFactory.queryQueryName()));
+                translators.setown(datafile->getTranslators(projectedCrc, projectedMeta, expectedCrc, expectedMeta, getEnableFieldTranslation(), FileFormatMode::index, queryFactory.queryQueryName()));
                 keyArray.setown(datafile->getKeyArray(isOpt, queryFactory.queryChannel()));
             }
         }
@@ -4012,7 +4012,7 @@ public:
             datafile.setown(_queryFactory.queryPackage().lookupFileName(indexFileName, isOpt, true, true, _queryFactory.queryWorkUnit(), true, isCodeSigned));
             if (datafile)
             {
-                translators.setown(datafile->getTranslators(projectedCrc, projectedMeta, expectedCrc, expectedMeta, queryFactory.queryOptions().enableFieldTranslation, FileFormatMode::index, queryFactory.queryQueryName()));
+                translators.setown(datafile->getTranslators(projectedCrc, projectedMeta, expectedCrc, expectedMeta, getEnableFieldTranslation(), FileFormatMode::index, queryFactory.queryQueryName()));
                 keyArray.setown(datafile->getKeyArray(isOpt, queryFactory.queryChannel()));
             }
         }

+ 2 - 0
roxie/ccd/ccdfile.cpp

@@ -2735,6 +2735,8 @@ public:
                     {
                         if (formatCrcs.item(idx) && expectedFormatCrc && (formatCrcs.item(idx) != expectedFormatCrc))
                             DBGLOG("Overriding stored record layout reading file %s", subname);
+
+                        thisFormatCrc = expectedFormatCrc;
                     }
                     else
                     {

+ 5 - 1
roxie/ccd/ccdserver.cpp

@@ -611,6 +611,10 @@ public:
     {
         return isCodeSigned;
     }
+    virtual RecordTranslationMode getEnableFieldTranslation() const
+    {
+        return CActivityFactory::getEnableFieldTranslation();
+    }
 };
 
 class CRoxieServerMultiInputInfo
@@ -1665,7 +1669,7 @@ public:
 protected:
     RecordTranslationMode getEnableFieldTranslation() const
     {
-        return factory->queryQueryFactory().queryOptions().enableFieldTranslation;
+        return factory->getEnableFieldTranslation();
     }
 };
 

+ 1 - 0
roxie/ccd/ccdserver.hpp

@@ -218,6 +218,7 @@ interface IRoxieServerActivityFactory : extends IActivityFactory
     virtual bool isInputOrdered(bool consumerOrdered, unsigned idx) const = 0;
     virtual roxiemem::RoxieHeapFlags getHeapFlags() const = 0;
     virtual bool isActivityCodeSigned() const = 0;
+    virtual RecordTranslationMode getEnableFieldTranslation() const = 0;
 };
 interface IGraphResult : public IInterface
 {

+ 100 - 0
testing/regress/ecl/alien2.ecl

@@ -0,0 +1,100 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2017 HPCC Systems®.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    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.
+############################################################################## */
+
+import lib_stringlib;
+import $.setup;
+prefix := setup.Files(false, false).FilePrefix + __TARGET_PLATFORM__ + '::';
+
+extractXStringLength(data x, unsigned len) := transfer(((data4)(x[1..len])), unsigned4);
+
+//A pretty weird type example - a length prefixed string, where the number of bytes used for the length is configurable...
+xstring(unsigned len) := type
+    export integer physicallength(data x) := extractXStringLength(x, len)+len;
+    export string load(data x) := (string)x[(len+1)..extractXStringLength(x, len)+len];
+    export data store(string x) := transfer(length(x), data4)[1..len]+(data)x;
+end;
+
+dstring(string del) := TYPE
+    export integer physicallength(string s) := StringLib.StringUnboundedUnsafeFind(s,del)+length(del)-1;
+    export string load(string s) := s[1..StringLib.StringUnboundedUnsafeFind(s,del)-1];
+    export string store(string s) := s+del; // Untested (vlength output generally broken)
+END;
+
+
+alienString := xstring(4);
+alienVarString := dstring('\000');
+
+namesRecord := RECORD
+    string          surname;
+    string          forename;
+    varstring       addr;
+    string4         extra;
+    varstring       extra2;
+END;
+
+namesRecordEx := RECORD(namesRecord)
+    unsigned        fpos{virtual(fileposition)};
+    string          filename{virtual(logicalfilename)};
+    unsigned        lfpos{virtual(localfileposition)};
+END;
+
+reducedNamesRecordEx := namesRecordEx - [addr, extra, lfpos];
+
+alienRecord := RECORD
+    alienString         surname;
+    alienString         forename;
+    alienVarString      addr;
+    string4             extra;
+    alienVarString      extra2;
+END;
+
+alienRecordEx := RECORD(alienRecord)
+    unsigned        fpos{virtual(fileposition)};
+    string          filename{virtual(logicalfilename)};
+    unsigned        lfpos{virtual(localfileposition)};
+END;
+
+
+filenameRaw := prefix+'alientest_raw';
+filenameAlien := prefix+'alientest_alien';
+
+namesTable := dataset([
+        {'Hawthorn','Gavin','Slapdash Lane', 'ABCD', ''},
+        {'Hawthorn','Mia','Slapdash Lane', '1234', 'groan'},
+        {'Smithe','Pru','Ashley Road', 'PLEH', 'grown' },
+        {'X','Z','Mars','!EM ', 'help'}], namesRecord);
+
+p := PROJECT(namesTable, TRANSFORM(alienRecord, SELF := LEFT));
+
+sequential(
+    //Output the files two ways - one using alien data types, and one using the equiavlent built in types.
+    output(namesTable,,filenameRaw, thor, overwrite);
+    output(p,,filenameAlien, thor, overwrite);
+
+    //Now read the files back in different ways
+
+    output(DATASET(filenameRaw, namesRecordEx, THOR),,NAMED('RawRaw'));
+    output(DATASET(filenameRaw, alienRecordEx, THOR, __OPTION__(LEGACY),HINT(layoutTranslation('alwaysEcl'))),,NAMED('RawAlien'));
+    output(DATASET(filenameAlien, namesRecordEx, THOR,HINT(layoutTranslation('alwaysEcl'))),,NAMED('AlienRaw'));
+    output(DATASET(filenameAlien, alienRecordEx, THOR, __OPTION__(LEGACY)),,NAMED('AlienAlien'));
+
+    //Read the files in and also project them - to test mixing projection and untranslatable file formats works correctly
+    output(PROJECT(DATASET(filenameRaw, namesRecordEx, THOR), transform(reducedNamesRecordEx, SELF := LEFT)),,NAMED('ProjectRawRaw'));
+    output(PROJECT(DATASET(filenameRaw, alienRecordEx, THOR, __OPTION__(LEGACY),HINT(layoutTranslation('alwaysEcl'))), transform(reducedNamesRecordEx, SELF := LEFT)),,NAMED('ProjectRawAlien'));
+    output(PROJECT(DATASET(filenameAlien, namesRecordEx, THOR,HINT(layoutTranslation('alwaysEcl'))), transform(reducedNamesRecordEx, SELF := LEFT)),,NAMED('ProjectAlienRaw'));
+    output(PROJECT(DATASET(filenameAlien, alienRecordEx, THOR, __OPTION__(LEGACY)), transform(reducedNamesRecordEx, SELF := LEFT)),,NAMED('ProjectAlienAlien'))
+);

+ 52 - 0
testing/regress/ecl/hthor/alien2.xml

@@ -0,0 +1,52 @@
+<Dataset name='Result 1'>
+</Dataset>
+<Dataset name='Result 2'>
+</Dataset>
+<Dataset name='RawRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::hthor::alientest_raw</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::hthor::alientest_raw</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::hthor::alientest_raw</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::hthor::alientest_raw</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='RawAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::hthor::alientest_raw</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::hthor::alientest_raw</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::hthor::alientest_raw</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::hthor::alientest_raw</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='AlienRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::hthor::alientest_alien</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::hthor::alientest_alien</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::hthor::alientest_alien</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::hthor::alientest_alien</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='AlienAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::hthor::alientest_alien</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::hthor::alientest_alien</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::hthor::alientest_alien</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::hthor::alientest_alien</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='ProjectRawRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::hthor::alientest_raw</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::hthor::alientest_raw</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::hthor::alientest_raw</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::hthor::alientest_raw</filename></Row>
+</Dataset>
+<Dataset name='ProjectRawAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::hthor::alientest_raw</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::hthor::alientest_raw</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::hthor::alientest_raw</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::hthor::alientest_raw</filename></Row>
+</Dataset>
+<Dataset name='ProjectAlienRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::hthor::alientest_alien</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::hthor::alientest_alien</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::hthor::alientest_alien</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::hthor::alientest_alien</filename></Row>
+</Dataset>
+<Dataset name='ProjectAlienAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::hthor::alientest_alien</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::hthor::alientest_alien</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::hthor::alientest_alien</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::hthor::alientest_alien</filename></Row>
+</Dataset>

+ 52 - 0
testing/regress/ecl/key/alien2.xml

@@ -0,0 +1,52 @@
+<Dataset name='Result 1'>
+</Dataset>
+<Dataset name='Result 2'>
+</Dataset>
+<Dataset name='RawRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::thorlcr::alientest_raw</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::thorlcr::alientest_raw</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::thorlcr::alientest_raw</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::thorlcr::alientest_raw</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='RawAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::thorlcr::alientest_raw</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::thorlcr::alientest_raw</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::thorlcr::alientest_raw</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::thorlcr::alientest_raw</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='AlienRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::thorlcr::alientest_alien</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::thorlcr::alientest_alien</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::thorlcr::alientest_alien</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::thorlcr::alientest_alien</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='AlienAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::thorlcr::alientest_alien</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::thorlcr::alientest_alien</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::thorlcr::alientest_alien</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::thorlcr::alientest_alien</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='ProjectRawRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::thorlcr::alientest_raw</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::thorlcr::alientest_raw</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::thorlcr::alientest_raw</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::thorlcr::alientest_raw</filename></Row>
+</Dataset>
+<Dataset name='ProjectRawAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::thorlcr::alientest_raw</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::thorlcr::alientest_raw</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::thorlcr::alientest_raw</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::thorlcr::alientest_raw</filename></Row>
+</Dataset>
+<Dataset name='ProjectAlienRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::thorlcr::alientest_alien</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::thorlcr::alientest_alien</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::thorlcr::alientest_alien</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::thorlcr::alientest_alien</filename></Row>
+</Dataset>
+<Dataset name='ProjectAlienAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::thorlcr::alientest_alien</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::thorlcr::alientest_alien</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::thorlcr::alientest_alien</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::thorlcr::alientest_alien</filename></Row>
+</Dataset>

+ 52 - 0
testing/regress/ecl/roxie/alien2.xml

@@ -0,0 +1,52 @@
+<Dataset name='Result 1'>
+</Dataset>
+<Dataset name='Result 2'>
+</Dataset>
+<Dataset name='RawRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::roxie::alientest_raw</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::roxie::alientest_raw</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::roxie::alientest_raw</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::roxie::alientest_raw</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='RawAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::roxie::alientest_raw</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::roxie::alientest_raw</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::roxie::alientest_raw</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::roxie::alientest_raw</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='AlienRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::roxie::alientest_alien</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::roxie::alientest_alien</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::roxie::alientest_alien</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::roxie::alientest_alien</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='AlienAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><addr>Slapdash Lane</addr><extra>ABCD</extra><extra2></extra2><fpos>0</fpos><filename>regress::single::roxie::alientest_alien</filename><lfpos>9223372036854775808</lfpos></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><addr>Slapdash Lane</addr><extra>1234</extra><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::roxie::alientest_alien</filename><lfpos>9223372036854775848</lfpos></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><addr>Ashley Road</addr><extra>PLEH</extra><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::roxie::alientest_alien</filename><lfpos>9223372036854775891</lfpos></Row>
+ <Row><surname>X</surname><forename>Z</forename><addr>Mars</addr><extra>!EM </extra><extra2>help</extra2><fpos>122</fpos><filename>regress::single::roxie::alientest_alien</filename><lfpos>9223372036854775930</lfpos></Row>
+</Dataset>
+<Dataset name='ProjectRawRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::roxie::alientest_raw</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::roxie::alientest_raw</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::roxie::alientest_raw</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::roxie::alientest_raw</filename></Row>
+</Dataset>
+<Dataset name='ProjectRawAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::roxie::alientest_raw</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::roxie::alientest_raw</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::roxie::alientest_raw</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::roxie::alientest_raw</filename></Row>
+</Dataset>
+<Dataset name='ProjectAlienRaw'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::roxie::alientest_alien</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::roxie::alientest_alien</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::roxie::alientest_alien</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::roxie::alientest_alien</filename></Row>
+</Dataset>
+<Dataset name='ProjectAlienAlien'>
+ <Row><surname>Hawthorn</surname><forename>Gavin</forename><extra2></extra2><fpos>0</fpos><filename>regress::single::roxie::alientest_alien</filename></Row>
+ <Row><surname>Hawthorn</surname><forename>Mia</forename><extra2>groan</extra2><fpos>40</fpos><filename>regress::single::roxie::alientest_alien</filename></Row>
+ <Row><surname>Smithe</surname><forename>Pru</forename><extra2>grown</extra2><fpos>83</fpos><filename>regress::single::roxie::alientest_alien</filename></Row>
+ <Row><surname>X</surname><forename>Z</forename><extra2>help</extra2><fpos>122</fpos><filename>regress::single::roxie::alientest_alien</filename></Row>
+</Dataset>