1 module pgsql.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 pgsql.protocol; 11 import pgsql.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 static if (isBoolean!T) { 36 appender.put(value ? "'t'" : "'f'"); 37 } else { 38 appender.put(cast(ubyte[])to!string(value)); 39 } 40 } 41 42 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == SysTime)) { 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 formattedWrite(appender, " %02d%02d%02d", hour, minute, second); 53 if (usec) 54 formattedWrite(appender, ".%06d", usec); 55 } 56 appender.put('\''); 57 } 58 59 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == DateTime)) { 60 auto hour = value.hour; 61 auto minute = value.minute; 62 auto second = value.second; 63 64 if (hour | minute | second) { 65 formattedWrite(appender, "'%04d%02d%02d%02d%02d%02d'", value.year, value.month, value.day, hour, minute, second); 66 } else { 67 formattedWrite(appender, "'%04d%02d%02d'", value.year, value.month, value.day); 68 } 69 } 70 71 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == TimeOfDay)) { 72 formattedWrite(appender, "'%02d%02d%02d'", value.hour, value.minute, value.second); 73 } 74 75 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == Date)) { 76 formattedWrite(appender, "'%04d%02d%02d'", value.year, value.month, value.day); 77 } 78 79 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == PgSQLFragment)) { 80 appender.put(cast(char[])value.data); 81 } 82 83 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == PgSQLRawString)) { 84 appender.put('\''); 85 appender.put(cast(char[])value.data); 86 appender.put('\''); 87 } 88 89 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == PgSQLBinary)) { 90 appendValue(appender, value.data); 91 } 92 93 void appendValue(Appender, T)(ref Appender appender, T value) if (is(Unqual!T == PgSQLValue)) { 94 final switch(value.type) with (PgColumnTypes) { 95 case UNKNOWN: 96 case NULL: 97 appender.put("null"); 98 break; 99 case CHAR: 100 appendValue(appender, value.peek!char); 101 break; 102 case BOOL: 103 appendValue(appender, value.peek!bool); 104 break; 105 case INT2: 106 appendValue(appender, value.peek!short); 107 break; 108 case INT4: 109 appendValue(appender, value.peek!int); 110 break; 111 case INT8: 112 appendValue(appender, value.peek!long); 113 break; 114 case REAL: 115 appendValue(appender, value.peek!float); 116 break; 117 case DOUBLE: 118 appendValue(appender, value.peek!double); 119 break; 120 case POINT: 121 case LSEG: 122 case PATH: 123 case BOX: 124 case POLYGON: 125 case LINE: 126 case TINTERVAL: 127 case INTERVAL: 128 case CIRCLE: 129 case BYTEA: 130 case JSONB: 131 appendValue(appender, value.peek!(ubyte[])); 132 break; 133 case NUMERIC: 134 case MONEY: 135 case BIT: 136 case VARBIT: 137 case INET: 138 case CIDR: 139 case MACADDR: 140 case MACADDR8: 141 case UUID: 142 case JSON: 143 case XML: 144 case TEXT: 145 case NAME: 146 case VARCHAR: 147 case CHARA: 148 appendValue(appender, value.peek!(char[])); 149 break; 150 case DATE: 151 appendValue(appender, value.peek!Date); 152 break; 153 case TIMETZ: 154 case TIME: 155 appendValue(appender, value.peek!TimeOfDay); 156 break; 157 case TIMESTAMP: 158 appendValue(appender, value.peek!DateTime); 159 break; 160 case TIMESTAMPTZ: 161 appendValue(appender, value.peek!SysTime); 162 break; 163 } 164 } 165 166 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))) { 167 appender.put('\''); 168 auto ptr = value.ptr; 169 auto end = value.ptr + value.length; 170 while (ptr != end) { 171 switch(*ptr) { 172 case '\\': 173 case '\'': 174 appender.put('\\'); 175 goto default; 176 default: 177 appender.put(*ptr++); 178 } 179 } 180 appender.put('\''); 181 }