ZEOS Postgres SIGSEGV

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

ZEOS Postgres SIGSEGV

Beitrag von Michl »

Ein fröhliches Hallo an alle Lazarus/ZEOS/Postgres - Nutzer,

ich hoffe, ich stehe da jetzt nicht alleine da :wink:

In einem Programm speichere ich verschiedene Datentypen in verschiedenen Tabellen/Spalten. Da ich zur Laufzeit Tabellen und Spalten in der Datenbank erstelle und dabei ein SIGSEGV auftrat, den ich mir nicht wirklich erklären kann, frage ich Euch Angesprochene.

Anbei ein Minimalbeispiel (getestet unter verschiedenen Lazarus-Versionen, ZEOS 7.1.3a stable, Postgres 9.3). Postgres muss installiert sein, Zeos ebenso, dann nur noch PostgresPasswort und Pfad im Quellcode entsprechend anpassen.

In Zeile 193/194 Connection.Disconnect und .Connect ausklammern und der Bug tritt auf:

Code: Alles auswählen

  function SpalteAnlegen: Boolean;                          //Legt die Spalte in der Tabelle an
  var
    i: Int32;
  begin
    Connection.ExecuteDirect('ALTER TABLE tab1 ADD COLUMN '+Spalte+' INTEGER;');
 
 
//    Connection.Disconnect;                                  //Warum muss ich hier Disconnecten und wieder Connecten???
//    Connection.Connect;
 
Habe verschiedene andere Versuche gemacht, diesen SIGSEGV zu unterbinden, einzig die Connection trennen und wieder verbinden hat bisher geholfen. Warum?
Dateianhänge
Minimalbsp.zip
(127.87 KiB) 68-mal heruntergeladen

Code: Alles auswählen

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

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

Re: ZEOS Postgres SIGSEGV

Beitrag von Michl »

Push :wink:

Habe mir auf einem anderen Rechner noch Zeos 7.2alpha installiert, dort kommt es zu dem gleichen Fehler (Bild anbei). Leider tritt der Fehler nicht direkt auf, sondern erst bei einem erneutem Zugriff mit der Connection, sodaß ein Debuggen mir nicht wirklich möglich ist (irgendwas scheint da bei der Connection bestehen zu bleiben, was diesen SIGSEGV auslöst).

Ich hatte auch versucht die Frage im Zeos-Forum zu stellen, konnte aber keinen neuen Thread eröffnen :(
Dateianhänge
Fehler.jpg

Code: Alles auswählen

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

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: ZEOS Postgres SIGSEGV

Beitrag von hde »

Um das mal zu checken muss ich erst PostGres installieren bin aber tagelang unterwegs.
Ich frage mich allerdings, warum du das nicht mal mit ZQuery.ExecuteSQL versuchst wenn es mit Zconnection.ExecuteDirect Problme gibt? :wink:
hde

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

Re: ZEOS Postgres SIGSEGV

Beitrag von Michl »

Hallo hde,

danke erstmal, dass Du Dich für mein Problem interessierst! Zur Lösung hatte ich natürlich auch Query.SQL.Text:=... und Query.ExecQSL probiert, dabei kommt es zu dem gleichen SIGSEGV-Fehler.

Evtl. sollte ich etwas weiter ausholen (ich dachte das Minimalbsp würde besser für sich sprechen, als wenn ich einen langen Text verfasse). Ich habe eine unbekannte Zahl an Tabellen (ich rechne mit ca. 5000 zur Laufzeit), in jeder dieser Tabellen können vom Programm beliebig viele Spalten mit unterschiedlichen Datentypen eingefügt werden (ich rechne mit 1..50 Spalten, im Schnitt werden es wohl ca. 10 Spalten sein). In diesen Spalten werden die Datensätze jeweils einer ID-Nr zugeordnet (ich rechne mit im Schnitt 5000 Datensätzen). Das Programm läuft auch soweit, sofern ich nicht mehr als eine Spalte einer Tabelle zur Laufzeit erstelle.

Um den Fehler einzugrenzen habe ich den Fehler auf das Minimalbeispiel reduzieren können.
Folgendes funktioniert:

1. Frage ab, ob Spalte existiert
2. Falls nicht, Spalte anlegen
3. Connection.Disconnect
4. Connection.Connect
5. Frage ob ID existiert
6. Trage Daten in Spalte ein, Update/Insert je nach Existenz von ID (eine Function UpSert kann ich nicht verwenden, da ich, falls die ID schon Daten/abweichende Daten in der Spalte hat, diese auslesen will und prüfen lassen will)
zurück zu 1

Folgendes funktioniert nicht:
1. Frage ab, ob Spalte existiert
2. Falls nicht, Spalte anlegen
3. Frage ob ID existiert
4. Trage Daten in Spalte ein, Update/Insert je nach Existenz von ID
zurück zu 1
1. Frage ab, ob Spalte existiert
2. Falls nicht, Spalte anlegen
3. Frage ob ID existiert <- hier kommt es zu dem SIGSEGV

Folgende SQL-Befehle verwende ich:

Code: Alles auswählen

//1. Frage ab, ob Spalte existiert
    Query.SQL.Text:='SELECT column_name FROM information_schema.COLUMNS WHERE table_name = ''tab1'';';
    Query.Open;
 
//2. Falls nicht, Spalte anlegen
    Connection.ExecuteDirect('ALTER TABLE tab1 ADD COLUMN '+Spalte+' INTEGER;');   
//oder
    Query.SQL.Text:='ALTER TABLE tab1 ADD COLUMN '+Spalte+' INTEGER;';
    Query.ExecSQL;
 
//3. Frage ob ID existiert
    Query.SQL.Text:='SELECT * FROM tab1 WHERE id = :id;';
    Query.ParamByName('id').AsInteger:=aID;
    Query.Open
 
//4. Insert
    Query.SQL.Text:='INSERT INTO tab1 (id, '+Spalte+') VALUES (:id, :wert);';
    Query.ParamByName('id').AsInteger:=aID;
    Query.ParamByName('wert').AsInteger:=aI;
    Query.ExecSQL;

Also eigentlich nichts ungewöhnliches?!

[Edit]: Nun wurde mein Thread im Zeos-Forum doch noch eröffnet: http://zeoslib.sourceforge.net/viewtopic.php?f=38&t=11384

Code: Alles auswählen

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

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

Re: ZEOS Postgres SIGSEGV

Beitrag von Michl »

So, bin mir nun zu 90% sicher, dass dies ein Bug von Zeos ist. Ich habe statt den Zeos-Komponenten mal die Lazarus-eigenen (SQLdb) in meinem Minimalbeispiel verwendet. Dabei tritt dieses Fehlverhalten nicht auf.

Ich hoffe, das Zeos-Team kann mir bei der Fehlersuche helfen, auf SQLdb umzusatteln wäre ganz schön ärgerlich, allein die Klasse um diese ZConnection, bei der dieser Fehler auftritt, hat nun mittlerweile mehr als 11.000 Zeilen (wobei ich mir nicht sicher bin, dass SQLdb nicht dann anderswo wieder Kummer bereitet) :cry: .

Code: Alles auswählen

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

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: ZEOS Postgres SIGSEGV

Beitrag von hde »

Ich werd's mal kurz checken, aber mein neu instslliertes PostGres will noch nicht so wie ich
hde

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

Re: ZEOS Postgres SIGSEGV

Beitrag von Michl »

Danke! Falls es zu viele Umstände macht, könnte ich auch noch im englischen Forum fragen (falls hier oder im Zeos-Forum niemand Rat weiss). Eventuell nutzt ja dort jemand die Kombination?!

Ich bin mir auch nicht ganz sicher, wo sich dieses Fehlverhalten einschleicht, es tritt soweit ich das eingrenzen konnte wirklich nur in der Kombination

Code: Alles auswählen

//1. Frage ab, ob Spalte existiert
    Query.SQL.Text:='SELECT column_name FROM information_schema.COLUMNS WHERE table_name = ''tab1'';';
    Query.Open;
 
//2. Falls nicht, Spalte anlegen
    Connection.ExecuteDirect('ALTER TABLE tab1 ADD COLUMN '+Spalte+' INTEGER;');   
//oder
    Query.SQL.Text:='ALTER TABLE tab1 ADD COLUMN '+Spalte+' INTEGER;';
    Query.ExecSQL;
auf.

Vielleicht könnte ich das Design da auch ändern, z.B. in

Code: Alles auswählen

    Connection.ExecuteDirect('ALTER TABLE tab1 ADD COLUMN IF NOT EXISTS '+Spalte+' INTEGER;');    
leider funktioniert das lt. Doku nur mit DROP aber nicht mit ADD. Falls das funktionieren würde, könnte ich mir die Spaltenexistenzabfrage sparen und somit auch diesen Bug...

Code: Alles auswählen

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

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: ZEOS Postgres SIGSEGV

Beitrag von hde »

Bei meinem ersten Versuch kann ich disconnect/connect auskommentieren und dein Prog läuft trotzdem.
Werd mal weiteres versuchen
hde

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

Re: ZEOS Postgres SIGSEGV

Beitrag von Michl »

Das klingt für mich sehr gut, kannst Du mir sagen, unter welchem System (OS, Lazarus, FPC, Postgres, Zeos)?!

Code: Alles auswählen

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

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: ZEOS Postgres SIGSEGV

Beitrag von hde »

so ..
ich hab's zuächst in einer alten VM compiliert, da tritt der Fehler nicht auf:
Laz 1.1 -40524
fpc 2.7.1
zeos 7.0.3-stable
win XP-32
--------
dann compiliert unter Win7-64 aber für Win-32 da kommt 'Access violation'
Laz 1.2.0 (stable)
fpc 2.6.2
zeos 7.1.3a-stable
---------
beides auf die gleiche PostGres Installation 9.3.4-1

werde mal noch PG für 64 bit installieren und testen

hde

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

Re: ZEOS Postgres SIGSEGV

Beitrag von Michl »

Danke für die Mühe!

Werde das Ergebnis im Zeos-Forum posten, dauert aber irgendwie eine Weile, bis die Beiträge auftauchen, weil sie irgendwie erst vom Moderator freigegeben werden müssen (evtl. wegen Spam oder so?!).

Code: Alles auswählen

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

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: ZEOS Postgres SIGSEGV

Beitrag von hde »

Laz 1,2.0
fpc 2.6.2
zeos 7.1.3a-stable
pg 9.3.4-1-64bit
unter Win7- 64bit für 64bit
da kommt auch der Fehler ..

kann sein dass ich noch andere Kombinationen habe, evtl. test ich da später auch noch mal

hde

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: ZEOS Postgres SIGSEGV

Beitrag von hde »

ob's an Zeos (7.0 bzw.7.1) liegt oder an fpc (2.6.2 bzw. 2.7.1) hab ich bisher nicht geklärt.
Ich hab zwar etliche Veersionen da, aber keine passende Zusammenstellung für diesen Test.
wenn du sonst nicht weiterkommst könnte ich aber solche Konfigurationen zusammenstellen.
hde

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

Re: ZEOS Postgres SIGSEGV

Beitrag von Michl »

Ich habe nun das Minimalbeispiel weiter verändert, das heisst kongret habe ich mal sämtliche SQL-Befehle, die ich bisher per Schleife aufgerufen habe, hintereinander geschrieben und immer eines auskommentiert und geschaut, ob der SIGSEGV noch auftritt. Dabei konnte ich das Beispiel auf nur noch 3 Anweisungen bis zum SIGSEGV reduzieren. Der Fehler stellt sich an einer anderen Stelle ein, als ich bisher vermutet hatte:

Code: Alles auswählen

procedure TForm1.Button2Click(Sender: TObject);
begin
  Query.SQL.Text:='SELECT * FROM tab1 WHERE id = 1;';
  Query.Open;
  Query.Close;
 
  Query.SQL.Text:='ALTER TABLE tab1 ADD COLUMN spalte2 INTEGER;';
  Query.ExecSQL;
//  Connection.ExecuteDirect('ALTER TABLE tab1 ADD COLUMN spalte2 INTEGER;');
 
  Query.SQL.Text:='SELECT * FROM tab1 WHERE id = 1;';
  Query.Open;       //Hier kommt es zum SIGSEGV
  Query.Close;
end;
Aber nur in der Kombination, wobei auch nur, wenn ID noch nicht in der Tabelle, also RecordCount=0

Ich werde mal versuchen hineinzudebuggen und schauen, ob ich den Fehler ausfindig machen kann.

Code: Alles auswählen

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

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: ZEOS Postgres SIGSEGV

Beitrag von hde »

Du hast mit dem 'Alter Table' die Metadaten verändert, der select * braucht die aber zum Auflösen des *,
beim Connect werden die neu eingelesen, deshalb tritt der Fehler dann afaik nicht auf.
check an der Stelle mal, dort könnte sich auch zwischen zeos 7.0 und 7.1 was geändert haben.
hdr

Antworten