Skip to content

Commit 9faabc6

Browse files
committed
Move functions to parse Lua index definitions into their own file
1 parent f4e64c8 commit 9faabc6

File tree

4 files changed

+156
-109
lines changed

4 files changed

+156
-109
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ if (WITH_LUA)
5050
flex-table.cpp
5151
flex-table-column.cpp
5252
flex-lua-geom.cpp
53+
flex-lua-index.cpp
5354
geom-transform.cpp
5455
lua-utils.cpp
5556
output-flex.cpp

src/flex-lua-index.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/**
2+
* SPDX-License-Identifier: GPL-2.0-or-later
3+
*
4+
* This file is part of osm2pgsql (https://osm2pgsql.org/).
5+
*
6+
* Copyright (C) 2006-2022 by the osm2pgsql developer community.
7+
* For a full list of authors see the git log.
8+
*/
9+
10+
#include "flex-lua-index.hpp"
11+
#include "lua-utils.hpp"
12+
#include "output-flex.hpp"
13+
#include "pgsql-capabilities.hpp"
14+
#include "util.hpp"
15+
16+
#include <string>
17+
#include <vector>
18+
19+
static void check_and_add_column(flex_table_t const &table,
20+
std::vector<std::string> *columns,
21+
char const *column_name)
22+
{
23+
auto const *column = util::find_by_name(table, column_name);
24+
if (!column) {
25+
throw std::runtime_error{"Unknown column '{}' in table '{}'."_format(
26+
column_name, table.name())};
27+
}
28+
columns->push_back(column_name);
29+
}
30+
31+
static void check_and_add_columns(flex_table_t const &table,
32+
std::vector<std::string> *columns,
33+
lua_State *lua_state)
34+
{
35+
lua_pushnil(lua_state);
36+
while (lua_next(lua_state, -2) != 0) {
37+
if (!lua_isnumber(lua_state, -2)) {
38+
throw std::runtime_error{
39+
"The 'column' field must contain a string or an array."};
40+
}
41+
if (!lua_isstring(lua_state, -1)) {
42+
throw std::runtime_error{
43+
"The entries in the 'column' array must be strings."};
44+
}
45+
check_and_add_column(table, columns, lua_tostring(lua_state, -1));
46+
lua_pop(lua_state, 1); // table
47+
}
48+
}
49+
50+
void flex_lua_setup_index(lua_State *lua_state, flex_table_t *table)
51+
{
52+
char const *const method =
53+
luaX_get_table_string(lua_state, "method", -1, "Index definition");
54+
if (!has_index_method(method)) {
55+
throw std::runtime_error{"Unknown index method '{}'."_format(method)};
56+
}
57+
58+
auto &index = table->add_index(method);
59+
60+
std::vector<std::string> columns;
61+
lua_getfield(lua_state, -2, "column");
62+
if (lua_isstring(lua_state, -1)) {
63+
check_and_add_column(*table, &columns, lua_tostring(lua_state, -1));
64+
index.set_columns(columns);
65+
} else if (lua_istable(lua_state, -1)) {
66+
check_and_add_columns(*table, &columns, lua_state);
67+
if (columns.empty()) {
68+
throw std::runtime_error{
69+
"The 'column' field in an index definition can not be an "
70+
"empty array."};
71+
}
72+
index.set_columns(columns);
73+
} else if (!lua_isnil(lua_state, -1)) {
74+
throw std::runtime_error{
75+
"The 'column' field in an index definition must contain a "
76+
"string or an array."};
77+
}
78+
79+
std::string const expression = luaX_get_table_string(
80+
lua_state, "expression", -3, "Index definition", "");
81+
82+
index.set_expression(expression);
83+
84+
if (expression.empty() == columns.empty()) {
85+
throw std::runtime_error{"You must set either the 'column' or the "
86+
"'expression' field in index definition."};
87+
}
88+
89+
std::vector<std::string> include_columns;
90+
lua_getfield(lua_state, -4, "include");
91+
if (get_database_version() >= 110000) {
92+
if (lua_isstring(lua_state, -1)) {
93+
check_and_add_column(*table, &include_columns,
94+
lua_tostring(lua_state, -1));
95+
} else if (lua_istable(lua_state, -1)) {
96+
check_and_add_columns(*table, &include_columns, lua_state);
97+
} else if (!lua_isnil(lua_state, -1)) {
98+
throw std::runtime_error{
99+
"The 'include' field in an index definition must contain a "
100+
"string or an array."};
101+
}
102+
index.set_include_columns(include_columns);
103+
} else if (!lua_isnil(lua_state, -1)) {
104+
throw std::runtime_error{
105+
"Database version ({}) doesn't support"
106+
" include columns in indexes."_format(get_database_version())};
107+
}
108+
109+
std::string const tablespace = luaX_get_table_string(
110+
lua_state, "tablespace", -5, "Index definition", "");
111+
check_identifier(tablespace, "tablespace");
112+
if (!has_tablespace(tablespace)) {
113+
throw std::runtime_error{"Unknown tablespace '{}'."_format(tablespace)};
114+
}
115+
index.set_tablespace(tablespace.empty() ? table->index_tablespace()
116+
: tablespace);
117+
118+
index.set_is_unique(luaX_get_table_bool(lua_state, "unique", -6,
119+
"Index definition", false));
120+
121+
index.set_where_condition(
122+
luaX_get_table_string(lua_state, "where", -7, "Index definition", ""));
123+
124+
// stack has: "where", "unique", "tablespace", "includes", "expression",
125+
// "column", "method"
126+
lua_pop(lua_state, 7);
127+
}

src/flex-lua-index.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef OSM2PGSQL_FLEX_LUA_INDEX_HPP
2+
#define OSM2PGSQL_FLEX_LUA_INDEX_HPP
3+
4+
/**
5+
* SPDX-License-Identifier: GPL-2.0-or-later
6+
*
7+
* This file is part of osm2pgsql (https://osm2pgsql.org/).
8+
*
9+
* Copyright (C) 2006-2022 by the osm2pgsql developer community.
10+
* For a full list of authors see the git log.
11+
*/
12+
13+
/**
14+
* \file
15+
*
16+
* Functions implementing the Lua interface for index creation.
17+
*/
18+
19+
struct lua_State;
20+
class flex_table_t;
21+
22+
void flex_lua_setup_index(lua_State *lua_state, flex_table_t *table);
23+
24+
#endif // OSM2PGSQL_FLEX_LUA_INDEX_HPP

src/output-flex.cpp

Lines changed: 4 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "expire-tiles.hpp"
1212
#include "flex-index.hpp"
1313
#include "flex-lua-geom.hpp"
14+
#include "flex-lua-index.hpp"
1415
#include "format.hpp"
1516
#include "geom-from-osm.hpp"
1617
#include "geom-functions.hpp"
@@ -1180,37 +1181,6 @@ void output_flex_t::setup_flex_table_columns(flex_table_t *table)
11801181
lua_pop(lua_state(), 1); // "columns"
11811182
}
11821183

1183-
static void check_and_add_column(flex_table_t const &table,
1184-
std::vector<std::string> *columns,
1185-
char const *column_name)
1186-
{
1187-
auto const *column = util::find_by_name(table, column_name);
1188-
if (!column) {
1189-
throw std::runtime_error{"Unknown column '{}' in table '{}'."_format(
1190-
column_name, table.name())};
1191-
}
1192-
columns->push_back(column_name);
1193-
}
1194-
1195-
static void check_and_add_columns(flex_table_t const &table,
1196-
std::vector<std::string> *columns,
1197-
lua_State *lua_state)
1198-
{
1199-
lua_pushnil(lua_state);
1200-
while (lua_next(lua_state, -2) != 0) {
1201-
if (!lua_isnumber(lua_state, -2)) {
1202-
throw std::runtime_error{
1203-
"The 'column' field must contain a string or an array."};
1204-
}
1205-
if (!lua_isstring(lua_state, -1)) {
1206-
throw std::runtime_error{
1207-
"The entries in the 'column' array must be strings."};
1208-
}
1209-
check_and_add_column(table, columns, lua_tostring(lua_state, -1));
1210-
lua_pop(lua_state, 1); // table
1211-
}
1212-
}
1213-
12141184
void output_flex_t::setup_indexes(flex_table_t *table)
12151185
{
12161186
assert(table);
@@ -1245,87 +1215,12 @@ void output_flex_t::setup_indexes(flex_table_t *table)
12451215
}
12461216
if (!lua_istable(lua_state(), -1)) {
12471217
throw std::runtime_error{
1248-
"The entries in the 'indexes' array must be tables."};
1249-
}
1250-
1251-
char const *const method = luaX_get_table_string(
1252-
lua_state(), "method", -1, "Index definition");
1253-
if (!has_index_method(method)) {
1254-
throw std::runtime_error{
1255-
"Unknown index method '{}'."_format(method)};
1256-
}
1257-
1258-
auto &index = table->add_index(method);
1259-
1260-
std::vector<std::string> columns;
1261-
lua_getfield(lua_state(), -2, "column");
1262-
if (lua_isstring(lua_state(), -1)) {
1263-
check_and_add_column(*table, &columns,
1264-
lua_tostring(lua_state(), -1));
1265-
index.set_columns(columns);
1266-
} else if (lua_istable(lua_state(), -1)) {
1267-
check_and_add_columns(*table, &columns, lua_state());
1268-
if (columns.empty()) {
1269-
throw std::runtime_error{
1270-
"The 'column' field in an index definition can not be an "
1271-
"empty array."};
1272-
}
1273-
index.set_columns(columns);
1274-
} else if (!lua_isnil(lua_state(), -1)) {
1275-
throw std::runtime_error{
1276-
"The 'column' field in an index definition must contain a "
1277-
"string or an array."};
1278-
}
1279-
1280-
std::string const expression = luaX_get_table_string(
1281-
lua_state(), "expression", -3, "Index definition", "");
1282-
1283-
index.set_expression(expression);
1284-
1285-
if (expression.empty() == columns.empty()) {
1286-
throw std::runtime_error{"You must set either the 'column' or the "
1287-
"'expression' field in index definition."};
1288-
}
1289-
1290-
std::vector<std::string> include_columns;
1291-
lua_getfield(lua_state(), -4, "include");
1292-
if (get_database_version() >= 110000) {
1293-
if (lua_isstring(lua_state(), -1)) {
1294-
check_and_add_column(*table, &include_columns,
1295-
lua_tostring(lua_state(), -1));
1296-
} else if (lua_istable(lua_state(), -1)) {
1297-
check_and_add_columns(*table, &include_columns, lua_state());
1298-
} else if (!lua_isnil(lua_state(), -1)) {
1299-
throw std::runtime_error{
1300-
"The 'include' field in an index definition must contain a "
1301-
"string or an array."};
1302-
}
1303-
index.set_include_columns(include_columns);
1304-
} else if (!lua_isnil(lua_state(), -1)) {
1305-
throw std::runtime_error{
1306-
"Database version ({}) doesn't support"
1307-
" include columns in indexes."_format(get_database_version())};
1218+
"The entries in the 'indexes' array must be Lua tables."};
13081219
}
13091220

1310-
std::string const tablespace = luaX_get_table_string(
1311-
lua_state(), "tablespace", -5, "Index definition", "");
1312-
check_identifier(tablespace, "tablespace");
1313-
if (!has_tablespace(tablespace)) {
1314-
throw std::runtime_error{
1315-
"Unknown tablespace '{}'."_format(tablespace)};
1316-
}
1317-
index.set_tablespace(tablespace.empty() ? table->index_tablespace()
1318-
: tablespace);
1319-
1320-
index.set_is_unique(luaX_get_table_bool(lua_state(), "unique", -6,
1321-
"Index definition", false));
1221+
flex_lua_setup_index(lua_state(), table);
13221222

1323-
index.set_where_condition(luaX_get_table_string(
1324-
lua_state(), "where", -7, "Index definition", ""));
1325-
1326-
// stack has: "where", "unique", "tablespace", "includes", "expression",
1327-
// "column", "method", table
1328-
lua_pop(lua_state(), 8);
1223+
lua_pop(lua_state(), 1);
13291224
}
13301225

13311226
lua_pop(lua_state(), 1); // "indexes"

0 commit comments

Comments
 (0)