C 预处理器 (cpp) 在历史上与 C 相关联(因此得名),但它确实是一个通用的文本处理器,可以用于(或滥用)其他用途。
考虑这个名为 location.src 的文件(稍后会详细介绍)。
// C++ style comments works here
/* C style works also */
-- plain old SQL comments also work,
-- but you should avoid using '#' style of comments,
-- this will confuse the C pre-processor ...
#define LOCATION_LEN 25
/* Debug helper macro */
#include "debug.src"
DROP TABLE IF EXISTS test.locations;
CREATE TABLE test.locations
(
`location` VARCHAR(LOCATION_LEN) NOT NULL
);
DROP PROCEDURE IF EXISTS test.AddLocation;
delimiter $$
CREATE PROCEDURE test.AddLocation (IN location VARCHAR(LOCATION_LEN))
BEGIN
-- example of macro
ASSERT(length(location) > 0, "lost or something ?");
-- do something
select "Hi there.";
END
$$
delimiter ;
和文件debug.src,其中包含:
#ifdef HAVE_DEBUG
#define ASSERT(C, T) \
begin \
if (not (C)) then \
begin \
declare my_msg varchar(1000); \
set my_msg = concat("Assert failed, file:", __FILE__, \
", line: ", __LINE__, \
", condition ", #C, \
", text: ", T); \
signal sqlstate "HY000" set message_text = my_msg; \
end; \
end if; \
end
#else
#define ASSERT(C, T) begin end
#endif
编译时:
cpp -E location.src -o location.sql
你会得到你正在寻找的代码,用 cpp 扩展#define 值。
编译时:
cpp -E -DHAVE_DEBUG location.src -o location.sql
你得到了同样的结果,加上 ASSERT 宏(作为奖励发布,以显示 可以做什么)。
假设在测试环境中部署了具有 HAVE_DEBUG 的构建(在 5.5 或更高版本中,因为使用了 SIGNAL),结果如下所示:
mysql> call AddLocation("Here");
+-----------+
| Hi there. |
+-----------+
| Hi there. |
+-----------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> call AddLocation("");
ERROR 1644 (HY000): Assert failed, file:location.src, line: 24, condition length(location) > 0, text: lost or something ?
请注意文件名、行号和条件如何指向源代码中 location.src 中引发断言的位置,再次感谢 C 预处理器。
现在,关于“.src”文件扩展名:
- 你可以使用任何东西。
- 具有不同的文件扩展名有助于生成文件等,并防止混淆。
编辑:最初发布为 .xql,为清楚起见重命名为 .src。这里没有与 xml 查询相关的内容。
与任何工具一样,使用 cpp 可以带来好处,并且以可移植方式维护 LOCATION_LEN 的用例看起来非常合理。
它也可能导致不好的事情,有太多的#include、嵌套的#ifdef hell、宏等,最终混淆了代码,所以你的里程可能会有所不同。
有了这个答案,你就得到了全部内容(#define、#include、#ifdef、__FILE__、__LINE__、#C,要构建的命令行选项),所以我希望它应该涵盖这一切。