1 /++ 2 Escape special characters in MySQL strings. 3 4 Note, it is strongly recommended to use prepared statements instead of relying 5 on manual escaping, as prepared statements are always safer, better and more 6 reliable (see `mysql.prepared`). But if you absolutely must escape manually, 7 the functionality is provided here. 8 +/ 9 module mysql.escape; 10 11 12 /++ 13 Simple escape function for dangerous SQL characters 14 15 Params: 16 input = string to escape 17 output = output range to write to 18 +/ 19 void mysql_escape ( Output, Input ) ( Input input, Output output ) 20 { 21 import std.string : translate; 22 23 immutable string[dchar] transTable = [ 24 '\\' : "\\\\", 25 '\'' : "\\'", 26 '\0' : "\\0", 27 '\n' : "\\n", 28 '\r' : "\\r", 29 '"' : "\\\"", 30 '\032' : "\\Z" 31 ]; 32 33 translate(input, transTable, null, output); 34 } 35 36 37 /++ 38 Struct to wrap around an input range so it can be passed to formattedWrite and be 39 properly escaped without allocating a temporary buffer 40 41 Params: 42 Input = (Template Param) Type of the input range 43 44 Note: 45 The delegate is expected to be @safe as of version 3.2.0. 46 +/ 47 struct MysqlEscape ( Input ) 48 { 49 Input input; 50 51 const void toString ( scope void delegate(scope const(char)[]) @safe sink ) 52 { 53 mysql_escape(input, sink); 54 } 55 } 56 57 /++ 58 Helper function to easily construct a escape wrapper struct 59 60 Params: 61 T = (Template Param) Type of the input range 62 input = Input to escape 63 +/ 64 MysqlEscape!(T) mysqlEscape ( T ) ( T input ) 65 { 66 return MysqlEscape!(T)(input); 67 } 68 69 @("mysqlEscape") 70 debug(MYSQLN_TESTS) 71 @safe unittest 72 { 73 import std.array : appender; 74 75 auto buf = appender!string(); 76 77 import std.format : formattedWrite; 78 79 formattedWrite(buf, "%s, %s, %s, mkay?", 1, 2, 80 mysqlEscape("\0, \r, \n, \", \\")); 81 82 assert(buf.data() == `1, 2, \0, \r, \n, \", \\, mkay?`); 83 }