SQLs parsen

Ich müsste SQLs parsen + erweitern können. Konkret will ich ein WHERE-Statement - wenn nicht vorhanden - setze , aber auch vorhandene um eine Bedingung erweitern. Die Selects hängen btw je nach Anforderung beim Kunden ab. D.h. da sind eigentlich alle Varianten vorhanden - weswegen ich mit allem rechnen muss.

Kennt da zufällig jemand eine gute Bibliothek mit der das einfach umzusetzen ist? Momentan experimentiere ich mit dem hier rum: https://github.com/FoundationDB/sql-parser was wohl auf dem Apache Derby Parser basiert. Aber da hab ich bis jetzt noch keine Erfolge mit gemacht.

Ich habe auch mal Zql ausprobiert, wobei das schon seit fast 3 Jahren nicht mehr gepflegt wird.

hab ich auch schon öfters versucht:

eine where-klausel schrittweise aufbauen: geht, kann aber kompliziert werden (mit “1=1” starten und dann mit " AND …=?" oder " OR …=?" schön StringBuildern, kann aber beliebig komplex werden

eine bestehende Abfrage aufbrezeln: fast unmöglich, nach dem WHERE kommen group bys und havings, vorher schon joins und komplizierter zeugs, das ergebnis eines parsers kann ein ziemlich aufgebrezelter Baum sein, den du nicht wirklich ‘generisch’ entwirren kannst. Vom irrsinigen Quellcode mit den in ein paar Jahren unlesbaren Stringmanipulationen mal ganz zu schweigen.

Eine typische Kundenanforderung: “Wir wollen frei definierte Reports, aber wir können kein SQL und wollen uns auch nicht mit den verfügbaren Tools befassen, die sind zu kompliziert. Programmier mal was einfaches”.

Allein die Idee, man könne <, >, =, <=, >=, NULL oder nicht?, LIKE ‘regex’, AND, OR, NOT, subselects, … usw. mal einfach so “per Programm” und “ganz flexibel” haben, ohne sich wirklich mit SQL zu befassen ist absurd.

Möglichkeiten:

A) Du einigst dich mit deinen Kunden auf FEST vorgegebene Abfragen, die mit WHERE/HAVING 1=1 enden, an die du dann FESTE Klauseln auf die BEKANNTEN Spalten per Stringmanipulationen anfügst.

oder

B) Der Kunde installiert ein übliches Report-Designer Tool und lernt das.

oder

C) Du schleifst entsprechend geglättete Views nach außen durch und gehst mit Excel->Daten->Externe-Daten drauf, dann können die da selbst filtern

Aber beachte: A) ist die schlechteste, unflexibelste Lösung - und die einzige, bei der du Geld verdienst.

wie passt denn

zu

oder den Schwierigkeiten von unmöglich kompliziert aufgebauten Queries mit Join, Sub-Query, Gruppierung & Co?

man muss sich schon auf ein Thema beschränken, kann nicht die ganze Welt auf einmal abdecken,
entweder es gibt hohes SQL-Verständnis und komplizierte Queries zu beackern, oder einen SQL-freien Baukasten,
ersteres ist wohl das Thema hier,
einen konkreten Einhakpunkt mit 1=1 einzubauen wäre schön, leicht zu finden, aber das kann man wohl kaum fordern

Jap, dass hatte ich auch erkannt. Wollte erst schauen, ob ich vllt einfach nur das WHERE selber erkennen lassen kann + entsprechend erweitern. Aber wenn dann noch Subselects kommen, dann müsste ich diese auch noch erkennen … dass scheint ein richtiger Rattenschwanz zu sein.

Und dass das WHERE auch sehr Zentral stehen kann (wie du schon richtig sagst: dank group bys, having, order by, …) verkompliziert alles nochmal erneut.

Mit den Parsern bin ich bisher nicht glücklich geworden. Ich glaube ich versuche es jetzt auf einem anderen Weg: Ich baue Kommentare in den Select ein, welche später einfach ersetzt werden können. Z.B.: SELECT * FROM tabelle WHERE /*HOOK:WHERE*/ type = "verzweiflungstat";

Falls jemand doch noch eine bessere Idee hat - oder eine Bibliothek kennt mit der man das Problem lösen kann, der kann es ja gerne posten (da wäre ich nach wie vor dankbar für). Aber da ich denke, mit dem Kommentar-Ersetzen mein Problem lösen/umschiffen zu können, werde ich das Thema erstmal auf gelöst setzen.

evtl. etwas Offtopic zu Ziel deiner Suche, aber nochmal naiv nüchtern begonnen: worin liegen eigentlich die Schwierigkeiten?
jede Query oder Subquery, ob im Union, Select- oder Where-Teil, dürfte doch deutlich mit SELECT beginnen, für Schachtelung zudem deutliche Klammerung?

FROM ist auch nicht zu vermeiden, es gibt vielleicht ein paar Join-Varianten, aber nach etwas Mühe diese selbst in Eigenprogrammierung drin, Tools sollten es umso klarer können,
dann eindeutig Ende des FROM-Teils daran zu erkennen dass WHERE oder einer der anderen nächsten Schritte (GROUP, ORDER, Query-Ende etwa durch Klammer) folgt,

damit Einsetzpunkt gefunden, WHERE evtl. ergänzen oder den klar definierten bisherigen WHERE-Teil in Klammern setzen und mit AND fortführen, mehr soll es ja anscheinend nicht sein,

ob WHERE des Hauptteils oder einer Subquery sollte beim Parsen jederzeit bewußt sein, welche davon man modifizieren will muss man schlicht wissen und entscheiden, keine direkte Programmieraufgabe

sieht doch alles überschaubar aus, egal wie groß der Baum wird, oder ein konkretes Problem-Beispiel? :wink:


bei
WHERE /*HOOK:WHERE*/ type = 'x' OR type = 'y';
musst du aufpassen was daraus werden soll, was du ergänzen willst, evtl. der Rest zu klammern:

WHERE date < 'heute' AND type = 'x' OR type = 'y';
oder
WHERE date < 'heute' AND (type = 'x' OR type = 'y');
hat evtl. ganz unterschiedliche Bedeutungen, je nach Ordnung von AND und OR, die ich mir lieber gar nie merke, Klammern sind ja sichere Variante

Naja, ein Problem ist dabei sicherlich die Zeit. Das wird mir wohl mit der Deadline zu knapp um da jetzt selber noch einen Parser zu schreiben. Ein konkretes Problembeispiel habe ich jetzt auch nicht. Höchstwahrscheinlich werden die SQLs nicht komplex - aber einer reicht aus und ich habe dann ein entsprechendes Problem ;-).

Und zu dem Klammerproblem: dass sollte man auch ganz gut abfangen können, wenn man beim schreiben des SQLs dran denkt. Also wenn es sich auswirkt, dann kann ich ja das ja schon Klammern: WHERE /*HOOK:WHERE*/ (type = 'x' OR type = 'y') läuft auch ohne den hook dann noch richtig.

eine Menge Vertrauen auf korrekte Vorarbeit, aber wenn die Möglichkeit dazu besteht, dann ja günstig

Ja, i.d.R werde wohl ich die Sachen pflegen dürfen. Aber die Mitarbeiter schule ich einfach dahingehend, dass Sie beim verwenden des Hooks die vorrherschende Bedingung klammern sollen. Da würde mir kein Szenario einfallen, wo das Probleme machen sollte (sofern man eben an die Klammern denkt).

das hatte ich auch oft
[SQL]
WHERE /HOOK:WHERE/ type = ‘x’ OR type = ‘y’;
[/SQL]
und
[SQL]
WHERE /HOOK:WHERE/ type = ‘x’ AND type = ‘y’;
[/SQL]
Wie fügst du da neue Bedingungen ein? Steht am Ende ein AND oder ein OR?

Klammerungen mit zu schleppen führt auch in ein Gewirr und Desaster…

Ein anderes Problem, das ich auch immer wieder hatte: Sonderzeichen bei der Eingabe usw.

Oder beim Datum: der Benutzer gibt ein “>2012” und musst das dann in die entsprechende SQL-Bedingung übersetzen…

Programmatisch. Ich nutze mehrere Hook-Points. Ein Hook kommt nur bei bestehenden WHERE-Clauses vor, da wird dann ein AND zusätzlich an die Bedingung angehängt. Bei anderen Hook-Points fehlt dann das komplette Where - da brauche ich mir um AND/OR/Klammern keine Gedanken machen.

Implementiert hab ich das ganze so, dass ich eben HOOKs über eine Klasse auffinden und ersetzen kann. Über die Klasse kann ich auch prüfen, ob bestimmte HOOKs vorhanden sind und dementsprechend verläuft dann meine Logik im Programm.

Geht. Die SQLs werden bei mir über mehrere Stufen erstellt. Das Programm gibt einen Default-SQL vor und der kann vom Anwender über Configs überschrieben werden. In den SQLs können dann auch nochmals eigene Variablen verwendet und definiert werden, welche später vom Programm entsprechend bearbeitet werden. Vieles Kundespezifische kann ich dadurch auslagern. Dann brauche ich im SQL selber eigentlich nur noch die Variable für die Kundenspezifische WHERE-Bedingung in Klammern zu setzen und schon läuft das automatisch immer richtig.

[QUOTE=Tomate_Salat;102782]Programmatisch. Ich nutze mehrere Hook-Points. Ein Hook kommt nur bei bestehenden WHERE-Clauses vor, da wird dann ein AND zusätzlich an die Bedingung angehängt. Bei anderen Hook-Points fehlt dann das komplette Where - da brauche ich mir um AND/OR/Klammern keine Gedanken machen.

Implementiert hab ich das ganze so, dass ich eben HOOKs über eine Klasse auffinden und ersetzen kann. Über die Klasse kann ich auch prüfen, ob bestimmte HOOKs vorhanden sind und dementsprechend verläuft dann meine Logik im Programm.

Geht. Die SQLs werden bei mir über mehrere Stufen erstellt. Das Programm gibt einen Default-SQL vor und der kann vom Anwender über Configs überschrieben werden. In den SQLs können dann auch nochmals eigene Variablen verwendet und definiert werden, welche später vom Programm entsprechend bearbeitet werden. Vieles Kundespezifische kann ich dadurch auslagern. Dann brauche ich im SQL selber eigentlich nur noch die Variable für die Kundenspezifische WHERE-Bedingung in Klammern zu setzen und schon läuft das automatisch immer richtig.[/QUOTE]

Ich hab auch mehrere so Lösungen (die Leute wollen das ja immer, bei Excel geht es ja auch) und bin wirklich nicht glücklich damit. Verkrüppelter Schmarren, im Lauf der Zeit durch zig Ausnahmen spaghettifiziert und noch dazu völlig überflüssig - weil seeeeeeehr selten genutzt. Aber was macht man nicht alles für Geld.

Ja das ist auch meine Sorge, dass wird wohl noch ein wenig weiter wuchern, wenn ich noch mehr Sachen dran erweitern darf. Momentan bohr ich die Anwendung an allen möglichen Stellen auf, um die neuen Anforderungen da irgendwie rein zu bekommen … og was mich der Featureteil schon an Nerven/Zeit gekostet …