# HG changeset patch # User jbe # Date 1447517223 -3600 # Node ID 4bcedf32b0890f505ec2196264ec1f21a4568c95 # Parent fb98b17056e5a255a1003f1038a3dfe8d38aca12 Allow direct (proxy) access to fields of JSON object in a special column (set in the model) (write access not implemented yet) diff -r fb98b17056e5 -r 4bcedf32b089 libraries/mondelefant/mondelefant.lua --- a/libraries/mondelefant/mondelefant.lua Sat Nov 14 15:44:53 2015 +0100 +++ b/libraries/mondelefant/mondelefant.lua Sat Nov 14 17:07:03 2015 +0100 @@ -915,11 +915,22 @@ Primary key of a database class (model). Defaults to "id". +If the primary key is a tuple, then a sequence (table with integer keys mapped to the column names) must be used. If the primary key is contained in a JSON document within a table column, then a special object with the following fields is expected: {json_doc = "column_name", key = "field_name_within_json_object", type = "postgresql_type"}. + --]]-- class_prototype.primary_key = "id" --//-- --[[-- +.document_column + +Optional column name to redirect key lookups to. This can be used to allow for an easier access to fields of a JSON document. + +--]]-- +class_prototype.document_column = nil +--//-- + +--[[-- db_handle = -- database connection handle used by this class :get_db_conn() diff -r fb98b17056e5 -r 4bcedf32b089 libraries/mondelefant/mondelefant_native.c --- a/libraries/mondelefant/mondelefant_native.c Sat Nov 14 15:44:53 2015 +0100 +++ b/libraries/mondelefant/mondelefant_native.c Sat Nov 14 17:07:03 2015 +0100 @@ -1490,80 +1490,87 @@ // different lookup for lists and objects: if (result_type && !strcmp(result_type, "object")) { // object lua_settop(L, 3); - // try inherited attributes, methods or getter functions: - while (lua_toboolean(L, 3)) { - lua_getfield(L, 3, "object"); // 4 - lua_pushvalue(L, 2); // 5 - lua_gettable(L, 4); // 5 - if (!lua_isnil(L, 5)) return 1; - lua_settop(L, 3); - lua_getfield(L, 3, "object_get"); // 4 - lua_pushvalue(L, 2); // 5 - lua_gettable(L, 4); // 5 - if (lua_toboolean(L, 5)) { - lua_pushvalue(L, 1); // 6 - lua_call(L, 1, 1); // 5 + lua_pushnil(L); + lua_insert(L, 3); // optional document column name on stack position 3 + // try inherited attributes, methods or getter functions + // (and determine optional document column, if existent): + while (lua_toboolean(L, 4)) { // class on stack position 4 (due to insert) + lua_getfield(L, 4, "object"); // 5 + lua_pushvalue(L, 2); // 6 + lua_gettable(L, 5); // 6 + if (!lua_isnil(L, 6)) return 1; + lua_settop(L, 4); + lua_getfield(L, 4, "object_get"); // 5 + lua_pushvalue(L, 2); // 6 + lua_gettable(L, 5); // 6 + if (lua_toboolean(L, 6)) { + lua_pushvalue(L, 1); // 7 + lua_call(L, 1, 1); // 6 return 1; } - lua_settop(L, 3); - lua_pushliteral(L, "prototype"); // 4 - lua_rawget(L, 3); // 4 - lua_replace(L, 3); + lua_settop(L, 4); + if (lua_isnil(L, 3)) { + lua_getfield(L, 4, "document_column"); // 5 + lua_replace(L, 3); + } + lua_pushliteral(L, "prototype"); // 5 + lua_rawget(L, 4); // 5 + lua_replace(L, 4); } - lua_settop(L, 2); + lua_settop(L, 3); // try primary keys of referenced objects: lua_pushcfunction(L, mondelefant_class_get_foreign_key_reference_name - ); // 3 - lua_getfield(L, 1, "_class"); // 4 - lua_pushvalue(L, 2); // 5 - lua_call(L, 2, 1); // 3 - if (!lua_isnil(L, 3)) { - // reference name at stack position 3 - lua_pushcfunction(L, mondelefant_class_get_reference); // 4 - lua_getfield(L, 1, "_class"); // 5 - lua_pushvalue(L, 3); // 6 - lua_call(L, 2, 1); // reference info at stack position 4 - lua_getfield(L, 1, "_ref"); // 5 - lua_getfield(L, 4, "ref"); // 6 - lua_gettable(L, 5); // 6 - if (!lua_isnil(L, 6)) { - if (lua_toboolean(L, 6)) { - lua_getfield(L, 4, "that_key"); // 7 - if (lua_isnil(L, 7)) { + ); // 4 + lua_getfield(L, 1, "_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, 1, "_class"); // 6 + lua_pushvalue(L, 4); // 7 + lua_call(L, 2, 1); // reference info at stack position 5 + lua_getfield(L, 1, "_ref"); // 6 + lua_getfield(L, 4, "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, 6); // 7 + lua_gettable(L, 7); // 8 } else { lua_pushnil(L); } return 1; } } - lua_settop(L, 2); + lua_settop(L, 3); // try normal data field info: - lua_getfield(L, 1, "_data"); // 3 - lua_pushvalue(L, 2); // 4 - lua_gettable(L, 3); // 4 - if (!lua_isnil(L, 4)) return 1; - lua_settop(L, 2); + lua_getfield(L, 1, "_data"); // 4 + lua_pushvalue(L, 2); // 5 + lua_gettable(L, 4); // 5 + if (!lua_isnil(L, 5)) return 1; + lua_settop(L, 3); // TODO: keep _data table on stack // try cached referenced object (or cached NULL reference): - lua_getfield(L, 1, "_ref"); // 3 - lua_pushvalue(L, 2); // 4 - lua_gettable(L, 3); // 4 - if (lua_isboolean(L, 4) && !lua_toboolean(L, 4)) { + lua_getfield(L, 1, "_ref"); // 4 + lua_pushvalue(L, 2); // 5 + lua_gettable(L, 4); // 5 + if (lua_isboolean(L, 5) && !lua_toboolean(L, 5)) { lua_pushnil(L); return 1; - } else if (!lua_isnil(L, 4)) { + } else if (!lua_isnil(L, 5)) { return 1; } - lua_settop(L, 2); + lua_settop(L, 3); // try to load a referenced object: - lua_pushcfunction(L, mondelefant_class_get_reference); // 3 - lua_getfield(L, 1, "_class"); // 4 - lua_pushvalue(L, 2); // 5 - lua_call(L, 2, 1); // 3 - if (!lua_isnil(L, 3)) { + lua_pushcfunction(L, mondelefant_class_get_reference); // 4 + lua_getfield(L, 1, "_class"); // 5 + lua_pushvalue(L, 2); // 6 + lua_call(L, 2, 1); // 4 + if (!lua_isnil(L, 4)) { lua_settop(L, 2); lua_getfield(L, 1, "load"); // 3 lua_pushvalue(L, 1); // 4 (self) @@ -1576,6 +1583,18 @@ if (lua_isboolean(L, 4) && !lua_toboolean(L, 4)) lua_pushnil(L); // TODO: use special object instead of false return 1; } + lua_settop(L, 3); + // try proxy access to document in special column: + if (lua_toboolean(L, 3)) { + lua_getfield(L, 1, "_data"); // 4 TODO: keep on stack from earlier + lua_insert(L, 3); // column name to stack position 4 + lua_gettable(L, 3); // 4 + if (!lua_isnil(L, 4)) { + lua_pushvalue(L, 2); // 5 + lua_gettable(L, 4); // 5 + if (!lua_isnil(L, 5)) return 1; + } + } return 0; } else if (result_type && !strcmp(result_type, "list")) { // list lua_settop(L, 3);