org.apache.cassandra.cql3

## Class SuperColumnCompatibility

- java.lang.Object
- - org.apache.cassandra.cql3.SuperColumnCompatibility

    public class SuperColumnCompatibility
    extends java.lang.Object

Class incapsulating the helper logic to handle SELECT / UPDATE / INSERT special-cases related to SuperColumn tables in applicable scenarios. SuperColumn families have a special layout and are represented as a Map internally. These tables have two special columns (called `column2` and `value` by default): * `column2`, `CFMetaData.superCfValueColumn`, a key of the SuperColumn map, exposed as a REGULAR column, but stored in schema tables as a CLUSTERING column to make a distinction from the SC value column in case of renames. * `value`, `CFMetaData.compactValueColumn()`, a value of the SuperColumn map, exposed and stored as a REGULAR column These columns have to be translated to this internal representation as key and value, correspondingly. In CQL terms, the SuperColumn families is encoded with: CREATE TABLE super ( key [key_validation_class], super_column_name [comparator], [column_metadata_1] [type1], ..., [column_metadata_n] [type1], "" map<[sub_comparator], [default_validation_class]> PRIMARY KEY (key, super_column_name) ) In other words, every super column is encoded by a row. That row has one column for each defined "column_metadata", but it also has a special map column (whose name is the empty string as this is guaranteed to never conflict with a user-defined "column_metadata") which stores the super column "dynamic" sub-columns. On write path, `column2` and `value` columns are translated to the key and value of the underlying map. During the read, the inverse conversion is done. Deletes are converted into discards by the key in the underlying map. Counters are handled by translating an update to a counter update with a cell path. See `SuperColumnCompatibility.SuperColumnRestrictions` for the details. Since non-dense SuperColumn families do not modify the contents of the internal map through in CQL and do not expose this via CQL either, reads, writes and deletes are handled normally. Sidenote: a _dense_ SuperColumn Familiy is the one that has no added REGULAR columns.

### Nested Class Summary

Nested Classes
`static class` `SuperColumnCompatibility.SuperColumnRestrictions` Restrictions are the trickiest part of the SuperColumn integration.

### Field Summary

Fields
`static java.nio.ByteBuffer` `SUPER_COLUMN_MAP_COLUMN`
`static java.lang.String` `SUPER_COLUMN_MAP_COLUMN_STR`

### Constructor Summary

Constructors
Constructor and Description
`SuperColumnCompatibility()`

### Method Summary

All Methods Static Methods Concrete Methods
`static CompactTables.DefaultNames` `columnNameGenerator(java.util.List<ColumnDefinition> partitionKeyColumns, java.util.List<ColumnDefinition> clusteringColumns, PartitionColumns partitionColumns)` Create a column name generator for SuperColumns
`static ColumnFilter` `getColumnFilter(CFMetaData cfm, QueryOptions queryOptions, SuperColumnCompatibility.SuperColumnRestrictions restrictions)` For _dense_ SuperColumn Families, the supercolumn key column has to be translated to the collection subselection query in order to avoid reading an entire collection and then filtering out the results.
`static ColumnDefinition` `getCompactValueColumn(PartitionColumns columns)`
`static ColumnDefinition` `getSuperCfKeyColumn(CFMetaData cfm, java.util.List<ColumnDefinition> clusteringColumns, CompactTables.DefaultNames defaultNames)` Find a SuperColumn key column if it's available (for example, when it was renamed) or create one with a default name.

`static ColumnDefinition`

`getSuperCfSschemaRepresentation(ColumnDefinition superCfKeyColumn)`
SuperColumn key is stored in `CFMetaData.columnMetadata` as a clustering column (to make sure we can make a distinction between the SuperColumn key and SuperColumn value columns, especially when they have the same type and were renamed), but exposed as `CFMetaData.superCfKeyColumn` as a regular column to be compatible with the storage engine.

`static ColumnDefinition` `getSuperCfValueColumn(CFMetaData cfm, PartitionColumns partitionColumns, ColumnDefinition superCfKeyColumn, CompactTables.DefaultNames defaultNames)` Find a SuperColumn value column if it's available (for example, when it was renamed) or create one with a default name.
`static boolean` `isSuperColumnMapColumn(ColumnDefinition column)`
`static WhereClause` `prepareDeleteOperations(CFMetaData cfm, WhereClause whereClause, VariableSpecifications boundNames, Operations operations)` For _dense_ SuperColumn Families.
`static void` `prepareInsertJSONOperations(CFMetaData cfm, java.util.List<ColumnDefinition> defs, VariableSpecifications boundNames, Json.Prepared prepared, WhereClause.Builder whereClause, Operations operations)` For _dense_ SuperColumn Families.
`static void` `prepareInsertOperations(CFMetaData cfm, java.util.List<ColumnDefinition.Raw> columnNames, WhereClause.Builder whereClause, java.util.List<Term.Raw> columnValues, VariableSpecifications boundNames, Operations operations)` For _dense_ SuperColumn Families.
`static WhereClause` `prepareUpdateOperations(CFMetaData cfm, WhereClause whereClause, java.util.List<Pair<ColumnDefinition.Raw,Operation.RawUpdate>> updates, VariableSpecifications boundNames, Operations operations)` For _dense_ SuperColumn Families.
`static void` `processPartition(CFMetaData cfm, Selection selection, RowIterator partition, Selection.ResultSetBuilder result, ProtocolVersion protocolVersion, SuperColumnCompatibility.SuperColumnRestrictions restrictions, QueryOptions queryOptions)` For _dense_ SuperColumn Families.
`static Conditions` `rebuildLWTColumnConditions(Conditions conditions, CFMetaData cfm, WhereClause whereClause)` Rebuilds LWT conditions on SuperColumn _value_ column.
`static boolean` `recalculateIsDense(Columns columns)` Dense flag might have been incorrectly set if the node was upgraded from 2.x before CASSANDRA-12373.

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

### Field Detail

#### SUPER_COLUMN_MAP_COLUMN

    public static final java.nio.ByteBuffer SUPER_COLUMN_MAP_COLUMN

#### SUPER_COLUMN_MAP_COLUMN_STR

    public static final java.lang.String SUPER_COLUMN_MAP_COLUMN_STR

### Constructor Detail

#### SuperColumnCompatibility

    public SuperColumnCompatibility()

### Method Detail

#### recalculateIsDense

    public static boolean recalculateIsDense(Columns columns)

Dense flag might have been incorrectly set if the node was upgraded from 2.x before CASSANDRA-12373. For 3.x created tables, the flag is set correctly in ThriftConversion code.

#### getColumnFilter

    public static ColumnFilter getColumnFilter(CFMetaData cfm,
                                               QueryOptions queryOptions,
                                               SuperColumnCompatibility.SuperColumnRestrictions restrictions)

For _dense_ SuperColumn Families, the supercolumn key column has to be translated to the collection subselection query in order to avoid reading an entire collection and then filtering out the results.

#### processPartition

    public static void processPartition(CFMetaData cfm,
                                        Selection selection,
                                        RowIterator partition,
                                        Selection.ResultSetBuilder result,
                                        ProtocolVersion protocolVersion,
                                        SuperColumnCompatibility.SuperColumnRestrictions restrictions,
                                        QueryOptions queryOptions)

For _dense_ SuperColumn Families. On read path, instead of writing row per map, we have to write a row per key/value pair in map. For example: | partition-key | clustering-key | { key1: value1, key2: value2 } | Will be translated to: | partition-key | clustering-key | key1 | value1 | | partition-key | clustering-key | key2 | value2 |

#### prepareInsertOperations

    public static void prepareInsertOperations(CFMetaData cfm,
                                               java.util.List<ColumnDefinition.Raw> columnNames,
                                               WhereClause.Builder whereClause,
                                               java.util.List<Term.Raw> columnValues,
                                               VariableSpecifications boundNames,
                                               Operations operations)

For _dense_ SuperColumn Families. On the write path, we have to do combine the columns into a key/value pair: So inserting a row: | partition-key | clustering-key | key1 | value1 | Would result into: | partition-key | clustering-key | {key1: value1} | or adding / overwriting the value for `key1`.

#### prepareInsertJSONOperations

    public static void prepareInsertJSONOperations(CFMetaData cfm,
                                                   java.util.List<ColumnDefinition> defs,
                                                   VariableSpecifications boundNames,
                                                   Json.Prepared prepared,
                                                   WhereClause.Builder whereClause,
                                                   Operations operations)

For _dense_ SuperColumn Families. `prepareInsertOperations(CFMetaData, List, VariableSpecifications, List, WhereClause.Builder, Operations)`, but for INSERT JSON queries

#### prepareUpdateOperations

    public static WhereClause prepareUpdateOperations(CFMetaData cfm,
                                                      WhereClause whereClause,
                                                      java.util.List<Pair<ColumnDefinition.Raw,Operation.RawUpdate>> updates,
                                                      VariableSpecifications boundNames,
                                                      Operations operations)

For _dense_ SuperColumn Families. During UPDATE operation, the update by clustering (with correponding relation in WHERE clause) has to be substituted with an update to the map that backs the given SuperColumn. For example, an update such as: UPDATE ... SET value = 'value1' WHERE key = 'pk' AND column1 = 'ck' AND column2 = 'mk' Will update the value under key 'mk' in the map, backing the SuperColumn, located in the row with clustering 'ck' in the partition with key 'pk'.

#### rebuildLWTColumnConditions

    public static Conditions rebuildLWTColumnConditions(Conditions conditions,
                                                        CFMetaData cfm,
                                                        WhereClause whereClause)

Rebuilds LWT conditions on SuperColumn _value_ column. Conditions have to be changed to correspond the internal representation of SuperColumn value, since it's not a separate column, but a value in a hidden compact value column.

#### prepareDeleteOperations

    public static WhereClause prepareDeleteOperations(CFMetaData cfm,
                                                      WhereClause whereClause,
                                                      VariableSpecifications boundNames,
                                                      Operations operations)

For _dense_ SuperColumn Families. Delete, when the "regular" columns are present, have to be translated into deletion of value in the internal map by key. For example, delete such as: DELETE FROM ... WHERE key = 'pk' AND column1 = 'ck' AND column2 = 'mk' Will delete a value under 'mk' from the map, located in the row with clustering key 'ck' in the partition with key 'pk'.

#### columnNameGenerator

    public static CompactTables.DefaultNames columnNameGenerator(java.util.List<ColumnDefinition> partitionKeyColumns,
                                                                 java.util.List<ColumnDefinition> clusteringColumns,
                                                                 PartitionColumns partitionColumns)

Create a column name generator for SuperColumns

#### getSuperCfKeyColumn

    public static ColumnDefinition getSuperCfKeyColumn(CFMetaData cfm,
                                                       java.util.List<ColumnDefinition> clusteringColumns,
                                                       CompactTables.DefaultNames defaultNames)

Find a SuperColumn key column if it's available (for example, when it was renamed) or create one with a default name.

#### getSuperCfValueColumn

    public static ColumnDefinition getSuperCfValueColumn(CFMetaData cfm,
                                                         PartitionColumns partitionColumns,
                                                         ColumnDefinition superCfKeyColumn,
                                                         CompactTables.DefaultNames defaultNames)

Find a SuperColumn value column if it's available (for example, when it was renamed) or create one with a default name.

#### getSuperCfSschemaRepresentation

    public static ColumnDefinition getSuperCfSschemaRepresentation(ColumnDefinition superCfKeyColumn)

SuperColumn key is stored in `CFMetaData.columnMetadata` as a clustering column (to make sure we can make a distinction between the SuperColumn key and SuperColumn value columns, especially when they have the same type and were renamed), but exposed as `CFMetaData.superCfKeyColumn` as a regular column to be compatible with the storage engine. This remapping is necessary to facilitate the column metadata part.

#### isSuperColumnMapColumn

    public static boolean isSuperColumnMapColumn(ColumnDefinition column)

#### getCompactValueColumn

    public static ColumnDefinition getCompactValueColumn(PartitionColumns columns)