package org.apache.cassandra.config;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import org.antlr.runtime.*;
import org.apache.cassandra.cql3.*;
import org.apache.cassandra.cql3.statements.SelectStatement;
import org.apache.cassandra.db.view.View;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
public class ViewDefinition
{
public final String ksName;
public final String viewName;
public final UUID baseTableId;
public final String baseTableName;
public final boolean includeAllColumns;
public final CFMetaData metadata;
public SelectStatement.RawStatement select;
public String whereClause;
public ViewDefinition(ViewDefinition def)
{
this(def.ksName, def.viewName, def.baseTableId, def.baseTableName, def.includeAllColumns, def.select, def.whereClause, def.metadata);
}
public ViewDefinition(String ksName, String viewName, UUID baseTableId, String baseTableName, boolean includeAllColumns, SelectStatement.RawStatement select, String whereClause, CFMetaData metadata)
{
this.ksName = ksName;
this.viewName = viewName;
this.baseTableId = baseTableId;
this.baseTableName = baseTableName;
this.includeAllColumns = includeAllColumns;
this.select = select;
this.whereClause = whereClause;
this.metadata = metadata;
}
public boolean includes(ColumnIdentifier column)
{
return metadata.getColumnDefinition(column) != null;
}
public ViewDefinition copy()
{
return new ViewDefinition(ksName, viewName, baseTableId, baseTableName, includeAllColumns, select, whereClause, metadata.copy());
}
public CFMetaData baseTableMetadata()
{
return Schema.instance.getCFMetaData(baseTableId);
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof ViewDefinition))
return false;
ViewDefinition other = (ViewDefinition) o;
return Objects.equals(ksName, other.ksName)
&& Objects.equals(viewName, other.viewName)
&& Objects.equals(baseTableId, other.baseTableId)
&& Objects.equals(includeAllColumns, other.includeAllColumns)
&& Objects.equals(whereClause, other.whereClause)
&& Objects.equals(metadata, other.metadata);
}
@Override
public int hashCode()
{
return new HashCodeBuilder(29, 1597)
.append(ksName)
.append(viewName)
.append(baseTableId)
.append(includeAllColumns)
.append(whereClause)
.append(metadata)
.toHashCode();
}
@Override
public String toString()
{
return new ToStringBuilder(this)
.append("ksName", ksName)
.append("viewName", viewName)
.append("baseTableId", baseTableId)
.append("baseTableName", baseTableName)
.append("includeAllColumns", includeAllColumns)
.append("whereClause", whereClause)
.append("metadata", metadata)
.toString();
}
public void renameColumn(ColumnIdentifier from, ColumnIdentifier to)
{
metadata.renameColumn(from, to);
List<Relation> relations = whereClauseToRelations(whereClause);
ColumnDefinition.Raw fromRaw = ColumnDefinition.Raw.forQuoted(from.toString());
ColumnDefinition.Raw toRaw = ColumnDefinition.Raw.forQuoted(to.toString());
List<Relation> newRelations = relations.stream()
.map(r -> r.renameIdentifier(fromRaw, toRaw))
.collect(Collectors.toList());
this.whereClause = View.relationsToWhereClause(newRelations);
String rawSelect = View.buildSelectStatement(baseTableName, metadata.allColumns(), whereClause);
this.select = (SelectStatement.RawStatement) QueryProcessor.parseStatement(rawSelect);
}
private static List<Relation> whereClauseToRelations(String whereClause)
{
try
{
List<Relation> relations = CQLFragmentParser.parseAnyUnhandled(CqlParser::whereClause, whereClause).build().relations;
return relations;
}
catch (RecognitionException | SyntaxException exc)
{
throw new RuntimeException("Unexpected error parsing materialized view's where clause while handling column rename: ", exc);
}
}
}