在秘塔搜索和 Perplexity 等 AI 搜索工具的冲击下,很多技术人员使用 Google 的频率大幅度下降。最近 ChatGPT 4O 也增添了 Search the web 的功能。
但是在这些 AI 搜索工具诞生之前,Google 几乎是技术人员进行关键词搜索的第一选择。
笔者的文章 SAP 错误消息调试之七种武器:让所有的错误消息都能被定位,曾经介绍过 ABAP 的源代码搜索工具 RS_ABAP_SOURCE_SCAN.
这个工具虽然好用,但是除了指定关键字之外,还需要使用者指定搜索范围,即在哪个 ABAP 开发包里进行搜索。
这个搜索工具的效率随着待搜索 ABAP 对象的数量增加而下降。当指定的开发包内包含海量的 ABAP 对象时,可能需要花费大量的时间完成搜索,甚至会遇到 Time Out 的运行时错误。
这是因为该工具的实现,只是简单地将指定 ABAP 开发包里所有的 ABAP 程序的源代码,逐一通过 READ REPORT 关键字读到 ABAP 内表里:
然后使用 ABAP 关键字 FIND ALL OCCURANCES 进行字符串匹配。
所有这些操作,都是在 ABAP 应用层完成的。
ABAP Development Tool 里提供了真正的类似 Google 的全文搜索模式。
在 ABAP Source Search 菜单里,只需要指定搜索关键字,就可以在整个系统范围内,进行全文搜索,而且速度极快。笔者系统上将搜索结果设定为 100 时,每次搜索在一秒内即可完成。
搜索结果的例子如下,出现在 ABAP 代码中的匹配关键字,会自动高亮显示。
ABAP 全文搜索的工作原理是什么?本文将会展开深入阐述。
开启这个全文搜索功能的前提条件:
系统版本 ≥ 7.40 SP05
底层数据库为 HANA
Business Function SRIS_SOURCE_SEARCH 需要处于开启状态
我们在 ABAP Development Tool 里选择菜单 Show View->ABAP Communication Log, 打开工具的通信记录模式,然后重复一次搜索操作:
然后就能看到这个在 ABAP Development Tool 里发起的全文搜索请求,实际上是消费了这个 Restful API:
/sap/bc/adt/repository/informationsystem/textsearch?searchString=Jerry&searchFromIndex=1&searchToIndex=100
把这个 url 之前的主机名和端口号补全之后,粘贴到浏览器地址栏里访问,同样可以得到搜索结果:
既然拿到了 url,想研究这个全文搜索的工作原理就直接多了,直接在 SICF 事务码里找到 url 里 adt 节点的 handler class:
在其 IF_HTTP_EXTENSION~HANDLE_REQUEST 方法里设置断点,按部就班单步调试即可。
最后通过单步调试,发现 ABAP 全文搜索,通过 ADBC(ABAP Database Connectivity) 拼凑的下面这行 SQLScript Query 语句实现:
SELECT TOP 100 *, SNIPPETS("DATA") AS "ABAP_CODE" FROM "SAPAG3"."RIS_V_PROG_TADIR" WHERE CONTAINS(("DATA"),'Jerry') WITH PARAMETERS ( 'request_flags'='LINESNIPPETS' )
从语法上判断,很明显这行语句并不是 ABAP OPEN SQL,而是 HANA 数据库的 SQLScript.
通过 ADBC,ABAP 开发人员能够在 ABAP 应用层,触发底层数据库提供的普通 ABAP OPEN SQL 不支持的数据库操作,比如本文正在讲述的 ABAP 全文搜索。
ADBC 提供了一系列 ABAP 工具类,比如用来向底层数据库发起连接的 CL_SQL_CONNECTION, 以及封装 SQL 操作语句的 CL_SQL_STATEMENT 等等。
https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abencl_sql_connection.htm
我们来详细分析从调试器里观察到的 SQLScript:
SELECT TOP 100 *, SNIPPETS("DATA") AS "ABAP_CODE" FROM "SAPAG3"."RIS_V_PROG_TADIR" WHERE CONTAINS(("DATA"),'Jerry') WITH PARAMETERS ( 'request_flags'='LINESNIPPETS' )
大体上容易看出,这行语句的语义,是从 RIS_V_PROG_TADIR 中使用 WHERE 语句里的 CONTAINS 操作,将字段 DATA 包含 Jerry 的前100条记录检索出来。
CONTAINS:SAP HANA SQLScript 里一个 Predicate 断言函数。所谓 Predicate,指一个返回布尔值 true 或者 false 的函数。
https://help.sap.com/docs/SAP_HANA_PLATFORM/691cb949c1034198800afde3e5be6570/9a4da8f6f23b4ebf95c98f1104a56db4.html
SNIPPETS("DATA") AS "ABAP_CODE":是 SQLScript 提供的一个标准函数,帮助文档如下:
For search queries using the CONTAINS predicate, you can use the function SNIPPETS to return search results with an excerpt of the text with your search term highlighted in bold. This short text excerpt provides some context for you to see where and how the term is used in the document.
https://help.sap.com/docs/SAP_HANA_PLATFORM/691cb949c1034198800afde3e5be6570/986627cbde9349e69ba2376c9e12b662.html
也就是说,对于满足 CONTAINS 判定函数条件的那些数据库行,SNIPPETS 能够将指定的数据库字段值的摘要提取出来,并且将其中匹配的搜索关键字加粗显示。
SNIPPTS 函数对于加粗显示全文搜索里的关键字及其上下文,再合适不过了。
再看 RIS_V_PROG_TADIR 搜索的 RIS_V_PROG_TADIR,RIS 代表 Repository Information System,V 代表这是个视图,能在 SE11 里查看,来自 REPOSRC,TADIR 和 RIS_PROG_TADIR 三张表的连接。
TADIR 是 SAP ABAP 的注册表,详细介绍参看笔者之前的文章:
REPOSRC 的 DATA 字段,存放的就是 SAP ABAP 系统所有 ABAP 对象的源代码文本(压缩之后的版本)。
RIS_PROG_TADIR 是一张映射表,存放的是 ABAP 对象和存储其源代码的 ABAP 报表名称的一一映射关系。
笔者之前的文章介绍过,比如一个 ABAP 类有三个方法 A,B,C. 这三个方法的源代码,分别存储在名为 a,b,c 的 ABAP 报表里。
那么 A->a, B->b, C->c 的映射关系,就维护在 RIS_PROG_TADIR 这张表里。
理论上通过 ABAP 类方法名称 A,从 RIS_PROG_TADIR 里拿到 a,有了 a 之后就能从 REPOSRC 表的 DATA 字段,拿到方法 A 的源代码了。
以上就是 ABAP 代码全文搜索实现的技术实现原理介绍。关于这个功能收到的 ABAP 从业者的反馈,可以查阅这篇 SAP 社区博客的评论区:
https://community.sap.com/t5/application-development-blog-posts/abap-sourcecode-search/ba-p/13074566