9

对于文档和进一步检查,我想对许多项目中的所有 DFM 文件运行“提取字符串”以查找所有 SQL 语句。有没有可以做到这一点的命令行工具?DFM 文件都是文本格式。

4

5 回答 5

3

根据您使用的查询组件的类型,我想您可以在项目文件夹上使用命令行 grep(或任何其他文本搜索工具)来执行此操作。在 DFM 中,对于普通的类似 TQuery 的组件,您将拥有类似于以下内容的内容

   SQL.Strings=('select * from mytable')

或者可能(我没有可以检查的德尔福,在家的乐趣!)

   SQL.Text=('从我的表中选择 *')

考虑到这些字符串如何分布在 DFM 内的多条“行”上,并且考虑到您可能需要检查几个变化,我个人会编写一小段 Delphi 来执行此操作。

基本思想是;遍历给定目录中的所有文件/子文件夹,查找所有 DFM 文件,并将每个文件读入 TStringList,检查您感兴趣的任何 TQuery (etc) SQL 属性,然后编写结果(组件名称、文件名、实际 SQL 字符串)输出到结果文件。真的不应该超过一两个小时的工作。

如果你已经存储了 procs,你调用的不是 TQuery 类型的组件,你必须先看看 DFM 内部,看看 SQL 是如何出现的;它可能会沿着

   CommandText=( 'exec mysproc :id, :value' )

等等

编辑:在评论中的讨论之后,这是我的一个 DFM 的示例;

    (其他属性)
    SQL.Strings = (
      '选择 D.*,'
      'C.DESCRIPTION 作为 CLASS_DESCRIPTION, '
      'C.CHQ_NUM_THRESHOLD 作为 CLASS_CHQ_NUM_THRESHOLD,'
      'C.CREDIT_LIMIT 作为 CLASS_CREDIT_LIMIT,'
      'A.REF 作为 ACCOUNT_REF,'
      'A.SORT_CODE 作为 ACCOUNT_SORT_CODE,'
      'A.ACCOUNT_NUMBER 作为 ACCOUNT_ACCOUNT_NUMBER,'
      'A.PREFERRED_ACCOUNT AS ACCOUNT_PREFERRED_ACCOUNT'
      '从 '
      'DRAWER_ACCOUNTS A LEFT JOIN DRAWERS D'
      'ON D.REF=A.DRAWER_REF'
      'LEFT JOIN REF_DRAWER_CLASSES C'
      '在 D.DRAWER_CLASS = C.CLASS_ID'
      'WHERE A.SORT_CODE=:PSORT AND A.ACCOUNT_NUMBER=:PACC')
    (其他属性)

因此,我真正需要做的就是找出该SQL.Strings = (位,然后读取该行的其余部分和所有后续行,删除前导和尾随',直到我到达以结尾的行')'-此时我完成了。每行的引号中可能包含的任何有趣的 SQL(和注释)实际上都是无关紧要的。您想阅读您感兴趣的每一行,并在每行的第一个和最后一个引号之间剪掉文本。这必须有效,因为我看不到 Delphi 将如何以任何其他方式传输它,它不可能“读取”字符串内容 - 它只是在 stringlist (可能)分成几行和每一行的基础上工作在 DFM 中用打开和关闭分隔',并且整个字符串列表内容本身包含在一对括号内。

这有意义吗,还是我仍然错过了什么?:-)

于 2010-03-25T07:06:46.970 回答
2

这是来自 Felix Colibri 的 DFM 解析器

DFM 解析器

这是一个有趣的工具来做这样的事情

YACC

于 2010-03-26T09:46:01.527 回答
1

我创建了自己的 DFM 解析器,并使用来自 RAD Studio 和我工作的公司的 600 个源文件进行了测试。解析器是用 Go 编写的。

https://github.com/gonutz/dfm

您可以使用它解析 DFM 文件并递归检查内存中的对象,查找 dfm.String 类型的属性。

于 2020-06-21T18:30:44.077 回答
0

由于 DFM 基本上是 name=value 格式,因此您可以加载到 tStringlist,然后遍历每一行以查找您感兴趣的特定属性名称:

var
  slDfm : tStringList;
  Item : String;
  ix : integer;
begin
  slDFM := tStringlist.create;
  try
    slDFM.LoadFromFile( filename );
    for ix := 0 to slDfm.Count-1 do
      begin
        slDfm.Strings[ix] := Trim(slDfm.Strings[ix]);
        if SameText(Trim(slDfm.Names[ix]),'CommandText') then
          memo1.Lines.Add('"'+Trim(slDfm.ValueFromIndex[ix])+'"');
      end;
  finally
    slDFM.free;
  end;
end;
于 2010-03-25T16:29:49.613 回答
0

非常感谢您的回答!我将尝试的另一个解决方案是“用于 Delphi 和 C++ Builder 的 GNU Gettext ”中包含的“提取字符串”工具。

.po 文件不仅包括所有组件文本,还包括所有资源字符串(存储 SQL 命令的另一个位置),以及对源的引用(哪个 pas 或 dfm 文件,哪个组件属性名称),它是一个非常简单的“名称=值”列表已经。

使用 .po 文件可以很容易地从 .pas 文件中分出所有 SQL.Text 以及所有文件中名称为“SQL_...”的所有资源字符串。

于 2010-03-26T17:19:33.017 回答