PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Hier dreht es sich um den PostGre Server

Moderator: Moderatoren

Antworten
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Hallöle.

Bei Nutzung der PGDBE/ISAM, die ansonsten wirklich fast vortrefflich funktioniert, gibt es derzeit noch gehäuft Probleme in Filtern. Filter werden serverseitig evaluiert, das ist letztlich dasselbe Spiel wie bei der Nutzung der ADSDBE. Nur macht die einfach einen Fallback auf die lokale Auswertung, zieht sich also die gesamte Tabellenmenge und wendet darauf dann lokal den Filter an (was man in den Fehlertabellen nachvollziehen kann). Die PGDBE erzeugt Serverfehler und frisst sich fest. Das betrifft ein paar Sonderzeichen (#, ! usw.), vor allem aber UDFs und einige Alaska-Funktionen. Alaska empfiehlt, in dieser Situation auf Stored Procedures zu setzen, also die in den Filterausdrücken verwendeten Funktionen serverseitig zu implementieren. Die Doku zum PostGresServer sagt, dass das eine supereinfache Supersache wäre, zudem in tausenden Sprachen möglich. Jawollo.
Ich habe schon Stored Procs genutzt, aber noch nie selbst gebaut. Vielleicht könnten wir das hier mal zusammen durchspielen, mit einigen Beispielen. Eine einfache Stored Proc beispielsweise, die herausfindet, ob jemand, der am Tag A geboren wurde, am Tag B Geburtstag hat (Day(dGeburtsDatum) == Day(dPruefDatum) .AND. Month(dGeburtsDatum) == Month(dPruefDatum), wobei DEFAULT dPruefDatum := Date(), umgesetzt als "FUNCTION HatGeburtstag(<dGebDatum>,[<dRefDatum>])" - aber so gemacht, dass man es eben direkt in einem Filterausdruck verwenden kann! Oder eine, die herausfindet, ob die abstrakte Datensatznummer in einem Array enthalten ist (um vorübergehend mit einer Art Prefetch-Filter zu arbeiten). Oder was weiß ich. Jemand interessiert? Ich jedenfalls schon.
Herzlich,
Tom
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Werner_Bayern »

Servus Tom,

hat zwar nicht direkt was damit zu tun, aber fürs Alter gibt's die Age-Funktion:

Code: Alles auswählen

select name1, name2, geb_datum, extract(year from age(adressen.geb_datum::DATE)) AS alter from adressen where … order by alter
und für Geburtstage reicht ein substring() oder die Funktion date_part()

Mit date_part() kann man das dann wiederum in eine Stored Procedure packen.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Marcus Herz »

Hier mal ein Kickoff,

Code: Alles auswählen

CREATE OR REPLACE FUNCTION public.Filtermatch(t_row kunde, filtermatch text )
  RETURNS boolean AS $$
DECLARE
BEGIN
if t_row.match = filtermatch then
  return TRUE;
end if;

RETURN false;
END;
$$ LANGUAGE plpgsql;
Die Abbfrage lautet:

Code: Alles auswählen

select * from kunde where filtermatch(kunde.*,'BAUER')
Man kann mit strtran den Filter Wert anstelle hier 'BAUER' schreiben. Die Funktion ist aber noch an eine Datei gebunden.
Man kann auch das verallgemeinern, dazu muss man die Doku lesen. Little by Little schaffen wir das gemeinsam

Grundsätzliich wird mit tabelle.* der aktuelle Satz übergeben
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Hallo, Werner.

Das Beispiel ist sicher nicht sehr tiefsinnig, aber es geht mir mehr um das How als um das What. Und es geht mir darum, die Filterausdrücke in der ISAM-Emulation funktionsfähig zu machen.

Hallo, Marcus.

Genau so etwas! Die Frage ist, wie das in einem herkömmlichen Filterausdruck in der ISAM-Emulation reflektiert werden würde.
Herzlich,
Tom
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Marcus Herz »

Da muss ich mir erst mal ein ISAM Tabelle erstellen. Verwende ich nie. Und wie handhabt die PGDBE einen Filteraudruck.
- Wann reicht die einen Filterausdruck an an PG Server als where Bedingung weiter?
- Ich hab da jetzt auf die Schnelle nichts in der Doku wegen stored proc gefunden
- Nur Alaska kann verrraten, welche Parameter an den Filterausdruck weitergegeben werden. In einer stored proc hab ich ja ohne weiteres keinen Zugriff auf den Inhalt der Tabelle
Das ist der Knackpunkt.
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Werner_Bayern »

Servus Tom,

gibt's dazu einen PDR? Der 7438 ist es ja nicht?
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Hallo, Werner.

Es geht um die PDRs 6970, 6963, 6962 und 6961. Und vermutlich noch ein paar weitere. PDR 7438 betrifft das Filterproblem aber auch - es geht darum, dass ein Filter keine Variablen der Anwendung referenzieren kann. Sie müssen durch ihre Werte ersetzt werden. "DbSetFilter({||kdnr == nKundenNr})" geht nicht. Man muss die Filterausdrücke mit Hilfe des Markooperators umbauen. Das ist nur insofern problematisch, dass ein Filter dann veränderte Inhalte solcher Variablen nicht mehr automatisch reflektiert. Wenn ich diesen Filter beispielhaft aktiv habe, springt ein DbGoTop() zum Datensatz, dessen "kdnr" dem Inhalt der Variablen im Moment der Navigation entspricht. Wenn ich diesen Inhalt ändere, also "nKundenNr" einen neuen Wert zuweise, und der Filter aktiv bleibt, führt ein abermaliges DbGoTop() normalerweise dazu, dass zur veränderten Kundennummer gesprungen wird. Mit dem Workaround für PDR 7438 muss ich den Filter neu setzen, falls ich dieses Verhalten in meiner Anwendung irgendwo verwende. Filter sind nicht mehr dynamisch.
Herzlich,
Tom
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Marcus Herz »

Hab das jetzt mal mit einer ISAM versucht.
Da erhalte ich den Fehler : Syntax Fehler in Makro" oder "expected return with error"
Wenn ich

Code: Alles auswählen

dbSetFilter( {||  field->companyname = "b" )})

gehts, bei

Code: Alles auswählen

dbSetFilter( {||  field->companyname like( "b*" )})
erhalte ich schon einen Fehler. Da bin ich nicht genug drin on der PGDBE. Ich bin raus
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Jan »

Tom,

auf der Alaska-Trello-Seite steht ganz oben in der Liste "In Progress" und mit höchster Priorität der Punkt "PostgreSQL fixing part-2.3 (Q3 2021)". Ich vermute mal das die damit sagen wollen, das die diesen Monat (halt der letzte im Q3) eine Reihe von Problemen mit der PostgreSQL lösen und beheben wollen.

Theoretisch.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Hallo, Jan.

Ich stehe mit Alaska deswegen in Verbindung. Sie werden das grundsätzliche Problem mit einigen Funktionen, die in Filtern nicht verwendet werden können, aber aller Voraussicht nach nicht lösen können. Deshalb wurde mir auch der Vorschlag unterbreitet, den Weg über Stored Procs zu wählen.
Herzlich,
Tom
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Marcus Herz »

Hat Alaska mehr zu der Lösung mit stored proc verraten?
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

@Marcus: Ja. Ich versuche morgen mal, das zusammenzufassen.
Herzlich,
Tom
Benutzeravatar
dtmackenzie
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Do, 22. Nov 2007 9:02
Wohnort: Leipzig
Hat sich bedankt: 66 Mal
Danksagung erhalten: 22 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von dtmackenzie »

Hallo Tom,

Du hast völlig Recht, Filters sind ein leidiges Thema, Du hast schon mal gesehen wie weit ich gegangen bin um die teilweise in SQL zu übersetzen...
Ich bin sehr gespannt auf die Zusammenfassung!
Stored Procs sind eine schöne Sache, nutze ich auch, kann sie aber bisher nur innerhalb SELECT-Befehle aufrufen.
Ein Mechanismus, die von Xbase++ Code in DbSetFilter aus aufzurufen wäre schon interessant - vielleicht mit etwas größeren Codeblocks bzw. Funktionen, die doch SELECT-Befehle ausführen?
Viele Grüße,
David
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Sorry, ich hatte viel zu tun. Ich versuche morgen mal, meine Infos zusammenzufassen.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Okay, ich habe von Alaska die Freigabe, das angehängte Dokument vorzustellen, als Diskussions- und vorläufige Handlungsgrundlage. Ich bin außerdem darum gebeten worden, darauf hinzuweisen, dass es sich um ein Dokument in Urheberschaft von Alaska Software handelt, worauf bitte zu achten ist, und dass die darin enthaltenen Informationen derzeit schnell altern. Alaska wird in ein bis zwei Monaten zu dieser Thematik online weitere Informationen veröffentlichen (Genaueres weiß ich auch nicht), also möglicherweise bessere Lösungen oder andere Ansätze.
Dateianhänge
migrating filters to posgresql.pdf
(682.87 KiB) 192-mal heruntergeladen
Herzlich,
Tom
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Marcus Herz »

- Da sind wir ja ganz nah dran, was ich geschrieben hatte. Man muss die Werte für die Filterfunktion übergeben, man hat hier keinen Zugriff auf den ganzen Satz.
- Und ja, sie verwenden den Filter Ausdruck als where Bedingung:
the Xbase++ ISAM emulation rewrites your filter expressions
aber eben nicht 1:1
- Die Beispiel sind banal, das Salz liegt in der realen Anwendung. Da kommt noch manches auf
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

@Marcus: Aber es zeigt sich, dass das eine weitaus komplexere Angelegenheit ist als zunächst gedacht. Ich denke, ich könnte ganz persönlich damit leben, wenn Filter, die man sowieso meistens auf kleine Datenmengen anwendet, genau so, wie es die ADSDBE manchmal macht, lokal ausgewertet würden, wenn also das WHERE ohne Filter generiert würde und der Filter dann lokal auf die Ergebnismenge (Tabelle, Scope) angewendet werden würde. Das ist vermutlich auch für Leute, die sich nicht so tief in die PG-Welt knien wollen, die bessere Lösung. Die Frage ist, ob das einen strukturellen Bruch nach sich ziehen würde.
Herzlich,
Tom
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Marcus Herz »

Die Idee von Alaska ist schon nicht schlecht. Mit Emulieren meinen sie, die Variablen aus dem Programm in die WHERE Bedingung hart einzutragen. Ändert sich die Variable im Programm, macht man ja meist wieder ein Gotop, was Alaska wohl als ein erneutes SELECT verwertet.
Lokale FIlter sind gut, wenn die Datemnemge klein ist. Bei großen hätt mans gern auf dem Server.
Eine eierlegende Wollmilchsau hat niemand erwartet oder versprochen, die wirds wahrscheinlich auch nicht geben. Aber >normale< Clipperansprüche sind ja dich einigermassen abgedeckt.
Warten wir mal ab
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
dtmackenzie
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Do, 22. Nov 2007 9:02
Wohnort: Leipzig
Hat sich bedankt: 66 Mal
Danksagung erhalten: 22 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von dtmackenzie »

Verstehe ich dies richtig, dass Funktionsnamen generell unverändert in die WHERE-Klausel kommen?
Dürfen wir also auch standard SQL-Funktionen in Filter-Ausdrücken verwenden? ;-)
Wird die Syntaxanalyse weitergeführt für Funktionsparameter und für geklammerte Ausdrücke im Allgemeinen?

Es wäre nett, falls Alaska diesen Weg geht, wenn sie eine DDL-Datei mit den wichtigsten Stored Procedures als plpgsql zur Verfügung stellen könnten, damit nicht jeder von uns die alle neu schreibt.

Operatoren sind auch ein Thema, welche sollten unterstützt werden?
Vergleiche, mathematische, logische und das berüchtigte "$"?
Insbesondere "x $ y" kann gut als "y LIKE ('%' || x || '%')" übersetzt werden.
Da x und y beliebige String-Ausdrücke sein dürfen fand ich solche Sachen schwierig in XBaseToSQL
(https://www.xbaseforum.de/viewtopic.php ... 11#p133511), aber Alaska dürften viel bessere Möglichkeiten für Syntaxanalyse haben.
Es gibt auch weitere Stolperfälle, z.B. "+" kann man oft so übernehmen so wie es ist, aber nicht für Strings - da braucht man "||"...
Datumswerte konvertiere ich prinzipiell zu Tagen seit 01.01.1970 mit "(EXTRACT(EPOCH FROM " + cDate + ") / 86400)", aber vielleicht wird das dann nicht mehr nötig - obwohl auch da das "+"-Operator ins Spiel kommt...
Der Code von XBaseToSQL ist schauderhaft, gebe ich zu, aber man kann ein paar solche Fällen daraus lesen...

Insgesamt finde ich den Ansatz von Alaska vielversprechend, aber die Beschreibung kommt mir noch ein bisschen übersimplifiziert vor. SET FILTER erlaubt nicht nur Spalten, Felder und Funktionen mit Vergleichsoperatoren sondern auch allgemeine Ausdrücke mitsamt weiteren Operatoren und Klammern - und das Ganze nicht nur hartkodiert sondern als Makro...

Letztendlich freue ich mich aber sehr, dass Alaska sich für das Thema engagieren! :-)
Viele Grüße,
David
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Ich hole das Thema mal wieder hoch.

Es ist ja offenbar einiges in Arbeit, und Alaska hat mir bestätigt, dass auch über lokale Filter nachgedacht wird. Da man Filter in aller Regel ohnehin nicht auf sehr große Datenmengen anwendet, ist es in dieser Konstellation auch nicht so schlimm, dass sozusagen eine ganze Tabelle vom Server kommt, also der Cursor alle Datensätze enthält, und man auf den Performancegewinn des serverseitigen Filters verzichten muss.

Das kann man in klassischen "SET FILTER-DO WHILE !Eof()"-Konstellation aber natürlich auch einfacher machen. Es hat den Vorteil, dass der Code auch weiterhin z.B. für DBFCDX oder ADS funktioniert, und in dieser Konstellation gäbe es ohnehin keinen Performancegewinn.

Wenn man also einfach ein:

Code: Alles auswählen

DbSetFilter({||MeinenochsokomplexeFilterBedingung})
DbGoTop()
DO WHILE !Eof()
  MachewasmitdenDaten()
  DbSkip(1)
ENDDO
nimmt und in solchen Code überführt:

Code: Alles auswählen

bMeinEvalBlock := {||MeinenochsokomplexeFilterBedingung}
DbGoTop()
DO WHILE !Eof()
  IF Eval(bMeinEvalBlock)
    MachewasmitdenDaten() 
  ENDIF
  DbSkip(1)
ENDDO
dann hat man für ISAM/filebasiert keinen Nachteil (hier wird sowieso immer alles gelesen, ob mit oder ohne Filter), kann aber mit der PGDBE arbeiten, ohne viel Code anpassen zu müssen, denn direkt auf den Daten lässt sich (fast) jeder noch so komplexe Ausdruck verwenden, aber eben nicht im Filter. Wie gesagt, das gilt für solche einfachen Konstruktionen. Ich habe für diesen Fall mein eigenes Workarea-Objekt, das sowieso einen eigenen Skipper und so etwas ähnliches wie einen zusätzlichen Filter kennt, etwas adaptiert, und DbSetFilter/SET FILTER TO über eine #command-Direktive verbogen, aber ansonsten lässt sich das auch anpassen, ohne auf die neuesten Entwicklungen warten zu müssen, falls man Konstrukte wie oben verwendet. In anderen Situationen mag es ein wenig schwieriger sein.
Herzlich,
Tom
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Jan »

Hallo Tom,

interessanter Ansatz. Und ja nun wirklich sowas von einfach und flexibel umzusetzen.

Aber kann es sein das da ein kleiner Fehler drin ist? Muß nicht in dem zweiten Beispiel das DbGoTop() von da oben runter unter das Eval() geschoben werden? Denn nur dort wäre ja der Filter aktiv.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Im unteren Beispiel ist kein Filter aktiv. Das, was vorher der Codeblock für den Filter war, wird hier einfach je Datensatz direkt evaluiert. Ist schon richtig.

Edit: Das ginge in diesem Fall (oder generell) auch ohne Zuweisung zu einem Codeblock (finde ich nur eleganter, für den Fall auch, dass die Bedingung mehrfach genutzt werden muss):

Code: Alles auswählen

DbGoTop()
DO WHILE !Eof()
  IF MeinenochsokomplexeFilterBedingung
    MachewasmitdenDaten() 
  ENDIF
  DbSkip(1)
ENDDO
Herzlich,
Tom
Benutzeravatar
dtmackenzie
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Do, 22. Nov 2007 9:02
Wohnort: Leipzig
Hat sich bedankt: 66 Mal
Danksagung erhalten: 22 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von dtmackenzie »

Hallo Tom,

wenn alles so einfach wäre... :D
Nur beim zweiten Lesen aber habe ich erkannt, dass das schon denkbar gewesen wäre.
Mein erster Gedanke war "es geht bei uns meistens um TBrowse", aber dann fiel mir ein, dass TBrowse schon vererbt ist und ich könnte theoretisch sowas in die Skipper-Methode einbauen...
Allerdings, um typischerweise nur ein paar Dutzend Datensätze aus vielen Tausenden auszufiltern befürchte ich, dass es zu langsam wäre - Filter sind bei uns schon auf relativ großen Datenmengen benutzt.
Daher bleibe ich vorerst bei meiner "Barock-Lösung", mit Übersetzung in SQL und einem parallel geführten Workarea mit SET RELATION auf __record.

P.S.
  • Unser (rein firmeninternes) System erlaubt sogar, dass Filterbedingungen von der Oberfläche fast überall eingegeben werden können. Gruselig, ja, aber das war schon so bevor ich es 2005 übernommen habe (das System hat seinen Ursprung in den frühen 90ern)! :wink:
  • Vielleicht habe ich vor ein paar Jahren, als ich mit Postgres anfing, sogar schon sowas Ähnliches probiert und wegen Performance-Bedenken abgewählt, es ist aber seitdem so viel passiert, dass ich mich nicht mehr genau daran erinnern kann.
Viele Grüße,
David
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von Tom »

Hallo, David.

Nein, einfach ist es nicht. Ich wollte letztlich nur darauf hinaus, dass ein Filter ja nichts weiter ist als eine Prüfung der gültigen Datensatzmenge zur Laufzeit. Wenn ein Filter aktiv ist, wird bei der Navigation geprüft, ob die Datensätze dem Filter genügen, und jene, auf die das nicht zutrifft, werden übersprungen, genau wie beim SET DELETED ON. Das macht die Engine implizit. Die Umsetzung der PGDBE in der ISAM-Emulation allerdings versucht, den Filter zum Server zu schieben, was eigentlich eine gute Idee ist, weil es Performance bringen würde, jedoch die bekannten Probleme zur Folge hat. Aber: Ganz egal, wie komplex ein Filter mal war, und wir haben Filter, die bewegen Dutzende Zeiger in anderen Tabellen, nudeln kräftig in Datenmengen herum, referenzieren mehrdimensionale Arrays und was weiß ich noch alles - auch mit der PGDBE lassen sich die Filterausdrücke jederzeit und verlustfrei verwenden, nur eben nicht in Filtern. Wenn ich ein einfaches DO-WHILE-!Eof()-Konstrukt habe, beispielsweise, um Daten zu extrahieren, dann kann ich einen Filter wie oben gezeigt einfach auflösen - aber seinen Ausdruck, also seine Logik weiterverwenden, und zwar eins zu eins. Wenn Filter komplexere Aufgaben abbilden und beispielsweise (das haben wir auch) sogar komplett frei definierbar sind, wird es etwas anstrengender. Worauf ich hinweisen wollte, ist lediglich, dass ein Workaround möglicherweise nicht immer direkt im Filter gesucht werden muss. Manchmal kann man das Problem lösen, indem man die Logik etwas umbaut, und das verlustfrei für alle bekannten Engines. Bei der PGDBE zieht man sich mit dieser Lösung den Nachteil, dass der Cursor die gesamte Tabelle umfasst, statt nur die Filtermenge zu liefern, aber das ist zumindest bei uns in den meisten Szenarien hinzunehmen.

Das Browse-Problem lösen wir über unsere eigene Klasse, die ohnehin schon zusätzliche Bedingungen für die Navigation kannte. Da können wir einfach die Filterbedingungen hinstecken und gut ist. 8)

Im Übrigen, und auch das sei noch einmal angemerkt, ist die PGDBE sensationelle Arbeit. Es sind zwar, und auch das hatte ich schon erwähnt, nicht nur ein paar Zeilen Code, die man ändern muss, aber die Arbeit ist überschaubar und lohnt sich wirklich. Und es macht einfach großen Spaß, mit einer Anwendung zu arbeiten, die gerade noch dateibasiert unterwegs war und jetzt plötzlich einen SQL-Server utilarisiert. Wir fahren übrigens alle Engines parallel, unterstützen also inzwischen DBF, ADS und PG im selben Code. Und das wird auch noch ein bisschen so bleiben.
Herzlich,
Tom
Benutzeravatar
dtmackenzie
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Do, 22. Nov 2007 9:02
Wohnort: Leipzig
Hat sich bedankt: 66 Mal
Danksagung erhalten: 22 Mal
Kontaktdaten:

Re: PGDBE: Stored Procs als Ersatz für UDFs in DbSetFilter()

Beitrag von dtmackenzie »

Hallo Tom,

ich stimme voll zu. PGDBE ist eine super Sache, meiner Meinung nach bei weitem die wichtigste strategische Neuerung von Alaska in diesem Jahrhundert. Abgesehen davon, dass es (zumindest) Lesezugriff von "außen" auf die Daten ermöglicht (einschließlich jede Menge nützliche Werkzeuge in der Postgres-Welt), löst es uns von unserer Abhängigkeit vom ADS-Server ab. ADS hat uns lange gute Dienste geleistet, ist aber nicht kostenfrei, begrenzt die Anzahl von Benutzern, ist keine vollwertige Datenbank, hat nicht so eine große Gemeinde und vielleicht auch nicht so eine sichere Zukunft wie Postgres. Irgendwann wird PGDBE zur ersten Wahl für die meisten, glaube ich. Wir sind nun voll auf PGDBE umgestiegen, andere Database-Engines sind nur im Legacy-Code für temporäre lokale Tabellen benutzt (typischerweise Reports).

Und ja, mit einem SQL-Server macht vieles Spaß, das zuvor muhsam war! Ad-hoc Anfragen, allgemeine Exports (zu CSV/Excel leicht zu programmieren, macht viele Reports überflüssig), Monitoring der Aktivitäten, sogar Vergleich ganzer Datenbanken (ich finde Folgendes richtig klasse - https://www.devart.com/dbforge/postgresql/datacompare/) u.v.m....
Viele Grüße,
David
Antworten