Discussion:
[Larceny-users] sqlite3 FFI
Peter Keller
2008-05-21 21:49:39 UTC
Permalink
Hello,

I'm new to larceny and have chosen to use it for a project because it
supports R6RS. How can I figure out what SRFIs are supported in R6RS mode
(any?) and specifically is there an sqlite3 R6RS library? If an FFI is
available and reasonably documented, I'd be willing to produce a sqlite3
wrapping library for larceny.

Thank you.

-pete
William D Clinger
2008-05-21 22:14:29 UTC
Permalink
Post by Peter Keller
I'm new to larceny and have chosen to use it for a project because it
supports R6RS. How can I figure out what SRFIs are supported in R6RS mode
(any?)
That's easy: No SRFIs are supported in R6RS mode.
SRFI 97 proposes a way to organize SRFIs as libraries
that would be compatible with ERR5RS and R6RS, but
there is as yet no agreement on whether the name of
a library version of SRFI 6 (for example) should be
(srfi 6), (srfi vi), (srfi n6), or something else
altogether. See http://srfi.schemers.org/srfi-97/

While we're waiting for SRFI 97 to be approved, you
can load many Larceny-supported SRFIs into Larceny's
ERR5RS mode via this trick:

% larceny -err5rs -- -e "(require 'srfi-6)"
Larceny v0.961 "Fluoridation" (Dec 31 2007 17:21:19, precise:Linux:unified)
larceny.heap, built on Mon Dec 31 17:21:43 EST 2007
ERR5RS mode (no libraries have been imported)
Post by Peter Keller
(import (rnrs)
(primitives open-input-string
open-output-string
get-output-string))

That's Larceny-specific, of course, and works only
in ERR5RS mode.
Post by Peter Keller
and specifically is there an sqlite3 R6RS library?
Not that I've heard of.
Post by Peter Keller
If an FFI is
available and reasonably documented, I'd be willing to produce a sqlite3
wrapping library for larceny.
That'd be great. Larceny does indeed have an FFI,
which is somewhat documented but not well documented.
See http://larceny.ccs.neu.edu/doc/ and specifically
http://larceny.ccs.neu.edu/doc/user-manual.chunked/ar01s10.html#id2559833

Will
Peter Keller
2008-05-22 05:25:22 UTC
Permalink
Post by William D Clinger
Post by Peter Keller
If an FFI is
available and reasonably documented, I'd be willing to produce a sqlite3
wrapping library for larceny.
That'd be great. Larceny does indeed have an FFI,
which is somewhat documented but not well documented.
See http://larceny.ccs.neu.edu/doc/ and specifically
http://larceny.ccs.neu.edu/doc/user-manual.chunked/ar01s10.html#id2559833
Thanks for the info!

What is the accepted manner in which to access fields in a C structure?
Do I treat the structure pointer returned by the foreign call into C as
a byte vector and (after figuring out the padding and whatnot) use
(%get-unsigned bv i) and friends or maybe the %peek equivalents?

Thank you.

-pete
Felix Klock
2008-05-22 05:57:45 UTC
Permalink
Post by Peter Keller
Post by William D Clinger
Post by Peter Keller
If an FFI is
available and reasonably documented, I'd be willing to produce a sqlite3
wrapping library for larceny.
That'd be great. Larceny does indeed have an FFI,
which is somewhat documented but not well documented.
See http://larceny.ccs.neu.edu/doc/ and specifically
http://larceny.ccs.neu.edu/doc/user-manual.chunked/ar01s10.html#id2559833
Thanks for the info!
What is the accepted manner in which to access fields in a C
structure?
Do I treat the structure pointer returned by the foreign call into C as
a byte vector and (after figuring out the padding and whatnot) use
(%get-unsigned bv i) and friends or maybe the %peek equivalents?
1.) A C structure pointer is generally not something Larceny would
consider a byte vector. Or maybe you meant "byte vector" as something
other than data type provided by (rnrs bytevectors (6))...

2.) I believe peek-bytes and poke-bytes and their ilk could do
whatever you could want, but its pretty painful, and may introduce
evil bugs if misused.

3.) For something a little less painful, I recommend that you look at:

lib/Standard/foreign-ctools.sch

Example uses of foreign-ctools appear in

lib/Standard/file-system.sch
lib/Experimental/unix.sch
lib/Experimental/winsock.sch

Other members of the larceny-users list might have better examples of
code using foreign-ctools.

The main reason to use foreign-ctools is that it allows you to be
oblivious to the padding/offset issues of your host environment; if
you have a C compiler available on the host, then foreign-ctools lets
you delegate such work to that compiler. (You do still need to go
through the process of extracting the relevant structure information
from the relevant header files; sorry about that.)

4.) I apologize that lib/Standard/foreign-ctools.sch is not documented
apart from sparse comments in its source code. Despite the lack of
documentation, I am pretty sure that it or something similar will
stick around in Larceny for the foreseeable future, so I believe time
spent learning about foreign-ctools is not going to go to waste if you
are planning to do things with the FFI.

-Felix Klock, who co-developed foreign-ctools with Jesse Tov.
Felix Klock
2008-05-22 06:12:42 UTC
Permalink
Post by Felix Klock
(You do still need to go
through the process of extracting the relevant structure information
from the relevant header files; sorry about that.)
Actually I should not have said "sorry" above, but instead crowed
happily about this as a *feature* of foreign-ctools.

The key word here is "relevant": you can *ignore* irrelevant fields
(such as extensions to the struct definition that are specific to a
particular host platform), and you do not have to transcribe any part
of the header file that is not related to the struct fields that you
happen to care about accessing.

That is, the beauty of foreign-ctools is that you don't need to pull
all of the structure information out. The library does not need to
know about all of the fields of your structure (unlike the C compiler,
which does need that information to determine field offsets and
typcially grabs it from an included header file).

Instead, you just need to know the struct type's name and the names of
the fields you want to access in that struct.

-Felix
Peter Keller
2008-05-25 02:49:32 UTC
Permalink
Post by William D Clinger
That'd be great. Larceny does indeed have an FFI,
which is somewhat documented but not well documented.
See http://larceny.ccs.neu.edu/doc/ and specifically
http://larceny.ccs.neu.edu/doc/user-manual.chunked/ar01s10.html#id2559833
So, after some hacking and getting a basic sqlite3 ffi done for r5rs in
larceny, I've come to realize that functions like (foreign-procedure
...) and friends don't seem to exist at all when running larceny in
-r6rs mode.

Is it even possible to build C interfaces in r6rs libraries in larceny? At
this point, I'm stuck.

Thank you.

-pete
Ray Racine
2008-05-25 13:39:28 UTC
Permalink
It can be done. I think the issue had to do with getting the macros to
work in R6RS libraries. I did redo the define-c-info macro into a R6RS
library as a syntax-case macro.

Since that time I think(?) Larceny has added additional capability
regarding its native explicit-renaming(?) macros inside R6RS libraries.
So other approaches might work as well.

My version of Larceny's FFI inside R6RS Libraries are here.

http://github.com/GreyLensman/rl3/tree/75c05ae3c3e838dace63c18d4c5a95590ed304bb/rl3/ffi

Examples of use are here:

Sockets:
http://github.com/GreyLensman/rl3/tree/75c05ae3c3e838dace63c18d4c5a95590ed304bb/rl3/io/net/sockets.sls

EPoll:
http://github.com/GreyLensman/rl3/tree/75c05ae3c3e838dace63c18d4c5a95590ed304bb/rl3/io/epoll.sls

The last caveat is the code is Linux specific. If you are on Windows
for examples you would have to add back a few cond-expands from
Larceny's native version into my ported version.

I'm open to any and all options regarding the RL3 code.
Post by Peter Keller
Post by William D Clinger
That'd be great. Larceny does indeed have an FFI,
which is somewhat documented but not well documented.
See http://larceny.ccs.neu.edu/doc/ and specifically
http://larceny.ccs.neu.edu/doc/user-manual.chunked/ar01s10.html#id2559833
So, after some hacking and getting a basic sqlite3 ffi done for r5rs in
larceny, I've come to realize that functions like (foreign-procedure
...) and friends don't seem to exist at all when running larceny in
-r6rs mode.
Is it even possible to build C interfaces in r6rs libraries in larceny? At
this point, I'm stuck.
Thank you.
-pete
_______________________________________________
Larceny-users mailing list
https://lists.ccs.neu.edu/bin/listinfo/larceny-users
Peter Keller
2008-05-25 17:43:58 UTC
Permalink
Post by Ray Racine
My version of Larceny's FFI inside R6RS Libraries are here.
http://github.com/GreyLensman/rl3/tree/75c05ae3c3e838dace63c18d4c5a95590ed304bb/rl3/ffi
I was able to download ffi-std.sls and foreign-ctools.sls, but before I
could get more libraries to resolve things foreign-ctools.sls needed,
http://github.com appeared to have went down. Maybe you should look
into that.

I'll try again later to get the rest.
Post by Ray Racine
The last caveat is the code is Linux specific. If you are on Windows
for examples you would have to add back a few cond-expands from
Larceny's native version into my ported version.
For now, this is just fine by me.

As for my sqlite3 interface, I'll probably do an api very similar to
the sqlite3 egg for the Chicken scheme compiler.

I do have a question though, since this is r6rs, should I do a naming convention
like:

sqlite3-open
OR
sqlite3/open
OR
sqlite3:open

or, just use:

open

and let the person bringing in the library set a prefix for whatever they
want for the functions and symbols the library exports?

The "open" case is interesting, but it gets annoying if those symbols collide
with something already in the environment.
Post by Ray Racine
I'm open to any and all options regarding the RL3 code.
Thank you for writing it, so far it looks like it'll meet my needs (once I get
the rest of it).

-pete
David Rush
2008-05-26 05:42:44 UTC
Permalink
Post by Peter Keller
I do have a question though, since this is r6rs, should I do a naming convention
sqlite3-open
this is very common in the scheme community and will help ensure that
your code works even without special library wrapper/alpha renaming
software.
Post by Peter Keller
sqlite3/open
the / convention usually means some kind of variant on the semantics
of the thing before the slash.
Post by Peter Keller
sqlite3:open
This is the convention that SLIB uses and also has a fairly wide acceptance.
Post by Peter Keller
open
and let the person bringing in the library set a prefix for whatever they
want for the functions and symbols the library exports?
bad bad bad. It's also hard to remember in the long run and a PITA to
have to go through an extra build step to rename everything in the
bloody module. This is one of the reasons I hate the PLT library
system (even though I applaud the capabilities). If God had wanted us
to rername everything she would have given us
lambda-abstractions....Oh wait a minute...

david rush
- --
GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Peter Keller
2008-05-26 05:53:50 UTC
Permalink
Post by David Rush
Post by Peter Keller
sqlite3-open
this is very common in the scheme community and will help ensure that
your code works even without special library wrapper/alpha renaming
software.
I figured it would be that, but I've been away from the scheme community
for a while (year or two) and came back just after r6rs was ratified. I've
read r6rs a few times at this point, but figured I'd better check on
whether or not the old conventions still applied.
Post by David Rush
bad bad bad. It's also hard to remember in the long run and a PITA to
have to go through an extra build step to rename everything in the
bloody module. This is one of the reasons I hate the PLT library
system (even though I applaud the capabilities). If God had wanted us
to rername everything she would have given us
lambda-abstractions....Oh wait a minute...
:)

Like I said, since the r6rs library system gives us a mechanism for
adding a prefix to something, I figured I'd better ask first when making
my library. Personally, I have no opinion one way or the other. I just
want to write something in the line of what other people write.

I appreciate your time.

Thank you.

-pete
Ray Racine
2008-05-22 00:30:38 UTC
Permalink
Post by Peter Keller
I'm new to larceny and have chosen to use it for a project because it
supports R6RS. How can I figure out what SRFIs are supported in R6RS mode
(any?) and specifically is there an sqlite3 R6RS library? If an FFI is
available and reasonably documented, I'd be willing to produce a sqlite3
wrapping library for larceny.
I can vouch that the FFI implementation itself is nicely done, flexible
and robust.

I have used the FFI to do a bit of binding to libusb for USB device
listing and status, as well as a near complete binding to the IBM MQ CLI
client library[1] and a number of miscellaneous Linux O/S apis.

[1] The MQ stuff was tragically lost on an office to home repository
migration. I still have nightmares about that little incident.
David Rush
2008-05-22 06:17:23 UTC
Permalink
Post by Ray Racine
[1] The MQ stuff was tragically lost on an office to home repository
migration. I still have nightmares about that little incident.
ARRRRGH! I could *so* use that right now...

david
--
GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Peter Keller
2008-05-24 06:06:23 UTC
Permalink
Post by Ray Racine
I have used the FFI to do a bit of binding to libusb for USB device
listing and status, as well as a near complete binding to the IBM MQ CLI
client library[1] and a number of miscellaneous Linux O/S apis.
Ok, so here is a question:

I'm learning to wrap just a couple functions at first, sqlite3_open() and
sqlite2_close(). The C prototypes look like this:

int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);

int sqlite3_close(sqlite3 *);

So far, I have this code:

(foreign-file "/usr/lib/libsqlite3.so")

(define sqlite3
(lambda ()
(make-bytevector sizeof:pointer 0)))

(define sqlite3-open
(let ((_sqlite3_open
(foreign-procedure "sqlite3_open" '(string boxed) 'int)))
(lambda (path db)
(_sqlite3_open path db))))

(define sqlite3-close
(let ((_sqlite3_close
(foreign-procedure "sqlite3_close" '(boxed) 'int)))
(lambda (db)
(_sqlite3_close db))))
Post by Ray Racine
(define db (sqlite3))
db
#vu8(0 0 0 0)

; the db is created on disk and the return code is SQLITE_OK
Post by Ray Racine
(sqlite3-open "/tmp/test.db" db)
0

; Seems filled in with stuff...
Post by Ray Racine
db
#vu8(160 48 95 9)

; this fails with SQLITE_MISUSE
; lsof says the file descriptor for /tmp/test.db is still open. No good...
Post by Ray Racine
(sqlite3-close db)
21

Unfortunately, I've already done something wrong....

I have a feeling that I'm not understanding how boxed is to be used in the
above codebase. In C, I'd pass the address of a db pointer to sqlite3_open,
but I don't see the analogue of that in the FFI.

Any advice?

Thank you.

-pete
Peter Keller
2008-05-24 22:02:45 UTC
Permalink
Post by Peter Keller
(define sqlite3-close
(let ((_sqlite3_close
(foreign-procedure "sqlite3_close" '(boxed) 'int)))
(lambda (db)
(_sqlite3_close db))))
If I rewrite this call to:

(define sqlite3-close
(let ((_sqlite3_close
(foreign-procedure "sqlite3_close" '(int) 'int)))
(lambda (db)
(_sqlite3_close (%get-pointer db 0)))))

Then the code starts working. I'm not entirely sure this is correct since
the prototype for sqlite3_close expects a pointer, not an int (but due to
the 32-bit platform I'm on at the moment, this will work).

It was my intention that the bytevector passed into sqlite3_open gets
the pointer written into it and that the sqlite3_close uses the pointer
in the bytevector.

Given this method I'm using, I have the basic sqlite3 api (open, close,
prepare_v2, finalize, step, column*) working. I'll do some more testing and
try and get it packaged into an r6rs library.

Thank you.

-pete
Peter Keller
2008-05-26 07:06:49 UTC
Permalink
Hello,

I'd like to thank all of the people who've help on and off this list
with my r6rs sqlite3 library. I have a bare bones library working now
using Ray Racine's rl3 library--specifically the ffi portion of it.

I'll check back in a while when I get enough of the API finished for
public consumption or if I have any other questions.

Thank you.

-pete
Peter Keller
2008-05-31 02:56:04 UTC
Permalink
Hello,

I have another question, if I may ask:

in my sqlite3 library, I have this:

(define-c-info (include<> "sqlite3.h")
(const SQLITE_INTEGER int "SQLITE_INTEGER")
(const SQLITE_FLOAT int "SQLITE_FLOAT")
(const SQLITE_BLOB int "SQLITE_BLOB")
(const SQLITE_TEXT int "SQLITE_TEXT"))

and then later something like this:

(define sqlite3-column
(lambda (stmt colid)
(case (sqlite3-column-type stmt colid)
((SQLITE_INTEGER)
(sqlite3-column-int stmt colid))
((SQLITE_TEXT)
(sqlite3-column-text stmt colid))
(else
'oops)))) ;; <- obviously this is still test code!

It looks like the SQLITE_INTEGER and SQLITE_TEXT in the sqlite3-column
function are not available to me (as the code simply doesn't work and
I get 'oops all the time) while in the library codes. If I replace them
with the real constants 1 and 3 respectively, or use SQLITE_INTEGER and
SQLITE_TEXT in a piece of code which imports the sqlite3 library, then
sqlite3-column behaves properly.

Any ideas?

Thank you.

-pete
Felix Klock
2008-05-31 14:07:07 UTC
Permalink
Post by Peter Keller
Hello,
(define-c-info (include<> "sqlite3.h")
(const SQLITE_INTEGER int "SQLITE_INTEGER")
(const SQLITE_FLOAT int "SQLITE_FLOAT")
(const SQLITE_BLOB int "SQLITE_BLOB")
(const SQLITE_TEXT int "SQLITE_TEXT"))
(define sqlite3-column
(lambda (stmt colid)
(case (sqlite3-column-type stmt colid)
((SQLITE_INTEGER)
(sqlite3-column-int stmt colid))
((SQLITE_TEXT)
(sqlite3-column-text stmt colid))
(else
'oops)))) ;; <- obviously this is still test code!
It looks like the SQLITE_INTEGER and SQLITE_TEXT in the sqlite3-column
function are not available to me (as the code simply doesn't work and
I get 'oops all the time) while in the library codes. If I replace them
with the real constants 1 and 3 respectively, or use SQLITE_INTEGER and
SQLITE_TEXT in a piece of code which imports the sqlite3 library, then
sqlite3-column behaves properly.
Any ideas?
Are you sure you mean to use Scheme's case special form in the above?

That is, is (sqlite3-column-type stmt colid) going to produce a
Symbol, or an Integer? If it produces a Symbol, then your case
expression might work. If it produces an Integer, then you will never
get anything other than 'oops back.

-Felix
Felix Klock
2008-05-31 14:17:25 UTC
Permalink
Post by Felix Klock
Post by Peter Keller
Hello,
(define-c-info (include<> "sqlite3.h")
(const SQLITE_INTEGER int "SQLITE_INTEGER")
(const SQLITE_FLOAT int "SQLITE_FLOAT")
(const SQLITE_BLOB int "SQLITE_BLOB")
(const SQLITE_TEXT int "SQLITE_TEXT"))
(define sqlite3-column
(lambda (stmt colid)
(case (sqlite3-column-type stmt colid)
((SQLITE_INTEGER)
(sqlite3-column-int stmt colid))
((SQLITE_TEXT)
(sqlite3-column-text stmt colid))
(else
'oops)))) ;; <- obviously this is still test code!
It looks like the SQLITE_INTEGER and SQLITE_TEXT in the sqlite3-
column
function are not available to me (as the code simply doesn't work and
I get 'oops all the time) while in the library codes. If I replace them
with the real constants 1 and 3 respectively, or use SQLITE_INTEGER and
SQLITE_TEXT in a piece of code which imports the sqlite3 library, then
sqlite3-column behaves properly.
Any ideas?
Are you sure you mean to use Scheme's case special form in the above?
That is, is (sqlite3-column-type stmt colid) going to produce a
Symbol, or an Integer? If it produces a Symbol, then your case
expression might work. If it produces an Integer, then you will never
get anything other than 'oops back.
One more thing: if you do want to get symbols instead of integers,
there is another library, foreign-cenums, that is a derivative of the
foreign-ctools library but provides C enum values as symbols rather
than integers.

(It does this by internally keeping a table mapping between the
integers produced by define-c-info and the symbols you provide to the
define-c-enum or define-c-enum-set special forms. The code isn't
anything terribly special and so you may be better off sticking with
define-c-info, but I thought I should point it out just in case you do
want to use symbols instead of global variables or integers for the
SQLITE constants.)

-Felix
Peter Keller
2008-05-31 22:57:07 UTC
Permalink
Post by Felix Klock
Are you sure you mean to use Scheme's case special form in the above?
After reading the spec, it seems I should have used cond. case expects a datum
there, not an expression, which is sorta what I needed.

Thanks for your help!

-pete
Peter Keller
2008-05-31 23:07:23 UTC
Permalink
Hello,

Ok, I'm basically done with my R6RS binding for sqlite3 except for all
of the testing code. I have a couple of questions though:

1. Does larceny have an CPAN-like (or egg-like, if you know about Chicken
Scheme) system for its R6RS libraries? What is the usual mechanism for
me to share this library (and its various revisions as it gets improved)
with others?

2. While I have a usable chunk of the sqlite3 interface done, should I
bother making statement level or higher abstractions, or just let that
be made by the people using the library?

3. If I were to write a complete test suite for this library, would it
be in the library itself as an exported function that people could run
after they've got the library loaded? Or just some other program which
loads the library and tests it?

4. I've noticed foreign-function can't wrap a C function which has a void
parameter list. The docs don't say void is a valid parameter type and at
least the rl3 library's foreign-function procedure complains about it.

5. How do Snow packages, R6RS libraries, and larceny play together?

Thank you very much for all of your help!

-pete
David Rush
2008-06-01 07:52:16 UTC
Permalink
Post by Peter Keller
2. While I have a usable chunk of the sqlite3 interface done, should I
bother making statement level or higher abstractions, or just let that
be made by the people using the library?
If you are programming a lot in Scheme, you will end up making those
higher-level abstractions almost as a matter of breathing. The system
I posted a few days ago for MySQL has several of them which are based
around my own analysis of the question of how a DB engine should be
related to fairly flat, transparent data structures such as Scheme
provides. I realize that given the lack of documentation, that they
would have been entirely invisible except to extremely interested
users.

The main interface is implemented from the section titled
'Query-Macros', however, there are a few important functions that
haven't yet been fully abstracted from the MySQL layer. The MySQL
leftovers get used in the 15% of my code that doesn't fit the usage
patterns covered by the main macros. I also have a deep and enduring
attraction to CPS programming, especially when it comes to dealing
with external systems (such as databases). All that said, I'm sure
that there have been several DB encapsulations built in the Scheme
world, but I've never really heard of any outside the PLT
implementation (I' have to bet that Chicken has one as well, though).

My API (a summary):

(define-cached-query name ...)

A macro that wraps up the machinery for grabbing the rows from a DB
based and keeping them in a keyed hashtable.

(define-cached-value (accessor-name . args) ...)

A macro that grabs values from a DB and stores them in a
user-specified data structure (mostly used for computing dependent
values in otherwise-persisted data structures)

(mysql-query-k cx query k-success k-failure)

This is the main 'workhorse' function which executes an arbitrary
query and returns the relevant information to the program to carry on
processing. <k-success> and <k-failure> are both called in tail
position to make it easy to use this as both a conditional and as a
binding form. There are a few pre-packaged kontinuations which can be
used to fit this into non-CPS code, as well.

(mysql-insert-k cx table-name field-alist obj k-success k-failure)

A relatively high-level function abstraction which generates a SQL
insert statement from the field conversions specified in <field-alist>
and the given object <obj>. There should probably be a macrotic
wrapping for this function, but the textual overhead associated with
it is not all that large.

(mysql-update-k cx table-name key-alist key field-alist obj k-success k-failure)

This is the same as MYSQL-INSERT-K except for SQL updates. It's a
really ugly interface and the comments in the source code even say
that, but then again the fundamental semantics of a DB update are a
little bit icky as well. I imagine that I will eventually come up with
a better abstraction here, but I also think it will involve a deeper
binding of Scheme data values and the notion of persistent data.

(mysql-row->alist row)

Builds a Scheme alist out of a returned DB row structure. Very useful
when you don't want to build a data structure around an ad-hoc query.

(mysql-convert-field row name string->datum . default)

Converts a column from MySQL's internal format into a Scheme datum.
The default value is used when MySQL indicates that the column had a
NULL value.

(mysql-construct row kons fields)

Converts a MySQL <row> into whatever object type <kons> returns when
it is applied to the list resulting from converting all the <fields>.
The <fields> list is a list of lists which contain the final 3
arguments to MYSQL-CONVERT-FIELD.

And that's the highlights of the interface folks. Eventually, I would
hope that everyone's interfaces to relational DBs might all settle
down enough to write a SRFI for it, but somehow I doubt that anything
resembling a community consensus even exists. For my own work, I do
plan to eventually abstract away from MySQL, but so far I haven't had
the need to use anything else (all the client-server systems I've been
working with lately have been built around MySQL), although I suspect
that I may wrap up an ODBC binding fairly soon. When that happens, I
fully expect to finish abstracting away from the MYSQL-* functions to
something a little less dependent on the specific patterns inflicted
by the MySQL API.

david rush
--
GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Peter Keller
2008-06-01 15:13:08 UTC
Permalink
Post by David Rush
If you are programming a lot in Scheme, you will end up making those
higher-level abstractions almost as a matter of breathing. The system
I posted a few days ago for MySQL has several of them which are based
around my own analysis of the question of how a DB engine should be
related to fairly flat, transparent data structures such as Scheme
provides.
At this time, I don't have that much experience as a DB engine user. I
have a project in mind which relies extensively on a relational DB
though, so I'm in the process of learning the ins and outs of SQL and
DB engine use.
Post by David Rush
I would
hope that everyone's interfaces to relational DBs might all settle
down enough to write a SRFI for it, but somehow I doubt that anything
resembling a community consensus even exists.
Given what I've seen with postgresql, mysql, and sqlite3, I'm not sure
an SRFI can be made at the level of the FFI to those DB. The only way
I see an SRFI being made is someone creating a scheme-like varient
of SQL example: (select (id name age) from table (where (eqv? 2 id)))
building an SRFI on THAT (along with certain operations on a DB like
how many rows changed, vacumming, etc, etc, etc) and then wedging that
into whatever offbeat SQL dialect a specific DB implementation requires.
I'm definitely not smart enough in relational databases to pull off that
kind of abstraction at this time and the SQL language as it currently
stands is a nice enough syntax.

For what it is worth, I've basically followed Chicken's sqlite3 interface
when I wrote mine. There are currently some small differences, like I'm
not sure what collation is in term of sqlite3, so I haven't copied that
portion of the interface.

I was just asking about the abstractions because I simply don't want to
be too clever and I don't have a lot of experience using a DB in code,
so I don't have a good feel for what the abstractions should be beyond
the obvious ones.

Thank you.

-pete
David Rush
2008-06-01 18:26:32 UTC
Permalink
Post by Peter Keller
Post by David Rush
I would
hope that everyone's interfaces to relational DBs might all settle
down enough to write a SRFI for it, but somehow I doubt that anything
resembling a community consensus even exists.
Given what I've seen with postgresql, mysql, and sqlite3, I'm not sure
an SRFI can be made at the level of the FFI to those DB.
Well they did it in Rails, but indeed at a level rather higher than
the raw FFI. Which is the style of interface I'm headed towards. I did
a lot of Rails work in 2k7 and slowly grew to be quite annoyed with it
- the ideas are fairly sound, but the execution really stinks. So I've
been slowly re-implementing it in Larceny/Gambit as I've had the need
for my own work.

david rush
--
GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt

Loading...