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(typeof(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 == MySQLRawString)) {
71 	appender.put('\'');
72 	appender.put(cast(char[])value.data);
73 	appender.put('\'');
74 }
75 
76 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == MySQLBinary)) {
77 	appendValue(appender, value.data);
78 }
79 
80 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == MySQLValue)) {
81 	final switch(value.type) with (ColumnTypes) {
82 	case MYSQL_TYPE_NULL:
83 		appender.put("null");
84 		break;
85 	case MYSQL_TYPE_TINY:
86 		if (value.isSigned) {
87 			appendValue(appender, value.peek!byte);
88 		} else {
89 			appendValue(appender, value.peek!ubyte);
90 		}
91 		break;
92 	case MYSQL_TYPE_YEAR:
93 	case MYSQL_TYPE_SHORT:
94 		if (value.isSigned) {
95 			appendValue(appender, value.peek!short);
96 		} else {
97 			appendValue(appender, value.peek!ushort);
98 		}
99 		break;
100 	case MYSQL_TYPE_INT24:
101 	case MYSQL_TYPE_LONG:
102 		if (value.isSigned) {
103 			appendValue(appender, value.peek!int);
104 		} else {
105 			appendValue(appender, value.peek!uint);
106 		}
107 		break;
108 	case MYSQL_TYPE_LONGLONG:
109 		if (value.isSigned) {
110 			appendValue(appender, value.peek!long);
111 		} else {
112 			appendValue(appender, value.peek!ulong);
113 		}
114 		break;
115 	case MYSQL_TYPE_DOUBLE:
116 		appendValue(appender, value.peek!double);
117 		break;
118 	case MYSQL_TYPE_FLOAT:
119 		appendValue(appender, value.peek!float);
120 		break;
121 	case MYSQL_TYPE_SET:
122 	case MYSQL_TYPE_ENUM:
123 	case MYSQL_TYPE_VARCHAR:
124 	case MYSQL_TYPE_VAR_STRING:
125 	case MYSQL_TYPE_STRING:
126 	case MYSQL_TYPE_NEWDECIMAL:
127 	case MYSQL_TYPE_DECIMAL:
128 		appendValue(appender, value.peek!(char[]));
129 		break;
130 	case MYSQL_TYPE_BIT:
131 	case MYSQL_TYPE_TINY_BLOB:
132 	case MYSQL_TYPE_MEDIUM_BLOB:
133 	case MYSQL_TYPE_LONG_BLOB:
134 	case MYSQL_TYPE_BLOB:
135 	case MYSQL_TYPE_GEOMETRY:
136 		appendValue(appender, value.peek!(ubyte[]));
137 		break;
138 	case MYSQL_TYPE_TIME:
139 	case MYSQL_TYPE_TIME2:
140 		appendValue(appender, value.peek!Duration);
141 		break;
142 	case MYSQL_TYPE_DATE:
143 	case MYSQL_TYPE_NEWDATE:
144 	case MYSQL_TYPE_DATETIME:
145 	case MYSQL_TYPE_DATETIME2:
146 	case MYSQL_TYPE_TIMESTAMP:
147 	case MYSQL_TYPE_TIMESTAMP2:
148 		appendValue(appender, value.peek!SysTime);
149 		break;
150 	}
151 }
152 
153 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))) {
154 	appender.put('\'');
155 	auto ptr = value.ptr;
156 	auto end = value.ptr + value.length;
157 	while (ptr != end) {
158 		switch(*ptr) {
159 		case '\\':
160 		case '\'':
161 			appender.put('\\');
162 			goto default;
163 		default:
164 			appender.put(*ptr++);
165 		}
166 	}
167 	appender.put('\'');
168 }