Advertisement
Guest User

table.d

a guest
Jul 12th, 2015
183
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 4.10 KB | None | 0 0
  1. import std.typecons : Flag;
  2. alias PK = Flag!"isPrimaryKey";
  3. alias PrimaryKey = PK;
  4.  
  5. class Table(Attributes...)
  6. {
  7.     //TODO: Enforce at least 1 PK
  8.     import std.exception;
  9.     // Build Record structure
  10.     pragma(msg, "Building Record structure");
  11.     enum THE_STRUCT = "static struct Record { " ~ generateStructAttributes!("", Attributes)() ~ "}";
  12.     pragma(msg, "\t", THE_STRUCT);
  13.     mixin(THE_STRUCT);
  14.  
  15.     static string generateStructAttributes(string attDeclarations)()
  16.     {
  17.         return attDeclarations;
  18.     }
  19.     static string generateStructAttributes(string attDeclarations, string name, K, T...)()
  20.     {
  21.         pragma(msg, "\tAdding attribute to Record: ", name, "(", K.stringof, ")");
  22.         enum newAttDeclarations = attDeclarations ~ K.stringof ~ " " ~ name ~ "; ";
  23.         static if(T.length && is(typeof(T[0]) == PK))
  24.         {
  25.             return generateStructAttributes!(newAttDeclarations, T[1..$]);
  26.         }
  27.         else
  28.         {
  29.             return generateStructAttributes!(newAttDeclarations, T)();
  30.         }
  31.     }
  32.  
  33.     // Build Index structure
  34.  
  35.     static string mapOf(string name)()
  36.     {
  37.         return "map_" ~ name;
  38.     }
  39.  
  40.     mixin Index!Attributes;
  41.     mixin template Index(){}
  42.     mixin template Index(string name, K, T...)
  43.     {
  44.         pragma(msg, "\tAttribute: ", name, "(", K.stringof, ")");
  45.         static if(is(typeof(T[0]) == PK))
  46.         {
  47.             static if(T[0] == PK.yes)
  48.             {
  49.                 pragma(msg, "\t\tIndexing this!");
  50.                 mixin("Record[" ~ K.stringof ~ "] " ~ mapOf!name ~ ";");
  51.             }
  52.             mixin Index!(T[1..$]);
  53.         }
  54.         else
  55.         {
  56.             mixin Index!T;
  57.         }
  58.     }
  59.  
  60.     Record get(string key, T)(T t)
  61.     {
  62.         import std.conv : to;
  63.         mixin("if(t !in " ~ mapOf!key ~ ") throw new Exception(\"Key \\\"\" ~ t.to!string ~ \"\\\" not found!\"); "
  64.                 ~ "return " ~ mapOf!key ~ "[t];");
  65.     }
  66.  
  67.     Record get(string key, T)(T t, Record defaultValue)
  68.     {
  69.         import core.exception : RangeError;
  70.         import std.exception : ifThrown;
  71.         mixin("return (" ~ mapOf!key ~ "[t]).ifThrown!RangeError(defaultValue);");
  72.     }
  73.  
  74.     void set(Record r)
  75.     {
  76.         pragma(msg, "Building setters");
  77.         enum SETTER_STRING = Setters!("", Attributes)();
  78.         pragma(msg, "\t", SETTER_STRING);
  79.         mixin(SETTER_STRING);
  80.         _length += 1;
  81.     }
  82.  
  83.     static string Setters(string setterMixinString)(){ return setterMixinString; }
  84.     static string Setters(string setterMixinString, string name, K, T...)()
  85.     {
  86.         pragma(msg, "\tSetter ", name, "(", K.stringof, ")");
  87.         static if(is(typeof(T[0]) == PK))
  88.         {
  89.             static if(T[0] == PK.yes)
  90.             {
  91.                 pragma(msg, "\t\tHooking into index");
  92.                 enum newSetterMixinString = setterMixinString ~ "if(r." ~ name ~ " in " ~ mapOf!name ~ ") throw new Exception(\"Unique key constraint failed!\"); "
  93.                                       ~ mapOf!name ~ "[r." ~ name ~ "] = r; ";
  94.                 return Setters!(newSetterMixinString, T[1..$]);
  95.             }
  96.             return Setters!(setterMixinString, T[1..$]);
  97.         }
  98.         else
  99.         {
  100.             return Setters!T;
  101.         }
  102.     }
  103.  
  104.     bool has(string key, T)(T t)
  105.     {
  106.         pragma(msg, "Building 'has' functions");
  107.         enum HAS_STRING = HasFunctions!("", Attributes)();
  108.         pragma(msg, "\t", HAS_STRING);
  109.         mixin(HAS_STRING);
  110.     }
  111.  
  112.     // FIXME: Can we factor this out somehow?
  113.     static string HasFunctions(string hasMixinString)(){ return hasMixinString ~ " return false;"; }
  114.     static string HasFunctions(string hasMixinString, string name, K, T...)()
  115.     {
  116.         pragma(msg, "\tSetter ", name, "(", K.stringof, ")");
  117.         static if(is(typeof(T[0]) == PK))
  118.         {
  119.             static if(T[0] == PK.yes)
  120.             {
  121.                 pragma(msg, "\t\tHooking into index");
  122.                 enum newHasMixinString = hasMixinString ~ " if(t in " ~ mapOf!name ~ ") return true;";
  123.                 return HasFunctions!(newHasMixinString, T[1..$]);
  124.             }
  125.             return HasFunctions!(hasMixinString, T[1..$]);
  126.         }
  127.         else
  128.         {
  129.             return HasFunctions!T;
  130.         }
  131.     }
  132.  
  133.     auto length() @property { return _length; }
  134.     auto empty() @property { return _length == 0; }
  135.  
  136. private:
  137.     size_t _length = 0;
  138. }
  139.  
  140. unittest
  141. {
  142.     alias Tabble = Table!("name", string, PK.yes, "number", size_t, PK.no);
  143.     alias Rec = Tabble.Record;
  144.     auto t = new Tabble();
  145.     Rec d = Rec("INVALID", 42);
  146.     t.set(Rec("Blarg", 1231));
  147.  
  148.     import std.stdio;
  149.     writeln(t.has!"name"("blarg"));
  150.     writeln(t.get!"name"("blarg", d));
  151.     writeln(t.has!"name"("Blarg"));
  152.     writeln(t.get!"name"("Blarg"));
  153. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement