# HG changeset patch # User jbe # Date 1453319003 -3600 # Node ID 1dbbe4c62f085b696ff76bf47744bb6fba7c87d2 # Parent f704f35923e22c651f9a300aa5f4c7fd540c2aa9 Methods :create_object() and :create_list() ignore any additional table argument; "_class" attribute is always set; "_col" proxy respects foreign keys diff -r f704f35923e2 -r 1dbbe4c62f08 libraries/mondelefant/mondelefant_native.autodoc.lua --- a/libraries/mondelefant/mondelefant_native.autodoc.lua Sat Jan 16 04:44:16 2016 +0100 +++ b/libraries/mondelefant/mondelefant_native.autodoc.lua Wed Jan 20 20:43:23 2016 +0100 @@ -96,7 +96,7 @@ db_list = -- database result being an empty list :create_list() -Creates an empty database result representing a list. The used meta-table is "result_metatable". The attribute "_connection" is set to the database handle, and the attribute "_type" is set to "list". +Creates an empty database result representing a list. The used meta-table is "result_metatable". The attribute "_connection" is set to the database handle, and the attribute "_type" is set to "list". The attribute "_class" is initialized to the default class prototype "class_prototype" of the module. --]]-- -- implemented in mondelefant_native.c as @@ -108,7 +108,7 @@ db_object = -- database result being an empty object (row) :create_object() -Creates an empty database result representing an object (row). The used meta-table is "result_metatable". The attribute "_connection" is set to the database handle, and the attribute "_type" is set to "object". Additionally the attributes "_data", "_dirty" and "_ref" are initialized with an empty table. TODO: Documentation of _data, _dirty and _ref. +Creates an empty database result representing an object (row). The used meta-table is "result_metatable". The attribute "_connection" is set to the database handle, and the attribute "_type" is set to "object". The attribute "_class" is initialized to the default class prototype "class_prototype" of the module. Additionally the attribute "_col" is set to a proxy table, and the attributes "_data", "_dirty" and "_ref" are initialized with an empty table. TODO: Documentation of _data, _dirty and _ref. --]]-- -- implemented in mondelefant_native.c as diff -r f704f35923e2 -r 1dbbe4c62f08 libraries/mondelefant/mondelefant_native.c --- a/libraries/mondelefant/mondelefant_native.c Sat Jan 16 04:44:16 2016 +0100 +++ b/libraries/mondelefant/mondelefant_native.c Wed Jan 20 20:43:23 2016 +0100 @@ -534,14 +534,9 @@ static int mondelefant_conn_create_list(lua_State *L) { // ensure that first argument is a database connection: luaL_checkudata(L, 1, MONDELEFANT_CONN_MT_REGKEY); - // if no second argument is given, use an empty table: - if (lua_isnoneornil(L, 2)) { - lua_settop(L, 1); - lua_newtable(L); // 2 - } else { - luaL_checktype(L, 2, LUA_TTABLE); - lua_settop(L, 2); - } + // create new table on stack position 2: + lua_settop(L, 1); + lua_newtable(L); // 2 // set meta-table for database result lists/objects: luaL_setmetatable(L, MONDELEFANT_RESULT_MT_REGKEY); // set "_connection" attribute to self: @@ -550,6 +545,9 @@ // set "_type" attribute to string "list": lua_pushliteral(L, "list"); // 3 lua_setfield(L, 2, "_type"); + // set "_class" attribute to default class: + lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CLASS_PROTO_REGKEY); // 3 + lua_setfield(L, 2, "_class"); // return created database result list: return 1; } @@ -558,14 +556,9 @@ static int mondelefant_conn_create_object(lua_State *L) { // ensure that first argument is a database connection: luaL_checkudata(L, 1, MONDELEFANT_CONN_MT_REGKEY); - // if no second argument is given, use an empty table: - if (lua_isnoneornil(L, 2)) { - lua_settop(L, 1); - lua_newtable(L); // 2 - } else { - luaL_checktype(L, 2, LUA_TTABLE); - lua_settop(L, 2); - } + // create new table on stack position 2: + lua_settop(L, 1); + lua_newtable(L); // 2 // set meta-table for database result lists/objects: luaL_setmetatable(L, MONDELEFANT_RESULT_MT_REGKEY); // set "_connection" attribute to self: @@ -574,6 +567,9 @@ // set "_type" attribute to string "object": lua_pushliteral(L, "object"); // 3 lua_setfield(L, 2, "_type"); // "object" or "list" + // set "_class" attribute to default class: + lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CLASS_PROTO_REGKEY); // 3 + lua_setfield(L, 2, "_class"); // create empty tables for "_data", "_dirty" and "_ref" attributes: lua_newtable(L); // 3 lua_setfield(L, 2, "_data"); @@ -1596,13 +1592,9 @@ if (lua_type(L, 2) != LUA_TSTRING || lua_tostring(L, 2)[0] == '_') { return 0; } - // value of "_class" attribute or default class on stack position 3: + // class on stack position 3: lua_settop(L, 2); lua_getfield(L, 1, "_class"); // 3 - if (!lua_toboolean(L, 3)) { - lua_settop(L, 2); - lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CLASS_PROTO_REGKEY); // 3 - } // get value of "_type" attribute: lua_getfield(L, 1, "_type"); // 4 result_type = lua_tostring(L, 4); @@ -1734,13 +1726,9 @@ lua_rawset(L, 1); return 1; } - // value of "_class" attribute or default class on stack position 4: + // class on stack position 4: lua_settop(L, 3); lua_getfield(L, 1, "_class"); // 4 - if (!lua_toboolean(L, 4)) { - lua_settop(L, 3); - lua_getfield(L, LUA_REGISTRYINDEX, MONDELEFANT_CLASS_PROTO_REGKEY); // 4 - } // get value of "_type" attribute: lua_getfield(L, 1, "_type"); // 5 result_type = lua_tostring(L, 5); @@ -1845,6 +1833,37 @@ luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 2); lua_rawgetp(L, 1, MONDELEFANT_COLUMNS_RESULT_LUKEY); // 3 + // try primary keys of referenced objects: + lua_pushcfunction(L, + mondelefant_class_get_foreign_key_reference_name + ); // 4 + lua_getfield(L, 3, "_class"); // 5 + lua_pushvalue(L, 2); // 6 + lua_call(L, 2, 1); // 4 + if (!lua_isnil(L, 4)) { + // reference name at stack position 4 + lua_pushcfunction(L, mondelefant_class_get_reference); // 5 + lua_getfield(L, 3, "_class"); // 6 + lua_pushvalue(L, 4); // 7 + lua_call(L, 2, 1); // reference info at stack position 5 + lua_getfield(L, 3, "_ref"); // 6 + lua_getfield(L, 5, "ref"); // 7 + lua_gettable(L, 6); // 7 + if (!lua_isnil(L, 7)) { + if (lua_toboolean(L, 7)) { + lua_getfield(L, 5, "that_key"); // 8 + if (lua_isnil(L, 8)) { + return luaL_error(L, "Missing 'that_key' entry in model reference."); + } + lua_gettable(L, 7); // 8 + } else { + lua_pushnil(L); + } + return 1; + } + } + lua_settop(L, 3); + // if not successful, use _data table: lua_getfield(L, 3, "_data"); // 4 lua_pushvalue(L, 2); // 5 lua_gettable(L, 4); // 5 @@ -1856,6 +1875,21 @@ luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 3); lua_rawgetp(L, 1, MONDELEFANT_COLUMNS_RESULT_LUKEY); // 4 + // reset reference cache, if neccessary: + lua_pushcfunction(L, + mondelefant_class_get_foreign_key_reference_name + ); // 5 + lua_getfield(L, 4, "_class"); // 6 + lua_pushvalue(L, 2); // 7 + lua_call(L, 2, 1); // 5 + if (!lua_isnil(L, 5)) { + lua_getfield(L, 4, "_ref"); // 6 + lua_pushvalue(L, 5); // 7 + lua_pushnil(L); // 8 + lua_settable(L, 6); + } + lua_settop(L, 4); + // set _data and _dirty: lua_getfield(L, 4, "_data"); // 5 lua_getfield(L, 4, "_dirty"); // 6 lua_pushvalue(L, 2);