view: generalize create_virtual_column and maybe_make_virtual to UDTs.
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user