SqliteClass
Usiamo SQLite con il c++

Data

by "Pnluck"

 

06/10/05

UIC's Home Page

Published by Quequero

Si prega la gentile clientela di donare qualcosa alla UIC

Bello il wrapper!

Si prega la gentile clientela di donare qualcosa alla UIC

....

Home page (se presente): http://pnluck.altervista.org
E-mail: [email protected]
Nick, UIN, canale IRC/EFnet frequentato

....

Difficoltà

(x)NewBies (x)Intermedio (x)Avanzato (x)Master

 


Introduzione

In questo articolo mostrerò come utilizzare SQLite tramite SqliteClass, un wrapper creato da Gianni Rossi e da me; vi mostrerò come creare un nuovo db, inserire e prelevare i field, etc...
PS: La lettura del tute richiede una conoscenza base dei comandi SQL.

Tools usati

Compilatore c++ (io ho usato il devcpp)
SqliteClass
SQLite

Essay

Per prima cosa, iniziamo dall'installazione dei componenti sui compilatori:
Iniziamo col coding. Creamo un nuovo progratto c++, per poi nel devcpp aggiungere cm opzioni di linking: -lsqlite3, il file SqliteClass.a; mentre nel vc basta aggiungere cm dipendenza sqlite.lib e SqliteClass.a, ed infine inseriamo nella cartella sqlite.dll (servirà per le import). Ora inseriamo un nuovo file c++
 
#include <iostream>
//dico al compilatore di usare questo header
#include "SqliteConnection.h"
using namespace std;
//e di usare il namespace SqliteClass
using namespace SqliteClass;

int main()
{
   //puntatore alla classe che serve per la connessione ad un db
    SqliteConnection* aConn;

//alloca dinamicamente l'oggeto SqliteConnection

aConn = new SqliteConnection();
//Open(char*) se è presente apre il database, altrimenti lo crea
aConn->Open("test.sqlite3");

//Ora creamo una nuova tabella
try
{
  //BeginTrans è usato per effetture i cambiamenti direttamente     su file e non in memoria
   aConn->BeginTrans();

   //Execute(string): permette di usare i comandi sql
  aConn->Execute("create table MiaTabella values(field1 text,   field2 text)"); 

  aConn->Execute("insert into MiaTabella (field1,field2) values   ('ciao','bello')"); 

  //Chiudiamo la transizione
  aConn->CommitTrans();
       
 }
catch (...)
 { 
       cout << "Si è verificato un errore";
 }

    //Close(); chiude la connessione al databse
    aConn->Close();
    delete aConn;      
    system("PAUSE");
  
    return 0;
}
Nel codice precedente abbiamo usato solo tre finzioni messe a disposizione dal wrapper(oltre a BeginTrans e CommintTrans): Open per creare un databese, Execute per creare una tabella ed inserirgli dei valori e Close per chiudere la connessione.
Il wrapper supporta due modi d'uso di Execute : Execute(string) e Execute(string, RecordSet). Il secondo modo serve quando si effettua un comando sql che ci deve restituire dei valori (es "select") e RecordSet � l'oggetto che andrà a contenere i record ricavati
.
#include <iostream>
//dico al compilatore di usare questo header
#include "SqliteConnection.h"
using namespace std;
//e di usare il namespace SqliteClass
using namespace SqliteClass;


//Funzione che stampa a video gli errori
void printexception(SqliteException ex)
{
cout << "\nAN ERROR HAS OCCOURS...." << "\n" ;
cout << "STATEMENT : " << ex.GetStatement() << "\n" ;
cout << "ERROR NUMBER : " << ex.GetErrNumber() << "\n";
cout << "ERROR DESCRIPTION : " << ex.GetErrDescription() << "\n\n\n" ;
}

int main()
{
    //puntatore alla classe per la connessione al db
    SqliteConnection* aConn;
    //Puntatore alla classe che andr� a contenere i Record
    SqliteRecordSet* aRecordSet;

//alloca dinamicamente l'oggeto SqliteConnection

aConn = new SqliteConnection();
//Open(char*) se è presente apre il database, altrimenti lo crea
aConn->Open("test.sqlite3");

//Ora creamo una nuova tabella
try
{
   //Execute(string,SqliteRecord)
  aConn->Execute("select * from test",aRecordSet);
       
     }
    catch (...)
    { 
       printexception(ex);
    }

    //###Ora andiamo prelevare tutti i record prelevati###

    //IsEmpty verifica se sono stati prelevati dei record
     if (!aRecordSet->IsEmpty())
     {
     //MoveFirst ci fa posizionare al primo record prelevato
     aRecordSet->MoveFirst();
     //Il ciclo avviene finch� non arriviamo all'ultimo record
     while (!aRecordSet->EndOfRecordSet)
     {
        try
          {
              //FildValue(n) preleva il valore contenuto nella colonna
              cout << aRecordSet->FieldValue(0) << " ";
              cout << aRecordSet->FieldValue(1) << "\n";
          } catch (SqliteException ex) { printexception(ex); }

         //MoveNext ci sposta al prossimo record
         aRecordSet->MoveNext();
     }

     }
     else
     {
         cout << "No records found!!\n";
     }


    //Close(); chiude la connessione al databse
    aConn->Close();
    delete aConn;      
    system("PAUSE");
  
    return 0;
}

Con questo codice apriamo il db precedentemente creato ed stampiamo a video tutti i suoi record. Le funzioni usate le ho gi� spigate nel source, vi informo solo che alla funzione FieldValue oltre ad int, si può passare anche il nome del field se lo conosciamo (in string). Ora vi mostro alcune funzioni che vi posso semplificare la vita, nel qual caso non sappiate il numero di field presenti:

  ColumnsCount(): restituisce il numero di field. Ecco un esempio che può essere usato nel ciclo while:
       for(int i=0;i < aRecordSet->ColumnsCount(); i++) { aRecordSet->FieldValue(i); }

  Oltre a MoveNext e MoveFirst vi sono anche: MovePrev, MoveLast e MoveTo(n).

Come vedete � intuibile l'uso di ogni funzione messaci a disposizione dal Wrapper, cmq vi sono altre funzione non menzionate in questo breve articolo che servono ad effettuare il dump del database su file, la rimozione di una colonna da un tabella, ed alcune funzioni molto interessanti, qualora non si sappia la struttura del db (tipo numero e nomi delle tabelle presenti), e si voglia comunque aprirlo ed usarlo: GetTableInfo e AllTable. La lista di tutte le funzioni � al sito ed alcuni esempi al forum, oppure vi potete spulciare i file .h del wrapper :D
                                                                                                                 Pnluck

Note finali

Come vedete il wrapper � semplice ma allo stesso tempo ha funzioni molto avanzate.
Ringrazio Gianni per avermi permesso di sviluppare il wrapper con lui, e poi tutti quelli di Pmode e della Uic .

Disclaimer

Vorrei ricordare che il software va comprato e  non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.