[plt-scheme] Resources in the transformer environment

From: Carl Eastlund (cce at ccs.neu.edu)
Date: Thu Oct 26 18:30:22 EDT 2006

Could you live with simply annotating the macro with the expected
columns?  Then the macro could build the class based on the
annotations rather than the database, and verify at runtime that the
expected fields actually match the table.  This would alleviate the
need for a connection at expansion time, avoid any problems with
changes to the table between expansion time and runtime, and allow you
to detect and signal any errors if the programmer expected the wrong
set of columns (rather than catching it later, at a field access).

This is, for instance, how the class macro deals with fields of an
unknown superclass: rather than trying to infer them at expansion
time, it requires an (inherit ...) clause to declare them.  It's not
the same issue, but it has a similar solution.

That's the quick, off-the-top-of-my-head answer.  If you absolutely
must get the columns straight from the database, I'll have to defer to
someone else with more macro black magic up their sleeve.

Carl Eastlund

On 10/26/06, Jon Zeppieri <zeppieri at gmail.com> wrote:
> I've been playing around with class.ss, attempting to implement
> something similar to Ruby's ActiveRecord class, which provides an
> automatic mapping between a class and a relational database table.
> I have a rudimentary form of this working, where each column from the
> DB table is represented by a field in the class.  This is accomplished
> by a macro, dbo-class*, which expands to a class* form.  Since the DB
> columns have to be known at expansion time (and since a goal of this
> project is to create the class automatically from the DB schema), I
> need to connect to the database during macro expansion.  However,
> using instances of the created classes obviously requires a connection
> to the database during normal runtime.
> As far as I can tell, there is no way to do this without creating two
> different connections, since the transformer and runtime environments
> are kept completely separate.  Now, opening two database connections
> isn't such a problem, but I am bothered by the fact that while I can
> sensibly manage the runtime connection (e.g., I can use dynamic-wind
> to create, use, and close the connection reliably), I'm not sure how
> to manage the connection in the transformer environment.
> Below is an example of the class's use.  Some information that might
> be useful in making sense of it:
>   - current-connection is a parameter provided my mysql.ss
>   - dbo.ss provides the dbo-class* macro
>   - the first parameter to dbo-class* is the name of the database
> table to be represented by the class
>  - the find method returns instances of the class, each of which
> represents a row of the DB table
> ==============================
> (require-for-syntax (lib "mysql.ss" "mysql"))
> (begin-for-syntax (current-connection (connect "host.domain.foo" 3306
> "my_username" "my_password" "my_schema")))
> (require (lib "mysql.ss" "mysql"))
> (require (lib "dbo.ss" "dbo"))
> (dynamic-wind
>  (lambda ()
>    (current-connection ()connect "host.domain.foo" 3306 "my_username"
> "my_password" "my_schema"))
>  (lambda ()
>    (define project%
>      (dbo-class* "project" object% ()
>                  (super-new)))
>    (define o (make-object project%))
>    (define ps (send o find #:all))
>    (display ps))
>  (lambda ()
>    (close (current-connection))))
> (begin-for-syntax (close (current-connection)))
> ===========================
> The above code works fine, but I'd like to use the dbo classes in web
> servlets, where I would be a lot more concerned about the lifetime of
> database connections.  That final (begin-for-syntax) in the above
> example doesn't seem to belong anywhere in a servlet module.
> Any ideas?  If it would be at all useful to see the dbo.ss code (or
> anything else), I can send it along.
> -Jon

Posted on the users mailing list.