Skip to content

Commit 0945055

Browse files
authored
Merge pull request #268 from schveiguy/fixUnsafeArgs
Fix unsafe args
2 parents 9e780b2 + 77f06c5 commit 0945055

File tree

3 files changed

+48
-31
lines changed

3 files changed

+48
-31
lines changed

source/mysql/impl/prepared.d

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,15 @@ struct UnsafePrepared
337337
void setArgs(T...)(T args)
338338
if(T.length == 0 || (!is(T[0] == Variant[]) && !is(T[0] == MySQLVal[])))
339339
{
340-
_safe.setArgs(args);
340+
// translate any variants to non-variants
341+
import std.meta;
342+
auto translateArg(alias arg)() {
343+
static if(is(typeof(arg) == Variant))
344+
return _toVal(arg);
345+
else
346+
return arg;
347+
}
348+
_safe.setArgs(staticMap!(translateArg, args));
341349
}
342350

343351
/// ditto

source/mysql/safe/commands.d

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,30 @@ struct ColumnSpecialization
5858
///ditto
5959
alias CSN = ColumnSpecialization;
6060

61+
// Common implementation for `queryRowTuple` overloads.
62+
package(mysql) void queryRowTupleImpl(T...)(Connection conn, ExecQueryImplInfo info, ref T args)
63+
{
64+
ulong ra;
65+
enforce!MYXNoResultRecieved(execQueryImpl(conn, info, ra));
66+
67+
auto rr = conn.getNextRow();
68+
/+if (!rr._valid) // The result set was empty - not a crime.
69+
return;+/
70+
enforce!MYX(rr._values.length == args.length, "Result column count does not match the target tuple.");
71+
foreach (size_t i, dummy; args)
72+
{
73+
import taggedalgebraic.taggedalgebraic : get, hasType;
74+
enforce!MYX(rr._values[i].hasType!(T[i]),
75+
"Tuple "~to!string(i)~" type and column type are not compatible.");
76+
// use taggedalgebraic get to avoid extra calls.
77+
args[i] = get!(T[i])(rr._values[i]);
78+
}
79+
// If there were more rows, flush them away
80+
// Question: Should I check in purgeResult and throw if there were - it's very inefficient to
81+
// allow sloppy SQL that does not ensure just one row!
82+
conn.purgeResult();
83+
}
84+
6185
@safe:
6286

6387
/++
@@ -446,30 +470,6 @@ void queryRowTuple(T...)(Connection conn, ref Prepared prepared, ref T args)
446470
prepared._lastInsertID = conn.lastInsertID; // Conceivably, this might be needed when multi-statements are enabled.
447471
}
448472

449-
/// Common implementation for `queryRowTuple` overloads.
450-
package(mysql) void queryRowTupleImpl(T...)(Connection conn, ExecQueryImplInfo info, ref T args)
451-
{
452-
ulong ra;
453-
enforce!MYXNoResultRecieved(execQueryImpl(conn, info, ra));
454-
455-
auto rr = conn.getNextRow();
456-
/+if (!rr._valid) // The result set was empty - not a crime.
457-
return;+/
458-
enforce!MYX(rr._values.length == args.length, "Result column count does not match the target tuple.");
459-
foreach (size_t i, dummy; args)
460-
{
461-
import taggedalgebraic.taggedalgebraic : get, hasType;
462-
enforce!MYX(rr._values[i].hasType!(T[i]),
463-
"Tuple "~to!string(i)~" type and column type are not compatible.");
464-
// use taggedalgebraic get to avoid extra calls.
465-
args[i] = get!(T[i])(rr._values[i]);
466-
}
467-
// If there were more rows, flush them away
468-
// Question: Should I check in purgeResult and throw if there were - it's very inefficient to
469-
// allow sloppy SQL that does not ensure just one row!
470-
conn.purgeResult();
471-
}
472-
473473
/++
474474
Execute an SQL SELECT command or prepared statement and return a single value:
475475
the first column of the first row received.

source/mysql/unsafe/commands.d

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,9 @@ UnsafeResultRange query(Connection conn, const(char[]) sql, ColumnSpecialization
193193
UnsafeResultRange query(T...)(Connection conn, const(char[]) sql, T args)
194194
if(T.length > 0 && !is(T[0] == Variant[]) && !is(T[0] == MySQLVal[]) && !is(T[0] == ColumnSpecialization) && !is(T[0] == ColumnSpecialization[]))
195195
{
196-
return SC.query(conn, sql, args).unsafe;
196+
auto prepared = conn.prepare(sql);
197+
prepared.setArgs(args);
198+
return query(conn, prepared);
197199
}
198200
///ditto
199201
UnsafeResultRange query(Connection conn, const(char[]) sql, Variant[] args) @system
@@ -303,7 +305,9 @@ Nullable!UnsafeRow queryRow(Connection conn, const(char[]) sql, ColumnSpecializa
303305
Nullable!UnsafeRow queryRow(T...)(Connection conn, const(char[]) sql, T args)
304306
if(T.length > 0 && !is(T[0] == Variant[]) && !is(T[0] == MySQLVal[]) && !is(T[0] == ColumnSpecialization) && !is(T[0] == ColumnSpecialization[]))
305307
{
306-
return SC.queryRow(conn, sql, args).unsafe;
308+
auto prepared = conn.prepare(sql);
309+
prepared.setArgs(args);
310+
return queryRow(conn, prepared);
307311
}
308312
///ditto
309313
Nullable!UnsafeRow queryRow(Connection conn, const(char[]) sql, Variant[] args) @system
@@ -368,20 +372,22 @@ args = The variables, taken by reference, to receive the values.
368372
+/
369373
void queryRowTuple(T...)(Connection conn, const(char[]) sql, ref T args)
370374
{
371-
return SC.queryRowTuple(conn, sql, args);
375+
return SC.queryRowTupleImpl(conn, ExecQueryImplInfo(false, sql), args);
372376
}
373377

374378
///ditto
375379
void queryRowTuple(T...)(Connection conn, ref Prepared prepared, ref T args)
376380
{
377-
SC.queryRowTuple(conn, prepared.safeForExec, args);
381+
auto preparedInfo = conn.registerIfNeeded(prepared.sql);
382+
SC.queryRowTupleImpl(conn, prepared.safe.getExecQueryImplInfo(preparedInfo.statementId), args);
383+
prepared.safe._lastInsertID = conn.lastInsertID; // Conceivably, this might be needed when multi-statements are enabled.
378384
}
379385

380386
///ditto
381387
void queryRowTuple(T...)(Connection conn, ref BackwardCompatPrepared prepared, ref T args) @system
382388
{
383389
auto p = prepared.prepared;
384-
SC.queryRowTuple(conn, p.safeForExec, args);
390+
queryRowTuple(conn, p, args);
385391
prepared._prepared = p;
386392
}
387393

@@ -465,8 +471,11 @@ Nullable!Variant queryValue(Connection conn, const(char[]) sql, ColumnSpecializa
465471
Nullable!Variant queryValue(T...)(Connection conn, const(char[]) sql, T args)
466472
if(T.length > 0 && !is(T[0] == Variant[]) && !is(T[0] == MySQLVal[]) && !is(T[0] == ColumnSpecialization) && !is(T[0] == ColumnSpecialization[]))
467473
{
468-
return SC.queryValue(conn, sql, args).asVariant;
474+
auto prepared = conn.prepare(sql);
475+
prepared.setArgs(args);
476+
return queryValue(conn, prepared);
469477
}
478+
470479
///ditto
471480
Nullable!Variant queryValue(Connection conn, const(char[]) sql, Variant[] args) @system
472481
{

0 commit comments

Comments
 (0)