mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-25 22:17:07 +01:00
- Fixed bug #4121
- Implemented filtering for sqldb git-svn-id: trunk@615 -
This commit is contained in:
parent
338d4fbe99
commit
5355abf860
@ -424,7 +424,8 @@ begin
|
|||||||
CheckError('FreeStatement', Status);
|
CheckError('FreeStatement', Status);
|
||||||
Statement := nil;
|
Statement := nil;
|
||||||
end;
|
end;
|
||||||
reAllocMem((cursor as tibcursor).SQLDA,0);
|
// reAllocMem((cursor as tibcursor).SQLDA,0);
|
||||||
|
// ^=bug moet nog ergens anders komen...
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TIBConnection.PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams);
|
procedure TIBConnection.PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams);
|
||||||
@ -436,7 +437,7 @@ var dh : pointer;
|
|||||||
i : integer;
|
i : integer;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ObtainSQLStatementType(cursor,buf);
|
// ObtainSQLStatementType(cursor,buf);
|
||||||
with cursor as TIBcursor do
|
with cursor as TIBcursor do
|
||||||
begin
|
begin
|
||||||
dh := GetHandle;
|
dh := GetHandle;
|
||||||
|
|||||||
@ -51,7 +51,7 @@ const
|
|||||||
'create', 'get', 'put', 'execute',
|
'create', 'get', 'put', 'execute',
|
||||||
'start','commit','rollback', '?'
|
'start','commit','rollback', '?'
|
||||||
);
|
);
|
||||||
SQLDelimiterCharacters = [',',' ','(',')',#13,#10,#9];
|
SQLDelimiterCharacters = [';',',',' ','(',')',#13,#10,#9];
|
||||||
|
|
||||||
|
|
||||||
{ TSQLConnection }
|
{ TSQLConnection }
|
||||||
@ -159,6 +159,10 @@ type
|
|||||||
FUpdateMode : TUpdateMode;
|
FUpdateMode : TUpdateMode;
|
||||||
FParams : TParams;
|
FParams : TParams;
|
||||||
FusePrimaryKeyAsKey : Boolean;
|
FusePrimaryKeyAsKey : Boolean;
|
||||||
|
FSQLBuf : String;
|
||||||
|
FFromPart : String;
|
||||||
|
FWhereStartPos : integer;
|
||||||
|
FWhereStopPos : integer;
|
||||||
// FSchemaInfo : TSchemaInfo;
|
// FSchemaInfo : TSchemaInfo;
|
||||||
|
|
||||||
procedure CloseStatement;
|
procedure CloseStatement;
|
||||||
@ -173,6 +177,7 @@ type
|
|||||||
procedure OnChangeSQL(Sender : TObject);
|
procedure OnChangeSQL(Sender : TObject);
|
||||||
|
|
||||||
procedure Execute;
|
procedure Execute;
|
||||||
|
Procedure ParseSQL(var SQL : string);
|
||||||
protected
|
protected
|
||||||
// abstract & virtual methods of TBufDataset
|
// abstract & virtual methods of TBufDataset
|
||||||
function Fetch : boolean; override;
|
function Fetch : boolean; override;
|
||||||
@ -191,6 +196,8 @@ type
|
|||||||
Function IsPrepared : Boolean; virtual;
|
Function IsPrepared : Boolean; virtual;
|
||||||
function GetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean): Boolean; overload; override;
|
function GetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean): Boolean; overload; override;
|
||||||
procedure SetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean); overload; override;
|
procedure SetFieldData(Field: TField; Buffer: Pointer; NativeFormat: Boolean); overload; override;
|
||||||
|
procedure SetFiltered(Value: Boolean); override;
|
||||||
|
procedure SetFilterText(const Value: string); override;
|
||||||
public
|
public
|
||||||
procedure Prepare; virtual;
|
procedure Prepare; virtual;
|
||||||
procedure UnPrepare; virtual;
|
procedure UnPrepare; virtual;
|
||||||
@ -202,8 +209,8 @@ type
|
|||||||
published
|
published
|
||||||
// redeclared data set properties
|
// redeclared data set properties
|
||||||
property Active;
|
property Active;
|
||||||
// property Filter;
|
property Filter;
|
||||||
// property Filtered;
|
property Filtered;
|
||||||
// property FilterOptions;
|
// property FilterOptions;
|
||||||
property BeforeOpen;
|
property BeforeOpen;
|
||||||
property AfterOpen;
|
property AfterOpen;
|
||||||
@ -531,16 +538,57 @@ begin
|
|||||||
SetFieldData(Field, Buffer);
|
SetFieldData(Field, Buffer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSQLQuery.SetFilterText(const Value: string);
|
||||||
|
|
||||||
|
begin
|
||||||
|
if Filtered then
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
Inherited SetFilterText(Value);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSQLQuery.SetFiltered(Value: Boolean);
|
||||||
|
|
||||||
|
var S : String;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if (Filtered <> Value) and Active then
|
||||||
|
begin
|
||||||
|
CloseStatement;
|
||||||
|
FIsEOF := False;
|
||||||
|
inherited internalclose;
|
||||||
|
|
||||||
|
s := FSQLBuf;
|
||||||
|
|
||||||
|
if Value then
|
||||||
|
begin
|
||||||
|
if FWhereStartPos = 0 then
|
||||||
|
s := s + ' where (' + Filter + ')'
|
||||||
|
else if FWhereStopPos > 0 then
|
||||||
|
system.insert(' and ('+Filter+') ',S,FWhereStopPos+1)
|
||||||
|
else
|
||||||
|
system.insert(' where ('+Filter+') ',S,FWhereStartPos);
|
||||||
|
end;
|
||||||
|
|
||||||
|
(Database as tsqlconnection).PrepareStatement(Fcursor,(transaction as tsqltransaction),S,FParams);
|
||||||
|
|
||||||
|
|
||||||
|
Execute;
|
||||||
|
inherited InternalOpen;
|
||||||
|
First;
|
||||||
|
|
||||||
|
inherited SetFiltered(Value);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TSQLQuery.Prepare;
|
procedure TSQLQuery.Prepare;
|
||||||
var
|
var
|
||||||
Buf : string;
|
|
||||||
db : tsqlconnection;
|
db : tsqlconnection;
|
||||||
sqltr : tsqltransaction;
|
sqltr : tsqltransaction;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if not IsPrepared then
|
if not IsPrepared then
|
||||||
begin
|
begin
|
||||||
|
|
||||||
db := (Database as tsqlconnection);
|
db := (Database as tsqlconnection);
|
||||||
sqltr := (transaction as tsqltransaction);
|
sqltr := (transaction as tsqltransaction);
|
||||||
if not assigned(Db) then
|
if not assigned(Db) then
|
||||||
@ -554,12 +602,14 @@ begin
|
|||||||
if assigned(fcursor) then FreeAndNil(fcursor);
|
if assigned(fcursor) then FreeAndNil(fcursor);
|
||||||
FCursor := Db.AllocateCursorHandle;
|
FCursor := Db.AllocateCursorHandle;
|
||||||
|
|
||||||
buf := TrimRight(FSQL.Text);
|
FSQLBuf := TrimRight(FSQL.Text);
|
||||||
|
|
||||||
|
ParseSQL(FSQLBuf);
|
||||||
|
|
||||||
Db.PrepareStatement(Fcursor,sqltr,buf,FParams);
|
Db.PrepareStatement(Fcursor,sqltr,FSQLBuf,FParams);
|
||||||
|
|
||||||
if (FCursor.FStatementType = stSelect) and not ReadOnly then
|
if (FCursor.FStatementType = stSelect) and not ReadOnly then
|
||||||
InitUpdates(Buf);
|
InitUpdates(FSQLBuf);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -632,98 +682,117 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSQLQuery.InitUpdates(SQL : string);
|
procedure TSQLQuery.ParseSQL(var SQL : string);
|
||||||
|
|
||||||
|
type TParsePart = (ppStart,ppSelect,ppWhere,ppFrom,ppOrder,ppComment,ppBogus);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
L : Integer;
|
PSQL,CurrentP,
|
||||||
P,PP : PChar;
|
PhraseP, PStatementPart : pchar;
|
||||||
PS: PChar;
|
S : string;
|
||||||
S : string;
|
ParsePart : TParsePart;
|
||||||
|
StrLength : Integer;
|
||||||
function GetStatement(var StartP : PChar) : PChar;
|
|
||||||
|
|
||||||
var p : pchar;
|
|
||||||
Cmt, Stm : boolean;
|
|
||||||
|
|
||||||
begin
|
|
||||||
p := StartP;
|
|
||||||
Cmt := false;
|
|
||||||
Stm := False;
|
|
||||||
While ((P-PP)<L) do
|
|
||||||
begin
|
|
||||||
if Cmt then
|
|
||||||
begin
|
|
||||||
end
|
|
||||||
else if (p^ in SQLDelimiterCharacters) then
|
|
||||||
begin
|
|
||||||
if stm then break;
|
|
||||||
end
|
|
||||||
else if not stm then
|
|
||||||
begin
|
|
||||||
StartP := p;
|
|
||||||
stm := true;
|
|
||||||
end;
|
|
||||||
inc(p);
|
|
||||||
end;
|
|
||||||
Result := P;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FUpdateable := False;
|
PSQL:=Pchar(SQL);
|
||||||
|
ParsePart := ppStart;
|
||||||
|
|
||||||
L:=Length(SQL);
|
CurrentP := PSQL-1;
|
||||||
|
PhraseP := PSQL;
|
||||||
|
|
||||||
|
FWhereStartPos := 0;
|
||||||
|
FWhereStopPos := 0;
|
||||||
|
|
||||||
PP:=Pchar(SQL);
|
repeat
|
||||||
P := pp;
|
|
||||||
PS := pp;
|
|
||||||
|
|
||||||
// select-keyword
|
|
||||||
P := GetStatement(PS);
|
|
||||||
|
|
||||||
Setlength(S,P-PS);
|
|
||||||
Move(PS^,S[1],(P-PS));
|
|
||||||
S:=Lowercase(S);
|
|
||||||
|
|
||||||
if (S) <> 'select' then exit;
|
|
||||||
|
|
||||||
// select-part
|
|
||||||
|
|
||||||
While ((P-PP)<L) and (S <> 'from') do
|
|
||||||
begin
|
begin
|
||||||
repeat
|
inc(CurrentP);
|
||||||
PS := P;
|
|
||||||
P := GetStatement(PS);
|
|
||||||
until P^ <> ',';
|
|
||||||
|
|
||||||
Setlength(S,P-PS);
|
if CurrentP^ in [' ',#13,#10,#9,#0,'(',')',';'] then
|
||||||
Move(PS^,S[1],(P-PS));
|
begin
|
||||||
S:=Lowercase(S);
|
if (CurrentP-PhraseP > 0) or (CurrentP^ in [';',#0]) then
|
||||||
|
begin
|
||||||
|
strLength := CurrentP-PhraseP;
|
||||||
|
Setlength(S,strLength);
|
||||||
|
if strLength > 0 then Move(PhraseP^,S[1],(strLength));
|
||||||
|
s := uppercase(s);
|
||||||
|
|
||||||
|
case ParsePart of
|
||||||
|
ppStart : begin
|
||||||
|
FCursor.FStatementType := (Database as tsqlconnection).StrToStatementType(s);
|
||||||
|
if FCursor.FStatementType = stSelect then ParsePart := ppSelect
|
||||||
|
else break;
|
||||||
|
PStatementPart := CurrentP;
|
||||||
|
end;
|
||||||
|
ppSelect : begin
|
||||||
|
if s = 'FROM' then
|
||||||
|
begin
|
||||||
|
ParsePart := ppFrom;
|
||||||
|
PhraseP := CurrentP;
|
||||||
|
PStatementPart := CurrentP;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
ppFrom : begin
|
||||||
|
if (s = 'WHERE') or (s = 'ORDER') or (CurrentP^=#0) or (CurrentP^=';') then
|
||||||
|
begin
|
||||||
|
if (s = 'WHERE') then
|
||||||
|
begin
|
||||||
|
ParsePart := ppWhere;
|
||||||
|
StrLength := PhraseP-PStatementPart;
|
||||||
|
end
|
||||||
|
else if (s = 'ORDER') then
|
||||||
|
begin
|
||||||
|
ParsePart := ppOrder;
|
||||||
|
StrLength := PhraseP-PStatementPart
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
ParsePart := ppBogus;
|
||||||
|
StrLength := CurrentP-PStatementPart;
|
||||||
|
end;
|
||||||
|
Setlength(FFromPart,StrLength);
|
||||||
|
Move(PStatementPart^,FFromPart[1],(StrLength));
|
||||||
|
FFrompart := trim(FFrompart);
|
||||||
|
FWhereStartPos := PStatementPart-PSQL+StrLength+1;
|
||||||
|
PStatementPart := CurrentP;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
ppWhere : begin
|
||||||
|
if (s = 'ORDER') or (CurrentP^=#0) or (CurrentP^=';') then
|
||||||
|
begin
|
||||||
|
ParsePart := ppBogus;
|
||||||
|
FWhereStartPos := PStatementPart-PSQL;
|
||||||
|
if s = 'ORDER' then
|
||||||
|
FWhereStopPos := PhraseP-PSQL+1
|
||||||
|
else
|
||||||
|
FWhereStopPos := CurrentP-PSQL+1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end; {case}
|
||||||
|
end;
|
||||||
|
PhraseP := CurrentP+1;
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
until CurrentP^=#0;
|
||||||
|
if (FWhereStartPos > 0) and (FWhereStopPos > 0) then
|
||||||
|
begin
|
||||||
|
system.insert('(',SQL,FWhereStartPos+1);
|
||||||
|
inc(FWhereStopPos);
|
||||||
|
system.insert(')',SQL,FWhereStopPos);
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSQLQuery.InitUpdates(SQL : string);
|
||||||
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
if pos(',',FFromPart) > 0 then
|
||||||
|
FUpdateable := False // select-statements from more then one table are not updateable
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
FUpdateable := True;
|
||||||
|
FTableName := FFromPart;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// from-part
|
|
||||||
|
|
||||||
PS := P;
|
|
||||||
P := GetStatement(PS);
|
|
||||||
|
|
||||||
Setlength(FTableName,P-PS);
|
|
||||||
Move(PS^,FTableName[1],(P-PS));
|
|
||||||
|
|
||||||
While ((P-PP)<L) do
|
|
||||||
begin
|
|
||||||
PS := P;
|
|
||||||
P := GetStatement(PS);
|
|
||||||
|
|
||||||
if P^ = ',' then exit; // select-statements from more then one table are not updateable
|
|
||||||
|
|
||||||
Setlength(S,P-PS);
|
|
||||||
Move(PS^,S[1],(P-PS));
|
|
||||||
S:=Lowercase(S);
|
|
||||||
|
|
||||||
if (s = 'where') or (s='order') then break;
|
|
||||||
end;
|
|
||||||
|
|
||||||
FUpdateable := True;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSQLQuery.InternalOpen;
|
procedure TSQLQuery.InternalOpen;
|
||||||
@ -837,7 +906,6 @@ end;
|
|||||||
function TSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind) : boolean;
|
function TSQLQuery.ApplyRecUpdate(UpdateKind : TUpdateKind) : boolean;
|
||||||
|
|
||||||
var
|
var
|
||||||
sql_tables : string;
|
|
||||||
s : string;
|
s : string;
|
||||||
|
|
||||||
procedure UpdateWherePart(var sql_where : string;x : integer);
|
procedure UpdateWherePart(var sql_where : string;x : integer);
|
||||||
@ -860,7 +928,6 @@ var
|
|||||||
sql_where : string;
|
sql_where : string;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
sql_tables := FTableName;
|
|
||||||
sql_set := '';
|
sql_set := '';
|
||||||
sql_where := '';
|
sql_where := '';
|
||||||
for x := 0 to Fields.Count -1 do
|
for x := 0 to Fields.Count -1 do
|
||||||
@ -876,7 +943,7 @@ var
|
|||||||
|
|
||||||
setlength(sql_set,length(sql_set)-1);
|
setlength(sql_set,length(sql_set)-1);
|
||||||
setlength(sql_where,length(sql_where)-5);
|
setlength(sql_where,length(sql_where)-5);
|
||||||
result := 'update ' + sql_tables + ' set ' + sql_set + ' where ' + sql_where;
|
result := 'update ' + FTableName + ' set ' + sql_set + ' where ' + sql_where;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -887,7 +954,6 @@ var
|
|||||||
sql_values : string;
|
sql_values : string;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
sql_tables := FTableName;
|
|
||||||
sql_fields := '';
|
sql_fields := '';
|
||||||
sql_values := '';
|
sql_values := '';
|
||||||
for x := 0 to Fields.Count -1 do
|
for x := 0 to Fields.Count -1 do
|
||||||
@ -901,7 +967,7 @@ var
|
|||||||
setlength(sql_fields,length(sql_fields)-1);
|
setlength(sql_fields,length(sql_fields)-1);
|
||||||
setlength(sql_values,length(sql_values)-1);
|
setlength(sql_values,length(sql_values)-1);
|
||||||
|
|
||||||
result := 'insert into ' + sql_tables + ' (' + sql_fields + ') values (' + sql_values + ')';
|
result := 'insert into ' + FTableName + ' (' + sql_fields + ') values (' + sql_values + ')';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DeleteRecQuery : string;
|
function DeleteRecQuery : string;
|
||||||
@ -910,15 +976,13 @@ var
|
|||||||
sql_where : string;
|
sql_where : string;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
sql_tables := FTableName;
|
|
||||||
|
|
||||||
sql_where := '';
|
sql_where := '';
|
||||||
for x := 0 to Fields.Count -1 do
|
for x := 0 to Fields.Count -1 do
|
||||||
UpdateWherePart(sql_where,x);
|
UpdateWherePart(sql_where,x);
|
||||||
|
|
||||||
setlength(sql_where,length(sql_where)-5);
|
setlength(sql_where,length(sql_where)-5);
|
||||||
|
|
||||||
result := 'delete from ' + sql_tables + ' where ' + sql_where;
|
result := 'delete from ' + FTableName + ' where ' + sql_where;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user