-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathParseLiteralValue.hpp
354 lines (307 loc) · 12.3 KB
/
ParseLiteralValue.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
#ifndef QUICKSTEP_PARSER_PARSE_LITERAL_VALUE_HPP_
#define QUICKSTEP_PARSER_PARSE_LITERAL_VALUE_HPP_
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "parser/ParseString.hpp"
#include "parser/ParseTreeNode.hpp"
#include "types/TypedValue.hpp"
#include "utility/Macros.hpp"
#include "glog/logging.h"
namespace quickstep {
class Type;
/** \addtogroup Parser
* @{
*/
/**
* @brief The parsed representation of a literal data value.
**/
class ParseLiteralValue : public ParseTreeNode {
public:
/**
* @brief Virtual destructor.
**/
~ParseLiteralValue() override {
}
/**
* @brief Obtain this value as a literal TypedValue in the quickstep type
* system.
*
* @param type_hint A hint of what Type is expected. This may be used to give
* NULL values the correct Type, or to disambiguate between types that
* have similar human-readable text formats. type_hint may be NULL, in
* which case the most sensible guess for the value's Type is used
* (for a NULL literal, the special type NullType is used).
* @param concretized_type After the call, *concretized_type will point to
* the actual Type that the returned TypedValue belongs to.
* @return The concrete version of this literal value.
**/
virtual TypedValue concretize(const Type *type_hint,
const Type **concretized_type) const = 0;
/**
* @brief Obtain an exact, deep copy of this ParseLiteralValue.
*
* @return A copy of this ParseLiteralValue.
**/
virtual ParseLiteralValue* clone() const = 0;
/**
* @brief Get a human-readable representation of this value.
*
* @return The human-readable form of this value.
**/
virtual std::string generateName() const = 0;
protected:
/**
* @brief Constructor.
*
* @param line_number Line number of the first token of this node in the SQL statement.
* @param column_number Column number of the first token of this node in the SQL statement.
**/
ParseLiteralValue(const int line_number, const int column_number)
: ParseTreeNode(line_number, column_number) {
}
private:
DISALLOW_COPY_AND_ASSIGN(ParseLiteralValue);
};
/**
* @brief The parsed representation of a NULL literal.
**/
class NullParseLiteralValue: public ParseLiteralValue {
public:
/**
* @brief Constructor.
*
* @param line_number Line number of the first token of this node in the SQL statement.
* @param column_number Column number of the first token of this node in the SQL statement.
**/
NullParseLiteralValue(const int line_number, const int column_number)
: ParseLiteralValue(line_number, column_number) {
}
std::string getName() const override {
return "NullLiteral";
}
TypedValue concretize(const Type *type_hint,
const Type **concretized_type) const override;
ParseLiteralValue* clone() const override {
return new NullParseLiteralValue(line_number(), column_number());
}
std::string generateName() const override {
return "NULL";
}
protected:
void getFieldStringItems(
std::vector<std::string> *inline_field_names,
std::vector<std::string> *inline_field_values,
std::vector<std::string> *non_container_child_field_names,
std::vector<const ParseTreeNode*> *non_container_child_fields,
std::vector<std::string> *container_child_field_names,
std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override {
}
private:
DISALLOW_COPY_AND_ASSIGN(NullParseLiteralValue);
};
/**
* @brief The parsed representation of an unquoted numeric literal.
**/
class NumericParseLiteralValue : public ParseLiteralValue {
public:
/**
* @brief Constructor.
*
* @param line_number Line number of the first token of this node in the SQL statement.
* @param column_number Column number of the first token of this node in the SQL statement.
* @param numstring The C-string form of the numeric value.
**/
NumericParseLiteralValue(const int line_number,
const int column_number,
const char *numstring);
/**
* @brief Destructor.
**/
~NumericParseLiteralValue() override {
}
std::string getName() const override {
return "NumericLiteral";
}
/**
* @brief Prepend a minus sign to this numeric value, negating it.
* @note This exists to work around a quirk in our Bison SQL grammar, since
* a minus sign can be the leading character in a negative number OR
* can represent the unary negation operation applied to a numeric
* value. Our solution is to have the Lexer scan all numeric literals
* as unsigned values, while the parser has a rule that calls this
* method when a minus-sign token occurs in front of a numeric literal.
**/
void prependMinus();
/**
* @brief Determine whether this numeric value looks like a floating-point
* value.
*
* @return True if the value is "float-like", false otherwise.
**/
bool float_like() const {
return float_like_;
}
/**
* @brief Get this numeric value as a long.
*
* @return This numeric value as a long.
**/
std::int64_t long_value() const {
DCHECK(!float_like_)
<< "Attempted to read integer value from float-like "
<< "NumericParseLiteralValue";
return long_value_;
}
/**
* @note This implementation of concretize() always tries to honor the given
* type_hint first. If resolution with the supplied type_hint fails, or
* if no type_hint is given, then the following rules apply:
* 1. If the literal contains a decimal point or exponent, resolve as
* DoubleType (unless FloatType is hinted, we always use
* DoubleType for more precision).
* 2. Otherwise, if the literal is in-range for a 32-bit signed
* integer, resolve as IntType.
* 3. Otherwise, resolve as LongType.
**/
TypedValue concretize(const Type *type_hint,
const Type **concretized_type) const override;
ParseLiteralValue* clone() const override {
return new NumericParseLiteralValue(line_number(),
column_number(),
numeric_string_.c_str());
}
std::string generateName() const override {
return numeric_string_;
}
protected:
void getFieldStringItems(
std::vector<std::string> *inline_field_names,
std::vector<std::string> *inline_field_values,
std::vector<std::string> *non_container_child_field_names,
std::vector<const ParseTreeNode*> *non_container_child_fields,
std::vector<std::string> *container_child_field_names,
std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override;
private:
std::int64_t long_value_;
bool float_like_;
std::string numeric_string_;
DISALLOW_COPY_AND_ASSIGN(NumericParseLiteralValue);
};
/**
* @brief The parsed representation of a quoted string value. This includes
* explicitly typed literals of the form "TYPE 'literal value'".
**/
class StringParseLiteralValue : public ParseLiteralValue {
public:
/**
* @brief Constructor.
*
* @param value The string.
* @param explicit_type If non-NULL, indicates an explicit Type that appeared
* immediately before a quoted string in the SQL syntax. If NULL, then
* value appeared by itself as a quoted string without an explicit
* Type.
**/
explicit StringParseLiteralValue(ParseString *value,
const Type *explicit_type)
: ParseLiteralValue(value->line_number(), value->column_number()),
value_(value),
explicit_type_(explicit_type) {
}
~StringParseLiteralValue() override {
}
/**
* @brief Attempt to parse an interval literal that was specified
* in the form "INTERVAL 'value string'" in SQL syntax.
* @note There are two distinct INTERVAL Types in Quickstep:
* DatetimeInterval ("DATETIME INTERVAL" in SQL) and YearMonthInterval
* ("YEARMONTH INTERVAL" in SQL). The INTERVAL keyword by itself is
* ambiguous and does not name a Type, however the text formats for
* literals of the two different interval Types are distinct and
* non-overlapping, so if a valid interval literal string follows the
* INTERVAL keyword, the Type can be determined unambiguously. This
* method does just that, allowing the SQL parser to be more forgiving
* when interval literals don't specify the flavor of interval
* up-front.
*
* @param value A string literal that followed an INTERVAL keyword in SQL
* syntax. On successful parse, this becomes owned by the parsed
* StringParseLiteralValue. On failure, it is deleted.
* @param output On successful parse, *output is overwritten to point to a
* new heap-allocated StringParseLiteralValue representing the parsed
* interval literal.
* @return true if value was successfully parsed as either of the interval
* types, false otherwise.
**/
static bool ParseAmbiguousInterval(ParseString *value,
StringParseLiteralValue **output);
/**
* @note The rules for what type this literal is resolved as depend on
* whether an explicit_type_ from the SQL context exists, and whether
* a type_hint is provided. Specifically, they are:
* 1. If there is an explicit_type_:
* a. If there is a type_hint and it is safely coercible from
* explicit_type_, do the coercion and resolve as type_hint.
* b. Otherwise resolve as explicit_type_.
* 2. If there is no explicit_type_:
* a. If there is a type_hint and it can successfully parse the
* string value, resolve as the hinted type.
* b. Otherwise, resolve as a non-nullable VarCharType that is
* exactly long enough for this string literal.
**/
TypedValue concretize(const Type *type_hint,
const Type **concretized_type) const override;
std::string getName() const override {
return "StringLiteral";
}
ParseLiteralValue* clone() const override {
return new StringParseLiteralValue(value_->clone(), explicit_type_);
}
std::string generateName() const override;
/**
* @brief Attempt to parse this string literal as an instance of the
* explicit Type provided to the constructor. This should ALWAYS be
* called by the parser immediately after creating a
* StringParseLiteralValue with an explicit Type.
*
* @return true if parse was successful, false if the string was not in a
* valid format for the specified explicit Type.
**/
bool tryExplicitTypeParse();
protected:
void getFieldStringItems(
std::vector<std::string> *inline_field_names,
std::vector<std::string> *inline_field_values,
std::vector<std::string> *non_container_child_field_names,
std::vector<const ParseTreeNode*> *non_container_child_fields,
std::vector<std::string> *container_child_field_names,
std::vector<std::vector<const ParseTreeNode*>> *container_child_fields) const override;
private:
std::unique_ptr<ParseString> value_;
const Type *explicit_type_;
TypedValue explicit_parsed_value_;
DISALLOW_COPY_AND_ASSIGN(StringParseLiteralValue);
};
/** @} */
} // namespace quickstep
#endif // QUICKSTEP_PARSER_PARSE_LITERAL_VALUE_HPP_