AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Möglicher Fehler in GetTableName

Ein Thema von Neutral General · begonnen am 8. Dez 2014 · letzter Beitrag vom 8. Dez 2014
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 11:45
Hallo,

Der Titel ist jetzt leider nicht gerade der Beste..
Habe folgende SQL:

Zitat:
SELECT
tabelle1.*,
(SELECT feld FROM tabelle_innen WHERE 1=1)
FROM tablle1
WHERE tabelle1.id = 4
TCustomDADataSet (unit DBAccess) ist nun die Basis für die Query-Komponente die ich benutze.
TCustomDADataSet besitzt eine Methode GetTableName die intern PSGetTableName aufruft, welche wiederrum in einigen Fällen die Funktion GetTableNameFromSQLEx aus der Unit Data.DBCommon aufruft.

Und diese GetTableNameFromSQLEx-Funktion hat in meinen Augen einen Fehler. Denn GetTableName und somit GetTableNameFromSQLEx liefern bei obiger Query als Ergebnis "TABELLE_INNEN" statt "TABELLE1".

In der Funktion selbst wird quasi das erste "FROM" gesucht und der Tabellenname dahinter zurückgegeben.

Meine 2 Fragen:

1) Könnt ihr das in eurer Delphi Version reproduzieren (habs mit XE7 probiert)
2) Stimmt ihr mir zu dass das Ergebnis oben falsch ist oder verstehe ich die Funktion nur falsch und TABELLE_INNEN ist zwar nicht das was ich will aber das was rauskommen sollte.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#2

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 11:53
...
Und diese GetTableNameFromSQLEx-Funktion hat in meinen Augen einen Fehler. Denn GetTableName und somit GetTableNameFromSQLEx liefern bei obiger Query als Ergebnis "TABELLE_INNEN" statt "TABELLE1".

In der Funktion selbst wird quasi das erste "FROM" gesucht und der Tabellenname dahinter zurückgegeben.
Wenn das wirklich so implementiert wurde, müsste man den Programmierer teeren und federn. Mindestens. Ich kenne die Funktion nicht, aber ich ziehe aus deinen Ausführungen den Schluss, das 'GetTableName' das/die an der Query maßgeblich beteiligten Tabelle(n) liefern soll. Ich frage mich zwar, was der Sinn dahinter ist, aber egal: Ich würde das pro Feld sinnvoller finden.

Zum Verständnis: Welchen Rückgabewert erwartest Du bei dieser Query?
Code:
select a.Customer
   from Tabelle1 a
   join Tabelle2 b on a.ID = b.ID
Und hier?
Code:
select a.Customer
   from Tabelle2 b
        join Tabelle1 a on a.ID = b.ID
Und hier?
Code:
select a.Customer, b.Info
   from Tabelle2 b
        join Tabelle1 a on a.ID = b.ID
Und hier?
Code:
select *
   from Tabelle2 b
        join Tabelle1 a on a.ID = b.ID
Nicht falsch verstehen: Ich will nur verstehen, welchen Sinn diese Funktion haben soll.
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 12:05
Es gibt z.B. Methoden die generieren aus einem SELECT Statement automatisch ein Insert-Statement für die jeweilige Tabelle. Dafür ist das halt nützlich u.a. Daher würde ICH folgende Ergebnisse erwarten:

- Tabelle1
- Tabelle2
- Tabelle2
- Tabelle2

Ob die Methode allerdings auch so gedacht ist weiß ich nicht. Im Prinzip erwarte ich den (ersten) Tabellennamen des äußersten FROM.

Die Funktion aus der Unit Data.DBCommon:

Delphi-Quellcode:
function GetTableNameFromSQLEx(const SQL: string; IdOption: IDENTIFIEROption): string;
var
  Start: PChar;
  Token: string;
  SQLToken, CurSection: TSQLToken;
begin
  Result := '';
  Start := PChar(SQL);
  CurSection := stUnknown;
  repeat
    SQLToken := NextSQLTokenEx(Start, Token, CurSection, IdOption);
    if SQLToken in SQLSections then CurSection := SQLToken;
  until SQLToken in [stEnd, stFrom];
  if SQLToken = stFrom then
  begin
    repeat
      SQLToken := NextSQLTokenEx(Start, Token, CurSection, IdOption);
      if SQLToken in SQLSections then
        CurSection := SQLToken else
      // stValue is returned if TableNames contain quote chars.
      if (SQLToken = stTableName) or (SQLToken = stValue) then
      begin
        if AnsiRightStr(Token, 1) = ';then
          Token := AnsiLeftStr(Token, Token.Length-1);
        if AnsiRightStr(Token, 1) = ')then
          Token := AnsiLeftStr(Token, Token.Length-1);
        Result := Trim(Token);
        while (Start[0] = '.') and not (SQLToken in [stEnd]) do
        begin
          SQLToken := NextSqlTokenEx(Start, Token, CurSection, IdOption);
          Result := Result + '.' + Token;
        end;
        Exit;
      end;
    until (CurSection <> stFrom) or (SQLToken in [stEnd, stTableName]);
  end;
end;
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."

Geändert von Neutral General ( 8. Dez 2014 um 12:08 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 12:27
Zitat:
Im Prinzip erwarte ich den (ersten) Tabellennamen des äußersten FROM
Nun da das Ergebnis Deiner Abfrage aus den verschiedensten Tabellen zusammen gesetz wurde/werden kann, halte ich Dein Ansehen für sehr vermessen.
Falls du unbedingt einen Tabellennamen brachst, dann gib ihn doch Deiner Abfrage mit
select'tabelle1',tabelle1.*,'tabelle2',tabelle2.* etc. Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#5

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 12:42
Ok, verstanden (dann wäre eine Antwort zwar nicht korrekt, aber unwichtig).

Man kann bei einer Typ-2-Grammatik keinen nichthierarchischen Parser verwenden. Oder einfacher ausgedrückt: Die Sprache ist rekursiv formuliert (Queries können Queries beinhalten, es gibt Klammerebenen), also muss man einen Satz der Sprache (das 'SQL-Statement') auch rekursiv analysieren. Es reicht natürlich ein Stack, aber der ist ja auch rekursiv.

Ob sich das Problem mit RegEx lösen lässt, weiß ich nicht. Rein theoretisch nicht, denn RegEx kann 'eigentlich' nur Typ-3 Grammatiken parsen, aber mit dem ganzen Lookahead-Gedöns und dem bilden von Gruppen wäre es theoretisch denkbar, obwohl... nee. geht nicht (meine Meinung )

Jedenfalls geht es nicht so. Garantiert nicht. Um es richtig zu machen, musst du einen Parser schreiben, der die kompletten SELECT-Syntax implementiert und dann im aufgespannten Syntaxbaum beim 'äußeren' FROM-Knoten nachschauen: Dort hängen dann die JOIN-Operatoren mit den in Frage kommenden Tabellen. Allerdings ist es ja so, dass die Veränderung nicht über eine Tabelle läuft, sondern über viele, d.h. alleine schon das Funktionsresultat "der Tabellenname" ist falsch, es müsste "die Tabellennamen" heißen und pro Feld angegeben werden.

Tipp: SQL-Server kann direkt auf einer View Operationen (DELETE, INSERT, UPDATE) ausführen. Andere RDBMS können das vielleicht/vermutlich auch. Wenn als *das* dein Problem ist, packe deine Query in eine View und führe das Update einfach auf der View aus.

Ansonsten bin ich persönlich kein Verfechter von 'Ich verstehe die Query und baue Dir ein INSERT draus'. Das geht nämlich manchmal auch in die Hose. Besser ist es, die DML explizit auszuformulieren.

Aber vermutlich ist das eh nicht dein Problem.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 13:56
Den ersten Tabellennamen vom äußersten FROM ...
SQL-Code:
select
  *
from
  ( select * from tab1 )
Es wird schwierig immer den richtigen Tabellennamen zu treffen und aufzulösen.

Darum ist es auch besser, die Statements eben nicht automatisch generieren zu lassen. Den Aufwand den man damit betreibt um auch wirklich alle Ausnahmen zu berücksichtigen schmeisst man wieder in die Tonne, wenn die nächste noch unberücksichtigte Ausnahme kommt. Irgendwann ist man es leid.

Da baue ich mir doch lieber ein Repository und arbeite mit Objekten, oder meinetwegen auch eine DataSet-Factory, die mir die passenden Abfrage-Instanzen liefert.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#7

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 14:15
..lieber ein Repository..
Dazu noch der Hinweis, dass selbest das "richtige" finden des Tabellennamens u.U. nicht das Ende der Fahnenstange ist. Werden hier nur Spalten aus der Update Table selektiert, ist vielleicht alles im grünen Bereich, sind aber Werte aus anderen Tabellen in den Ausgabespalten dabei(soll ja vorkommen), dann kann man die nicht updaten, zumindest nicht auf Basis einer Update Table.

Im Repository würde man also nicht nur die Table, sondern vielleicht auch die Spalten mitverwalten.
Gruß, Jo
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 14:29
..lieber ein Repository..
Dazu noch der Hinweis, dass selbest das "richtige" finden des Tabellennamens u.U. nicht das Ende der Fahnenstange ist. Werden hier nur Spalten aus der Update Table selektiert, ist vielleicht alles im grünen Bereich, sind aber Werte aus anderen Tabellen in den Ausgabespalten dabei(soll ja vorkommen), dann kann man die nicht updaten, zumindest nicht auf Basis einer Update Table.

Im Repository würde man also nicht nur die Table, sondern vielleicht auch die Spalten mitverwalten.
Wieso denn jetzt Spalten mitverwalten?

Meine Repositories sehen ungefähr so aus
Delphi-Quellcode:
type
  TFooId = type Integer;
  TFooIdHelper = record helper for TFooId
    const
      null = 0;
  end;

  TFoo = class
  public
    constructor Create( Id : TFooId; const Title : string );
    property Id : TFooId read Fid;
    property Title : string read FTitle;
  end;

  IFooRepository = interface
    function Get( FooId : TFooId; out Foo : TFoo ) : Boolean;
    function GetAll : TArray<TFooId>;
    function Store( Foo : TFoo; Dispose : Boolean = False ) : Boolean;
    function NextFooId : TFooId;
  end;
Das Repository weiß, wo die Informationen gespeichert werden und eben auch, wo es die Informationen wieder holen kann (da wo man auch speichert?). Das Repository hat dann x Abfrage-Objekte und leitet die Anforderungen durch diese hindurch.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 8. Dez 2014 um 14:31 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#9

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 14:32
Leute ihr driftet total ab.

Es ist jetzt total egal ob man sich irgendwelche Statements generieren lassen sollte oder nicht oder welche Alternativen es dazu gibt.

Die Frage ist: Ist das ein Fehler in der RTL?
Sollte diese Funktion in dem von mir genannten Fall nicht "TABELLE1" statt "TABELLE_INNEN" zurückgeben?

Alles andere ist vollkommen irrelevant.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.977 Beiträge
 
Delphi 12 Athens
 
#10

AW: Möglicher Fehler in GetTableName

  Alt 8. Dez 2014, 15:10
Die Frage ist: Ist das ein Fehler in der RTL?
Sollte diese Funktion in dem von mir genannten Fall nicht "TABELLE1" statt "TABELLE_INNEN" zurückgeben?
Gibt es denn irgendwo eine Beschreibung, was die Funktion GetTableNameFromSQLEx bei bestimmten Eingabeparametern zurückliefern soll? Eine vollständige semantische Analyse des SQL-Statements kann man da wohl eher nicht erwarten.

Bei FireDAC ist das zumindest so gelöst, daß man über UpdateOptions.UpdateTableName den Namen angeben kann und sogar muss, wenn "FireDAC den Namen der zu aktualisierenden Tabelle nicht korrekt aus der Abfrage abrufen kann." Dabei ist es ziemlich unerheblich, warum FireDAC das nicht kann, weil der entsprechende Algorithmus vielleicht nur für simple SELECT-Anweisungen funktioniert. Ich habe jetzt die erwähnten DA-Komponenten nicht greifbar, aber vielleicht gibt es da ja einen ähnlichen Mechanismus.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz