Thomas Kramer

IT-COW | All posts tagged 'Firebird'

Ansteuerung von Firebird-Datenbanken aus C++

By Administrator at Mai 25, 2011 12:07
Filed Under: C(++), Studium

Im Studium sollten wir aus C++ die Ansteuerung einer Firebird-Datenbank nachvollziehen.

 

Es handelt sich hierbei um ein einfaches Konsolen-Menüprogramm; es können Datensätze aufgelistet und geändert werden. Das Programm referenziert die Beispieldatenbank employee.fdb von Firebird und benutzt das IBPP-C++-Interface für Firebird Server.

 

Die grundsätzliche Vorgehensweise zur Einbindung von IBPP ist folgendermaßen:

 

  • Alle CPP-Dateien - außer all_in_one.cpp - ins Projekt einbinden -> in Code::Blocks unter Project/Add files.
  • Die ibpp.h-Headerdatei mit #include "IBPP/core/ibpp.h" ins Projekt einbinden -> Pfad natürlich anpassen, falls nötig.
  • Im Projekt mit #define IBPP_WINDOWS dem IBPP-Framework mitteilen, das das Programm unter Windows kompiliert wird. Wichtig: Muss vor dem include der ibpp.h-Datei aufgelistet sein.
  • Mit using namespace IBPP alle Methoden dem Compiler bekannt machen -> ansonsten muss vor den Methodenaufrufen C++-typisch immer ein Präfix für den Namensraum (in diesem Fall IBPP, gefolgt von ::) - in dem die referenzierten Klassen enthalten sind - eingefügt werden.

 

Eine kleine Ergänzung noch, weil ich eben darüber gestolpert bin:

 

funktioniert:

      string sqlstring=(string) ("SELECT * from country where country=")+ "'"+ Personen.Job_Country+ "'";     

      string sqlstring="SELECT * from country where country='"+ Personen.Job_Country+ "'";

 

funktioniert nicht:

      string sqlstring="SELECT * from country where country="+ "'"+ Personen.Job_Country+ "'";

 

Eine Textzeile, gequotet mit Anführungszeichen, ist in C++ eigentlich ein char[]-Array - eine Zuweisung an einen string-Datentyp funktioniert aber auch ohne Casten. Eine Verkettung zweier char[]-Arrays mittels des Verkettungsoperators + ist aber nicht (direkt) möglich - zwischen einem char[]-Array und einem string dagegen schon. Wenn man zwei char[]-Arrays mittels + verketten will - direkt aufeinanderfolgend -, muss man eines davon vorher nach string casten.

 

Übrigens ist das einfache Anführungszeichen ' das Quotungszeichen von Firebird; wenn man auf Zeichenketten abfragen will müssen diese damit umklammert (gequotet) sein - bei Zahlen ohne alphanumerische Zeichen kann auch darauf verzichtet werden.

 

SYSDBA ist der Standard-Administrator-Benutzer von Firebird, mit dem Standard-Passwort masterkey. Den Windows-Benutzer thomas wird es bei euch vermutlich nicht geben, demnach müssen die Pfade bei euch natürlich angepasst werden - je nachdem, wo bei euch diese Firebird-Beispieldatenbank liegt.

 

#define IBPP_WINDOWS

/* includes in <> spezifizieren Standard-Include-Dateien, die in "" vom Programmierer
   bereitgestellte Include-Dateien
   http://www.imb-jena.de/~gmueller/kurse/c_c++/c_includ.html */

#include <stdio.h>
#include <windows.h>
#include <iostream>
#include <iomanip>
#include "IBPP/core/ibpp.h"

using namespace std;
using namespace IBPP;

int menu();
void Datensaetze_lesen();
void Datensatz_aendern(string last_name, string first_name, string hire_date);

const char* DbName = "C:\\Users\\thomas\\Documents\\EMPLOYEE.FDB";  
const char* BkName = "C:\\Users\\thomas\\Documents\\EMPLOYEE.FBK";
const string ServerName = "localhost";
const string UserName = "SYSDBA";
const string Password = "masterkey";

struct Employee{
  int             EMP_NO;
  string          First_Name;
  string          Last_Name;
  string          Phone_Ext;
  IBPP::Timestamp Hire_Date;
  string          Dept_No;
  string          Job_Code;
  int             Job_Grade;
  string          Job_Country;
  float           Salary;
  string          Full_Name;
};

Employee Personen;

int main( int argc, const char* argv[] )
{
    int auswahl=menu();
    return 0;
}

int menu()
{
    /* Bildschirm löschen */
    system("cls");

    int w;
    cout << "\n***** Konsolenprogramm für FB-Datenbank";
    cout << "\n* 1 - Liste der Mitarbeiter anzeigen (lt. Aufg. 2)";
    cout << "\n* 2 - Aktualisieren eines Mitarbeiter-Datensatzes";
    cout << "\n* 9 - Ende des Programms \n\n";
    cin >> w;

    if (w!=1 && w!=2 && w!=9)
    {
        w=menu();
    } else if (w==1)
    {
      Datensaetze_lesen();
    } else if (w==2)
    {
      cout << "\n\n";

      string last_name;
      string first_name;
      string hire_date;

      cout << "Bitte Nachname eingeben: "; cin >> last_name;
      cout << "Bitte Vorname eingeben: "; cin >>first_name;
      cout << "Bitte neuen Arbeitsbeginn eingeben: "; cin >> hire_date;

      Datensatz_aendern(last_name,first_name,hire_date);
    }

    return w;
}

void Datensaetze_lesen()
{
  try
  {
    Database db1;
    db1 = DatabaseFactory(ServerName, DbName, UserName, Password,
        "", "WIN1252", "PAGE_SIZE 8192 DEFAULT CHARACTER SET WIN1252");
    db1->Connect();

    Transaction tr1 = TransactionFactory(db1);
    tr1->Start();
    Statement st1 = StatementFactory(db1, tr1);
    Statement st2 = StatementFactory(db1, tr1);

    cout << "+-------------------------------------------------------+" << '\n';
    cout << "|Name                       | Arbeitsbeginn | Währung   |" << '\n';
    cout << "+---------------------------+---------------+-----------+" << '\n';

    int i=0;
    st1->Execute("SELECT * from employee");
    while (st1->Fetch())
    {
      i++;

      /* Datensatz einlesen */
      st1->Get(1 ,Personen.EMP_NO);
      st1->Get(2 ,Personen.First_Name);
      st1->Get(3 ,Personen.Last_Name);
      st1->Get(4 ,Personen.Phone_Ext);
      st1->Get(5 ,Personen.Hire_Date);
      st1->Get(6 ,Personen.Dept_No);
      st1->Get(7 ,Personen.Job_Code);
      st1->Get(8 ,Personen.Job_Grade);
      st1->Get(9 ,Personen.Job_Country);
      st1->Get(10,Personen.Salary);
      st1->Get(11,Personen.Full_Name);

      /* Datum für Ausgabe konvertieren */
      int Dd = 0 , Mm = 0 , Yyyy = 0;
      (Personen.Hire_Date).GetDate( Yyyy, Mm, Dd);

      /* Währung einlesen */
      string sqlstring="SELECT * from country where country='" + Personen.Job_Country+ "'";
      string waehrung;
      st2->Execute(sqlstring);
      st2->Fetch();
      st2->Get(2,waehrung);

      /* Ausgabe */
      /* Manipulatoren: http://www.willemer.de/informatik/cpp/iostream.htm */
      /* left=rechts mit Füllzeichen auffüllen, right umgekehrt */
      cout << "| ";
      cout.width(26); cout << left << Personen.Full_Name << "| ";
      cout << setw(2) << right << Dd << "." << setw(2) << right << Mm << "." << Yyyy << "    | ";
      cout << setw(10) << left << waehrung << "|";

      /* alle 20 Zeilen eine Unterbrechung -> auf Enter warten */
      if (i%20==0)
      {
         char c;
         do {
           c=getchar();
         } while (c == 0);
      } else {
        cout << '\n';
      }
    }

    cout << "+-------------------------------------------------------+" << '\n';
    tr1->Commit();
    db1->Disconnect();
  }
  catch (IBPP::Exception& e)
  {
    cout << e.ErrorMessage();
  }
}

void Datensatz_aendern(string last_name, string first_name, string hire_date)
{
  try
  {
    Database db = DatabaseFactory(ServerName, DbName, UserName, Password);
    db->Connect();

    Transaction tr = TransactionFactory(db);
    tr->Start();

    Statement st = StatementFactory(db, tr);
    st->Execute("update employee set hire_date='"+hire_date+"' where first_name='"+first_name+"' and last_name='"+last_name+"'");
    tr->Commit();

    db->Disconnect();
  }
    catch (Exception& e)
  {
    cout << e.ErrorMessage();
  }
}

 

Monats-Liste