[gelöst] PostgreSQL Datenbank erstellen mit TPQConnection

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

[gelöst] PostgreSQL Datenbank erstellen mit TPQConnection

Beitrag von Michl »

Eine mal etwas spezielle Frage. Ich nutzte bisher Zeos um meine Datenbankanfragen etc. durchzuführen. Das funktioniert auch prima. Unter anderem kann ich da eine neue Datenbank erstellen.

Das heist, da ich keine Möglichkeit habe ,bzw. AFAIK Postgres dies nicht bereitstellt, eine Abfrage in dem Sinn "CREATE DATABASE IF NOT EXISTS vigema;" durchzuführen, erstelle ich einfach immer eine. Falls keine existiert, wird sie erstellt. Falls diese Datenbank schon besteht, kommt es zu einer Exception, die ich abfange. So weit so gut.

Nun probiere ich gerade Alternativen aus und wollte statt Zeos mal die Bordmittel von Lazarus nutzen. Ich nutze dafür eine TPQConnection, die auch wunderbar eine Datenbank erstellt (per Methode: "PQConnection.CreateDB;" oder per Hand "PQConnection.ExecuteDirect('CREATE DATABASE vigema;');" was beides funktioniert, wenn es noch keine Datenbank gibt. Existiert jedoch schon die Datenbank, kommt es zu einer Exception "EPQDatabaseError Fehler: Datenbank existiert bereits", die ich nicht abfangen kann.

Hier mal der Code:

Code: Alles auswählen

      try
        PQConnection.ExecuteDirect('Commit Work;');
        PQConnection.ExecuteDirect('CREATE DATABASE vigema;');
 
//        PQConnection.CreateDB;  //Dies geht auch nur, wenn Datenbank noch nicht existiert -> gleiche Exception
      except
        on E: Exception do
          status.Write(1,'Exception: '+E.Message)
        else
          status.Write(1,'Unbekannter Fehler');
      end;
Nun die Fragen:
1. Gibt es eine Möglichkeit bei PostgreSQL im Vorfeld zu checken, ob eine Datenbank existiert?!
2. Alternative: wie kann ich die Exception abfangen (mit Zeos geht das ja)?!

Ähnlich diesem Forum http://www.lazarusforum.de/viewtopic.php?p=23694, leider ohne Lösung!
Zuletzt geändert von Michl am Mi 4. Sep 2013, 22:20, insgesamt 1-mal geändert.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: PostgreSQL Datenbank erstellen mit TPQConnection

Beitrag von Michl »

Achso in einem anderen Forum hatte ich noch gelesen, dass man das ganze auch anders herum machen könnte, also erst Zugriff versuchen, bei Fehler, erstellen:

Code: Alles auswählen

      PQConnection.HostName:='localhost';
      PQConnection.DatabaseName:='vigema';
      PQConnection.Password:='*****';
      PQConnection.UserName:='postgres';
      try
        PQConnection.Connected:=true;
      except
        on E: Exception do begin
          status.Write(1,'Datenbank existiert nicht, erstelle sie neu!');
          PQConnection.CreateDB;
        end;
      end; 
diese Exception geht ebenfalls nicht abzufangen, funktioniert also nicht!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: PostgreSQL Datenbank erstellen mit TPQConnection

Beitrag von Michl »

Ok, habe nun nach einigem Suchen (und zwar hier) eine recht saubere Lösung gefunden. Falls jemand nochmal einen Ansatz brauch, ich bin soweit ganz zufrieden damit 8) :

Code: Alles auswählen

type
...
    DBConnect:TPQConnection;                               //Connection für Postgres
    DBTransaction:TSQLTransaction;                         //Transaction für Postgres
    DBQuery:TSQLQuery;                                     //Query für Postgres
...
procedure StartConnection;                                   //Erstmal eine Verbindung zur Datenbank herstellen
var
  DBCount:integer;
begin
  DBConnect.HostName:='localhost';                         //Lokal - Computer mit Entwicklungsumgebung
  DBConnect.DatabaseName:='postgres';                      //Diese Datenbank wird immer bei der Installation von Postgres erstellt
  DBConnect.UserName:='postgres';                          //Benutzer von Postgres immer vergeben / Admin
  DBConnect.Password:='*****';                             //Passwort bei Installation von PostgreSQL vergeben
 
  DBConnect.Transaction:=DBTransaction;                    //Transaktion verbinden
  DBQuery.DataBase:=DBConnect;                             //Query verbinden
 
  try                                                      //Versuche eine Verbindung herzustellen
    DBConnect.Connected:=true;
  except
    on E: Exception do begin
//      status.Write(1,'[SaveUnit.TStartThread.Execute.TesteConnection] Connect1-Exception: '+E.Message);
//      Geladen:=False;                                      //Mein Status, ob Klasse ordentlich geladen/erstellt wurde
      exit;
    end;
  end;
 
  DBQuery.SQL.Clear;                                       //Jetzt abfragen, wieviele DataBases in Postgres mit dem Namen vorkommen
  DBQuery.SQL.Add('SELECT COUNT(*) FROM PG_CATALOG.PG_DATABASE WHERE DATNAME = '+#39+'vigema'+#39+';');
  DBQuery.Open;
 
  if DBQuery.FieldCount>0 then                             //wurde eine Antwort erhalten, wenn ja, dann
    DBCount:=DBQuery.Fields[0].AsInteger                   //DBCount=0 keine / DBCount=1 wenn Datenbank existiert
  else begin                                               //keine Antwort auf SQL-Befehl
//    status.Write(1,'[SaveUnit.TStartThread.Execute.TesteConnection] Fehler: keine Antwort auf Postgres-Anfrage Anzahl Datenbanken [vigema]');
//    Geladen:=False;
    exit;
  end;
 
  DBQuery.Close;
 
  if DBCount=0 then                                        //Die Datenbank existiert noch nicht, daher Datenbank und Role/User erstellen!
    try
      DBConnect.ExecuteDirect('Commit Work;');
      DBConnect.ExecuteDirect('CREATE USER vigema WITH PASSWORD '+#39+'*****'+#39+';');   //Vigema als User generieren - geht
      DBConnect.ExecuteDirect('ALTER USER vigema VALID UNTIL '+#39+'infinity'+#39+';');   //Passwort erlischt niemals
      DBConnect.ExecuteDirect('ALTER USER vigema NOCREATEDB NOCREATEROLE REPLICATION;');  //User Vigema darf keine neuen User und Datenbanken generieren
      DBConnect.ExecuteDirect('CREATE DATABASE vigema;');                                 //Datenbank Vigema anlegen
      DBConnect.ExecuteDirect('GRANT ALL PRIVILEGES ON DATABASE vigema TO vigema;');
    except
      on E: Exception do begin
//        status.Write(1,'[SaveUnit.TStartThread.Execute.TesteConnection] CreateDB-Exception: '+E.Message);
//        Geladen:=False;
        exit;
      end;
    end;
 
  DBConnect.Connected:=false;
  DBConnect.DatabaseName:='vigema';                        //Das Ganze wieder starten, mit der eigenen Datenbank
  DBConnect.UserName:='vigema';                            //Benutzer von Postgres immer vergeben / Admin
  DBConnect.Password:='*****';                             //Passwort bei Installation von PostgreSQL vergeben
 
  try                                                      //Versuche eine Verbindung herzustellen
    DBConnect.Connected:=true;
  except
    on E: Exception do begin
//      status.Write(1,'[SaveUnit.TStartThread.Execute.TesteConnection] Connect2-Exception: '+E.Message);
//      Geladen:=False;                                      //Mein Status, ob Klasse ordentlich geladen/erstellt wurde
      exit;
    end;
  end;
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Antworten