YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/integration-tests/cql_test_util.h
Line
Count
Source
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
#ifndef YB_INTEGRATION_TESTS_CQL_TEST_UTIL_H
15
#define YB_INTEGRATION_TESTS_CQL_TEST_UTIL_H
16
17
#include <cassandra.h>
18
19
#include <string>
20
21
#include "yb/util/monotime.h"
22
#include "yb/util/result.h"
23
#include "yb/util/status_log.h"
24
25
namespace yb {
26
27
class CassandraJson;
28
class CassandraStatement;
29
30
// Cassandra CPP driver has his own functions to release objects, so we should use them for it.
31
template <class T, void (*Func)(T*)>
32
class FuncDeleter {
33
 public:
34
427k
  void operator()(T* t) const {
35
427k
    if (
t427k
) {
36
427k
      Func(t);
37
427k
    }
38
427k
  }
yb::FuncDeleter<CassIterator_, &(cass_iterator_free)>::operator()(CassIterator_*) const
Line
Count
Source
34
3.01k
  void operator()(T* t) const {
35
3.01k
    if (t) {
36
3.01k
      Func(t);
37
3.01k
    }
38
3.01k
  }
yb::FuncDeleter<CassResult_ const, &(cass_result_free)>::operator()(CassResult_ const*) const
Line
Count
Source
34
148
  void operator()(T* t) const {
35
148
    if (t) {
36
148
      Func(t);
37
148
    }
38
148
  }
yb::FuncDeleter<CassPrepared_ const, &(cass_prepared_free)>::operator()(CassPrepared_ const*) const
Line
Count
Source
34
620
  void operator()(T* t) const {
35
620
    if (t) {
36
620
      Func(t);
37
620
    }
38
620
  }
yb::FuncDeleter<CassFuture_, &(cass_future_free)>::operator()(CassFuture_*) const
Line
Count
Source
34
32.9k
  void operator()(T* t) const {
35
32.9k
    if (
t32.9k
) {
36
32.9k
      Func(t);
37
32.9k
    }
38
32.9k
  }
yb::FuncDeleter<CassStatement_, &(cass_statement_free)>::operator()(CassStatement_*) const
Line
Count
Source
34
391k
  void operator()(T* t) const {
35
391k
    if (
t391k
) {
36
391k
      Func(t);
37
391k
    }
38
391k
  }
39
};
40
41
template <class Out>
42
struct GetCassandraValue {
43
  static CassError Apply(const CassValue* value, Out* out);
44
};
45
46
class CassandraValue {
47
 public:
48
11.7k
  explicit CassandraValue(const CassValue* value) : value_(value) {}
49
50
  template <class Out>
51
10.2k
  void Get(Out* out) const {
52
10.2k
    CHECK_EQ(CASS_OK, GetCassandraValue<Out>::Apply(value_, out));
53
10.2k
  }
void yb::CassandraValue::Get<yb::Slice>(yb::Slice*) const
Line
Count
Source
51
2.86k
  void Get(Out* out) const {
52
2.86k
    CHECK_EQ(CASS_OK, GetCassandraValue<Out>::Apply(value_, out));
53
2.86k
  }
void yb::CassandraValue::Get<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const
Line
Count
Source
51
4.36k
  void Get(Out* out) const {
52
4.36k
    CHECK_EQ(CASS_OK, GetCassandraValue<Out>::Apply(value_, out));
53
4.36k
  }
void yb::CassandraValue::Get<long long>(long long*) const
Line
Count
Source
51
34
  void Get(Out* out) const {
52
34
    CHECK_EQ(CASS_OK, GetCassandraValue<Out>::Apply(value_, out));
53
34
  }
void yb::CassandraValue::Get<int>(int*) const
Line
Count
Source
51
79
  void Get(Out* out) const {
52
79
    CHECK_EQ(CASS_OK, GetCassandraValue<Out>::Apply(value_, out));
53
79
  }
void yb::CassandraValue::Get<CassUuid_>(CassUuid_*) const
Line
Count
Source
51
1.43k
  void Get(Out* out) const {
52
1.43k
    CHECK_EQ(CASS_OK, GetCassandraValue<Out>::Apply(value_, out));
53
1.43k
  }
void yb::CassandraValue::Get<CassInet_>(CassInet_*) const
Line
Count
Source
51
1.48k
  void Get(Out* out) const {
52
1.48k
    CHECK_EQ(CASS_OK, GetCassandraValue<Out>::Apply(value_, out));
53
1.48k
  }
54
55
  template <class Out>
56
10.2k
  Out As() const {
57
10.2k
    Out result;
58
10.2k
    Get(&result);
59
10.2k
    return result;
60
10.2k
  }
yb::Slice yb::CassandraValue::As<yb::Slice>() const
Line
Count
Source
56
2.86k
  Out As() const {
57
2.86k
    Out result;
58
2.86k
    Get(&result);
59
2.86k
    return result;
60
2.86k
  }
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > yb::CassandraValue::As<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >() const
Line
Count
Source
56
4.34k
  Out As() const {
57
4.34k
    Out result;
58
4.34k
    Get(&result);
59
4.34k
    return result;
60
4.34k
  }
long long yb::CassandraValue::As<long long>() const
Line
Count
Source
56
31
  Out As() const {
57
31
    Out result;
58
31
    Get(&result);
59
31
    return result;
60
31
  }
int yb::CassandraValue::As<int>() const
Line
Count
Source
56
66
  Out As() const {
57
66
    Out result;
58
66
    Get(&result);
59
66
    return result;
60
66
  }
CassUuid_ yb::CassandraValue::As<CassUuid_>() const
Line
Count
Source
56
1.43k
  Out As() const {
57
1.43k
    Out result;
58
1.43k
    Get(&result);
59
1.43k
    return result;
60
1.43k
  }
CassInet_ yb::CassandraValue::As<CassInet_>() const
Line
Count
Source
56
1.48k
  Out As() const {
57
1.48k
    Out result;
58
1.48k
    Get(&result);
59
1.48k
    return result;
60
1.48k
  }
61
62
  bool IsNull() const;
63
64
  std::string ToString() const;
65
66
 private:
67
  const CassValue* value_;
68
};
69
70
typedef std::unique_ptr<
71
    CassIterator, FuncDeleter<CassIterator, &cass_iterator_free>> CassIteratorPtr;
72
73
class CassandraRowIterator {
74
 public:
75
1.43k
  explicit CassandraRowIterator(CassIterator* iterator) : cass_iterator_(iterator) {}
76
77
  bool Next();
78
79
  template <class Out>
80
  void Get(Out* out) const {
81
    Value().Get(out);
82
  }
83
84
  CassandraValue Value() const;
85
86
 private:
87
  CassIteratorPtr cass_iterator_;
88
};
89
90
class CassandraRow {
91
 public:
92
1.52k
  explicit CassandraRow(const CassRow* row) : cass_row_(row) {}
93
94
  template <class Out>
95
  void Get(size_t index, Out* out) const {
96
    return Value(index).Get(out);
97
  }
98
99
  CassandraValue Value(size_t index) const;
100
101
  CassandraRowIterator CreateIterator() const;
102
103
  std::string RenderToString(const std::string& separator = ",");
104
105
  void TakeIterator(CassIteratorPtr iterator);
106
107
 private:
108
  const CassRow* cass_row_; // owned by iterator
109
  CassIteratorPtr cass_iterator_;
110
};
111
112
class CassandraIterator {
113
 public:
114
146
  explicit CassandraIterator(CassIterator* iterator) : cass_iterator_(iterator) {}
115
116
  bool Next();
117
118
  CassandraRow Row();
119
120
  void MoveToRow(CassandraRow* row);
121
122
 private:
123
  CassIteratorPtr cass_iterator_;
124
};
125
126
typedef std::unique_ptr<
127
    const CassResult, FuncDeleter<const CassResult, &cass_result_free>> CassResultPtr;
128
129
class CassandraResult {
130
 public:
131
148
  explicit CassandraResult(const CassResult* result) : cass_result_(result) {}
132
133
  CassandraIterator CreateIterator() const;
134
135
  std::string RenderToString(const std::string& line_separator = ";",
136
                             const std::string& value_separator = ",") const;
137
138
 private:
139
  CassResultPtr cass_result_;
140
};
141
142
typedef std::unique_ptr<
143
    const CassPrepared, FuncDeleter<const CassPrepared, &cass_prepared_free>> CassPreparedPtr;
144
145
class CassandraPrepared {
146
 public:
147
  CassandraPrepared() = default;
148
620
  explicit CassandraPrepared(const CassPrepared* prepared) : prepared_(prepared) {}
149
150
  CassandraStatement Bind();
151
152
 private:
153
  CassPreparedPtr prepared_;
154
};
155
156
typedef std::unique_ptr<
157
    CassFuture, FuncDeleter<CassFuture, &cass_future_free>> CassFuturePtr;
158
159
class CassandraFuture {
160
 public:
161
32.9k
  explicit CassandraFuture(CassFuture* future) : future_(future) {}
162
163
  bool Ready() const;
164
165
  CHECKED_STATUS Wait();
166
167
  CHECKED_STATUS WaitFor(MonoDelta duration);
168
169
  CassandraResult Result();
170
171
  CassandraPrepared Prepared();
172
173
 private:
174
  CHECKED_STATUS CheckErrorCode();
175
176
  CassFuturePtr future_;
177
};
178
179
typedef std::unique_ptr<
180
    CassStatement, FuncDeleter<CassStatement, &cass_statement_free>> CassStatementPtr;
181
182
class CassandraStatement {
183
 public:
184
  explicit CassandraStatement(CassStatement* statement)
185
389k
      : cass_statement_(statement) {}
186
187
  explicit CassandraStatement(const std::string& query, size_t parameter_count = 0)
188
1.78k
      : cass_statement_(cass_statement_new(query.c_str(), parameter_count)) {}
189
190
  void SetKeyspace(const std::string& keyspace);
191
192
  void Bind(size_t index, const std::string& v);
193
  void Bind(size_t index, const cass_bool_t& v);
194
  void Bind(size_t index, const cass_float_t& v);
195
  void Bind(size_t index, const cass_double_t& v);
196
  void Bind(size_t index, const cass_int32_t& v);
197
  void Bind(size_t index, const cass_int64_t& v);
198
  void Bind(size_t index, const CassandraJson& v);
199
200
  CassStatement* get() const;
201
202
 private:
203
  friend class CassandraBatch;
204
  friend class CassandraSession;
205
206
  CassStatementPtr cass_statement_;
207
};
208
209
typedef std::unique_ptr<CassBatch, FuncDeleter<CassBatch, &cass_batch_free>> CassBatchPtr;
210
211
class CassandraBatch {
212
 public:
213
  explicit CassandraBatch(CassBatchType type) : cass_batch_(cass_batch_new(type)) {}
214
215
  void Add(CassandraStatement* statement);
216
217
 private:
218
  friend class CassandraSession;
219
220
  CassBatchPtr cass_batch_;
221
};
222
223
struct DeleteSession {
224
  void operator()(CassSession* session) const;
225
};
226
227
typedef std::unique_ptr<CassSession, DeleteSession> CassSessionPtr;
228
229
class CassandraSession {
230
 public:
231
197
  CassandraSession() = default;
232
233
  CHECKED_STATUS Connect(CassCluster* cluster);
234
235
  static Result<CassandraSession> Create(CassCluster* cluster);
236
237
  CHECKED_STATUS Execute(const CassandraStatement& statement);
238
239
  Result<CassandraResult> ExecuteWithResult(const CassandraStatement& statement);
240
241
  CassandraFuture ExecuteGetFuture(const CassandraStatement& statement);
242
243
  CassandraFuture ExecuteGetFuture(const std::string& query);
244
245
  CHECKED_STATUS ExecuteQuery(const std::string& query);
246
247
  template <class... Args>
248
  CHECKED_STATUS ExecuteQueryFormat(const std::string& query, Args&&... args) {
249
    return ExecuteQuery(Format(query, std::forward<Args>(args)...));
250
  }
251
252
  Result<CassandraResult> ExecuteWithResult(const std::string& query);
253
254
  Result<std::string> ExecuteAndRenderToString(const std::string& statement);
255
256
  template <class Action>
257
  CHECKED_STATUS ExecuteAndProcessOneRow(
258
      const CassandraStatement& statement, const Action& action) {
259
    auto result = VERIFY_RESULT(ExecuteWithResult(statement));
260
    auto iterator = result.CreateIterator();
261
    if (!iterator.Next()) {
262
      return STATUS(IllegalState, "Row does not exists");
263
    }
264
    auto row = iterator.Row();
265
    action(row);
266
    if (iterator.Next()) {
267
      return STATUS(IllegalState, "Multiple rows returned");
268
    }
269
    return Status::OK();
270
  }
271
272
  template <class Action>
273
  CHECKED_STATUS ExecuteAndProcessOneRow(const std::string& query, const Action& action) {
274
    return ExecuteAndProcessOneRow(CassandraStatement(query), action);
275
  }
276
277
  template <class T>
278
  Result<T> FetchValue(const std::string& query) {
279
    T result = T();
280
    RETURN_NOT_OK(ExecuteAndProcessOneRow(query, [&result](const CassandraRow& row) {
281
      result = row.Value(0).As<T>();
282
    }));
283
    return result;
284
  }
285
286
  CHECKED_STATUS ExecuteBatch(const CassandraBatch& batch);
287
288
  CassandraFuture SubmitBatch(const CassandraBatch& batch);
289
290
  // If 'local_keyspace' is not empty, creating temporary CassStatement and setting keyspace
291
  // for this statement only. Result CassPrepared will be based on this temporary statement.
292
  Result<CassandraPrepared> Prepare(const std::string& prepare_query,
293
                                    MonoDelta timeout = MonoDelta::kZero,
294
                                    const std::string& local_keyspace = std::string());
295
296
  void Reset();
297
298
 private:
299
  CassSessionPtr cass_session_;
300
};
301
302
YB_STRONGLY_TYPED_BOOL(UsePartitionAwareRouting);
303
304
class CppCassandraDriver {
305
 public:
306
  CppCassandraDriver(
307
      const std::vector<std::string>& hosts, uint16_t port,
308
      UsePartitionAwareRouting use_partition_aware_routing);
309
310
  ~CppCassandraDriver();
311
312
  Result<CassandraSession> CreateSession();
313
314
 private:
315
  CassCluster* cass_cluster_ = nullptr;
316
};
317
318
class CassandraJson {
319
 public:
320
  CassandraJson() = default;
321
  explicit CassandraJson(const std::string& s) : value_(s) {}
322
4
  explicit CassandraJson(std::string&& s) : value_(std::move(s)) {}
323
  explicit CassandraJson(const char* s) : value_(s) {}
324
325
24
  const std::string& value() const {
326
24
    return value_;
327
24
  }
328
329
 private:
330
  std::string value_;
331
};
332
333
inline std::ostream& operator<<(std::ostream& out, const CassandraJson& value) {
334
  return out << value.value();
335
}
336
337
inline bool operator==(const CassandraJson& lhs, const CassandraJson& rhs) {
338
  return lhs.value() == rhs.value();
339
}
340
341
extern const MonoDelta kCassandraTimeOut;
342
extern const std::string kCqlTestKeyspace;
343
344
Result<CassandraSession> EstablishSession(CppCassandraDriver* driver);
345
346
} // namespace yb
347
348
#endif // YB_INTEGRATION_TESTS_CQL_TEST_UTIL_H