Thu Oct 21, 2021 4:42 am
Login Register Lost Password? Contact Us


Getting my head round the TABLE command.

Comments and questions related to the Enterprise Control Language

Mon Oct 24, 2011 11:12 am Change Time Zone

Hi,

I'm trying to understand the 'Vertical Slice' type of TABLE command.
The source specification in the 'format' seems to have to contain information on the actual recordset being used. (the 1st parameter to the TABLE command)

I can't understand this tie up, as it seems to limit the use of that particular TABLE command to that specific record set. The syntax checker will complain if I attempt to supply a different record set to the TABLE command even though I know it's the same structure. Consequently there does not seem to be a reason for the 1st parameter to the TABLE command given the record set used is defined by the 'format' parameter.

I have an example below which works when the table command is given the record set 'Raw2' but fails is supplied 'Raw3' Even though the structure of Raw2 and Raw3 are the same.
Code: Select all
Layout_Book := RECORD
   STRING Text;
END;

Layout_Verse := RECORD
   UNSIGNED2 Chapter;
    UNSIGNED2 Verse;
   STRING Text;
END;

RawGen := DATASET('~thor::niv::genesis',Layout_Book,CSV(HEADING(4),SEPARATOR('')));
RawExo := DATASET('~thor::niv::exodus',Layout_Book,CSV(HEADING(4),SEPARATOR('')));

Layout_Verse Split(Layout_Book pInput) := TRANSFORM
    SELF.Chapter := (UNSIGNED2)pInput.Text[1..Find(pInput.Text,':',1)];
      SELF.Verse   := (UNSIGNED2)pInput.Text[Find(pInput.Text,':',1)+1..Find(pInput.Text,':',2)];
      SELF.Text    := pInput.Text[Find(pInput.Text,':',2)+1..];
END;

Raw2 := PROJECT(RawGen,Split(LEFT));
Raw3 := PROJECT(RawExo,Split(LEFT));

Verse_with_hash := RECORD
   UNSIGNED2 Chapter := Raw2.Chapter;
   UNSIGNED2 Verse := Raw2.Verse;
   STRING Text := Raw2.Text;
   UNSIGNED4 h := HASH(Raw2.Text,Raw2.Chapter,Raw2.Verse);
END;

WithHash := TABLE(Raw2,Verse_with_hash);
OUTPUT(WithHash);
Allan
 
Posts: 442
Joined: Sat Oct 01, 2011 7:26 pm

Mon Oct 24, 2011 12:48 pm Change Time Zone

Hi Allan,

We need more information. What error (failure) are you receiving? If you modify the record structure to use the Raw3 defaults does it work after that?

For example:

Verse_with_hash := RECORD
UNSIGNED2 Chapter := Raw3.Chapter;
UNSIGNED2 Verse := Raw3.Verse;
STRING Text := Raw3.Text;
UNSIGNED4 h := HASH(Raw3.Text,Raw3.Chapter,Raw3.Verse);
END;

WithHash := TABLE(Raw3,Verse_with_hash);


Regards,

Bob
bforeman
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1005
Joined: Wed Jun 29, 2011 7:13 pm

Mon Oct 24, 2011 1:01 pm Change Time Zone

Hi Bob,

Actually the syntax checker works for:
Code: Select all
WithHash := TABLE(Raw3,Verse_with_hash);

However when submitting to Thor I get error:
Code: Select all
Warning:  (0,0): error C2131: raw2.chapter - Table raw2 is not related to raw3 (0, 0), 0,

If everything is changed to use 'Raw3', as in your example above, then it works.
The datasets have the same structure just contain different data.

Yours

Allan
Allan
 
Posts: 442
Joined: Sat Oct 01, 2011 7:26 pm

Mon Oct 24, 2011 1:17 pm Change Time Zone

Ok, Allan, I think that the error makes sense. As you know, the record layout of the TABLE needs default values defined. If you are creating a TABLE using the Raw3 recordset, it will need to use the default values of the current record being read, and if you are referencing different default values from a different recordset, it does not know which values to use since they are not related. Even though they both have the same structure, they both indeed have different values. Hope this helps!

Best regards,

Bob
bforeman
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1005
Joined: Wed Jun 29, 2011 7:13 pm

Mon Oct 24, 2011 2:22 pm Change Time Zone

Hi Bob,

I must admit I don't understand.

Both DATASETs Raw2 and Raw3 can use the same default values. e.g.
Code: Select all
BlankSet := DATASET([{0,0,'',0}],Verse_with_hash);


So how can I get the record definition 'Verse_with_hash' to be used by both datasets?

Yours

Allan
Allan
 
Posts: 442
Joined: Sat Oct 01, 2011 7:26 pm

Mon Oct 24, 2011 3:22 pm Change Time Zone

Hi Allan,

I don't think you can with TABLE, since the second parameter format also requires the correct source. Here's a simple FUNCTION that generates one TABLE or the other:

Code: Select all
IMPORT Training AS X;

MyTableFunc(BOOLEAN cond) := FUNCTION

myrec := RECORD
    unsigned8 id := X.People.File.id;
    string15  firstname := X.People.File.firstname;
    string25  lastname := X.People.File.lastname;
  END;
myrec2 := RECORD 
    unsigned8 id2 := X.DN.People.id;
    string15  firstname2 := X.DN.People.firstname;
    string25  lastname2 := X.DN.People.lastname;
END;   


MyTable := IF (cond = TRUE,
               TABLE(X.People.File,myrec),
          TABLE(X.DN.People,myrec2));
 
RETURN(MyTable);

END;

MyTableFunc(TRUE);
MyTableFunc(FALSE);
bforeman
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1005
Joined: Wed Jun 29, 2011 7:13 pm

Mon Oct 24, 2011 4:20 pm Change Time Zone

Hi Bob,

SO that FUNCTION works with 2 instances, how about 102 identical record sets?

This ECL will take a lot of getting used to. You seem to have to jump though hoops to do the simplest things.

I suppose in real life one would merge all into one record-set, and somehow in the merge generate a field as a discriminator for use in future processing where the record sets need to be treated differently,

Thanks for your help

Allan
Allan
 
Posts: 442
Joined: Sat Oct 01, 2011 7:26 pm

Mon Oct 24, 2011 4:26 pm Change Time Zone

Hi Allan,

When you change the specs to accomodate 102 different datasets, of course a TABLE may not be the best solution. In that case, a simple PROJECT would do the trick and you could use the same record structure for the different datasets.

There are many ways to the mountain top ;-)

Regards,

Bob
bforeman
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1005
Joined: Wed Jun 29, 2011 7:13 pm

Mon Oct 24, 2011 5:04 pm Change Time Zone

I don't have the data - so I checked this syntax checks - but it may not work :)

Code: Select all
Layout_Book := RECORD
   STRING Text;
END;

Layout_Verse := RECORD
      UNSIGNED1 Book;
    UNSIGNED2 Chapter;
    UNSIGNED2 Verse;
      UNSIGNED4 HashN := 0;
    STRING Text;
END;

Books := ['genesis','exodus','leviticus','numbers']; // etc

Layout_Verse FromBook(UNSIGNED1 Bk) := FUNCTION
   Raw := DATASET('~thor::niv::'+Books[Bk],Layout_Book,CSV(HEADING(4),SEPARATOR('')));
   Layout_Verse Split(Layout_Book pInput) := TRANSFORM
     SELF.Book    := Bk;
    SELF.Chapter := (UNSIGNED2)pInput.Text[1..Find(pInput.Text,':',1)];
    SELF.Verse   := (UNSIGNED2)pInput.Text[Find(pInput.Text,':',1)+1..Find(pInput.Text,':',2)];
    SELF.Text    := pInput.Text[Find(pInput.Text,':',2)+1..];
   END;
   P1 := PROJECT(Raw,Split(LEFT));
   RETURN PROJECT(P1,TRANSFORM(Layout_Verse,SELF.HashN := HASH(LEFT.Text,LEFT.Chapter,LEFT.Verse), SELF := LEFT));
  END;

RawGen := FromBook(1);
RawExo := FromBook(2);

RawGen+RawExo


For this demo example it would be cleaner to pass in the name rather than have the set. The set is useful if you want to use Loop to bring in all the books to one datastream .... (and generally speaking - 1 datastream is WAY better than 66)
dabayliss
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 109
Joined: Fri Apr 29, 2011 1:35 pm

Mon Oct 24, 2011 7:20 pm Change Time Zone

Allan,

>>The source specification in the 'format' seems to have to contain information on the actual recordset being used. (the 1st parameter to the TABLE command)<<

The TABLE function creates a temporary "table" in memory by deriving data from the first parameter recordset and structuring it using the second parameter RECORD structure. Therefore, the RECORD structure has to define, for each field in the table it creates, the datatype (can be inferred), name of the field, AND how to construct the output field.

Now, most TABLE functions (especially the vertical slice variety) simply specify the subset of fields from the dataset that you want to work with (making this a valuable tool for following the "operate only on the data you need" principle), but that is far from the only thing you can do with TABLE.

Here's a simple example that demonstrates doing more than just slicing out some columns:

Code: Select all
IMPORT STD;
ds := DATASET([{'A','B','C'},{'D','E','F'},{'G','H','I'}],
              {STRING1 Ltr1, STRING1 Ltr2, STRING1 Ltr3});

Trec := RECORD
  STRING1 Ltr1 := ds.Ltr1;    //explicitly specifies type, name, and source
  ds.Ltr2;                    //implicitly specifies type, name, and source
  STRING1 Ltr3 := STD.Str.ToLowerCase(ds.Ltr3);    //modify the data
  STRING3 F1 := ds.Ltr1 + ds.Ltr2 + ds.Ltr3;       //build totally new fields
  STRING20 F4 := 'I am a work field';              //create a work field
END;                     
t := TABLE(ds,Trec);
t;                     


Notice my input structure and output from the TABLE are completely different. But each field in Trec defines datatype, name, and source of the result data each in a different way.

HTH,

Richard
richard.taylor@lexisnexis.com
 
Posts: 11
Joined: Wed Jun 15, 2011 6:00 pm

Next

Return to ECL

Who is online

Users browsing this forum: No registered users and 1 guest

cron