* fcl-db: dbf,bufdataset (and descendents): allow filter using double delimiters inside string. Fixes issue #25432

allow escaping delimiters by doubling them e.g.
  Filter:='(NAME=''O''''Malley''''s "Magic" Hammer'')';
  which gives
  (NAME='O''Malley''s "Magic" Hammer')
  which will match record
  O'Malley's "Magic" Hammer

git-svn-id: trunk@26253 -
This commit is contained in:
reiniero 2013-12-19 16:42:57 +00:00
parent 4229c6b40f
commit 48e4fc4bb2
2 changed files with 31 additions and 7 deletions

View File

@ -835,17 +835,32 @@ var
else if AnExpr[I2] = FDecimalSeparator then
ReadConstant(AnExpr, false)
else
// String constants can be delimited by ' or "
// but need not be - see below
// To use a delimiter inside the string, double it up to escape it
case AnExpr[I2] of
'''', '"':
begin
isConstant := true;
constChar := AnExpr[I2];
Inc(I2);
while (I2 <= Len) and (AnExpr[I2] <> constChar) do
Inc(I2);
if I2 <= Len then
Inc(I2);
while (I2 <= Len) do
begin
// Regular character?
if (AnExpr[I2] <> constChar) then
Inc(I2)
else // we do have a const, now check for escaped consts
if (I2+1 <= Len) and
(AnExpr[I2+1]=constChar) then
Inc(I2,2) //skip past, deal with duplicates later
else //at the trailing delimiter
begin
Inc(I2); //move past delimiter
break;
end;
end;
end;
// However string constants can also appear without delimiters
'a'..'z', 'A'..'Z', '_':
begin
while (I2 <= Len) and (AnExpr[I2] in ['a'..'z', 'A'..'Z', '_', '0'..'9']) do
@ -933,8 +948,12 @@ begin
W := IntToStr(StrToInt(W));
end;
if (W[1] = '''') or (W[1] = '"') then
TempWord := TStringConstant.Create(W)
else begin
begin
// StringConstant will handle any escaped quotes
TempWord := TStringConstant.Create(W);
end
else
begin
DecSep := Pos(FDecimalSeparator, W);
if (DecSep > 0) then
begin

View File

@ -186,6 +186,8 @@ type
private
FValue: string;
public
// Allow undelimited, delimited by single quotes, delimited by double quotes
// If delimited, allow escaping inside string with double delimiters
constructor Create(AValue: string);
function AsPointer: PChar; override;
@ -606,7 +608,10 @@ begin
firstChar := AValue[1];
lastChar := AValue[Length(AValue)];
if (firstChar = lastChar) and ((firstChar = '''') or (firstChar = '"')) then
FValue := Copy(AValue, 2, Length(AValue) - 2)
begin
FValue := Copy(AValue, 2, Length(AValue) - 2);
FValue := StringReplace(FValue, firstChar+FirstChar, firstChar, [rfReplaceAll,rfIgnoreCase])
end
else
FValue := AValue;
end;