Coverage Report

Created: 2022-08-24 06:40

/src/duckdb/src/parser/parser.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "duckdb/parser/parser.hpp"
2
3
#include "duckdb/parser/transformer.hpp"
4
#include "duckdb/parser/parsed_data/create_table_info.hpp"
5
#include "duckdb/parser/statement/create_statement.hpp"
6
#include "duckdb/parser/statement/extension_statement.hpp"
7
#include "duckdb/parser/statement/select_statement.hpp"
8
#include "duckdb/parser/statement/update_statement.hpp"
9
#include "duckdb/parser/query_node/select_node.hpp"
10
#include "duckdb/parser/tableref/expressionlistref.hpp"
11
#include "postgres_parser.hpp"
12
#include "duckdb/parser/query_error_context.hpp"
13
#include "duckdb/parser/parser_extension.hpp"
14
15
#include "parser/parser.hpp"
16
17
namespace duckdb {
18
19
180
Parser::Parser(ParserOptions options_p) : options(options_p) {
20
180
}
21
22
180
void Parser::ParseQuery(const string &query) {
23
180
  Transformer transformer(options.max_expression_depth);
24
180
  {
25
180
    PostgresParser::SetPreserveIdentifierCase(options.preserve_identifier_case);
26
180
    PostgresParser parser;
27
180
    parser.Parse(query);
28
29
180
    if (!parser.success) {
30
4
      if (options.extensions) {
31
4
        for (auto &ext : *options.extensions) {
32
0
          D_ASSERT(ext.parse_function);
33
0
          auto result = ext.parse_function(ext.parser_info.get(), query);
34
0
          if (result.type == ParserExtensionResultType::PARSE_SUCCESSFUL) {
35
0
            auto statement = make_unique<ExtensionStatement>(ext, move(result.parse_data));
36
0
            statement->stmt_length = query.size();
37
0
            statement->stmt_location = 0;
38
0
            statements.push_back(move(statement));
39
0
            return;
40
0
          }
41
0
          if (result.type == ParserExtensionResultType::DISPLAY_EXTENSION_ERROR) {
42
0
            throw ParserException(result.error);
43
0
          }
44
0
        }
45
4
      }
46
4
      throw ParserException(QueryErrorContext::Format(query, parser.error_message, parser.error_location - 1));
47
4
    }
48
49
176
    if (!parser.parse_tree) {
50
      // empty statement
51
0
      return;
52
0
    }
53
54
    // if it succeeded, we transform the Postgres parse tree into a list of
55
    // SQLStatements
56
176
    transformer.TransformParseTree(parser.parse_tree, statements);
57
176
  }
58
176
  if (!statements.empty()) {
59
174
    auto &last_statement = statements.back();
60
174
    last_statement->stmt_length = query.size() - last_statement->stmt_location;
61
174
    for (auto &statement : statements) {
62
174
      statement->query = query;
63
174
      if (statement->type == StatementType::CREATE_STATEMENT) {
64
0
        auto &create = (CreateStatement &)*statement;
65
0
        create.info->sql = query.substr(statement->stmt_location, statement->stmt_length);
66
0
      }
67
174
    }
68
174
  }
69
176
}
70
71
0
vector<SimplifiedToken> Parser::Tokenize(const string &query) {
72
0
  auto pg_tokens = PostgresParser::Tokenize(query);
73
0
  vector<SimplifiedToken> result;
74
0
  result.reserve(pg_tokens.size());
75
0
  for (auto &pg_token : pg_tokens) {
76
0
    SimplifiedToken token;
77
0
    switch (pg_token.type) {
78
0
    case duckdb_libpgquery::PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_IDENTIFIER:
79
0
      token.type = SimplifiedTokenType::SIMPLIFIED_TOKEN_IDENTIFIER;
80
0
      break;
81
0
    case duckdb_libpgquery::PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_NUMERIC_CONSTANT:
82
0
      token.type = SimplifiedTokenType::SIMPLIFIED_TOKEN_NUMERIC_CONSTANT;
83
0
      break;
84
0
    case duckdb_libpgquery::PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_STRING_CONSTANT:
85
0
      token.type = SimplifiedTokenType::SIMPLIFIED_TOKEN_STRING_CONSTANT;
86
0
      break;
87
0
    case duckdb_libpgquery::PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_OPERATOR:
88
0
      token.type = SimplifiedTokenType::SIMPLIFIED_TOKEN_OPERATOR;
89
0
      break;
90
0
    case duckdb_libpgquery::PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_KEYWORD:
91
0
      token.type = SimplifiedTokenType::SIMPLIFIED_TOKEN_KEYWORD;
92
0
      break;
93
    // comments are not supported by our tokenizer right now
94
0
    case duckdb_libpgquery::PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_COMMENT: // LCOV_EXCL_START
95
0
      token.type = SimplifiedTokenType::SIMPLIFIED_TOKEN_COMMENT;
96
0
      break;
97
0
    default:
98
0
      throw InternalException("Unrecognized token category");
99
0
    } // LCOV_EXCL_STOP
100
0
    token.start = pg_token.start;
101
0
    result.push_back(token);
102
0
  }
103
0
  return result;
104
0
}
105
106
0
bool Parser::IsKeyword(const string &text) {
107
0
  return PostgresParser::IsKeyword(text);
108
0
}
109
110
0
vector<ParserKeyword> Parser::KeywordList() {
111
0
  auto keywords = PostgresParser::KeywordList();
112
0
  vector<ParserKeyword> result;
113
0
  for (auto &kw : keywords) {
114
0
    ParserKeyword res;
115
0
    res.name = kw.text;
116
0
    switch (kw.category) {
117
0
    case duckdb_libpgquery::PGKeywordCategory::PG_KEYWORD_RESERVED:
118
0
      res.category = KeywordCategory::KEYWORD_RESERVED;
119
0
      break;
120
0
    case duckdb_libpgquery::PGKeywordCategory::PG_KEYWORD_UNRESERVED:
121
0
      res.category = KeywordCategory::KEYWORD_UNRESERVED;
122
0
      break;
123
0
    case duckdb_libpgquery::PGKeywordCategory::PG_KEYWORD_TYPE_FUNC:
124
0
      res.category = KeywordCategory::KEYWORD_TYPE_FUNC;
125
0
      break;
126
0
    case duckdb_libpgquery::PGKeywordCategory::PG_KEYWORD_COL_NAME:
127
0
      res.category = KeywordCategory::KEYWORD_COL_NAME;
128
0
      break;
129
0
    default:
130
0
      throw InternalException("Unrecognized keyword category");
131
0
    }
132
0
    result.push_back(res);
133
0
  }
134
0
  return result;
135
0
}
136
137
4
vector<unique_ptr<ParsedExpression>> Parser::ParseExpressionList(const string &select_list, ParserOptions options) {
138
  // construct a mock query prefixed with SELECT
139
4
  string mock_query = "SELECT " + select_list;
140
  // parse the query
141
4
  Parser parser(options);
142
4
  parser.ParseQuery(mock_query);
143
  // check the statements
144
4
  if (parser.statements.size() != 1 || parser.statements[0]->type != StatementType::SELECT_STATEMENT) {
145
0
    throw ParserException("Expected a single SELECT statement");
146
0
  }
147
4
  auto &select = (SelectStatement &)*parser.statements[0];
148
4
  if (select.node->type != QueryNodeType::SELECT_NODE) {
149
0
    throw ParserException("Expected a single SELECT node");
150
0
  }
151
4
  auto &select_node = (SelectNode &)*select.node;
152
4
  return move(select_node.select_list);
153
4
}
154
155
0
vector<OrderByNode> Parser::ParseOrderList(const string &select_list, ParserOptions options) {
156
  // construct a mock query
157
0
  string mock_query = "SELECT * FROM tbl ORDER BY " + select_list;
158
  // parse the query
159
0
  Parser parser(options);
160
0
  parser.ParseQuery(mock_query);
161
  // check the statements
162
0
  if (parser.statements.size() != 1 || parser.statements[0]->type != StatementType::SELECT_STATEMENT) {
163
0
    throw ParserException("Expected a single SELECT statement");
164
0
  }
165
0
  auto &select = (SelectStatement &)*parser.statements[0];
166
0
  if (select.node->type != QueryNodeType::SELECT_NODE) {
167
0
    throw InternalException("Expected a single SELECT node");
168
0
  }
169
0
  auto &select_node = (SelectNode &)*select.node;
170
0
  if (select_node.modifiers.empty() || select_node.modifiers[0]->type != ResultModifierType::ORDER_MODIFIER ||
171
0
      select_node.modifiers.size() != 1) {
172
0
    throw InternalException("Expected a single ORDER clause");
173
0
  }
174
0
  auto &order = (OrderModifier &)*select_node.modifiers[0];
175
0
  return move(order.orders);
176
0
}
177
178
void Parser::ParseUpdateList(const string &update_list, vector<string> &update_columns,
179
0
                             vector<unique_ptr<ParsedExpression>> &expressions, ParserOptions options) {
180
  // construct a mock query
181
0
  string mock_query = "UPDATE tbl SET " + update_list;
182
  // parse the query
183
0
  Parser parser(options);
184
0
  parser.ParseQuery(mock_query);
185
  // check the statements
186
0
  if (parser.statements.size() != 1 || parser.statements[0]->type != StatementType::UPDATE_STATEMENT) {
187
0
    throw ParserException("Expected a single UPDATE statement");
188
0
  }
189
0
  auto &update = (UpdateStatement &)*parser.statements[0];
190
0
  update_columns = move(update.columns);
191
0
  expressions = move(update.expressions);
192
0
}
193
194
0
vector<vector<unique_ptr<ParsedExpression>>> Parser::ParseValuesList(const string &value_list, ParserOptions options) {
195
  // construct a mock query
196
0
  string mock_query = "VALUES " + value_list;
197
  // parse the query
198
0
  Parser parser(options);
199
0
  parser.ParseQuery(mock_query);
200
  // check the statements
201
0
  if (parser.statements.size() != 1 || parser.statements[0]->type != StatementType::SELECT_STATEMENT) {
202
0
    throw ParserException("Expected a single SELECT statement");
203
0
  }
204
0
  auto &select = (SelectStatement &)*parser.statements[0];
205
0
  if (select.node->type != QueryNodeType::SELECT_NODE) {
206
0
    throw ParserException("Expected a single SELECT node");
207
0
  }
208
0
  auto &select_node = (SelectNode &)*select.node;
209
0
  if (!select_node.from_table || select_node.from_table->type != TableReferenceType::EXPRESSION_LIST) {
210
0
    throw InternalException("Expected a single VALUES statement");
211
0
  }
212
0
  auto &values_list = (ExpressionListRef &)*select_node.from_table;
213
0
  return move(values_list.values);
214
0
}
215
216
0
vector<ColumnDefinition> Parser::ParseColumnList(const string &column_list, ParserOptions options) {
217
0
  string mock_query = "CREATE TABLE blabla (" + column_list + ")";
218
0
  Parser parser(options);
219
0
  parser.ParseQuery(mock_query);
220
0
  if (parser.statements.size() != 1 || parser.statements[0]->type != StatementType::CREATE_STATEMENT) {
221
0
    throw ParserException("Expected a single CREATE statement");
222
0
  }
223
0
  auto &create = (CreateStatement &)*parser.statements[0];
224
0
  if (create.info->type != CatalogType::TABLE_ENTRY) {
225
0
    throw InternalException("Expected a single CREATE TABLE statement");
226
0
  }
227
0
  auto &info = ((CreateTableInfo &)*create.info);
228
0
  return move(info.columns);
229
0
}
230
231
} // namespace duckdb