view: generalize create_virtual_column and maybe_make_virtual to UDTs.

This commit is contained in:
Kamil Braun
2019-10-21 10:16:05 +02:00
parent 574e1cd514
commit 2ada219f2c

View File

@@ -70,6 +70,7 @@
#include "service/storage_service.hh"
#include "view_info.hh"
#include "view_update_checks.hh"
#include "types/user.hh"
using namespace std::chrono_literals;
@@ -396,15 +397,10 @@ static void maybe_make_virtual(atomic_cell_or_collection& c, const column_defini
throw std::logic_error("Virtual cell has wrong type");
}
c = make_empty(c.as_atomic_cell(*col));
} else {
if (!col->type->is_collection()) {
// TODO: when we support unfrozen UDT (#2201), we will need to
// supported it here too.
throw std::logic_error("Virtual cell is neither atomic nor collection");
}
} else if (col->type->is_collection()) {
auto ctype = static_pointer_cast<const collection_type_impl>(col->type);
if (ctype->is_list()) {
// A list has integers as keys, and values (the list's items).
// A list has timeuuids as keys, and values (the list's items).
// We just need to build a list with the same keys (and liveness
// information), but empty values.
auto ltype = static_cast<const list_type_impl*>(col->type.get());
@@ -428,7 +424,12 @@ static void maybe_make_virtual(atomic_cell_or_collection& c, const column_defini
// A collection can't be anything but a list, map or set...
throw std::logic_error("Virtual cell has unexpected collection type");
}
} else if (col->type->is_user_type()) {
// We leave c unmodified. See the comment in create_virtual_column regarding user types.
} else {
throw std::logic_error("Virtual cell is neither atomic nor collection, nor user type");
}
}
void create_virtual_column(schema_builder& builder, const bytes& name, const data_type& type) {
@@ -436,33 +437,45 @@ void create_virtual_column(schema_builder& builder, const bytes& name, const dat
builder.with_column(name, empty_type, column_kind::regular_column, column_view_virtual::yes);
return;
}
// A multi-cell collection (a frozen collection is a single
// cell and handled handled in the is_atomic() case above).
// A multi-cell collection or user type (a frozen collection
// or user type is a single cell and handled in the is_atomic() case above).
// The virtual version can't be just one cell, it has to be
// itself a collection of cells.
auto ctype = dynamic_pointer_cast<const collection_type_impl>(type);
if (!ctype) {
// TODO: When #2201 is done, we also need to handle here
// unfrozen UDTs.
throw exceptions::invalid_request_exception(format("Unsupported unselected multi-cell non-collection column {} for Materialized View", name));
}
if (ctype->is_list()) {
// A list has ints as keys, and values (the list's items).
// We just need these intss, i.e., a list of empty items.
builder.with_column(name, list_type_impl::get_instance(empty_type, true), column_kind::regular_column, column_view_virtual::yes);
} else if (ctype->is_map()) {
// A map has keys and values. We don't need these values,
// and can use empty values instead.
auto mtype = dynamic_pointer_cast<const map_type_impl>(type);
builder.with_column(name, map_type_impl::get_instance(mtype->get_keys_type(), empty_type, true), column_kind::regular_column, column_view_virtual::yes);
} else if (ctype->is_set()) {
// A set's cell has nothing beyond the keys, so the
// virtual version of a set is, unfortunately, a complete
// copy of the set.
if (type->is_collection()) {
auto ctype = static_pointer_cast<const collection_type_impl>(type);
if (ctype->is_list()) {
// A list has timeuuids as keys, and values (the list's items).
// We just need these timeuuids, i.e., a list of empty items.
builder.with_column(name, list_type_impl::get_instance(empty_type, true),
column_kind::regular_column, column_view_virtual::yes);
} else if (ctype->is_map()) {
// A map has keys and values. We don't need these values,
// and can use empty values instead.
auto mtype = static_pointer_cast<const map_type_impl>(type);
builder.with_column(name, map_type_impl::get_instance(mtype->get_keys_type(), empty_type, true),
column_kind::regular_column, column_view_virtual::yes);
} else if (ctype->is_set()) {
// A set's cell has nothing beyond the keys, so the
// virtual version of a set is, unfortunately, a complete
// copy of the set.
builder.with_column(name, type, column_kind::regular_column, column_view_virtual::yes);
} else {
// A collection can't be anything but a list, map or set...
abort();
}
} else if (type->is_user_type()) {
// FIXME (kbraun): we currently use the original type itself for the virtual version.
// Instead we could try to:
// 1. use a modified UDT with all value types replaced with empty_type,
// which would require creating and storing a completely new type in the DB
// just for the purpose of virtual columns,
// 2. or use a map, which would require the make_empty function above
// to receive both the original type (UDT in this case) and virtual type (map in this case)
// to perform conversion correctly.
builder.with_column(name, type, column_kind::regular_column, column_view_virtual::yes);
} else {
// A collection can't be anything but a list, map or set...
abort();
throw exceptions::invalid_request_exception(
format("Unsupported unselected multi-cell non-collection, non-UDT column {} for Materialized View", name));
}
}