lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> Am 24.12.2015 um 10:29 schrieb Jonathan Goble <jcgoble3@gmail.com>:
> 
> On Thu, Dec 24, 2015 at 4:15 AM, Marc Balmer <marc@msys.ch> wrote:
>> Is it possible to define a metatable that has a table of functions as the __index element, and then, trigger another metatable when a key is not found up in __index?
> 
> Set a metatable for the table of functions, with __index set to your
> catch-all index function.
> 
> In other words, if __index is a table, and that table doesn't contain
> the key, then Lua will check if that table has a metatable of its own
> with an __index metamethod. This metatable chaining could
> theoretically continue indefinitely.
> 

Actually I found a nice way to achieve what I want.  In the index function I first look for the special values, and if they are not there, I lookup the key in the metatable using rawget.

Works like a charm:

res = db:exec('select 'abc' as name')

print(res:ntuples())   -- outputs '1'
print(res[1].name)  -- outputs 'abc'

Here's the function:

static int
res_index(lua_State *L)
{
	if (lua_type(L, -1) == LUA_TNUMBER) {
		tuple *t;
		PGresult *res;
		int row;

		res = *(PGresult **)luaL_checkudata(L, 1, RES_METATABLE);
		row = luaL_checkinteger(L, 2) - 1;

		if (row < 0 || row > PQntuples(res))
			lua_pushnil(L);
		else {
			t = lua_newuserdata(L, sizeof(tuple));
			t->res = res;
			t->row = row;
			luaL_getmetatable(L, TUPLE_METATABLE);
			lua_setmetatable(L, -2);
		}
	} else {
		const char *nam;

		nam = lua_tostring(L, -1);
		if (lua_getmetatable(L, -2)) {
			lua_pushstring(L, nam);
			lua_rawget(L, -2);
		} else
			lua_pushnil(L);
	}
	return 1;
}