# SQL-Statement parser?



## TheSunToucher (30. Mai 2005)

Hallo,

ich muss für ein aktuelles Projekt SQL-Statements parsen und diese unter Umständen verändern, also beispielsweise den Tabellennamen in einem Select-Statment finden und diesen ersetzen. Ich habe begonnen eine Java-Klasse zu schreiben und mit liebevoll gestalteten RegularExpressions einfache Statements zu parsen. Allerdings ist die ganze Angelegenheit sehr komplex, da bei SQL-Statements dem Einfallsreichtum mancher Entwickler keine Grenzen gesetzt sind. Lange Rede, kurzer Sinn, kennt jemand vieleicht ein (kostenloses, OpenSource) Produkt, mit dem man SQL zuverläßig parsen kann?

Ich stelle mir das so vor das ich ein "Statment"-Objekt mit Hilfe des SQLs anlege und dann mit Gettern und Settern arbeiten kann.

Danke, gruß
Tim


----------



## bronks (30. Mai 2005)

Wenn Du noch ein bissl mehr zu Sinn und Zweck erklären könntest ... Mir kommt das ganze schon etwas bekannt vor, aber konkret ...


----------



## TheSunToucher (30. Mai 2005)

Ich versteh die Frage nicht, ich habe doch gesagt was ich machen will. Am besten soll er möglichst viel können, ich möchte den Tabellennamen ändern oder escapen können, ebenso Spaltennamen. Ich möchte values ersetzen können und vieleicht die Syntax ein bischen verändern. 
Das ganze um die Unterschiede der Datenbanken auszugleichen. Zum Beispiel sind die Tabellennamen auf manchen Datenbank-Systemen Casesensitiv, auf anderen nicht. Oracle kennt keine Leerstrings usw...


----------



## Sky (31. Mai 2005)

Verstehe ich das richtig: Du willst in Abhängigkeit von einer Eingabe 
	
	
	
	





```
SELECT * FROM bla
```
 und der zugehörigen DB, den Aufruf 
	
	
	
	





```
SELECT * FROM blub
```
 machen???

Also ich glaube, das es da nix fertiges gibt! Ich bin der Meinung, wenn sich jemand nicht an einen Standard halten kann, dann soll er die Finger von den Dingen lassen! 
Ein Beispiel: Wenn es Datenbanken gibt, welche Casesensitiv arbeiten, dann sollte man die Tabellennamen immer korrekt angeben und die DB's, welche nicht Casesensitiv arbeiten werden auch damit zurecht kommen!


----------



## bronks (31. Mai 2005)

TheSunToucher hat gesagt.:
			
		

> Ich versteh die Frage nicht, ich habe doch gesagt was ich machen will.


Ich verstehe dagegen Deine Anforderung und meine, daß Du an die ganze Sache total anders rangehen mußt. Ich hab keine Ahnung, warum Du SQLs hast, die falsche Feld- und Tabellennamen enthalten und auch noch in der Syntax angepaßt werden müssen. Soetwas mach man m.E. anders und je nach Zweck total verschieden.


----------



## Bleiglanz (31. Mai 2005)

sowas (mit gettern und settern) gibts nicht

ich würd das lieber lassen, wie du schon erkannt hast kann handgestricktes optimiertes SQL extrem komplex werden, und diese Komplexität müsste das von dir gewünschte Tool auch mitmachen



> ...muss für ein aktuelles Projekt SQL-Statements parsen und diese unter Umständen verändern, also beispielsweise den Tabellennamen in einem Select-Statment finden und diesen ersetzen


das ist ziemliches Schrott-Design, vor allem wenn die SQL Statements schon fertig sind und nicht mehr adaptiert werden können

ansonsten würde ich eben mit Platzhaltern im SQL arbeiten (so ala Veleocty ${tab1} durch den "echten" Tabellennamen ersetzen

=> dazu müssten aber die SQL-Statements VORHER verändert werden...


----------



## TheSunToucher (31. Mai 2005)

Ich kann eure Einwände verstehen und hätte wahrscheinlich eine ähnliche Antwort verfaßt, aber ich habe mir diese Taktik nicht überlegt, sondern mein Chef. Ich muss das Problem lösen, also versuche ich es möglichst elegant. Die Statements ändern kommt nicht in Frage, sondern es soll an zentraler stelle geschehen.

Es gibt schon einige Sachen die an zentraler Stelle mit den SQL-Statements gemacht werden, das funktioniert schon ganz gut. Das jetztige Vorhaben überteibt's ein bischen, aber wie gesagt, ich kann nichts daran ändern.

Folgendes soll manipuliert/normalisiert werden:

Tabellen und Spaltennamen toUpperCase
escapen von reservierten wörtern, die als Tabellen- oder Spaltenname verwendet werden
besondere behandlung von LeerStrings auf Oracle
Syntax-Unterschiede wie z.B. "AS" auf Oracle

Wie auch immer, ich muss halt eine Lösung suchen. Ich habe im Internet eine Klasse gefunden die mit JavaCC geschrieben wurde, leider bietet die nicht die Möglichkeiten die ich mir erhofft hatte. Ich bin aber fest davon überzeugt das es sowas schon gibt, immerhin müssen "100% pure Java Datenbanken" ala HSQLDB die Statements auch parsen, oder liege ich falsch?

Is' komisch, aber ich wäre euch trotzdem für eure Tipps dankbar
Gruß
Tim


----------



## Bleiglanz (1. Jun 2005)

# Tabellen und Spaltennamen toUpperCase

überflüssiger Käse

# escapen von reservierten wörtern,
# die als Tabellen- oder Spaltenname verwendet werden

ja und? replacaAll? du weisst ja gar nicht, wann etwas markiert werden soll? SELECT 'SELECT','MAX','class','do while' FROM DUAL

da müsstest du ja immer noch die quotes mitzählen, ob das nicht zufällig eine literale Konstante ist

# besondere behandlung von LeerStrings auf Oracle

wahnsinn, wie soll denn das nun wieder gehen...?

# Syntax-Unterschiede wie z.B. "AS" auf Oracle 

wozu?



> Die Statements ändern kommt nicht in Frage, sondern es soll an zentraler stelle geschehen


Schon mal was von der broken window theorie gehört? Habe den starken Verdacht, dass hier ein schrotthaufen durch einen neuen (extrem aufwändigen) Layer noch repariert werden soll


----------



## TheSunToucher (1. Jun 2005)

Hi Bleiglanz,

wie gesagt ich hab mir den Mist nicht ausgedacht, muss es trotzdem machen, außer du bietest mir einen lukrativen Job in deiner Firma an ;-]



			
				Bleiglanz hat gesagt.:
			
		

> # Tabellen und Spaltennamen toUpperCase
> überflüssiger Käse



Naja, wenn ich auf SQL-Server eine Binary-Kollation nutzen will sind die Spalten- und Tabellennamen Casesensitiv. Und auf Oracle anscheind immer, oder kennst du/ihr eine Möglichkeit das zu ändern?



			
				Bleiglanz hat gesagt.:
			
		

> # escapen von reservierten wörtern,
> # die als Tabellen- oder Spaltenname verwendet werden
> 
> ja und? replacaAll? du weisst ja gar nicht, wann etwas markiert werden soll? SELECT 'SELECT','MAX','class','do while' FROM DUAL
> ...



Dessen bin ich mir natürlich bewußt, einfache Statements wie das von die gepostete ersetzt meine Klasse schon vollkommen korrekt. Dafür habe ich mittlerweile 300 Zeilen Code und RegularExpressions, die mittlerweile wirklich unleserlich sind, aber das Ding kann schon eine ganze Menge. Aber der Fakt, das es mit replaceAll nicht getan ist, hat mich ja erst auf die Idee gebracht nach einen StatementParser zu suchen.



			
				Bleiglanz hat gesagt.:
			
		

> # besondere behandlung von LeerStrings auf Oracle
> 
> wahnsinn, wie soll denn das nun wieder gehen...?



Ich habe in der Vergangenheit schon etwas ähnliches für die Portierung nach SQL-Server in den Layer implementiert. Eigentlich ist unsere Anwendung auf DB2 zu Hause, da gibt es den SQL-Datentyp DATE, auf SQL-Server gibt es den nicht, sondern nur DATETIME. Da sich DATETIME anders verhält als DB2's DATE, habe ich auf SQL-Server ein VARCHAR daraus gemacht und beim abholen mit "resultSet.getString()" wird der String in ein Datum geparst.
Dieser Dirty-Trick funktioniert einwandfrei, wir mußten nicht mehrere Hundert Klassen und JSPs überarbeiten und es ist erfolgreich im Betrieb beim Kunden!
Daher könnte ich mir vorstellen, das ich sowas auch für Oracle basteln kann...



			
				Bleiglanz hat gesagt.:
			
		

> # Syntax-Unterschiede wie z.B. "AS" auf Oracle
> wozu?



Die Syntax auf DB2, also unserer aktuellen Statements ist etwas anders als auf Oracle, um die Statements nicht alle prüfen zumüssen soll hier eine zentrale Änderung herbei. Hier (zu Hause) habe ich kein Oracle, ich werde bei gelegenheit mal ein paar Beispiele posten.



			
				Bleiglanz hat gesagt.:
			
		

> > Die Statements ändern kommt nicht in Frage, sondern es soll an zentraler stelle geschehen
> 
> 
> Schon mal was von der broken window theorie gehört? Habe den starken Verdacht, dass hier ein schrotthaufen durch einen neuen (extrem aufwändigen) Layer noch repariert werden soll



Tja, leider... und ich bin die arme Sau an der es hängen bleibt...
Nee, von der broken window theorie hab ich leider noch nix gehört, aber sobald ich "absenden" geklickt habe werde ich mal google'n.


----------



## TheSunToucher (1. Jun 2005)

*Off-Topic @Bleigeiz:*

Ich habe mehrere Artikel zur "broken Window Theorie" gefunden, ich schätze mal du nimmst bezug auf folgendes:



> „Sozialpsychologen und Polizeibeamte stimmen darin überein, daß ein zerbrochenes Fenster in einem Gebäude, das nicht repariert wird, die Zerstörung der restlichen Fenster des Gebäudes innerhalb kürzester Zeit nach sich zieht. Dies gilt für gehobene Nachbarschaftsgegenden ebenso wie für heruntergekommene. Die Zerstörung von Fensterscheiben geschieht nicht deshalb übermäßig oft in einer Gegend, weil dort viele Zerstörer von Fensterscheiben leben, während sich in anderen Gegenden Fensterscheibenliebhaber aufhalten. Viel eher trifft zu, daß ein nicht wieder in Stand gesetztes Fenster ein Zeichen dafür ist, daß an diesem Ort keiner daran Anstoß nimmt. So können beliebig viele Fenster zerstört werden, ohne daß damit gerechnet werden muß, für den Schaden aufzukommen. (Es macht ja auch eine Menge Spaß.)“



Quelle: netzwerk.wisis.de/id~qV5o2QlDkSUNw9X3/text/335.htm

Aber was willst du mir damit sagen? Das wenn ich die inkompatiblen Statements nicht berichtige die anderen Programmierer weiter solche schreiben? Naja, wenn der StatementParser korrekt funktioniert, dann können sie das ja machen. Da wäre, als ob man ein Bild eines intakten Fensters vor die kaputten stellt, damit die Besucher denken die Gegend wäre ordentlich ;-]


----------



## Bleiglanz (2. Jun 2005)

damit ist eigentlich gemeint, dass man "Schrott" immer gleich reparieren soll (hab ich im "Pragmatic Programmer" gelesen, das Argument finde ich nicht schlecht)

300 zeilen code mit unleserlichen preparedStatements zusammenhacken - das kostet auch Zeit und Geld. Und wenn du jetzt einen Parser hast, kannst du diese Regexe wieder auf den Müll werfen...

Das Vertrauen aller im Projekt beteiligten Programmierer ist einfach dahin, wenn es nur eine einzige Stelle gibt, bei der alle sagen: "das ist hier Schrott, muss aber drinbleiben, weil..."

Andere Progger könnten verleitet werden zu sagen: "na ja, die ganze Datenbank-Zugriffsschicht ist eh schon Mist, da kann ich bei meinen eigenen Sachen auch ein paar wirre Hacks einbauen"...



> mehrere Hundert Klassen und JSPs


in denen literal <% %> java quelltext UND SQL-Statements enthalten sind???!!!!??? Klingt nach Mülltonne...


klar, du kannst nix dafür, aber in dem Fall würde ich meinem Chef dringend ein komplettes Refactoring anraten!

JSP sollen kein Java enthalten

native SQL-Strings sollten an einer zentralen Stelle verwaltet werden

Wenn man wirklich DB unabhängig sein will, dann funktioniert das eigentlich nur mit Code-Generatoren bzw. den gängigen O/R Mappern

Ausserdem: Ihr habt eine Anwendung die von Oracle nach DB2 geschoben werden soll? Beide DBs bieten die Möglichkeit, Stored Procs und eingene Spaltentypen zu definieren, damit könnte man gewisse unterschiede wesentlich einfacher ausgleichen


----------



## TheSunToucher (2. Jun 2005)

Jo, ich gebe dir recht, aber die meisten Entscheidungen haben finanzielle, politische und persönliche Gründe. Ich und auch die meisten der Mitarbeiter kennen sehrwohl JavaServerFaces, Taglibs, Struts, Hibernate usw. Ich glaub es ist jedem klar das dieser historisch gewachsene Haufe Quellcode am besten komplett weggeschmissen und mit dem jetzigen KnowHow, der Erfahrung und aktuellen Techniken neuprogrammiert werden sollte, aber ich hab wohl keine Chance den Chef davon zu überzeugen. Deshalb ist es leider müßig darüber zu diskutieren...


----------

