webmcp
changeset 376:4bcedf32b089
Allow direct (proxy) access to fields of JSON object in a special column (set in the model) (write access not implemented yet)
author | jbe |
---|---|
date | Sat Nov 14 17:07:03 2015 +0100 (2015-11-14) |
parents | fb98b17056e5 |
children | ecafddf7ac93 |
files | libraries/mondelefant/mondelefant.lua libraries/mondelefant/mondelefant_native.c |
line diff
1.1 --- a/libraries/mondelefant/mondelefant.lua Sat Nov 14 15:44:53 2015 +0100 1.2 +++ b/libraries/mondelefant/mondelefant.lua Sat Nov 14 17:07:03 2015 +0100 1.3 @@ -915,11 +915,22 @@ 1.4 1.5 Primary key of a database class (model). Defaults to "id". 1.6 1.7 +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"}. 1.8 + 1.9 --]]-- 1.10 class_prototype.primary_key = "id" 1.11 --//-- 1.12 1.13 --[[-- 1.14 +<db_class>.document_column 1.15 + 1.16 +Optional column name to redirect key lookups to. This can be used to allow for an easier access to fields of a JSON document. 1.17 + 1.18 +--]]-- 1.19 +class_prototype.document_column = nil 1.20 +--//-- 1.21 + 1.22 +--[[-- 1.23 db_handle = -- database connection handle used by this class 1.24 <db_class>:get_db_conn() 1.25
2.1 --- a/libraries/mondelefant/mondelefant_native.c Sat Nov 14 15:44:53 2015 +0100 2.2 +++ b/libraries/mondelefant/mondelefant_native.c Sat Nov 14 17:07:03 2015 +0100 2.3 @@ -1490,80 +1490,87 @@ 2.4 // different lookup for lists and objects: 2.5 if (result_type && !strcmp(result_type, "object")) { // object 2.6 lua_settop(L, 3); 2.7 - // try inherited attributes, methods or getter functions: 2.8 - while (lua_toboolean(L, 3)) { 2.9 - lua_getfield(L, 3, "object"); // 4 2.10 - lua_pushvalue(L, 2); // 5 2.11 - lua_gettable(L, 4); // 5 2.12 - if (!lua_isnil(L, 5)) return 1; 2.13 - lua_settop(L, 3); 2.14 - lua_getfield(L, 3, "object_get"); // 4 2.15 - lua_pushvalue(L, 2); // 5 2.16 - lua_gettable(L, 4); // 5 2.17 - if (lua_toboolean(L, 5)) { 2.18 - lua_pushvalue(L, 1); // 6 2.19 - lua_call(L, 1, 1); // 5 2.20 + lua_pushnil(L); 2.21 + lua_insert(L, 3); // optional document column name on stack position 3 2.22 + // try inherited attributes, methods or getter functions 2.23 + // (and determine optional document column, if existent): 2.24 + while (lua_toboolean(L, 4)) { // class on stack position 4 (due to insert) 2.25 + lua_getfield(L, 4, "object"); // 5 2.26 + lua_pushvalue(L, 2); // 6 2.27 + lua_gettable(L, 5); // 6 2.28 + if (!lua_isnil(L, 6)) return 1; 2.29 + lua_settop(L, 4); 2.30 + lua_getfield(L, 4, "object_get"); // 5 2.31 + lua_pushvalue(L, 2); // 6 2.32 + lua_gettable(L, 5); // 6 2.33 + if (lua_toboolean(L, 6)) { 2.34 + lua_pushvalue(L, 1); // 7 2.35 + lua_call(L, 1, 1); // 6 2.36 return 1; 2.37 } 2.38 - lua_settop(L, 3); 2.39 - lua_pushliteral(L, "prototype"); // 4 2.40 - lua_rawget(L, 3); // 4 2.41 - lua_replace(L, 3); 2.42 + lua_settop(L, 4); 2.43 + if (lua_isnil(L, 3)) { 2.44 + lua_getfield(L, 4, "document_column"); // 5 2.45 + lua_replace(L, 3); 2.46 + } 2.47 + lua_pushliteral(L, "prototype"); // 5 2.48 + lua_rawget(L, 4); // 5 2.49 + lua_replace(L, 4); 2.50 } 2.51 - lua_settop(L, 2); 2.52 + lua_settop(L, 3); 2.53 // try primary keys of referenced objects: 2.54 lua_pushcfunction(L, 2.55 mondelefant_class_get_foreign_key_reference_name 2.56 - ); // 3 2.57 - lua_getfield(L, 1, "_class"); // 4 2.58 - lua_pushvalue(L, 2); // 5 2.59 - lua_call(L, 2, 1); // 3 2.60 - if (!lua_isnil(L, 3)) { 2.61 - // reference name at stack position 3 2.62 - lua_pushcfunction(L, mondelefant_class_get_reference); // 4 2.63 - lua_getfield(L, 1, "_class"); // 5 2.64 - lua_pushvalue(L, 3); // 6 2.65 - lua_call(L, 2, 1); // reference info at stack position 4 2.66 - lua_getfield(L, 1, "_ref"); // 5 2.67 - lua_getfield(L, 4, "ref"); // 6 2.68 - lua_gettable(L, 5); // 6 2.69 - if (!lua_isnil(L, 6)) { 2.70 - if (lua_toboolean(L, 6)) { 2.71 - lua_getfield(L, 4, "that_key"); // 7 2.72 - if (lua_isnil(L, 7)) { 2.73 + ); // 4 2.74 + lua_getfield(L, 1, "_class"); // 5 2.75 + lua_pushvalue(L, 2); // 6 2.76 + lua_call(L, 2, 1); // 4 2.77 + if (!lua_isnil(L, 4)) { 2.78 + // reference name at stack position 4 2.79 + lua_pushcfunction(L, mondelefant_class_get_reference); // 5 2.80 + lua_getfield(L, 1, "_class"); // 6 2.81 + lua_pushvalue(L, 4); // 7 2.82 + lua_call(L, 2, 1); // reference info at stack position 5 2.83 + lua_getfield(L, 1, "_ref"); // 6 2.84 + lua_getfield(L, 4, "ref"); // 7 2.85 + lua_gettable(L, 6); // 7 2.86 + if (!lua_isnil(L, 7)) { 2.87 + if (lua_toboolean(L, 7)) { 2.88 + lua_getfield(L, 5, "that_key"); // 8 2.89 + if (lua_isnil(L, 8)) { 2.90 return luaL_error(L, "Missing 'that_key' entry in model reference."); 2.91 } 2.92 - lua_gettable(L, 6); // 7 2.93 + lua_gettable(L, 7); // 8 2.94 } else { 2.95 lua_pushnil(L); 2.96 } 2.97 return 1; 2.98 } 2.99 } 2.100 - lua_settop(L, 2); 2.101 + lua_settop(L, 3); 2.102 // try normal data field info: 2.103 - lua_getfield(L, 1, "_data"); // 3 2.104 - lua_pushvalue(L, 2); // 4 2.105 - lua_gettable(L, 3); // 4 2.106 - if (!lua_isnil(L, 4)) return 1; 2.107 - lua_settop(L, 2); 2.108 + lua_getfield(L, 1, "_data"); // 4 2.109 + lua_pushvalue(L, 2); // 5 2.110 + lua_gettable(L, 4); // 5 2.111 + if (!lua_isnil(L, 5)) return 1; 2.112 + lua_settop(L, 3); // TODO: keep _data table on stack 2.113 // try cached referenced object (or cached NULL reference): 2.114 - lua_getfield(L, 1, "_ref"); // 3 2.115 - lua_pushvalue(L, 2); // 4 2.116 - lua_gettable(L, 3); // 4 2.117 - if (lua_isboolean(L, 4) && !lua_toboolean(L, 4)) { 2.118 + lua_getfield(L, 1, "_ref"); // 4 2.119 + lua_pushvalue(L, 2); // 5 2.120 + lua_gettable(L, 4); // 5 2.121 + if (lua_isboolean(L, 5) && !lua_toboolean(L, 5)) { 2.122 lua_pushnil(L); 2.123 return 1; 2.124 - } else if (!lua_isnil(L, 4)) { 2.125 + } else if (!lua_isnil(L, 5)) { 2.126 return 1; 2.127 } 2.128 - lua_settop(L, 2); 2.129 + lua_settop(L, 3); 2.130 // try to load a referenced object: 2.131 - lua_pushcfunction(L, mondelefant_class_get_reference); // 3 2.132 - lua_getfield(L, 1, "_class"); // 4 2.133 - lua_pushvalue(L, 2); // 5 2.134 - lua_call(L, 2, 1); // 3 2.135 - if (!lua_isnil(L, 3)) { 2.136 + lua_pushcfunction(L, mondelefant_class_get_reference); // 4 2.137 + lua_getfield(L, 1, "_class"); // 5 2.138 + lua_pushvalue(L, 2); // 6 2.139 + lua_call(L, 2, 1); // 4 2.140 + if (!lua_isnil(L, 4)) { 2.141 lua_settop(L, 2); 2.142 lua_getfield(L, 1, "load"); // 3 2.143 lua_pushvalue(L, 1); // 4 (self) 2.144 @@ -1576,6 +1583,18 @@ 2.145 if (lua_isboolean(L, 4) && !lua_toboolean(L, 4)) lua_pushnil(L); // TODO: use special object instead of false 2.146 return 1; 2.147 } 2.148 + lua_settop(L, 3); 2.149 + // try proxy access to document in special column: 2.150 + if (lua_toboolean(L, 3)) { 2.151 + lua_getfield(L, 1, "_data"); // 4 TODO: keep on stack from earlier 2.152 + lua_insert(L, 3); // column name to stack position 4 2.153 + lua_gettable(L, 3); // 4 2.154 + if (!lua_isnil(L, 4)) { 2.155 + lua_pushvalue(L, 2); // 5 2.156 + lua_gettable(L, 4); // 5 2.157 + if (!lua_isnil(L, 5)) return 1; 2.158 + } 2.159 + } 2.160 return 0; 2.161 } else if (result_type && !strcmp(result_type, "list")) { // list 2.162 lua_settop(L, 3);