YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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
3.00k
    : YQLVirtualTable(table_name, namespace_name, master, CreateSchema()) {
34
3.00k
}
35
36
namespace {
37
38
1.23k
const string& ColumnName(const Schema& schema, const ColumnId id) {
39
1.23k
  auto column = schema.column_by_id(id);
40
1.23k
  DCHECK(column.ok());
41
1.23k
  return column->name();
42
1.23k
}
43
44
4.01k
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
4.01k
  switch (where_expr.expr_case()) {
48
0
    case yb::QLExpressionPB::EXPR_NOT_SET: return "NULL";
49
1.23k
    case QLExpressionPB::kValue:
50
1.23k
      return QLValue(where_expr.value()).ToValueString(QuotesType::kSingleQuotes);
51
1.23k
    case QLExpressionPB::kColumnId: return ColumnName(schema, ColumnId(where_expr.column_id()));
52
1.53k
    case QLExpressionPB::kCondition:
53
1.53k
    {
54
1.53k
      std::string res;
55
1.53k
      res += QLExpressionPBToPredicateString(where_expr.condition().operands(0), schema);
56
1.53k
      switch (where_expr.condition().op()) {
57
298
        case QLOperator::QL_OP_AND:
58
298
          res += " AND ";
59
298
          break;
60
373
        case QLOperator::QL_OP_EQUAL:
61
373
          res += " = ";
62
373
          break;
63
301
        case QLOperator::QL_OP_NOT_EQUAL:
64
301
          res += " != ";
65
301
          break;
66
491
        case QLOperator::QL_OP_GREATER_THAN:
67
491
          res += " > ";
68
491
          break;
69
25
        case QLOperator::QL_OP_GREATER_THAN_EQUAL:
70
25
          res += " >= ";
71
25
          break;
72
25
        case QLOperator::QL_OP_LESS_THAN:
73
25
          res += " < ";
74
25
          break;
75
25
        case QLOperator::QL_OP_LESS_THAN_EQUAL:
76
25
          res += " <= ";
77
25
          break;
78
0
        default:
79
0
          LOG_IF(DFATAL, false) << "We should have handled anything required.";
80
0
          break;
81
1.53k
      }
82
1.53k
      res += QLExpressionPBToPredicateString(where_expr.condition().operands(1), schema);
83
1.53k
      return res;
84
1.53k
    }
85
0
    default:
86
0
      LOG_IF(DFATAL, false) << "We should have handled anything required.";
87
4.01k
  }
88
0
  return std::string();
89
4.01k
}
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
270k
  for (const auto& table : tables) {
100
270k
    const auto indexed_table_id = table->indexed_table_id();
101
270k
    if (indexed_table_id.empty()) {
102
262k
      continue;
103
262k
    }
104
105
    // Skip non-YQL indexes.
106
8.52k
    if (!IsYcqlTable(*table)) {
107
2.57k
      continue;
108
2.57k
    }
109
110
5.94k
    scoped_refptr<TableInfo> indexed_table = catalog_manager->GetTableInfo(indexed_table_id);
111
    // Skip if the index is invalid (bad schema).
112
5.94k
    if (indexed_table == nullptr) {
113
0
      continue;
114
0
    }
115
5.94k
    Schema indexed_schema;
116
5.94k
    RETURN_NOT_OK(indexed_table->GetSchema(&indexed_schema));
117
118
    // Get namespace for table.
119
5.94k
    auto ns_info = VERIFY_RESULT(catalog_manager->FindNamespaceById(table->namespace_id()));
120
121
    // Create appropriate row for the table;
122
0
    QLRow& row = vtable->Extend();
123
5.94k
    RETURN_NOT_OK(SetColumnValue(kKeyspaceName, ns_info->name(), &row));
124
5.94k
    RETURN_NOT_OK(SetColumnValue(kTableName, indexed_table->name(), &row));
125
5.94k
    RETURN_NOT_OK(SetColumnValue(kIndexName, table->name(), &row));
126
5.94k
    RETURN_NOT_OK(SetColumnValue(kKind, "COMPOSITES", &row));
127
128
5.94k
    string target;
129
5.94k
    IndexInfo index_info = indexed_table->GetIndexInfo(table->id());
130
12.6k
    for (size_t i = 0; i < index_info.hash_column_count(); 
i++6.72k
) {
131
6.72k
      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
6.72k
        target += YcqlName::DemangleName(index_info.columns()[i].column_name);
135
6.72k
      } else {
136
0
        target += ColumnName(indexed_schema, index_info.columns()[i].indexed_column_id);
137
0
      }
138
6.72k
      if (i != index_info.hash_column_count() - 1) {
139
776
        target += ", ";
140
776
      }
141
6.72k
    }
142
5.94k
    if (index_info.hash_column_count() > 1) {
143
763
      target = '(' + target + ')';
144
763
    }
145
5.94k
    for (size_t i = index_info.hash_column_count();
146
20.6k
         i < index_info.hash_column_count() + index_info.range_column_count(); 
i++14.6k
) {
147
14.6k
      target += ", ";
148
14.6k
      if (
index_info.use_mangled_column_name()14.6k
) {
149
        // Newer IndexInfo uses mangled name of expression instead of column ID of the table
150
        // that was indexed.
151
14.6k
        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
14.6k
    }
156
157
5.94k
    string include;
158
5.94k
    for (size_t i = index_info.hash_column_count() + index_info.range_column_count();
159
10.2k
         i < index_info.columns().size(); 
i++4.25k
) {
160
4.25k
      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
4.25k
        include += YcqlName::DemangleName(index_info.columns()[i].column_name);
164
4.25k
      } else {
165
0
        include += ColumnName(indexed_schema, index_info.columns()[i].indexed_column_id);
166
0
      }
167
4.25k
      if (i != index_info.columns().size() - 1) {
168
1.89k
        include += ", ";
169
1.89k
      }
170
4.25k
    }
171
172
5.94k
    string predicate;
173
5.94k
    if (index_info.where_predicate_spec()) {
174
941
      predicate = QLExpressionPBToPredicateString(index_info.where_predicate_spec()->where_expr(),
175
941
                                                  indexed_schema);
176
941
    }
177
178
5.94k
    QLValue options;
179
5.94k
    options.set_map_value();
180
5.94k
    options.add_map_key()->set_string_value("target");
181
5.94k
    options.add_map_value()->set_string_value(target);
182
5.94k
    if (!include.empty()) {
183
2.36k
      options.add_map_key()->set_string_value("include");
184
2.36k
      options.add_map_value()->set_string_value(include);
185
2.36k
    }
186
5.94k
    if (!predicate.empty()) {
187
940
      options.add_map_key()->set_string_value("predicate");
188
940
      options.add_map_value()->set_string_value(predicate);
189
940
    }
190
5.94k
    RETURN_NOT_OK(SetColumnValue(kOptions, options.value(), &row));
191
192
    // Create appropriate table uuids.
193
5.94k
    Uuid uuid;
194
    // Note: table id is in host byte order.
195
5.94k
    RETURN_NOT_OK(uuid.FromHexString(indexed_table_id));
196
5.94k
    RETURN_NOT_OK(SetColumnValue(kTableId, uuid, &row));
197
5.94k
    RETURN_NOT_OK(uuid.FromHexString(table->id()));
198
5.94k
    RETURN_NOT_OK(SetColumnValue(kIndexId, uuid, &row));
199
200
5.94k
    Schema schema;
201
5.94k
    RETURN_NOT_OK(table->GetSchema(&schema));
202
5.94k
    const auto & table_properties = schema.table_properties();
203
204
5.94k
    if (table_properties.HasNumTablets()) {
205
30
      int32_t num_tablets = table_properties.num_tablets();
206
30
      RETURN_NOT_OK(SetColumnValue(kNumTablets, num_tablets, &row));
207
30
    }
208
209
5.94k
    QLValue txn;
210
5.94k
    txn.set_map_value();
211
5.94k
    txn.add_map_key()->set_string_value("enabled");
212
5.94k
    txn.add_map_value()->set_string_value(table_properties.is_transactional() ? 
"true"3.86k
:
"false"2.08k
);
213
5.94k
    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.08k
      txn.add_map_key()->set_string_value("consistency_level");
217
2.08k
      txn.add_map_value()->set_string_value("user_enforced");
218
2.08k
    }
219
5.94k
    RETURN_NOT_OK(SetColumnValue(kTransactions, txn.value(), &row));
220
221
5.94k
    RETURN_NOT_OK(SetColumnValue(kIsUnique, table->is_unique_index(), &row));
222
5.94k
  }
223
224
14.5k
  return vtable;
225
14.5k
}
226
227
3.00k
Schema YQLIndexesVTable::CreateSchema() const {
228
3.00k
  SchemaBuilder builder;
229
3.00k
  CHECK_OK(builder.AddHashKeyColumn(kKeyspaceName, QLType::Create(DataType::STRING)));
230
3.00k
  CHECK_OK(builder.AddKeyColumn(kTableName, QLType::Create(DataType::STRING)));
231
3.00k
  CHECK_OK(builder.AddKeyColumn(kIndexName, QLType::Create(DataType::STRING)));
232
3.00k
  CHECK_OK(builder.AddColumn(kKind, QLType::Create(DataType::STRING)));
233
3.00k
  CHECK_OK(builder.AddColumn(kOptions,
234
3.00k
                             QLType::CreateTypeMap(DataType::STRING, DataType::STRING)));
235
3.00k
  CHECK_OK(builder.AddColumn(kTableId, QLType::Create(DataType::UUID)));
236
3.00k
  CHECK_OK(builder.AddColumn(kIndexId, QLType::Create(DataType::UUID)));
237
3.00k
  CHECK_OK(builder.AddColumn(kTransactions,
238
3.00k
                             QLType::CreateTypeMap(DataType::STRING, DataType::STRING)));
239
3.00k
  CHECK_OK(builder.AddColumn(kIsUnique, QLType::Create(DataType::BOOL)));
240
3.00k
  CHECK_OK(builder.AddColumn(kNumTablets, QLType::Create(DataType::INT32)));
241
242
3.00k
  return builder.Build();
243
3.00k
}
244
245
}  // namespace master
246
}  // namespace yb