YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/master/yql_indexes_vtable.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include "yb/master/yql_indexes_vtable.h"
15
16
#include "yb/common/index_column.h"
17
#include "yb/common/ql_name.h"
18
#include "yb/common/ql_type.h"
19
#include "yb/common/ql_value.h"
20
#include "yb/common/schema.h"
21
22
#include "yb/master/catalog_entity_info.h"
23
#include "yb/master/catalog_manager_if.h"
24
25
#include "yb/util/status_log.h"
26
27
namespace yb {
28
namespace master {
29
30
YQLIndexesVTable::YQLIndexesVTable(const TableName& table_name,
31
                                   const NamespaceName& namespace_name,
32
                                   Master* const master)
33
2.00k
    : YQLVirtualTable(table_name, namespace_name, master, CreateSchema()) {
34
2.00k
}
35
36
namespace {
37
38
1.69k
const string& ColumnName(const Schema& schema, const ColumnId id) {
39
1.69k
  auto column = schema.column_by_id(id);
40
1.69k
  DCHECK(column.ok());
41
1.69k
  return column->name();
42
1.69k
}
43
44
5.42k
string QLExpressionPBToPredicateString(const QLExpressionPB& where_expr, const Schema& schema) {
45
  // TODO(Piyush): Move this to some sort of util file and handle more cases if later we support
46
  // them in partial index predicate.
47
5.42k
  switch (where_expr.expr_case()) {
48
0
    case yb::QLExpressionPB::EXPR_NOT_SET: return "NULL";
49
1.68k
    case QLExpressionPB::kValue:
50
1.68k
      return QLValue(where_expr.value()).ToValueString(QuotesType::kSingleQuotes);
51
1.69k
    case QLExpressionPB::kColumnId: return ColumnName(schema, ColumnId(where_expr.column_id()));
52
2.04k
    case QLExpressionPB::kCondition:
53
2.04k
    {
54
2.04k
      std::string res;
55
2.04k
      res += QLExpressionPBToPredicateString(where_expr.condition().operands(0), schema);
56
2.04k
      switch (where_expr.condition().op()) {
57
351
        case QLOperator::QL_OP_AND:
58
351
          res += " AND ";
59
351
          break;
60
362
        case QLOperator::QL_OP_EQUAL:
61
362
          res += " = ";
62
362
          break;
63
305
        case QLOperator::QL_OP_NOT_EQUAL:
64
305
          res += " != ";
65
305
          break;
66
995
        case QLOperator::QL_OP_GREATER_THAN:
67
995
          res += " > ";
68
995
          break;
69
10
        case QLOperator::QL_OP_GREATER_THAN_EQUAL:
70
10
          res += " >= ";
71
10
          break;
72
10
        case QLOperator::QL_OP_LESS_THAN:
73
10
          res += " < ";
74
10
          break;
75
10
        case QLOperator::QL_OP_LESS_THAN_EQUAL:
76
10
          res += " <= ";
77
10
          break;
78
0
        default:
79
0
          LOG_IF(DFATAL, false) << "We should have handled anything required.";
80
0
          break;
81
2.04k
      }
82
2.04k
      res += QLExpressionPBToPredicateString(where_expr.condition().operands(1), schema);
83
2.04k
      return res;
84
2.04k
    }
85
0
    default:
86
0
      LOG_IF(DFATAL, false) << "We should have handled anything required.";
87
5.42k
  }
88
0
  return std::string();
89
5.42k
}
90
91
} // namespace
92
93
Result<std::shared_ptr<QLRowBlock>> YQLIndexesVTable::RetrieveData(
94
14.5k
    const QLReadRequestPB& request) const {
95
14.5k
  auto vtable = std::make_shared<QLRowBlock>(schema());
96
14.5k
  auto* catalog_manager = &this->catalog_manager();
97
98
14.5k
  auto tables = catalog_manager->GetTables(GetTablesMode::kVisibleToClient);
99
268k
  for (const auto& table : tables) {
100
268k
    const auto indexed_table_id = table->indexed_table_id();
101
268k
    if (indexed_table_id.empty()) {
102
260k
      continue;
103
260k
    }
104
105
    // Skip non-YQL indexes.
106
7.71k
    if (!IsYcqlTable(*table)) {
107
1.28k
      continue;
108
1.28k
    }
109
110
6.43k
    scoped_refptr<TableInfo> indexed_table = catalog_manager->GetTableInfo(indexed_table_id);
111
    // Skip if the index is invalid (bad schema).
112
6.43k
    if (indexed_table == nullptr) {
113
0
      continue;
114
0
    }
115
6.43k
    Schema indexed_schema;
116
6.43k
    RETURN_NOT_OK(indexed_table->GetSchema(&indexed_schema));
117
118
    // Get namespace for table.
119
6.43k
    auto ns_info = VERIFY_RESULT(catalog_manager->FindNamespaceById(table->namespace_id()));
120
121
    // Create appropriate row for the table;
122
6.43k
    QLRow& row = vtable->Extend();
123
6.43k
    RETURN_NOT_OK(SetColumnValue(kKeyspaceName, ns_info->name(), &row));
124
6.43k
    RETURN_NOT_OK(SetColumnValue(kTableName, indexed_table->name(), &row));
125
6.43k
    RETURN_NOT_OK(SetColumnValue(kIndexName, table->name(), &row));
126
6.43k
    RETURN_NOT_OK(SetColumnValue(kKind, "COMPOSITES", &row));
127
128
6.43k
    string target;
129
6.43k
    IndexInfo index_info = indexed_table->GetIndexInfo(table->id());
130
13.6k
    for (size_t i = 0; i < index_info.hash_column_count(); i++) {
131
7.21k
      if (index_info.use_mangled_column_name()) {
132
        // Newer IndexInfo uses mangled name of expression instead of column ID of the table
133
        // that was indexed.
134
7.21k
        target += YcqlName::DemangleName(index_info.columns()[i].column_name);
135
0
      } else {
136
0
        target += ColumnName(indexed_schema, index_info.columns()[i].indexed_column_id);
137
0
      }
138
7.21k
      if (i != index_info.hash_column_count() - 1) {
139
783
        target += ", ";
140
783
      }
141
7.21k
    }
142
6.43k
    if (index_info.hash_column_count() > 1) {
143
772
      target = '(' + target + ')';
144
772
    }
145
6.43k
    for (size_t i = index_info.hash_column_count();
146
23.3k
         i < index_info.hash_column_count() + index_info.range_column_count(); i++) {
147
16.9k
      target += ", ";
148
16.9k
      if (index_info.use_mangled_column_name()) {
149
        // Newer IndexInfo uses mangled name of expression instead of column ID of the table
150
        // that was indexed.
151
16.9k
        target += YcqlName::DemangleName(index_info.columns()[i].column_name);
152
18.4E
      } else {
153
18.4E
        target += ColumnName(indexed_schema, index_info.columns()[i].indexed_column_id);
154
18.4E
      }
155
16.9k
    }
156
157
6.43k
    string include;
158
6.43k
    for (size_t i = index_info.hash_column_count() + index_info.range_column_count();
159
10.3k
         i < index_info.columns().size(); i++) {
160
3.91k
      if (index_info.use_mangled_column_name()) {
161
        // Newer IndexInfo uses mangled name of expression instead of column ID of the table
162
        // that was indexed.
163
3.91k
        include += YcqlName::DemangleName(index_info.columns()[i].column_name);
164
0
      } else {
165
0
        include += ColumnName(indexed_schema, index_info.columns()[i].indexed_column_id);
166
0
      }
167
3.91k
      if (i != index_info.columns().size() - 1) {
168
1.42k
        include += ", ";
169
1.42k
      }
170
3.91k
    }
171
172
6.43k
    string predicate;
173
6.43k
    if (index_info.where_predicate_spec()) {
174
1.34k
      predicate = QLExpressionPBToPredicateString(index_info.where_predicate_spec()->where_expr(),
175
1.34k
                                                  indexed_schema);
176
1.34k
    }
177
178
6.43k
    QLValue options;
179
6.43k
    options.set_map_value();
180
6.43k
    options.add_map_key()->set_string_value("target");
181
6.43k
    options.add_map_value()->set_string_value(target);
182
6.43k
    if (!include.empty()) {
183
2.47k
      options.add_map_key()->set_string_value("include");
184
2.47k
      options.add_map_value()->set_string_value(include);
185
2.47k
    }
186
6.43k
    if (!predicate.empty()) {
187
1.34k
      options.add_map_key()->set_string_value("predicate");
188
1.34k
      options.add_map_value()->set_string_value(predicate);
189
1.34k
    }
190
6.43k
    RETURN_NOT_OK(SetColumnValue(kOptions, options.value(), &row));
191
192
    // Create appropriate table uuids.
193
6.43k
    Uuid uuid;
194
    // Note: table id is in host byte order.
195
6.43k
    RETURN_NOT_OK(uuid.FromHexString(indexed_table_id));
196
6.43k
    RETURN_NOT_OK(SetColumnValue(kTableId, uuid, &row));
197
6.43k
    RETURN_NOT_OK(uuid.FromHexString(table->id()));
198
6.43k
    RETURN_NOT_OK(SetColumnValue(kIndexId, uuid, &row));
199
200
6.43k
    Schema schema;
201
6.43k
    RETURN_NOT_OK(table->GetSchema(&schema));
202
6.43k
    const auto & table_properties = schema.table_properties();
203
204
6.43k
    if (table_properties.HasNumTablets()) {
205
41
      int32_t num_tablets = table_properties.num_tablets();
206
41
      RETURN_NOT_OK(SetColumnValue(kNumTablets, num_tablets, &row));
207
41
    }
208
209
6.43k
    QLValue txn;
210
6.43k
    txn.set_map_value();
211
6.43k
    txn.add_map_key()->set_string_value("enabled");
212
4.00k
    txn.add_map_value()->set_string_value(table_properties.is_transactional() ? "true" : "false");
213
6.43k
    if (table_properties.consistency_level() == YBConsistencyLevel::USER_ENFORCED) {
214
      // If consistency level is user-encorced, show it also. Omit the other consistency levels
215
      // which are not recognized by "CREATE INDEX" syntax.
216
2.42k
      txn.add_map_key()->set_string_value("consistency_level");
217
2.42k
      txn.add_map_value()->set_string_value("user_enforced");
218
2.42k
    }
219
6.43k
    RETURN_NOT_OK(SetColumnValue(kTransactions, txn.value(), &row));
220
221
6.43k
    RETURN_NOT_OK(SetColumnValue(kIsUnique, table->is_unique_index(), &row));
222
6.43k
  }
223
224
14.5k
  return vtable;
225
14.5k
}
226
227
2.00k
Schema YQLIndexesVTable::CreateSchema() const {
228
2.00k
  SchemaBuilder builder;
229
2.00k
  CHECK_OK(builder.AddHashKeyColumn(kKeyspaceName, QLType::Create(DataType::STRING)));
230
2.00k
  CHECK_OK(builder.AddKeyColumn(kTableName, QLType::Create(DataType::STRING)));
231
2.00k
  CHECK_OK(builder.AddKeyColumn(kIndexName, QLType::Create(DataType::STRING)));
232
2.00k
  CHECK_OK(builder.AddColumn(kKind, QLType::Create(DataType::STRING)));
233
2.00k
  CHECK_OK(builder.AddColumn(kOptions,
234
2.00k
                             QLType::CreateTypeMap(DataType::STRING, DataType::STRING)));
235
2.00k
  CHECK_OK(builder.AddColumn(kTableId, QLType::Create(DataType::UUID)));
236
2.00k
  CHECK_OK(builder.AddColumn(kIndexId, QLType::Create(DataType::UUID)));
237
2.00k
  CHECK_OK(builder.AddColumn(kTransactions,
238
2.00k
                             QLType::CreateTypeMap(DataType::STRING, DataType::STRING)));
239
2.00k
  CHECK_OK(builder.AddColumn(kIsUnique, QLType::Create(DataType::BOOL)));
240
2.00k
  CHECK_OK(builder.AddColumn(kNumTablets, QLType::Create(DataType::INT32)));
241
242
2.00k
  return builder.Build();
243
2.00k
}
244
245
}  // namespace master
246
}  // namespace yb