【发布时间】:2014-12-15 12:15:20
【问题描述】:
为了简化用 C++ 编写 SQL 查询,我使用宏
#define SQL(...) #__VA_ARGS__
它工作正常,除非出现空字符串文字(在类似
SQL(select * from foo where bar = '')
),clang(并且没有其他编译器)给出警告
warning: empty character constant [-Winvalid-pp-token]
我正在做的是否违反标准或此处过于关键(字符文字未出现在预处理器指令中)的严重破解(我仍然保留,因为它允许多行 sql 语句可读)?
编辑: 忘了提到并非所有平台都支持 C++11,因此我们不能使用原始字符串文字。我们可能会在 VisualC++ 9.0 中停留几年,而 Gcc 4.6-somesnapshot 可能会更少,但仍然是几年。该 hack 也早于 C++11。
【问题讨论】:
-
这是一个严重的 hack :o) 我经常做的是:
std::ostringstream sql; sql << "select * from table"; sql << " where id = '"; sql << id; sql << "'"; mysql_execute(&mysql, sql.str().c_str()); -
@Galik:不敢提sql的字符串操作。那应该是开火!我所说的技巧只是用合适的多行结构替换双引号,因为我们的 SQL 语句在正确分解和缩进以提高可读性时通常有 30 行以上。
-
如果您拆分字符串文字,则很容易拥有可读的多行 sql 语句 - 即。
"select *" " from foo" " where bar = ''"可以分成 3 行(并缩进),但仍算作一个字符串文字。 -
@SanderDeDycker:是的。除了,好吧,假设你有超过 30 行的语句,你需要更改它,包括删除、添加、连接和拆分行。添加和删除引号是一件很痛苦的事,更不用说大多数编辑器不再自动缩进和括号匹配了。
-
@Angew:因为试图确保插入的参数不包含任何特殊字符或正确引用很容易出错,如果参数来自用户且难以诊断,错误会导致 SQL 注入漏洞否则错误。所有数据库都支持参数绑定,它负责正确引用,而且通常这样的语句只解析一次,并且可以使用多个参数替换运行,从而节省大量时间,因为查询不需要重新解析,尤其是重新优化。跨度>
标签: c++ clang language-lawyer c-preprocessor c++03