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