ODBC

5 views
Skip to first unread message

Jiri Spitz

unread,
Feb 7, 2009, 5:34:18 PM2/7/09
to pure...@googlegroups.com
Hi,

I added ODBC module ported from Q. It compiles under Linux for now.

There is a difference against Q: Records of resultsets and parameters
to sql_exec are represented as lists instead of tuples.

Most functions seem to work here, but `odbc_sources' and `odbc_drivers'
return always an empty list. Who knows why, `SQLDataSources' and
`SQLDrivers' return always `SQL_NO_DATA'. The same code from Q works fine.

The binary data is represented by bytestrings in the same way as in Q.
Pure is now lacking direct support for bytestrings. Should we create it
or is there a better way to represent binary data in Pure?


When time permits I'll continue with Windows compilation.

Enjoy.

Jiri

Albert Graef

unread,
Feb 8, 2009, 6:56:24 AM2/8/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> I added ODBC module ported from Q. It compiles under Linux for now.

Wow, we're really getting somewhere. :) Thanks a lot!

I ran into various compilation issues, mostly header-related stuff and
64 bit quirks. I already fixed these in svn. Note that I changed the
default odbc lib to -lodbc which is what seems to be available on most
systems nowadays. I also added an ODBCLIB variable for that. If you
prefer, you can change the default value of ODBCLIB back to -liodbc, but
AFAICT unixODBC seems to be the way to go (iodbc seems to be largely
unmaintained and SUSE doesn't even ship it any more; whereas unixodbc is
still actively developed and is included in all major Linux distros).

There are still quite a few memory leaks to be fixed, due to the
different way in which (is_)tuplev/listv works in Pure. I'm looking at
these right now.

I also did some minor cosmetic surgery on odbc.pure (r764).
Specifically, ODBC::odbc_error is just ODBC::error now and the 'using
namespace' declaration in the second half of the module was superflous
(the current namespace is always searched anyway).

I'd really prefer it if the namespace was named 'odbc' rather than
'ODBC' so that it matches the module name. Any objections to that?

> There is a difference against Q: Records of result sets and parameters

> to sql_exec are represented as lists instead of tuples.

Yes, this makes sense. But then the singleton case in odbc_sql_exec
ought to be removed and only lists should be allowed as the third
parameter; the singleton case really makes sense only in conjunction
with tuples. I've already committed this in r763.

> Most functions seem to work here, but `odbc_sources' and `odbc_drivers'
> return always an empty list. Who knows why, `SQLDataSources' and
> `SQLDrivers' return always `SQL_NO_DATA'. The same code from Q works fine.

Did you configure your ODBC data sources? On Linux there are some config
files (.odbcrc or similar) which need to be edited. UnixODBC also offers
some GUI tools for that. Also, you need to have the ODBC drivers for
your RDBMS installed (as well as the RDBMS itself, of course).

> The binary data is represented by bytestrings in the same way as in Q.

This doesn't work. In Pure bytestrings are just raw C pointers without
any size information, so the size information needs to be passed
separately in some way, or we need a new kind of blob data type. I'm not
sure what the right thing is, I'll have to take a closer look at it.

> When time permits I'll continue with Windows compilation.

IIRC there should be some mingw headers and an import library for the
Win ODBC library. I'll have to look it up.

Cheers,
Albert

--
Dr. Albert Gr"af
Dept. of Music-Informatics, University of Mainz, Germany
Email: Dr.G...@t-online.de, a...@muwiinfa.geschichte.uni-mainz.de
WWW: http://www.musikinformatik.uni-mainz.de/ag

Jiri Spitz

unread,
Feb 8, 2009, 7:33:54 AM2/8/09
to pure...@googlegroups.com
Albert Graef wrote:
>
> There are still quite a few memory leaks to be fixed, due to the
> different way in which (is_)tuplev/listv works in Pure. I'm looking at
> these right now.
>
> I also did some minor cosmetic surgery on odbc.pure (r764).
> Specifically, ODBC::odbc_error is just ODBC::error now and the 'using
> namespace' declaration in the second half of the module was superflous
> (the current namespace is always searched anyway).
>
>
Thx for bugfixing :-) .

> I'd really prefer it if the namespace was named 'odbc' rather than
> 'ODBC' so that it matches the module name. Any objections to that?
>
No problem.

>
> Did you configure your ODBC data sources?
>
Of course, otherwise I would not be able to test the stuff. It might be
problem of using iodbc. I installed Q from rpm and that might be the
reason why it works there.

>
> This doesn't work. In Pure bytestrings are just raw C pointers without
> any size information, so the size information needs to be passed
> separately in some way, or we need a new kind of blob data type. I'm not
> sure what the right thing is, I'll have to take a closer look at it.
>
I let it be the same way as in Q - the bstr struct. Only the Pure stuff
to deal with it is missing.

> IIRC there should be some mingw headers and an import library for the
> Win ODBC library. I'll have to look it up.
>
It compiles without any problems :-) .

Inbetween I added README, COPYING and config.guess. README is mostly
updated.

Jiri

Eddie Rucker

unread,
Feb 8, 2009, 9:01:39 AM2/8/09
to pure...@googlegroups.com
Hi guys,

On Sat 07/02/09 4:34 PM , Jiri Spitz jiri....@gmail.com sent:


> I added ODBC module ported from Q. It compiles under Linux for now.

This one is a must for me. Thanks :)

> Enjoy.

That, I shall ;-)

e.r.

Jiri Spitz

unread,
Feb 8, 2009, 7:11:03 PM2/8/09
to pure...@googlegroups.com
Albert Graef wrote:
>
>> Most functions seem to work here, but `odbc_sources' and `odbc_drivers'
>> return always an empty list. Who knows why, `SQLDataSources' and
>> `SQLDrivers' return always `SQL_NO_DATA'. The same code from Q works fine.
>>
>
> Did you configure your ODBC data sources? On Linux there are some config
> files (.odbcrc or similar) which need to be edited. UnixODBC also offers
> some GUI tools for that. Also, you need to have the ODBC drivers for
> your RDBMS installed (as well as the RDBMS itself, of course).
>
I removed iODBC and installed UnixODBC. Now it works fine. So does under
Windows.

Now I discovered a weird bug maybe caused by memory allocation/disposal
disorder. To reproduce do:

> let db = odbc::connect ... ;
> odbc::tables db; // OK
> odbc::sql_exec db ... ; // OK
> odbc::sql_fetch db; // crash

It happens always both under Linux and Windows.

Jiri

Albert Graef

unread,
Feb 9, 2009, 3:00:31 PM2/9/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Thx for bugfixing :-) .

Sorry, I didn't have the time to get around fixing the memleaks yet, as
I'm still working on pure-gen.

It isn't terribly hard to do if you want to fix those memleaks yourself.
You have to look for all calls to pure_listv/pure_is_listv as well as
pure_tuplev/pure_is_tuplev.

The expression vectors taken or returned by these aren' freed
automatically in Pure, you'll have to do that yourself. That's all. But
you have to be careful with pure_is_listv and pure_is_tuplev; if these
return zero elements then the corresponding expression vector will be
NULL, so better don't free it in that case. ;-)

> I let it be the same way as in Q - the bstr struct. Only the Pure stuff
> to deal with it is missing.

Well, those are simply pointers to a struct containing the size and
another pointer to the data, which can easily be handled using the ffi
struct functions if necessary. I'll have a look at this when time
permits. Fortunately, starting next week we have semester holidays. :)

>> IIRC there should be some mingw headers and an import library for the
>> Win ODBC library. I'll have to look it up.
>>
> It compiles without any problems :-) .

Great. :)

Albert Graef

unread,
Feb 9, 2009, 3:17:13 PM2/9/09
to pure...@googlegroups.com
Albert Graef wrote:
> Sorry, I didn't have the time to get around fixing the memleaks yet, as
> I'm still working on pure-gen.

Just for the record, the bigint stuff needs a review as well.
Specifically, pure_mpz copies its argument, so the mpz_t argument needs
to be freed with mpz_clear after that. Similarly, the mpz_t result in
the call to pure_is_mpz in set_arg also needs to be cleared after use.

Also, the bigint marshalling uses an intermediate string representation
right now. This is wasteful. runtime.h has functions for directly
converting Pure bigints to 64 bit integers and vice versa, these should
be used instead (cf. odbc.c lines 132 and 1065).

Albert Graef

unread,
Feb 9, 2009, 3:20:34 PM2/9/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Now I discovered a weird bug maybe caused by memory allocation/disposal
> disorder. To reproduce do:
>
> > let db = odbc::connect ... ;
> > odbc::tables db; // OK
> > odbc::sql_exec db ... ; // OK
> > odbc::sql_fetch db; // crash

Hmm, I don't see any obvious glitches in that routine. Maybe add some
printf's to the odbc_sql_fetch routine to see where exactly it bombs?

John Cowan

unread,
Feb 9, 2009, 3:56:22 PM2/9/09
to pure...@googlegroups.com
Albert Graef scripsit:

> The expression vectors taken or returned by these aren' freed
> automatically in Pure, you'll have to do that yourself. That's all. But
> you have to be careful with pure_is_listv and pure_is_tuplev; if these
> return zero elements then the corresponding expression vector will be
> NULL, so better don't free it in that case. ;-)

ISO C and Posix compliant free() will do nothing if passed NULL, so that
advice is pretty much obsolete.

--
Do I contradict myself? John Cowan
Very well then, I contradict myself. co...@ccil.org
I am large, I contain multitudes. http://www.ccil.org/~cowan
--Walt Whitman, Leaves of Grass

Albert Graef

unread,
Feb 9, 2009, 11:51:56 PM2/9/09
to pure...@googlegroups.com
Albert Graef wrote:

> Jiri Spitz wrote:
>> I let it be the same way as in Q - the bstr struct. Only the Pure stuff
>> to deal with it is missing.

Yes, that's because Pure doesn't need all this bstr stuff any more since
it can handle raw C pointers just fine and interface directly to the C
routines that handle them. So the sooner we get rid of this legacy the
better. :)

> Well, those are simply pointers to a struct containing the size and
> another pointer to the data, which can easily be handled using the ffi
> struct functions if necessary. I'll have a look at this when time
> permits.

All right, I reviewed the uses of these in pure-odbc, and basically
they're employed for two purposes:

- odbc::getinfo: This is essentially a raw interface to SQLGetInfo(),
which returns a pointer to the requested information, which either
points to an integer or a string. I think that it would make things much
easier to just return a malloc'd pointer there. The caller presumably
knows what kind of information he wants to get, thus he can just invoke
get_int or cstring_dup from the prelude to extract the information. In
any case the len field doesn't provide any useful additional information
here.

- As query parameters in sql_exec and query results in sql_fetch. Here
the binary data will usually be handled through a third party library.
E.g., you might want to store, sounds, graphics and videos in a
database, that's what these blobs are for. Those external libraries
won't be able to do anything with a bstr struct either. Hence I think we
should represent the blobs as pairs size,data, on both input and output,
where data is just a malloc'd pointer to the data and size the size of
the blob (better allow a bigint for that, I'd guess that SQLLEN is
actually a 64 bit type nowadays, at least on 64 bit systems).

The necessary changes to odbc.c are trivial, I can do them if you want.

Ok?

Jiri Spitz

unread,
Feb 10, 2009, 7:55:01 AM2/10/09
to pure...@googlegroups.com
Albert Graef wrote:
>
> Also, the bigint marshalling uses an intermediate string representation
> right now. This is wasteful. runtime.h has functions for directly
> converting Pure bigints to 64 bit integers and vice versa, these should
> be used instead (cf. odbc.c lines 132 and 1065).
>

I'm afraid we cannot avoid this (at least on 32 bit systems). Citing
from ODBC documentation:

"SQL_BIGINT:
The number of bytes required to hold the character representation of
this data if the character set is ANSI, and twice this number if the
character set is UNICODE, because this data type is returned as a
character string by default. The character representation consists of 20
characters: 19 for digits and a sign, if signed, or 20 digits, if
unsigned. Therefore, the length is 20."

Since the `iv' member of the ODBCParam struct is defined as long, we
cannot assign a 64 bit integer to it on a 32 bit system. Moreover, I did
not find a SQL C type for BIGINT.

Am I right?

Jiri

Jiri Spitz

unread,
Feb 10, 2009, 12:36:22 PM2/10/09
to pure...@googlegroups.com
Albert Graef wrote:
>
> - odbc::getinfo: This is essentially a raw interface to SQLGetInfo(),
> which returns a pointer to the requested information, which either
> points to an integer or a string. I think that it would make things much
> easier to just return a malloc'd pointer there. The caller presumably
> knows what kind of information he wants to get, thus he can just invoke
> get_int or cstring_dup from the prelude to extract the information. In
> any case the len field doesn't provide any useful additional information
> here.
>
> - As query parameters in sql_exec and query results in sql_fetch. Here
> the binary data will usually be handled through a third party library.
> E.g., you might want to store, sounds, graphics and videos in a
> database, that's what these blobs are for. Those external libraries
> won't be able to do anything with a bstr struct either. Hence I think we
> should represent the blobs as pairs size,data, on both input and output,
> where data is just a malloc'd pointer to the data and size the size of
> the blob (better allow a bigint for that, I'd guess that SQLLEN is
> actually a 64 bit type nowadays, at least on 64 bit systems).
>
Done, but PLS look at this code. I cannot test the 64-bit stuff.

Jiri

Jiri Spitz

unread,
Feb 10, 2009, 6:53:47 PM2/10/09
to pure...@googlegroups.com
Albert Graef napsal(a):

> Jiri Spitz wrote:
>
>> Now I discovered a weird bug maybe caused by memory allocation/disposal
>> disorder. To reproduce do:
>>
>> > let db = odbc::connect ... ;
>> > odbc::tables db; // OK
>> > odbc::sql_exec db ... ; // OK
>> > odbc::sql_fetch db; // crash
>>
>
> Hmm, I don't see any obvious glitches in that routine. Maybe add some
> printf's to the odbc_sql_fetch routine to see where exactly it bombs?
>
>
The function crashes on `return res' (the 3rd line from the end). I
suspect there is something wrong with `odbc_tables'. As long as I do not
call it, `odbc_sql_fetch' works fine. As soon as I call `odbc_tables'
then `odbc_sql_fetch' always crashes regardless how many other
statements were called in between. It seems, `odbc_tables' leaves the
environment somehow corrupted. I have no idea, how to debug this.

I enclose the crash dump.

Jiri

crashdump.txt

Albert Graef

unread,
Feb 10, 2009, 8:25:52 PM2/10/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> I'm afraid we cannot avoid this (at least on 32 bit systems).

Yes, I came pretty much to the same conclusion. Ok, then so be it.

Albert Graef

unread,
Feb 10, 2009, 8:34:05 PM2/10/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Done, but PLS look at this code. I cannot test the 64-bit stuff.

Will do, as soon as I get an odbc client up and running.

Albert Graef

unread,
Feb 10, 2009, 8:40:01 PM2/10/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> The function crashes on `return res' (the 3rd line from the end).

Are you sure? No function should ever crash on a return statement like
that, unless the C stack is thrashed. Now that would be *really* bad.

> I suspect there is something wrong with `odbc_tables'. As long as I do not
> call it, `odbc_sql_fetch' works fine. As soon as I call `odbc_tables'
> then `odbc_sql_fetch' always crashes regardless how many other
> statements were called in between. It seems, `odbc_tables' leaves the
> environment somehow corrupted. I have no idea, how to debug this.

Well, it might be that odbc_tables() trashes the sql statement data
structure. Reinitializing that from scratch might help. Will look into
that when I find the time.

Albert

Jiri Spitz

unread,
Feb 11, 2009, 2:43:00 AM2/11/09
to pure...@googlegroups.com
Albert Graef wrote:
>> The function crashes on `return res' (the 3rd line from the end).
>
> Are you sure? No function should ever crash on a return statement like
> that, unless the C stack is thrashed. Now that would be *really* bad.
>

Yes, I am. And the dump witnesses for your malicious diagnosis - "Stack
smashing" :-( .

Jiri

Jiri Spitz

unread,
Feb 13, 2009, 10:23:27 AM2/13/09
to pure...@googlegroups.com
Albert Graef wrote:
>> The function crashes on `return res' (the 3rd line from the end).
Hi Albert,

Revision 851 does not suffer from this weird error under Windows
anymore. :-) I'll try it under Linux in the evening and let you know.

Jiri

Jiri Spitz

unread,
Feb 13, 2009, 4:40:35 PM2/13/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Revision 851 does not suffer from this weird error under Windows
> anymore. :-) I'll try it under Linux in the evening and let you know.

Unfortunately, under Linux the problem persists :-(. Moreover, I found
other similar bug. The combination typeinfo + sql causes a segfault.

Jiri

Albert Graef

unread,
Feb 13, 2009, 9:14:35 PM2/13/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Unfortunately, under Linux the problem persists :-(. Moreover, I found
> other similar bug. The combination typeinfo + sql causes a segfault.

Also, numelem in set_arg needs to be a size_t. I just fixed that (r862).

I'll take a look at the other issue some time next week. Can you please
upload a minimal example which reliably reproduces the segfault on Linux?

Jiri Spitz

unread,
Feb 14, 2009, 3:44:01 AM2/14/09
to pure...@googlegroups.com
Albert Graef napsal(a):

>
> Also, numelem in set_arg needs to be a size_t. I just fixed that (r862).
Thx.

>
> I'll take a look at the other issue some time next week. Can you please
> upload a minimal example which reliably reproduces the segfault on Linux?
>

It is enclosed.

Jiri

odbcerr.pure

Albert Graef

unread,
Feb 23, 2009, 7:14:00 AM2/23/09
to pure...@googlegroups.com

Looks good to me. I did some minor surgery, though, you can find the
details in the svn logs.

Having thought about this some more, I think that we should actually
split odbc::getinfo into two routines, odbc::getinfo_int which returns
an int and odbc::getinfo_string which returns a string value. Thereby we
can completely get rid of the pointer returns in odbc::getinfo (which
always invite memleaks). Do you see any problems with that?

Or maybe there's some easy clue in the type_info constants which would
allow odbc::getinfo allow to figure out the return type on its own? I
don't see anything in the SQLGetInfo description, though. Another
example of an API that's broken by design.

I also think that we should turn the raw blob pointers in sql_fetch
results into cooked pointers which free themselves after use, so that
they don't leak memory either. That's easy to add and very convenient
since the user doesn't have to free those blobs manually. Ok?

NB: I finally got a MySQL database with unixODBC up and running so that
I can now test stuff myself. ;-) I did some more cosmetic surgery, most
notably the example is now in a separate examples subdir as required by
'make dist' and I also renamed it to menagerie.pure. I expect to look at
the tables/sql_fetch bomb later today or tomorrow.

Jiri Spitz

unread,
Feb 23, 2009, 8:08:23 AM2/23/09
to pure...@googlegroups.com
Albert Graef wrote:
> Having thought about this some more, I think that we should actually
> split odbc::getinfo into two routines, odbc::getinfo_int which returns
> an int and odbc::getinfo_string which returns a string value. Thereby we
> can completely get rid of the pointer returns in odbc::getinfo (which
> always invite memleaks). Do you see any problems with that?
>
> Or maybe there's some easy clue in the type_info constants which would
> allow odbc::getinfo allow to figure out the return type on its own? I
> don't see anything in the SQLGetInfo description, though. Another
> example of an API that's broken by design.
>
Perhaps we could change the list of constants in "odbc.pure" into a
dictionary with `constant => result_type' pairs. Then we could have only
one odbc::getinfo calling propper C::getinfo variant and returning
short, long or string depending on the `result_type'.

> I also think that we should turn the raw blob pointers in sql_fetch
> results into cooked pointers which free themselves after use, so that
> they don't leak memory either. That's easy to add and very convenient
> since the user doesn't have to free those blobs manually. Ok?
>

Oh, yes.

Jiri

Albert Graef

unread,
Feb 23, 2009, 1:59:16 PM2/23/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Perhaps we could change the list of constants in "odbc.pure" into a
> dictionary with `constant => result_type' pairs. Then we could have only
> one odbc::getinfo calling propper C::getinfo variant and returning
> short, long or string depending on the `result_type'.

The problem is that the info_type enumerants are open-ended, so in
general we don't really have that type information. Note that odbc.pure
only defines the common enumerants, ODBC drivers are free to define
their own. I wouldn't want odbc::getinfo to preclude use of the
vendor-specific info_types.

As a compromise I made the result of odbc::getinfo a cooked pointer so
that it frees itself now. Blob results returned by odbc::sql_fetch are
now auto-disposing as well (r956).

NB: There's a bug in the pure_symbol() function of the Pure runtime (all
versions <= 0.18) which keeps the 'free' sentries defined in odbc.c from
working. This has been fixed in r955.

Cheers,
Albert

P.S.: Ryan and Toni, I've attached the necessary patch to runtime.cc for
your convenience. It would be nice if you'd consider applying that patch
to your pure-0.18 packages. The bug is not a real showstopper (doesn't
cause any segfaults), but will cause memleaks with pure-odbc which I
expect to be released soon.

pure_symbol.patch

Ryan Schmidt

unread,
Feb 24, 2009, 5:36:27 AM2/24/09
to pure...@googlegroups.com

On Feb 23, 2009, at 12:59, Albert Graef wrote:

> P.S.: Ryan and Toni, I've attached the necessary patch to
> runtime.cc for
> your convenience. It would be nice if you'd consider applying that
> patch
> to your pure-0.18 packages. The bug is not a real showstopper (doesn't
> cause any segfaults), but will cause memleaks with pure-odbc which I
> expect to be released soon.

Done in MacPorts:

http://trac.macports.org/changeset/47267


Albert Graef

unread,
Feb 24, 2009, 9:36:45 AM2/24/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Albert Graef napsal(a):

>> I'll take a look at the other issue some time next week. Can you please
>> upload a minimal example which reliably reproduces the segfault on Linux?
>>
> It is enclosed.

Fixed (r980). Jiri, can you please verify? (This is about the
typeinfo/table-related crashes. Pretty obvious in retrospect. Wonder why
that went unfixed for so long.)

I also fixed a bunch of other bugs and memleaks (see the svn log), added
lazy variations of sql/msql which produce streams instead of (eager)
lists (pretty useful for dealing with large result sets), and added some
remarks about how to interface to SQLite via ODBC (I think that's by far
the most convenient way to get a local database up and running quickly,
if you don't want to depend on Windows-only stuff).

Jiri, I'm through with my TODO list (except rechecking the Windows
port), so I'd say it's about time for a 0.1 release. Anything you still
want to fix or add?

Jiri Spitz

unread,
Feb 24, 2009, 10:05:05 AM2/24/09
to pure...@googlegroups.com
Albert Graef wrote:
> Fixed (r980). Jiri, can you please verify? (This is about the
> typeinfo/table-related crashes. Pretty obvious in retrospect. Wonder why
> that went unfixed for so long.)
>
Works fine - tested under Windows with MS Access, PostgreSQL and MySQL.

> I also fixed a bunch of other bugs and memleaks (see the svn log), added
> lazy variations of sql/msql which produce streams instead of (eager)
> lists (pretty useful for dealing with large result sets), and added some
> remarks about how to interface to SQLite via ODBC (I think that's by far
> the most convenient way to get a local database up and running quickly,
> if you don't want to depend on Windows-only stuff).
>

I would rather say you rebuilt the interface from the scratch ;-) .

> Jiri, I'm through with my TODO list (except rechecking the Windows
> port), so I'd say it's about time for a 0.1 release. Anything you still
> want to fix or add?
>

In between I noticed we should change lists of tuples into lists of
lists for columns, primary_keys and foreign_keys as well because
one-element tuples can occur there.

Otherwise, I am happy with the functionality. As regards Windows, it
compiles and works without any problems.

Many thanks,

Jiri

Albert Graef

unread,
Feb 24, 2009, 10:21:36 AM2/24/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Works fine - tested under Windows with MS Access, PostgreSQL and MySQL.

Great. :)

> I would rather say you rebuilt the interface from the scratch ;-) .

Not really. I just got rid of a few unnecessary complications. ;-)

Seriously, you did most of the tedious work on that port. I really
appreciate that!

> In between I noticed we should change lists of tuples into lists of
> lists for columns, primary_keys and foreign_keys as well because
> one-element tuples can occur there.

columns and primary_keys are supposed to always return lists of strings,
foreign_keys always a list of string triples. I don't see why these
should be changed. Can you elaborate, please?

> Otherwise, I am happy with the functionality. As regards Windows, it
> compiles and works without any problems.

I don't recall whether any additional packages are needed to compile and
link odbc apps with mingw, did you have to install anything special for
that?

Albert Graef

unread,
Feb 24, 2009, 10:35:39 AM2/24/09
to pure...@googlegroups.com
Albert Graef wrote:
> columns and primary_keys are supposed to always return lists of strings,

Correction: columns is supposed to return a list of quadrupels.

Yeah, I see what you mean now. The NULLABLE and DEFAULT members in the
columns result may be () if they are "empty". Hmm.

Ok, then we could just turn the tuples in columns and foreign_keys into
lists, that makes some sense. tables should be changed then, too. But
columns? It seems inconvenient to turn a silly list of strings into a
list of 1-lists just for the sake of 100% consistency. ;-)

Albert Graef

unread,
Feb 24, 2009, 10:39:16 AM2/24/09
to pure...@googlegroups.com
Albert Graef wrote:
> But columns? It seems inconvenient to turn a silly list of strings into a
> list of 1-lists just for the sake of 100% consistency. ;-)

s/columns/primary_keys/. I should think before hitting "send". :)

Jiri Spitz

unread,
Feb 24, 2009, 10:54:44 AM2/24/09
to pure...@googlegroups.com
Albert Graef wrote:
>
> columns and primary_keys are supposed to always return lists of strings,
> foreign_keys always a list of string triples. I don't see why these
> should be changed. Can you elaborate, please?
>
You answered yourself before I was able to read this message :-) .

> I don't recall whether any additional packages are needed to compile and
> link odbc apps with mingw, did you have to install anything special for
> that?
>

Nothing else than for Pure itself (with GMP) is required and "CC=gcc
ODBCLIB=-lodbc32" options for make.

Jiri

Jiri Spitz

unread,
Feb 24, 2009, 11:27:02 AM2/24/09
to pure...@googlegroups.com
Albert Graef wrote:
> Correction: columns is supposed to return a list of quadrupels.
>
> Yeah, I see what you mean now. The NULLABLE and DEFAULT members in the
> columns result may be () if they are "empty". Hmm.
>
> Ok, then we could just turn the tuples in columns and foreign_keys into
> lists, that makes some sense. tables should be changed then, too. But
> columns? It seems inconvenient to turn a silly list of strings into a
> list of 1-lists just for the sake of 100% consistency. ;-)
>
In fact, the problem is only with columns - I had some short circuit.
And what about replacing () with a 'null' symbol - it is the usual way
of denoting empty fields in the DB world and we could keep tuples here.

Jiri

Albert Graef

unread,
Feb 24, 2009, 7:53:12 PM2/24/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> In fact, the problem is only with columns - I had some short circuit.
> And what about replacing () with a 'null' symbol - it is the usual way
> of denoting empty fields in the DB world and we could keep tuples here.

Right. I've implemented this now (r987). The special constant is named
odbc::SQLNULL. (Didn't want to shadow ::NULL.)

Let me know how this works for you. The SQL NULL representation is now
encapsulated in the pure_sqlnull/pure_is_sqlnull functions in odbc.c, so
we can easily change it back to () if we want.

In fact, the situation with odbc::columns isn't all that bad anyway. The
only field which can actually become SQLNULL right now is the last one
(the default value), one could also just return an empty string in that
case instead. The 'nullable' field is a string which is supposed to be
the empty string (rather than SQLNULL) if the nullable status of a
column isn't known (which isn't supposed to happen in ISO SQL databases
anyway).

Note that now that we have a dedicated SQLNULL constant, we could also
go back to a tuple representation for the data records if we want. (We'd
have to change the blob representation to something other than a pair,
but that isn't a big deal.)

However, I think that representing data records as lists has some
definitive advantages, such as having the entire arsenal of list
functions and comprehensions available to work on them. And it's also
nice for compatibility with Eddie's csv module which also represents
records as lists.

Opinions?

Albert Graef

unread,
Feb 24, 2009, 7:56:12 PM2/24/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> Nothing else than for Pure itself (with GMP) is required and "CC=gcc
> ODBCLIB=-lodbc32" options for make.

I changed that in the Makefile now, so that no special 'make' options
should be needed. Will test tomorrow.

Jiri Spitz

unread,
Feb 25, 2009, 1:23:24 AM2/25/09
to pure...@googlegroups.com
Albert Graef wrote:
> Right. I've implemented this now (r987). The special constant is named
> odbc::SQLNULL. (Didn't want to shadow ::NULL.)
>
> Let me know how this works for you. The SQL NULL representation is now
> encapsulated in the pure_sqlnull/pure_is_sqlnull functions in odbc.c, so
> we can easily change it back to () if we want.
>
Yes, it works both in result sets and parameter lists.


> In fact, the situation with odbc::columns isn't all that bad anyway. The
> only field which can actually become SQLNULL right now is the last one
> (the default value), one could also just return an empty string in that
> case instead. The 'nullable' field is a string which is supposed to be
> the empty string (rather than SQLNULL) if the nullable status of a
> column isn't known (which isn't supposed to happen in ISO SQL databases
> anyway).
>

There seems to be something wrong with the 'nullable' field - it returns
*always* SQLNULL (or () in older revisions) independently of the 'not
null' flag (even for primary keys, where it is the default).

> Note that now that we have a dedicated SQLNULL constant, we could also
> go back to a tuple representation for the data records if we want. (We'd
> have to change the blob representation to something other than a pair,
> but that isn't a big deal.)
>

It would not be very practical because a tuple with just one member is
reduced to that member itself. So we would need to add special treatment
for result sets with one field only. I'd prefer a uniform way of
processing for all result sets.

> However, I think that representing data records as lists has some
> definitive advantages, such as having the entire arsenal of list
> functions and comprehensions available to work on them. And it's also
> nice for compatibility with Eddie's csv module which also represents
> records as lists.
>

I am of the same opinion.

Jiri

Jiri Spitz

unread,
Feb 25, 2009, 1:40:01 AM2/25/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> There seems to be something wrong with the 'nullable' field - it
> returns *always* SQLNULL (or () in older revisions) independently of
> the 'not null' flag (even for primary keys, where it is the default).
That applies for PostgreSQL. MS Access returns *always* 'YES' instead. :-(

Jiri

Jiri Spitz

unread,
Feb 25, 2009, 1:42:25 AM2/25/09
to pure...@googlegroups.com
Albert Graef wrote:
> I changed that in the Makefile now, so that no special 'make' options
> should be needed. Will test tomorrow.
>
>
I still have to add 'CC=gcc' ;-) .

Jiri

Albert Graef

unread,
Feb 25, 2009, 3:15:48 AM2/25/09
to pure...@googlegroups.com

Works ok over here, with both mysql and sqlite. (sqlite needs to be told
'not null' explicitly, though, even on a 'primary key' field.)

Seems that the PostgreSQL ODBC driver is to blame for the SQLNULLs in
the IS_NULLABLE field. Apparently it doesn't implement all ODBC 3.0
SQLColumns() fields. In such cases you'll just have to use the
inspection capabilities provided by the DBMS itself, 'show columns' or
whatever.

Albert Graef

unread,
Feb 25, 2009, 11:41:01 AM2/25/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> I still have to add 'CC=gcc' ;-) .

I don't. Maybe you have CC set in your environment? Or an old/botched
make version?

Albert Graef

unread,
Feb 25, 2009, 11:53:03 AM2/25/09
to pure...@googlegroups.com
Albert Graef wrote:
> I changed that in the Makefile now, so that no special 'make' options
> should be needed. Will test tomorrow.

Works. Did a few adjustments in the menagerie example, so that ppl don't
need to install one of those hulking databases, only SQLite ODBC is
needed, which is really easy to install on Windows.

Jiri, I'm ready to release. Ok?

Jiri Spitz

unread,
Feb 25, 2009, 12:02:42 PM2/25/09
to pure...@googlegroups.com
Albert Graef wrote:
> I don't. Maybe you have CC set in your environment? Or an old/botched
> make version?
>
I updated to MSYS 1.0.11 which likely has some problems (e.g. broken
'which'). It might be the cause of improper definition of 'CC' as well.

Jiri

Jiri Spitz

unread,
Feb 25, 2009, 12:07:12 PM2/25/09
to pure...@googlegroups.com
Albert Graef wrote:
> Jiri, I'm ready to release. Ok?
>
It works fine for me now. Let us go :-) .

Many thanks,
Jiri

Albert Graef

unread,
Feb 25, 2009, 12:13:41 PM2/25/09
to pure...@googlegroups.com
Jiri Spitz wrote:
> I updated to MSYS 1.0.11 which likely has some problems (e.g. broken
> 'which'). It might be the cause of improper definition of 'CC' as well.

Hmm, I'm running 1.0.11 also, but I did an incremental upgrade IIRC.

Well, just setting CC=gcc in your msys environment should cure it.

Reply all
Reply to author
Forward
0 new messages