DBI for Euphoria

new topic     » topic index » view thread      » older message » newer message

Being mainly a database programmer by trade, a DBI is important to me for some apps. Other apps I want all the raw power of a database server exposed to me. I have been thinking of a DBI for a while and this is what I came up with. Please comment if you would like to see it designed differently. This will not be a core product, but something developed and distributed separately by me, not core Euphoria (it may change, who knows).

include dbi/core.e as dbi ... This is the only include file you will need to deal with.

Your application need not "include" different database drivers, they will be dynamically loaded. Your application may even load database drivers that were not around at the time your application was developed. Anyone can develop a DBD (database driver). It is a DLL/SO file that adheres to a published "DBD" spec (according to the DBI). DBD's can exist for any database including PostrgreSQL, MySQL, ODBC, EDS, SQLite, Firebird, etc...

The connecting of the database should happen in a manner that is only changed by 1 connection string. The application should not need to know about what type of database it is connecting to, however, it could determine the connected database easily if it wishes.

The DBI will automatically convert to proper Euphoria types. Atom, Integer, String, Date, Time and Date/Time values will be understood directly.

The DBD would have to implement a small number of functions: dbd_connect, dbd_close, dbd_last_id, dbd_execute, dbd_query, dbd_field, dbd_field_count, dbd_field_name, dbd_field_type. The DBI will take care of all the nice functionality. The drivers should be written in C for speed.

On with some example code:

include dbi/core.e as dbi 
include std/datetime.e as dt 
include std/map.e as m 
 
dbi:handle dbh = dbi:connect("mysql://people?user=john") 
--dbi:handle dbh = dbi:connect("sqlite3://people.db") 
--dbi:handle dbh = dbi:connect("eds://people.edb") 
--dbi:handle dbh = dbi:connect("pgsql://people?user=jim&password=secret&host=jim.com&ssl=true") 
if dbi:error(dbh) then 
	printf(1, "DBI failed to connect: %s\n", { dbh }) 
	abort(1) 
end if 
 
if not dbi:execute(dbh, "INSERT INTO people VALUES (%s,%s,%t)", { "John", "Doe", dt:now() }) 
then 
	printf(1, "Could not insert people record: %s\n", { dbi:error_message(dbh) }) 
	dbi:close(dbh) 
	abort(1) 
end if 
printf(1, "Last inserted id: %d\n", { dbi:lastid(dbh, "people_id") }) 
 
dbi:result rs = dbi:query(dbh, "SELECT * FROM people WHERE name LIKE %s", { "%e%" }) 
if dbi:error(dbh) then 
	printf(1, "DBI failed to query people table: %s\n", { dbi:error_message(dbh) }) 
	dbi:close(dbh) 
	abort(1) 
end if 
 
while dbi:next(rs) do 
	printf(1, "Person: %s %s was born on %s\n", { dbi:field(rs, "fname"), dbi:field(rs, "lname"),  
		dt:format("%m/%d/%Y", dbi:field(rs, "dob") }) 
	printf(1, "Person: %s %s\n", dbi:fields(rs, { "fname", "lname", "dob" })) 
	printf(1, "Person: %s %s\n", dbi:fields(rs, { 1, 2 })) 
 
	m:map p = dbi:fetch_map(rs) 
	printf(1, "Person: %s %s\n", { m:get(p, "fname"), m:get(p, "lname") }) 
end while 
dbi:close_result(rs) 
 
printf(1, "Min name: %s, Max name: %s\n", { dbi:query_one(dbh, "SELECT min(fname) FROM people"), 
	dbi:query_one(dbh, "SELECT max(fname) FROM people") }) 
printf(1, "John Doe: %s %s\n", { dbi:query_one_row(dbh, "SELECT * FROM people WHERE id=%d", { 10 }) }) 
 
m:map p = m:new() 
m:put(p, "fname", "Jack") 
m:put(p, "lname", "Smith") 
m:put(p, "id", 0) 
 
if not dbi:save_map(dbh, "people", p) then 
	printf(1, "Could not save map to database table people: %s\n", { dbi:error_message(dbh) }) 
end if 
 
dbi:close(dbh) 

Any thoughts or comments?

Jeremy

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu