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