YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/tablet/tablet-schema-test.cc
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
33
#include <algorithm>
34
#include <limits>
35
#include <string>
36
#include <unordered_set>
37
#include <vector>
38
39
#include <glog/logging.h>
40
#include <gtest/gtest.h>
41
42
#include "yb/common/partial_row.h"
43
#include "yb/common/ql_protocol_util.h"
44
#include "yb/common/schema.h"
45
46
#include "yb/docdb/ql_rowwise_iterator_interface.h"
47
48
#include "yb/gutil/strings/numbers.h"
49
#include "yb/gutil/strings/substitute.h"
50
51
#include "yb/tablet/local_tablet_writer.h"
52
#include "yb/tablet/tablet-test-util.h"
53
#include "yb/tablet/tablet.h"
54
#include "yb/tablet/tablet_metadata.h"
55
56
#include "yb/util/env.h"
57
#include "yb/util/status_log.h"
58
#include "yb/util/test_macros.h"
59
#include "yb/util/test_util.h"
60
61
using strings::Substitute;
62
63
namespace yb {
64
namespace tablet {
65
66
class TestTabletSchema : public YBTabletTest {
67
 public:
68
  TestTabletSchema()
69
3
    : YBTabletTest(CreateBaseSchema(), YQL_TABLE_TYPE) {
70
3
  }
71
72
1
  void InsertRows(int32_t first_key, int32_t nrows) {
73
11
    for (int32_t i = first_key; i < nrows; ++i) {
74
10
      InsertRow(i);
75
10
      if (i == (nrows / 2)) {
76
1
        ASSERT_OK(tablet()->Flush(tablet::FlushMode::kSync));
77
1
      }
78
10
    }
79
1
  }
80
81
13
  void InsertRow(int32_t key) {
82
13
    LocalTabletWriter writer(tablet().get());
83
13
    QLWriteRequestPB req;
84
13
    QLAddInt32HashValue(&req, key);
85
13
    QLAddInt32ColumnValue(&req, kFirstColumnId + 1, key);
86
13
    ASSERT_OK(writer.Write(&req));
87
13
  }
88
89
1
  void DeleteRow(int32_t key) {
90
1
    LocalTabletWriter writer(tablet().get());
91
1
    QLWriteRequestPB req;
92
1
    req.set_type(QLWriteRequestPB::QL_STMT_DELETE);
93
1
    QLAddInt32HashValue(&req, key);
94
1
    ASSERT_OK(writer.Write(&req));
95
1
  }
96
97
2
  void MutateRow(int32_t key, int32_t col_idx, int32_t new_val) {
98
2
    LocalTabletWriter writer(tablet().get());
99
2
    QLWriteRequestPB req;
100
2
    QLAddInt32HashValue(&req, key);
101
2
    QLAddInt32ColumnValue(&req, kFirstColumnId + col_idx, new_val);
102
2
    ASSERT_OK(writer.Write(&req));
103
2
  }
104
105
  void VerifyTabletRows(const Schema& projection,
106
4
                        const std::vector<std::pair<string, string> >& keys) {
107
4
    typedef std::pair<string, string> StringPair;
108
109
4
    vector<string> rows;
110
4
    ASSERT_OK(DumpTablet(*tablet(), projection, &rows));
111
4
    std::sort(rows.begin(), rows.end());
112
5
    for (const string& row : rows) {
113
5
      bool found = false;
114
6
      for (const StringPair& k : keys) {
115
6
        if (row.find(k.first) != string::npos) {
116
5
          ASSERT_STR_CONTAINS(row, k.second);
117
5
          found = true;
118
5
          break;
119
5
        }
120
6
      }
121
10
      ASSERT_TRUE(found) << "Row: " << row << ", keys: " << yb::ToString(keys);
122
5
    }
123
4
  }
124
125
 private:
126
3
  Schema CreateBaseSchema() {
127
3
    return Schema({ ColumnSchema("key", INT32, false, true),
128
3
                    ColumnSchema("c1", INT32) }, 1);
129
3
  }
130
};
131
132
// Read from a tablet using a projection schema with columns not present in
133
// the original schema. Verify that the server reject the request.
134
1
TEST_F(TestTabletSchema, TestRead) {
135
1
  const size_t kNumRows = 10;
136
1
  Schema projection({ ColumnSchema("key", INT32, false, true),
137
1
                      ColumnSchema("c2", INT64),
138
1
                      ColumnSchema("c3", STRING) },
139
1
                    1);
140
141
1
  InsertRows(0, kNumRows);
142
143
1
  auto iter = tablet()->NewRowIterator(projection);
144
1
  ASSERT_TRUE(!iter.ok() && iter.status().IsInvalidArgument());
145
1
  ASSERT_STR_CONTAINS(iter.status().message().ToBuffer(),
146
1
                      "Some columns are not present in the current schema: c2, c3");
147
1
}
148
149
// Write to the table using a projection schema with a renamed field.
150
1
TEST_F(TestTabletSchema, TestRenameProjection) {
151
1
  std::vector<std::pair<string, string> > keys;
152
153
  // Insert with the base schema
154
1
  InsertRow(1);
155
156
  // Switch schema to s2
157
1
  SchemaBuilder builder(*tablet()->metadata()->schema());
158
1
  ASSERT_OK(builder.RenameColumn("c1", "c1_renamed"));
159
1
  AlterSchema(builder.Build());
160
1
  Schema s2 = builder.BuildWithoutIds();
161
162
  // Insert with the s2 schema after AlterSchema(s2)
163
1
  InsertRow(2);
164
165
  // Read and verify using the s2 schema
166
1
  keys.clear();
167
5
  for (int i = 1; i <= 4; ++i) {
168
4
    keys.push_back(std::pair<string, string>(Substitute("{ int32_value: $0", i),
169
4
                                             Substitute("int32_value: $0 }", i)));
170
4
  }
171
1
  VerifyTabletRows(s2, keys);
172
173
  // Delete the first two rows
174
1
  DeleteRow(/* key= */ 1);
175
176
  // Alter the remaining row
177
1
  MutateRow(/* key= */ 2, /* col_idx= */ 1, /* new_val= */ 6);
178
179
  // Read and verify using the s2 schema
180
1
  keys.clear();
181
1
  keys.push_back(std::pair<string, string>("{ int32_value: 2", "int32_value: 6 }"));
182
1
  VerifyTabletRows(s2, keys);
183
1
}
184
185
// Verify that removing a column and re-adding it will not result in making old data visible
186
1
TEST_F(TestTabletSchema, TestDeleteAndReAddColumn) {
187
1
  std::vector<std::pair<string, string> > keys;
188
189
  // Insert and Mutate with the base schema
190
1
  InsertRow(1);
191
1
  MutateRow(/* key= */ 1, /* col_idx= */ 1, /* new_val= */ 2);
192
193
1
  keys.clear();
194
1
  keys.push_back(std::pair<string, string>("{ int32_value: 1", "int32_value: 2 }"));
195
1
  VerifyTabletRows(client_schema_, keys);
196
197
  // Switch schema to s2
198
1
  SchemaBuilder builder(*tablet()->metadata()->schema());
199
1
  ASSERT_OK(builder.RemoveColumn("c1"));
200
  // NOTE this new 'c1' will have a different id from the previous one
201
  //      so the data added to the previous 'c1' will not be visible.
202
1
  ASSERT_OK(builder.AddNullableColumn("c1", INT32));
203
1
  AlterSchema(builder.Build());
204
1
  Schema s2 = builder.BuildWithoutIds();
205
206
  // Verify that the new 'c1' have the default value
207
1
  keys.clear();
208
1
  keys.push_back(std::pair<string, string>("{ int32_value: 1", "null }"));
209
1
  VerifyTabletRows(s2, keys);
210
1
}
211
212
} // namespace tablet
213
} // namespace yb