Coding for Multiple Databases in C/C++?
scorp1us asks: "I'm working on a project which was coded in C/C++ to use a MySQL database. I've since been ordered to make it work with other databases as well. I found one that was close to what I want, SQLAPI++, but it is not database agnostic. You end up using the same function calls but you also end up having SQL for each database. I'm looking for a product that looks like DirectX, but for databases (DirectX emulates features in software if no hardware acceleration is present.) PHP's ADOdb is what I want, but I need it in C/C++. Has anyone seen something like this? My last requirment that it must work for MySQL, MS SQL server, and Informix, and work under Win32 and Linux."
http://www.unixodbc.org/
Read... Enjoy...
afaik there is very little out there that is truly db agnostic
i have coded in Windoze using ODBC, it's not hard and there are some good books on the subject to help you through. i am not aware of what there is available across Linux platforms that is ODBC like
The key with ODBC is understanding the two-phase process in communicating with your DB. There are in fact two ODBC drivers, the one that extracts the commands required from the langauge you are coding in and t'other actually communicating that command to the DB engine.
i haven't looked at SQLAPI, but ODBC avoids embedded SQL statements and i suspect embedded SQL statements is what you want to go away from.
Your other problem is the features available from each DB may be very different. I has to work across MSSQL and Access and (initially) any other db. This 'any other db' was rapidly restricted to those that fit the SQL standards. (Note DB2 does not)
I can't this minute recall whether SQL92 has been superceded by SQL 97 (or whether i am getting confused between standards in my old age) but it is worth chasing the standards up so that you can identify standard and non-standard features especially in your existing code. Your existing code may not be agnostic
The way your db is treated in your existing code may / may not work for other db's in exactly the same way.
Good luck
Agnostic via standards?
HTH
I've been working on some projects that will access multiple db servers and took a different approach to it. Since most db servers have different advanced commands, I decided to write specificly for each while making everything else the same. Basicly I create a different project for each db and using conditional defines I keep all access to the database in its own files. So if talking to ms sql I have a complete set of functionality that deals with ms sql. For oracle I have a different set of functionality, and so on for each server. I end up with a different program for each db server.
If you are never going to have a large set of users hitting the sql server at once then it should be ok to go generic, but if the user base is going to be larger then I don't see how you can avoid using db server specific commands to increase performance and minimise overworking the server.
I'm sure there are other easier ways to pull it off but I like quality and feel the extra work is justified to make it run well on every server I choose to support. Hope this gives you some help in figuring out what you want to do.
If ignorance is bliss, the world is full of blissful people
SQL Relay does this (site looks like it is down at the moment so I'm pointing to the google cache). It is a persistent database connection pooling, proxying and load balancing system for Unix and Linux supporting ODBC, Oracle, MySQL, mSQL, PostgreSQL, Sybase, MS SQL Server, IBM DB2, Interbase, Lago and SQLite with APIs for C, C++, Perl, Perl-DBD, Python, Python-DB, Zope, PHP, Ruby, Ruby-DBD and Java, command line clients, a GUI configuration tool and extensive documentation. The APIs support advanced database operations such as bind variables, multi-row fetches, client side result set caching and suspended transactions. It is ideal for speeding up database-driven web-based applications, accessing databases from unsupported platforms, migrating between databases, distributing access to replicated databases and throttling database access.
It strikes me that SQL is a standard. Yes, the TRANSPORT of the SQL changes according to the database, but the SQL is, well... SQL.
So, that's the way I designed my database connector. Standardize the transport, and send SQL. Of course you keep the SQL you are using to the common base (what is it now, AFAIK SQL92, but I am not going to bother to look it up).
Otherwise, the use of SQL itself doesn't make sense. Look at an analogy: you are putting a scripting language into your application, and you choose an ANSI standard. Say (to be obscure), REXX. Now, different REXX vendors have different ways of linking in your scripts, so you loose faith. Instead of replacing REXX, you decide to write a Perl to REXX translator. Well... you go and BUY this thing from someone else. The claim is that this is a "universal" solution, because no matter HOW the REXX transport changes or someone modifies the ANSI standard language, you won't have to change your code. On the other hand, the translator itself is incomplete, and the vendor changes it 3 times a year forever (this actually happens, I have lost count on the number of times Microsoft has rolled out a new database connector!).
You should look at what SQL you intend on using, and check if the various vendors support that subset. Maybe ensure that you are using ANSI SQL. If the SQL database vendors AREN'T support ANSI SQL, take them to task! You shouldn't have to be buying additional software to make up a lack of support for the standard. And when this is true, the actual transport issue can be easily solved by your existing shim.
Ratboy.
Just another "Cubible(sic) Joe" 2 17 3061
RogueWave's SourcePro DB is basically what you're looking for, and RogueWave is fairly well known in the C++ comminity. The only caveat for you is that it directly doesn't support MySQL. It does however support Oracle, Sybase, MS SQL, Informix, and DB2. It also supports generic ODBC on the back, and I'm pretty sure there's an ODBC interface for MySQL out there - so you could use it that way.
11*43+456^2
Do the database abtraction yourself (I'll tell you why later..).
the code should be compartmentalised so there's a switch somewhere (either runtime of compile time) thats says - for this database do that to get the data I need in the datastructure (or put the data into the ddb).
Now as to why....
most RDBMS's have wonder extentions to SQL and difference ways of doing this. In order to optimise a certain query or insert/update you'll have to to mangle the SQL accordingly. Also some make heavy used of stored procedures for optimising techniques and others have no idea of a SP.
It's like porting to code from one language to another - SQL isn't generic enough IMHO to make you RDBMS perform at a consistent rate of knots.
Also many Big Iron RDBMS (Oracle, DB2) assume you access to a Database Administor who can monitor the database and keep things ticking over. Others, eg SQL-Server, don't assume this (which can or cannot be helpful) etc etc.
You need to code a db layer. The db layer should handle all the interaction with each database. In one case we used our db layer against db2, oracle, sybase, and another one I think called vsam(?).
The way you would do this is you would have a function to update, delete and insert to each table, and also get and reads. This would get ALL the fields of a table or you could get fancy and find a way to specify the fields of the table.
Something like #include
dbget(usertable, key); or dbread(usertable, key);
Yes something that simeple works. It gets all the fields in the table. If however you don't mind using vargs then you could have it take an sprintf format of dbget(usertable, key, fieldname1, fieldname2) and then get only those fields. This to me would be idea.
Ideally you would have a data dictionary that would store ALL the info on every table and all the fields and their sizes and types. Then using this you could have a perl script or C/C++ program (I'd do a script language a it may be easier IMHO) to read the data dictionary and output the necessary table.dat files that the programmers can then include and generate the necessary sql for the insert, update, delete, etc of the table data, also it would generate the necessary C/C++ API calls like the dbget() fns and the dbread() fns.
This is what most places I have been to do. They way that you update or add means that you need to set the fields in the included table.dat file to what you want and then you call the dbupdate(table); function and it uses the dat data.
In these include files you would have structure declarations that would define the layout of each table. Then the programmer would just need to declare a structure userstable mytable; and then user the db functions. This gives much flexability.
I hope this helps as a starting point.
Only 'flamers' flame!
Bing Bing. Mod that up.
Here's the deal. No matter what abstraction you use, you have to code for the lowest common denominator. This means that even if a DB supports subselects, you can't use it. Ditto for features like MySQL's "LIMIT" and such. Transactions? Forget em. You will also need to use only a limited set of data types.
This also means that you will have to emulate most advanced features yourself (which can DRASTICALLY complicate your project.)
A side effect is also that you won't be able to take advantage of many of the performance enhancing features of different databases, meaning that your code may run THOUSANDS of times slower depending on the DB, schema, etc. than if you supported a limited set of databases directly in your code.
I guess it all depends what your needs are, and what tradeoff's you can handle. But you do need to ask yourself the question: Is it truely worth it? Many of the large application vendors require a specific DB for all the issues described above and by other people.
With gcj, you can compile JDBC from java to
native code that can be transparently called
by C++ -- transparent modulo the run-time setup
call in your program's main(), that is.
Works slick. Use the mingw32 target of gcc 3.2
for Win32 platforms.
-I like my women like I like my tea: green-