Browse Source

* Implemented the sqEscapeSlash and sqescapeRepeat connection options
* Adapted and added a test

git-svn-id: trunk@6085 -

joost 18 years ago
parent
commit
90a6bdcdd4

+ 3 - 3
fcl/db/db.pp

@@ -1624,9 +1624,9 @@ type
     Function  IsEqual(Value: TParams): Boolean;
     Function  IsEqual(Value: TParams): Boolean;
     Function  ParamByName(const Value: string): TParam;
     Function  ParamByName(const Value: string): TParam;
     Function  ParseSQL(SQL: String; DoCreate: Boolean): String;
     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 RemoveParam(Value: TParam);
     Procedure CopyParamValuesFromDataset(ADataset : TDataset; CopyBound : Boolean);
     Procedure CopyParamValuesFromDataset(ADataset : TDataset; CopyBound : Boolean);
     Property Dataset : TDataset Read GetDataset;
     Property Dataset : TDataset Read GetDataset;

+ 8 - 11
fcl/db/dsparams.inc

@@ -156,24 +156,24 @@ var pb : TParamBinding;
     rs : string;
     rs : string;
 
 
 begin
 begin
-  Result := ParseSQL(SQL,DoCreate,psInterbase, pb, rs);
+  Result := ParseSQL(SQL,DoCreate,True,True,psInterbase, pb, rs);
 end;
 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;
 var pb : TParamBinding;
     rs : string;
     rs : string;
 
 
 begin
 begin
-  Result := ParseSQL(SQL,DoCreate,ParameterStyle,pb, rs);
+  Result := ParseSQL(SQL,DoCreate,EscapeSlash,EscapeRepeat,ParameterStyle,pb, rs);
 end;
 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;
 var rs : string;
 
 
 begin
 begin
-  Result := ParseSQL(SQL,DoCreate,ParameterStyle,ParamBinding, rs);
+  Result := ParseSQL(SQL,DoCreate,EscapeSlash, EscapeRepeat, ParameterStyle,ParamBinding, rs);
 end;
 end;
 
 
 function SkipComments(var p: PChar; EscapeSlash, EscapeRepeat : Boolean) : Boolean;
 function SkipComments(var p: PChar; EscapeSlash, EscapeRepeat : Boolean) : Boolean;
@@ -187,7 +187,7 @@ var notRepeatEscaped : boolean;
       notRepeatEscaped := True;
       notRepeatEscaped := True;
       while not (p^ in [#0, QuoteChar]) do
       while not (p^ in [#0, QuoteChar]) do
       begin
       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);
         else Inc(p);
       end;
       end;
       if p^=QuoteChar then
       if p^=QuoteChar then
@@ -238,7 +238,7 @@ begin
   end; {case}
   end; {case}
 end;
 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
 type
   // used for ParamPart
   // used for ParamPart
@@ -280,10 +280,7 @@ begin
   p:=PChar(SQL);
   p:=PChar(SQL);
   BufStart:=p; // used to calculate ParamPart.Start values
   BufStart:=p; // used to calculate ParamPart.Start values
   repeat
   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
     case p^ of
       ':','?': // parameter
       ':','?': // parameter
         begin
         begin

+ 2 - 2
fcl/db/sqldb/interbase/ibconnection.pp

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

+ 10 - 1
fcl/db/sqldb/mysql/mysqlconn.inc

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

+ 8 - 1
fcl/db/sqldb/odbc/odbcconn.pas

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

+ 2 - 2
fcl/db/sqldb/postgres/pqconnection.pp

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

+ 10 - 4
fcl/db/sqldb/sqldb.pp

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

+ 26 - 17
fcl/dbtests/testbasics.pas

@@ -35,49 +35,58 @@ var Params  : TParams;
 begin
 begin
   Params := TParams.Create;
   Params := TParams.Create;
   AssertEquals(     'select * from table where id = $1',
   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',
   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)',
   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'')',
   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'')',
   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',
   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('$',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)',
   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('$',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'')',
   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('$$',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'')',
   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('$$',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'')',
   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('$$$',ReplStr);
 
 
   AssertEquals(     'select * from table where id = ?',
   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;
   Params.Free;
 end;
 end;

+ 12 - 0
fcl/dbtests/testsqlfieldtypes.pas

@@ -27,6 +27,7 @@ type
     procedure RunTest; override;
     procedure RunTest; override;
   published
   published
   
   
+    procedure TestDoubleQuoteEscapeComments;
     procedure TestpfInUpdateFlag; // bug 7565
     procedure TestpfInUpdateFlag; // bug 7565
     procedure TestInt;
     procedure TestInt;
     procedure TestScript;
     procedure TestScript;
@@ -801,6 +802,17 @@ begin
     inherited RunTest;
     inherited RunTest;
 end;
 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;
 procedure TTestFieldTypes.TestParametersAndDates;
 begin
 begin
   with TSQLDBConnector(DBConnector).Query do
   with TSQLDBConnector(DBConnector).Query do