1010#include " flex-lua-table.hpp"
1111
1212#include " expire-output.hpp"
13+ #include " flex-lua-expire-output.hpp"
1314#include " flex-lua-index.hpp"
1415#include " flex-table.hpp"
1516#include " lua-utils.hpp"
@@ -166,35 +167,46 @@ static void setup_flex_table_id_columns(lua_State *lua_state,
166167 lua_pop (lua_state, 1 ); // "ids"
167168}
168169
169- static std::size_t
170- find_expire_output (std::vector<expire_output_t > const &expire_outputs,
171- std::string_view name)
170+ static std::size_t idx_from_userdata (lua_State *lua_state, int idx,
171+ std::size_t expire_outputs_size)
172172{
173- std::size_t n = 0 ;
174- for (auto const &eo : expire_outputs) {
175- if (eo.name () == name) {
176- return n;
177- }
178- ++n;
173+ void const *const user_data = lua_touserdata (lua_state, idx);
174+
175+ if (user_data == nullptr || !lua_getmetatable (lua_state, idx)) {
176+ throw std::runtime_error{" Expire output must be of type ExpireOutput." };
177+ }
178+
179+ luaL_getmetatable (lua_state, osm2pgsql_expire_output_name);
180+ if (!lua_rawequal (lua_state, -1 , -2 )) {
181+ throw std::runtime_error{" Expire output must be of type ExpireOutput." };
179182 }
183+ lua_pop (lua_state, 2 ); // remove the two metatables
180184
181- throw fmt_error (" Unknown ExpireOutput '{}'." , name);
185+ auto const eo = *static_cast <std::size_t const *>(user_data);
186+ if (eo >= expire_outputs_size) {
187+ throw std::runtime_error{" Internal error in expire output code." };
188+ }
189+ return eo;
182190}
183191
184- static void
185- parse_and_set_expire_options (lua_State *lua_state, flex_table_column_t *column,
186- std::vector< expire_output_t > *expire_outputs ,
187- bool append_mode)
192+ static void parse_and_set_expire_options (lua_State *lua_state,
193+ flex_table_column_t *column,
194+ std::size_t expire_outputs_size ,
195+ bool append_mode)
188196{
189197 auto const type = lua_type (lua_state, -1 );
190198
191199 if (type == LUA_TNIL) {
192200 return ;
193201 }
194202
195- if (type == LUA_TSTRING) {
196- auto eo =
197- find_expire_output (*expire_outputs, lua_tostring (lua_state, -1 ));
203+ if (!column->is_geometry_column () || column->srid () != 3857 ) {
204+ throw std::runtime_error{" Expire only allowed for geometry"
205+ " columns in Web Mercator projection." };
206+ }
207+
208+ if (type == LUA_TUSERDATA) {
209+ auto const eo = idx_from_userdata (lua_state, -1 , expire_outputs_size);
198210 expire_config_t config{eo};
199211 // Actually add the expire only if we are in append mode.
200212 if (append_mode) {
@@ -215,19 +227,13 @@ parse_and_set_expire_options(lua_State *lua_state, flex_table_column_t *column,
215227 throw std::runtime_error{" Expire field must be a Lua array table" };
216228 }
217229
218- if (!column->is_geometry_column () || column->srid () != 3857 ) {
219- throw std::runtime_error{" Expire only allowed for geometry"
220- " columns in Web Mercator projection." };
221- }
222-
223230 luaX_for_each (lua_state, [&]() {
224231 if (!lua_istable (lua_state, -1 ) || luaX_is_array (lua_state)) {
225232 throw std::runtime_error{" Expire config must be a Lua table" };
226233 }
227234
228- auto const *name =
229- luaX_get_table_string (lua_state, " output" , -1 , " Entry 'output'" );
230- auto eo = find_expire_output (*expire_outputs, name);
235+ lua_getfield (lua_state, -1 , " output" );
236+ auto const eo = idx_from_userdata (lua_state, -1 , expire_outputs_size);
231237 lua_pop (lua_state, 1 ); // "output"
232238
233239 expire_config_t config{eo};
@@ -337,7 +343,7 @@ setup_flex_table_columns(lua_State *lua_state, flex_table_t *table,
337343 lua_pop (lua_state, 1 ); // "projection"
338344
339345 lua_getfield (lua_state, -1 , " expire" );
340- parse_and_set_expire_options (lua_state, &column, expire_outputs,
346+ parse_and_set_expire_options (lua_state, &column, expire_outputs-> size () ,
341347 append_mode);
342348 lua_pop (lua_state, 1 ); // "expire"
343349
0 commit comments