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