Bancos de dados/Abstração
Este livro ou módulo precisa ser formatado segundo o modelo wiki e/ou organizado conforme as convenções do Wikilivros. (discuta) Por favor ajude a formatar este módulo de acordo com as diretrizes estabelecidas no livro de estilo. Editor: considere colocar o mês e o ano da marcação. |
Ensaio acerca de bibliotecas de código aberto para abstração de acesso a banco de dados em linguagem C++
Este estudo é um ensaio acerca das ferramentas de programação em linguagem C++ destinadas a fornecer uma camada de abstração para operar indistintamente bibliotecas clientes nativas de servidores de banco de dados. Camadas de abstração de acesso a banco de dados são comuns em plataformas de desenvolvimento e disponíveis em diversas linguagens de programação. Para a linguagem C++ temos algumas opções disponíveis. Esse ensaio introduz o conceito de camadas de abstração e fornece uma analise introdutória de algumas ferramentas consideradas relevantes.
Introdução
editarA metodologia mais utilizada em projetos de aplicativos de acesso a banco de dados é a que faz uso da arquitetura cliente-servidor, onde o aplicativo do usuário acessa um Sistema Gerenciador de Banco de Dados (SGBD), ou servidor de banco de dados, através de uma rede de computadores.
Nessa arquitetura o aplicativo do cliente é responsável por interagir com o usuário através de uma interface gráfica, enviando comandos ao SGBD, que por sua vez é responsável por armazenar e recuperar dados.
Existem diversos SGBD's disponíveis, como Oracle, MySQL, Firebird, etc. Cada um deles utiliza mecanismos próprios de comunicação, autenticação e representação dos dados resultantes das consultas. Ou seja, cada um deles opera segundo protocolos próprios de comunicação e aquisição de dados.
Dessa forma, um aplicativo cliente, aquele que interage com o usuário e opera os dados através do SGBD, deve ser capaz de comunicar-se com o servidor segundo o protocolo de comunicação próprio do SGBD em questão.
Os servidores SGBD normalmente vem acompanhados de softwares (mais especificamente, bibliotecas de programação conhecidas como "bibliotecas cliente") que fornecem funcionalidades para conectar-se ao servidor e realizar operações.
As bibliotecas cliente fornecidas juntamente com um SGBD são compatíveis apenas com o SGBD ao qual estão associadas, sendo incapazes de operar com outros servidores. por isso são também são chamadas de bibliotecas cliente nativas.
O diagrama abaixo representa a arquitetura de um aplicativo que acessa SGBD's através de bibliotecas nativas.
O uso de bibliotecas nativas é defendido por muitos desenvolvedores, mas sua adoção traz varias limitações ao aplicativo que faz uso das mesmas: 1) dependência do SGBD em questão, já que a biblioteca nativa acessa apenas o SGBD para o qual foi criada 2) dependência de plataforma de software e hardware, já que o aplicativo que faz uso da biblioteca nativa poderá operar apenas nas plataformas em que a biblioteca nativa também opera.
Além disso, o uso de bibliotecas nativas torna-se questionável se analisarmos as varias bibliotecas de abstração de acesso a SGBD's existentes para linguagem C++. Bibliotecas de abstração fornecem uma API genérica para acesso aos recursos de diferentes servidores, permitindo independência de SGBD, alem de oferecer diversos recursos extras, métodos próprios para manipulação dos diferentes tipos de dados e, em alguns casos, componentes gráficos para correta apresentação desses dados em interfaces gráficas (GUI´s).
Essas ferramentas são consideradas camadas de abstração, pois fazem uso das bibliotecas nativas de acesso as diferentes fontes de dados, ao mesmo tempo que fornecem ao programador uma única interface de programação, permitindo que diferentes SGBD's sejam acessados e operados de forma indistinta.
O diagrama abaixo representa a arquitetura de um aplicativo que acessa SGBD's através de camada de abstração.
O uso de bibliotecas para abstração de acesso a SGBD' s traz um grande numero de benefícios relevantes, sendo as principais:
1) Independência de SGBD: Uma mesma biblioteca de abstração normalmente opera sobre bibliotecas nativas de vários servidores de banco de dados diferentes. Isso propicia independência de servidor de banco de dados, tornando possível migrar entre diferentes SGBD's sem alterar o código. Essa funcionalidade, mesmo considerada isoladamente, seria suficiente para justificar o uso de camadas de abstração para a grande numero das aplicações.
2) Representação facilitada para tipos de dados: Bibliotecas de abstração de SGBD's normalmente utilizam uma representação genérica para tipos de dados próprios de cada SGBD, fazendo as conversões necessárias e, desse modo, facilitando a portabilidade entre SGBD's diferentes.
3) Uso de recursos modernos da linguagem C++: algumas bibliotecas de abstração fazem uso de modernos recursos de STL e Boost, como conteineres e tipos de dados como o 'tuple' [11]', alem de sintaxe inspirada em streams.
4) Sintaxe facilitada: Algumas bibliotecas fazem uso criativo de polimorfismo e sobrecarga de operadores para permitir operações utilizando sentenças curtas e legíveis, facilitando a criação de instruções SQL e subsequente tratamento dos dados resultantes.
5) Operação em ambiente multi-thread: mesmo que a biblioteca nativa do SGBD não seja thread-safe, a biblioteca de abstração pode cuidar do acesso concorrente permitindo a operação segura em ambientes multi-thread.
6) Conformidade com padrões e independência de plataforma: As bibliotecas apresentadas aqui são concordantes com padrões e, em principio, portáveis entre várias plataformas e compiladores.
7) Manutenibilidade: as bibliotecas estudadas aqui são softwares de código aberto, permitindo manutenção, depuração, extensão e alterações de forma facilitada, caso contrario ao da maioria das bibliotecas nativas de acesso a SGBD's.
8) Funcionalidades inéditas: algumas bibliotecas implementam facilidades que não estão presentes de forma facilitada na biblioteca nativa de acesso ao SGBD
9) Acesso a fontes de dados alternativas: algumas bibliotecas foram projetadas para acessar fontes de dados pouco populares ou não concordantes com a linguagem de consulta SQL, como servidores LDAP, arquivos CSV, MySQL, arquivos Microsoft Access ou bancos de dados Berkeley DB.
10) Criação de sentenças SQL: algumas bibliotecas fornecem ferramentas para facilitar a criação de querys no padrão SQL através de uma metodologia simplificada. Esse método pode gerar consultas otimizadas e adaptadas a cada tipo de servidor de banco de dados em particular a partir de uma construção padrão única.
11) Arquitetura modular: a maioria das bibliotecas de abstração são projetadas segundo uma arquitetura modular, permitindo a criação de extensões para acesso a novas fontes de dados de forma facilitada.
O uso de uma arquitetura de camada de acesso intermediaria aos recursos das bibliotecas nativas (camada de abstração) também oferece algumas desvantagens, sendo as principais:
1) Isolamento dos recursos da biblioteca de acesso nativa: nem todos os recursos da biblioteca nativa podem estar disponíveis através da camada de abstração, que busca reunir o conjunto de funcionalidades presentes na maioria das bibliotecas nativas. Embora normalmente bibliotecas de abstração forneçam acesso direto à biblioteca nativa, essa pratica deve ser evitada, pois vai contra os princípios da utilização de uma camada de abstração, tornando o aplicativo dependente de um SGBD em particular.
2) Overload: as bibliotecas de abstração são uma camada de acesso as bibliotecas nativas e, desse modo, é de se esperar que apresentem alguma perda de desempenho. Entretanto, testes de desempenho realizados pelos criadores de algumas bibliotecas de abstração mostram que essa perda é pouco significativa e não justifica desconsiderarmos o uso dessas ferramentas na grande maioria dos casos. Você deve consultar o site oficial de cada biblioteca para maiores informações sobre desempenho.
Existem diversas bibliotecas multiplataforma para abstração de acesso a SGBD's disponíveis para linguagem C++. Para esta versão deste documento, estudaremos três das ferramentas que consideramos relevantes: GDAmm [1] , SOCI [2] e DBIxx [3].
Outras bibliotecas viáveis são citadas brevemente na conclusão deste ensaio.
GDAmm
editarIntrodução
editarGDA [1], acrônimo para GNU Data Access, é a biblioteca para acesso a banco de dados que integra a plataforma GNU de desenvolvimento, que inclui também uma serie de bibliotecas de programação para diversas finalidades. Como acontece com todas as bibliotecas de programação da plataforma GNU, GDA é desenvolvida utilizando a linguagem C e são desenvolvidas ligações para as mais diversas linguagens de programação. Em nosso caso, faremos uso de GDAmm, que é a ligação em linguagem C++ para a biblioteca GDA. GDAmm [8] é o que chamamos de wrapper, uma camada de abstração em linguagem C++ que faz uso de chamadas a uma biblioteca em linguagem C para realizar suas tarefas. Em outras palavras, GDAmm encapsula as chamadas a GDA, fornecendo acesso as funções da biblioteca em linguagem C através da semântica própria da linguagem C++. Essa arquitetura pode parecer estranha mas é bastante empregada. A ferramenta de abstração DBIxx, por exemplo, também faz uso da mesma arquitetura. GDAmm esta integrado ao toolkit gráfico da plataforma GNU de desenvolvimento, o GTKmm, [4], fornecendo componentes gráficos como tabelas (grids) e formulários para apresentação e edição dos dados retornados das consultas ao SGBD de maneira facilitada, funcionalidade também presente na maioria das plataformas de desenvolvimento populares. Uma questão relevante acerca da plataforma GNU é o fato de a mesma ser mantida pela Free Software Foundation, o que nos da alguma garantia de que essa ferramenta não será descontinuada, mas, pelo contrario, continuara a receber aperfeiçoamentos e correções por um longo período. Como veremos, trata-se de uma biblioteca muito versátil e bastante completa.
Plataformas e backends
editarOficialmente, GDAmm é compatível com as plataformas Windows, Linux, MacOS X e a maioria dos sistemas concordantes com Posix, mas é provável que possa ser utilizado em qualquer plataforma que ofereça um compilador compatível com ISO C++ e disponha da biblioteca STL. Segundo seus manuais, os backends suportados no momento são os seguintes: MySQL, Oracle, PostgreSQL, Berkeley DB, arquivos .mdb (com recursos limitados), SQLite, SQLCipher, JDBC e Firebird. Versões anteriores também acessavam Microsoft SQL, servidores LDAP, Sybase SQL, Xbase e IBM DB2, mas a versão atual de GDA ainda não foi atualizada para operar junto a esses backends.
Principais componentes
editarOs principais componentes de GDAmm são os seguintes:
Gda::Value
Libgda é uma biblioteca nitidamente orientada a dados e baseada em um complexo mecanismo de tipagem dinâmica em linguagem C chamado GObject. O recurso de tipagem dinâmica [5] [6], comum em linguagens interpretadas como Python e PHP, necessita de um método complicado e trabalhoso para uma implementação em linguagem C. Consulte documentação adicional sobre tipagem dinâmica para obter mais informações sobre o assunto. Felizmente, a biblioteca GDAmm opera todos os tipos de dados de libGDA de forma facilitada através da classe Value, sem precisar lidar com o mecanismo de Gobject [6].
O uso correto de tipagem dinâmica pode ser muito útil para tratar dados operados junto aos SGBD's. O problema da arquitetura utilizada em GDA (na verdade, utilizada em todos os projetos que utilizam glib) diz respeito à intenção da biblioteca para tratamento de novos tipos de dados, que envolve a criação de objetos em C utilizando o complicado mecanismo da biblioteca gobject [7]. Value permite tratamento indistinto para diferentes tipos de dados, sendo capaz de realizar diversas conversões entre tipos de dados diferentes. Uma olhada na assinatura da classe nos da uma idéia precisa dos tipos de dados e conversões possíveis. Os tipos dados utilizados são os presentes em glib, que em alguns casos são typedefs para tipos primitivos. Seus correspondentes em linguagem C podem ser deduzidos a partir de seu nome, por exemplo, gchar é um tipo char primitivo, gulong é um unsigned long primitivo, assim por diante.
Construtores:
Value (const Glib::ustring& as_string, GType type)
Value (guint val)
Value (guchar val)
Value (gchar val)
Value (const Timestamp& val)
Value (const Time& val)
Value (const char* val)
Value (const Glib::ustring& val)
Value (gulong val)
Value (gushort val)
Value (gshort val)
Value (float val)
Value (const GdaNumeric* val)
Value (const GdaValueList* val)
Value (int val)
Value (const GeometricPoint& val)
Value (double val)
Value (const Glib::Date& val)
Value (bool val)
Value (const GdaBlob* val)
Value (const guchar* val, long size)
Value (const Value& src)
Value (const GValue* castitem)
Value ()
Métodos:
const guchar* get_binary (long& size)
const const GdaBlob* get_blob ()
const bool get_boolean ()
const Glib::Date get_date ()
const double get_double ()
const float get_float ()
const Gtype get_g_type ()
const GeometricPoint get_geometric_point ()
const Glib::RefPtr<const Glib::Object> get_gobject ()
int get_int ()
const gint64 get_int64 ()
const const GdaValueList* get_list ()
const GdaNumeric* get_numeric ()
const gshort get_short ()
const Glib::ustring get_string ()
const Time get_time ()
const Timestamp get_timestamp ()
const guint get_uint ()
const guint64 get_uint64 ()
const gulong get_ulong ()
const gushort get_ushort ()
const Gtype get_value_type ()
const bool is_null () const bool is_number ()
const bool operator!= (const Value& src)
const Value& operator= (const Value& src)
bool operator== (const Value& src)
const void set (guint val)
void set (guchar val)
void set (gchar val)
void set (const Timestamp& val)
void set (const Time& val)
void set (const char* val)
void set (const Glib::ustring& val)
void set (gulong val)
void set (gushort val)
void set (gshort val)
void set (float val) void set (const GdaNumeric* val)
void set (const GdaValueList* val)
void set (int val)
void set (const Glib::RefPtr<Glib::Object>& val)
void set (const GeometricPoint& val)
void set (double val)
void set (const Glib::Date& val)
void set (bool val)
void set (const GdaBlob* val)
void set (const guchar* val, long size)
void set_g_type (GType val)
void set_int64 (gint64 val)
void set_uint64 (guint64 val)
É obrigação do programador utilizar operações coerentes para conversão de dados, já que uma grande quantidade de tipos de dados incompatíveis é operada.
Espera-se que objetos do tipo Value sejam usados em conjunto com os outros objetos de GDAmm para entrada e recuperação de dados, embora tipos primitivos também possam ser usados em muitos dos casos.
Gda::Query
A classe query permite a definição de consultas através do uso de objetos que definem de forma genérica as operações, condições e tabelas que compõe uma consulta, gerando como saída uma string contendo uma query otimizada para o backend (SGBD) em uso. Seu propósito é fornecer uma interface de programação genérica para criação consultas apropriadas para as diferentes fontes de dados , lidando com limitações e diferenças na implementação da linguagem SQL de cada servidor em particular, gerar consultas otimizadas, assim como perimir acesso a fontes de dados incompatíveis com SQL. Sua adoção favorece a portabilidade entre SGBDs e seu uso é recomendado, embora a biblioteca permita a especificação direta da string de consulta, sem o uso dos recursos dessa classe.
Os principais objetos para programação de uma query são: GdaQueryTarget, que representa as tabelas a serem operadas, QdaQueryJoin, que especifica a operação de mesmo nome (join), e GdaQueryCondition, que representa uma condição (clausula WHERE). Consulte a referencia de GDAmm para exemplos de uso dessas classes.
Gda::Conection
Objeto que realiza a conexão com o SGBD, realiza as operações no banco e controla as transações de forma transparente. Tem métodos para especificação dos parâmetros de conexão com o banco, como set_username , set_password e set_dsn para especificação de usuário, senha e nome do banco, respectivamente. Os métodos execute_select_command(string) e execute_nom_select_command(string) são os principais métodos para realizar operações no banco de dados. Outras funcionalidades incluem acesso a alguns metadados e controle de transações. Um recurso interessante e utilização das funcionalidades de libsig++ para implementar um sistema de sinais e slots para associação de tratadores dos eventos de conexão, desconexão ou abertura de novo banco de dados. O objeto Gda::Connection retorna os dados da consulta em modelos de dados derivados de Gda::DataModel, estudados a seguir
Gda::DataModel A biblioteca cliente de cada SGBD em particular retorna dados estruturados de uma forma diferente, de modo que umas das funcionalidades mais importantes para permitir operação indistinta entre diferentes fontes de dados é um mecanismo que permita acessar os dados resultantes das consultas de uma forma genérica, independe do formato fornecido pela biblioteca cliente nativa do banco de dados em uso.
Gda implementa um modelo de dados bastante simples para representar dados de diferentes tipos em linhas e colunas (uma tabela), fornecendo dois métodos diferentes para recuperação de dados: através de seu índice ou através de um iterador.
Através do uso desse modelo de dados padrão, operamos os dados resultantes de operações no banco de uma forma única, seja qual for o formato nativo fornecido pela biblioteca cliente em uso.
Objetos gráficos (widgets)
O ambiente de desenvolvimento GNU oferece objetos de interface gráfica (visões) para visualização e manipulação dos dados em um modelo de dados Gda::DataModel usando arquitetura MVC. Essa funcionalidade é comum em ambientes de desenvolvimento populares. Inicialmente, GDA era integrante da biblioteca GNOME-DB, que incluía também os componentes gráficos de visualização de dados. Recentemente foi criado um projeto separado para tratar do desenvolvimento dos objetos gráficos (widgets), o projeto libgda-uimm. No presente momento, nem todos os componentes presentes em gnome-db foram portados, e houve mudanças na API.
Os principais componentes gráficos são:
Gda::Grid: Um componente semelhante aos existentes em muitas plataformas de desenvolvimento, que recebe como argumento um modelo de dados resultante de uma consulta ao SGBD e os apresenta em um objeto gráfico na forma de tabela (linhas e colunas) de forma automática.
Gda::Form: Componente para representação de dados contidos em um Gda::DataModel, mas apresentando um registro por vez, na forma de um formulário.
Gda::DataEntry: Componente de edição de texto para entrada e edição de dados de diferentes tipos, como valores numéricos, booleanos, strings e data.
SOCI
editar1. Introdução
editarSOCI [2] é um acrônimo para “Simple Oracle Call Interface” e foi criada inicialmente para fornecer uma camada de abstração facilitadora para acesso ao banco de dados Oracle. Com o passar do tempo, novos backends foram adicionados e, em sua versão atual, os bancos de dados suportados são Oracle, MySQL, PostgreSQL, SQLite3, Firebird e ODBC, operando sobre as plataformas Linux e Windows. Conforme citado no site oficial da biblioteca [2], “SOCI cria a ilusão de embarcar consultas SQL em código C++ comum, permanecendo inteiramente compatível com STL”, “A idéia é prover aos programadores em C++ uma maneira de acessar bancos de dados SQL da maneira mais natural e intuitiva”.
De fato, o que chama a atenção em SOCI são suas criativas e redundantes maneiras para especificar instruções SQL e acessar os dados resultantes dessas consultas.. Podemos usar estruturas, tipos primitivos, utilizar tipos tuple [11] (de BOOST) ou receber os dados em objetos através de um método de mapeamento objeto-relacional. Um dos métodos possíveis, baseado em streams, bastante criativo e funcional, serviu de inspiração para o método de acesso utilizado em DBIxx, outra biblioteca de abstração incluída neste ensaio. SOCI está na versão 3.1, que foi disponibilizada em 2011, e vem sendo ativamente desenvolvida desde 2004.
Principais componentes
editar- soci::session Estabelece uma conexão com o servidor de banco de dados e fornece diferentes métodos para realização de operações em linguagem SQL. Um dos métodos é a especificação de strings de instruções SQL baseado na sintaxe de streams, utilizando o operador de intração “<<” e dois métodos para associação de dados:
- soci::into() especifica o destino dos dados resultantes de uma operação no banco
- soci::use() Usado para fácil associação de uma variável local a string SQL.
O objeto de conexão pode receber argumentos de conexão de varias formas, uma delas usando uma sintaxe parecida com objetos de conexão de outras bibliotecas:
<objeto-de-conexao> nome_objeto (“nome do backend”, “argumentos”);
… o que resulta em:
soci::session sql ( “mysql”, ”db=teste user=root password='senha' ” );
O objeto session criado com soci::session é então usado para operações no banco, de várias maneiras, entre elas, são válidas operações como:
sql << "drop table persons";
sql << "delete from person where id = " << 100;
Podemos compor uma string de operação SQL de maneiras diferentes utilizando soci::use para associar dados de variáveis locais a string resultante, como no exemplo seguinte:
string firstName = "John", lastName = "Smith";
int personId = 7;
sql << "insert into person(id, firstname, lastname) values(:id, :fn, :ln)",
use(firstName, "fn"), use(lastName, "ln"), use(personId, "id");
Também podemos recuperar os dados resultantes de consultas de maneiras distintas. Operações que retornam apenas um valor podem ser especificadas assim:
std::string name;
sql << “select name from numbers where id=10 ", into(name);
Para recuperação de múltiplos registros podemos recuperar registros seqüencialmente utilizando a classe soci::statement e seus métodos execute() e fetch(), como o código seguinte:
std::string name;
statement st = (sql.prepare << "select name from consumers", into(name));
st.execute();
while (st.fetch())
{
std::cout << name << '\n';
}
Outro método para recuperação de dados de múltiplos registros utiliza-se do objeto soci::row, que funciona de maneira parecida a um vetor STL, operando com iterador. Seu funcionamento segue um padrão parecido ao presente em outras ferramentas, por isso não trataremos desse método aqui.
Há também um método que consideramos muito simples e prático baseado na classe tuple da biblioteca BOOST [11], consulte a página oficial de SOCI para informações sobre o uso desse método[2].
DBIxx
editarIntrodução
editarDBIxx [3] , assim como GDAmm, também é um wrapper, que no caso, encapsula a biblioteca DBI [9] . Inspirada na sintaxe da biblioteca SOCI [3], DBIxx também oferece ferramentas de fácil utilização para criação de consultas SQL e tratamento de dados. É uma difícil decisão de projeto escolher entre a adoção de DBIxx e SOCI, já que as mesmas têm API's extremamente semelhantes. DBI (e conseqüentemente DBIxx) opera sobre Firebird, Interbase, MySQL, PostgreSQL, Sqlite3, alem de MS SQL e Sybase através da biblioteca FreeTDS [10].
Principais Componentes
editarParte considerável dos objetos de DBIxx tem correspondente na API de SOCI, às vezes utilizando o mesmo nome. Tendo SOCI como referencia, o exemplo abaixo é praticamente auto-explicativo.
using namespace dbixx; using namespace std;
int main(){
try {
session sql("sqlite3:dbname=test.db;sqlite3_dbdir=./");
sql<<"DROP TABLE IF EXISTS users";
sql.exec();
sql<<"CREATE TABLE users ( "
" id integer primary key not null, "
" name varchar(128) not null "
");";
sql.exec();
sql<<"INSERT INTO users(id,name) VALUES(?,?)",
1,"Moshe",exec();
sql<<"INSERT INTO users(id,name) VALUES(?,?)",
2,"Yossi",exec();
sql<<"SELECT name FROM users WHERE id=?",1;
row r;
if(sql.single(r)) {
string name;
r>>name;
cout<<name<<endl;
}
else {
cout<<"No user with id="<<1<<endl;
}
result res;
sql<<"SELECT id,name FROM users";
sql.fetch(res);
cout<<"There are "<<res.rows()<<" users\n";
while(res.next(r)) {
int id;
string name;
r>>id>>name;
cout<<id<<"\t"<<name<<endl;
}
}
catch(std::exception const &e) {
cerr<<e.what()<<endl;
return 1;
}
return 0;
}
Ao primeiro olhar percebemos uma sintaxe ligeiramente diferente para composição de strings de instruções SQL, alem necessidade de chamar o método exec() parar efetivamente realizar as operações, mas percebemos também a sintaxe básica de SOCI.
Para realizar a conexão com o banco, temos um objeto de mesmo nome, mas com passagem de parâmetros ligeiramente diferente:
session sql("sqlite3:dbname=test.db;sqlite3_dbdir=./");
O uso de intratores para especificar instruções SQL ao objeto de conexão:
sql<<"DROP TABLE IF EXISTS users";
E um mecanismo de recuperação de dados parecido com o utilizado através das classes soci::statement e statement.fech() de SOCI, utilizando o objeto dbixx::result juntamente com método result.next():
soci::result res; sql<<"SELECT id,name FROM users"; sql.fetch(res); while(res.next(r)) { (…) }
Outras ferramentas
editarCppDB: http://art-blog.no-ip.info/sql/cppdb/intro.html
Outra ferramenta claramente inspirada em SOCI. Teve ultimo release em 2011 e, em principio, pode ser uma ferramenta viavel, necessita de estudo e teste. Opera sobre MySQL, PostgreSQL, Sqlite3 e ODBC, nas plataformas Linux e Windows.
QT é um framework de desenvolvimento multiplataforma. Fornece uma grande quantidade de funcionalidades diversas, incluindo camada de abstração de acesso a banco de dados e componentes graficos (widgets) para apresentação de dados resultantes de consultas ao banco da dados, utilizando a arquitetura MVC.
GQL http://gql.sourceforge.net/drivers.html
GQL suporta os bancos de dados MySQL, PostgreSQL e Sqlite, sua documentação é muito precaria, sabemos que utiliza glib e seu ultimo release foi feito em 2003 (obsoleto?)
DTL http://dtemplatelib.sourceforge.net/
Database Templete Library é baseada em ODBC e containeres SQL. Solução a ser considerada se voce prefere tratar tados como containeres e não se importa em estar limitado ao uso de ODBC.
SPTK http://www.sptk.net/index.php
Simply Powerfull Toolkit é uma biblioteca de abstração associada ao toolkit grafico fltk [12] e fornece componentes de conexao, operacao e tratamento de dados no acesso a servidores de banco de dados, fornecendo componentes graficos para visualização e edição de dados utilizando os componentes do toolkit gráfico FLTK. Infelizmente essa ferramenta é bem pouco documentada, o que dificulta sua análise.
OUTRAS...
Certamente existem outras bibliotecas de código aberto para abstração de acesso a bancos de dados disponiveis, procuramos citar as mais relevantes. Lembre-se que foram consideradas apenas ferramentas multiplataforma de código aberto para linguagem C++ que operam sobre multiplos backends. Ferramentas que operam sobre apenas um backend, como mysql++, foram desconsideradas. Gostariamos de lembrar que esse documento é um ensaio, você pode contribuir com alterações, correções e extenções atraves do mecanismo Wiki em:
Referências
editar[1] (libgda) http://developer.gnome.org/libgda/4.2/
[2] (soci) http://soci.sf.net
[3] (DBIxx) http://art-blog.no-ip.info/wikipp/en/page/ref_dbixx
[4] (GTKmm) http://www.gtkmm.org/
[5] http://en.wikipedia.org/wiki/Type_system#Dynamic_typing
[6] http://developer.gnome.org/gobject/stable/chapter-gtype.html
[7] http://en.wikipedia.org/wiki/GObject
[8] http://ftp.gnome.org/pub/GNOME/sources/libgdamm/
[9] http://libdbi.sourceforge.net/
[10] http://freetds.sourceforge.net/
[11] http://www.boost.org/doc/libs/1_35_0/libs/tuple/doc/tuple_users_guide.html
[12] http://fltk.org