[Gelöst] Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

[Gelöst] Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MacWomble »

Ich habe eine Funktion, welche als Parameter 'Source: TZQuery' beinhaltet. Nun benötige ich die selbe Funktion auch für TZReadOnlyQuery.
Wie gehe ich hier am besten vor?
Muss ich die Funktion für beide Fälle extra schreiben und überladen?

Code: Alles auswählen

function OpenSQLSet(SQLSet: TZQuery; SQLText:String): Boolean;
begin
  with SQLSet do
  begin
...
end


Nachtrag:

Eigentlich wollte ich hiermit erreichen, für Listen, welche nur eingelesen aber nicht verarbeitet werden, ReadOnly-Querys zu verwenden.
Da ich jedoch mit Stored Procedures arbeite, nutzt die Lösung hier nicht wirklich.
Stored Procedures funktionieren nicht (ohne weiteres) im ReadOnly, auch wenn diese nur Daten zurück liefern!
Dennoch enthält der Thread viele nützliche Informationen.
Zuletzt geändert von MacWomble am Fr 4. Jan 2019, 09:41, insgesamt 3-mal geändert.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

MmVisual
Beiträge: 1437
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MmVisual »

Code: Alles auswählen

function OpenSQLSet(SQLSet: TDataset; SQLText:String): Boolean;
begin
  with TZQuery(SQLSet) do
  begin
...
end;
EleLa - Elektronik Lagerverwaltung - www.elela.de

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MacWomble »

Damit komme ich aber auch nicht weiter, da ja dann in der Funktion wieder TZQuery verwendung findet ...
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

MmVisual
Beiträge: 1437
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MmVisual »

So lange man keine Sondereingenschaften von TZxxxx benötigt geht auch das:

Code: Alles auswählen

function OpenSQLSet(SQLSet: TDataset; SQLText:String): Boolean;
begin
  with SQLSet do
  begin
...
end;
EleLa - Elektronik Lagerverwaltung - www.elela.de

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von wp_xyz »

Was machst du denn in OpenSQLSet mit SQLSet? Vielleicht tut's der "ferne" Vorfahr TDataSet auch schon, hat allerdings kein SQL, falls du dieses zuweisen willst. Allerdings würde ich nicht den Brutal-Typecase von MmVisual anwenden, sondern vorher mit "is" noch prüfen, ob wirklich ein TZReadOnlyDataset oder eine TZQuery vorliegen.

Allerdings ist es meiner Meinung nach besser, sich die im ZEOS eingeführten Klassen näher anzushen und einen gemeinesamen Vorfahren zu finder, der alles kann, was man braucht.

Auf TDataset folgt hier die Klasse TZAbstractRODataset, die bereits eine Property SQL implementiert. Davon abgeleitet sind TZReadonlyDataset und TZAbstractDataset. Von TZAbstractDataset schließlich ist TZQuery abgeleitet (sowie TZTable). Wenn du als Gemeinsamkeit nur die Eigenschaft SQL benötigst, dann kannst du den Parameter SQLSet als TZAbstractRODataset deklarieren. Evtl brauchst du auch noch die Eigenschaft Active (bzw. Methoden Open/Close) - diese sind schon in TDataset eingeführt

Code: Alles auswählen

  TDataset ---  TZAbstractRODataset ---- TZReadOnlyDataset
                 |
                  --- TZAbstractDataset 
                       |
                       |--- TZQuery
                       |--- TZTable

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MacWomble »

Ich habe unterschiedliche Fumktionen, welche derzeit mit TZQuery befeuert werden. Das funktioniert auch ganz gut. Ich möchte nun aber einen Teil meiner TZQuery durch TZReadOnlyQuery ersetzen, ohne alle Funktionen nochmals im Programm hinterlegen zu müssen. Ich habe als gemeinsamen Vorfahr TZAbstractDataset anstelle von TZQuery versucht, aber das wird nicht gefunden. (Momentan habe ich ca. 60 TZQuery im Projekt)

Was ich möchte ist unabhängig davon, ob es eine TZQuery oder TZReadOnlyQuery ist, dieses an die Funktion zu übergeben.

Beispiel der einer Funktion:

Code: Alles auswählen

function OpenSQLSet(SQLSet: TZQuery; SQLText:String): Boolean;
begin
  with SQLSet do
  begin
    writeln;
    writeln('OpenSQLSet:        ' + SQLText);
    try
     Close
     except
     end;
    try
     SQL.Clear;
     SQL.Text := SQLText;
     Open;
     Result := True;
    Except
    On E :Exception do
      begin
        writeln;
        writeln('ERROR in OpenSQLSet:        ' + SQLText);
        Result:=false;
       end;
    end;
  end;
end;
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

MmVisual
Beiträge: 1437
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MmVisual »

Code: Alles auswählen

function OpenSQLSet(SQLSet: TDataSet; SQLText:String): Boolean;
begin
  Result:=false;
  If (SQLSet Is TZQuery) Or (SQLSet Is TZReadOnlyQuery) Then
  with TZQuery(SQLSet) do
  begin
    writeln;
    writeln('OpenSQLSet:        ' + SQLText);
    try
     SQL.Text := SQLText;
     Open;
     Result := True;
    Except
    On E :Exception do
      begin
        writeln;
        writeln('ERROR in OpenSQLSet:        ' + SQLText + ' E:' + E.Message);
       end;
    end;
  end;
end;


Zum Hintergrund:
- TDataSet ist der Vorfahre von allen Queries, auch die von Zeos
- SQL.Text schließt automatisch die Query
- Der gelöschte Code ist nicht nötig und nur Dateifüller
- E.Message ist so ziemlich das hilfreichste um zu sehen warum es geknallt hat.
- Result =False muss unbedingt zu Anfang stehen, damit immer der Result initialisiert ist
EleLa - Elektronik Lagerverwaltung - www.elela.de

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von wp_xyz »

Wenn ich das richtig erkenne, brauchst du, wie ich oben schon vermutet hatte, die Methoden Open und Close sowie die Eigenschaft SQL. TZQuery und TReadOnlyQuery haben einen gemeinsamen Vorfahren TZAbstractRODataset. Dieser erbt von TDataset die öffentlichen Methoden Open und Close; außerdem wird die Eigenschaft SQL eingeführt. Daher kannst du die Funktion mit TZAbstractRODataset deklarieren:

Code: Alles auswählen

function OpenSQLSet(SQLSet: TZAbstractRODataset; SQLText:String): Boolean;

Da TZAbstractRODataset die Eigenschaft SQL nur als protected eingeführt hat, kannst du sie von dem so deklarierten SQLSet aus nicht aufrufen. Der übliche Trick ist, eine Hilfsklasse, etwa TZAbstractRODatasetMitSQL, einzuführen, die ebenfalls von TZAbstractRODataset abgeleitet ist und SQL als public umdeklariert. Durch eine Typumwandlung nach TZAbstractRODatasetMitSQL kannst du die Eigenschaft sichtbar machen. Das funktioniert, weil sich sich TZQuery und TZReadOnlyQuery hinsichtlich der Eigenschaft SQL nicht unterscheiden und du nichts anderes von dem gemeinsamen Vorfahren verwendest (wiegesagt, Open und Close sind schon öffentlich). Eine saublere Implementierung muss allerdings noch vorsehen, dass nur TZQuery oder TZReadOnlyQuery verwendet werden.

Code: Alles auswählen

implemenation
  ...
 
type
  TZAbstracRODatasetMitSQL = class(TZAbstractRODataset)
  public
    property SQL;
  end;
 
function OpenSQLSet(SQLSet: TZAbstracctRODataset; SQLText:String): Boolean;
begin
  if not ((SQLSet is TZQuery) or (SQLSet is TZReadOnlyQuery))  then
    raise Exception.Create('OpenSQLSet kann nur mit TZQuery oder TZReadOnlyQuery aufgerufen werden.');
 
  with TZAbstractRODatasetMitSQL(SQLSet) do
  begin
    writeln;
    writeln('OpenSQLSet:        ' + SQLText);
    try
     Close
     except
     end;
    try
     SQL.Clear;
     SQL.Text := SQLText;
     Open;
     Result := True;
    Except
    On E :Exception do
      begin
        writeln;
        writeln('ERROR in OpenSQLSet:        ' + SQLText);
        Result:=false;
       end;
    end;
  end;
end;


[EDIT]
Ja, ok, MmVisual's direkter Cast zu TZQuery geht auch, weil sich TZQuery und TZReadOnlyQuery hinsichtlich der Eigenschaft SQL nicht unterscheiden. Meine Schreibweise erscheint mir allerdings etwas sicherer, weil man im Unterschied zu dem TZQuery-Cast in dem with-Teil nicht mehr irrtümlicherweise eine Nur-TZQuery-Methode aufrufen kann, obwohl ein TZReadOnlyQuery als Parameter übergeben ist.
Zuletzt geändert von wp_xyz am Mi 2. Jan 2019, 18:32, insgesamt 1-mal geändert.

MmVisual
Beiträge: 1437
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MmVisual »

Noch etwas:
Verwende TZSQLMonitor und aktiviere den, da bekommst Du automatisch ein Event über jeden SQL Befehl der gestartet wird, damit kannst Du diese Zeile auch löschen:

Code: Alles auswählen

    writeln;
    writeln('OpenSQLSet:        ' + SQLText);
EleLa - Elektronik Lagerverwaltung - www.elela.de

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MacWomble »

Ich danke euch, jetzt habe ich das auch gefressen ;-)

Die Konsolenausgaben mache ich, weil diese mir das debuggen deutlich vereinfachen.
Da melde ich mir noch weitere Sachen nach außen (Datensatz-IDs etc), so kann ich auch beim Kunden mal schnell grob nach einem Problem suchen, falls notwendig.
ZEOS-log läuft aber auch mit.

Danke auch für die weiteren Informationen, welche mir auch nicht alle geläufig waren.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

MmVisual
Beiträge: 1437
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MmVisual »

MacWomble hat geschrieben:Die Konsolenausgaben mache ich, weil diese mir das debuggen deutlich vereinfachen.


Die werden nicht unter Windows funktionieren ... Mache deshalb besser eine Logdatei, bzw. schreibe die Info in ein TMemo.
Die Logdatei ist dann hilfreich, sollte die EXE direkt nach dem Start abstürzen.
Für Linux und eigene Übungen ist die Konsole OK - obwohl die schnell unübersichtlich wird wenn da viel geloggt wird, bzw. aus dem Screen Buffer das wichtige verschwindet.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6197
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: [Gelöst] Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von af0815 »

Für das Logging (auch beim Kunden, wenn nötig) verwende ich den LazLogger. Der ist bei Lazarus dabei, Lazarus selbst verwendet den, lässt sich über die Parameter beim Aufruf steuern. Bin damit sehr zu
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: [Gelöst] Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MacWomble »

Da derzeit Windows die EU-DSGVO nicht umsetzt, ist es für mich ohne weiteres Interesse ... :twisted:

Nein, im Ernst: Ich habe keine Windows-Kunden. Ich entwickle zwar - wenn irgend möglich - plattformunabhängig, aber solche kleinen Details wie die writelines kommen nur in einer einzigen Unit bei mir vor und sind auch leicht austauschbar. Es ist einfach besser nutzbar als ein Logfile. Wenn ich das Programm von der Konsole starte, kann ich so sehr schön den Programmablauf verfolgen und auch die logischen Abläufe kontrollieren. Später wird das ersetzt, aber im Moment ist es die einfachste und schnellst Lösung für mich.
Mir ist schon klar, dass ein Logfile zur nachträglichen Fehlersuche die deutlich bessere (einzige) Wahl ist. Deswegen läuft ja auch das ZEOS-Log mit.
Dennoch danke für die Hinweise!

Was die Übersichtlichkeit angeht ein Beispiel (das ZEOS-log ist viel komplexer):

Code: Alles auswählen

OpenSQLSet:             Select * from Kontakte left join Colors on fk_color = idcolor where fk_adresse =25
 
OpenSQLSet:             Select * from view_kontakte where fk_adresse = 25
 
OpenSQLSet:             Select * from Dokumente Where fk_historie = 1
 
OpenSQLSet:             CALL get_artikelpreise(1)
 
OpenSQLSet:             CALL get_auftragssummen(50)
 
OpenSQLSet:             Select sum(zah_betrag) as bezahlt from Auftraege, Zahlungen where fk_auftrag = idauftrag and auf_typ > 49 and auf_typ < 60 and Auftraege.fk_quellauftrag = 50
ExecSQLDirect:          Update Auftraege set auf_offenbrutto = 46.41 where idauftrag = 50
 
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6197
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: [Gelöst] Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von af0815 »

Der LazLogger arbeitet auch über die Konsole, wenn eine vorhanden ist. Durch die Unabhängigkeit vom BS kann ich bei meinem Programmen beliebig zwischen Win und Linux, mit oder ohne Konsole umschalten. Logdatei wird nur wenn gewünscht erstellt.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: [Gelöst] Funktionsaufruf mit TZQuery und TZReadOnlyQuery

Beitrag von MacWomble »

af0815 hat geschrieben:Der LazLogger arbeitet auch über die Konsole, wenn eine vorhanden ist.


Man lernt doch nie aus -Danke!

Ich habe nun auf LazLogger umgestellt - funktioniert wirklich gut - auch in der Konsole :)
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Antworten