原文
以下是DIP1036
的SQL
支持方式:
这里
auto execi(Args...)(Sqlite db, InterpolationHeader header, Args args, InterpolationFooter footer) {import arsd.sqlite;//`SQLite`允许你执行`?1,?2`等操作enum string query = () {string sql;int number;import std.conv;foreach(idx, arg; Args)static if(is(arg == InterpolatedLiteral!str, string str))sql ~= str;else static if(is(arg == InterpolationHeader) || is(arg == InterpolationFooter))throw new Exception("Nested interpolation not supported");else static if(is(arg == InterpolatedExpression!code, string code)){ } //只需跳过它elsesql ~= " " ~ to!string(++number);return sql;}();auto statement = Statement(db, query);int number;foreach(arg; args) {static if(!isInterpolatedMetadata!(typeof(arg)))statement.bind(++number, arg);}return statement.execute();
}
这里:
1
.按参数元组后转换istring
后,再传递给execi
模板.
2
.它循环
了参数,(讽刺的是!)再转换
为格式串
.格式不是%s
,而是?1,?2,?3
等.
3
.它跳过DIP1036
插入的所有插值参数
.
4
.把其余参数
分别绑定
到1,2,3
索引.
5
.然后它执行sql
语句.
注意,不支持嵌套
的istring
.
看看它如何与DIP1027
配合使用:
auto execi(Args...)(Sqlite db, Args args) {import arsd.sqlite;//`SQLite`允许你执行`?1,?2`等操作enum string query = () {string sql;int number;import std.conv;auto fmt = arg[0];for (size_t i = 0; i < fmt.length, ++i){char c = fmt[i];if (c == '%' && i + 1 < fmt.length && fmt[i + 1] == 's'){sql ~= " " ~ to!string(++number);++i;}else if (c == '%' && i + 1 < fmt.length && fmt[i + 1] == '%')++i; //跳过转义百分比elsesql ~= c;}return sql;}();auto statement = Statement(db, query);int number;foreach(arg; args[1 .. args.length]) {statement.bind(++number, arg);}return statement.execute();
}
这:
1
.在转换istring
为参数元组
后,传递
给execi
模板.
2
.第一个元组
元素是格式串
.
3
.用相应arg
的索引的"n"
,替换"%s"
的所有实例
.
4
.把替换格式串
绑定到语句
,把参数
绑定他们的索引
.
5
.然后执行sql
语句.
它是等价
的.