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