Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Seltsamer Fehler bzgl. Parameterobjekt (https://www.delphipraxis.net/180284-seltsamer-fehler-bzgl-parameterobjekt.html)

Jumpy 7. Mai 2014 15:01

Datenbank: SQLServer • Version: ? • Zugriff über: ADO

Seltsamer Fehler bzgl. Parameterobjekt
 
Hallo,

ich bekomme bei einem einfachen Select eine Exception mit folgender Fehlermeldung:

Zitat:

Ein Parameterobjekt ist nicht ordnungsgemäß definiert. Inkonsistente oder unvollständige Informationen wurden angegeben.
Ich habe die Meldung natürlich gegoogelt, da war auch von einem Bug in ADO-Komponenten in älteren Delphis die Rede, aber da ging es um Inserts oder Updates und hatte was mit den Anführungsstrichen oder anderen Sonderzeichen zu tun.
Bei mir ist es aber nur ein Select und das SQL-Statement ist ohne Parameter, daher frage ich mich was der Fehler soll.
Die Meldung kommt mMn (ist innerhalb einer Webanwendung daher schlecht zu debuggen) nicht beim Öffnen der Abfrage sondern nach einem Locate und dem Auslesen eines Feldes der Datenmenge.

Jetzt der Clou(?): Der (Text-)Inhalt dieses Datenfeldes (mit dieser ID) enthält einen Doppelpunkt. Entferne ich in der Datenbank den Doppelpunkt in dem Feld dieses einen Datensatzes ist alles OK.
Also nicht Doppelpunkt im SQL-Statement, sondern im Ergebnis!

Wie kann das sein? Gibt es da noch einen anderen Bug (D6)?

Dejan Vu 7. Mai 2014 16:10

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Wie lautet der SQL-Befehl?

Kannst Du nicht ein Beispielprojekt erstellen, in dem Du die Query exrahierst und eine Form mit einer TADOQuery erzeugst, dann ein Button, der das Teil öffnet und dann siehst du ja, wo es hängt.

p80286 7. Mai 2014 16:47

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Ich vermute, daß das Problem im
Delphi-Quellcode:
Locate
steckt.
U.U. ist der Klartext
Code:
select id from data where text='mit doppelpunkt:'
und das wird dann als Parameter interpretiert.
Als workaround fällt mir ad hoc nur das durchscrollen per
Delphi-Quellcode:
.Next
und
Delphi-Quellcode:
Pos
ein, und das ist ja wahrhaftig nicht soo doll.
Kannst Du das ursprüngliche Select nicht so anpassen, daß Du das
Delphi-Quellcode:
Locate
nicht mehr benötigst?

Gruß
K-H

Nachtrag hast Du mal mit " und ' gespielt?
Da gibt es ja recht viele Seltsamkeiten

Dejan Vu 7. Mai 2014 16:50

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Wenn man sich den Code von 'Finde die Parameter im SQL-Text' anschaut, muss man sich nicht wundern.
Ob das am Locate liegt, würde ich dann bezweifeln. Abhilfe: den Suchtext mit dem Doppelpunkt als Parameter deklarieren,
also
Delphi-Quellcode:
ADOQuery.SQL.Text = 'select * from tabelle where feld = :ParamMitDoppelPunkt';
ADOQuery.Parameter['ParamMitDoppelPunkt'] := 'Der Text mit dem Doppelpunkt: ';
Achtung! Pseudocode. Hab hier kein Delphi.

p80286 7. Mai 2014 17:06

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Hast Du vllt. den Gag übersehen?
Zitat:

Zitat von Jumpy (Beitrag 1258235)
Jetzt der Clou(?): Der (Text-)Inhalt dieses Datenfeldes (mit dieser ID) enthält einen Doppelpunkt. Entferne ich in der Datenbank den Doppelpunkt in dem Feld dieses einen Datensatzes ist alles OK.
Also nicht Doppelpunkt im SQL-Statement, sondern im Ergebnis!

Gruß
K-H

mkinzler 7. Mai 2014 17:10

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Die genaue Abfrage würde uns aber wirklich weiterhelfen.

Dejan Vu 8. Mai 2014 06:54

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von p80286 (Beitrag 1258244)
Hast Du vllt. den Gag übersehen?

Nope. Aber Du schreibst.
Zitat:

Zitat von p80286 (Beitrag 1258240)
U.U. ist der Klartext
Code:
select id from data where text='mit doppelpunkt:'
und das wird dann als Parameter interpretiert.

Und darauf bin ich dann eingegangen. Wenn hier also einer den Gag nicht verstanden hat, dann... ach ist doch egal.

Wenn man das allerdings ausprobiert, sieht man, das alles wie gewünscht funktioniert.

Die vom Fragesteller beobachtete Problematik kenne ich nicht und kann mir das auch nicht vorstellen, denn die Query wird vor der Ausführung geparst, ergo beziehen sich alle Probleme bezüglich der Parameter auf den Zeitpunkt *vor* der Ausführung.

Was sein kann ist, das das Dataset mit einem anderen Dataset verknüpft ist und dort dann der Hund begraben liegt. Man kann die ja so verknüpfen, das beim Record-Wechsel in DS1 eine neue parametrierte Query DS2 ausgeführt wird (Datasource-Eigenschaft von DS2 setzen. Dann könnte ein 'Locate' im DS1 zu Problemen führen (wenn die Query in DS2 fehlerhaft ist). Soweit ich mich erinnere muss der Parameter in DS2 einem Feldnamen in DS1 entsprechen.

Aber das ist alles nur Ratenspiel bzw. müsste man das ausprobieren, aber dazu habe ich jetzt keine Lust.
Delphi-Quellcode:
DS1 := 'Select MasterID, moreData from MasterTable';
DataSource1.Dataset := DS1;
DS2.DataSource := DataSource1;
DS2.SQL.Text := 'Select * from Details where MasterID = :MasterID';
Das mal testen. Und dann im DS2.SQL den Parameternamen ändern oder ein Leerzeichen zwischen ':' und 'M' setzen (damit das zu Problemen führt). Dann DS1 öffnen und wieder per Locate wechseln (obwohl das Locate überflüssig wäre, denn es knallt schon beim Öffnen von DS2)

Jumpy 8. Mai 2014 07:58

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Sorry, war gestern nicht mehr online und konnte das nicht weiter ausführen.

Die Tabelle enthält Textbausteine für meine Web-CGI, quasi ein Mini-CMS für Arme.
Sobald aus dem Webrequest ersichtlich ist, welche neue Web-Seite angefordert wurde, wird die Query geöffnet, die da lautet:

SQL-Code:
Select * From
  Webtexte
Where
  Seite='*'
  or Seite='Name der angeforderten Seite'
  or Kategorie='Menuitem'
Das einzige was an dem Statement variabel ist ist der Name der angeforderten Seite. In Delphi sieht die Stelle so as:

Code:
Webtexte.SQL.Add('or Seite = ');
Webtexte.SQL.Add(QuotedStr(GetPagename(RequestedPage)));
Die GetPagename-Funktion liefert nur definierte Namen zurück, so dass ich mich nicht um SQL-Injektion o.ä. sorgen musste und keine Parameter benutze!
Wie man sieht enthält auch die Where-Klausel keinen Vergleich mit einem Text der einen Doppelpunkt enthält.

Es gibt dann eine Funktion, die aus der bereits ohne Fehler geöffneten Datenmenge einen Textbaustein anhand der ID sucht und in dieser tritt mMn der Fehler auf. Sinngemäß (hab Delphi noch nicht auf):

Delphi-Quellcode:
function GetContentFromID(ID:String):String;
begin
  if Webtexte.Active then
    begin
    Webtexte.Locate('ID',ID,[]);
    Result:=Webtexte.FieldByName('DE').AsString;
    end;
end;
Es werden während der Laufzeit der CGI mehrere Textbausteine mit verschiedenen ID's aus der Datenmenge geladen, daher weiß ich, dass diese sich auf jeden Fall öffnet. Nur halt der eine Datensatz, der einen Doppelpunkt enthält, macht halt Probleme. Der Text in dem Datensatz ist:
"Gehen Sie dabei wie folgt vor:"
Laß ich den Doppelpunkt weg, funzt halt alles.

Ich hoffe so wird klarer warum ich das nicht nachvollziehen kann.

mkinzler 8. Mai 2014 08:13

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Vor Seite fehlt höchstwahrscheinlich ein Leerzeichen, bze es schadet nicht dort eins einzufügen

Delphi-Quellcode:
Webtexte.SQL.Add(' or Seite = ');
Zudem würde ich, wie auch schon mehrmals genannt, Parameter verwenden!

Sherlock 8. Mai 2014 08:33

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Dadurch das
Delphi-Quellcode:
SQL.Add
eine neue Zeile (tatsächlich einen neuen String in die StringListe, ich weiss) einfügt ist das Leerzeichen vor dem 'or' überflüssig.
Es sei denn natürlich, die verwendeten DB-Komponenten klöppeln daraus einen einzigen zusammenhängenden (nicht durch CR getrennten) String.

Sherlock

mkinzler 8. Mai 2014 08:38

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Dadurch das SQL.Add eine neue Zeile (tatsächlich einen neuen String in die StringListe, ich weiss) einfügt ist das Leerzeichen vor dem 'or' überflüssig.
Nein ist er nicht.
Zitat:

Es sei denn natürlich, die verwendeten DB-Komponenten klöppeln daraus einen einzigen zusammenhängenden (nicht durch CR getrennten) String.
Müssen sie ja, da das Statement an den SQL-Server weitergeben.

Blup 8. Mai 2014 08:50

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von Jumpy (Beitrag 1258272)
Das einzige was an dem Statement variabel ist ist der Name der angeforderten Seite. In Delphi sieht die Stelle so as:

Code:
Webtexte.SQL.Add('or Seite = ');
Webtexte.SQL.Add(QuotedStr(GetPagename(RequestedPage)));
Die GetPagename-Funktion liefert nur definierte Namen zurück, so dass ich mich nicht um SQL-Injektion o.ä. sorgen musste und keine Parameter benutze!
Wie man sieht enthält auch die Where-Klausel keinen Vergleich mit einem Text der einen Doppelpunkt enthält.

Gerade das sieht man eben nicht, definierte Namen könnten auch Doppelpunkte enthalten.
SQL-Injektion ist eben nur ein (seltener) Grund und warum mit Parametern gearbeitet wird.
Auf jeden Fall kann man mit Parametern diese Fehlerquelle erst einmal ausschließen.

Wenn konkret ein bestimmter Datensatz auf Grundlage der ID benötigt wird, bietet es sich doch an, einfach nur diesen Datensatz mit einer zusätzlichen Abfrage zu holen.
Ein Problem mit Zeilenumbrüchen ist mir nicht bekannt, es spricht aber auch nichts dagegen die einzelnen Bedingungen zu klammern, ist für mich lesbarer.

Auf jeden Fall hilft es nicht alle Vorschläge wegzudiskutieren, ausprobieren bringt dich weiter.

Sir Rufo 8. Mai 2014 09:15

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Also ich habe das mal versucht nachzustellen, konnte aber keine Probleme diesbezüglich feststellen.

Doppelpunkte im Text können mit Locate einwandfrei gefunden werden.

p80286 8. Mai 2014 10:55

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von Jumpy (Beitrag 1258272)
SQL-Code:
Select * From
  Webtexte
Where
  Seite='*'
  or Seite='Name der angeforderten Seite'
  or Kategorie='Menuitem'

dieses
Code:
Seite='*'
erscheint mir aber sehr obskur.
Und bei jeder Abfrage alle MenueItems?

Zitat:

Zitat von Jumpy (Beitrag 1258272)
"Gehen Sie dabei wie folgt vor:"
Laß ich den Doppelpunkt weg, funzt halt alles.

Ich hoffe so wird klarer warum ich das nicht nachvollziehen kann.

Leider nicht, Ich habe auch gerade versucht, das nach zu vollziehen konnte das Fehlverhalten allerdings auch nicht provozieren.

Ich denke es wird langsam Zeit für den Debugger.

Gruß
K-H

Sherlock 8. Mai 2014 12:15

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von mkinzler (Beitrag 1258277)
Zitat:

Dadurch das SQL.Add eine neue Zeile (tatsächlich einen neuen String in die StringListe, ich weiss) einfügt ist das Leerzeichen vor dem 'or' überflüssig.
Nein ist er nicht.
Zitat:

Es sei denn natürlich, die verwendeten DB-Komponenten klöppeln daraus einen einzigen zusammenhängenden (nicht durch CR getrennten) String.
Müssen sie ja, da das Statement an den SQL-Server weitergeben.

:shock:

Ist nicht wahr, oder? Gott, jetzt merk ich mal wieder wie sehr Oracle einen verwöhnt.

Sherlock

p80286 8. Mai 2014 12:38

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von Sherlock (Beitrag 1258297)
:shock:

Ist nicht wahr, oder? Gott, jetzt merk ich mal wieder wie sehr Oracle einen verwöhnt.

Ist wohl weniger Oracle als die verwendeten Treiber. Ohne White Spaces hagelt es bei mir auch Fehlermeldungen.

Gruß
K-H

Jumpy 8. Mai 2014 14:28

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Hallo,

musste das ruhen lassen (ohne Doppelpunkt in dem Textfeld geht es ja erstmal) und komme erst morgen dazu eure Anregungen einmal aufzugreifen.

Werde wohl versuchen die relevanten Teile in eine GUI-Anwendung zu kopieren oder das Logging erweitern, mal sehen.

Und danach auch mal eure Anregungen aufgreifen, habt ja recht. Aber trotzdem ist es doch seltsam, dass es funzt, wenn der Doppelpunkt im Feld!!! (nicht im Feldnamen, nicht im SQl-Statement) weggelassen wird. Oder das ein Paramter-Fehler gemeldet wird, wo ich doch keine Parameter einsetze.

In anderen Datensätzen ist dies übrigens kein Problem, z.B. gibt es da auch viele Textbausteine für Webformulare mit Einträgen wie "Name:", "Ort:" usw. da klappt alles. Einziger unterschied, da gehe ich nicht über die ID um den Eintrag zu finden sondern über die Felder Seite, Position, Kategorie usw.

Bzgl. Seite='*' noch kurz. D.h. nur, dass wenn ein Textbaustein auf jeder Seite der Webanwendung auftauchen könnte, nicht auf einer konkreten, dann steht da in der Spalte "Seite" halt ein Stern drin. Solange ich nichts mit "like" im SQL mache sollte ich doch da auch keine Schwierigkeiten kriegen, dass das als Wildecard interpretiert wird.

Sherlock 8. Mai 2014 15:11

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von p80286 (Beitrag 1258302)
Zitat:

Zitat von Sherlock (Beitrag 1258297)
:shock:

Ist nicht wahr, oder? Gott, jetzt merk ich mal wieder wie sehr Oracle einen verwöhnt.

Ist wohl weniger Oracle als die verwendeten Treiber. Ohne White Spaces hagelt es bei mir auch Fehlermeldungen.

Ein CR/LF ist doch auch ein Whitespace. Oder sieht das der SQLServer anders?

Sherlock

p80286 8. Mai 2014 15:16

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von Jumpy (Beitrag 1258307)
... wo ich doch keine Parameter einsetze.

Ein Doppelpunkt ist ein Parameter. Darüber bin ich auch mal gestolpert, ich hab bloß keine Ahnung mehr wie ich das damals maskiert habe. Ist zwar blöde aber mit Computern diskutiert man nicht.

Gruß
K-H
QSherlock:
Zitat:

Ein CR/LF ist doch auch ein Whitespace. Oder sieht das der SQLServer anders?
Doch ist so, aber ich bin mir nicht sicher ob ein .Add immer ein CRLF produziert, darum immer ein Blank am Zeilenende und Einrücken.

Dejan Vu 8. Mai 2014 16:10

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Ihr verwechselt da was (?):
Delphi-Quellcode:
SQL.Add('foo');
SQL.Add('bar');
// vs.
SQL.Add('foo'
      + 'bar');
Das eine erzeugt einen String mit zwei durch (CR)LF getrennten Token, das zweite erzeugt logischerweise ein Token.
'Token' deshalb, weil es das ist, was der Tokenizer/Parser im RDMBS als Teil des Statement-Compilers dann aus dem Input-String herauszuppelt.

Einige RDMBS benötigen an bestimmten Stellen ein sogar CRLF (als Ersatz für den Statement-Trenner ';'), sodaß es wohl kaum einen Treiber gibt, der das wegschnippelt.

Wieso sollte ein Treiber ein CRLF ersatzlos wegschnippeln? Das wäre ein schwerwiegender Bug... Und wenn man sich in einem Profiler oder ähnlichen Programm dann anschaut, was genau zum Server geschickt wird, sollte klar werden, das Zeilentrenner nie nicht niemals ersatzlos weggeschnippelt werden.

Nun kann man trotz allem ja trotzdem Leerzeichen 'sicherheitshalber' einbauen, aber wozu? Aberglaube?

So, nun bin ich aber wirklich gespannt, wie die Geschichte mit dem Doppelpunkt ausgeht...

mkinzler 8. Mai 2014 16:15

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Sorry, meine Schuld, wie kann ich auch vorschlagen ein Leerzeichen einzubauen! Ich hatte nie geschriben, dass der Zeilentrenner entfernt wird und habe auch nicht gesagt, dass es bestimmt daran liegt bzw. das ein abolutes Problem ist!

Die Hauptaussage war "Verwende Parameter". Was der TE aber wohl aus irgendwelchen Gründen nicht will.

Dejan Vu 8. Mai 2014 18:07

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von mkinzler (Beitrag 1258314)
Sorry, meine Schuld

Du warst doch gar nicht gemeint. Wieso fühlst Du dich angesprochen? Wir schweifen doch eh ab, es geht um diesen Doppelpunkt.

Sherlock 9. Mai 2014 08:49

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Eben, Sorry, das ich das einwarf. Wie ist es denn nun ausgegangen, mit dem Doppelpunkt?


Sherlock

Jumpy 9. Mai 2014 10:30

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
MoinMoin,

ich hab heut morgen jetzt fast 2 Std. damit verbracht das Problem zu lösen und ich kann nur hoffen, dass ihr mich jetzt nicht steinigt. Das Problem wurde nämlich nicht da verursacht wo ich gedacht habe.

Nachdem ich die (wie ich dachte) relevanten Teile aus der Web-Cgi in ein Mini Testprojekt ausgelagert habe, trat der Fehler nicht auf, wie ja auch Sir Rufo und andere das schon nachgestellt haben.

Da ich aber nicht wußte, wie man eine CGI vernünftigt debuggt (gibt's da was?) habe ich nach und nach an diversen Stellen Logging-Calls eingebaut, um zu sehen, wo genau der Fehler geworfen wird und da hab ich dann bemerkt, das meine eigentlichen Routinen auch in der CGI ohne Fehler sauber durchlaufen.

Als ich dann geschaut habe, woher eigentlich die Anfrage nach diesem speziellen Textbaustein kommt, habe ich gesehen, dass das von einem Ajax-Request aus einem anderen Modul kommt. Weitere Recherchen haben dann ergeben, das es letzte Woche in dem Modul wohl ein Problem gab und ein Kollege, der die normale Logging-Routine nicht benutzen wollte, sich schnell selber eine Logtabelle erstellt hat um sämtliche Ajax-Requests und -Responses zu loggen. Die Funktion die er dafür mal eben schnelll erstellt hat, benutzt natürlich keine Parameter (ihr hattet ja alle irgendwie Recht :thumb:) und platziert nun einen Text, der einen Doppelpunkt enthält in ein SQL-Statement und da wird dann ein Parameter vermisst.

Sherlock 9. Mai 2014 10:44

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Hier wird nicht gesteinigt...es ist ja schließlich keiner von uns ohne Fehler ;)

Sherlock

Dejan Vu 9. Mai 2014 11:08

AW: Seltsamer Fehler bzgl. Parameterobjekt
 
Zitat:

Zitat von Sherlock (Beitrag 1258395)
es ist ja schließlich keiner von uns ohne Fehler ;)

Doch. Die Moderatoren :mrgreen:
Ich finde es immer beruhigend, am Ende einer bug fishing session das Teil im Netz zu haben. Schlimm ist nur, wenn der Fehler 'verschwindet' und keiner weiß, warum.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:14 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz