1 /**
2 *   PostgreSQL major types oids.
3 *
4 *   Copyright: © 2014 DSoftOut
5 *   Authors: NCrashed <ncrashed@gmail.com>
6 */
7 
8 module dpq2.oids;
9 
10 @safe:
11 
12 package OidType oid2oidType(Oid oid) pure
13 {
14     static assert(Oid.sizeof == OidType.sizeof);
15 
16     return cast(OidType)(oid);
17 }
18 
19 /**
20  * Convert between array Oid and element Oid or vice versa
21  *
22  * Params:
23  *  s = "array" or "element"
24  *  type = source object type
25  */
26 OidType oidConvTo(string s)(OidType type)
27 {
28     foreach(ref a; appropriateArrOid)
29     {
30         static if(s == "array")
31         {
32             if(a.value == type)
33                 return a.array;
34         }
35         else
36         static if(s == "element")
37         {
38             if(a.array == type)
39                 return a.value;
40         }
41         else
42         static assert(false, "Wrong oidConvTo type "~s);
43     }
44 
45     import dpq2.value: ValueConvException, ConvExceptionType;
46     import std.conv: to;
47 
48     throw new ValueConvException(
49             ConvExceptionType.NOT_IMPLEMENTED,
50             "Conv to "~s~" for type "~type.to!string~" isn't defined",
51             __FILE__, __LINE__
52         );
53 }
54 
55 /// Checks if Oid type can be mapped to native D integer
56 bool isNativeInteger(OidType t) pure
57 {
58     with(OidType)
59     switch(t)
60     {
61         case Int8:
62         case Int2:
63         case Int4:
64         case Oid:
65             return true;
66         default:
67             break;
68     }
69 
70     return false;
71 }
72 
73 /// Checks if Oid type can be mapped to native D float
74 bool isNativeFloat(OidType t) pure
75 {
76     with(OidType)
77     switch(t)
78     {
79         case Float4:
80         case Float8:
81             return true;
82         default:
83             break;
84     }
85 
86     return false;
87 }
88 
89 package:
90 
91 private struct AppropriateArrOid
92 {
93     OidType value;
94     OidType array;
95 }
96 
97 private static immutable AppropriateArrOid[] appropriateArrOid;
98 
99 shared static this()
100 {
101     alias A = AppropriateArrOid;
102 
103     with(OidType)
104     {
105         immutable AppropriateArrOid[] a =
106         [
107             A(Text, TextArray),
108             A(Name, NameArray),
109             A(Bool, BoolArray),
110             A(Int2, Int2Array),
111             A(Int4, Int4Array),
112             A(Int8, Int8Array),
113             A(Float4, Float4Array),
114             A(Float8, Float8Array),
115             A(Date, DateArray),
116             A(Time, TimeArray),
117             A(TimeWithZone, TimeWithZoneArray),
118             A(TimeStampWithZone, TimeStampWithZoneArray),
119             A(TimeStamp, TimeStampArray),
120             A(Line, LineArray),
121             A(Json, JsonArray),
122             A(UUID, UUIDArray)
123         ];
124 
125         appropriateArrOid = a;
126     }
127 }
128 
129 import derelict.pq.pq: Oid;
130 
131 bool isSupportedArray(OidType t) pure nothrow @nogc
132 {
133     with(OidType)
134     switch(t)
135     {
136         case BoolArray:
137         case ByteArrayArray:
138         case CharArray:
139         case Int2Array:
140         case Int4Array:
141         case TextArray:
142         case NameArray:
143         case Int8Array:
144         case Float4Array:
145         case Float8Array:
146         case TimeStampArray:
147         case TimeStampWithZoneArray:
148         case DateArray:
149         case TimeArray:
150         case TimeWithZoneArray:
151         case NumericArray:
152         case UUIDArray:
153         case LineArray:
154         case JsonArray:
155         case JsonbArray:
156             return true;
157         default:
158             break;
159     }
160 
161     return false;
162 }
163 
164 OidType detectOidTypeFromNative(T)()
165 {
166     import std.typecons : Nullable;
167 
168     static if(is(T == Nullable!R,R))
169         return detectOidTypeNotCareAboutNullable!(typeof(T.get));
170     else
171         return detectOidTypeNotCareAboutNullable!T;
172 }
173 
174 private OidType detectOidTypeNotCareAboutNullable(T)()
175 {
176     import std.bitmanip : BitArray;
177     import std.datetime.date : StdDate = Date, TimeOfDay, DateTime;
178     import std.datetime.systime : SysTime;
179     import std.traits : Unqual, isSomeString;
180     import std.uuid : StdUUID = UUID;
181     static import dpq2.conv.geometric;
182     static import dpq2.conv.time;
183     import vibe.data.json : VibeJson = Json;
184 
185     alias UT = Unqual!T;
186 
187     with(OidType)
188     {
189         static if(isSomeString!UT){ return Text; } else
190         static if(is(UT == ubyte[])){ return ByteArray; } else
191         static if(is(UT == bool)){ return Bool; } else
192         static if(is(UT == short)){ return Int2; } else
193         static if(is(UT == int)){ return Int4; } else
194         static if(is(UT == long)){ return Int8; } else
195         static if(is(UT == float)){ return Float4; } else
196         static if(is(UT == double)){ return Float8; } else
197         static if(is(UT == StdDate)){ return Date; } else
198         static if(is(UT == TimeOfDay)){ return Time; } else
199         static if(is(UT == dpq2.conv.time.TimeOfDayWithTZ)){ return TimeWithZone; } else
200         static if(is(UT == DateTime)){ return TimeStamp; } else
201         static if(is(UT == SysTime)){ return TimeStampWithZone; } else
202         static if(is(UT == dpq2.conv.time.TimeStamp)){ return TimeStamp; } else
203         static if(is(UT == dpq2.conv.time.TimeStampUTC)){ return TimeStampWithZone; } else
204         static if(is(UT == VibeJson)){ return Json; } else
205         static if(is(UT == StdUUID)){ return UUID; } else
206         static if(is(UT == BitArray)){ return VariableBitString; } else
207         static if(dpq2.conv.geometric.isValidPointType!UT){ return Point; } else
208         static if(dpq2.conv.geometric.isValidLineType!UT){ return Line; } else
209         static if(dpq2.conv.geometric.isValidPathType!UT){ return Path; } else
210         static if(dpq2.conv.geometric.isValidPolygon!UT){ return Polygon; } else
211         static if(dpq2.conv.geometric.isValidCircleType!UT){ return Circle; } else
212         static if(dpq2.conv.geometric.isValidLineSegmentType!UT){ return LineSegment; } else
213         static if(dpq2.conv.geometric.isValidBoxType!UT){ return Box; } else
214 
215         static assert(false, "Unsupported D type: "~T.stringof);
216     }
217 }
218 
219 /// Enum of Oid types defined in PG
220 public enum OidType : Oid
221 {
222     Undefined = 0, ///
223 
224     Bool = 16, ///
225     ByteArray = 17, ///
226     Char = 18, ///
227     Name = 19, ///
228     Int8 = 20, ///
229     Int2 = 21, ///
230     Int2Vector = 22, ///
231     Int4 = 23, ///
232     RegProc = 24, ///
233     Text = 25, ///
234     Oid = 26, ///
235     Tid = 27, ///
236     Xid = 28, ///
237     Cid = 29, ///
238     OidVector = 30, ///
239 
240     AccessControlList = 1033, ///
241     TypeCatalog = 71, ///
242     AttributeCatalog = 75, ///
243     ProcCatalog = 81, ///
244     ClassCatalog = 83, ///
245 
246     Json = 114, ///
247     Jsonb = 3802, ///
248     Xml = 142, ///
249     NodeTree = 194, ///
250     StorageManager = 210, ///
251 
252     Point = 600, ///
253     LineSegment = 601, ///
254     Path = 602, ///
255     Box = 603, ///
256     Polygon = 604, ///
257     Line = 628, ///
258 
259     Float4 = 700, ///
260     Float8 = 701, ///
261     AbsTime = 702, ///
262     RelTime = 703, ///
263     Interval = 704, ///
264     Unknown = 705, ///
265 
266     Circle = 718, ///
267     Money = 790, ///
268     MacAddress = 829, ///
269     HostAddress = 869, ///
270     NetworkAddress = 650, ///
271 
272     FixedString = 1042, ///
273     VariableString = 1043, ///
274 
275     Date = 1082, ///
276     Time = 1083, ///
277     TimeStamp = 1114, ///
278     TimeStampWithZone = 1184, ///
279     TimeInterval = 1186, ///
280     TimeWithZone = 1266, ///
281 
282     FixedBitString = 1560, ///
283     VariableBitString = 1562, ///
284 
285     Numeric = 1700, ///
286     RefCursor = 1790, ///
287     RegProcWithArgs = 2202, ///
288     RegOperator = 2203, ///
289     RegOperatorWithArgs = 2204, ///
290     RegClass = 2205, ///
291     RegType = 2206, ///
292 
293     UUID = 2950, ///
294     TSVector = 3614, ///
295     GTSVector = 3642, ///
296     TSQuery = 3615, ///
297     RegConfig = 3734, ///
298     RegDictionary = 3769, ///
299     TXidSnapshot = 2970, ///
300 
301     Int4Range = 3904, ///
302     NumRange = 3906, ///
303     TimeStampRange = 3908, ///
304     TimeStampWithZoneRange = 3910, ///
305     DateRange = 3912, ///
306     Int8Range = 3926, ///
307 
308     // Arrays
309     XmlArray = 143, ///
310     JsonbArray = 3807, ///
311     JsonArray = 199, ///
312     LineArray = 629, ///
313     BoolArray = 1000, ///
314     ByteArrayArray = 1001, ///
315     CharArray = 1002, ///
316     NameArray = 1003, ///
317     Int2Array = 1005, ///
318     Int2VectorArray = 1006, ///
319     Int4Array = 1007, ///
320     RegProcArray = 1008, ///
321     TextArray = 1009, ///
322     OidArray  = 1028, ///
323     TidArray = 1010, ///
324     XidArray = 1011, ///
325     CidArray = 1012, ///
326     OidVectorArray = 1013, ///
327     FixedStringArray = 1014, ///
328     VariableStringArray = 1015, ///
329     Int8Array = 1016, ///
330     PointArray = 1017, ///
331     LineSegmentArray = 1018, ///
332     PathArray = 1019, ///
333     BoxArray = 1020, ///
334     Float4Array = 1021, ///
335     Float8Array = 1022, ///
336     AbsTimeArray = 1023, ///
337     RelTimeArray = 1024, ///
338     IntervalArray = 1025, ///
339     PolygonArray = 1027, ///
340     AccessControlListArray = 1034, ///
341     MacAddressArray = 1040, ///
342     HostAdressArray = 1041, ///
343     NetworkAdressArray = 651, ///
344     CStringArray = 1263, ///
345     TimeStampArray = 1115, ///
346     DateArray = 1182, ///
347     TimeArray = 1183, ///
348     TimeStampWithZoneArray = 1185, ///
349     TimeIntervalArray = 1187, ///
350     NumericArray = 1231, ///
351     TimeWithZoneArray = 1270, ///
352     FixedBitStringArray = 1561, ///
353     VariableBitStringArray = 1563, ///
354     RefCursorArray = 2201, ///
355     RegProcWithArgsArray = 2207, ///
356     RegOperatorArray = 2208, ///
357     RegOperatorWithArgsArray = 2209, ///
358     RegClassArray = 2210, ///
359     RegTypeArray = 2211, ///
360     UUIDArray = 2951, ///
361     TSVectorArray = 3643, ///
362     GTSVectorArray = 3644, ///
363     TSQueryArray = 3645, ///
364     RegConfigArray = 3735, ///
365     RegDictionaryArray = 3770, ///
366     TXidSnapshotArray = 2949, ///
367     Int4RangeArray = 3905, ///
368     NumRangeArray = 3907, ///
369     TimeStampRangeArray = 3909, ///
370     TimeStampWithZoneRangeArray = 3911, ///
371     DateRangeArray = 3913, ///
372     Int8RangeArray = 3927, ///
373 
374     // Pseudo types
375     Record = 2249, ///
376     RecordArray = 2287, ///
377     CString = 2275, ///
378     AnyVoid = 2276, ///
379     AnyArray = 2277, ///
380     Void = 2278, ///
381     Trigger = 2279, ///
382     EventTrigger = 3838, ///
383     LanguageHandler = 2280, ///
384     Internal = 2281, ///
385     Opaque = 2282, ///
386     AnyElement = 2283, ///
387     AnyNoArray = 2776, ///
388     AnyEnum = 3500, ///
389     FDWHandler = 3115, ///
390     AnyRange = 3831, ///
391 }