Subject | Re: [IBO] Re: Extracting Table names from a SQL select statement |
---|---|
Author | Markus Ostenried |
Post date | 2009-03-08T11:22:54Z |
On Sun, Mar 8, 2009 at 12:07, sshowl09 <sshowl09@...> wrote:
uses IB_Parse;
// - if the SQL statement doesn't specify an alias for a table then RelAliasList
// will contain the relation name as the alias.
// - IOW for every relation there's an alias listed in RelAliasList.
function GetRelAliasList(ASQL: String): String;
var
LAliases: TStringList;
begin
LAliases := TStringList.Create;
try
ASQL := StripParensFromSQLJoin(ASQL);
IB_Parse.GetRelAliasList(ASQL, LAliases);
Result := Trim(LAliases.Text);
finally
LAliases.Free;
end;
end;
// IBO doesn't like parens '(' and ')' when parsing the join clause.
// This is not tested well, so it would be best if the joins
// didn't contain any parens.
function StripParensFromSQLJoin(const ASQL: String): String;
function FindSQLJoin(const ASQL: String; var ABegPos, AEndPos:
Integer): Boolean;
var
LTermKeyWord: String;
begin
ABegPos := ParseLineInvalid;
AEndPos := ParseLineEnd;
Result := ParseStr(ASQL, 'JOIN', [],
['WHERE','GROUP-','-BY','HAVING','UNION','PLAN',
'ORDER-','-BY','ROWS','FOR-','-UPDATE',';',''],
ABegPos, AEndPos, LTermKeyWord);
if not Result then begin
ABegPos := ParseLineInvalid;
AEndPos := ParseLineEnd;
end;
end;
function RemoveUnquotedChar(ACh: Char; var AStr: String): Integer;
var
LIdx: Integer;
begin
Result := 0;
repeat
LIdx := getLitSafePos(ACh, AStr, 1);
if (LIdx > 0) then begin
Delete(AStr, LIdx, 1);
Inc(Result);
end;
until (LIdx < 1);
end;
var
LJoinFound : Boolean;
LBegPos, LEndPos : Integer;
LCountOpeningParens: Integer;
LCountClosingParens: Integer;
LSQLJoin : String;
begin
// find join clause
LJoinFound := FindSQLJoin(ASQL, LBegPos, LEndPos);
if not LJoinFound then begin
Result := ASQL;
Exit;
end;
// extract join clause
LSQLJoin := Copy(ASQL, LBegPos, LEndPos-LBegPos+1);
// remove unquoted parens
LCountOpeningParens := RemoveUnquotedChar('(', LSQLJoin);
LCountClosingParens := RemoveUnquotedChar(')', LSQLJoin);
// check count of opening and closing parens
if (LCountOpeningParens <> LCountClosingParens) then begin
raise Exception.CreateFmt('LCountOpeningParens (%d) <>
LCountClosingParens (%d), LSQLJoin:'+#13#10+'%s',
[LCountOpeningParens,
LCountClosingParens, LSQLJoin]);
end;
// put result together
if (LCountOpeningParens > 0) then begin
Result := Copy(ASQL, 1, LBegPos-1) + LSQLJoin + Copy(ASQL,
LEndPos+1, MaxInt);
end else begin
Result := ASQL;
end;
end;
HTH,
Markus
> Is it possible to access the relationNames information if the query is invalid ?You can try this:
>
> For example if some of the tables mentioned in the query don't exist in the database ?
uses IB_Parse;
// - if the SQL statement doesn't specify an alias for a table then RelAliasList
// will contain the relation name as the alias.
// - IOW for every relation there's an alias listed in RelAliasList.
function GetRelAliasList(ASQL: String): String;
var
LAliases: TStringList;
begin
LAliases := TStringList.Create;
try
ASQL := StripParensFromSQLJoin(ASQL);
IB_Parse.GetRelAliasList(ASQL, LAliases);
Result := Trim(LAliases.Text);
finally
LAliases.Free;
end;
end;
// IBO doesn't like parens '(' and ')' when parsing the join clause.
// This is not tested well, so it would be best if the joins
// didn't contain any parens.
function StripParensFromSQLJoin(const ASQL: String): String;
function FindSQLJoin(const ASQL: String; var ABegPos, AEndPos:
Integer): Boolean;
var
LTermKeyWord: String;
begin
ABegPos := ParseLineInvalid;
AEndPos := ParseLineEnd;
Result := ParseStr(ASQL, 'JOIN', [],
['WHERE','GROUP-','-BY','HAVING','UNION','PLAN',
'ORDER-','-BY','ROWS','FOR-','-UPDATE',';',''],
ABegPos, AEndPos, LTermKeyWord);
if not Result then begin
ABegPos := ParseLineInvalid;
AEndPos := ParseLineEnd;
end;
end;
function RemoveUnquotedChar(ACh: Char; var AStr: String): Integer;
var
LIdx: Integer;
begin
Result := 0;
repeat
LIdx := getLitSafePos(ACh, AStr, 1);
if (LIdx > 0) then begin
Delete(AStr, LIdx, 1);
Inc(Result);
end;
until (LIdx < 1);
end;
var
LJoinFound : Boolean;
LBegPos, LEndPos : Integer;
LCountOpeningParens: Integer;
LCountClosingParens: Integer;
LSQLJoin : String;
begin
// find join clause
LJoinFound := FindSQLJoin(ASQL, LBegPos, LEndPos);
if not LJoinFound then begin
Result := ASQL;
Exit;
end;
// extract join clause
LSQLJoin := Copy(ASQL, LBegPos, LEndPos-LBegPos+1);
// remove unquoted parens
LCountOpeningParens := RemoveUnquotedChar('(', LSQLJoin);
LCountClosingParens := RemoveUnquotedChar(')', LSQLJoin);
// check count of opening and closing parens
if (LCountOpeningParens <> LCountClosingParens) then begin
raise Exception.CreateFmt('LCountOpeningParens (%d) <>
LCountClosingParens (%d), LSQLJoin:'+#13#10+'%s',
[LCountOpeningParens,
LCountClosingParens, LSQLJoin]);
end;
// put result together
if (LCountOpeningParens > 0) then begin
Result := Copy(ASQL, 1, LBegPos-1) + LSQLJoin + Copy(ASQL,
LEndPos+1, MaxInt);
end else begin
Result := ASQL;
end;
end;
HTH,
Markus