query-result-set: merge handling of null and missing values

Nothing seems to differentiate a missing and a null value. This patch
then merges the two exception types and now the only method that
throws is get_nonnull. The other methods return nullptr or
std::nullopt as appropriate.

Signed-off-by: Rafael Ávila de Espíndola <espindola@scylladb.com>
This commit is contained in:
Rafael Ávila de Espíndola
2019-04-29 12:37:01 -07:00
parent ee9f3388f6
commit 2770b29036
3 changed files with 20 additions and 26 deletions

View File

@@ -1033,8 +1033,8 @@ static std::map<std::vector<bytes>, const query::result_set_row*> build_row_map(
for (const auto& row: rows) {
std::vector<bytes> key;
for (const auto& column : primary_key) {
const data_value &val = row.get_data_value(column.name_as_text());
key.push_back(val.serialize());
const data_value *val = row.get_data_value(column.name_as_text());
key.push_back(val->serialize());
}
ret.insert(std::pair(std::move(key), &row));
}
@@ -1376,7 +1376,7 @@ lw_shared_ptr<keyspace_metadata> create_keyspace_from_schema_partition(const sch
// We get called from multiple shards with result set originating on only one of them.
// Cannot use copying accessors for "deep" types like map, because we will hit shared_ptr asserts
// (or screw up shared pointers)
const auto& replication = value_cast<map_type_impl::native_type>(row.get_data_value("replication"));
const auto& replication = value_cast<map_type_impl::native_type>(*row.get_data_value("replication"));
std::map<sstring, sstring> strategy_options;
for (auto& p : replication) {

View File

@@ -33,12 +33,7 @@
namespace query {
class no_such_column : public std::runtime_error {
public:
using runtime_error::runtime_error;
};
class null_column_value : public std::runtime_error {
class no_value : public std::runtime_error {
public:
using runtime_error::runtime_error;
};
@@ -56,42 +51,41 @@ public:
bool has(const sstring& column_name) const {
return _cells.count(column_name) > 0;
}
// Look up a deserialized row cell value by column name; throws no_such_column on error
const data_value&
// Look up a deserialized row cell value by column name
const data_value*
get_data_value(const sstring& column_name) const {
auto it = _cells.find(column_name);
if (it == _cells.end()) {
throw no_such_column(column_name);
return nullptr;
}
return it->second;
return &it->second;
}
// Look up a deserialized row cell value by column name; throws no_such_column on error.
// Look up a deserialized row cell value by column name
template<typename T>
std::optional<T>
get(const sstring& column_name) const {
auto&& value = get_data_value(column_name);
if (value.is_null()) {
return std::nullopt;
if (const auto *value = get_ptr<T>(column_name)) {
return std::optional(*value);
}
return std::optional<T>{value_cast<T>(value)};
return std::nullopt;
}
template<typename T>
const T*
get_ptr(const sstring& column_name) const {
auto&& value = get_data_value(column_name);
if (value.is_null()) {
const auto *value = get_data_value(column_name);
if (value == nullptr || value->is_null()) {
return nullptr;
}
return &value_cast<T>(value);
return &value_cast<T>(*value);
}
// throws no_such_column or null_column_value on error
// throws no_value on error
template<typename T>
T get_nonnull(const sstring& column_name) const {
auto v = get_ptr<std::remove_reference_t<T>>(column_name);
if (v) {
return *v;
}
throw null_column_value(column_name);
throw no_value(column_name);
}
const std::unordered_map<sstring, data_value>& cells() const { return _cells; }
friend inline bool operator==(const result_set_row& x, const result_set_row& y);

View File

@@ -38,13 +38,13 @@ row_assertion::matches(const query::result_set_row& row) const {
// FIXME: result_set_row works on sstring column names instead of more general "bytes".
auto ss_name = to_sstring(name);
if (!row.has(ss_name)) {
const data_value* val = row.get_data_value(ss_name);
if (val == nullptr) {
if (!value.is_null()) {
return false;
}
} else {
const data_value& val = row.get_data_value(ss_name);
if (val != value) {
if (*val != value) {
return false;
}
}