* Implemented the sqEscapeSlash and sqescapeRepeat connection options

* Adapted and added a test

git-svn-id: trunk@6085 -
This commit is contained in:
joost 2007-01-19 22:45:49 +00:00
parent 3594230958
commit 90a6bdcdd4
9 changed files with 81 additions and 41 deletions

View File

@ -1624,9 +1624,9 @@ type
Function IsEqual(Value: TParams): Boolean;
Function ParamByName(const Value: string): TParam;
Function ParseSQL(SQL: String; DoCreate: Boolean): String;
Function ParseSQL(SQL: String; DoCreate: Boolean; ParameterStyle : TParamStyle): String; overload;
Function ParseSQL(SQL: String; DoCreate: Boolean; ParameterStyle : TParamStyle; var ParamBinding: TParambinding): String; overload;
Function ParseSQL(SQL: String; DoCreate: Boolean; ParameterStyle : TParamStyle; var ParamBinding: TParambinding; var ReplaceString : string): String;
Function ParseSQL(SQL: String; DoCreate, EscapeSlash, EscapeRepeat : Boolean; ParameterStyle : TParamStyle): String; overload;
Function ParseSQL(SQL: String; DoCreate, EscapeSlash, EscapeRepeat : Boolean; ParameterStyle : TParamStyle; var ParamBinding: TParambinding): String; overload;
Function ParseSQL(SQL: String; DoCreate, EscapeSlash, EscapeRepeat : Boolean; ParameterStyle : TParamStyle; var ParamBinding: TParambinding; var ReplaceString : string): String;
Procedure RemoveParam(Value: TParam);
Procedure CopyParamValuesFromDataset(ADataset : TDataset; CopyBound : Boolean);
Property Dataset : TDataset Read GetDataset;

View File

@ -156,24 +156,24 @@ var pb : TParamBinding;
rs : string;
begin
Result := ParseSQL(SQL,DoCreate,psInterbase, pb, rs);
Result := ParseSQL(SQL,DoCreate,True,True,psInterbase, pb, rs);
end;
Function TParams.ParseSQL(SQL: String; DoCreate: Boolean; ParameterStyle : TParamStyle): String;
Function TParams.ParseSQL(SQL: String; DoCreate, EscapeSlash, EscapeRepeat : Boolean; ParameterStyle : TParamStyle): String;
var pb : TParamBinding;
rs : string;
begin
Result := ParseSQL(SQL,DoCreate,ParameterStyle,pb, rs);
Result := ParseSQL(SQL,DoCreate,EscapeSlash,EscapeRepeat,ParameterStyle,pb, rs);
end;
Function TParams.ParseSQL(SQL: String; DoCreate: Boolean; ParameterStyle : TParamStyle; var ParamBinding: TParambinding): String;
Function TParams.ParseSQL(SQL: String; DoCreate, EscapeSlash, EscapeRepeat : Boolean; ParameterStyle : TParamStyle; var ParamBinding: TParambinding): String;
var rs : string;
begin
Result := ParseSQL(SQL,DoCreate,ParameterStyle,ParamBinding, rs);
Result := ParseSQL(SQL,DoCreate,EscapeSlash, EscapeRepeat, ParameterStyle,ParamBinding, rs);
end;
function SkipComments(var p: PChar; EscapeSlash, EscapeRepeat : Boolean) : Boolean;
@ -187,7 +187,7 @@ var notRepeatEscaped : boolean;
notRepeatEscaped := True;
while not (p^ in [#0, QuoteChar]) do
begin
if EscapeSlash and (p^='\') then Inc(p,2) // make sure we handle \' and \\ correct
if EscapeSlash and (p^='\') and (p[1] <> #0) then Inc(p,2) // make sure we handle \' and \\ correct
else Inc(p);
end;
if p^=QuoteChar then
@ -238,7 +238,7 @@ begin
end; {case}
end;
Function TParams.ParseSQL(SQL: String; DoCreate: Boolean; ParameterStyle : TParamStyle; var ParamBinding: TParambinding; var ReplaceString : string): String;
Function TParams.ParseSQL(SQL: String; DoCreate, EscapeSlash, EscapeRepeat: Boolean; ParameterStyle : TParamStyle; var ParamBinding: TParambinding; var ReplaceString : string): String;
type
// used for ParamPart
@ -280,10 +280,7 @@ begin
p:=PChar(SQL);
BufStart:=p; // used to calculate ParamPart.Start values
repeat
// This doesn't work, since ParseSQL passes psInterbase as default. This need
// some more advanced solution. Now temporary fix, to fix at least fpcbot...
// SkipComments(p,ParameterStyle<>psPostgreSQL,ParameterStyle=psPostgreSQL);
SkipComments(p,True,True);
SkipComments(p,EscapeSlash,EscapeRepeat);
case p^ of
':','?': // parameter
begin

View File

@ -144,7 +144,7 @@ constructor TIBConnection.Create(AOwner : TComponent);
begin
inherited;
FConnOptions := FConnOptions + [sqSupportParams];
FConnOptions := FConnOptions + [sqSupportParams] + [sqEscapeRepeat];
FBLobSegmentSize := 80;
end;
@ -508,7 +508,7 @@ begin
tr := aTransaction.Handle;
if assigned(AParams) and (AParams.count > 0) then
buf := AParams.ParseSQL(buf,false,psInterbase,paramBinding);
buf := AParams.ParseSQL(buf,false,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psInterbase,paramBinding);
if isc_dsql_prepare(@Status[0], @tr, @Statement, 0, @Buf[1], Dialect, nil) <> 0 then
CheckError('PrepareStatement', Status);

View File

@ -53,6 +53,8 @@ Type
MapDSRowToMSQLRow : array of integer;
end;
{ TConnectionName }
TConnectionName = class (TSQLConnection)
private
FDialect: integer;
@ -97,6 +99,7 @@ Type
procedure RollBackRetaining(trans : TSQLHandle); override;
procedure UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string); override;
Public
constructor Create(AOwner : TComponent); override;
procedure CreateDB; override;
procedure DropDB; override;
Property ServerInfo : String Read FServerInfo;
@ -348,7 +351,7 @@ begin
begin
FStatement:=Buf;
if assigned(AParams) and (AParams.count > 0) then
FStatement := AParams.ParseSQL(FStatement,false,psSimulated,paramBinding,ParamReplaceString);
FStatement := AParams.ParseSQL(FStatement,false,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psSimulated,paramBinding,ParamReplaceString);
if FStatementType=stSelect then
FNeedData:=True;
ConnectMySQL(FQMySQL,FMySQL^.host,FMySQL^.user,FMySQL^.passwd);
@ -803,6 +806,12 @@ begin
qry.free;
end;
constructor TConnectionName.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FConnOptions := FConnOptions + [sqEscapeRepeat] + [sqEscapeSlash];
end;
function TConnectionName.GetTransactionHandle(trans: TSQLHandle): pointer;
begin
Result:=Nil;

View File

@ -100,6 +100,7 @@ type
// Internal utility functions
function CreateConnectionString:string;
public
constructor Create(AOwner : TComponent); override;
property Environment:TODBCEnvironment read FEnvironment;
published
property Driver:string read FDriver write FDriver; // will be passed as DRIVER connection parameter
@ -256,6 +257,12 @@ begin
end;
end;
constructor TODBCConnection.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FConnOptions := FConnOptions + [sqEscapeRepeat] + [sqEscapeSlash];
end;
procedure TODBCConnection.SetParameters(ODBCCursor: TODBCCursor; AParams: TParams);
var
ParamIndex:integer;
@ -440,7 +447,7 @@ begin
// Parse the SQL and build FParamIndex
if assigned(AParams) and (AParams.count > 0) then
buf := AParams.ParseSQL(buf,false,psInterbase,ODBCCursor.FParamIndex);
buf := AParams.ParseSQL(buf,false,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psInterbase,ODBCCursor.FParamIndex);
// prepare statement
ODBCCheckResult(

View File

@ -112,7 +112,7 @@ constructor TPQConnection.Create(AOwner : TComponent);
begin
inherited;
FConnOptions := FConnOptions + [sqSupportParams];
FConnOptions := FConnOptions + [sqSupportParams] + [sqEscapeRepeat] + [sqEscapeSlash];
end;
procedure TPQConnection.CreateDB;
@ -480,7 +480,7 @@ begin
else DatabaseErrorFmt(SUnsupportedParameter,[Fieldtypenames[AParams[i].DataType]],self);
end;
s[length(s)] := ')';
buf := AParams.ParseSQL(buf,false,psPostgreSQL);
buf := AParams.ParseSQL(buf,false,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psPostgreSQL);
end;
s := s + ' as ' + buf;
res := pqexec(tr.PGConn,pchar(s));

View File

@ -23,7 +23,7 @@ interface
uses SysUtils, Classes, DB, bufdataset;
type TSchemaType = (stNoSchema, stTables, stSysTables, stProcedures, stColumns, stProcedureParams, stIndexes, stPackages);
TConnOption = (sqSupportParams);
TConnOption = (sqSupportParams,sqEscapeSlash,sqEscapeRepeat);
TConnOptions= set of TConnOption;
type
@ -632,11 +632,14 @@ end;
{ TSQLQuery }
procedure TSQLQuery.OnChangeSQL(Sender : TObject);
var ConnOptions : TConnOptions;
begin
UnPrepare;
if (FSQL <> nil) then
begin
FParams.ParseSQL(FSQL.Text,True);
ConnOptions := (DataBase as TSQLConnection).ConnOptions;
Fparams.ParseSQL(FSQL.Text,True, sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psInterbase);
If Assigned(FMasterLink) then
FMasterLink.RefreshParamNames;
end;
@ -866,6 +869,7 @@ Var
StrLength : Integer;
EndOfComment : Boolean;
BracketCount : Integer;
ConnOptions : TConnOptions;
begin
PSQL:=Pchar(ASQL);
@ -876,12 +880,14 @@ begin
FWhereStartPos := 0;
FWhereStopPos := 0;
ConnOptions := (DataBase as TSQLConnection).ConnOptions;
repeat
begin
inc(CurrentP);
EndOfComment := SkipComments(CurrentP,True,False);
EndOfComment := SkipComments(CurrentP,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions);
if EndOfcomment then dec(currentp);
if EndOfComment and (ParsePart = ppStart) then PhraseP := CurrentP;

View File

@ -35,49 +35,58 @@ var Params : TParams;
begin
Params := TParams.Create;
AssertEquals( 'select * from table where id = $1',
params.ParseSQL('select * from table where id = :id',true,psPostgreSQL));
params.ParseSQL('select * from table where id = :id',true,True,True,psPostgreSQL));
AssertEquals( 'select * from table where id = $1',
params.ParseSQL('select * from table where id = :id',false,psPostgreSQL));
params.ParseSQL('select * from table where id = :id',false,True,True,psPostgreSQL));
AssertEquals( 'update test set 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6 7=$7 8=$8 9=$9 where (id = $2)',
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :2)',true,psPostgreSQL));
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :2)',true,True,True,psPostgreSQL));
AssertEquals( 'update test set 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6 7=$7 8=$8 9=$9 where (id = $3) and (test=''$test'')',
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :par3) and (test=''$test'')',true,psPostgreSQL));
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :par3) and (test=''$test'')',true,true,true,psPostgreSQL));
AssertEquals( 'update test set 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6 7=$7 8=$8 9=$9 10=$10 11=$11 12=$5 where (id = $3) and (test=''$test'')',
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id = :par3) and (test=''$test'')',true,psPostgreSQL));
AssertEquals( 'select * from table where ''id '''' = :id''',
params.ParseSQL('select * from table where ''id '''' = :id''',true,psPostgreSQL));
AssertEquals( 'select * from table where "id "" = :id"',
params.ParseSQL('select * from table where "id "" = :id"',true,psPostgreSQL));
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id = :par3) and (test=''$test'')',true,true,true,psPostgreSQL));
AssertEquals( 'select * from table where id = $1',
params.ParseSQL('select * from table where id = :id',true,psSimulated,pb,ReplStr));
params.ParseSQL('select * from table where id = :id',true,true,false,psSimulated,pb,ReplStr));
AssertEquals('$',ReplStr);
AssertEquals( 'update test set 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6 7=$7 8=$8 9=$9 where (id = $2)',
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :2)',true,psSimulated,pb,ReplStr));
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :2)',true,true,false,psSimulated,pb,ReplStr));
AssertEquals('$',ReplStr);
AssertEquals( 'update test set 1=$$1 2=$$2 3=$$3 4=$$4 5=$$5 6=$$6 7=$$7 8=$$8 9=$$9 where (id = $$3) and (test=''$test'')',
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :par3) and (test=''$test'')',true,psSimulated,pb,ReplStr));
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 where (id = :par3) and (test=''$test'')',true,true,false,psSimulated,pb,ReplStr));
AssertEquals('$$',ReplStr);
AssertEquals( 'update test set 1=$$1 2=$$2 3=$$3 4=$$4 5=$$5 6=$$6 7=$$7 8=$$8 9=$$9 10=$$10 11=$$11 12=$$5 where (id = $$3) and (test=''$test'')',
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id = :par3) and (test=''$test'')',true,psSimulated));
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id = :par3) and (test=''$test'')',true,True,True,psSimulated));
AssertEquals('$$',ReplStr);
AssertEquals( 'update test set 1=$$$1 2=$$$2 3=$$$3 4=$$$4 5=$$$5 6=$$$6 7=$$$7 8=$$$8 9=$$$9 10=$$$10 11=$$$11 12=$$$5 where (id$$ = $$$3) and (test$=''$test'')',
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id$$ = :par3) and (test$=''$test'')',true,psSimulated,pb,ReplStr));
params.ParseSQL('update test set 1=:1 2=:2 3=:par3 4=:par4 5=:par5 6=:par6 7=:par7 8=:par8 9=:par9 10=:par10 11=:11 12=:par5 where (id$$ = :par3) and (test$=''$test'')',true,true,False,psSimulated,pb,ReplStr));
AssertEquals('$$$',ReplStr);
AssertEquals( 'select * from table where id = ?',
params.ParseSQL('select * from table where id = :id',true,psInterbase));
params.ParseSQL('select * from table where id = :id',true,true,true,psInterbase));
// Test escape-sequences:
AssertEquals( 'select * from table where ''id '''' = :id''',
params.ParseSQL('select * from table where ''id '''' = :id''',true,False,True,psPostgreSQL));
AssertEquals( 'select * from table where "id "" = :id"',
params.ParseSQL('select * from table where "id "" = :id"',true,False,True,psPostgreSQL));
AssertEquals( 'select * from table where "id \" = :id"',
params.ParseSQL('select * from table where "id \" = :id"',true,True,False,psPostgreSQL));
AssertEquals( 'select * from table where "id \" = $1',
params.ParseSQL('select * from table where "id \" = :id',true,False,False,psPostgreSQL));
AssertEquals( 'select * from table where "id = :id\',
params.ParseSQL('select * from table where "id = :id\',true,True,True,psInterbase));
Params.Free;
end;

View File

@ -27,6 +27,7 @@ type
procedure RunTest; override;
published
procedure TestDoubleQuoteEscapeComments;
procedure TestpfInUpdateFlag; // bug 7565
procedure TestInt;
procedure TestScript;
@ -801,6 +802,17 @@ begin
inherited RunTest;
end;
procedure TTestFieldTypes.TestDoubleQuoteEscapeComments;
begin
with TSQLDBConnector(DBConnector).Query do
begin
SQL.Clear;
SQL.Add('select * from FPDEV where name=''test '''' and :ThisIsNotAParameter ''');
open;
close;
end;
end;
procedure TTestFieldTypes.TestParametersAndDates;
begin
with TSQLDBConnector(DBConnector).Query do