[DB-SIG] RE: column type casting

Federico Di Gregorio fog@mixadlive.com
Fri, 23 Mar 2001 18:45:13 +0100

Scavenging the mail folder uncovered M.-A. Lemburg's letter:
> Good idea.
> There seem to be a few things common to all implementations:
> * settings are inherited from connection to cursor objects, but
>   can be overridden on the cursor
> * argument callback assignment is done in a positional way, meaning 
>   that each argument can be handled individually
> * type mappings map cursor.description type codes to converters

the last two items are quite orthogonal, but the basic concept, the use
of a typecast object or a callback function applies to both. this is why
i propose the following api that, to me, has some advantages:

1/ it is simple (both to use and implement)

2/ it is db-independent

3/ imho, does it the python-way...

first of all, the callbacks are callable objects and the old type 
singletons should be implemented as those new objects (everything
that applies to the old singleton types applies to this new type
objects.) you can build a new type object by calling the new_type()
function on the module:

	TYPE = module.new_type(name, cast_func, type_codes)

where name is just a string (we can drop it, it is usefull only for
debugging purpouses); cast_func is a function that takes a data in
the db _natural_ format (that is a String or Buffer, usually) and
casts it into the new type and type codes are the codes from
description.type_code to which the TYPE object should be equal.
mmm, bad english, example: TYPE == cursor.fetchone().description[1]
should be true is the type code returned by the db is one of the
values in type_codes.

as i said above, TYPE should be a callable object (it works like a
callback function) so that doing TYPE(data...) returns the data 
correctly type-casted.

now that we have types, we can use them in two, orthoganl ways.
we can register the types with the system (i'll put the function
in module, because the default types NUMBER, STRING, etc. are 
defined in it, but working on the connection is equally valid)
by calling:


from now on all the columns that have a type_code included in the
TYPE's list of type_codes, are concerted by calling TYPE(data) on
the column data returned by fetchXXX().

what happens if (like in postgres lobs) the type code is not enough
but u need to convert just a single column? you simply call:

	cursor.register_type(TYPE, column)

to associate the TYPE callback to a specific column in a specific
cursor (i see aproblem here, what happens if the user forget to
destroy the cursor and reuse it for a different SELECT? maybe
the data can't be converted and an exception should be raised?)

that's all. as you see, three functions and an object that is already
half-implemented in the current driver. this stuff should be fairly
easy to implement for everyone. and cover almost all cases. what
do you think about?


Federico Di Gregorio
MIXAD LIVE Chief of Research & Technology              fog@mixadlive.com
Debian GNU/Linux Developer & Italian Press Contact        fog@debian.org
  Those who do not study Lisp are doomed to reimplement it. Poorly.
                                     -- from Karl M. Hegbloom .signature