1 module dpq.value; 2 3 import dpq.result; 4 import dpq.exception; 5 import dpq.meta; 6 import dpq.attributes; 7 import dpq.connection; 8 import dpq.serialisation; 9 10 //import derelict.pq.pq; 11 import libpq.libpq; 12 13 import std.algorithm : map; 14 import std.array; 15 import std.conv : to; 16 import std.typecons : Nullable, TypedefType; 17 import std.bitmanip; 18 import std.traits; 19 import std.datetime : SysTime, DateTime; 20 21 version(unittest) import std.stdio; 22 23 24 package enum Type : Oid 25 { 26 INFER = 0, 27 BOOL = 16, 28 BYTEA = 17, 29 CHAR = 18, 30 NAME = 19, 31 INT8 = 20, 32 INT2 = 21, 33 INT2VECTOR = 22, 34 INT4 = 23, 35 REGPROC = 24, 36 TEXT = 25, 37 OID = 26, 38 TID = 27, 39 XID = 28, 40 CID = 29, 41 OIDVECTOR = 30, 42 JSON = 114, 43 XML = 142, 44 PGNODETREE = 194, 45 POINT = 600, 46 LSEG = 601, 47 PATH = 602, 48 BOX = 603, 49 POLYGON = 604, 50 LINE = 628, 51 FLOAT4 = 700, 52 FLOAT8 = 701, 53 ABSTIME = 702, 54 RELTIME = 703, 55 TINTERVAL = 704, 56 UNKNOWN = 705, 57 CIRCLE = 718, 58 CASH = 790, 59 MACADDR = 829, 60 INET = 869, 61 CIDR = 650, 62 INT2ARRAY = 1005, 63 INT4ARRAY = 1007, 64 TEXTARRAY = 1009, 65 INT8ARRAY = 1016, 66 OIDARRAY = 1028, 67 FLOAT4ARRAY = 1021, 68 ACLITEM = 1033, 69 CSTRINGARRAY = 1263, 70 BPCHAR = 1042, 71 VARCHAR = 1043, 72 DATE = 1082, 73 TIME = 1083, 74 TIMESTAMP = 1114, 75 TIMESTAMPTZ = 1184, 76 INTERVAL = 1186, 77 TIMETZ = 1266, 78 BIT = 1560, 79 VARBIT = 1562, 80 NUMERIC = 1700, 81 REFCURSOR = 1790, 82 REGPROCEDURE = 2202, 83 REGOPER = 2203, 84 REGOPERATOR = 2204, 85 REGCLASS = 2205, 86 REGTYPE = 2206, 87 REGTYPEARRAY = 2211, 88 UUID = 2950, 89 LSN = 3220, 90 TSVECTOR = 3614, 91 GTSVECTOR = 3642, 92 TSQUERY = 3615, 93 REGCONFIG = 3734, 94 REGDICTIONARY = 3769, 95 JSONB = 3802, 96 INT4RANGE = 3904, 97 RECORD = 2249, 98 RECORDARRAY = 2287, 99 CSTRING = 2275, 100 ANY = 2276, 101 ANYARRAY = 2277, 102 VOID = 2278, 103 TRIGGER = 2279, 104 EVTTRIGGER = 3838, 105 LANGUAGE_HANDLER = 2280, 106 INTERNAL = 2281, 107 OPAQUE = 2282, 108 ANYELEMENT = 2283, 109 ANYNONARRAY = 2776, 110 ANYENUM = 3500, 111 FDW_HANDLER = 3115, 112 ANYRANGE = 3831, 113 } 114 115 package Oid[string] customTypes; 116 117 struct Value 118 { 119 private 120 { 121 ubyte[] _valueBytes; 122 int _size; 123 Type _type; 124 bool _isNull; 125 } 126 127 this(typeof(null) n) 128 { 129 _isNull = true; 130 } 131 132 this(T)(T val) 133 { 134 opAssign(val); 135 } 136 137 this(T)(T* val, int len, Type type = Type.INFER) 138 { 139 _size = len; 140 _type = type; 141 142 _valueBytes = val[0 .. len].dup; 143 } 144 145 void opAssign(T)(T val) 146 if (isArray!T) 147 { 148 _size = (ForeachType!T.sizeof * val.length).to!int; 149 150 static if (is(T == ubyte[])) 151 _valueBytes = val; 152 else 153 { 154 _valueBytes = toBytes(val); 155 _size = _valueBytes.length.to!int; 156 } 157 158 _type = typeOid!T; 159 } 160 161 void opAssign(T)(T val) 162 if(!isArray!T) 163 { 164 if (isAnyNull(val)) 165 { 166 _size = 0; 167 _valueBytes = null; 168 _isNull = true; 169 170 return; 171 } 172 173 _valueBytes = toBytes(val); 174 _size = _valueBytes.length.to!int; 175 _type = typeOid!T; 176 } 177 178 void opAssign(string val) 179 { 180 import std..string; 181 182 _valueBytes = val.representation.dup; 183 _size = _valueBytes.length.to!int; 184 _type = Type.TEXT; 185 } 186 187 void opAssign(SysTime val) 188 { 189 _type = typeOid!SysTime; 190 _size = typeof(val.stdTime).sizeof; 191 192 _valueBytes = toBytes(val); 193 } 194 195 void opAssign(Value val) 196 { 197 _valueBytes = val._valueBytes; 198 _size = val._size; 199 _type = val._type; 200 } 201 202 @property int size() 203 { 204 return _size; 205 } 206 207 @property Oid type() 208 { 209 return _type; 210 } 211 212 @property const(ubyte)* valuePointer() 213 { 214 return _valueBytes.ptr; 215 } 216 217 T as(T)() 218 if (isInstanceOf!(Nullable, T)) 219 { 220 alias RT = ReturnType!(T.get); 221 return as!(Unqual!RT); 222 } 223 224 Nullable!T as(T)() 225 if (!isInstanceOf!(Nullable, T)) 226 { 227 alias RT = Unqual!T; 228 229 if (_isNull) 230 return Nullable!RT.init; 231 232 ubyte[] data = _valueBytes[0 .. _size]; 233 return fromBytes!RT(data, _size); 234 } 235 236 unittest 237 { 238 import std.typecons : Typedef; 239 240 writeln("\t * as"); 241 242 Value v = "123"; 243 assert(v.as!string == "123"); 244 245 v = 123; 246 assert(v.as!int == 123); 247 248 v = [[1, 2], [3, 4]]; 249 assert(v.as!(int[][]) == [[1, 2], [3, 4]]); 250 251 int[2] arr = [1, 2]; 252 v = arr; 253 254 assert(v.as!(int[2]) == [1, 2]); 255 256 257 alias MyInt = Typedef!int; 258 MyInt x = 2; 259 v = Value(x); 260 assert(v.as!MyInt == x, v.as!(MyInt).to!string ~ " and " ~ x.to!string ~ " are not equal"); 261 } 262 } 263 264 265 Oid[] paramTypes(Value[] values) 266 { 267 return array(values.map!(v => v.type)); 268 } 269 270 int[] paramLengths(Value[] values) 271 { 272 return array(values.map!(v => v.size)); 273 } 274 275 int[] paramFormats(Value[] values) 276 { 277 return array(values.map!(v => 1)); 278 } 279 280 const(ubyte)*[] paramValues(Value[] values) 281 { 282 return array(values.map!(v => v.valuePointer)); 283 }