| 1028 | } |
| 1029 | |
| 1030 | static void db_sql_finalize_function(sqlite3_context *context) { |
| 1031 | sdb_func *func = (sdb_func*)sqlite3_user_data(context); |
| 1032 | lua_State *L = func->db->L; |
| 1033 | void *p = sqlite3_aggregate_context(context, 1); /* minimal mem usage */ |
| 1034 | lcontext *ctx; |
| 1035 | int top = lua_gettop(L); |
| 1036 | |
| 1037 | lua_rawgeti(L, LUA_REGISTRYINDEX, func->fn_finalize); /* function to call */ |
| 1038 | |
| 1039 | /* i think it is OK to use assume that using a light user data |
| 1040 | ** as an entry on LUA REGISTRY table will be unique */ |
| 1041 | lua_pushlightuserdata(L, p); |
| 1042 | lua_rawget(L, LUA_REGISTRYINDEX); /* context table */ |
| 1043 | |
| 1044 | if (lua_isnil(L, -1)) { /* not yet created? - shouldn't happen in finalize function */ |
| 1045 | lua_pop(L, 1); |
| 1046 | ctx = lsqlite_make_context(L); |
| 1047 | lua_pushlightuserdata(L, p); |
| 1048 | lua_pushvalue(L, -2); |
| 1049 | lua_rawset(L, LUA_REGISTRYINDEX); |
| 1050 | } |
| 1051 | else |
| 1052 | ctx = lsqlite_getcontext(L, -1); |
| 1053 | |
| 1054 | /* set context */ |
| 1055 | ctx->ctx = context; |
| 1056 | |
| 1057 | if (lua_pcall(L, 1, 0, 0)) { |
| 1058 | sqlite3_result_error(context, lua_tostring(L, -1), -1); |
| 1059 | } |
| 1060 | |
| 1061 | /* invalidate context */ |
| 1062 | ctx->ctx = NULL; |
| 1063 | |
| 1064 | /* cleanup context */ |
| 1065 | luaL_unref(L, LUA_REGISTRYINDEX, ctx->ud); |
| 1066 | /* remove it from registry */ |
| 1067 | lua_pushlightuserdata(L, p); |
| 1068 | lua_pushnil(L); |
| 1069 | lua_rawset(L, LUA_REGISTRYINDEX); |
| 1070 | |
| 1071 | lua_settop(L, top); |
| 1072 | } |
| 1073 | |
| 1074 | /* |
| 1075 | ** Register a normal function |
nothing calls this directly
no test coverage detected