秋·风

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

最近使用lazarus BufDataset控件遇到中文字段名称过滤时出错的问题,曾尝试将中文字段名加双引号或中括号,但仍然不行。经跟踪Bufdataset源码发现procedure TCustomExpressionParser.ParseString里的procedure ReadWord没正确识别中文引起的,修正这个问题比较简单:

打开/fpcsrc/packages/fcl-db/src/dbase/dbf_prscore.pas
定位fpcsrc 3.2.2版本832、865和867行(fpcsrc3.3.1版本:837、870和872行),按以下添加#$80..#$FF,然后重新编译fpcsrc及应用程序就可以。

          while (I2 <= Len) and (AnExpr[I2] in ['a'..'z', 'A'..'Z', '_', '0'..'9',#$80..#$FF]) do  //第837行添加#$80..#$FF
          // However string constants can also appear without delimiters
          'a'..'z', 'A'..'Z', '_',#$80..#$FF://第870行添加#$80..#$FF
            begin
              while (I2 <= Len) and (AnExpr[I2] in ['a'..'z', 'A'..'Z', '_', '0'..'9',#$80..#$FF]) do //第872行添加#$80..#$FF
                Inc(I2);
            end;

过滤前:

修复前中文字段过滤出错:

 修正后中文字段已能正确过滤:


按黄色行修改就可以。

  procedure ReadWord(AnExpr: string);
  var
    OldI2: Integer;
    constChar: Char;
  begin
    isConstant := false;
    I1 := I2;
    while (I1 < Len) and (AnExpr[I1] = ' ') do
      Inc(I1);
    I2 := I1;
    if I1 <= Len then
    begin
      if AnExpr[I2] = HexChar then
      begin
        Inc(I2);
        OldI2 := I2;
        ReadConstant(AnExpr, true);
        if I2 = OldI2 then
        begin
          isConstant := false;
          while (I2 <= Len) and (AnExpr[I2] in ['a'..'z', 'A'..'Z', '_', '0'..'9',#$80..#$FF]) do
            Inc(I2);
        end;
      end
      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) 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', '_',#$80..#$FF:
            begin
              while (I2 <= Len) and (AnExpr[I2] in ['a'..'z', 'A'..'Z', '_', '0'..'9',#$80..#$FF]) do
                Inc(I2);
            end;
          '>', '<':
            begin
              if (I2 <= Len) then
                Inc(I2);
              if AnExpr[I2] in ['=', '<', '>'] then
                Inc(I2);
            end;
          '=':
            begin
              if (I2 <= Len) then
                Inc(I2);
              if AnExpr[I2] in ['<', '>', '='] then
                Inc(I2);
            end;
          '&':
            begin
              if (I2 <= Len) then
                Inc(I2);
              if AnExpr[I2] in ['&'] then
                Inc(I2);
            end;
          '|':
            begin
              if (I2 <= Len) then
                Inc(I2);
              if AnExpr[I2] in ['|'] then
                Inc(I2);
            end;
          ':':
            begin
              if (I2 <= Len) then
                Inc(I2);
              if AnExpr[I2] = '=' then
                Inc(I2);
            end;
          '!':
            begin
              if (I2 <= Len) then
                Inc(I2);
              if AnExpr[I2] = '=' then //support for !=
                Inc(I2);
            end;
          '+':
            begin
              Inc(I2);
              if (AnExpr[I2] = '+') and FWordsList.Search(PChar('++'), I) then
                Inc(I2);
            end;
          '-':
            begin
              Inc(I2);
              if (AnExpr[I2] = '-') and FWordsList.Search(PChar('--'), I) then
                Inc(I2);
            end;
          '^', '/', '\', '*', '(', ')', '%', '~', '$':
            Inc(I2);
          '0'..'9':
            ReadConstant(AnExpr, false);
        else
          begin
            Inc(I2);
          end;
        end;
    end;
  end;

 

posted on 2023-07-20 09:08  秋·风  阅读(192)  评论(0编辑  收藏  举报