fb++: Biblioteca C++ para Acesso ao Gerenciador de Banco de Dados Firebird 1.5 Sérgio Aurélio Ferreira Soares1, Brauliro Gonçalves Leal2, Pedro de Brito Cavalcanti Neto1, Mario Godoy Neto2 1 2 Graduando do Curso de Engenharia da Computação da Universidade Federal do Vale do São Francisco - UNIVASF CEP 48.902-300 – Juazeiro – BA – Brasil Professor do Colegiado de Engenharia da Computação – Universidade Federal do Vale do São Francisco - UNIVASF CEP 48.902-300 – Juazeiro – BA – Brasil {eng.sergiosoares, pdibrito}@gmail.com, {brauliro.leal, mario.godoy}@univasf.edu.br Abstract. The use of database management systems (DBMS's) has become increasingly common in small software solutions. On some occasions, the choice is not to use DBMS in small applications because is necessary to develop a connection interface, which makes the task of software development more costly. From this need, we developed a library in C++ language that aims to facilitate the work of the developer providing a basic set of functions that perform the connection and data obtaining in Firebird 1.5. The two main features of this library are the possibility of use in any platform and the facility to manipulate. The Open Source code is available at www.univasf.edu.br/~brauliro.leal/download.htm. Resumo. A utilização de Sistemas de Gerenciamento de Banco de Dados (SGBD’s) tem se tornado cada vez mais frequente em soluções de pequeno porte. Em algumas ocasiões, opta-se pela não utilização de SGBD’s nessas aplicações devido à necessidade de se desenvolver uma interface de conexão, o que torna a tarefa de desenvolvimento do software mais onerosa. Partindo dessa necessidade, desenvolveu-se uma biblioteca em linguagem C++ que objetiva facilitar o trabalho do desenvolvedor provendo um conjunto básico de funções que realizam a conexão e a obtenção de dados no Firebird 1.5. A biblioteca caracteriza-se por ser multiplataforma, de simples manipulação e Open Source, disponível em www.univasf.edu.br/~brauliro.leal/download.htm. 1. Introdução Muitas organizações possuem grandes volumes de informações e dados que precisam ser armazenados. A utilização do papel se mostra uma alternativa ineficiente e de difícil gestão de tais informações devido à dificuldade na busca por fatos, consolidação, elaboração de relatórios derivados, espaço físico de armazenamento, desgaste pelo tempo entre outras carências. Por essa razão, a partir do surgimento dos computadores, o papel vem sendo gradativamente substituído e o computador apresenta-se como um forte recurso para minimizar esse problema, já que possui entre outras vantagens, eficiência e rapidez na recuperação das informações e facilidade de manutenção. Por muitos anos, utilizaram-se os sistemas de processamento de arquivos que armazenavam os dados e informações permanentes em vários arquivos do sistema operacional. Porém, esse método apresenta diversas desvantagens como, por exemplo, redundância e inconsistência dos dados, dificuldade de acesso, problemas de atomicidade e anomalias de acesso concorrente. Em resposta a tal método, surgiram os Sistemas de Gerenciamento de Banco de Dados (SGBD’s) ou DBMS’s do inglês Database Management Systems como, por exemplo, o Firebird, Oracle, Postgre, SQLite e MySQL. Segundo Elmasri e Navathe (2005), o SGBD é um sistema de software de propósito geral que facilita os processos de definição, construção, manipulação e compartilhamento de bancos de dados entre vários usuários e aplicações. O principal objetivo de um SGBD, de acordo com Silberschatz et al. (2006), é fornecer uma maneira de recuperar informações de banco de dados que seja tanto conveniente quanto eficiente. Esta nova abordagem tem possibilitado a eliminação dos problemas dos sistemas de processamento de arquivos, citados anteriormente, e oferecido novas vantagens para o armazenamento e recuperação de informações. O Firebird, SGBD Relacional open-source, originou-se do Interbase 6, é desenvolvido e mantido por uma comunidade internacional, caracterizado por ser estável, seguro, robusto, de alto desempenho e com excelente suporte a concorrência. Possui arquitetura multigeradora, commit automático em duas fases, sombreamento de banco de dados, replicação, admissão e tratamento de blobs, índices em mapa de bits disperso, colunas vetoriais multidimensionais e subsistema de eventos de alertas. Está em conformidade com os requisitos SQL-92 – ANSI, com extensões próprias para gerenciamento de Generators, Triggers e Stored-Procedures. Suporta integridade referencial declarativa com operações em cascata, visões atualizáveis e outer joins (Firebird, 2011). Outras informações complementares e importantes estão: a) na página da comunidade brasileira, http://www.firebase.com.br; b) no site da comunidade portuguesa, http://www.comunidade-firebird.org; e c) no site da comunidade internacional, http://www.ibphoenix.com. 2. Biblioteca Proposta Uma aplicação que pretende utilizar um SGBD para gerenciar dados necessita, normalmente, de uma interface de acesso que possibilite a conexão da aplicação com o SGBD utilizado. Muitas vezes, desenvolver aplicações que funcionem como interface de conexão, é uma tarefa que torna o desenvolvimento de software mais oneroso. Dessa forma, partindo dessa necessidade, se projetou e desenvolveu uma biblioteca implementada através da linguagem C++ que possibilita a conexão e obtenção de dados no SGBD Firebird versão 1.5 para sistemas de 32 bits. A biblioteca destaca-se por ser multiplataforma, Open Source e apresentar fácil utilização. A proposta inicial dessa biblioteca é prover um conjunto básico de funções, para aplicações simples e que utilizem as operações mais comuns de um SGBD. Sendo assim, na presente versão 1.0 não se implementou, por exemplo, a manipulação de operações sobre alguns tipos de dados como, por exemplo, o tipo Array. 2.1. Visão Geral A biblioteca desenvolvida é composta por duas classes: fbDriver e fbQuery. A classe fbDriver é responsável pela conexão com o SGBD Firebird. A classe fbQuery é responsável por manipular os comandos SQL e possui um conjunto de métodos auxiliares para a obtenção dos resultados de consultas. A aplicação que utilizará a biblioteca, pode instanciar vários objetos da classe fbQuery, de forma a obter resultados de consultas distintas sem a necessidade de sobrescrever a consulta anterior. A Figura 1 mostra uma visão geral da biblioteca proposta. Figura 1 – Visão geral da utilização da biblioteca fb++ 2.2. Métodos da classe fbDriver A classe fbDriver é responsável por se conectar e desconectar a um banco de dados através dos métodos Attach e Detach, respectivamente. O primeiro recebe como parâmetros o nome do usuário, senha e caminho do arquivo que contém o banco de dados. O segundo não possui parâmetros e é responsável por encerrar essa conexão. A Tabela 1 apresenta os métodos e uma breve descrição de suas funcionalidades. Grande parte dos métodos desenvolvidos apresenta relativa complexidade e foram obtidos dos exemplos e manuais disponíveis nos programas de instalação do Firebird e no sítio www.firebirdsql.org. Tabela 1 – Métodos da classe fbDriver Método Descrição bool Attach(char* user, char* psw, Abre o banco de dados de nome “nameBd” char* name ) com o usuário “user” e a senha “psw”. Retorna false se a conexão foi bem sucedida void Detach( void ) Fecha o banco de dados aberto A fbDriver possui ainda dois atributos db e status. O primeiro é o handler da conexão com o SGBD Firebird que é inicializado no método Attach. O segundo é um vetor que guarda as informações da conexão. Esses atributos são úteis no momento da inicialização de um novo objeto da classe fbQuery. 2.3. Métodos da classe fbQuery Objetos da classe fbQuery são responsáveis por executar comandos SQL em uma determinada base de dados que já tenha sido devidamente conectada por um objeto da classe fbDriver. Os protótipos e a descrição de cada método público dessa classe podem ser vistos na Tabela 2. Na seção 3 é apresentado, através de exemplos, o uso da maioria das funções disponíveis, objetivando uma maior compreensão. Tabela 2 – Métodos públicos da classe fbQuery Método bool Open ( ISC_STATUS*, isc_db_handle& ) bool Close ( void ) bool Fetch ( void ) int Columns ( void ) bool bool bool string SQL ( string ) Commit ( void ) Rollback ( void ) asString ( string ) string asString ( int ) string Varchar ( int ) short Short ( int ) int Int ( int ) long Long ( int ) float Float ( int ) double Double ( int ) string TimeStamp( int ) string Date ( int ) string Time ( int ) string Blob ( int ) int Type ( int ) int Size ( int ) Descrição Conecta um objeto da classe fbQuery a uma base de dados já inicializada por um objeto da classe fbDriver Desconecta um objeto da classe fbQuery de um banco de dados Move o cursor para o próximo registro disponível no resultado de uma consulta Retorna a quantidade de colunas ou campos de uma tabela resultante de uma consulta Envia um comando SQL ao SGBD Autoriza a execução de uma transação em andamento Aborta a execução de uma transação em andamento Recebe o nome de um campo e retorna o seu valor no formato string C++ Recebe o índice de um campo e retorna o seu valor no formato string C++ Recebe o índice de um campo Varchar e retorna o seu valor no formato string C++ Recebe o índice de um campo inteiro e retorna o seu valor Recebe o índice de um campo inteiro e retorna o seu valor Recebe o índice de um campo inteiro e retorna o seu valor Recebe o índice de um campo ponto flutuante e retorna o seu valor Recebe o índice de um campo ponto flutuante e retorna o seu valor Recebe o índice de um campo Date e Time e retorna o seu valor no formato string C++ Recebe o índice de um campo Date e retorna o seu valor no formato string C++ (dd/mm/aaaa) Recebe o índice de um campo Time e retorna o seu valor no formato string C++ (hh:mm:ss) Recebe o índice de um campo binário e retorna o seu valor no formato string C++ Recebe o índice de um campo e retorna um inteiro que o representa (maiores detalhes no método) Recebe o índice de um campo e retorna o seu tamanho em dígitos ou caracteres string Name ( int ) string itos ( int ) string ftos ( double ) Recebe o índice de um campo e retorna o seu nome Converte inteiro para string C++ Converte double para string C++ A classe fbQuery possui ainda métodos e atributos privados, que são utilizados para efetivamente realizar a interface entre a aplicação e o SGBD. O usuário da biblioteca não necessita compreender o objetivo desses métodos e atributos se o seu interesse for apenas a simples utilização da biblioteca. Os atributos privados são apresentados na Tabela 3. Tabela 3 – Atributos privados da classe fbQuery Atributo isc_db_handle db ISC_STATUS *status isc_tr_handle trans isc_stmt_handle stmt XSQLDA *sqlda short double Descrição Handler da conexão com o SGDB Firebird Vetor de atributos da conexão Handler da transação com o SGDB Firebird Handler da sentença SQL Estrutura que permite transferir dados entre a aplicação e o banco de dados columns Número de campos da tabela armazenada em sqlda returned Auxilia o retorno da função Data Os métodos privados da classe fbQuery tem como principal objetivo obter os dados diretamente da API do SGBD Firebird e formatá-los de modo que os métodos disponíveis na Erro! Fonte de referência não encontrada. possam retorná-los ao usuário. Tabela 4 – Métodos privados da classe fbQuery Método void* Data( XSQLVAR* ) void* TimeStamp( XSQLVAR* ) void* void* void* double Date ( XSQLVAR* ) Time ( XSQLVAR* ) Blob ( XSQLVAR* ) Scale ( long*, short ) Descrição Identifica o tipo de dado recebido e aciona funções para a formatação quando necessário Decodifica e formata um dado do tipo TimeStamp Decodifica e formata um dado do tipo Date Decodifica e formata um dado do tipo Time Decodifica e formata um dado do tipo Blob Converte e retorna um dado do tipo double 2.4. Exemplo de uso Para exemplificar o uso da biblioteca fb++ e facilitar o entendimento dos métodos descritos na seção 2.3, criou-se um novo banco de dados que possui apenas uma tabela A, indexada, com os campos conforme descritos na Tabela 5, um generator e uma trigger associada ao campo A0 para torná-lo auto-incremento. A criação dessa base de dados foi feita utilizando o software IBExpert Personal Edition (IBExpert, 2011). Tabela 5 – Domínio dos campos da tabela A utilizada no exemplo Campo A0 A1 A2 A3 A4 A5 A6 Tipo Integer not null Integer Numeric(15,2) Char(26) Varchar(26) Time Date Após a criação da base de dados, é necessário escrever um programa em linguagem C++ que faça uso dos métodos descritos nas tabelas 1 e 2 seguindo uma seqüência de passos obrigatórios. O primeiro passo é a conexão com a base de dados através da instanciação de um objeto da classe fbDriver e a chamada ao método Attach com a passagem dos devidos argumentos (usuário, senha e caminho da base de dados). O segundo passo é a instanciação de um objeto da classe fbQuery e a execução do método Open para a ligação desse objeto ao banco de dados conectado anteriormente. O terceiro passo é a execução de um comando SQL através da chamada ao método também denominado SQL. O quarto passo é executar o método Fetch, para que o cursor seja direcionado ao início do resultado da consulta SQL. Este método retorna true enquanto ainda existem registros no resultado da consulta e a cada chamada avança para a próxima linha da tabela. Para acessar um campo da tabela, basta utilizar alguns dos métodos descritos na Tabela 2 passando como argumento o índice referente à coluna do campo como, por exemplo, Double(0) e asString(4). Esses dois comandos informam a biblioteca, respectivamente, que o usuário deseja o valor do campo double que está na coluna (0) e o valor do campo da coluna (4) convertido em string. Após o término das execuções dos comandos SQL, é recomendado utilizar a função Close, para que a ligação com o banco seja desfeita. Os trechos de programa a seguir apresentam um exemplo completo da execução de todas as etapas. #include <stdio.h> #include "fbDriver.h" #include "fbQuery.h" int main( void ) { fbDriver *db = new fbDriver(); fbQuery *Query = new fbQuery(); if( db->Attach("FB++","fb++","FB++.FDB") ) { printf( "\n :: attach error ::\n" ); getchar(); return 1; } Query->Open( db->status, db->db ); Query->SQL("delete from A"); for( int k = 0; k < 30; k++ ) Query->SQL(" insert into A(A0,A1,A2,A3,A4,A5,A6) values (1,1,1.2,'aaaaa','aaaaa','11:11:11','15.01.2011')"); Query->SQL("select * from A" ); Observe que este trecho de código representa os três primeiros passos descritos anteriormente. Nas duas primeiras linhas instancia-se os objetos das classes fbQuery e fbDriver. Após a verificação de erros na operação de Attach, faz-se a ligação do objeto da classe fbQuery no banco de dados aberto. Observe que o nome da base de dados é FB++, a senha é fb++ e o diretório da mesma é o mesmo do programa executável e possui nome FB++.FDB. As linhas seguintes executam comandos SQL com o objetivo de limpar a tabela e preenchê-la com 30 registros de valores arbitrários. A última linha seleciona todos os registros e campos da tabela A. O trecho de código a seguir, executa o quarto passo para a obtenção e impressão na tela dos dados consultados. while( Query->Fetch() ) { printf( "%d ", Query->Int(0) printf( "%d ", Query->Int(1) printf( "%f ", Query->Double(2) printf( "%s ", Query->Varchar(3).c_str() printf( "%s ", Query->Varchar(4).c_str() printf( "%s ", Query->Time(5).c_str() printf( "%s\n", Query->Date(6).c_str() } ); ); ); ); ); ); ); Observe que as funções para obtenção dos dados possuem os mesmos nomes dos tipos para facilitar a memorização. Uma forma equivalente de executar o trecho de código acima de forma genérica é utilizar a função asString como mostrado a seguir. Query->SQL("select * from A" ); while( Query->Fetch() ) { for( int i = 0; i < Query->Columns(); i++ ) printf( "%s ", Query->asString(i).c_str() ); printf("\n"); } Após a manipulação dos dados, resta executar o método Close e destruir os objetos instanciados: Query->Close(); db->Detach(); delete Query; delete db; printf("\nPressione qualquer tecla para continuar..."); getchar(); return 0; } Este exemplo, juntamente com um projeto para o ambiente de desenvolvimento Dev-C++ está disponível no sítio: www.univasf.edu.br/~brauliro.leal/download.htm. 2.5. Compilando Programas com a Biblioteca fb++ Para compilar programas utilizando a biblioteca fb++, é necessário incluir os arquivos cabeçalho fbDriver.h e fbQuery.h conforme visto no item 2.4. No momento da compilação é preciso vincular os arquivos com a biblioteca do SGBD Firebird, através do arquivo fbclient_ms.lib que se encontra na subpasta lib do diretório onde o Firebird foi instalado. Utilizando o ambiente de desenvolvimento Dev-C++ (Bloodshed, 2011), o usuário pode escolher a opção Project->Project Options escolher a aba Parameters e clicar no botão Add Library or Object em seguida deve-se escolher o caminho da biblioteca do Firebird como, por exemplo, C:\Program Files\Firebird_1_5 \lib\fbclient_ms.lib. Após a inclusão da biblioteca, é necessário adicionar um diretório de inclusão de arquivos. Para tanto, o usuário deve selecionar a aba Directories, clicar em Include Directories e adicionar o caminho da pasta include do Firebird como, por exemplo, C:\Program Files\Firebird_1_5\include. Procedimentos semelhantes podem ser feitos em outros ambientes de desenvolvimento como, por exemplo, o Code Blocks (Code::Blocks, 2011). 3. Conclusão Os sistemas de banco de dados se tornaram ferramentas indispensáveis no cotidiano do mundo moderno. As vantagens oferecidas pelo seu uso, que já atraíam desenvolvedores de aplicações de grande porte, atualmente tem atraído os que produzem aplicações mais simples. Proporcionar uma alternativa para a conexão e obtenção de dados utilizando o Firebird, que ofereça simplicidade e abstração na manipulação, é o principal objetivo deste trabalho, já que muitas vezes, conectar-se a um SGBD é um procedimento que onera o desenvolvimento de software. Sendo assim, propôs-se neste artigo, uma biblioteca em linguagem C++, multiplataforma e de fácil manipulação, que possibilita a conexão e obtenção de dados no SGBD Firebird e implementa as operações mais comuns de um SGBD. Seu código fonte e exemplos de uso estão disponíveis para download gratuitamente no sítio http://www.univasf.edu.br/~brauliro.leal/download.htm. A biblioteca vem sendo utilizada em muitas soluções de software e tem se mostrado útil. 4. Referências Silberschatz, Abraham; Korth, F. Henry; Sudarshan, S. Sistemas de banco de dados. Rio de Janeiro: Elsevier, 2006. Elmasri, Ramez; Navathe, Shamkant B.. Sistemas de banco de dados. São Paulo: Pearson Addison Wesley, 2005. Code::Blocks. The open source, cross platform, free C++ IDE. Disponível em: <www.codeblocks.org>. Acesso em: 17 Fev 2011. Bloodshed. Dev-C++ 5. Disponível em: <www.bloodshed.net/devcpp.html>. Acesso em: 17 Fev 2011. HK-Software. IBExpert KG. Disponível em: <ibexpert.net/ibe>. Acesso em: 17 Fev 2011. Firebird. The RDBMS that's going where you're <www.firebirdsql.org/ >. Acesso em: 17 Fev 2011. going. Disponível em: