dwsLinq update: INTO

I just checked in an update to dwsLinq that covers a big step in its progress: the INTO clause.

This is not quite the same thing as INTO in C#’s version of LINQ.  INTO there basically acts as a naming operator, taking a query expression and giving it a name so that you can use it as a sub-expression in further query work.

I did something different with this.  INTO in dwsLinq takes a function pointer as its argument.  The function has to have a single parameter of type Dataset, and return some value, and the INTO clause changes the output of the entire query expression.

If the INTO function returns an array type, it will be called once, and whatever it returns becomes the query result.  Otherwise, it gets called once for each result in the dataset, and the individual results get collected into an array of whatever type the INTO function returns, which becomes the query result.  The idea is that this can be used to quickly load data into script objects or records.  You provide the basic query, and a function that transforms a dataset row into an object, and let dwsLinq take care of the plumbing.

Having to write a function pointer expression into the query is a bit awkward, but it’s a limitation of the language at the moment.  Once DWS is able to deal with anonymous methods, I’ll expand the capabilities of INTO.

Here’s the test that I wrote, that demonstrates the syntax for both forms of INTO.  Both styles shown here give the same result:

uses System.Data;

function processor(ds: Dataset): integer;
begin
   result := ds.FieldByName('VALUE_1').AsInteger;
end;

function processor2(ds: Dataset): array of integer;
begin
   var value := ds.FieldByName('VALUE_1');
   while ds.step do
      result.add(value.AsInteger);
end;

var db := DataBase.Create('SQLite', ['.\Linq\linqtest.s3db']);

var values := from DB.TBL1
              order by ID
              select VALUE_1
              into @processor;
for var value in values do
   printLn(value);

PrintLn('');

var values2 := from DB.TBL1
               order by ID
               select VALUE_1
               into @processor2;
for var value2 in values2 do
   printLn(value2);

Yes, the @ is necessary for the DWS parser to recognize it as a function pointer.

2 Comments

  1. Eric says:

    When asking the compiler to read an expression, you can specify an expected type as argument, if this type is a function type, and the expression is a function that matches that type, the @ isn’t necessary (same as in Delphi the @ is waived in situations where a function pointer is expected)

Leave a Reply