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

Reply via email to