October 12, 2011
On 10/11/2011 5:31 PM, Andrei Alexandrescu wrote:
> On 10/11/11 3:05 PM, Jacob Carlborg wrote:
>> If we're talking use cases and high level interfaces I would go with
>> something like:
> [snip]
>> I recommend that everyone take a good look at ActiveRecord in Ruby on
>> Rails:
>>
>> http://guides.rubyonrails.org/active_record_querying.html
>> http://guides.rubyonrails.org/association_basics.html
>> http://guides.rubyonrails.org/active_record_validations_callbacks.html
>
> I confess the example you gave looks very foreign to me. From consulting
> http://guides.rubyonrails.org/active_record_querying.html, I see Ruby's
> active records esentially recode relational algebra in Ruby (as for the
> constructs the equivalent SQL is shown).
>
> For a variety of reasons, this would be tenuous in D. One simple reason
> is that e.g. lambdas don't offer access to textual representation, which
> would be necessary to translate lambda-based conditions into SQL text.
>
> I might be narrow-minded, but I thought we're still looking at writing
> and executing good old SQL code.
>
>
> Andrei
>

We should always allow the user to get down to the nitty-gritty and write good ol' SQL statements and execute them. However, writing all that plumbing code gets old very quickly, so if we can provide some clean and simple frameworks on top of that, users would appreciate it.
October 12, 2011
On 10/11/11 7:43 PM, Johann MacDonagh wrote:
> We should always allow the user to get down to the nitty-gritty and
> write good ol' SQL statements and execute them. However, writing all
> that plumbing code gets old very quickly, so if we can provide some
> clean and simple frameworks on top of that, users would appreciate it.

The way I see it, I should either learn SQL plus some alternate syntax for it, or SQL alone.

Andrei
October 12, 2011
On Tue, 11 Oct 2011 09:29:57 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> On 10/10/11 11:02 PM, Robert Jacques wrote:
>> On Mon, 10 Oct 2011 11:09:34 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 10/10/11 7:01 AM, Steve Teale wrote:
>>
>> [snip]
>>
>>> That's a bug in std.variant. Large structs should be supported
>>> automatically by using an indirection and dynamic allocation.
>>
>> For what it's worth, my improved Variant proposal, does do that. (i.e.
>> it fixes the bug)
>
> Is it ready for review?
>
> Andrei
>

Yes. However, I'm currently writing my PhD thesis so my bandwidth is limited.
October 12, 2011
>>
>> I might be narrow-minded, but I thought we're still looking at writing and executing good old SQL code.
>>

>> Andrei
>>
>>
> We should always allow the user to get down to the nitty-gritty and write good ol' SQL statements and execute them. However, writing all that plumbing code gets old very quickly, so if we can provide some clean and simple frameworks on top of that, users would appreciate it.

I'm mostly with Andei. I'm all for sophisticated techniques, but what the user has to do should not look like a primer for them. Also if the user has to change down a cog the lower-level interfaces should not look like they're written in another language.

From my experiments with MySQL I believe we can provide clean and simple frameworks. But, you get what you pay for - simple interfaces will be suitable for simple cases.

Steve
October 12, 2011
On Mon, 10 Oct 2011 22:09:49 +0200, Piotr Szturmaj wrote:

> Steve Teale wrote:
>> I've just been looking at the documentation for the PostgreSQL C api. Wow!
>>
>> It is so different from MySQL, and so clean. No out parameters from queries. That one is not going to be a problem.
>>
>> Steve
> 
> PostgreSQL's C lib is not needed if we handle postgres protocol directly
> (already done).

Is that something that the user is going to be comfortable with if she has to step out of the bounds of our implementation. I would feel better using Posgres' excellent api documentation.
October 12, 2011
On 2011-10-11 23:09, Johann MacDonagh wrote:
> On 10/11/2011 4:07 AM, Jacob Carlborg wrote:
>>
>> I think that the use of opDispatch and selecting with a struct should be
>> available at the higher level interfaces and not in the low level
>> interface.
>>
>
> What do you mean by this? Do you mean instead of having the opDispatch
> in the Connection class, we'd have it in a separate struct / template /
> other magic? This would allow us to utilize this method for other
> sources of data, such as XML.

Something like that. Take advantage of opDispatch in a more ORM like interface. Which also hides the connection and executing of raw SQL.

> On the other hand though, this doesn't add a whole lot. Let's say we had
> this code:
>
> auto rows = db.execute("SELECT score, a.user FROM users a JOIN scores b
> on a.user = b.user");
> foreach (row; rows) {
> writeln(to!int(row["score"]));
> }

I think that the above code would sit in a middle layer between the lower level of the database driver and a higher level of an ORM like interface. See my reply to one of Andrei's posts.

-- 
/Jacob Carlborg
October 12, 2011
On 2011-10-11 23:31, Andrei Alexandrescu wrote:
> On 10/11/11 3:05 PM, Jacob Carlborg wrote:
>> If we're talking use cases and high level interfaces I would go with
>> something like:
> [snip]
>> I recommend that everyone take a good look at ActiveRecord in Ruby on
>> Rails:
>>
>> http://guides.rubyonrails.org/active_record_querying.html
>> http://guides.rubyonrails.org/association_basics.html
>> http://guides.rubyonrails.org/active_record_validations_callbacks.html
>
> I confess the example you gave looks very foreign to me. From consulting
> http://guides.rubyonrails.org/active_record_querying.html, I see Ruby's
> active records esentially recode relational algebra in Ruby (as for the
> constructs the equivalent SQL is shown).

Yes, exactly. The point is to have as much as possible in functions instead of string literals and have a more Ruby like API than an SQL looking API.

connection.select("*").from("users");

instead of

connection.execute("select * from users")

Then they wrap everything in an object oriented API.

> For a variety of reasons, this would be tenuous in D. One simple reason
> is that e.g. lambdas don't offer access to textual representation, which
> would be necessary to translate lambda-based conditions into SQL text.

ActiveRecord doesn't support these lambda-based conditions out of the box. It is possible with the help of plugins, which uses a Ruby parser to get things done.

I though that it might be possible to do in D, without the use of a parser. Take this for example:

Post.where(p => p.title == "asd")

"p" would be some kind of object/struct that overloads opDispatch. The opDispatch method would return an object/struct that overloads opCmp and opEquals. opCmp/opEquals would then return an object/struct that have recorded the comparison. The "where" method can then translate it in to raw SQL.

To this to work opCmp/opEquals need to be able to return a struct or an object, I don't know if this is possible.

> I might be narrow-minded, but I thought we're still looking at writing
> and executing good old SQL code.
>
>
> Andrei

That would of course still be needed. I would consider that interface sit in the middle layer, above the lower driver level and below a higher ORM like level.

Everyone is of course free to choose at which layer they want to interface with the database.

-- 
/Jacob Carlborg
October 12, 2011
On 2011-10-12 02:43, Johann MacDonagh wrote:
> On 10/11/2011 5:31 PM, Andrei Alexandrescu wrote:
>> On 10/11/11 3:05 PM, Jacob Carlborg wrote:
>>> If we're talking use cases and high level interfaces I would go with
>>> something like:
>> [snip]
>>> I recommend that everyone take a good look at ActiveRecord in Ruby on
>>> Rails:
>>>
>>> http://guides.rubyonrails.org/active_record_querying.html
>>> http://guides.rubyonrails.org/association_basics.html
>>> http://guides.rubyonrails.org/active_record_validations_callbacks.html
>>
>> I confess the example you gave looks very foreign to me. From consulting
>> http://guides.rubyonrails.org/active_record_querying.html, I see Ruby's
>> active records esentially recode relational algebra in Ruby (as for the
>> constructs the equivalent SQL is shown).
>>
>> For a variety of reasons, this would be tenuous in D. One simple reason
>> is that e.g. lambdas don't offer access to textual representation, which
>> would be necessary to translate lambda-based conditions into SQL text.
>>
>> I might be narrow-minded, but I thought we're still looking at writing
>> and executing good old SQL code.
>>
>>
>> Andrei
>>
>
> We should always allow the user to get down to the nitty-gritty and
> write good ol' SQL statements and execute them. However, writing all
> that plumbing code gets old very quickly, so if we can provide some
> clean and simple frameworks on top of that, users would appreciate it.

Yes, exactly. The point of having several layers built on top of each other is that everyone is free to choose on which layer they want to interact with the database.

If someone is comfortable with interacting with the database in an object oriented API they're free to do that. If they're instead more comfortable in executing raw SQL, then that's possible as well.

-- 
/Jacob Carlborg
October 12, 2011
On Wednesday, October 12, 2011 08:57:54 Jacob Carlborg wrote:
> On 2011-10-11 23:31, Andrei Alexandrescu wrote:
> > On 10/11/11 3:05 PM, Jacob Carlborg wrote:
> >> If we're talking use cases and high level interfaces I would go with
> > 
> >> something like:
> > [snip]
> > 
> >> I recommend that everyone take a good look at ActiveRecord in Ruby on Rails:
> >> 
> >> http://guides.rubyonrails.org/active_record_querying.html http://guides.rubyonrails.org/association_basics.html http://guides.rubyonrails.org/active_record_validations_callbacks.html
> > 
> > I confess the example you gave looks very foreign to me. From consulting http://guides.rubyonrails.org/active_record_querying.html, I see Ruby's active records esentially recode relational algebra in Ruby (as for the constructs the equivalent SQL is shown).
> 
> Yes, exactly. The point is to have as much as possible in functions instead of string literals and have a more Ruby like API than an SQL looking API.
> 
> connection.select("*").from("users");
> 
> instead of
> 
> connection.execute("select * from users")

I don't know what all of the pros and cons are, since I'm not all that experienced with DB stuff, but on the surface at least, from the perspective of usability, I don't see anything better about the first one than the second one.

- Jonathan M Davis
October 12, 2011
On 2011-10-11 23:31, Andrei Alexandrescu wrote:
> On 10/11/11 3:05 PM, Jacob Carlborg wrote:
>> If we're talking use cases and high level interfaces I would go with
>> something like:
> [snip]
>> I recommend that everyone take a good look at ActiveRecord in Ruby on
>> Rails:
>>
>> http://guides.rubyonrails.org/active_record_querying.html
>> http://guides.rubyonrails.org/association_basics.html
>> http://guides.rubyonrails.org/active_record_validations_callbacks.html
>
> I confess the example you gave looks very foreign to me. From consulting
> http://guides.rubyonrails.org/active_record_querying.html, I see Ruby's
> active records esentially recode relational algebra in Ruby (as for the
> constructs the equivalent SQL is shown).
>
> For a variety of reasons, this would be tenuous in D. One simple reason
> is that e.g. lambdas don't offer access to textual representation, which
> would be necessary to translate lambda-based conditions into SQL text.

This is an example of how a lambda-based condition can be translated into SQL:

module test;

import std.stdio;
import std.conv;

struct Result
{
    string str;
}

struct Compare
{
    string str;

    Result eq (T) (T t)
    {
        return Result(str ~ " = '" ~ s ~ "'");
    }
}

struct Table
{
    Compare opDispatch (string name) ()
    {
        return Compare(name);
    }
}

void where (Result delegate (Table) dg)
{
    auto result = dg(Table());
    writeln("where ", result.str);
}

void main ()
{
    where((Table post){
        return post.name.eq("foobar");
    });
}

The above code will print "where name = 'foobar'".

Here I'm using the "eq" method instead of opEquals since opEquals requires a specific signature.

-- 
/Jacob Carlborg