Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import std.typecons : Flag;
- alias PK = Flag!"isPrimaryKey";
- alias PrimaryKey = PK;
- class Table(Attributes...)
- {
- //TODO: Enforce at least 1 PK
- import std.exception;
- // Build Record structure
- pragma(msg, "Building Record structure");
- enum THE_STRUCT = "static struct Record { " ~ generateStructAttributes!("", Attributes)() ~ "}";
- pragma(msg, "\t", THE_STRUCT);
- mixin(THE_STRUCT);
- static string generateStructAttributes(string attDeclarations)()
- {
- return attDeclarations;
- }
- static string generateStructAttributes(string attDeclarations, string name, K, T...)()
- {
- pragma(msg, "\tAdding attribute to Record: ", name, "(", K.stringof, ")");
- enum newAttDeclarations = attDeclarations ~ K.stringof ~ " " ~ name ~ "; ";
- static if(T.length && is(typeof(T[0]) == PK))
- {
- return generateStructAttributes!(newAttDeclarations, T[1..$]);
- }
- else
- {
- return generateStructAttributes!(newAttDeclarations, T)();
- }
- }
- // Build Index structure
- static string mapOf(string name)()
- {
- return "map_" ~ name;
- }
- mixin Index!Attributes;
- mixin template Index(){}
- mixin template Index(string name, K, T...)
- {
- pragma(msg, "\tAttribute: ", name, "(", K.stringof, ")");
- static if(is(typeof(T[0]) == PK))
- {
- static if(T[0] == PK.yes)
- {
- pragma(msg, "\t\tIndexing this!");
- mixin("Record[" ~ K.stringof ~ "] " ~ mapOf!name ~ ";");
- }
- mixin Index!(T[1..$]);
- }
- else
- {
- mixin Index!T;
- }
- }
- Record get(string key, T)(T t)
- {
- import std.conv : to;
- mixin("if(t !in " ~ mapOf!key ~ ") throw new Exception(\"Key \\\"\" ~ t.to!string ~ \"\\\" not found!\"); "
- ~ "return " ~ mapOf!key ~ "[t];");
- }
- Record get(string key, T)(T t, Record defaultValue)
- {
- import core.exception : RangeError;
- import std.exception : ifThrown;
- mixin("return (" ~ mapOf!key ~ "[t]).ifThrown!RangeError(defaultValue);");
- }
- void set(Record r)
- {
- pragma(msg, "Building setters");
- enum SETTER_STRING = Setters!("", Attributes)();
- pragma(msg, "\t", SETTER_STRING);
- mixin(SETTER_STRING);
- _length += 1;
- }
- static string Setters(string setterMixinString)(){ return setterMixinString; }
- static string Setters(string setterMixinString, string name, K, T...)()
- {
- pragma(msg, "\tSetter ", name, "(", K.stringof, ")");
- static if(is(typeof(T[0]) == PK))
- {
- static if(T[0] == PK.yes)
- {
- pragma(msg, "\t\tHooking into index");
- enum newSetterMixinString = setterMixinString ~ "if(r." ~ name ~ " in " ~ mapOf!name ~ ") throw new Exception(\"Unique key constraint failed!\"); "
- ~ mapOf!name ~ "[r." ~ name ~ "] = r; ";
- return Setters!(newSetterMixinString, T[1..$]);
- }
- return Setters!(setterMixinString, T[1..$]);
- }
- else
- {
- return Setters!T;
- }
- }
- bool has(string key, T)(T t)
- {
- pragma(msg, "Building 'has' functions");
- enum HAS_STRING = HasFunctions!("", Attributes)();
- pragma(msg, "\t", HAS_STRING);
- mixin(HAS_STRING);
- }
- // FIXME: Can we factor this out somehow?
- static string HasFunctions(string hasMixinString)(){ return hasMixinString ~ " return false;"; }
- static string HasFunctions(string hasMixinString, string name, K, T...)()
- {
- pragma(msg, "\tSetter ", name, "(", K.stringof, ")");
- static if(is(typeof(T[0]) == PK))
- {
- static if(T[0] == PK.yes)
- {
- pragma(msg, "\t\tHooking into index");
- enum newHasMixinString = hasMixinString ~ " if(t in " ~ mapOf!name ~ ") return true;";
- return HasFunctions!(newHasMixinString, T[1..$]);
- }
- return HasFunctions!(hasMixinString, T[1..$]);
- }
- else
- {
- return HasFunctions!T;
- }
- }
- auto length() @property { return _length; }
- auto empty() @property { return _length == 0; }
- private:
- size_t _length = 0;
- }
- unittest
- {
- alias Tabble = Table!("name", string, PK.yes, "number", size_t, PK.no);
- alias Rec = Tabble.Record;
- auto t = new Tabble();
- Rec d = Rec("INVALID", 42);
- t.set(Rec("Blarg", 1231));
- import std.stdio;
- writeln(t.has!"name"("blarg"));
- writeln(t.get!"name"("blarg", d));
- writeln(t.has!"name"("Blarg"));
- writeln(t.get!"name"("Blarg"));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement