소스 검색

HPCC-12251 Create cassandra plugin for workunit storage

Simplify getWorkunitsSorted API call to make it easier to implement in
Cassandra.

Add easily configured server to cassandra regression suite test.

Combine secondary tables into a single, case-insensitive, scalable but (in the
future) wildcardable search table.

Added catchall for subtrees.

Refactored noteDirty.

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 10 년 전
부모
커밋
f4758f39b8

+ 14 - 16
common/workunit/workunit.cpp

@@ -2674,8 +2674,8 @@ public:
         return root->numChildren();
     }
 
-    IConstWorkUnitIterator* getWorkUnitsSorted( WUSortField *sortorder, // list of fields to sort by (terminated by WUSFterm)
-                                                WUSortField *filters,   // NULL or list of fields to folteron (terminated by WUSFterm)
+    IConstWorkUnitIterator* getWorkUnitsSorted( WUSortField sortorder, // field to sort by (and flags for desc sort etc)
+                                                WUSortField *filters,   // NULL or list of fields to filter on (terminated by WUSFterm)
                                                 const void *filterbuf,  // (appended) string values for filters
                                                 unsigned startoffset,
                                                 unsigned maxnum,
@@ -2783,19 +2783,17 @@ public:
             }
         }
         query.insert(0, namefilter.get());
-        if (sortorder) {
-            for (unsigned i=0;sortorder[i]!=WUSFterm;i++) {
-                if (so.length())
-                    so.append(',');
-                int fmt = sortorder[i];
-                if (fmt&WUSFreverse)
-                    so.append('-');
-                if (fmt&WUSFnocase)
-                    so.append('?');
-                if (fmt&WUSFnumeric)
-                    so.append('#');
-                so.append(getEnumText(fmt&0xff,workunitSortFields));
-            }
+        if (sortorder)
+        {
+            if (so.length())
+                so.append(',');
+            if (sortorder & WUSFreverse)
+                so.append('-');
+            if (sortorder & WUSFnocase)
+                so.append('?');
+            if (sortorder & WUSFnumeric)
+                so.append('#');
+            so.append(getEnumText(sortorder&0xff,workunitSortFields));
         }
         IArrayOf<IPropertyTree> results;
         Owned<IElementsPager> elementsPager = new CWorkUnitsPager(query.str(), so.length()?so.str():NULL, namefilterlo.get(), namefilterhi.get(), unknownAttributes);
@@ -3127,7 +3125,7 @@ public:
         return baseFactory->setTracingLevel(newLevel);
     }
 
-    virtual IConstWorkUnitIterator* getWorkUnitsSorted( WUSortField *sortorder, // list of fields to sort by (terminated by WUSFterm)
+    virtual IConstWorkUnitIterator* getWorkUnitsSorted( WUSortField sortorder, // field to sort by
                                                         WUSortField *filters,   // NULL or list of fields to filter on (terminated by WUSFterm)
                                                         const void *filterbuf,  // (appended) string values for filters
                                                         unsigned startoffset,

+ 1 - 1
common/workunit/workunit.hpp

@@ -1273,7 +1273,7 @@ interface IWorkUnitFactory : extends IInterface
     virtual IConstWorkUnitIterator * getWorkUnitsByECL(const char * ecl, ISecManager *secmgr = NULL, ISecUser *secuser = NULL) = 0;
     virtual IConstWorkUnitIterator * getWorkUnitsByCluster(const char * cluster, ISecManager *secmgr = NULL, ISecUser *secuser = NULL) = 0;
     virtual IConstWorkUnitIterator * getWorkUnitsByXPath(const char * xpath, ISecManager *secmgr = NULL, ISecUser *secuser = NULL) = 0;
-    virtual IConstWorkUnitIterator * getWorkUnitsSorted(WUSortField * sortorder, WUSortField * filters, const void * filterbuf,
+    virtual IConstWorkUnitIterator * getWorkUnitsSorted(WUSortField sortorder, WUSortField * filters, const void * filterbuf,
                                                         unsigned startoffset, unsigned maxnum, const char * queryowner, __int64 * cachehint, unsigned *total,
                                                         ISecManager *secmgr = NULL, ISecUser *secuser = NULL) = 0;
     virtual unsigned numWorkUnits() = 0;

+ 1 - 1
common/workunit/workunit.ipp

@@ -587,7 +587,7 @@ public:
     virtual IConstWorkUnitIterator * getWorkUnitsByECL(const char * ecl, ISecManager *secmgr = NULL, ISecUser *secuser = NULL) = 0;
     virtual IConstWorkUnitIterator * getWorkUnitsByCluster(const char * cluster, ISecManager *secmgr = NULL, ISecUser *secuser = NULL) = 0;
     virtual IConstWorkUnitIterator * getWorkUnitsByXPath(const char * xpath, ISecManager *secmgr = NULL, ISecUser *secuser = NULL) = 0;  // deprecated
-    virtual IConstWorkUnitIterator* getWorkUnitsSorted(WUSortField *sortorder, // list of fields to sort by (terminated by WUSFterm)
+    virtual IConstWorkUnitIterator* getWorkUnitsSorted(WUSortField sortorder, // field to sort by
                                                 WUSortField *filters,   // NULL or list of fields to filter on (terminated by WUSFterm)
                                                 const void *filterbuf,  // (appended) string values for filters
                                                 unsigned startoffset,

+ 113 - 26
ecl/wutest/wutest.cpp

@@ -143,21 +143,6 @@ bool dump(IConstWorkUnit &w, IProperties *globals)
     return true;
 }
 
-void testPagedWuList(IWorkUnitFactory *factory)
-{
-    __int64 cachehint=0;
-    unsigned n=0;
-    for (unsigned page=0;page<3;page++) {
-        WUSortField sortorder[] = {WUSFuser,WUSFstate,WUSFterm};
-        Owned<IConstWorkUnitIterator> it = factory->getWorkUnitsSorted(sortorder, NULL, NULL, page*10, 10, "nigel", &cachehint, NULL);
-        ForEach(*it) {
-            n++;
-            IConstWorkUnitInfo& wu = it->query();
-            printf("%d: %s, %s, %d\n", n, wu.queryWuid(), wu.queryUser(), (int)wu.getState());
-        }
-    }
-}
-
 #ifdef FORCE_WORKUNITS_TO_CASSANDRA
 extern "C" IWorkUnitFactory *createWorkUnitFactory(const IPropertyTree *props);
 #endif
@@ -214,12 +199,8 @@ int main(int argc, const char *argv[])
         }
         Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
         const char *action = globals->queryProp("#action");
-        if (action && (stricmp(action, "testpaged")==0))
-        {
-            testPagedWuList(factory);
-        }
 #ifdef _USE_CPPUNIT
-        else if (action && (stricmp(action, "-selftest")==0))
+        if (action && (stricmp(action, "-selftest")==0))
         {
             testSize = globals->getPropInt("testSize", 100);
             queryStderrLogMsgHandler()->setMessageFields(MSGFIELD_time | MSGFIELD_milliTime | MSGFIELD_prefix);
@@ -229,8 +210,9 @@ int main(int argc, const char *argv[])
             bool wasSucessful = runner.run( "", false );
             return wasSucessful;
         }
+        else
 #endif
-        else if (action && (stricmp(action, "validate")==0))
+        if (action && (stricmp(action, "validate")==0))
         {
             bool fix = globals->getPropBool("fix", false);
             unsigned errors = factory->validateRepository(fix);
@@ -428,6 +410,7 @@ class WuTest : public CppUnit::TestFixture
     CPPUNIT_TEST_SUITE(WuTest);
         CPPUNIT_TEST(testCreate);
         CPPUNIT_TEST(testList);
+        CPPUNIT_TEST(testSet);
         CPPUNIT_TEST(testDelete);
         CPPUNIT_TEST(testCopy);
     CPPUNIT_TEST_SUITE_END();
@@ -444,7 +427,10 @@ protected:
             VStringBuffer clusterName("WuTestCluster%d", i % 5);
             VStringBuffer jobName("WuTest job %d", i % 3);
             Owned<IWorkUnit>wu = factory->createWorkUnit("WuTest", NULL, NULL, NULL);
-            wu->setState(WUStateFailed);
+            if (i % 6)
+                wu->setState(WUStateCompleted);
+            else
+                wu->setState(WUStateFailed);
             wu->setUser(userId);
             wu->setClusterName(clusterName);
             if (i % 3)
@@ -689,7 +675,7 @@ protected:
         DBGLOG("Comparing xml2 and xml3");
         checkStringsMatch(xml2, xml3);
 
-        // Check that copy preservers everything it should (and resets what it should)
+        // Check that copy preserves everything it should (and resets what it should)
         // We can't directly compare xml1 with xml2 - not everything is copied
         Owned<IPropertyTree> p2 = createPTreeFromXMLString(xml2);
         p2->removeProp("Statistics/Statistic[@kind='WhenCreated']");
@@ -766,6 +752,94 @@ protected:
         ASSERT(factory->validateRepository(false)==0);
     }
 
+    void testSet()
+    {
+        Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
+        unsigned start = msTick();
+        int i;
+        for (i = 0; i < testSize; i++)
+        {
+            Owned<IWorkUnit> wu = factory->updateWorkUnit(wuids.item(i));
+            wu->addProcess("ptype", "pInstance", 54321, "mylog");
+            wu->setAction(WUActionCompile);
+            wu->setApplicationValue("app1", "av1", "value", true);
+            wu->setApplicationValueInt("app2", "av2", 42, true);
+            wu->setIsQueryService(true);
+            wu->setClusterName("clustername");
+            wu->setDebugValue("debug1", "value", true);
+            wu->setDebugValueInt("debug2", 42, true);
+            wu->setJobName("jobname");
+            wu->setPriority(PriorityClassHigh);
+            wu->setPriorityLevel(2) ;
+            wu->setRescheduleFlag(true);
+            wu->setResultLimit(101);
+            wu->setSecurityToken("secret");
+            wu->setState(WUStateAborted);
+            wu->setStateEx("stateEx");
+            wu->setAgentSession(1234567890123);
+//            virtual void setStatistic(StatisticCreatorType creatorType, const char * creator, StatisticScopeType scopeType, const char * scope, StatisticKind kind, const char * optDescription, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue, StatsMergeAction mergeAction) = 0;
+            wu->setTracingValue("trace1", "tvalue1");
+            wu->setTracingValueInt("trace2", 43);
+            wu->setUser("user");
+            wu->setWuScope("scope");
+            wu->setSnapshot("snap");
+            wu->setWarningSeverity(1234, SeverityFatal);
+        }
+        unsigned end = msTick();
+        DBGLOG("%u workunits set in %d ms", testSize, end-start);
+        start = end;
+        SCMStringBuffer s;
+        for (i = 0; i < testSize; i++)
+        {
+            Owned<IConstWorkUnit> wu = factory->openWorkUnit(wuids.item(i), false);
+            if (false)
+            {
+                StringBuffer wuXML;
+                exportWorkUnitToXML(wu, wuXML, true, false, false);
+                DBGLOG("%s", wuXML.str());
+            }
+
+            Owned<IPTreeIterator> processes = wu->getProcesses("ptype", "pInstance");
+            ASSERT(processes->first());
+            IPTree &process = processes->query();
+            ASSERT(process.getPropInt("@pid", 0)==54321);
+            ASSERT(streq(process.queryProp("@log"), "mylog"));
+            ASSERT(!processes->next());
+            ASSERT(wu->getAction() == WUActionCompile);
+            ASSERT(streq(wu->getApplicationValue("app1", "av1", s).str(), "value"));
+            ASSERT(wu->getApplicationValueInt("app2", "av2", 0) == 42);
+            ASSERT(wu->getIsQueryService());
+            ASSERT(streq(wu->queryClusterName(),"clustername"));
+            ASSERT(streq(wu->getDebugValue("debug1", s).str(), "value"));
+            ASSERT(wu->getDebugValueInt("debug2", 0) == 42);
+            ASSERT(streq(wu->queryJobName(),"jobname"));
+            ASSERT(wu->getPriority()==PriorityClassHigh);
+            ASSERT(wu->getPriorityLevel()==2);
+            ASSERT(wu->getRescheduleFlag());
+            ASSERT(wu->getResultLimit()==101);
+            ASSERT(streq(wu->getSecurityToken(s).str(), "secret"));
+            ASSERT(wu->getState()==WUStateAborted);
+            ASSERT(streq(wu->getStateEx(s).str(), "stateEx"));
+            ASSERT(wu->getAgentSession()==1234567890123);
+//            virtual void setStatistic(StatisticCreatorType creatorType, const char * creator, StatisticScopeType scopeType, const char * scope, StatisticKind kind, const char * optDescription, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue, StatsMergeAction mergeAction) = 0;
+            // Tracing is only retrievable via XML
+            const IExtendedWUInterface *ewu = queryExtendedWU(wu);
+            ASSERT(ewu);
+            IPropertyTree *p = ewu->queryPTree();
+            StringBuffer xml;
+            ASSERT(p->queryPropTree("Tracing"));
+            toXML(p->queryPropTree("Tracing"), xml, 0, XML_SortTags);
+            ASSERT(streq(xml, "<Tracing><trace1>tvalue1</trace1><trace2>43</trace2></Tracing>"));
+
+            ASSERT(streq(wu->queryUser(), "user"));
+            ASSERT(streq(wu->getWuScope(s).str(), "scope"));
+            ASSERT(streq(wu->getSnapshot(s).str(),"snap"));
+            ASSERT(wu->getWarningSeverity(1234, SeverityInformation) == SeverityFatal);
+        }
+        end = msTick();
+        DBGLOG("%u workunits reread in %d ms", testSize, end-start);
+    }
+
     void testList()
     {
         Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
@@ -790,7 +864,7 @@ protected:
             ASSERT(streq(wu.queryUser(), "WuTestUser0"));
             numIterated++;
         }
-        DBGLOG("%d workunits listed in %d ms", numIterated, msTick()-start);
+        DBGLOG("%d owned workunits listed in %d ms", numIterated, msTick()-start);
         ASSERT(numIterated == (testSize+49)/50);
 
         // And by non-existent owner...
@@ -801,7 +875,7 @@ protected:
         {
             numIterated++;
         }
-        DBGLOG("%d workunits listed in %d ms", numIterated, msTick()-start);
+        DBGLOG("%d non-existent workunits listed in %d ms", numIterated, msTick()-start);
         ASSERT(numIterated == 0);
 
         // And by cluster
@@ -814,9 +888,22 @@ protected:
             ASSERT(streq(wu.queryClusterName(), "WuTestCluster0"));
             numIterated++;
         }
-        DBGLOG("%d workunits listed in %d ms", numIterated, msTick()-start);
+        DBGLOG("%d cluster workunits listed in %d ms", numIterated, msTick()-start);
         ASSERT(numIterated == (testSize+4)/5);
 
+        // And by state
+        wus.setown(factory->getWorkUnitsByState(WUStateFailed, NULL, NULL));
+        start = msTick();
+        numIterated = 0;
+        ForEach(*wus)
+        {
+            IConstWorkUnitInfo &wu = wus->query();
+            ASSERT(wu.getState() == WUStateFailed);
+            numIterated++;
+        }
+        DBGLOG("%d failed workunits listed in %d ms", numIterated, msTick()-start);
+        ASSERT(numIterated == (testSize+5)/6);
+
     }
 };
 StringArray WuTest::wuids;

+ 12 - 12
esp/services/ws_workunits/ws_workunitsService.cpp

@@ -1781,31 +1781,31 @@ void doWUQueryWithSort(IEspContext &context, IEspWUQueryRequest & req, IEspWUQue
         pagesize = count;
     }
 
-    WUSortField sortorder[2] = {(WUSortField) (WUSFwuid | WUSFreverse), WUSFterm};
-    if(notEmpty(req.getSortby()))
+    WUSortField sortorder = (WUSortField) (WUSFwuid | WUSFreverse);
+    if (notEmpty(req.getSortby()))
     {
         const char *sortby = req.getSortby();
         if (strieq(sortby, "Owner"))
-            sortorder[0] = WUSFuser;
+            sortorder = WUSFuser;
         else if (strieq(sortby, "JobName"))
-            sortorder[0] = WUSFjob;
+            sortorder = WUSFjob;
         else if (strieq(sortby, "Cluster"))
-            sortorder[0] = WUSFcluster;
+            sortorder = WUSFcluster;
         else if (strieq(sortby, "RoxieCluster"))
-            sortorder[0] = WUSFroxiecluster;
+            sortorder = WUSFroxiecluster;
         else if (strieq(sortby, "Protected"))
-            sortorder[0] = WUSFprotected;
+            sortorder = WUSFprotected;
         else if (strieq(sortby, "State"))
-            sortorder[0] = WUSFstate;
+            sortorder = WUSFstate;
         else if (strieq(sortby, "ClusterTime"))
-            sortorder[0] = (WUSortField) (WUSFtotalthortime+WUSFnumeric);
+            sortorder = (WUSortField) (WUSFtotalthortime+WUSFnumeric);
         else
-            sortorder[0] = WUSFwuid;
+            sortorder = WUSFwuid;
 
-        sortorder[0] = (WUSortField) (sortorder[0] | WUSFnocase);
+        sortorder = (WUSortField) (sortorder | WUSFnocase);
         bool descending = req.getDescending();
         if (descending)
-            sortorder[0] = (WUSortField) (sortorder[0] | WUSFreverse);
+            sortorder = (WUSortField) (sortorder | WUSFreverse);
     }
 
     WUSortField filters[10];

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 615 - 309
plugins/cassandra/cassandraembed.cpp


+ 6 - 0
system/jlib/jstring.cpp

@@ -75,6 +75,12 @@ StringBuffer::StringBuffer(const char *value)
     append(value);
 }
 
+StringBuffer::StringBuffer(char value)
+{
+    init();
+    append(value);
+}
+
 StringBuffer::StringBuffer(unsigned len, const char *value)
 {
     init();

+ 1 - 0
system/jlib/jstring.hpp

@@ -41,6 +41,7 @@ public:
     StringBuffer(unsigned len, const char *value);
     StringBuffer(const StringBuffer & value);
     StringBuffer(bool useInternal);
+    StringBuffer(char value);
     ~StringBuffer();
 
     inline size32_t length() const                      { return curLen; }

+ 30 - 23
testing/regress/ecl/cassandra-simple.ecl

@@ -28,6 +28,8 @@ IMPORT cassandra;
 // Note that the default values specified in the fields will be used when a NULL value is being
 // returned from Cassandra
 
+server := '127.0.0.1';
+
 maprec := RECORD
    string fromVal => string toVal
  END;
@@ -61,11 +63,11 @@ init2 := ROW({'name4' , 3, true, 9.10, 11.12, D'aa55aa55', 987.65, U'Baße', U'B
 
 // Note that server will default to localhost if not specified...
 
-createks() := EMBED(cassandra : server('127.0.0.1'),user('rchapman'))
+createks() := EMBED(cassandra : server(server),user('rchapman'))
   CREATE KEYSPACE IF NOT EXISTS test WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '3' } ;
 ENDEMBED;
 
-createTables() := EMBED(cassandra : server('127.0.0.1'),user('rchapman'),keyspace('test'))
+createTables() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   DROP TABLE IF EXISTS tbl1;
 
   // Note that an ECL SET can map to either a SET or a LIST in Cassandra (it's actually closer to a LIST since repeated values are allowed and order is preserved)
@@ -96,23 +98,23 @@ ENDEMBED;
 // has restrictions about what can be done in a batch, we can't default to using batch
 // unless told to...
 
-initialize(dataset(childrec) values) := EMBED(cassandra : user('rchapman'),keyspace('test'),batch('unlogged'))
+initialize(dataset(childrec) values) := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'),batch('unlogged'))
   INSERT INTO tbl1 (name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1) values (?,?,?,?,?,?,?,?,?,?,?,?,?);
 ENDEMBED;
 
-initialize2(row(childrec) values) := EMBED(cassandra : user('rchapman'),keyspace('test'))
+initialize2(row(childrec) values) := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   INSERT INTO tbl1 (name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1) values (?,?,?,?,?,?,?,?,?,?,?,?,?);
 ENDEMBED;
 
 // Returning a dataset
 
-dataset(childrec) testCassandraDS() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+dataset(childrec) testCassandraDS() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1 from tbl1;
 ENDEMBED;
 
 // Returning a single row
 
-childrec testCassandraRow() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+childrec testCassandraRow() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1 from tbl1 LIMIT 1;
 ENDEMBED;
 
@@ -138,64 +140,68 @@ testCassandraParms(
    // Note we can't pass a dataset as a paramter to bind to a collection field - it would be interpreted as 'execute once per value in the dataset'
    // You have to pass a record containing the field as a child dataset
    ROW(mapwrapper) map1
-   ) := EMBED(cassandra : user('rchapman'),keyspace('test'))
+   ) := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   INSERT INTO tbl1 (name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1) values (?,?,?,?,?,?,'8.76543',?,?,?,?,?,?);
 ENDEMBED;
 
 // Returning scalars
 
-string testCassandraString() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+string testCassandraString() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT name from tbl1 LIMIT 1;
 ENDEMBED;
 
-dataset(childrec) testCassandraStringParam(string filter) := EMBED(cassandra : user('rchapman'),keyspace('test'))
+dataset(childrec) testCassandraStringParam(string filter) := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1 from tbl1 where name = ?;
 ENDEMBED;
 
-integer testCassandraInt() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+dataset(childrec) testCassandraStringSetParam(set of string filter) := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
+  SELECT name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1 from tbl1 where name IN ?;
+ENDEMBED;
+
+integer testCassandraInt() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT value from tbl1 LIMIT 1;
 ENDEMBED;
 
-boolean testCassandraBool() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+boolean testCassandraBool() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT boolval from tbl1 WHERE name='name1';
 ENDEMBED;
 
-real8 testCassandraReal8() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+real8 testCassandraReal8() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT r8 from tbl1 WHERE name='name1';
 ENDEMBED;
 
-real4 testCassandraReal4() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+real4 testCassandraReal4() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT r4 from tbl1 WHERE name='name1';
 ENDEMBED;
 
-data testCassandraData() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+data testCassandraData() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT d from tbl1 WHERE name='name1';
 ENDEMBED;
 
-UTF8 testCassandraUtf8() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+UTF8 testCassandraUtf8() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT u1 from tbl1 WHERE name='name1';
 ENDEMBED;
 
-UNICODE testCassandraUnicode() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+UNICODE testCassandraUnicode() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT u2 from tbl1 WHERE name='name1';
 ENDEMBED;
 
-STRING testCassandraAscii() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+STRING testCassandraAscii() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT a from tbl1 WHERE name='name1';
 ENDEMBED;
 
-SET OF STRING testCassandraSet() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+SET OF STRING testCassandraSet() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT set1 from tbl1 WHERE name='name1';
 ENDEMBED;
 
-SET OF INTEGER4 testCassandraList() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+SET OF INTEGER4 testCassandraList() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT list1 from tbl1 WHERE name='name1';
 ENDEMBED;
 
 // Just as you can't pass a dataset parameter to bind to a map column (only a child dataset of a record),
 // if you wanted to return just a map column you have to do so via a child dataset
 
-MapWrapper testCassandraMap() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+MapWrapper testCassandraMap() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT map1 from tbl1 WHERE name='name1';
 ENDEMBED;
 
@@ -205,7 +211,7 @@ stringrec := RECORD
    string name
 END;
 
-TRANSFORM(childrec) t(stringrec L) := EMBED(cassandra : user('rchapman'),keyspace('test'))
+TRANSFORM(childrec) t(stringrec L) := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1 from tbl1 where name = ?;
 ENDEMBED;
 
@@ -220,7 +226,7 @@ stringrec extractName(childrec l) := TRANSFORM
   SELF := l;
 END;
 
-dataset(childrec) testCassandraDSParam(dataset(stringrec) inrecs) := EMBED(cassandra : user('rchapman'),keyspace('test'))
+dataset(childrec) testCassandraDSParam(dataset(stringrec) inrecs) := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT name, value, boolval, r8, r4,d,ddd,u1,u2,a,set1,list1,map1 from tbl1 where name = ?;
 ENDEMBED;
 
@@ -237,7 +243,7 @@ testCassandraBulk := initialize(s1);
 
 // Check that 25000 got inserted
 
-integer testCassandraCount() := EMBED(cassandra : user('rchapman'),keyspace('test'))
+integer testCassandraCount() := EMBED(cassandra : server(server),user('rchapman'),keyspace('test'))
   SELECT COUNT(*) from tbl1;
 ENDEMBED;
 
@@ -255,6 +261,7 @@ sequential (
   OUTPUT(testCassandraRow().name),
   OUTPUT(testCassandraString()),
   OUTPUT(testCassandraStringParam(testCassandraString())),
+  OUTPUT(testCassandraStringSetParam(['name1', 'name2'])),
   OUTPUT(testCassandraInt()),
   OUTPUT(testCassandraBool()),
   OUTPUT(testCassandraReal8()),

+ 17 - 13
testing/regress/ecl/key/cassandra-simple.xml

@@ -15,45 +15,49 @@
  <Row><name>name1</name><value>1</value><boolval>true</boolval><r8>1.2</r8><r4>3.400000095367432</r4><d>6161353561613535</d><ddd>1234567.89</ddd><u1>Straße</u1><u2>Straße</u2><a>Ascii</a><set1><Item>one</Item><Item>three</Item><Item>two</Item></set1><list1><Item>5</Item><Item>4</Item><Item>4</Item><Item>3</Item></list1><map1><Row><fromval>b</fromval><toval>banana</toval></Row><Row><fromval>a</fromval><toval>apple</toval></Row></map1></Row>
 </Dataset>
 <Dataset name='Result 5'>
- <Row><Result_5>1</Result_5></Row>
+ <Row><name>name1</name><value>1</value><boolval>true</boolval><r8>1.2</r8><r4>3.400000095367432</r4><d>6161353561613535</d><ddd>1234567.89</ddd><u1>Straße</u1><u2>Straße</u2><a>Ascii</a><set1><Item>one</Item><Item>three</Item><Item>two</Item></set1><list1><Item>5</Item><Item>4</Item><Item>4</Item><Item>3</Item></list1><map1><Row><fromval>b</fromval><toval>banana</toval></Row><Row><fromval>a</fromval><toval>apple</toval></Row></map1></Row>
+ <Row><name>name2</name><value>2</value><boolval>false</boolval><r8>5.6</r8><r4>7.800000190734863</r4><d>3030</d><ddd>-1234567.89</ddd><u1>là</u1><u2>là</u2><a>Ascii</a><set1></set1><list1></list1><map1></map1></Row>
 </Dataset>
 <Dataset name='Result 6'>
- <Row><Result_6>true</Result_6></Row>
+ <Row><Result_6>1</Result_6></Row>
 </Dataset>
 <Dataset name='Result 7'>
- <Row><Result_7>1.2</Result_7></Row>
+ <Row><Result_7>true</Result_7></Row>
 </Dataset>
 <Dataset name='Result 8'>
- <Row><Result_8>3.400000095367432</Result_8></Row>
+ <Row><Result_8>1.2</Result_8></Row>
 </Dataset>
 <Dataset name='Result 9'>
- <Row><Result_9>6161353561613535</Result_9></Row>
+ <Row><Result_9>3.400000095367432</Result_9></Row>
 </Dataset>
 <Dataset name='Result 10'>
- <Row><Result_10>Straße</Result_10></Row>
+ <Row><Result_10>6161353561613535</Result_10></Row>
 </Dataset>
 <Dataset name='Result 11'>
  <Row><Result_11>Straße</Result_11></Row>
 </Dataset>
 <Dataset name='Result 12'>
- <Row><Result_12><Item>one</Item><Item>three</Item><Item>two</Item></Result_12></Row>
+ <Row><Result_12>Straße</Result_12></Row>
 </Dataset>
 <Dataset name='Result 13'>
- <Row><Result_13><Item>5</Item><Item>4</Item><Item>4</Item><Item>3</Item></Result_13></Row>
+ <Row><Result_13><Item>one</Item><Item>three</Item><Item>two</Item></Result_13></Row>
 </Dataset>
 <Dataset name='Result 14'>
+ <Row><Result_14><Item>5</Item><Item>4</Item><Item>4</Item><Item>3</Item></Result_14></Row>
+</Dataset>
+<Dataset name='Result 15'>
  <Row><fromval>b</fromval><toval>banana</toval></Row>
  <Row><fromval>a</fromval><toval>apple</toval></Row>
 </Dataset>
-<Dataset name='Result 15'>
+<Dataset name='Result 16'>
  <Row><name>name1</name><value>1</value><boolval>true</boolval><r8>1.2</r8><r4>3.400000095367432</r4><d>6161353561613535</d><ddd>1234567.89</ddd><u1>Straße</u1><u2>Straße</u2><a>Ascii</a><set1><Item>one</Item><Item>three</Item><Item>two</Item></set1><list1><Item>5</Item><Item>4</Item><Item>4</Item><Item>3</Item></list1><map1><Row><fromval>b</fromval><toval>banana</toval></Row><Row><fromval>a</fromval><toval>apple</toval></Row></map1></Row>
  <Row><name>name2</name><value>2</value><boolval>false</boolval><r8>5.6</r8><r4>7.800000190734863</r4><d>3030</d><ddd>-1234567.89</ddd><u1>là</u1><u2>là</u2><a>Ascii</a><set1></set1><list1></list1><map1></map1></Row>
 </Dataset>
-<Dataset name='Result 16'>
-</Dataset>
 <Dataset name='Result 17'>
- <Row><Result_17>25001</Result_17></Row>
 </Dataset>
 <Dataset name='Result 18'>
- <Row><Result_18>Done</Result_18></Row>
+ <Row><Result_18>25001</Result_18></Row>
+</Dataset>
+<Dataset name='Result 19'>
+ <Row><Result_19>Done</Result_19></Row>
 </Dataset>