1 module dpq.meta; 2 3 import dpq.attributes; 4 5 import std.traits; 6 import std.typecons : Nullable; 7 import std.datetime : SysTime; 8 9 version(unittest) import std.stdio; 10 11 deprecated("Use SQLType instead, not all array types are supported by sqlType") 12 string sqlType(T)() 13 { 14 // TODO: More types, embedded structs, Date types 15 16 static if (isArray!T) 17 alias FT = ForeachType!T; 18 else 19 alias FT = T; 20 21 static if (is(FT == int) || is(FT == ushort)) 22 enum type = "INT"; 23 else static if (is(FT == long) || is(FT == uint)) 24 enum type = "INT8"; 25 else static if (is(FT == short)) 26 enum type = "INT2"; 27 else static if (is(FT == long)) 28 enum type = "BIGINT"; 29 else static if (is(FT == float)) 30 enum type = "FLOAT4"; 31 else static if (is(FT == double)) 32 enum type = "FLOAT8"; 33 else static if (is(FT == char[]) || is(FT == string)) 34 enum type = "TEXT"; 35 else static if (is(FT == bool)) 36 enum type = "BOOL"; 37 else static if (is(FT == char)) 38 enum type = "CHAR(1)"; 39 else static if(is(FT == ubyte[]) || is(FT == byte[])) 40 enum type = "BYTEA"; 41 else static if (is(FT == enum)) 42 enum type = sqlType!(OriginalType!FT); 43 else 44 static assert(false, "Cannot map type \"" ~ T.stringof ~ "\" to any PG type, please specify it manually using @type."); 45 46 static if (isArray!T) 47 { 48 static if (isStaticArray!T) 49 return type ~ "[%d]".format(T.length); 50 else 51 return type ~ "[]"; 52 } 53 else 54 return type; 55 } 56 57 /** 58 Returns the array's base type 59 60 Returns the string type for any type that returns true 61 for isSomeString!T 62 63 Examples: 64 --------------- 65 alias T = BaseType!(int[][]); 66 alias T2 = BaseType!(int[]); 67 alias T3 = BaseType!int; 68 alias T4 = BaseType!(string[]) 69 70 static assert(is(T == int)); 71 static assert(is(T2 == int)); 72 static assert(is(T3 == int)); 73 static assert(is(T4 == string)); 74 --------------- 75 */ 76 template BaseType(T) 77 { 78 static if (isArray!T && !isSomeString!T) 79 alias BaseType = BaseType!(ForeachType!T); 80 else 81 alias BaseType = Unqual!T; 82 } 83 84 unittest 85 { 86 writeln(" * meta"); 87 writeln("\t * BaseType"); 88 89 static assert(is(BaseType!(int[][][]) == int)); 90 static assert(is(BaseType!(string[]) == string)); 91 static assert(is(BaseType!string == string)); 92 static assert(is(BaseType!dstring == dstring)); 93 } 94 95 template SQLType(T) 96 { 97 alias BT = BaseType!T; 98 99 static if(isInstanceOf!(Nullable, T)) 100 { 101 enum SQLType = SQLType!(Unqual!(typeof(T.get))); 102 //enum isNullable = true; 103 } 104 else 105 { 106 enum isNullable = false; 107 static if(is(T == ubyte[]) || is(T == byte[])) 108 enum SQLType = "BYTEA"; 109 else 110 { 111 static if (isSomeString!BT) 112 enum type = "TEXT"; 113 else static if (is(BT == SysTime)) 114 enum type = "timestamp"; 115 else static if (is(BT == int)) 116 enum type = "INT4"; 117 else static if (is(BT == long)) 118 enum type = "INT8"; 119 else static if (is(BT == short)) 120 enum type = "INT2"; 121 else static if (is(BT == float)) 122 enum type = "FLOAT4"; 123 else static if (is(BT == double)) 124 enum type = "FLOAT8"; 125 else static if (is(BT == bool)) 126 enum type = "BOOL"; 127 else static if (is(BT == char)) 128 enum type = "CHAR(1)"; 129 else static if (is(BT == enum)) 130 enum type = SQLType!(OriginalType!BT); 131 else 132 static assert(false, 133 "Cannot map type \"" ~ T.stringof ~ "\" to any PG type, " ~ 134 "please note that embedded structures need an @embed " ~ 135 "or @type attribute if you do not wish to embed them."); 136 137 static if (isArray!T && !isSomeString!T) 138 enum SQLType = type ~ "[]"; 139 else 140 enum SQLType = type; 141 } 142 } 143 } 144 145 unittest 146 { 147 writeln("\t * SQLType"); 148 149 static assert(SQLType!int == "INT4"); 150 static assert(SQLType!long == "INT8"); 151 static assert(SQLType!float == "FLOAT4"); 152 static assert(SQLType!(int[]) == "INT4[]"); 153 static assert(SQLType!(long[]) == "INT8[]"); 154 static assert(SQLType!(double[]) == "FLOAT8[]"); 155 static assert(SQLType!(string) == "TEXT"); 156 static assert(SQLType!(string[]) == "TEXT[]"); 157 static assert(SQLType!(ubyte[]) == "BYTEA"); 158 159 static assert(SQLType!(Nullable!int) == "INT4"); 160 } 161 162 /** 163 Returns the number of dimensions of the given array type 164 165 Examples: 166 ----------------- 167 auto dims = ArrayDimensions!(int[][]); 168 static assert(dims == 2); 169 ----------------- 170 */ 171 template ArrayDimensions(T) 172 { 173 static if (isArray!T) 174 enum ArrayDimensions = 1 + ArrayDimensions!(ForeachType!T); 175 else 176 enum ArrayDimensions = 0; 177 } 178 179 unittest 180 { 181 writeln("\t * ArrayDimensions"); 182 183 static assert(ArrayDimensions!int == 0); 184 static assert(ArrayDimensions!(int[]) == 1); 185 static assert(ArrayDimensions!(int[][]) == 2); 186 static assert(ArrayDimensions!(int[][][]) == 3); 187 } 188 189 190 template ShouldRecurse(alias TA) 191 { 192 alias T = typeof(TA); 193 static if (is(T == class) || is(T == struct)) 194 static if (hasUDA!(TA, EmbedAttribute)) 195 enum ShouldRecurse = true; 196 else 197 enum ShouldRecurse = false; 198 else 199 enum ShouldRecurse = false; 200 }