Interest in an ODBC library?

Hi all, I'd like to gauge interest in an odbc wrapper library. I am currently writing one and the most important difference to other libraries I've seen is the ease with which my library allows binding variables to odbc columns and parameters. Given a table in the database named 'my_table' and a struct my_table, this would be the shortest code to retrieve all rows of that table and do something with them: odbc::table t; my_table data; t.bind(data); //!!! This does all the binding! t.open(); while (t.fetch().ok()) { } Note that this is the full, actual working code, not pseudo code. I have *not* omitted any function arguments. The only thing thats missing is setting the DSN and credentials for the default connection (see below). 'bind' makes use of another library 'data adapters', which allow writing runtime generic methods. I hope to make a separate announcement shortly, once I get my sourceforge CVS connection going agan. In the meantime, have a look at http://tinyurl.com/8ctju to get an idea of it. Other features: + ANSI SQL-92 "schema" support + uses DBMS strategy objects that handle DBMS specific functions such as creating a database, creating users and groups etc... + unit tests currently run with MS-Jet, MS-SQL Server 2000, postgres + has a macro 'preprocessor' for SQL statements built in that hides some of the differences between DBMS system. Example: CREATE TABLE abc(id $$SERIAL primary key not null) will expand to INT AUTOINCREMENT with MS-JET but to SERIAL on postgres. That way you can have one script that works with different databases. + always tries to fail gracefully if a feature is not supported by a specific DBMS Any interest? Best regards Hajo Two examples: Example ONE: Given this struct definition, which mirrors the table definition struct my_table { int m_id; char m_name[51]; string m_long_textfield; }; LWL_BEGIN_ADAPTER(my_table) PROP(m_id) PROP(m_name) PROP(m_long_textfield) LWL_END_ADAPTER() This is how you'd use the library In your main(), set the login data // set the credentials for the default 'unnamed' connection // all table/statement etc... will use this connection unless // specified otherwise odbc::connection::pool().set("MyDSN", "MyUserName", "MyPassword"); Anywhere use // instantiate my_table struct my_table data; // table uses the unnamed default connection odbc::table t; // bind does the magic. it automatically binds // all my_table member variables to the columns t.bind(data); // open the table t.open(); // fetch the rows while (t.fetch().ok()) { // do something cout << data.m_long_textfield; } // check for errors if (t.last_error().no_error()==false) { cerr << "ODBC error: " << t.last_error().as_string() << endl; } Example TWO: // create a statement with parameter marker statement s("SELECT * FROM my_table WHERE id=?([in]p_id)"); // bind the data to the columns my_table data; s.bind(data); // bind the WHERE parameter long parameter; s.bind(parameter, "p_id"); parameter=5; if (s.execute().ok() && s.fetch().ok()) { // data contains the row WHERE id = 5 cout << data.m_long_textfield; } else cerr << s.last_error().as_string() << endl; -- -------------------------------------------- Lit Window Library - Speed up GUI coding 10x http://www.litwindow.com/library?src=ml wxVisualSetup - integrate wxWidgets into Visual Studio .NET http://www.litwindow.com/Products/products.html?src=ml BugLister - Defect Tracker http://www.litwindow.com/buglister?src=ml Tips & Tricks for wxWidgets & MS Visual Studio http://www.litwindow.com/Knowhow/knowhow.html?src=ml

Hajo Kirchhoff wrote:
I'd like to gauge interest in an odbc wrapper library.
This subject is recurring, with some peaks divided by long periods of complete silence. :)
I am currently writing one and the most important difference to other libraries I've seen is the ease with which my library allows binding variables to odbc columns and parameters.
Given a table in the database named 'my_table' and a struct my_table, this would be the shortest code to retrieve all rows of that table and do something with them:
odbc::table t; my_table data; t.bind(data); //!!! This does all the binding! t.open(); while (t.fetch().ok()) { }
What I don't like in your approach is that you require that there is a type (my_table above) for each different rowset traversal "profile" - this is a table in your case, but why not query just a subset of rows? I have seen an application with a table containing 150 columns (no joke, and add to this joins with other tables) and of course, all queries were interested in only some of the columns - from 2 to 5, typically. Do you require that the application always retrieves all columns? Just imagine a single table with 4 columns - there are 15 different subsets of columns there (not counting the queries with no columns). Now, imagine a table with 10 columns. What about 150? What about joins? You does your approach scale in this aspect? In my humble opinion, a DB library needs to be usable also with the assumption that each query in a program can potentially retrieve a *different* set of attributes (columns).
Note that this is the full, actual working code, not pseudo code.
Take a look at this: http://soci.sourceforge.net/ In the context of Boost, you might be interested in this informal page: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Relational_Da... -- Maciej Sobczak http://www.msobczak.com

Hi,
What I don't like in your approach is that you require that there is a type (my_table above) for each different rowset traversal "profile" -
I don't. This is not required, this is merely an example. For small tables and simple queries its the fastest way. But not the only way.
interested in only some of the columns - from 2 to 5, typically. Do you require that the application always retrieves all columns?
Absolutely not. odbc::statement s("SELECT column1,column2,etc... FROM ..."); is supported of course.
Just imagine a single table with 4 columns - there are 15 different subsets of columns there (not counting the queries with no columns).
Also there does not have to be a 1:1 relationship between the members in my_table and the columns of the table. Subsets are fine. In fact, if you have a table with 150 columns and want to select only a subset of columns, you have a couple of options with my approach. a) write a struct ... containing only a few member variables for those columns you want to select. b) use individual variables to bind them. c) all of the above Another example: odbc::statement s("SELECT one([bindto]a), two([bindto b), sixteen, seventeen, eighteen FROM huge_table"); long a, b; struct some_struct; // has members m_sixteen, ... some_struct data; s.bind(a, "a"); // bind variable a to column one s.bind(b, "b"); // bind variable b to column b // bind all member variables of 'data' to columns // of the same name ... if they exist s.bind(data);
You does your approach scale in this aspect?
It does.
In my humble opinion, a DB library needs to be usable also with the assumption that each query in a program can potentially retrieve a *different* set of attributes (columns).
Absolutely.
Interesting approach. I'll probably steal ideas from it. Thanks for your comments Hajo -- -------------------------------------------- Lit Window Library - Speed up GUI coding 10x http://www.litwindow.com/library?src=ml wxVisualSetup - integrate wxWidgets into Visual Studio .NET http://www.litwindow.com/Products/products.html?src=ml BugLister - Defect Tracker http://www.litwindow.com/buglister?src=ml Tips & Tricks for wxWidgets & MS Visual Studio http://www.litwindow.com/Knowhow/knowhow.html?src=ml

On 7/27/05, Hajo Kirchhoff <mailinglists@hajo-kirchhoff.de> wrote:
Hi all,
I'd like to gauge interest in an odbc wrapper library. I am currently writing one and the most important difference to other libraries I've seen is the ease with which my library allows binding variables to odbc columns and parameters.
Hi, Well I for one am keen on something like this in boost. I was looking around for something similar a while back and toyed with DTL (Database Template Library - http://dtemplatelib.sourceforge.net/dtl_introduction.htm) for a while. DTL had some nice aspects, but also some that I didn't like (especially when I started using it for some "real" work. From first impressions it looks you probably have most of the "nice" parts (like easy binding), and not some of the less attractive parts (like the non-sql interface for querying). A few of things that you may have addressed, but which seem missing from your examples: 1. Higher level MACRO helpers, so you can declare your struct and bind it in the same bit of code (in addition to the two stage approach you already showed). 2. iterator interface over "record sets" (compiant with iterator concepts). 3. As mentioned indirectly elsewhere, ability to bind to variants (preferably one of the existing boost versions), a set of variant tuples of various number, and an associative lookup container of variants as the default recordset type (to fulfill the ADO-like need). WIthout knowing more that's all I have for now - but I'll be watching this thread with interest. Incidentally, the project I was using DTL for previously I have now switched to Java and JDBC, but I may end up JNI'ing back gto C++ for ODBC stuff at a later date. Best regards, [)o IhIL..
participants (3)
-
Hajo Kirchhoff
-
Maciej Sobczak
-
Phil Nash