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 }