Database applications and OOness

People,
I’m going to write an application that needs to deal with reasonably
large amounts of data over a reasonably long period of time. So the
question that immediately comes up is, how do I store said data when the
program is not running? As I see it, the options can be divided into two
categories in two different ways: How the data is stored and how it is
interfaced.

The data can be stored in (essentially) one of two ways: in memory, or
on disk. In my case, in-memory systems are probably no good - with the
volumes of data I want to hold, and the periods of time I want to hold
them over (some if it is accounting data, which is likely to be kept for
years) I don’t want it all in memory. Therefore, I will choose a
disk-based system such as an RDBMS. My RDBMS of choice is PostgreSQL, so
I’ll run with that for now.

The other way my options can be divided is (and I’m simplifying things a
bit again) between those libraries that present the data as objects and
those that present it as database rows. Let me clarify:

#<Person:0x40132728 @name=“name”, @number=“phone number”, @address=“address”>
vs
[“name”,“address”,“phone number”]

I like the first one better, because you get encapsulation and behaviour
with your data, but most of the database interface libraries that I’ve
seen of that type tend to take most of the querying out of the hands of
the user. They allow you to retrieve objects that have properties that
match a given example, but very seldom any more complex than that - the
equivalent of limiting yourself to “SELECT * FROM table WHERE
table.column = ?” type queries only. Part of the reason I like RDBMSs is
that I can do complex queries which don’t necessarily return a simple
list of objects, like:

“SELECT s.name AS name, COUNT(DISTINCT t.customer_id) AS customers
FROM salesperson s JOIN transactions t ON s.id = t.salesperson
ORDER BY customers DESC;”

This really returns a salesperson-to-integer mapping of how many
customers a salesperson has dealt with. You can’t represent this as a
plain list of objects, unless you created a special type of object just
for it (which is silly) and most OO-type database libraries won’t let
you make that sort of query at all without going behind their backs,
which is really ugly.

The alternative is to use something like vanilla DBI, in which you write
your own SQL and everything comes back as arrays of values. This allows
you to do whatever queries you want but you lose the niceness of the OO
approach. I don’t want to do vanilla DBI, it’s too messy.

What I want is some sort of happy medium, and I’m starting to think I’ll
have to write it as none of the database interface libraries I’ve
evaluated do it the way I want - which is the motivation for writing a
lot of software, is it not? I believe that’s how Ruby itself got its
start, so I’m in noble company…

But also on a deadline. Any suggestions?

Tim Bates

···


tim@bates.id.au

“Tim Bates” tim@bates.id.au schrieb im Newsbeitrag
news:20040107100517.GA7464@bates.id.au
[snip persistent storage selection]

The other way my options can be divided is (and I’m simplifying things a
bit again) between those libraries that present the data as objects and
those that present it as database rows. Let me clarify:

#<Person:0x40132728 @name=“name”, @number=“phone number”,
@address=“address”>
vs
[“name”,“address”,“phone number”]

I like the first one better, because you get encapsulation and behaviour
with your data, but most of the database interface libraries that I’ve
seen of that type tend to take most of the querying out of the hands of
the user. They allow you to retrieve objects that have properties that
match a given example, but very seldom any more complex than that - the
equivalent of limiting yourself to “SELECT * FROM table WHERE
table.column = ?” type queries only. Part of the reason I like RDBMSs is
that I can do complex queries which don’t necessarily return a simple
list of objects, like:

“SELECT s.name AS name, COUNT(DISTINCT t.customer_id) AS customers
FROM salesperson s JOIN transactions t ON s.id = t.salesperson
ORDER BY customers DESC;”

This really returns a salesperson-to-integer mapping of how many
customers a salesperson has dealt with. You can’t represent this as a
plain list of objects, unless you created a special type of object just
for it (which is silly) and most OO-type database libraries won’t let
you make that sort of query at all without going behind their backs,
which is really ugly.

There are however object relational mapping tools that come with their own
query language. These query languages are most likely not as powerful and
flexible as SQL but they ten to be more flexible than QBE (query by
example), which you mention.

The alternative is to use something like vanilla DBI, in which you write
your own SQL and everything comes back as arrays of values. This allows
you to do whatever queries you want but you lose the niceness of the OO
approach. I don’t want to do vanilla DBI, it’s too messy.

What I want is some sort of happy medium, and I’m starting to think I’ll
have to write it as none of the database interface libraries I’ve
evaluated do it the way I want - which is the motivation for writing a
lot of software, is it not? I believe that’s how Ruby itself got its
start, so I’m in noble company…

But also on a deadline. Any suggestions?

You didn’t say whether your project has Ruby as a requirement written on
it or whether tools you use must be free. In case not, you could consider
object relational binding tools like

etc.

Or you consider an OO database and write only the query language parser
yourself. You could then use

etc.

You’ll probably notice that I’m coming from a Java background. :slight_smile: I’m
sure there are similar tools for other languages.

Kind regards

robert

have you ever looked at the Criteria library ?

···

il Wed, 7 Jan 2004 19:06:32 +0900, Tim Bates tim@bates.id.au ha scritto::

What would you like it to return? Should it construct a class on the fly,
with fields ‘name’ and ‘customers’? And should it use its own query
language to do so, or parse the sql query?

martin

···

Tim Bates tim@bates.id.au wrote:

I like the first one better, because you get encapsulation and behaviour
with your data, but most of the database interface libraries that I’ve
seen of that type tend to take most of the querying out of the hands of
the user. They allow you to retrieve objects that have properties that
match a given example, but very seldom any more complex than that - the
equivalent of limiting yourself to “SELECT * FROM table WHERE
table.column = ?” type queries only. Part of the reason I like RDBMSs is
that I can do complex queries which don’t necessarily return a simple
list of objects, like:

“SELECT s.name AS name, COUNT(DISTINCT t.customer_id) AS customers
FROM salesperson s JOIN transactions t ON s.id = t.salesperson
ORDER BY customers DESC;”

This really returns a salesperson-to-integer mapping of how many
customers a salesperson has dealt with. You can’t represent this as a
plain list of objects, unless you created a special type of object just
for it (which is silly) and most OO-type database libraries won’t let
you make that sort of query at all without going behind their backs,
which is really ugly.

on a sidenote: someone agrees with me that we should have a common
shared and abstract ruby/DBMS api like python/java/whatever instead of
a wrapper package (DBI)?

(I hinted this long time ago and had no answer at all. Falling in
Warnock’s Dilemma, so I post again…)

···

il Wed, 7 Jan 2004 19:06:32 +0900, Tim Bates tim@bates.id.au ha scritto::

I’ve build an implementation of Martin Fowler’s ActiveRecord pattern
[1] with support for single-table inheritance [2]. It’s designed with
the notion of “Convention Over Configuration”, which basically means
that you follow a set of naming conventions to get a bunch of behavior
for free. Best to show with an example:

CREATE TABLE posts (
id int(11) unsigned NOT NULL auto_increment,
title varchar(255),
body text,
posted_on datetime,
PRIMARY KEY (id)
)

CREATE TABLE comments (
id int(11) unsigned NOT NULL auto_increment,
post_id int(11) unsigned NOT NULL,
body text,
PRIMARY KEY (id)
)

class Post < ActiveRecord
def comments
Comments.find_all "post_id = #{id}"
end

 protected
    def before_create
	    self.posted_on = Time.now
    end

    def before_destroy
	    Comments.destroy_all "post_id = #{id}"
    end

end

class Comment < ActiveRecord
end

The code above shows a couple of things. First, there’s no build-in
mapping for foreign key object relations (I had to make Post#comments
myself). Second, much of the behavior of the ActiveRecord can be
customized through callback hooks, like before_create (which tellingly
is called just before a row is created in the database) and
before_destroy. Third, “Post” automatically match up with the "posts"
table – this behavior can be overwritten for things like
Person/people.

Anyway, some usage examples:

post = Post.new
post.title = "My new post"
post.body = "Active Records are easy"
post.save # since the post has no id, a INSERT-sql statement is executed

print post.id # prints the auto_id assigned by MySQL
print post.posted_on # prints the time of creation

post.title = "I’ve changed"
post.save # an id exists, so an UPDATE-sql statement is executed

post.attribute_that_doesnt_exist # Throws a NameError exception

Objects can also be initialized with a hash, which is especially

convenient

in web-apps that can just pass on the POST-parameters

first_comment = Comment.new({ “body” => “hello world”, “post_id” =>
post.id })
first_comment.save

second_comment = Comment.new({ “body” => “hello world”, “post_id” =>
post.id })
second_comment.save

print post.comments.length # prints 2
post.comments[0].body == first_comment.body # true

…and then there’s a wide range of class/table-level methods, like:

Comment.update_all "body = ‘all are changed’"
Comment.find(1).body == Comment.find(2).body # true (find uses SELECT,
btw)

print Comment.count # prints 2

post_with_comment = Post.find_by_sql(
"SELECT post.*, comment.body as comment_body " +
"FROM posts LEFT JOIN comments ON posts.id = comments.post_id " +
“ORDER BY comments.id DESC”
)

post_with_comment.comment_by # will print the body of the last comment

I think that’s the basics. On top of that, there’s support for simple
inheritance, like Company < ActiveRecord, Firm < Company, Client <
Company, which does correct type instantiations. There’s also
validation support with error reporting – think automatic form
validation from Strut’s ActionForm[3] classes but on the model instead
of controller.

Caveats:

  • Id generation is tied to MySQL’s autoID functionality, which
    currently binds it to MySQL – but through use of DBI.
  • No build-in transaction support

I’ve used a similar design in a couple of PHP web-apps and it has
worked very well. I’m currently finishing up a Ruby web-app called
Basecamp for 37signals[4] that uses this all the way through.

I plan on releasing this as soon as I’ve wrapped up Basecamp, but if
anyone is interested now (which means little documentation besides
inline comments and unit tests), I could easily package up a version.

[1] http://www.martinfowler.com/eaaCatalog/activeRecord.html
[2] http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
[3]
http://jakarta.apache.org/struts/userGuide/
building_controller.html#action_form_classes
[4] Sneak peak:
http://www.37signals.com/svn/archives/000505.php?29#comments

···


David Heinemeier Hansson.
http://www.loudthinking.com/ – Broadcasting Brain

Yes, in fact I wrote a DBI module for it. It’s great; if I were going to
write an OO DBMS interface I’d use it, or at least some of the code and
ideas from it. But it doesn’t solve the whole problem - only the
querying bit, and even then it can’t quite manage queries as complex as
the example I gave with in the OP. It still only returns (at best)
arrays of data, and does nothing about turning them into first-class
objects.

I don’t know if there is a solution to my problem, whether what I want
can be done cleanly. To tell the truth I’m not 100% certain of what I
want, but I visualise something like a cross between Vapor and Criteria.
If no such thing exists, and I can’t find an alternate solution I guess
I’m back to writing it myself, or settling for some other method. It
just seems like there should be a good way to marry the power of SQL
(and the optimised searching/indexing and concurrency routines a good
RDBMS provides) with the pristine Object-Orientedness of Ruby.

Tim Bates

···

On Wed, Jan 07, 2004 at 08:16:40PM +0900, gabriele renzi wrote:

have you ever looked at the Criteria library ?


tim@bates.id.au

Date: Wed, 07 Jan 2004 20:31:44 GMT
From: gabriele renzi surrender_it@remove.yahoo.it
Newsgroups: comp.lang.ruby
Subject: Re: Database applications and OOness

il Wed, 7 Jan 2004 19:06:32 +0900, Tim Bates tim@bates.id.au ha
scritto::

on a sidenote: someone agrees with me that we should have a common
shared and abstract ruby/DBMS api like python/java/whatever instead of
a wrapper package (DBI)?

yaml?

(I hinted this long time ago and had no answer at all. Falling in
Warnock’s Dilemma, so I post again…)

-a

···

On Wed, 7 Jan 2004, gabriele renzi wrote:

ATTN: please update your address books with address below!

===============================================================================

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
STP :: http://www.ngdc.noaa.gov/stp/
NGDC :: http://www.ngdc.noaa.gov/
NESDIS :: http://www.nesdis.noaa.gov/
NOAA :: http://www.noaa.gov/
US DOC :: http://www.commerce.gov/

The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”

/bin/sh -c ‘for l in ruby perl;do $l -e “print “\x3a\x2d\x29\x0a””;done’
===============================================================================

I don’t know. Probably an array of arrays or an array of hashes - which,
I know, is exactly what DBI would return for such a query. The point I’m
trying to make is I’d like the system to be able to handle this sort of
query as_well_as the “SELECT * FROM table WHERE property = ?” type
return-a-list-of-objects query. I don’t know of any system that can do
that, or even if it could be done neatly. Possibly such a system would
have to accept two sorts of query and handle both separately, but that
introduces its own ugliness.

Tim Bates

···

On Wed, Jan 07, 2004 at 10:16:42PM +0900, Martin DeMello wrote:

This really returns a salesperson-to-integer mapping of how many
customers a salesperson has dealt with. You can’t represent this as a
plain list of objects, unless you created a special type of object just
for it (which is silly) and most OO-type database libraries won’t let
you make that sort of query at all without going behind their backs,
which is really ugly.

What would you like it to return? Should it construct a class on the fly,
with fields ‘name’ and ‘customers’? And should it use its own query
language to do so, or parse the sql query?


tim@bates.id.au

“gabriele renzi” surrender_it@remove.yahoo.it schrieb im Newsbeitrag
news:vsqovvcssebk77gk420d56gp5676vq5egg@4ax.com

il Wed, 7 Jan 2004 19:06:32 +0900, Tim Bates tim@bates.id.au ha
scritto::

on a sidenote: someone agrees with me that we should have a common
shared and abstract ruby/DBMS api like python/java/whatever instead of
a wrapper package (DBI)?

What exactly is the difference between the “shared and abstract ruby/DBMS
api” and DBI? IMHO DBI is exactly an abstract DBMC API, albeit only for
relational databases. Do you want to unify the different SQL dialects?
Or do you want only certain things unified, e.g. date and time formats
(like JDBC tries with its escape sequences)?

Kind regards

robert

Oh, yes, please? Pretty please? That looks a LOT like what I was
conceptualizing writing for my needs. If it indeed is, I’ll probably even
help you document it, as I expect to use it quite a bit.

Kirk Haines

···

On Sat, 10 Jan 2004, David Heinemeier Hansson wrote:

I plan on releasing this as soon as I’ve wrapped up Basecamp, but if
anyone is interested now (which means little documentation besides
inline comments and unit tests), I could easily package up a version.

just two things:

the auto_id functionality may be achieved with SERIAL type in standard
sql, I suppose, or at least as a stored procedure. Am I wrong?.
Maybe you could write various driver for various db :slight_smile:

did you see SPL on RAA ? it adds automagic persistence to objects via
a mixin, and it seem to me that it’s really similar to your design

···

il Sat, 10 Jan 2004 08:28:50 +0900, David Heinemeier Hansson david@loudthinking.com ha scritto::

I’ve build an implementation of Martin Fowler’s ActiveRecord pattern
[1] with support for single-table inheritance [2]. It’s designed with
the notion of “Convention Over Configuration”, which basically means
that you follow a set of naming conventions to get a bunch of behavior
for free. Best to show with an example:

Whoa, me too – I came up with it while coding an MVC-structured web app
this week. My code works like so:

class Foo < SQLObject
key_field :id
field :name
field :amount
field :date
field :quantity
calculated_field: total
end

and there’s a get, put & find method. field defines accessors for the
values, and sets up an array of fields in the class instance.

The table that this comes from is defined to be class.name.lower+‘s’ –
overridable by overriding the class’ table method.

It works well for me – it hides enough of the SQL to be “OO enough” for
me, and lets me use inheritance to show relation.

Ari

···

On Fri, 2004-01-09 at 16:28, David Heinemeier Hansson wrote:

I’ve build an implementation of Martin Fowler’s ActiveRecord pattern
[1] with support for single-table inheritance [2]. It’s designed with
the notion of “Convention Over Configuration”, which basically means
that you follow a set of naming conventions to get a bunch of behavior
for free. Best to show with an example:

Tim Bates wrote:

I don’t know if there is a solution to my problem, whether what I want
can be done cleanly. To tell the truth I’m not 100% certain of what I
want, but I visualise something like a cross between Vapor and Criteria.
If no such thing exists, and I can’t find an alternate solution I guess
I’m back to writing it myself, or settling for some other method. It
just seems like there should be a good way to marry the power of SQL
(and the optimised searching/indexing and concurrency routines a good
RDBMS provides) with the pristine Object-Orientedness of Ruby.

Tim,

I think I have an inkling of what you want.

My take on it is this: If you’re going to do some coding to
meke this happen, it’s easier to take an existing DB (with
fancy query capabilities and presumably efficient, reliable
data storage) and graft an OO layer onto it. (Easier, that is,
than vice versa.)

For example, you might wrap a query in a method that returned
a Struct whose member names were the database field names.

I’m sure there are complications there, but they shouldn’t be
of the same order of magnitude as a full database with a full
SQL parser.

Hal

As somebody who’s done some of this work (I wrote Lafcadio), I
strongly recommend that you consider extending somebody else’s work
before doing it yourself. When you enter this problem domain there are
a lot of little wrinkles you run into, and the best solution isn’t
always necessarily obvious from the start. I know that personally it
took me a while to figure out the best way to transparently handle
relations between different rows, for example.

Now, I’ve only used Lafcadio, but I have the feeling that right now
the Ruby OR-mapping tools out there are either 1) strong on mapping
rows to objects, or 2) strong on ad-hoc querying, but not both. I’d
put Lafcadio and Vapor in category 1, and Criteria in category 2.
Either requirement is pretty big; both are twice as big. In the
long-term, my feeling is that any library that sticks around in this
space will have to satisfy both needs.

In the short-term, I can tell you what you’d have to do for Lafcadio
to get it do what you want. First, Lafcadio was written first for
MySQL, and although it should support Postgres with minimal changes, I
have yet to implement or test such a change. (At RubyConf Ryan Davis
told me he was very interested in helping add Postgres functionality,
and I moved the library to DBI to enable that, but I suspect that,
like everybody else, Ryan’s pretty busy.) Second, Lafcadio’s support
for querying works, but I’ll be the first to admit that it’s verbose
and ugly as hell. Query inference is very high on my list, but then,
I’m busy, too. So Vapor or Criteria might be a better choice for you,
depending.

At the least you might want to poke around in the various libraries
and steal the best ideas for yourself.

Francis

Tim Bates tim@bates.id.au wrote in message news:20040107121053.GB7464@bates.id.au

···

I don’t know if there is a solution to my problem, whether what I want
can be done cleanly. To tell the truth I’m not 100% certain of what I
want, but I visualise something like a cross between Vapor and Criteria.
If no such thing exists, and I can’t find an alternate solution I guess
I’m back to writing it myself, or settling for some other method. It
just seems like there should be a good way to marry the power of SQL
(and the optimised searching/indexing and concurrency routines a good
RDBMS provides) with the pristine Object-Orientedness of Ruby.

I liek the look of ROE
(http://www.cincomsmalltalk.com/userblogs/avi/blogView?showComments=true&ent
ry=3246121322) on Squeak. Don’t know if its what you’re looking for of
course, since even you don’t know what you’re looking for :slight_smile:

David
http://homepages.ihug.com.au/~naseby/

···

-----Original Message-----
From: Tim Bates [mailto:tim@bates.id.au]
I don’t know if there is a solution to my problem, whether what I want
can be done cleanly. To tell the truth I’m not 100% certain of what I
want, but I visualise something like a cross between Vapor and Criteria.
If no such thing exists, and I can’t find an alternate solution I guess
I’m back to writing it myself, or settling for some other method. It
just seems like there should be a good way to marry the power of SQL
(and the optimised searching/indexing and concurrency routines a good
RDBMS provides) with the pristine Object-Orientedness of Ruby.

have you ever looked at the Criteria library ?

Yes, in fact I wrote a DBI module for it. It’s great; if I were
going to write an OO DBMS interface I’d use it, or at least some of
the code and ideas from it. But it doesn’t solve the whole problem -
only the querying bit, and even then it can’t quite manage queries
as complex as the example I gave with in the OP. It still only
returns (at best) arrays of data, and does nothing about turning
them into first-class objects.

I just noticed a thread discussing Criteria in passing. :wink: Looking
at the original post, I don’t think the query is that hard to
generate:

require 'criteria/sql'
include Criteria

s = SQLTable.new("salesperson")
t = SQLTable.new("transactions")

q          = s.*.left_outer_join(s.id == t.salesperson, s)
q.order_by = :customers
q.order    = :desc

q.select(s.name, "COUNT(DISTINCT #{t.customer_id})")

# => SELECT salesperson.name, COUNT(DISTINCT
# transactions.customer_id) FROM salesperson LEFT OUTER JOIN
# salesperson ON (salesperson.id = transactions.salesperson) ORDER
# BY customers desc

Granted, it doesn’t generater column headings, and you currently have
to use a literal string hack to get the SQL function. This should
hopefully be fixed before long.

I don’t know if there is a solution to my problem, whether what I
want can be done cleanly. To tell the truth I’m not 100% certain of
what I want, but I visualise something like a cross between Vapor
and Criteria. If no such thing exists, and I can’t find an
alternate solution I guess I’m back to writing it myself, or
settling for some other method. It just seems like there should be a
good way to marry the power of SQL (and the optimised
searching/indexing and concurrency routines a good RDBMS provides)
with the pristine Object-Orientedness of Ruby.

I’m not sure what Vapor is, but—and I know you’ve mentioned it so
you’re aware of it—you may take a look at Mephle, since I think it
does what you want:

class Foo
    # When you call these, they automatically update the proper
    # row in the table.
    attr_accessor_indexed String, :bar, :baz
    attr_accessor_indexed Integer, :quux

    :
end

Things are a little less automatic than I’d like at the moment.
Writing this has given me an idea of how to fix it, though, with an
’auto_index’ function, so you’d have something like:

class Foo
    IDX = DBITable.new(...)

    def initialize(...)
       :

       auto_index(IDX)
    end
end

This could look at the column titles (or a list of what
attr_accessor_indexed declares) and insert a row with the proper
data. (Right now you have to do a manual insertion, which isn’t too
tough either.)

There are a few reason I still serialize and index instead of using
tables exclusively:

1.  Some objects are large, and you don't want to index everything
2.  Looking up attributes every time is slow
3.  Not all ruby things can be represented as SQL things

(4. SQL isn’t guaranteed to be the storage mechanism, either)

I’m open to suggestion though. It’s conceivable that there’s a
"CachedTableObject" class or something where you give up the ability
to write into a live system, and you avoid point 2, for objects that
work. Of course, you still need to be able to load that object later,
and using a unique OID for every object in the system is nice, so
you’d still have something in the object table. I’m not sure what you
gain by this one other than a few extra bytes, but it could be done.

Making Mephle indexing less manual is probably a lot more useful—you
get what you want without any work (and there’s not really much as it
is).

···

On Wed, 7 Jan 2004 21:12:06 +0900 Tim Bates tim@bates.id.au wrote:

On Wed, Jan 07, 2004 at 08:16:40PM +0900, gabriele renzi wrote:


Ryan Pavlik rpav@mephle.com

“Spinal hazards are hazardous…” - 8BT

I would like to see a Ruby library along the lines of Alphora’s
Dataphor product:

http://www.alphora.com/tiern.asp?ID=DATAPHOR

Regards,

Mark Wilson

I’ve been watching this thread with a great deal of interest. I’m
relatively new to Ruby, and have no experience with the various db
approaches (well, except for playing with pstore for a few hours). But I
did use NeXT/Apple’s EOF product for a few years. I thought I’d just post a
few remarks in case any of you gurus are trying to strategize something.

That framework used a model object (an EOModel), with which the application
communicates directly. The model itself used vendor-free semantics to
describe standard database ops, and then the app loaded an appropriate
adaptor (EOOracleAdaptor, EOSybaseAdaptor) at runtime to translate the join
and fetch requirements into a particular vendor’s SQL flavor.

In the model, Entities (think tables) could be specified to return either
instances of specific Java classes (and earlier, Objective-C classes), or
dictionaries. The dictionaries were basically hashes, but they shared the
ability with the custom Java classes to respond to key-value coding for
fetching and traversal, so that a “keypath” like
"someVendor.principalContact.phoneNumber" behaved the same, whatever the
type of object loaded. (Note: Apple relied heavily enough on key-value
coding and keypath notation to obtain at least one patent on it. I suppose
someone looking to implement from the ground up would blow past that
pioneering effort and look straight at OGNL, or somesuch.)

The model had some support for groupings, and custom read-write statements
could be recorded in the model on a per-attribute basis, to override the
model’s default SQL generation. For instance, you could model two Entities
on an invoice table, say “Invoice”, which did the standard CRUD stuff, and
"InvoiceSummary", which had a couple of standard attributes and a custom
reader defined as “sum %amount_due%” (sorry, can’t remember the specific
syntax, but you get the idea).

And there are/were some other nifty ideas. For instance, a “fault” system
(much easier for the product engineers to implement in the earlier versions,
since Obj-C instances can be coerced into swizzling their own class
pointers at runtime…the Java version, from what I understand, took the
midnight sacrifice of multiple chickens to come together). Anyway, the idea
was that objects fetched from the db would know just enough about themselves
to be able to identify (actually, lie about) their Entity types and locate
the rest of their data in db. Then, they’d stay dormant until touched for
the first time, at which point they’d swap in their correct class
information and fetch their individual underlying rows. (That, too, could
obviously be a performance problem, but the system provided "batch faulting"
and other ways to tune for that.)

As my dear (but long-winded) great uncle used to say, “I said all of that to
say this:” Anyone thinking of doing this kind of stuff from the ground up
could maybe profit from a few weeks’ study of the EOF architecture. No
need to buy the product; I think there are ample whitepapers up at the Apple
site to give an overview of the system. And, given Ruby’s runtime dynamics
(compared even to Obj-C, to say nothing of Java), and the caliber of folks
who hang out here, I have no doubt someone could put together a Clean, Lean
Persistence Machine :wink:

-dan

“Tim Bates” tim@bates.id.au wrote in message
news:20040108060053.GG742@bates.id.au

···

The point I’m
trying to make is I’d like the system to be able to handle this sort of
query as_well_as the “SELECT * FROM table WHERE property = ?” type
return-a-list-of-objects query. I don’t know of any system that can do
that, or even if it could be done neatly. Possibly such a system would
have to accept two sorts of query and handle both separately, but that
introduces its own ugliness.

actually, I meant having at least a JDBC like interface, or, what in
python is the DB-api (I suppose).
I mean, if you have to connect to various db you may find:

first find in google for each dbms

PGconn.connect “localhost”, 5432, “”, “”, "test1"
ORAconn.logon “foo”, “bar”, "db"
Mysql.new host, user, passwd
Interbase.connect database,username,password,charset

Now, I know different dbms have different features, but ate least some
convention on a basic set of available methods would be good.
If we, as a community, could agree on a general dbms interface (dbi
fits well to me :slight_smile: hat would be better than a separate wrapper
package.

ATM, Joe De Veloper has to choose beetween dbi-api, DBMS-foo api,
DBMS-bar api. Then he have to get DBMS-(foo|bar) api, dbi wrapper,
and finally start coding.

With a common api Joe just download a binding, find an already common
and documented interface, and start coding.
Then if he want to switch to DBMS-bar he could have (potentially)
working code without the need for changes.

Obviously just in a ideal world :slight_smile:

···

il Thu, 8 Jan 2004 09:50:14 +0100, “Robert Klemme” bob.news@gmx.net ha scritto::

What exactly is the difference between the “shared and abstract ruby/DBMS
api” and DBI? IMHO DBI is exactly an abstract DBMC API, albeit only for
relational databases. Do you want to unify the different SQL dialects?
Or do you want only certain things unified, e.g. date and time formats
(like JDBC tries with its escape sequences)?