String literal format parsing enhancement.
------------------------------------------
Key: CORE-3459
URL: http://tracker.firebirdsql.org/browse/CORE-3459
Project: Firebird Core
Issue Type: New Feature
Components: Engine
Reporter: Jason Wharton
Priority: Minor
I am working with data that has control characters in it that makes it so that
I cannot use the script component in my components effectively.
I wrote some routines in Delphi that produce strings I can work with in Pascal
but unfortuantely the Firebird string parser does not recognize the same
format. It would be very helpful if the statement parser were enhanced to allow
for this.
For example:
Insert into MyTable values ( 1234, 'Row1'#13#10'Row2' );
This would allow me to have the CRLF inside of a string literal without messing
up my script's formatting.
Here is the code in Pascal that handles this, in case it may be of any
assistance to whoever would enhance the Firebird statement parser. It is really
a very simple algorithm and it should not hurt performance in any significant
way. Look at the call with '#' as the value to the Lit: char parameter.
function isLitCriteria( const AStr: string; Lit: char ): Boolean;
var
tmpLen: integer;
tmpStr: string;
UsePound: boolean;
ii: integer;
jj: integer;
begin
UsePound := Lit = '#';
if UsePound then
Lit := '''';
tmpStr := Trim( AStr );
tmpLen := iboLength( tmpStr );
Result := tmpLen > 1;
if Result then
begin
if ( lit = '''' ) or ( lit = '"' ) then
Result := (( tmpStr[1] = lit ) and ( tmpStr[ tmpLen ] = lit ))
else
Result := (( tmpStr[1] = '''' ) and ( tmpStr[ tmpLen ] = '''' )) or
(( tmpStr[1] = '"' ) and ( tmpStr[ tmpLen ] = '"' ));
if not Result and UsePound then
begin
Result := true;
if tmpStr[ tmpLen ] <> '''' then
begin
repeat
jj := tmpLen;
while ( tmpLen >= 1 ) and
( tmpStr[tmpLen] >= '0' ) and
( tmpStr[tmpLen] <= '9' ) do Dec( tmpLen );
if ( tmpLen >= 1 ) and
( tmpStr[tmpLen] = '#' ) then Dec( tmpLen );
if ( tmpLen >= 1 ) and
( tmpStr[tmpLen] = '''' ) then Break;
if jj = tmpLen then
Result := false;
until ( not Result ) or ( tmpLen < 1 );
end;
ii := 1;
if Result and ( tmpStr[ 1 ] <> '''' ) and ( tmpLen > 0 ) then
begin
repeat
jj := ii;
if ( ii <= tmpLen ) and
( tmpStr[ii] = '#' ) then Inc( ii );
while ( ii <= tmpLen ) and
( tmpStr[ii] >= '0' ) and
( tmpStr[ii] <= '9' ) do Inc( ii );
if ( ii >= 1 ) and
( tmpStr[ii] = '''' ) then Break;
if jj = ii then
Result := false;
until ( not Result ) or ( ii = tmpLen );
end;
end;
end;
end;
function mkLitCriteria( const AStr: string; Lit: char ): string;
var
ii: integer;
LitFlag: boolean;
UsePound: boolean;
begin
UsePound := Lit = '#';
if isLitCriteria( AStr, Lit ) then
Result := AStr
else
begin
if UsePound then
Lit := '''';
Result := '';
LitFlag := true;
for ii := 1 to iboLength( AStr ) do
begin
if AStr[ii] = Lit then
begin
Result := Result + Lit + Lit;
LitFlag := true;
end
else
if ( AStr[ii] < ' ' ) and UsePound then
begin
if not LitFlag then
Result := Result + Lit;
Result := Result + '#' + IntToStr( Ord( AStr[ii] ));
LitFlag := true;
end
else
begin
if LitFlag then
Result := Result + Lit;
Result := Result + AStr[ii];
LitFlag := false;
end;
end;
if Result = '' then
Result := Lit + Lit
else
if not LitFlag then
Result := Result + Lit;
end;
end;
function stLitCriteria( const AStr: String; Lit: char ): String;
var
ii: integer;
jj: integer;
kk: integer;
tmpS: string;
LitFlag: boolean;
UsePound: boolean;
LitFound: boolean;
begin
LitFound := false;
UsePound := Lit = '#';
if ( Lit <> '''' ) and
( Lit <> '#' ) and
( Lit <> '"' ) then
begin
if isLitCriteria( AStr, '#' ) then
begin
Lit := '#';
LitFound := true;
UsePound := true;
end
else
if isLitCriteria( AStr, '''' ) then
begin
Lit := '''';
LitFound := true;
end
else
if isLitCriteria( AStr, '"' ) then
begin
Lit := '"';
LitFound := true;
end
else
begin
Result := AStr;
Exit;
end;
end;
if LitFound or isLitCriteria( AStr, Lit ) then
begin
if UsePound then
Lit := '''';
Result := AStr;
LitFlag := true;
ii := 1;
if Result = Lit + Lit then
begin
Result := '';
Exit;
end
else
while ii <= iboLength( Result ) do
begin
if LitFlag then
begin
if Result[ii] = Lit then
begin
iboDelete( Result, ii, 1 );
LitFlag := false;
end
else
if ( Result[ii] = '#' ) and UsePound then
begin
if ( ii > 1 ) and ( Result[ii-1] = '''' ) then
begin
iboDelete( Result, ii - 1, 1 );
Dec( ii );
end;
jj := ii;
kk := jj;
repeat
if Result[ii] = '#' then
iboDelete( Result, ii, 1 )
else
Break;
jj := ii;
kk := jj;
tmpS := '';
while ( jj <= iboLength( Result )) and
( Result[jj] >= '0' ) and
( Result[jj] <= '9' ) do
begin
tmpS := tmpS + Result[jj];
Inc( jj );
end;
if tmpS <> '' then
begin
Result[ii] := Char( StrToInt( tmpS ));
iboDelete( Result, ii + 1, jj - ii -1 );
end;
Inc( ii );
until ( ii = iboLength( Result )) or ( kk = jj ) or ( tmpS = '' );
LitFlag := Result[ii] = '''';
if LitFlag then
Dec( ii );
end;
end
else
LitFlag := Result[ii] = Lit;
Inc( ii );
end;
if LitFlag then
iboDelete( Result, ii - 1, 1 );
end
else
Result := AStr;
end;
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://tracker.firebirdsql.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
------------------------------------------------------------------------------
WhatsUp Gold - Download Free Network Management Software
The most intuitive, comprehensive, and cost-effective network
management toolset available today. Delivers lowest initial
acquisition cost and overall TCO of any competing solution.
http://p.sf.net/sfu/whatsupgold-sd
Firebird-Devel mailing list, web interface at
https://lists.sourceforge.net/lists/listinfo/firebird-devel