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