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