std.database

Erik Smith via Digitalmars-d digitalmars-d at puremagic.com
Fri Mar 4 10:42:45 PST 2016


On Friday, 4 March 2016 at 16:43:00 UTC, Kagamin wrote:
> On Friday, 4 March 2016 at 14:44:48 UTC, Erik Smith wrote:
>> Actually I like this and I think it can work.  I'm trying to 
>> keep a single execute function name for both row/no-row 
>> queries. I can still return the range proxy for no-row queries 
>> that is either empty or throws on access.
>
> Yes, that's the idea.
>
>> I'm just waiting for the code to settle a bit in a basic 
>> working state before I refactor into a two layer design.
>
> Another idea from previous attempts: rename `execute` to 
> `query`.
> foreach(row; db.query("select * from t"))
> { ... }
> And name for package: std.sql
>
>>> The result set is even iterator/stream, i.e. conceptually has 
>>> even less container properties than ranges themselves. Why 
>>> would you think of it as a container? I think it's ok as 
>>> input range. Anyway, this `execute` method is a frontend, 
>>> i.e. it's replaceable without touching the driver.
>>
>> The range itself is an InputRange.  The statement is acting as 
>> a container only in that it is the source of the range and 
>> holds the data.  I agree that it is confusing to use the term 
>> container although it seems to fit the definition of one.
>
> `execute` should not return a statement, but a result set 
> reader, that would be a range. Yeah, the result set is indeed a 
> range conceptually: it has a definite number of ordered rows, a 
> beginning and an end.



On further thought, execute() should definitely return something 
but I think it needs to return a Result (alternative name 
RowSet), the actual container, rather than the range.  This more 
cleanly separates out the post execute state management into a 
separate object from Statement.  The user will often want other 
things from the execute then just the range, such as meta-data (# 
columns, columns names/types) describing the returned table and 
RowSet provides convenient access to it. This also suggests that 
execute should be explicit & once/only, which I think is better.  
Here is an updated example to illustrate:

     auto db = createDatabase("file:///testdb");
     auto rowSet = db.connection().statement("select name,score 
from score").execute;
     foreach (r; rowSet) writeln(r[0].as!string,",",r[1].as!int);

I'll track query as an alternative name for execute() and std.sql 
as alternative for std.database.






More information about the Digitalmars-d mailing list