/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.cassandra.cql3;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.restrictions.Restriction;
import org.apache.cassandra.cql3.restrictions.SingleColumnRestriction;
import org.apache.cassandra.cql3.restrictions.TermSlice;
import org.apache.cassandra.cql3.selection.Selection;
import org.apache.cassandra.cql3.statements.Bound;
import org.apache.cassandra.db.Clustering;
import org.apache.cassandra.db.Columns;
import org.apache.cassandra.db.CompactTables;
import org.apache.cassandra.db.PartitionColumns;
import org.apache.cassandra.db.filter.ColumnFilter;
import org.apache.cassandra.db.filter.RowFilter;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.db.rows.Cell;
import org.apache.cassandra.db.rows.CellPath;
import org.apache.cassandra.db.rows.ComplexColumnData;
import org.apache.cassandra.db.rows.Row;
import org.apache.cassandra.db.rows.RowIterator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Pair;

import static org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
import static org.apache.cassandra.cql3.statements.RequestValidations.checkNotNull;
import static org.apache.cassandra.cql3.statements.RequestValidations.checkTrue;
import static org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest;
import static org.apache.cassandra.cql3.statements.SelectStatement.getComponents;

/**
 * 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`, {@link 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`, {@link 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 {@link 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.
 */
public class SuperColumnCompatibility
{
    // We use an empty value for the 1) this can't conflict with a user-defined column and 2) this actually
    // validate with any comparator which makes it convenient for columnDefinitionComparator().
    public static final ByteBuffer SUPER_COLUMN_MAP_COLUMN = ByteBufferUtil.EMPTY_BYTE_BUFFER;
    public static final String SUPER_COLUMN_MAP_COLUMN_STR = UTF8Type.instance.compose(SUPER_COLUMN_MAP_COLUMN);

    /**
     * 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.
     */
    public static boolean recalculateIsDense(Columns columns)
    {
        return columns.size() == 1 && columns.getComplex(0).name.toString().isEmpty();
    }

    /**
     * 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.
     */
    public static ColumnFilter getColumnFilter(CFMetaData cfm, QueryOptions queryOptions, SuperColumnRestrictions restrictions)
    {
        assert cfm.isSuper() && cfm.isDense();

        ColumnFilter.Builder builder = ColumnFilter.selectionBuilder();
        builder.add(cfm.compactValueColumn());

        if (restrictions.keySliceRestriction != null)
        {
            SingleColumnRestriction.SuperColumnKeySliceRestriction restriction = restrictions.keySliceRestriction;
            TermSlice slice = restriction.slice;

            ByteBuffer start = slice.hasBound(Bound.START) ? slice.bound(Bound.START).bindAndGet(queryOptions) : null;
            ByteBuffer end = slice.hasBound(Bound.END) ? slice.bound(Bound.END).bindAndGet(queryOptions) : null;

            builder.slice(cfm.compactValueColumn(),
                          start == null ? CellPath.BOTTOM : CellPath.create(start),
                          end == null ? CellPath.TOP : CellPath.create(end));
        }
        else if (restrictions.keyEQRestriction != null)
        {
            SingleColumnRestriction.SuperColumnKeyEQRestriction restriction = restrictions.keyEQRestriction;
            ByteBuffer value = restriction.bindValue(queryOptions);
            builder.select(cfm.compactValueColumn(), CellPath.create(value));
        }
        else if (restrictions.keyINRestriction != null)
        {
            SingleColumnRestriction.SuperColumnKeyINRestriction cast = restrictions.keyINRestriction;
            Set<ByteBuffer> keyINRestrictionValues = new TreeSet<ByteBuffer>(((MapType) cfm.compactValueColumn().type).getKeysType());
            keyINRestrictionValues.addAll(cast.getValues(queryOptions));

            for (ByteBuffer value : keyINRestrictionValues)
                builder.select(cfm.compactValueColumn(), CellPath.create(value));
        }
        else if (restrictions.multiEQRestriction != null)
        {
            SingleColumnRestriction.SuperColumnMultiEQRestriction restriction = restrictions.multiEQRestriction;
            ByteBuffer value = restriction.secondValue;
            builder.select(cfm.compactValueColumn(), CellPath.create(value));
        }

        return builder.build();
    }

    /**
     * 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 |
     *
     */
    public static void processPartition(CFMetaData cfm, Selection selection, RowIterator partition, Selection.ResultSetBuilder result, int protocolVersion,
                                        SuperColumnRestrictions restrictions, QueryOptions queryOptions)
    {
        assert cfm.isDense();
        ByteBuffer[] keyComponents = getComponents(cfm, partition.partitionKey());

        int nowInSeconds = FBUtilities.nowInSeconds();
        while (partition.hasNext())
        {
            Row row = partition.next();

            ComplexColumnData ccd = row.getComplexColumnData(cfm.compactValueColumn());

            if (ccd == null)
                continue;

            Iterator<Cell> cellIter = ccd.iterator();

            outer:
            while (cellIter.hasNext())
            {
                Cell cell = cellIter.next();
                ByteBuffer superColumnKey = cell.path().get(0);

                if (restrictions != null)
                {
                    // Slice on SuperColumn key
                    if (restrictions.keySliceRestriction != null)
                    {
                        for (Bound bound : Bound.values())
                        {
                            if (restrictions.keySliceRestriction.hasBound(bound) &&
                                !restrictions.keySliceRestriction.isInclusive(bound))
                            {
                                ByteBuffer excludedValue = restrictions.keySliceRestriction.bindValue(queryOptions);
                                if (excludedValue.equals(superColumnKey))
                                    continue outer;
                            }
                        }
                    }

                    // Multi-column restriction on clustering+SuperColumn key
                    if (restrictions.multiSliceRestriction != null &&
                        cfm.comparator.compare(row.clustering(), new Clustering(restrictions.multiSliceRestriction.firstValue)) == 0)
                    {
                        AbstractType t = ((MapType) cfm.compactValueColumn().type).getKeysType();
                        int cmp = t.compare(superColumnKey, restrictions.multiSliceRestriction.secondValue);

                        if ((cmp == 0 && !restrictions.multiSliceRestriction.trueInclusive) ||     // EQ
                            (restrictions.multiSliceRestriction.hasBound(Bound.END) && cmp > 0) || // LT
                            (restrictions.multiSliceRestriction.hasBound(Bound.START) && cmp < 0)) // GT
                            continue outer;
                    }
                }

                result.newRow(protocolVersion);

                for (ColumnDefinition def : selection.getColumns())
                {
                    if (cfm.isSuperColumnKeyColumn(def))
                    {
                        result.add(superColumnKey);
                    }
                    else if (cfm.isSuperColumnValueColumn(def))
                    {
                        result.add(cell, nowInSeconds);
                    }
                    else
                    {
                        switch (def.kind)
                        {
                            case PARTITION_KEY:
                                result.add(keyComponents[def.position()]);
                                break;
                            case CLUSTERING:
                                result.add(row.clustering().get(def.position()));
                                break;
                            case REGULAR:
                            case STATIC:
                                throw new AssertionError(String.format("Invalid column '%s' found in SuperColumn table", def.name.toString()));
                        }
                    }
                }
            }
        }
    }

    /**
     * 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`.
     */
    public static void prepareInsertOperations(CFMetaData cfm,
                                               List<ColumnIdentifier.Raw> columnNames,
                                               WhereClause.Builder whereClause,
                                               List<Term.Raw> columnValues,
                                               VariableSpecifications boundNames,
                                               Operations operations)
    {
        List<ColumnDefinition> defs = new ArrayList<>(columnNames.size());
        for (int i = 0; i < columnNames.size(); i++)
        {
            ColumnIdentifier id = columnNames.get(i).prepare(cfm);
            defs.add(cfm.getColumnDefinition(id));
        }

        prepareInsertOperations(cfm, defs, boundNames, columnValues, whereClause, operations);
    }

    /**
     * For _dense_ SuperColumn Families.
     *
     * {@link #prepareInsertOperations(CFMetaData, List, VariableSpecifications, List, WhereClause.Builder, Operations)},
     * but for INSERT JSON queries
     */
    public static void prepareInsertJSONOperations(CFMetaData cfm,
                                                   List<ColumnDefinition> defs,
                                                   VariableSpecifications boundNames,
                                                   Json.Prepared prepared,
                                                   WhereClause.Builder whereClause,
                                                   Operations operations)
    {
        List<Term.Raw> columnValues = new ArrayList<>(defs.size());
        for (ColumnDefinition def : defs)
            columnValues.add(prepared.getRawTermForColumn(def));

        prepareInsertOperations(cfm, defs, boundNames, columnValues, whereClause, operations);
    }

    private static void prepareInsertOperations(CFMetaData cfm,
                                                List<ColumnDefinition> defs,
                                                VariableSpecifications boundNames,
                                                List<Term.Raw> columnValues,
                                                WhereClause.Builder whereClause,
                                                Operations operations)
    {
        assert cfm.isDense();
        assert defs.size() == columnValues.size();

        Term.Raw superColumnKey = null;
        Term.Raw superColumnValue = null;

        for (int i = 0, size = defs.size(); i < size; i++)
        {
            ColumnDefinition def = defs.get(i);
            Term.Raw raw = columnValues.get(i);

            if (cfm.isSuperColumnKeyColumn(def))
            {
                superColumnKey = raw;
                collectMarkerSpecifications(raw, boundNames, def);
            }
            else if (cfm.isSuperColumnValueColumn(def))
            {
                superColumnValue = raw;
                collectMarkerSpecifications(raw, boundNames, def);
            }
            else if (def.isPrimaryKeyColumn())
            {
                whereClause.add(new SingleColumnRelation(new ColumnIdentifier.ColumnIdentifierValue(def.name), Operator.EQ, raw));
            }
            else
            {
                throw invalidRequest("Invalid column {} in where clause");
            }
        }

        checkTrue(superColumnValue != null,
                  "Column value is mandatory for SuperColumn tables");
        checkTrue(superColumnKey != null,
                  "Column key is mandatory for SuperColumn tables");

        Operation operation = new Operation.SetElement(superColumnKey, superColumnValue).prepare(cfm.ksName, cfm.compactValueColumn());
        operations.add(operation);
    }

    /**
     * Collect the marker specifications for the bound columns manually, since the operations on a column are
     * converted to the operations on the collection element.
     */
    private static void collectMarkerSpecifications(Term.Raw raw, VariableSpecifications boundNames, ColumnDefinition def)
    {
        if (raw instanceof AbstractMarker.Raw)
            boundNames.add(((AbstractMarker.Raw) raw).bindIndex(), def);
    }

    /**
     * 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'.
     */
    public static WhereClause prepareUpdateOperations(CFMetaData cfm,
                                                      WhereClause whereClause,
                                                      List<Pair<ColumnIdentifier.Raw, Operation.RawUpdate>> updates,
                                                      VariableSpecifications boundNames,
                                                      Operations operations)
    {
        assert cfm.isDense();
        Term.Raw superColumnKey = null;
        Term.Raw superColumnValue = null;

        List<Relation> newRelations = new ArrayList<>(whereClause.relations.size());
        for (int i = 0; i < whereClause.relations.size(); i++)
        {
            SingleColumnRelation relation = (SingleColumnRelation) whereClause.relations.get(i);
            ColumnIdentifier id = relation.getEntity().prepare(cfm);
            ColumnDefinition def = cfm.getColumnDefinition(id);

            if (cfm.isSuperColumnKeyColumn(def))
            {
                superColumnKey = relation.getValue();
                collectMarkerSpecifications(superColumnKey, boundNames, def);
            }
            else
            {
                newRelations.add(relation);
            }
        }

        checkTrue(superColumnKey != null,
                  "Column key is mandatory for SuperColumn tables");

        for (Pair<ColumnIdentifier.Raw, Operation.RawUpdate> entry : updates)
        {
            ColumnIdentifier id = entry.left.prepare(cfm);
            ColumnDefinition def = cfm.getColumnDefinition(id);

            if (!cfm.isSuperColumnValueColumn(def))
                throw invalidRequest("Column `%s` of type `%s` found in SET part", def.name, def.type.asCQL3Type());

            Operation operation;

            if (entry.right instanceof Operation.Addition)
            {
                Operation.Addition op = (Operation.Addition) entry.right;
                superColumnValue = op.value();

                operation = new Operation.ElementAddition(superColumnKey, superColumnValue).prepare(cfm.ksName, cfm.compactValueColumn());
            }
            else if (entry.right instanceof Operation.Substraction)
            {
                Operation.Substraction op = (Operation.Substraction) entry.right;
                superColumnValue = op.value();

                operation = new Operation.ElementSubtraction(superColumnKey, superColumnValue).prepare(cfm.ksName, cfm.compactValueColumn());
            }
            else if (entry.right instanceof Operation.SetValue)
            {
                Operation.SetValue op = (Operation.SetValue) entry.right;
                superColumnValue = op.value();

                operation = new Operation.SetElement(superColumnKey, superColumnValue).prepare(cfm.ksName, cfm.compactValueColumn());
            }
            else
            {
                throw invalidRequest("Invalid operation `%s` on column `%s` of type `%s` found in SET part", entry.right, def.name, def.type.asCQL3Type());
            }

            collectMarkerSpecifications(superColumnValue, boundNames, def);
            operations.add(operation);
        }

        checkTrue(superColumnValue != null,
                  "Column value is mandatory for SuperColumn tables");

        return newRelations.size() != whereClause.relations.size() ? whereClause.copy(newRelations) : 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.
     */
    public static Conditions rebuildLWTColumnConditions(Conditions conditions, CFMetaData cfm, WhereClause whereClause)
    {
        if (conditions.isEmpty() || conditions.isIfExists() || conditions.isIfNotExists())
            return conditions;

        ColumnConditions.Builder builder = ColumnConditions.newBuilder();
        Collection<ColumnCondition> columnConditions = ((ColumnConditions) conditions).columnConditions();

        Pair<ColumnDefinition, Relation> superColumnKeyRelation = SuperColumnCompatibility.getSuperColumnKeyRelation(whereClause.relations, cfm);

        checkNotNull(superColumnKeyRelation,
                     "Lightweight transactions on SuperColumn tables are only supported with supplied SuperColumn key");

        for (ColumnCondition columnCondition : columnConditions)
        {
            checkTrue(cfm.isSuperColumnValueColumn(columnCondition.column),
                      "Lightweight transactions are only supported on the value column of SuperColumn tables");

            Term.Raw value = superColumnKeyRelation.right.getValue();
            Term collectionElemnt = value instanceof AbstractMarker.Raw ?
                                    new Constants.Marker(((AbstractMarker.Raw) value).bindIndex(),
                                                         superColumnKeyRelation.left) :
                                    value.prepare(cfm.ksName, superColumnKeyRelation.left);
            builder.add(ColumnCondition.condition(cfm.compactValueColumn(),
                                                  collectionElemnt,
                                                  columnCondition.value(), columnCondition.operator));
        }

        return builder.build();
    }

    /**
     * Returns a relation on the SuperColumn key
     */
    private static Pair<ColumnDefinition, Relation> getSuperColumnKeyRelation(List<Relation> relations, CFMetaData cfm)
    {
        for (int i = 0; i < relations.size(); i++)
        {
            SingleColumnRelation relation = (SingleColumnRelation) relations.get(i);
            ColumnIdentifier id = relation.getEntity().prepare(cfm);
            ColumnDefinition def = cfm.getColumnDefinition(id);

            if (cfm.isSuperColumnKeyColumn(def))
                return Pair.create(def, relation);
        }
        return null;
    }

    /**
     * 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'.
     */
    public static WhereClause prepareDeleteOperations(CFMetaData cfm,
                                                      WhereClause whereClause,
                                                      VariableSpecifications boundNames,
                                                      Operations operations)
    {
        assert cfm.isDense();
        List<Relation> newRelations = new ArrayList<>(whereClause.relations.size());

        for (int i = 0; i < whereClause.relations.size(); i++)
        {
            Relation orig = whereClause.relations.get(i);

            checkFalse(orig.isMultiColumn(),
                       "Multi-column relations cannot be used in WHERE clauses for UPDATE and DELETE statements: %s", orig);
            checkFalse(orig.onToken(),
                       "Token relations cannot be used in WHERE clauses for UPDATE and DELETE statements: %s", orig);

            SingleColumnRelation relation = (SingleColumnRelation) orig;
            ColumnIdentifier id = relation.getEntity().prepare(cfm);
            ColumnDefinition def = cfm.getColumnDefinition(id);

            if (cfm.isSuperColumnKeyColumn(def))
            {
                Term.Raw value = relation.getValue();

                if (value instanceof AbstractMarker.Raw)
                    boundNames.add(((AbstractMarker.Raw) value).bindIndex(), def);

                Operation operation = new Maps.DiscarderByKey(cfm.compactValueColumn(), value.prepare(cfm.ksName, def));
                operations.add(operation);
            }
            else
            {
                newRelations.add(relation);
            }
        }

        return newRelations.size() != whereClause.relations.size() ? whereClause.copy(newRelations) : whereClause;
    }

    /**
     * Create a column name generator for SuperColumns
     */
    public static CompactTables.DefaultNames columnNameGenerator(List<ColumnDefinition> partitionKeyColumns,
                                                                 List<ColumnDefinition> clusteringColumns,
                                                                 PartitionColumns partitionColumns)
    {
        Set<String> names = new HashSet<>();
        // If the clustering column was renamed, the supercolumn key's default nname still can't be `column1` (SuperColumn
        // key renames are handled separately by looking up an existing column).
        names.add("column1");
        for (ColumnDefinition columnDefinition: partitionKeyColumns)
            names.add(columnDefinition.name.toString());
        for (ColumnDefinition columnDefinition: clusteringColumns)
            names.add(columnDefinition.name.toString());
        for (ColumnDefinition columnDefinition: partitionColumns)
            names.add(columnDefinition.name.toString());

        return CompactTables.defaultNameGenerator(names);
    }

    /**
     * Find a SuperColumn key column if it's available (for example, when it was renamed) or create one with a default name.
     */
    public static ColumnDefinition getSuperCfKeyColumn(CFMetaData cfm, List<ColumnDefinition> clusteringColumns, CompactTables.DefaultNames defaultNames)
    {
        assert cfm.isDense();

        MapType mapType = (MapType) cfm.compactValueColumn().type;
        // Pre CASSANDRA-12373 3.x-created supercolumn family
        if (clusteringColumns.size() == 1)
        {
            // create a new one with a default name
            ColumnIdentifier identifier = ColumnIdentifier.getInterned(defaultNames.defaultClusteringName(), true);
            return new ColumnDefinition(cfm.ksName, cfm.cfName, identifier, mapType.getKeysType(), ColumnDefinition.NO_POSITION, ColumnDefinition.Kind.REGULAR);
        }

        // Upgrade path: table created in 2.x, handle pre-created columns and/or renames.
        assert clusteringColumns.size() == 2 : clusteringColumns;
        ColumnDefinition cd = clusteringColumns.get(1);

        assert cd.type.equals(mapType.getKeysType()) : cd.type + " != " + mapType.getKeysType();
        return new ColumnDefinition(cfm.ksName, cfm.cfName, cd.name, mapType.getKeysType(), ColumnDefinition.NO_POSITION, ColumnDefinition.Kind.REGULAR);
    }

    /**
     * Find a SuperColumn value column if it's available (for example, when it was renamed) or create one with a default name.
     */
    public static ColumnDefinition getSuperCfValueColumn(CFMetaData cfm, PartitionColumns partitionColumns, ColumnDefinition superCfKeyColumn, CompactTables.DefaultNames defaultNames)
    {
        assert cfm.isDense();

        MapType mapType = (MapType) cfm.compactValueColumn().type;
        for (ColumnDefinition def: partitionColumns.regulars)
        {
            if (!def.name.bytes.equals(SUPER_COLUMN_MAP_COLUMN) && def.type.equals(mapType.getValuesType()) && !def.equals(superCfKeyColumn))
                return def;
        }

        ColumnIdentifier identifier = ColumnIdentifier.getInterned(defaultNames.defaultCompactValueName(), true);
        return new ColumnDefinition(cfm.ksName, cfm.cfName, identifier, mapType.getValuesType(), ColumnDefinition.NO_POSITION, ColumnDefinition.Kind.REGULAR);
    }

    /**
     * SuperColumn key is stored in {@link 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 {@link CFMetaData#superCfKeyColumn} as a regular column to be compatible with
     * the storage engine.
     *
     * This remapping is necessary to facilitate the column metadata part.
     */
    public static ColumnDefinition getSuperCfSschemaRepresentation(ColumnDefinition superCfKeyColumn)
    {
        return new ColumnDefinition(superCfKeyColumn.ksName, superCfKeyColumn.cfName, superCfKeyColumn.name, superCfKeyColumn.type, 1, ColumnDefinition.Kind.CLUSTERING);
    }

    public static boolean isSuperColumnMapColumn(ColumnDefinition column)
    {
        return column.isRegular() && column.name.bytes.equals(SuperColumnCompatibility.SUPER_COLUMN_MAP_COLUMN);
    }

    public static ColumnDefinition getCompactValueColumn(PartitionColumns columns)
    {
        for (ColumnDefinition column : columns.regulars)
        {
            if (isSuperColumnMapColumn(column))
                return column;
        }
        throw new AssertionError("Invalid super column table definition, no 'dynamic' map column");
    }

    /**
     * Restrictions are the trickiest part of the SuperColumn integration.
     * See specific docs on each field. For the purpose of this doc, the "default" column names are used,
     * `column2` and `value`. Detailed description and semantics of these fields can be found in this class'
     * header comment.
     */
    public static class SuperColumnRestrictions
    {
        /**
         * Restrictions in the form of:
         *   ... AND (column1, column2) > ('value1', 1)
         * Multi-column restrictions. `column1` will be handled normally by the clustering bounds,
         * and `column2` value has to be "saved" and filtered out in `processPartition`, as there's no
         * direct mapping of multi-column restrictions to clustering + cell path. The first row
         * is special-cased to make sure the semantics of multi-column restrictions are preserved.
         */
        private final SingleColumnRestriction.SuperColumnMultiSliceRestriction multiSliceRestriction;

        /**
         * Restrictions in the form of:
         *   ... AND (column1, column2) = ('value1', 1)
         * Multi-column restriction with EQ does have a direct mapping: `column1` will be handled
         * normally by the clustering bounds, and the `column2` will be special-cased by the
         * {@link #getColumnFilter(CFMetaData, QueryOptions, SuperColumnRestrictions)} as a collection path lookup.
         */
        private final SingleColumnRestriction.SuperColumnMultiEQRestriction multiEQRestriction;

        /**
         * Restrictions in the form of:
         *   ... AND column2 >= 5
         * For non-filtering cases (when the preceding clustering column and a partition key are
         * restricted), will be handled in {@link #getColumnFilter(CFMetaData, QueryOptions, SuperColumnRestrictions)}
         * like an inclusive bounds lookup.
         *
         * For the restrictions taking a form of
         *   ... AND column2 > 5
         * (non-inclusive ones), the items that match `=` will be filtered out
         * by {@link #processPartition(CFMetaData, Selection, RowIterator, Selection.ResultSetBuilder, int, SuperColumnRestrictions, QueryOptions)}
         *
         * Unfortunately, there are no good ways to do it other than here:
         * {@link RowFilter} can't be used in this case, since the complex collection cells are not yet rows by that
         * point.
         * {@link ColumnFilter} (which is used for inclusive slices) can't be changed to support exclusive slices as it would
         * require a protocol change in order to add a Kind. So exclusive slices are a combination of inclusive plus
         * an ad-hoc filter.
         */
        private final SingleColumnRestriction.SuperColumnKeySliceRestriction keySliceRestriction;

        /**
         * Restrictions in the form of:
         *   ... AND column2 IN (1, 2, 3)
         * For non-filtering cases (when the preceeding clustering column and a partition key are
         * restricted), are handled in {@link #getColumnFilter(CFMetaData, QueryOptions, SuperColumnRestrictions)} by
         * adding multiple collection paths to the {@link ColumnFilter}
         */
        private final SingleColumnRestriction.SuperColumnKeyINRestriction keyINRestriction;

        /**
         * Restrictions in the form of:
         *   ... AND column2 = 1
         * For non-filtering cases (when the preceeding clustering column and a partition key are
         * restricted), will be handled by converting the restriction to the column filter on
         * the collection key in {@link #getColumnFilter(CFMetaData, QueryOptions, SuperColumnRestrictions)}
         */
        private final SingleColumnRestriction.SuperColumnKeyEQRestriction keyEQRestriction;

        public SuperColumnRestrictions(Iterator<Restriction> restrictions)
        {
            // In order to keep the fields final, assignments have to be done outside the loop
            SingleColumnRestriction.SuperColumnMultiSliceRestriction multiSliceRestriction = null;
            SingleColumnRestriction.SuperColumnKeySliceRestriction keySliceRestriction = null;
            SingleColumnRestriction.SuperColumnKeyINRestriction keyINRestriction = null;
            SingleColumnRestriction.SuperColumnMultiEQRestriction multiEQRestriction = null;
            SingleColumnRestriction.SuperColumnKeyEQRestriction keyEQRestriction = null;

            while (restrictions.hasNext())
            {
                Restriction restriction = restrictions.next();

                if (restriction instanceof SingleColumnRestriction.SuperColumnMultiSliceRestriction)
                    multiSliceRestriction = (SingleColumnRestriction.SuperColumnMultiSliceRestriction) restriction;
                else if (restriction instanceof SingleColumnRestriction.SuperColumnKeySliceRestriction)
                    keySliceRestriction = (SingleColumnRestriction.SuperColumnKeySliceRestriction) restriction;
                else if (restriction instanceof SingleColumnRestriction.SuperColumnKeyINRestriction)
                    keyINRestriction = (SingleColumnRestriction.SuperColumnKeyINRestriction) restriction;
                else if (restriction instanceof SingleColumnRestriction.SuperColumnMultiEQRestriction)
                    multiEQRestriction = (SingleColumnRestriction.SuperColumnMultiEQRestriction) restriction;
                else if (restriction instanceof SingleColumnRestriction.SuperColumnKeyEQRestriction)
                    keyEQRestriction = (SingleColumnRestriction.SuperColumnKeyEQRestriction) restriction;
            }

            this.multiSliceRestriction = multiSliceRestriction;
            this.keySliceRestriction = keySliceRestriction;
            this.keyINRestriction = keyINRestriction;
            this.multiEQRestriction = multiEQRestriction;
            this.keyEQRestriction = keyEQRestriction;
        }
    }
}
