Jump to page: 1 2 3
Thread overview
Abstract Database Interface
Oct 28, 2012
BLM768
Oct 28, 2012
Jacob Carlborg
Oct 29, 2012
BLM768
Oct 29, 2012
Jacob Carlborg
Oct 29, 2012
BLM768
Oct 29, 2012
Jacob Carlborg
Oct 29, 2012
BLM768
Oct 29, 2012
Jacob Carlborg
Oct 30, 2012
BLM768
Oct 30, 2012
Jacob Carlborg
Oct 30, 2012
Philippe Sigaud
Oct 30, 2012
Kapps
Oct 30, 2012
Jacob Carlborg
Oct 30, 2012
Jacob Carlborg
Oct 30, 2012
Philippe Sigaud
Oct 30, 2012
Timon Gehr
Oct 31, 2012
Philippe Sigaud
Dec 23, 2012
Timon Gehr
Dec 24, 2012
Philippe Sigaud
Dec 24, 2012
BLM768
Oct 28, 2012
Rory McGuire
Oct 28, 2012
Robik
Oct 29, 2012
BLM768
Nov 07, 2012
Marco Leise
October 28, 2012
I've recently been working with Ruby's ActiveRecord as part of my job, and I realized that D was powerful enough to make a similar abstraction layer. I've been playing with the idea for a little while, and I've put up some code at https://github.com/blm768/adbi. It isn't nearly as comprehensive as ActiveRecord, but it captures the basic idea of representing database structures as objects/structs.

Using it is something like this:

module main;

import std.stdio;

import adbi.model;
import adbi.sqlite3.database;

struct Test {
	mixin Model!"test";
	
	const(char)[] name;
	double num;
	mixin reference!("test2", "test2", Test2);
}

struct Test2 {
	mixin Model!"test2";
	int value;
}

int main(string[] args) {
	auto db = new Sqlite3Database("test.db");
	auto q = db.query("SELECT * FROM test;");
	
	Test.updateSchema(db);
	Test2.updateSchema(db);
	
	auto range = ModelRange!Test(q);
	
	foreach(value; range) {
		writeln(value);
	}
	
	auto q2 = db.query("SELECT * FROM test, test2 WHERE test2_id = test2.id");
	
	auto r2 = ModelRange!(Join!(Test, Test2))(q2);
	
	foreach(j; r2) {
		writeln(j);
	}
	
	return 0;
}

This code prints out every entry in the "test" table, then prints the results of a join on the "test" and "test2" tables. The calls to updateSchema() set up some static members of Test and Test2; after these calls, the library does not perform any operations with the column names, which should make retrieving a record noticeably faster than in a system like ActiveRecord. The downside is that these functions must be called every time the database schema changes in a way that affects column order, but that should happen very rarely, if ever, in a typical application.

The code is far from complete, but it's an interesting toy and might actually be useful for simple applications once some of the issues are ironed out.

October 28, 2012
On 2012-10-28 02:31, BLM768 wrote:
> I've recently been working with Ruby's ActiveRecord as part of my job,
> and I realized that D was powerful enough to make a similar abstraction
> layer. I've been playing with the idea for a little while, and I've put
> up some code at https://github.com/blm768/adbi. It isn't nearly as
> comprehensive as ActiveRecord, but it captures the basic idea of
> representing database structures as objects/structs.
>
> Using it is something like this:
>
> module main;
>
> import std.stdio;
>
> import adbi.model;
> import adbi.sqlite3.database;
>
> struct Test {
>      mixin Model!"test";
>
>      const(char)[] name;
>      double num;
>      mixin reference!("test2", "test2", Test2);
> }
>
> struct Test2 {
>      mixin Model!"test2";
>      int value;
> }
>
> int main(string[] args) {
>      auto db = new Sqlite3Database("test.db");
>      auto q = db.query("SELECT * FROM test;");
>
>      Test.updateSchema(db);
>      Test2.updateSchema(db);
>
>      auto range = ModelRange!Test(q);
>
>      foreach(value; range) {
>          writeln(value);
>      }
>
>      auto q2 = db.query("SELECT * FROM test, test2 WHERE test2_id =
> test2.id");
>
>      auto r2 = ModelRange!(Join!(Test, Test2))(q2);
>
>      foreach(j; r2) {
>          writeln(j);
>      }
>
>      return 0;
> }
>
> This code prints out every entry in the "test" table, then prints the
> results of a join on the "test" and "test2" tables. The calls to
> updateSchema() set up some static members of Test and Test2; after these
> calls, the library does not perform any operations with the column
> names, which should make retrieving a record noticeably faster than in a
> system like ActiveRecord. The downside is that these functions must be
> called every time the database schema changes in a way that affects
> column order, but that should happen very rarely, if ever, in a typical
> application.
>
> The code is far from complete, but it's an interesting toy and might
> actually be useful for simple applications once some of the issues are
> ironed out.

Looking at the API used in this example it would say that it's not very interesting and not very ActiveRecrod like. I think this looks more interesting and more like ActiveRecrod:

class Person : Model
{
}

void main ()
{
    auto p = new Person;
    p.name = "John Doe";
    p.save();

    p = Person.where!(x => x.name == "John Doe");
}

But when you start to use associative it won't be as nice looking as ActiveRecord due to the not so nice mixin syntax. What we need is AST macros and user defined attributes/annotations. With that, associations could potentially look like this:

class Foo : Model {}

class Person : Model
{
    @hasMany Foo;
}

-- 
/Jacob Carlborg
October 28, 2012
I like, nice work.
On 28 Oct 2012 02:35, "BLM768" <blm768@gmail.com> wrote:

> I've recently been working with Ruby's ActiveRecord as part of my job, and I realized that D was powerful enough to make a similar abstraction layer. I've been playing with the idea for a little while, and I've put up some code at https://github.com/blm768/adbi**. It isn't nearly as comprehensive as ActiveRecord, but it captures the basic idea of representing database structures as objects/structs.
>
> Using it is something like this:
>
> module main;
>
> import std.stdio;
>
> import adbi.model;
> import adbi.sqlite3.database;
>
> struct Test {
>         mixin Model!"test";
>
>         const(char)[] name;
>         double num;
>         mixin reference!("test2", "test2", Test2);
> }
>
> struct Test2 {
>         mixin Model!"test2";
>         int value;
> }
>
> int main(string[] args) {
>         auto db = new Sqlite3Database("test.db");
>         auto q = db.query("SELECT * FROM test;");
>
>         Test.updateSchema(db);
>         Test2.updateSchema(db);
>
>         auto range = ModelRange!Test(q);
>
>         foreach(value; range) {
>                 writeln(value);
>         }
>
>         auto q2 = db.query("SELECT * FROM test, test2 WHERE test2_id =
> test2.id");
>
>         auto r2 = ModelRange!(Join!(Test, Test2))(q2);
>
>         foreach(j; r2) {
>                 writeln(j);
>         }
>
>         return 0;
> }
>
> This code prints out every entry in the "test" table, then prints the results of a join on the "test" and "test2" tables. The calls to updateSchema() set up some static members of Test and Test2; after these calls, the library does not perform any operations with the column names, which should make retrieving a record noticeably faster than in a system like ActiveRecord. The downside is that these functions must be called every time the database schema changes in a way that affects column order, but that should happen very rarely, if ever, in a typical application.
>
> The code is far from complete, but it's an interesting toy and might actually be useful for simple applications once some of the issues are ironed out.
>
>


October 28, 2012
On Sunday, 28 October 2012 at 00:31:49 UTC, BLM768 wrote:
> I've recently been working with Ruby's ActiveRecord as part of my job, and I realized that D was powerful enough to make a similar abstraction layer. I've been playing with the idea for a little while, and I've put up some code at https://github.com/blm768/adbi. It isn't nearly as comprehensive as ActiveRecord, but it captures the basic idea of representing database structures as objects/structs.
>
> Using it is something like this:
>
> module main;
>
> import std.stdio;
>
> import adbi.model;
> import adbi.sqlite3.database;
>
> struct Test {
> 	mixin Model!"test";
> 	
> 	const(char)[] name;
> 	double num;
> 	mixin reference!("test2", "test2", Test2);
> }
>
> struct Test2 {
> 	mixin Model!"test2";
> 	int value;
> }
>
> int main(string[] args) {
> 	auto db = new Sqlite3Database("test.db");
> 	auto q = db.query("SELECT * FROM test;");
> 	
> 	Test.updateSchema(db);
> 	Test2.updateSchema(db);
> 	
> 	auto range = ModelRange!Test(q);
> 	
> 	foreach(value; range) {
> 		writeln(value);
> 	}
> 	
> 	auto q2 = db.query("SELECT * FROM test, test2 WHERE test2_id = test2.id");
> 	
> 	auto r2 = ModelRange!(Join!(Test, Test2))(q2);
> 	
> 	foreach(j; r2) {
> 		writeln(j);
> 	}
> 	
> 	return 0;
> }
>
> This code prints out every entry in the "test" table, then prints the results of a join on the "test" and "test2" tables. The calls to updateSchema() set up some static members of Test and Test2; after these calls, the library does not perform any operations with the column names, which should make retrieving a record noticeably faster than in a system like ActiveRecord. The downside is that these functions must be called every time the database schema changes in a way that affects column order, but that should happen very rarely, if ever, in a typical application.
>
> The code is far from complete, but it's an interesting toy and might actually be useful for simple applications once some of the issues are ironed out.

I am working on similar project, named SQLd[1]. If you are interested, we can join forces and work togheder :)

IRC Nick: Robik
[1]: http://github.com/robik/SQLd

October 29, 2012
> I am working on similar project, named SQLd[1]. If you are interested, we can join forces and work togheder :)
>
> IRC Nick: Robik
> [1]: http://github.com/robik/SQLd

That might be a good idea. I haven't done much for supporting different databases, so getting more backend support would be quite nice. What might work well is for me to just refactor my code to sit on top of your existing database classes. So far, I've really just been playing around, but if people show enough interest, I'd like to play with the idea a while longer. :)


October 29, 2012
>
> Looking at the API used in this example it would say that it's not very interesting and not very ActiveRecrod like. I think this looks more interesting and more like ActiveRecrod:
>
> class Person : Model
> {
> }
>
> void main ()
> {
>     auto p = new Person;
>     p.name = "John Doe";
>     p.save();
>
>     p = Person.where!(x => x.name == "John Doe");
> }
>
> But when you start to use associative it won't be as nice looking as ActiveRecord due to the not so nice mixin syntax. What we need is AST macros and user defined attributes/annotations. With that, associations could potentially look like this:
>
> class Foo : Model {}
>
> class Person : Model
> {
>     @hasMany Foo;
> }

It's definitely not ActiveRecord, but my goal is just to take some inspiration from it, not to duplicate it. I'm very concerned about efficiency, which is why I'm using structs, and I like hard-coding the fields into the structure so there's some documentation of what the record is supposed to hold and so the compiler can optimize it more heavily. It will probably be a little less pretty, but it'll work, and that's what really matters. At some point, I might implement an interface to generate SQL queries with function calls, but for now, just manually writing the queries really isn't hard, and it provides a significant speed boost for systems like Sqlite that compile queries down to bytecode because it's easier to reuse the query object.

October 29, 2012
> It's definitely not ActiveRecord, but my goal is just to take some
> inspiration from it, not to duplicate it. I'm very concerned about
> efficiency, which is why I'm using structs, and I like hard-coding the
> fields into the structure so there's some documentation of what the
> record is supposed to hold and so the compiler can optimize it more
> heavily. It will probably be a little less pretty, but it'll work, and
> that's what really matters. At some point, I might implement an
> interface to generate SQL queries with function calls, but for now, just
> manually writing the queries really isn't hard, and it provides a
> significant speed boost for systems like Sqlite that compile queries
> down to bytecode because it's easier to reuse the query object.

My point was just that you removed the key features and soul of ActiveRecord. Without these features it's just like any other ORM library.

-- 
/Jacob Carlborg
October 29, 2012
> My point was just that you removed the key features and soul of ActiveRecord. Without these features it's just like any other ORM library.

That's a good point. I haven't had any experience with other ORM libraries, so ActiveRecord was the closest thing that came to mind.

I definitely do want to eventually capture some of ActiveRecord's features, but probably not all of them. I feel like the solution should be implemented in a way that fits well with a statically typed language, so I'll definitely have to drop some of the features. It won't be quite as nice to use, but it will be simpler in dome ways, which is one of my primary goals as a developer. Tools like ActiveRecord are more fun to use, but thinking of all the hash table lookups makes me cringe. :)

If and when the library matures, though, I might think about adding some more ActiveRecord-like features if enough people miss them.

October 29, 2012
On 2012-10-29 15:42, BLM768 wrote:

> That's a good point. I haven't had any experience with other ORM
> libraries, so ActiveRecord was the closest thing that came to mind.
>
> I definitely do want to eventually capture some of ActiveRecord's
> features, but probably not all of them. I feel like the solution should
> be implemented in a way that fits well with a statically typed language,
> so I'll definitely have to drop some of the features. It won't be quite
> as nice to use, but it will be simpler in dome ways, which is one of my
> primary goals as a developer. Tools like ActiveRecord are more fun to
> use, but thinking of all the hash table lookups makes me cringe. :)
>
> If and when the library matures, though, I might think about adding some
> more ActiveRecord-like features if enough people miss them.

You can have a look at DataMapper. That's also for Ruby but it's not specific for SQL, if I recall correctly. Have a look at some ORM library written in Scala, I would guess they can be quite innovative and it's statically typed.

http://squeryl.org/index.html
http://datamapper.org/

-- 
/Jacob Carlborg
October 29, 2012
>
> You can have a look at DataMapper. That's also for Ruby but it's not specific for SQL, if I recall correctly. Have a look at some ORM library written in Scala, I would guess they can be quite innovative and it's statically typed.
>
> http://squeryl.org/index.html
> http://datamapper.org/

Those libraries definitely look interesting. I should probably consider some type of NoSQL database support...

Thanks for the links!


« First   ‹ Prev
1 2 3