原文
以下是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语句.
它是等价的.