YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/yql/cql/ql/ql_processor.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/ql_processor.h"
17
18
#include <memory>
19
20
#include "yb/client/table.h"
21
#include "yb/client/yb_table_name.h"
22
23
#include "yb/common/index.h"
24
25
#include "yb/gutil/bind.h"
26
27
#include "yb/util/metrics.h"
28
#include "yb/util/scope_exit.h"
29
#include "yb/util/status_format.h"
30
#include "yb/util/thread_restrictions.h"
31
32
#include "yb/yql/cql/ql/parser/parser.h"
33
34
DECLARE_bool(use_cassandra_authentication);
35
DECLARE_bool(ycql_require_drop_privs_for_truncate);
36
37
METRIC_DEFINE_histogram_with_percentiles(
38
    server, handler_latency_yb_cqlserver_SQLProcessor_ParseRequest,
39
    "Time spent parsing the SQL query", yb::MetricUnit::kMicroseconds,
40
    "Time spent parsing the SQL query", 60000000LU, 2);
41
METRIC_DEFINE_histogram_with_percentiles(
42
    server, handler_latency_yb_cqlserver_SQLProcessor_AnalyzeRequest,
43
    "Time spent to analyze the parsed SQL query", yb::MetricUnit::kMicroseconds,
44
    "Time spent to analyze the parsed SQL query", 60000000LU, 2);
45
METRIC_DEFINE_histogram_with_percentiles(
46
    server, handler_latency_yb_cqlserver_SQLProcessor_ExecuteRequest,
47
    "Time spent executing the parsed SQL query", yb::MetricUnit::kMicroseconds,
48
    "Time spent executing the parsed SQL query", 60000000LU, 2);
49
METRIC_DEFINE_histogram_with_percentiles(
50
    server, handler_latency_yb_cqlserver_SQLProcessor_NumRoundsToAnalyze,
51
    "Number of rounds to successfully parse a SQL query", yb::MetricUnit::kOperations,
52
    "Number of rounds to successfully parse a SQL query", 60000000LU, 2);
53
METRIC_DEFINE_histogram_with_percentiles(
54
    server, handler_latency_yb_cqlserver_SQLProcessor_NumRetriesToExecute,
55
    "Number of retries to successfully execute a SQL query", yb::MetricUnit::kOperations,
56
    "Number of retries to successfully execute a SQL query", 60000000LU, 2);
57
METRIC_DEFINE_histogram_with_percentiles(
58
    server, handler_latency_yb_cqlserver_SQLProcessor_NumFlushesToExecute,
59
    "Number of flushes to successfully execute a SQL query", yb::MetricUnit::kOperations,
60
    "Number of flushes to successfully execute a SQL query", 60000000LU, 2);
61
METRIC_DEFINE_histogram_with_percentiles(
62
    server, handler_latency_yb_cqlserver_SQLProcessor_SelectStmt,
63
    "Time spent processing a SELECT statement", yb::MetricUnit::kMicroseconds,
64
    "Time spent processing a SELECT statement", 60000000LU, 2);
65
METRIC_DEFINE_histogram_with_percentiles(
66
    server, handler_latency_yb_cqlserver_SQLProcessor_InsertStmt,
67
    "Time spent processing an INSERT statement", yb::MetricUnit::kMicroseconds,
68
    "Time spent processing an INSERT statement", 60000000LU, 2);
69
METRIC_DEFINE_histogram_with_percentiles(
70
    server, handler_latency_yb_cqlserver_SQLProcessor_UpdateStmt,
71
    "Time spent processing an UPDATE statement", yb::MetricUnit::kMicroseconds,
72
    "Time spent processing an UPDATE statement", 60000000LU, 2);
73
METRIC_DEFINE_histogram_with_percentiles(
74
    server, handler_latency_yb_cqlserver_SQLProcessor_DeleteStmt,
75
    "Time spent processing a DELETE statement", yb::MetricUnit::kMicroseconds,
76
    "Time spent processing a DELETE statement", 60000000LU, 2);
77
METRIC_DEFINE_histogram_with_percentiles(
78
    server, handler_latency_yb_cqlserver_SQLProcessor_UseStmt,
79
    "Time spent processing a USE statement", yb::MetricUnit::kMicroseconds,
80
    "Time spent processing a USE statement", 60000000LU, 2);
81
METRIC_DEFINE_histogram_with_percentiles(
82
    server, handler_latency_yb_cqlserver_SQLProcessor_OtherStmts,
83
    "Time spent processing any statement other than SELECT/INSERT/UPDATE/DELETE",
84
    yb::MetricUnit::kMicroseconds,
85
    "Time spent processing any statement other than SELECT/INSERT/UPDATE/DELETE", 60000000LU, 2);
86
METRIC_DEFINE_histogram_with_percentiles(
87
    server, handler_latency_yb_cqlserver_SQLProcessor_Transaction,
88
    "Time spent processing a transaction", yb::MetricUnit::kMicroseconds,
89
    "Time spent processing a transaction", 60000000LU, 2);
90
METRIC_DEFINE_histogram_with_percentiles(
91
    server, handler_latency_yb_cqlserver_SQLProcessor_ResponseSize,
92
    "Size of the returned response blob (in bytes)", yb::MetricUnit::kBytes,
93
    "Size of the returned response blob (in bytes)", 60000000LU, 2);
94
95
namespace yb {
96
namespace ql {
97
98
using std::shared_ptr;
99
using std::string;
100
using client::YBClient;
101
using client::YBMetaDataCache;
102
using client::YBTableName;
103
using ql::audit::IsPrepare;
104
using ql::audit::ErrorIsFormatted;
105
106
6.11k
QLMetrics::QLMetrics(const scoped_refptr<yb::MetricEntity> &metric_entity) {
107
6.11k
  time_to_parse_ql_query_ =
108
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_ParseRequest.Instantiate(metric_entity);
109
6.11k
  time_to_analyze_ql_query_ =
110
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_AnalyzeRequest.Instantiate(metric_entity);
111
6.11k
  time_to_execute_ql_query_ =
112
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_ExecuteRequest.Instantiate(metric_entity);
113
6.11k
  num_rounds_to_analyze_ql_ =
114
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_NumRoundsToAnalyze.Instantiate(
115
6.11k
          metric_entity);
116
6.11k
  num_retries_to_execute_ql_ =
117
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_NumRetriesToExecute.Instantiate(
118
6.11k
          metric_entity);
119
6.11k
  num_flushes_to_execute_ql_ =
120
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_NumFlushesToExecute.Instantiate(
121
6.11k
          metric_entity);
122
123
6.11k
  ql_select_ =
124
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_SelectStmt.Instantiate(metric_entity);
125
6.11k
  ql_insert_ =
126
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_InsertStmt.Instantiate(metric_entity);
127
6.11k
  ql_update_ =
128
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_UpdateStmt.Instantiate(metric_entity);
129
6.11k
  ql_delete_ =
130
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_DeleteStmt.Instantiate(metric_entity);
131
6.11k
  ql_use_ =
132
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_UseStmt.Instantiate(metric_entity);
133
6.11k
  ql_others_ =
134
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_OtherStmts.Instantiate(metric_entity);
135
6.11k
  ql_transaction_ =
136
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_Transaction.Instantiate(metric_entity);
137
138
6.11k
  ql_response_size_bytes_ =
139
6.11k
      METRIC_handler_latency_yb_cqlserver_SQLProcessor_ResponseSize.Instantiate(metric_entity);
140
6.11k
}
141
142
0
QLMetrics::~QLMetrics() = default;
143
144
namespace {
145
146
ThreadSafeObjectPool<Parser> default_parser_pool;
147
148
}
149
150
QLProcessor::QLProcessor(client::YBClient* client,
151
                         shared_ptr<YBMetaDataCache> cache, QLMetrics* ql_metrics,
152
                         ThreadSafeObjectPool<Parser>* parser_pool,
153
                         const server::ClockPtr& clock,
154
                         TransactionPoolProvider transaction_pool_provider)
155
    : ql_env_(client, cache, clock, std::move(transaction_pool_provider)),
156
      audit_logger_(ql_env_),
157
      analyzer_(&ql_env_),
158
      executor_(&ql_env_, &audit_logger_, this, ql_metrics),
159
      ql_metrics_(ql_metrics),
160
18.1k
      parser_pool_(parser_pool ? parser_pool : &default_parser_pool) {
161
18.1k
}
162
163
1
QLProcessor::~QLProcessor() {
164
1
}
165
166
Status QLProcessor::Parse(const string& stmt, ParseTree::UniPtr* parse_tree,
167
                          const bool reparsed, const MemTrackerPtr& mem_tracker,
168
342k
                          const bool internal) {
169
  // Parse the statement and get the generated parse tree.
170
342k
  const MonoTime begin_time = MonoTime::Now();
171
342k
  auto* parser = parser_pool_->Take();
172
342k
  auto scope_exit = ScopeExit([this, parser] {
173
338k
    this->parser_pool_->Release(parser);
174
338k
  });
175
342k
  const Status s = parser->Parse(stmt, reparsed, mem_tracker, internal);
176
342k
  const MonoTime end_time = MonoTime::Now();
177
342k
  if (ql_metrics_ != nullptr) {
178
339k
    const MonoDelta elapsed_time = end_time.GetDeltaSince(begin_time);
179
339k
    ql_metrics_->time_to_parse_ql_query_->Increment(elapsed_time.ToMicroseconds());
180
339k
  }
181
342k
  if (!s.ok()) {
182
96
    RETURN_NOT_OK(audit_logger_.LogStatementError(stmt, s, ErrorIsFormatted::kTrue));
183
96
    return s;
184
96
  }
185
342k
  *parse_tree = parser->Done();
186
342k
  DCHECK
(*parse_tree) << "Parse tree is null"3.77k
;
187
342k
  return Status::OK();
188
342k
}
189
190
338k
Status QLProcessor::Analyze(ParseTree::UniPtr* parse_tree) {
191
  // Semantic analysis - traverse, error-check, and decorate the parse tree nodes with datatypes.
192
338k
  const MonoTime begin_time = MonoTime::Now();
193
338k
  const Status s = analyzer_.Analyze(std::move(*parse_tree));
194
338k
  const MonoTime end_time = MonoTime::Now();
195
341k
  if (
ql_metrics_ != nullptr338k
) {
196
341k
    const MonoDelta elapsed_time = end_time.GetDeltaSince(begin_time);
197
341k
    ql_metrics_->time_to_analyze_ql_query_->Increment(elapsed_time.ToMicroseconds());
198
341k
    ql_metrics_->num_rounds_to_analyze_ql_->Increment(1);
199
341k
  }
200
338k
  *parse_tree = analyzer_.Done();
201
18.4E
  DCHECK(*parse_tree) << "Parse tree is null";
202
338k
  return s;
203
338k
}
204
205
Status QLProcessor::Prepare(const string& stmt, ParseTree::UniPtr* parse_tree,
206
                            const bool reparsed, const MemTrackerPtr& mem_tracker,
207
341k
                            const bool internal) {
208
341k
  RETURN_NOT_OK(Parse(stmt, parse_tree, reparsed, mem_tracker, internal));
209
341k
  Status s = Analyze(parse_tree);
210
341k
  if (s.IsQLError() && 
GetErrorCode(s) == ErrorCode::STALE_METADATA1.08k
&&
!reparsed414
) {
211
414
    *parse_tree = nullptr;
212
414
    RETURN_NOT_OK(Parse(stmt, parse_tree, true /* reparsed */, mem_tracker));
213
414
    s = Analyze(parse_tree);
214
414
  }
215
341k
  if (s.IsQLError()) {
216
1.03k
    RETURN_NOT_OK(audit_logger_.LogStatementError((*parse_tree)->root().get(), stmt, s,
217
1.03k
                                                  ErrorIsFormatted::kTrue));
218
1.03k
  }
219
341k
  return s;
220
341k
}
221
222
124k
bool QLProcessor::CheckPermissions(const ParseTree& parse_tree, StatementExecutedCallback cb) {
223
124k
  const TreeNode* tnode = parse_tree.root().get();
224
124k
  if (tnode != nullptr) {
225
123k
    Status s = CheckNodePermissions(tnode);
226
123k
    if (!s.ok()) {
227
60
      cb.Run(s, nullptr);
228
60
      return false;
229
60
    }
230
123k
  }
231
123k
  return true;
232
124k
}
233
234
123k
Status QLProcessor::CheckNodePermissions(const TreeNode* tnode) {
235
123k
  Status s; // OK by default initialization.
236
123k
  switch (DCHECK_NOTNULL(tnode)->opcode()) {
237
906
    case TreeNodeOpcode::kPTCreateKeyspace:
238
906
      s = ql_env_.HasResourcePermission(
239
906
          "data", ObjectType::SCHEMA, PermissionType::CREATE_PERMISSION);
240
906
      break;
241
237
    case TreeNodeOpcode::kPTCreateTable: {
242
237
      const char* keyspace =
243
237
          static_cast<const PTCreateTable*>(tnode)->table_name()->first_name().c_str();
244
237
      s = ql_env_.HasResourcePermission(get_canonical_keyspace(keyspace), ObjectType::SCHEMA,
245
237
                                        PermissionType::CREATE_PERMISSION, keyspace);
246
237
      break;
247
0
    }
248
24
    case TreeNodeOpcode::kPTCreateType:
249
      // Check has AllKeyspaces permission.
250
24
      s = ql_env_.HasResourcePermission(
251
24
          "data", ObjectType::SCHEMA, PermissionType::CREATE_PERMISSION);
252
24
      if (!s.ok()) {
253
16
        const string keyspace =
254
16
            static_cast<const PTCreateType*>(tnode)->yb_type_name().namespace_name();
255
        // Check has Keyspace permission.
256
16
        s = ql_env_.HasResourcePermission(get_canonical_keyspace(keyspace),
257
16
            ObjectType::SCHEMA, PermissionType::CREATE_PERMISSION, keyspace);
258
16
      }
259
24
      break;
260
7
    case TreeNodeOpcode::kPTCreateIndex: {
261
7
      const YBTableName indexed_table_name =
262
7
          static_cast<const PTCreateIndex*>(tnode)->indexed_table_name();
263
7
      s = ql_env_.HasTablePermission(indexed_table_name, PermissionType::ALTER_PERMISSION);
264
7
      break;
265
0
    }
266
8
    case TreeNodeOpcode::kPTAlterTable: {
267
8
      const YBTableName table_name = static_cast<const PTAlterTable*>(tnode)->yb_table_name();
268
8
      s = ql_env_.HasTablePermission(table_name, PermissionType::ALTER_PERMISSION);
269
8
      break;
270
0
    }
271
17
    case TreeNodeOpcode::kPTTruncateStmt: {
272
17
      const YBTableName table_name = static_cast<const PTTruncateStmt*>(tnode)->yb_table_name();
273
17
      if (FLAGS_ycql_require_drop_privs_for_truncate) {
274
7
        s = ql_env_.HasTablePermission(table_name, PermissionType::DROP_PERMISSION);
275
10
      } else {
276
10
        s = ql_env_.HasTablePermission(table_name, PermissionType::MODIFY_PERMISSION);
277
10
      }
278
17
      break;
279
0
    }
280
2
    case TreeNodeOpcode::kPTExplainStmt: {
281
2
      const PTExplainStmt* explain_stmt = static_cast<const PTExplainStmt*>(tnode);
282
2
      s = CheckNodePermissions(DCHECK_NOTNULL(explain_stmt->stmt().get()));
283
2
      break;
284
0
    }
285
19
    case TreeNodeOpcode::kPTUpdateStmt: FALLTHROUGH_INTENDED;
286
27
    case TreeNodeOpcode::kPTDeleteStmt: FALLTHROUGH_INTENDED;
287
155
    case TreeNodeOpcode::kPTInsertStmt: {
288
155
      DCHECK(tnode->IsDml());
289
155
      const YBTableName table_name = static_cast<const PTDmlStmt*>(tnode)->table_name();
290
155
      s = ql_env_.HasTablePermission(table_name, PermissionType::MODIFY_PERMISSION);
291
155
      break;
292
27
    }
293
117k
    case TreeNodeOpcode::kPTSelectStmt: {
294
117k
      const auto select_stmt = static_cast<const PTSelectStmt*>(tnode);
295
117k
      if (select_stmt->IsReadableByAllSystemTable()) {
296
115k
        break;
297
115k
      }
298
1.61k
      const YBTableName table_name = select_stmt->table_name();
299
1.61k
      s = ql_env_.HasTablePermission(table_name, PermissionType::SELECT_PERMISSION);
300
1.61k
      break;
301
117k
    }
302
757
    case TreeNodeOpcode::kPTCreateRole:
303
757
      s = ql_env_.HasResourcePermission("roles", ObjectType::ROLE,
304
757
                                        PermissionType::CREATE_PERMISSION);
305
757
      break;
306
58
    case TreeNodeOpcode::kPTAlterRole: {
307
58
      const char* role = static_cast<const PTAlterRole*>(tnode)->role_name();
308
58
      s = ql_env_.HasRolePermission(role, PermissionType::ALTER_PERMISSION);
309
58
      break;
310
117k
    }
311
60
    case TreeNodeOpcode::kPTGrantRevokeRole: {
312
60
      const auto grant_revoke_role_stmt = static_cast<const PTGrantRevokeRole*>(tnode);
313
60
      const string granted_role = grant_revoke_role_stmt->granted_role_name();
314
60
      const string recipient_role = grant_revoke_role_stmt->recipient_role_name();
315
60
      s = ql_env_.HasRolePermission(granted_role, PermissionType::AUTHORIZE_PERMISSION);
316
60
      if (s.ok()) {
317
52
        s = ql_env_.HasRolePermission(recipient_role, PermissionType::AUTHORIZE_PERMISSION);
318
52
      }
319
60
      break;
320
117k
    }
321
731
    case TreeNodeOpcode::kPTGrantRevokePermission: {
322
731
      const auto grant_revoke_permission = static_cast<const PTGrantRevokePermission*>(tnode);
323
731
      const string canonical_resource = grant_revoke_permission->canonical_resource();
324
731
      const char* keyspace = grant_revoke_permission->namespace_name();
325
      // It's only a table name if the resource type is TABLE.
326
731
      const char* table = grant_revoke_permission->resource_name();
327
731
      switch (grant_revoke_permission->resource_type()) {
328
238
        case ResourceType::KEYSPACE: {
329
238
          DCHECK_EQ(canonical_resource, get_canonical_keyspace(keyspace));
330
238
          s = ql_env_.HasResourcePermission(canonical_resource, ObjectType::SCHEMA,
331
238
                                            PermissionType::AUTHORIZE_PERMISSION,
332
238
                                            keyspace);
333
238
          break;
334
0
        }
335
201
        case ResourceType::TABLE: {
336
201
          DCHECK_EQ(canonical_resource, get_canonical_table(keyspace, table));
337
201
          s = ql_env_.HasTablePermission(keyspace, table, PermissionType::AUTHORIZE_PERMISSION);
338
201
          break;
339
0
        }
340
87
        case ResourceType::ROLE: {
341
87
          DCHECK_EQ(canonical_resource,
342
87
                    get_canonical_role(grant_revoke_permission->resource_name()));
343
87
          s = ql_env_.HasResourcePermission(canonical_resource, ObjectType::ROLE,
344
87
                                            PermissionType::AUTHORIZE_PERMISSION);
345
87
          break;
346
0
        }
347
138
        case ResourceType::ALL_KEYSPACES: {
348
138
          DCHECK_EQ(canonical_resource, "data");
349
138
          s = ql_env_.HasResourcePermission(canonical_resource, ObjectType::SCHEMA,
350
138
                                            PermissionType::AUTHORIZE_PERMISSION);
351
138
          break;
352
0
        }
353
67
        case ResourceType::ALL_ROLES:
354
67
          DCHECK_EQ(canonical_resource, "roles");
355
67
          s = ql_env_.HasResourcePermission(canonical_resource, ObjectType::ROLE,
356
67
                                            PermissionType::AUTHORIZE_PERMISSION);
357
67
          break;
358
731
      }
359
731
      break;
360
731
    }
361
1.87k
    case TreeNodeOpcode::kPTDropStmt: {
362
1.87k
      const auto drop_stmt = static_cast<const PTDropStmt*>(tnode);
363
1.87k
      const ObjectType object_type = drop_stmt->drop_type();
364
1.87k
      switch(object_type) {
365
732
        case ObjectType::ROLE:
366
732
          s = ql_env_.HasRolePermission(drop_stmt->name()->QLName(),
367
732
                                        PermissionType::DROP_PERMISSION);
368
732
          break;
369
874
        case ObjectType::SCHEMA:
370
874
          s = ql_env_.HasResourcePermission(
371
874
              get_canonical_keyspace(drop_stmt->yb_table_name().namespace_name()),
372
874
              ObjectType::SCHEMA, PermissionType::DROP_PERMISSION);
373
874
          break;
374
237
        case ObjectType::TABLE:
375
237
          s = ql_env_.HasTablePermission(drop_stmt->yb_table_name(),
376
237
                                         PermissionType::DROP_PERMISSION);
377
237
          break;
378
24
        case ObjectType::TYPE:
379
          // Check has AllKeyspaces permission.
380
24
          s = ql_env_.HasResourcePermission(
381
24
              "data", ObjectType::SCHEMA, PermissionType::DROP_PERMISSION);
382
24
          if (!s.ok()) {
383
20
            const string keyspace = drop_stmt->yb_table_name().namespace_name();
384
            // Check has Keyspace permission.
385
20
            s = ql_env_.HasResourcePermission(get_canonical_keyspace(keyspace),
386
20
                ObjectType::SCHEMA, PermissionType::DROP_PERMISSION, keyspace);
387
20
          }
388
24
          break;
389
4
        case ObjectType::INDEX: {
390
4
          bool cache_used = false;
391
4
          const YBTableName table_name(YQL_DATABASE_CQL,
392
4
                                       drop_stmt->yb_table_name().namespace_name(),
393
4
                                       drop_stmt->yb_table_name().table_name());
394
4
          std::shared_ptr<client::YBTable> table = ql_env_.GetTableDesc(table_name, &cache_used);
395
396
          // If the table is not found, or if it's not an index, let the operation go through
397
          // so that we can return a "not found" error.s
398
4
          if (table && table->IsIndex()) {
399
4
            std::shared_ptr<client::YBTable> indexed_table =
400
4
                ql_env_.GetTableDesc(table->index_info().indexed_table_id(), &cache_used);
401
402
4
            if (!indexed_table) {
403
0
              s = STATUS_SUBSTITUTE(InternalError,
404
0
                                    "Unable to find index $0",
405
0
                                    drop_stmt->name()->QLName());
406
0
              break;
407
0
            }
408
409
4
            s = ql_env_.HasTablePermission(indexed_table->name(),
410
4
                                           PermissionType::ALTER_PERMISSION);
411
4
          }
412
4
          break;
413
4
        }
414
4
        default:
415
0
          break;
416
1.87k
      }
417
1.87k
      break;
418
1.87k
    }
419
2.05k
    default:
420
2.05k
      break;
421
123k
  }
422
123k
  return s;
423
123k
}
424
425
void QLProcessor::ExecuteAsync(const ParseTree& parse_tree, const StatementParameters& params,
426
9.09M
                               StatementExecutedCallback cb) {
427
9.09M
  if (FLAGS_use_cassandra_authentication && 
!parse_tree.internal()129k
) {
428
123k
    if (!CheckPermissions(parse_tree, cb)) {
429
60
      return;
430
60
    }
431
123k
  }
432
9.09M
  executor_.ExecuteAsync(parse_tree, params, std::move(cb));
433
9.09M
}
434
435
1.62k
void QLProcessor::ExecuteAsync(const StatementBatch& batch, StatementExecutedCallback cb) {
436
1.62k
  executor_.ExecuteAsync(batch, std::move(cb));
437
1.62k
}
438
439
void QLProcessor::RunAsync(const string& stmt, const StatementParameters& params,
440
337k
                           StatementExecutedCallback cb, const bool reparsed) {
441
337k
  ParseTree::UniPtr parse_tree;
442
337k
  const Status s = Prepare(stmt, &parse_tree, reparsed);
443
337k
  if (PREDICT_FALSE(!s.ok())) {
444
962
    return cb.Run(s, nullptr /* result */);
445
962
  }
446
336k
  const ParseTree* ptree = parse_tree.release();
447
  // Do not make a copy of stmt and params when binding to the RunAsyncDone callback because when
448
  // error occurs due to stale matadata, the statement needs to be reexecuted. We should pass the
449
  // original references which are guaranteed to still be alive when the statement is reexecuted.
450
336k
  ExecuteAsync(*ptree, params, Bind(&QLProcessor::RunAsyncDone, Unretained(this), ConstRef(stmt),
451
336k
                                    ConstRef(params), Owned(ptree), cb));
452
336k
}
453
454
void QLProcessor::RunAsyncDone(const string& stmt, const StatementParameters& params,
455
                               const ParseTree* parse_tree, StatementExecutedCallback cb,
456
335k
                               const Status& s, const ExecutedResult::SharedPtr& result) {
457
  // If execution fails due to stale metadata and the statement has not been reparsed, rerun this
458
  // statement with stale metadata flushed. The rerun needs to be rescheduled in because this
459
  // callback may not be executed in the RPC worker thread. Also, rescheduling gives other calls a
460
  // chance to execute first before we do.
461
335k
  if (s.IsQLError() && 
GetErrorCode(s) == ErrorCode::STALE_METADATA3.21k
&&
!parse_tree->reparsed()570
) {
462
570
    return Reschedule(&run_async_task_.Bind(this, stmt, params, std::move(cb)));
463
570
  }
464
335k
  cb.Run(s, result);
465
335k
}
466
467
1
void QLProcessor::Reschedule(rpc::ThreadPoolTask* task) {
468
1
  is_rescheduled_.store(IsRescheduled::kTrue, std::memory_order_release);
469
  // Some unit tests are not executed in CQL proxy. In those cases, just execute the callback
470
  // directly while disabling thread restrictions.
471
1
  const bool allowed = ThreadRestrictions::SetWaitAllowed(true);
472
1
  task->Run();
473
  // In such tests QLProcessor is deleted right after Run is executed, since QLProcessor tasks
474
  // do nothing in Done we could just don't execute it.
475
  // task->Done(Status::OK());
476
1
  ThreadRestrictions::SetWaitAllowed(allowed);
477
1
}
478
479
1
CoarseTimePoint QLProcessor::GetDeadline() const {
480
  // Used only in tests.
481
1
  return CoarseMonoClock::now() + MonoDelta::FromSeconds(60);
482
1
}
483
484
}  // namespace ql
485
}  // namespace yb