1 module mysql.appender; 2 3 4 import std.conv; 5 import std.datetime; 6 import std.format; 7 import std.traits; 8 import std.typecons; 9 10 import mysql.protocol; 11 import mysql.type; 12 13 14 void appendValues(Appender, T)(ref Appender appender, T values) if (isArray!T && !isSomeString!(OriginalType!T)) { 15 foreach (size_t i, value; values) { 16 appendValue(appender, value); 17 if (i != values.length-1) 18 appender.put(','); 19 } 20 } 21 22 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == typeof(null))) { 23 appender.put("null"); 24 } 25 26 void appendValue(Appender, T)(ref Appender appender, T value) if (isInstanceOf!(Nullable, T) || isInstanceOf!(NullableRef, T)) { 27 if (value.isNull) { 28 appendValue(appender, null); 29 } else { 30 appendValue(appender, value.get); 31 } 32 } 33 34 void appendValue(Appender, T)(ref Appender appender, T value) if (isScalarType!T) { 35 appender.put(cast(ubyte[])to!string(value)); 36 } 37 38 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == SysTime)) { 39 value = value.toUTC; 40 41 auto hour = value.hour; 42 auto minute = value.minute; 43 auto second = value.second; 44 auto usec = value.fracSecs.total!"usecs"; 45 46 formattedWrite(appender, "%04d%02d%02d", value.year, value.month, value.day); 47 if (hour | minute | second | usec) { 48 formattedWrite(appender, "%02d%02d%02d", hour, minute, second); 49 if (usec) 50 formattedWrite(appender, ".%06d", usec); 51 } 52 } 53 54 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == DateTime)) { 55 auto hour = value.hour; 56 auto minute = value.minute; 57 auto second = value.second; 58 59 if (hour | minute | second) { 60 formattedWrite(appender, "%04d%02d%02d%02d%02d%02d", value.year, value.month, value.day, hour, minute, second); 61 } else { 62 formattedWrite(appender, "%04d%02d%02d", value.year, value.month, value.day); 63 } 64 } 65 66 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == TimeOfDay)) { 67 formattedWrite(appender, "%02d%02d%02d", value.hour, value.minute, value.second); 68 } 69 70 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == Date)) { 71 formattedWrite(appender, "%04d%02d%02d", value.year, value.month, value.day); 72 } 73 74 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == Duration)) { 75 auto parts = value.split(); 76 if (parts.days) { 77 appender.put('\''); 78 formattedWrite(appender, "%d ", parts.days); 79 } 80 formattedWrite(appender, "%02d%02d%02d", parts.hours, parts.minutes, parts.seconds); 81 if (parts.usecs) 82 formattedWrite(appender, ".%06d ", parts.usecs); 83 if (parts.days) 84 appender.put('\''); 85 } 86 87 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == MySQLFragment)) { 88 appender.put(cast(char[])value.data); 89 } 90 91 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == MySQLRawString)) { 92 appender.put('\''); 93 appender.put(cast(char[])value.data); 94 appender.put('\''); 95 } 96 97 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == MySQLBinary)) { 98 appendValue(appender, value.data); 99 } 100 101 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == MySQLValue)) { 102 final switch(value.type) with (ColumnTypes) { 103 case MYSQL_TYPE_NULL: 104 appender.put("null"); 105 break; 106 case MYSQL_TYPE_TINY: 107 if (value.isSigned) { 108 appendValue(appender, value.peek!byte); 109 } else { 110 appendValue(appender, value.peek!ubyte); 111 } 112 break; 113 case MYSQL_TYPE_YEAR: 114 case MYSQL_TYPE_SHORT: 115 if (value.isSigned) { 116 appendValue(appender, value.peek!short); 117 } else { 118 appendValue(appender, value.peek!ushort); 119 } 120 break; 121 case MYSQL_TYPE_INT24: 122 case MYSQL_TYPE_LONG: 123 if (value.isSigned) { 124 appendValue(appender, value.peek!int); 125 } else { 126 appendValue(appender, value.peek!uint); 127 } 128 break; 129 case MYSQL_TYPE_LONGLONG: 130 if (value.isSigned) { 131 appendValue(appender, value.peek!long); 132 } else { 133 appendValue(appender, value.peek!ulong); 134 } 135 break; 136 case MYSQL_TYPE_DOUBLE: 137 appendValue(appender, value.peek!double); 138 break; 139 case MYSQL_TYPE_FLOAT: 140 appendValue(appender, value.peek!float); 141 break; 142 case MYSQL_TYPE_SET: 143 case MYSQL_TYPE_ENUM: 144 case MYSQL_TYPE_VARCHAR: 145 case MYSQL_TYPE_VAR_STRING: 146 case MYSQL_TYPE_STRING: 147 case MYSQL_TYPE_JSON: 148 case MYSQL_TYPE_NEWDECIMAL: 149 case MYSQL_TYPE_DECIMAL: 150 appendValue(appender, value.peek!(char[])); 151 break; 152 case MYSQL_TYPE_BIT: 153 case MYSQL_TYPE_TINY_BLOB: 154 case MYSQL_TYPE_MEDIUM_BLOB: 155 case MYSQL_TYPE_LONG_BLOB: 156 case MYSQL_TYPE_BLOB: 157 case MYSQL_TYPE_GEOMETRY: 158 appendValue(appender, value.peek!(ubyte[])); 159 break; 160 case MYSQL_TYPE_TIME: 161 case MYSQL_TYPE_TIME2: 162 appendValue(appender, value.peek!Duration); 163 break; 164 case MYSQL_TYPE_DATE: 165 case MYSQL_TYPE_NEWDATE: 166 case MYSQL_TYPE_DATETIME: 167 case MYSQL_TYPE_DATETIME2: 168 case MYSQL_TYPE_TIMESTAMP: 169 case MYSQL_TYPE_TIMESTAMP2: 170 appendValue(appender, value.peek!SysTime); 171 break; 172 } 173 } 174 175 void appendValue(Appender, T)(ref Appender appender, T value) if (isArray!T && (is(Unqual!(typeof(T.init[0])) == ubyte) || is(Unqual!(typeof(T.init[0])) == char))) { 176 appender.put('\''); 177 auto ptr = value.ptr; 178 auto end = value.ptr + value.length; 179 while (ptr != end) { 180 switch(*ptr) { 181 case '\\': 182 case '\'': 183 appender.put('\\'); 184 goto default; 185 default: 186 appender.put(*ptr++); 187 } 188 } 189 appender.put('\''); 190 }