以下是DIP1036
的SQL
支持方式:
这里
cpp
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))
{ } //只需跳过它
else
sql ~= " " ~ 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
配合使用:
cpp
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; //跳过转义百分比
else
sql ~= 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
语句.
它是等价
的.