YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/yql/cql/ql/ptree/process_context.cc
Line
Count
Source (jump to first uncovered line)
1
//--------------------------------------------------------------------------------------------------
2
// Copyright (c) YugaByte, Inc.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
// in compliance with the License.  You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software distributed under the License
10
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
// or implied.  See the License for the specific language governing permissions and limitations
12
// under the License.
13
//
14
//--------------------------------------------------------------------------------------------------
15
16
#include "yb/yql/cql/ql/ptree/process_context.h"
17
18
#include "yb/util/logging.h"
19
20
#include "yb/yql/cql/ql/ptree/parse_tree.h"
21
#include "yb/yql/cql/ql/ptree/yb_location.h"
22
#include "yb/yql/cql/ql/util/errcodes.h"
23
24
namespace yb {
25
namespace ql {
26
27
using std::endl;
28
using std::istream;
29
using std::min;
30
using std::string;
31
32
//--------------------------------------------------------------------------------------------------
33
// ProcessContextBase
34
//--------------------------------------------------------------------------------------------------
35
36
5.76M
ProcessContextBase::ProcessContextBase() : error_code_(ErrorCode::SUCCESS) {
37
5.76M
}
38
39
5.77M
ProcessContextBase::~ProcessContextBase() {
40
5.77M
}
41
42
//--------------------------------------------------------------------------------------------------
43
44
10.1k
MCString* ProcessContextBase::error_msgs() {
45
10.1k
  if (error_msgs_ == nullptr) {
46
8.47k
    error_msgs_.reset(new MCString(PTempMem()));
47
8.47k
  }
48
10.1k
  return error_msgs_.get();
49
10.1k
}
50
51
337k
Status ProcessContextBase::GetStatus() {
52
  // Erroneous index is negative while successful index is non-negative.
53
337k
  if (error_code_ < ErrorCode::SUCCESS) {
54
1.13k
    return STATUS(QLError, error_msgs()->c_str(), Slice(), QLError(error_code_));
55
1.13k
  }
56
335k
  return Status::OK();
57
335k
}
58
59
//--------------------------------------------------------------------------------------------------
60
61
0
void ProcessContextBase::Warn(const YBLocation& loc, const string& msg, ErrorCode error_code) {
62
0
  error_code_ = error_code;
63
0
  LOG(WARNING) << kErrorFontStart << "SQL Warning (" << loc << "): " << msg << kErrorFontEnd
64
0
               << endl;
65
0
}
66
67
//--------------------------------------------------------------------------------------------------
68
69
Status ProcessContextBase::Error(const YBLocation& loc,
70
                                 const char *m,
71
                                 ErrorCode error_code,
72
8.96k
                                 const char* token) {
73
8.96k
  error_code_ = error_code;
74
75
  // Form an error message.
76
8.96k
  MCString msg(PTempMem());
77
78
  // Concatenate error code.
79
8.96k
  msg += ErrorText(error_code);
80
81
8.96k
  if (strcmp(m, "") != 0) {
82
5.99k
    msg += ". ";
83
    // Concatenate error message.
84
5.99k
    msg += m;
85
5.99k
  }
86
87
  // Concantenate token.
88
8.96k
  msg += "\n";
89
8.96k
  if (token == nullptr) {
90
    // Try to mark the error token from the input statement in the error message.
91
    // This may not be possible if:
92
    //   1. Bison reports a wrong/invalid error location (e.g. ENG-2052).
93
    //   2. Theoretically, if input statement is empty.
94
8.96k
    bool wrote_token = false;
95
8.96k
    if (!stmt().empty()) {
96
      // Bison-reported line/column numbers start from 1, we use 0-based numbering here.
97
8.96k
      const int err_begin_line = loc.BeginLine() - 1;
98
8.96k
      const int err_begin_column = loc.BeginColumn() - 1;
99
8.96k
      const int err_end_line = loc.EndLine() - 1;
100
8.96k
      const int err_end_column = loc.EndColumn() - 1;
101
102
      // Error location values should have sane lower bound.
103
      // The reported values may exceed upper bound (ENG-2052) so we handle that in code below.
104
8.96k
      DCHECK_GE(err_begin_line, 0);
105
8.96k
      DCHECK_GE(err_begin_column, 0);
106
8.96k
      DCHECK_GE(err_end_line, 0);
107
8.96k
      DCHECK_GE(err_end_column, 0);
108
109
8.96k
      int curr_line = 0;
110
8.96k
      int curr_col = 0;
111
8.96k
      const char *stmt_begin = stmt().c_str();
112
8.96k
      const char *stmt_end = stmt_begin + stmt().length();
113
8.96k
      const char *curr_char = stmt_begin;
114
115
489k
      while (curr_char <= stmt_end) {
116
480k
        if (curr_char == stmt_end || *curr_char == '\n') { // End of stmt/line char.
117
8.97k
          msg += '\n';
118
119
          // If in error-token range, try writing line marking error location with '^'.
120
8.97k
          if (curr_line >= err_begin_line && curr_line <= err_end_line) {
121
8.97k
            const char *line_start = curr_char - curr_col; // Inclusive, first char of line.
122
8.97k
            const char *line_end = curr_char - 1; // Inclusive, last char of line.
123
124
            // Line start and end should be within statement bounds.
125
8.97k
            DCHECK_GE(line_start, stmt_begin);
126
8.97k
            DCHECK_LT(line_start, stmt_end);
127
8.97k
            DCHECK_GE(line_end, stmt_begin);
128
8.97k
            DCHECK_LT(line_end, stmt_end);
129
130
            // Finding error-token start, left-trim spaces if this is first line of the error token.
131
8.97k
            const char *error_start = line_start; // Inclusive, first char of error token.
132
8.97k
            if (curr_line == err_begin_line) {
133
8.97k
              error_start += err_begin_column;
134
8.97k
            }
135
8.97k
            if (!wrote_token) {
136
14.2k
              while (error_start <= line_end && isspace(*error_start)) {
137
5.32k
                error_start++;
138
5.32k
              }
139
8.97k
            }
140
141
            // Finding error-token end, right-trim spaces if this is last line of the error token.
142
8.97k
            const char *error_end = line_end; // Inclusive, last char of error token.
143
8.97k
            if (curr_line == err_end_line) {
144
              // The end-column location reported by Bison is generally exclusive (i.e. character
145
              // after the error token) so by default we subtract one from reported value.
146
              // ENG-2052: End-column value may be wrong/out-of-bounds so we cap value to line end.
147
8.96k
              error_end = std::min(line_start + err_end_column - 1, line_end);
148
149
9.04k
              while (error_end >= error_start && isspace(*error_end)) {
150
79
                error_end--;
151
79
              }
152
8.96k
            }
153
154
            // If we found a valid token range write a marker line.
155
8.97k
            if (error_end >= error_start) {
156
8.95k
              msg.append(error_start - line_start, ' ');
157
8.95k
              msg.append(error_end - error_start + 1, '^'); // +1 since both limits are inclusive.
158
8.95k
              msg += '\n';
159
8.95k
              wrote_token = true;
160
8.95k
            }
161
8.97k
          }
162
163
8.97k
          curr_line++;
164
8.97k
          curr_col = 0;
165
471k
        } else {
166
471k
          msg += *curr_char;
167
471k
          curr_col++;
168
471k
        }
169
480k
        curr_char++;
170
480k
      }
171
8.96k
    }
172
173
    // If we couldn't mark the error token in the stmt we append the reported location directly.
174
8.96k
    if (!wrote_token) {
175
15
      msg += "At location: (";
176
15
      loc.ToString<MCString>(&msg, false /* starting_location_only */);
177
15
      msg += ")\n";
178
15
    }
179
0
  } else {
180
0
    msg += token;
181
0
  }
182
183
  // Append this error message to the context.
184
8.96k
  error_msgs()->append(msg);
185
8.96k
  YB_LOG_EVERY_N_SECS(WARNING, 1) << "SQL Error: " << msg;
186
8.96k
  return STATUS(QLError, msg.c_str(), Slice(), QLError(error_code_));
187
8.96k
}
188
189
Status ProcessContextBase::Error(const YBLocation& loc,
190
                                 const std::string& msg,
191
                                 ErrorCode error_code,
192
1
                                 const char* token) {
193
1
  return Error(loc, msg.c_str(), error_code, token);
194
1
}
195
196
0
Status ProcessContextBase::Error(const YBLocation& loc, const std::string& msg, const char* token) {
197
0
  return Error(loc, msg, ErrorCode::SQL_STATEMENT_INVALID, token);
198
0
}
199
200
86
Status ProcessContextBase::Error(const YBLocation& loc, const char *msg, const char* token) {
201
86
  return Error(loc, msg, ErrorCode::SQL_STATEMENT_INVALID, token);
202
86
}
203
204
Status ProcessContextBase::Error(const YBLocation& loc,
205
                                 ErrorCode error_code,
206
2.97k
                                 const char* token) {
207
2.97k
  return Error(loc, "", error_code, token);
208
2.97k
}
209
210
Status ProcessContextBase::Error(const TreeNode *tnode,
211
                                 const std::string& msg,
212
2.09k
                                 ErrorCode error_code) {
213
2.09k
  return Error(tnode->loc(), msg.c_str(), error_code);
214
2.09k
}
215
216
Status ProcessContextBase::Error(const TreeNode *tnode,
217
                                 const char *msg,
218
2.84k
                                 ErrorCode error_code) {
219
2.84k
  return Error(tnode->loc(), msg, error_code);
220
2.84k
}
221
222
Status ProcessContextBase::Error(const TreeNode *tnode,
223
247
                                 ErrorCode error_code) {
224
247
  return Error(tnode->loc(), error_code);
225
247
}
226
227
Status ProcessContextBase::Error(const TreeNode *tnode,
228
                                 const Status& s,
229
596
                                 ErrorCode error_code) {
230
596
  return Error(tnode->loc(), s.ToUserMessage().c_str(), error_code);
231
596
}
232
233
Status ProcessContextBase::Error(const TreeNode::SharedPtr& tnode,
234
444
                                 ErrorCode error_code) {
235
444
  return Error(tnode->loc(), error_code);
236
444
}
237
238
Status ProcessContextBase::Error(const TreeNode::SharedPtr& tnode,
239
                                 const std::string& msg,
240
3
                                 ErrorCode error_code) {
241
3
  return Error(tnode->loc(), msg.c_str(), error_code);
242
3
}
243
244
Status ProcessContextBase::Error(const TreeNode::SharedPtr& tnode,
245
                                 const char *msg,
246
16
                                 ErrorCode error_code) {
247
16
  return Error(tnode->loc(), msg, error_code);
248
16
}
249
250
Status ProcessContextBase::Error(const TreeNode::SharedPtr& tnode,
251
                                 const Status& s,
252
63
                                 ErrorCode error_code) {
253
63
  return Error(tnode->loc(), s.ToUserMessage().c_str(), error_code);
254
63
}
255
256
//--------------------------------------------------------------------------------------------------
257
258
//--------------------------------------------------------------------------------------------------
259
// ProcessContext
260
//--------------------------------------------------------------------------------------------------
261
262
ProcessContext::ProcessContext(ParseTree::UniPtr parse_tree)
263
665k
    : parse_tree_(std::move(parse_tree)) {
264
665k
}
265
266
669k
ProcessContext::~ProcessContext() {
267
669k
}
268
269
//--------------------------------------------------------------------------------------------------
270
271
333k
void ProcessContext::SaveGeneratedParseTree(TreeNode::SharedPtr generated_parse_tree) {
272
136
  CHECK(parse_tree_.get() != nullptr) << "Context is not associated with a parse tree";
273
333k
  parse_tree_->set_root(generated_parse_tree);
274
333k
}
275
276
1.01M
const std::string& ProcessContext::stmt() const {
277
1.01M
  return parse_tree_->stmt();
278
1.01M
}
279
280
// Memory pool for constructing the parse tree of a statement.
281
10.8M
MemoryContext *ProcessContext::PTreeMem() const {
282
10.8M
  return parse_tree_->PTreeMem();
283
10.8M
}
284
285
670k
ParseTreePtr ProcessContext::AcquireParseTree() {
286
670k
  return std::move(parse_tree_);
287
670k
}
288
289
}  // namespace ql
290
}  // namespace yb