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