You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by al...@apache.org on 2015/09/16 16:35:17 UTC
[6/6] cassandra git commit: Improve MV schema representation
Improve MV schema representation
patch by Carl Yeksigian; reviewed by Aleksey Yeschenko for
CASSANDRA-9921
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/a3a8dbca
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/a3a8dbca
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/a3a8dbca
Branch: refs/heads/cassandra-3.0
Commit: a3a8dbca5cc190caea36c5029d83f02977b6d149
Parents: f542a20
Author: Carl Yeksigian <ca...@apache.org>
Authored: Tue Aug 11 12:01:48 2015 -0400
Committer: Aleksey Yeschenko <al...@apache.org>
Committed: Wed Sep 16 15:34:18 2015 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
...ore-3.0.0-alpha3-55db84c-SNAPSHOT-shaded.jar | Bin 2209303 -> 0 bytes
...ore-3.0.0-alpha3-8bd064d-SNAPSHOT-shaded.jar | Bin 0 -> 2218913 bytes
...iver-internal-only-3.0.0a2.post0-2429ba3.zip | Bin 229078 -> 0 bytes
...iver-internal-only-3.0.0a2.post0-96883eb.zip | Bin 0 -> 230630 bytes
.../org/apache/cassandra/concurrent/Stage.java | 4 +-
.../cassandra/concurrent/StageManager.java | 2 +-
.../org/apache/cassandra/config/CFMetaData.java | 55 +-
.../cassandra/config/DatabaseDescriptor.java | 2 +-
.../config/MaterializedViewDefinition.java | 93 --
.../org/apache/cassandra/config/Schema.java | 111 +-
.../apache/cassandra/config/ViewDefinition.java | 114 ++
src/java/org/apache/cassandra/cql3/Cql.g | 12 +-
.../AlterMaterializedViewStatement.java | 91 --
.../cql3/statements/AlterTableStatement.java | 99 +-
.../cql3/statements/AlterTypeStatement.java | 10 +
.../cql3/statements/AlterViewStatement.java | 94 ++
.../CreateMaterializedViewStatement.java | 286 ----
.../cql3/statements/CreateTriggerStatement.java | 2 +-
.../cql3/statements/CreateViewStatement.java | 321 +++++
.../DropMaterializedViewStatement.java | 92 --
.../cql3/statements/DropTableStatement.java | 21 +-
.../cql3/statements/DropTypeStatement.java | 2 +-
.../cql3/statements/DropViewStatement.java | 93 ++
.../cql3/statements/ModificationStatement.java | 38 +-
.../cql3/statements/SelectStatement.java | 6 +-
.../cql3/statements/TruncateStatement.java | 2 +-
.../apache/cassandra/db/ColumnFamilyStore.java | 18 +-
src/java/org/apache/cassandra/db/Keyspace.java | 20 +-
.../org/apache/cassandra/db/SystemKeyspace.java | 72 +-
src/java/org/apache/cassandra/db/WriteType.java | 2 +-
.../db/compaction/CompactionManager.java | 4 +-
.../cassandra/db/compaction/OperationType.java | 2 +-
.../cassandra/db/view/MaterializedView.java | 749 ----------
.../db/view/MaterializedViewBuilder.java | 215 ---
.../db/view/MaterializedViewManager.java | 241 ----
.../db/view/MaterializedViewUtils.java | 109 --
src/java/org/apache/cassandra/db/view/View.java | 682 +++++++++
.../apache/cassandra/db/view/ViewBuilder.java | 214 +++
.../apache/cassandra/db/view/ViewManager.java | 271 ++++
.../org/apache/cassandra/db/view/ViewUtils.java | 109 ++
.../cassandra/dht/ByteOrderedPartitioner.java | 2 +-
.../dht/OrderPreservingPartitioner.java | 2 +-
.../cassandra/metrics/MVWriteMetrics.java | 42 -
.../cassandra/metrics/ViewWriteMetrics.java | 42 +
.../cassandra/schema/KeyspaceMetadata.java | 52 +-
.../cassandra/schema/MaterializedViews.java | 149 --
.../apache/cassandra/schema/SchemaKeyspace.java | 292 ++--
src/java/org/apache/cassandra/schema/Views.java | 171 +++
.../cassandra/service/CassandraDaemon.java | 11 +-
.../cassandra/service/MigrationListener.java | 14 +
.../cassandra/service/MigrationManager.java | 62 +-
.../apache/cassandra/service/StartupChecks.java | 2 +-
.../apache/cassandra/service/StorageProxy.java | 60 +-
.../cassandra/service/StorageService.java | 18 +-
.../cassandra/streaming/StreamReceiveTask.java | 15 +-
.../cassandra/thrift/CassandraServer.java | 19 +-
.../cassandra/thrift/ThriftConversion.java | 8 +-
.../utils/NativeSSTableLoaderClient.java | 82 +-
.../cql3/MaterializedViewLongTest.java | 188 ---
.../org/apache/cassandra/cql3/ViewLongTest.java | 188 +++
.../unit/org/apache/cassandra/SchemaLoader.java | 2 +-
.../config/DatabaseDescriptorTest.java | 2 +-
.../cassandra/cql3/MaterializedViewTest.java | 1251 ----------------
.../org/apache/cassandra/cql3/ViewTest.java | 1355 ++++++++++++++++++
.../db/view/MaterializedViewUtilsTest.java | 115 --
.../apache/cassandra/db/view/ViewUtilsTest.java | 115 ++
.../apache/cassandra/dht/LengthPartitioner.java | 2 +-
.../org/apache/cassandra/hints/HintTest.java | 2 +-
.../schema/LegacySchemaMigratorTest.java | 3 +
70 files changed, 4484 insertions(+), 4041 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index c688615..b213260 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
3.0.0-rc1
+ * Improve MV schema representation (CASSANDRA-9921)
* Add flag to enable/disable coordinator batchlog for MV writes (CASSANDRA-10230)
* Update cqlsh COPY for new internal driver serialization interface (CASSANDRA-10318)
* Give index implementations more control over rebuild operations (CASSANDRA-10312)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/lib/cassandra-driver-core-3.0.0-alpha3-55db84c-SNAPSHOT-shaded.jar
----------------------------------------------------------------------
diff --git a/lib/cassandra-driver-core-3.0.0-alpha3-55db84c-SNAPSHOT-shaded.jar b/lib/cassandra-driver-core-3.0.0-alpha3-55db84c-SNAPSHOT-shaded.jar
deleted file mode 100644
index 385d947..0000000
Binary files a/lib/cassandra-driver-core-3.0.0-alpha3-55db84c-SNAPSHOT-shaded.jar and /dev/null differ
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/lib/cassandra-driver-core-3.0.0-alpha3-8bd064d-SNAPSHOT-shaded.jar
----------------------------------------------------------------------
diff --git a/lib/cassandra-driver-core-3.0.0-alpha3-8bd064d-SNAPSHOT-shaded.jar b/lib/cassandra-driver-core-3.0.0-alpha3-8bd064d-SNAPSHOT-shaded.jar
new file mode 100644
index 0000000..fc5d2f0
Binary files /dev/null and b/lib/cassandra-driver-core-3.0.0-alpha3-8bd064d-SNAPSHOT-shaded.jar differ
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/lib/cassandra-driver-internal-only-3.0.0a2.post0-2429ba3.zip
----------------------------------------------------------------------
diff --git a/lib/cassandra-driver-internal-only-3.0.0a2.post0-2429ba3.zip b/lib/cassandra-driver-internal-only-3.0.0a2.post0-2429ba3.zip
deleted file mode 100644
index 435c5e1..0000000
Binary files a/lib/cassandra-driver-internal-only-3.0.0a2.post0-2429ba3.zip and /dev/null differ
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/lib/cassandra-driver-internal-only-3.0.0a2.post0-96883eb.zip
----------------------------------------------------------------------
diff --git a/lib/cassandra-driver-internal-only-3.0.0a2.post0-96883eb.zip b/lib/cassandra-driver-internal-only-3.0.0a2.post0-96883eb.zip
new file mode 100644
index 0000000..e55b4c3
Binary files /dev/null and b/lib/cassandra-driver-internal-only-3.0.0a2.post0-96883eb.zip differ
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/concurrent/Stage.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/concurrent/Stage.java b/src/java/org/apache/cassandra/concurrent/Stage.java
index a57587c..ccb1565 100644
--- a/src/java/org/apache/cassandra/concurrent/Stage.java
+++ b/src/java/org/apache/cassandra/concurrent/Stage.java
@@ -27,7 +27,7 @@ public enum Stage
READ,
MUTATION,
COUNTER_MUTATION,
- MATERIALIZED_VIEW_MUTATION,
+ VIEW_MUTATION,
GOSSIP,
REQUEST_RESPONSE,
ANTI_ENTROPY,
@@ -61,7 +61,7 @@ public enum Stage
return "internal";
case MUTATION:
case COUNTER_MUTATION:
- case MATERIALIZED_VIEW_MUTATION:
+ case VIEW_MUTATION:
case READ:
case REQUEST_RESPONSE:
case READ_REPAIR:
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/concurrent/StageManager.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/concurrent/StageManager.java b/src/java/org/apache/cassandra/concurrent/StageManager.java
index ee1fbe5..a2ad892 100644
--- a/src/java/org/apache/cassandra/concurrent/StageManager.java
+++ b/src/java/org/apache/cassandra/concurrent/StageManager.java
@@ -47,7 +47,7 @@ public class StageManager
{
stages.put(Stage.MUTATION, multiThreadedLowSignalStage(Stage.MUTATION, getConcurrentWriters()));
stages.put(Stage.COUNTER_MUTATION, multiThreadedLowSignalStage(Stage.COUNTER_MUTATION, getConcurrentCounterWriters()));
- stages.put(Stage.MATERIALIZED_VIEW_MUTATION, multiThreadedLowSignalStage(Stage.MATERIALIZED_VIEW_MUTATION, getConcurrentMaterializedViewWriters()));
+ stages.put(Stage.VIEW_MUTATION, multiThreadedLowSignalStage(Stage.VIEW_MUTATION, getConcurrentViewWriters()));
stages.put(Stage.READ, multiThreadedLowSignalStage(Stage.READ, getConcurrentReaders()));
stages.put(Stage.REQUEST_RESPONSE, multiThreadedLowSignalStage(Stage.REQUEST_RESPONSE, FBUtilities.getAvailableProcessors()));
stages.put(Stage.INTERNAL_RESPONSE, multiThreadedStage(Stage.INTERNAL_RESPONSE, FBUtilities.getAvailableProcessors()));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java
index a26b19d..cf1dbbf 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -62,7 +62,7 @@ public final class CFMetaData
{
public enum Flag
{
- SUPER, COUNTER, DENSE, COMPOUND, VIEW
+ SUPER, COUNTER, DENSE, COMPOUND
}
private static final Logger logger = LoggerFactory.getLogger(CFMetaData.class);
@@ -79,7 +79,7 @@ public final class CFMetaData
private final boolean isCompound;
private final boolean isSuper;
private final boolean isCounter;
- private final boolean isMaterializedView;
+ private final boolean isView;
private final boolean isIndex;
@@ -94,7 +94,6 @@ public final class CFMetaData
private volatile AbstractType<?> keyValidator = BytesType.instance;
private volatile Map<ByteBuffer, DroppedColumn> droppedColumns = new HashMap<>();
private volatile Triggers triggers = Triggers.none();
- private volatile MaterializedViews materializedViews = MaterializedViews.none();
private volatile Indexes indexes = Indexes.none();
/*
@@ -219,12 +218,6 @@ public final class CFMetaData
return this;
}
- public CFMetaData materializedViews(MaterializedViews prop)
- {
- materializedViews = prop;
- return this;
- }
-
public CFMetaData indexes(Indexes indexes)
{
this.indexes = indexes;
@@ -238,7 +231,7 @@ public final class CFMetaData
boolean isCounter,
boolean isDense,
boolean isCompound,
- boolean isMaterializedView,
+ boolean isView,
List<ColumnDefinition> partitionKeyColumns,
List<ColumnDefinition> clusteringColumns,
PartitionColumns partitionColumns,
@@ -252,7 +245,7 @@ public final class CFMetaData
this.isCompound = isCompound;
this.isSuper = isSuper;
this.isCounter = isCounter;
- this.isMaterializedView = isMaterializedView;
+ this.isView = isView;
EnumSet<Flag> flags = EnumSet.noneOf(Flag.class);
if (isSuper)
@@ -263,8 +256,6 @@ public final class CFMetaData
flags.add(Flag.DENSE);
if (isCompound)
flags.add(Flag.COMPOUND);
- if (isMaterializedView)
- flags.add(Flag.VIEW);
this.flags = Sets.immutableEnumSet(flags);
isIndex = cfName.contains(".");
@@ -307,16 +298,6 @@ public final class CFMetaData
this.compactValueColumn = CompactTables.getCompactValueColumn(partitionColumns, isSuper());
}
- public MaterializedViews getMaterializedViews()
- {
- return materializedViews;
- }
-
- public boolean hasMaterializedViews()
- {
- return !materializedViews.isEmpty();
- }
-
public Indexes getIndexes()
{
return indexes;
@@ -329,7 +310,7 @@ public final class CFMetaData
boolean isCompound,
boolean isSuper,
boolean isCounter,
- boolean isMaterializedView,
+ boolean isView,
List<ColumnDefinition> columns,
IPartitioner partitioner)
{
@@ -363,7 +344,7 @@ public final class CFMetaData
isCounter,
isDense,
isCompound,
- isMaterializedView,
+ isView,
partitions,
clusterings,
builder.build(),
@@ -464,7 +445,7 @@ public final class CFMetaData
isCounter(),
isDense(),
isCompound(),
- isMaterializedView(),
+ isView(),
copy(partitionKeyColumns),
copy(clusteringColumns),
copy(partitionColumns),
@@ -481,7 +462,7 @@ public final class CFMetaData
isCounter,
isDense,
isCompound,
- isMaterializedView,
+ isView,
copy(partitionKeyColumns),
copy(clusteringColumns),
copy(partitionColumns),
@@ -511,7 +492,6 @@ public final class CFMetaData
return newCFMD.params(oldCFMD.params)
.droppedColumns(new HashMap<>(oldCFMD.droppedColumns))
.triggers(oldCFMD.triggers)
- .materializedViews(oldCFMD.materializedViews)
.indexes(oldCFMD.indexes);
}
@@ -702,7 +682,6 @@ public final class CFMetaData
&& Objects.equal(columnMetadata, other.columnMetadata)
&& Objects.equal(droppedColumns, other.droppedColumns)
&& Objects.equal(triggers, other.triggers)
- && Objects.equal(materializedViews, other.materializedViews)
&& Objects.equal(indexes, other.indexes);
}
@@ -720,7 +699,6 @@ public final class CFMetaData
.append(columnMetadata)
.append(droppedColumns)
.append(triggers)
- .append(materializedViews)
.append(indexes)
.toHashCode();
}
@@ -731,7 +709,8 @@ public final class CFMetaData
*/
public boolean reload()
{
- return apply(SchemaKeyspace.createTableFromName(ksName, cfName));
+ return apply(isView ? SchemaKeyspace.createViewFromName(ksName, cfName).metadata
+ : SchemaKeyspace.createTableFromName(ksName, cfName));
}
/**
@@ -766,7 +745,6 @@ public final class CFMetaData
droppedColumns = cfm.droppedColumns;
triggers = cfm.triggers;
- materializedViews = cfm.materializedViews;
indexes = cfm.indexes;
logger.debug("application result is {}", this);
@@ -1070,9 +1048,9 @@ public final class CFMetaData
return isCompound;
}
- public boolean isMaterializedView()
+ public boolean isView()
{
- return isMaterializedView;
+ return isView;
}
public Serializers serializers()
@@ -1121,7 +1099,6 @@ public final class CFMetaData
.append("columnMetadata", columnMetadata.values())
.append("droppedColumns", droppedColumns)
.append("triggers", triggers)
- .append("materializedViews", materializedViews)
.append("indexes", indexes)
.toString();
}
@@ -1134,7 +1111,7 @@ public final class CFMetaData
private final boolean isCompound;
private final boolean isSuper;
private final boolean isCounter;
- private final boolean isMaterializedView;
+ private final boolean isView;
private IPartitioner partitioner;
private UUID tableId;
@@ -1144,7 +1121,7 @@ public final class CFMetaData
private final List<Pair<ColumnIdentifier, AbstractType>> staticColumns = new ArrayList<>();
private final List<Pair<ColumnIdentifier, AbstractType>> regularColumns = new ArrayList<>();
- private Builder(String keyspace, String table, boolean isDense, boolean isCompound, boolean isSuper, boolean isCounter, boolean isMaterializedView)
+ private Builder(String keyspace, String table, boolean isDense, boolean isCompound, boolean isSuper, boolean isCounter, boolean isView)
{
this.keyspace = keyspace;
this.table = table;
@@ -1152,7 +1129,7 @@ public final class CFMetaData
this.isCompound = isCompound;
this.isSuper = isSuper;
this.isCounter = isCounter;
- this.isMaterializedView = isMaterializedView;
+ this.isView = isView;
this.partitioner = DatabaseDescriptor.getPartitioner();
}
@@ -1296,7 +1273,7 @@ public final class CFMetaData
isCounter,
isDense,
isCompound,
- isMaterializedView,
+ isView,
partitions,
clusterings,
builder.build(),
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index ed220b8..7553c92 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -1143,7 +1143,7 @@ public class DatabaseDescriptor
return conf.concurrent_counter_writes;
}
- public static int getConcurrentMaterializedViewWriters()
+ public static int getConcurrentViewWriters()
{
return conf.concurrent_materialized_view_writes;
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/config/MaterializedViewDefinition.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/MaterializedViewDefinition.java b/src/java/org/apache/cassandra/config/MaterializedViewDefinition.java
deleted file mode 100644
index 90fa35c..0000000
--- a/src/java/org/apache/cassandra/config/MaterializedViewDefinition.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.config;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.cassandra.cql3.ColumnIdentifier;
-
-public class MaterializedViewDefinition
-{
- public final String baseCfName;
- public final String viewName;
- // The order of partititon columns and clustering columns is important, so we cannot switch these two to sets
- public final List<ColumnIdentifier> partitionColumns;
- public final List<ColumnIdentifier> clusteringColumns;
- public final Set<ColumnIdentifier> included;
- public final boolean includeAll;
-
- public MaterializedViewDefinition(MaterializedViewDefinition def)
- {
- this(def.baseCfName, def.viewName, new ArrayList<>(def.partitionColumns), new ArrayList<>(def.clusteringColumns), new HashSet<>(def.included));
- }
-
- /**
- * @param baseCfName Name of the column family from which this view is based
- * @param viewName Name of the view
- * @param partitionColumns List of all of the partition columns, in the order they are defined
- * @param clusteringColumns List of all of the clustering columns, in the order they are defined
- * @param included
- */
- public MaterializedViewDefinition(String baseCfName, String viewName, List<ColumnIdentifier> partitionColumns, List<ColumnIdentifier> clusteringColumns, Set<ColumnIdentifier> included)
- {
- assert partitionColumns != null && !partitionColumns.isEmpty();
- assert included != null;
- this.baseCfName = baseCfName;
- this.viewName = viewName;
- this.partitionColumns = partitionColumns;
- this.clusteringColumns = clusteringColumns;
- this.includeAll = included.isEmpty();
- this.included = included;
- }
-
- /**
- * @return true if the view specified by this definition will include the column, false otherwise
- */
- public boolean includes(ColumnIdentifier column)
- {
- return includeAll
- || partitionColumns.contains(column)
- || clusteringColumns.contains(column)
- || included.contains(column);
- }
-
- /**
- * Replace the column {@param from} with {@param to} in this materialized view definition's partition,
- * clustering, or included columns.
- */
- public void renameColumn(ColumnIdentifier from, ColumnIdentifier to)
- {
- if (!includeAll && included.contains(from))
- {
- included.remove(from);
- included.add(to);
- }
-
- int partitionIndex = partitionColumns.indexOf(from);
- if (partitionIndex >= 0)
- partitionColumns.set(partitionIndex, to);
-
- int clusteringIndex = clusteringColumns.indexOf(from);
- if (clusteringIndex >= 0)
- clusteringColumns.set(clusteringIndex, to);
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/config/Schema.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/Schema.java b/src/java/org/apache/cassandra/config/Schema.java
index 7cc8394..bcde978 100644
--- a/src/java/org/apache/cassandra/config/Schema.java
+++ b/src/java/org/apache/cassandra/config/Schema.java
@@ -147,6 +147,7 @@ public class Schema
public Schema load(KeyspaceMetadata keyspaceDef)
{
keyspaceDef.tables.forEach(this::load);
+ keyspaceDef.views.forEach(this::load);
setKeyspaceMetadata(keyspaceDef);
return this;
}
@@ -224,8 +225,11 @@ public class Schema
public CFMetaData getCFMetaData(String keyspaceName, String cfName)
{
assert keyspaceName != null;
+
KeyspaceMetadata ksm = keyspaces.get(keyspaceName);
- return (ksm == null) ? null : ksm.tables.getNullable(cfName);
+ return ksm == null
+ ? null
+ : ksm.getTableOrViewNullable(cfName);
}
/**
@@ -246,6 +250,13 @@ public class Schema
return getCFMetaData(descriptor.ksname, descriptor.cfname);
}
+ public ViewDefinition getView(String keyspaceName, String viewName)
+ {
+ assert keyspaceName != null;
+ KeyspaceMetadata ksm = keyspaces.get(keyspaceName);
+ return (ksm == null) ? null : ksm.views.getNullable(viewName);
+ }
+
/**
* Get metadata about keyspace by its name
*
@@ -274,12 +285,12 @@ public class Schema
*
* @return metadata about ColumnFamilies the belong to the given keyspace
*/
- public Tables getTables(String keyspaceName)
+ public Iterable<CFMetaData> getTablesAndViews(String keyspaceName)
{
assert keyspaceName != null;
KeyspaceMetadata ksm = keyspaces.get(keyspaceName);
assert ksm != null;
- return ksm.tables;
+ return ksm.tablesAndViews();
}
/**
@@ -356,6 +367,24 @@ public class Schema
}
/**
+ * Load individual View Definition to the schema
+ * (to make View lookup faster)
+ *
+ * @param view The View definition to load
+ */
+ public void load(ViewDefinition view)
+ {
+ CFMetaData cfm = view.metadata;
+ Pair<String, String> key = Pair.create(cfm.ksName, cfm.cfName);
+
+ if (cfIdMap.containsKey(key))
+ throw new RuntimeException(String.format("Attempting to load already loaded view %s.%s", cfm.ksName, cfm.cfName));
+
+ logger.debug("Adding {} to cfIdMap", cfm);
+ cfIdMap.put(key, cfm.cfId);
+ }
+
+ /**
* Used for ColumnFamily data eviction out from the schema
*
* @param cfm The ColumnFamily Definition to evict
@@ -365,6 +394,16 @@ public class Schema
cfIdMap.remove(Pair.create(cfm.ksName, cfm.cfName));
}
+ /**
+ * Used for View eviction from the schema
+ *
+ * @param view The view definition to evict
+ */
+ private void unload(ViewDefinition view)
+ {
+ cfIdMap.remove(Pair.create(view.ksName, view.viewName));
+ }
+
/* Function helpers */
/**
@@ -442,6 +481,7 @@ public class Schema
{
KeyspaceMetadata ksm = getKSMetaData(keyspaceName);
ksm.tables.forEach(this::unload);
+ ksm.views.forEach(this::unload);
clearKeyspaceMetadata(ksm);
}
@@ -468,13 +508,13 @@ public class Schema
KeyspaceMetadata ksm = Schema.instance.getKSMetaData(ksName);
String snapshotName = Keyspace.getTimestampedSnapshotName(ksName);
- CompactionManager.instance.interruptCompactionFor(ksm.tables, true);
+ CompactionManager.instance.interruptCompactionFor(ksm.tablesAndViews(), true);
Keyspace keyspace = Keyspace.open(ksm.name);
// remove all cfs from the keyspace instance.
List<UUID> droppedCfs = new ArrayList<>();
- for (CFMetaData cfm : ksm.tables)
+ for (CFMetaData cfm : ksm.tablesAndViews())
{
ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(cfm.cfName);
@@ -556,6 +596,67 @@ public class Schema
CommitLog.instance.forceRecycleAllSegments(Collections.singleton(cfm.cfId));
}
+ public void addView(ViewDefinition view)
+ {
+ assert getCFMetaData(view.ksName, view.viewName) == null;
+
+ update(view.ksName, ks ->
+ {
+ load(view);
+
+ // make sure it's init-ed w/ the old definitions first,
+ // since we're going to call initCf on the new one manually
+ Keyspace.open(view.ksName);
+
+ return ks.withSwapped(ks.views.with(view));
+ });
+
+ Keyspace.open(view.ksName).initCf(view.metadata.cfId, view.viewName, true);
+ Keyspace.open(view.ksName).viewManager.reload();
+ MigrationManager.instance.notifyCreateView(view);
+ }
+
+ public void updateView(String ksName, String viewName)
+ {
+ Optional<ViewDefinition> optView = getKSMetaData(ksName).views.get(viewName);
+ assert optView.isPresent();
+ ViewDefinition view = optView.get();
+ boolean columnsDidChange = view.metadata.reload();
+
+ Keyspace keyspace = Keyspace.open(view.ksName);
+ keyspace.getColumnFamilyStore(view.viewName).reload();
+ Keyspace.open(view.ksName).viewManager.update(view.viewName);
+ MigrationManager.instance.notifyUpdateView(view, columnsDidChange);
+ }
+
+ public void dropView(String ksName, String viewName)
+ {
+ KeyspaceMetadata oldKsm = getKSMetaData(ksName);
+ assert oldKsm != null;
+ ColumnFamilyStore cfs = Keyspace.open(ksName).getColumnFamilyStore(viewName);
+ assert cfs != null;
+
+ // make sure all the indexes are dropped, or else.
+ cfs.indexManager.markAllIndexesRemoved();
+
+ // reinitialize the keyspace.
+ ViewDefinition view = oldKsm.views.get(viewName).get();
+ KeyspaceMetadata newKsm = oldKsm.withSwapped(oldKsm.views.without(viewName));
+
+ unload(view);
+ setKeyspaceMetadata(newKsm);
+
+ CompactionManager.instance.interruptCompactionFor(Collections.singleton(view.metadata), true);
+
+ if (DatabaseDescriptor.isAutoSnapshot())
+ cfs.snapshot(Keyspace.getTimestampedSnapshotName(cfs.name));
+ Keyspace.open(ksName).dropCf(view.metadata.cfId);
+ Keyspace.open(ksName).viewManager.reload();
+ MigrationManager.instance.notifyDropView(view);
+
+ CommitLog.instance.forceRecycleAllSegments(Collections.singleton(view.metadata.cfId));
+ }
+
public void addType(UserType ut)
{
update(ut.keyspace, ks -> ks.withSwapped(ks.types.with(ut)));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/config/ViewDefinition.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/ViewDefinition.java b/src/java/org/apache/cassandra/config/ViewDefinition.java
new file mode 100644
index 0000000..39695b9
--- /dev/null
+++ b/src/java/org/apache/cassandra/config/ViewDefinition.java
@@ -0,0 +1,114 @@
+/*
+ * 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.config;
+
+import java.util.Objects;
+import java.util.UUID;
+
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import org.apache.cassandra.cql3.ColumnIdentifier;
+
+public class ViewDefinition
+{
+ public final String ksName;
+ public final String viewName;
+ public final UUID baseTableId;
+ public final boolean includeAllColumns;
+ // The order of partititon columns and clustering columns is important, so we cannot switch these two to sets
+ public final CFMetaData metadata;
+
+ public ViewDefinition(ViewDefinition def)
+ {
+ this(def.ksName, def.viewName, def.baseTableId, def.includeAllColumns, def.metadata);
+ }
+
+ /**
+ * @param viewName Name of the view
+ * @param baseTableId Internal ID of the table which this view is based off of
+ * @param includeAllColumns Whether to include all columns or not
+ */
+ public ViewDefinition(String ksName, String viewName, UUID baseTableId, boolean includeAllColumns, CFMetaData metadata)
+ {
+ this.ksName = ksName;
+ this.viewName = viewName;
+ this.baseTableId = baseTableId;
+ this.includeAllColumns = includeAllColumns;
+ this.metadata = metadata;
+ }
+
+ /**
+ * @return true if the view specified by this definition will include the column, false otherwise
+ */
+ public boolean includes(ColumnIdentifier column)
+ {
+ return metadata.getColumnDefinition(column) != null;
+ }
+
+ public ViewDefinition copy()
+ {
+ return new ViewDefinition(ksName, viewName, baseTableId, includeAllColumns, 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(metadata, other.metadata);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return new HashCodeBuilder(29, 1597)
+ .append(ksName)
+ .append(viewName)
+ .append(baseTableId)
+ .append(includeAllColumns)
+ .append(metadata)
+ .toHashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return new ToStringBuilder(this)
+ .append("ksName", ksName)
+ .append("viewName", viewName)
+ .append("baseTableId", baseTableId)
+ .append("includeAllColumns", includeAllColumns)
+ .append("metadata", metadata)
+ .toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/cql3/Cql.g
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g
index 87bec4b..f6d54f5 100644
--- a/src/java/org/apache/cassandra/cql3/Cql.g
+++ b/src/java/org/apache/cassandra/cql3/Cql.g
@@ -740,7 +740,7 @@ indexIdent returns [IndexTarget.Raw id]
* PRIMARY KEY (<pkColumns>)
* WITH <property> = <value> AND ...;
*/
-createMaterializedViewStatement returns [CreateMaterializedViewStatement expr]
+createMaterializedViewStatement returns [CreateViewStatement expr]
@init {
boolean ifNotExists = false;
List<ColumnIdentifier.Raw> partitionKeys = new ArrayList<>();
@@ -753,7 +753,7 @@ createMaterializedViewStatement returns [CreateMaterializedViewStatement expr]
'(' '(' k1=cident { partitionKeys.add(k1); } ( ',' kn=cident { partitionKeys.add(kn); } )* ')' ( ',' c1=cident { compositeKeys.add(c1); } )* ')'
| '(' k1=cident { partitionKeys.add(k1); } ( ',' cn=cident { compositeKeys.add(cn); } )* ')'
)
- { $expr = new CreateMaterializedViewStatement(cf, basecf, sclause, wclause, partitionKeys, compositeKeys, ifNotExists); }
+ { $expr = new CreateViewStatement(cf, basecf, sclause, wclause, partitionKeys, compositeKeys, ifNotExists); }
( K_WITH cfamProperty[expr.properties] ( K_AND cfamProperty[expr.properties] )*)?
;
@@ -820,14 +820,14 @@ alterTableStatement returns [AlterTableStatement expr]
}
;
-alterMaterializedViewStatement returns [AlterMaterializedViewStatement expr]
+alterMaterializedViewStatement returns [AlterViewStatement expr]
@init {
TableAttributes attrs = new TableAttributes();
}
: K_ALTER K_MATERIALIZED K_VIEW name=columnFamilyName
K_WITH properties[attrs]
{
- $expr = new AlterMaterializedViewStatement(name, attrs);
+ $expr = new AlterViewStatement(name, attrs);
}
;
@@ -886,10 +886,10 @@ dropIndexStatement returns [DropIndexStatement expr]
/**
* DROP MATERIALIZED VIEW [IF EXISTS] <view_name>
*/
-dropMaterializedViewStatement returns [DropMaterializedViewStatement expr]
+dropMaterializedViewStatement returns [DropViewStatement expr]
@init { boolean ifExists = false; }
: K_DROP K_MATERIALIZED K_VIEW (K_IF K_EXISTS { ifExists = true; } )? cf=columnFamilyName
- { $expr = new DropMaterializedViewStatement(cf, ifExists); }
+ { $expr = new DropViewStatement(cf, ifExists); }
;
/**
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/cql3/statements/AlterMaterializedViewStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterMaterializedViewStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterMaterializedViewStatement.java
deleted file mode 100644
index bc4ba11..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/AlterMaterializedViewStatement.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.statements;
-
-import org.apache.cassandra.auth.Permission;
-import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.cql3.CFName;
-import org.apache.cassandra.db.view.MaterializedView;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.RequestValidationException;
-import org.apache.cassandra.exceptions.UnauthorizedException;
-import org.apache.cassandra.schema.TableParams;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.MigrationManager;
-import org.apache.cassandra.transport.Event;
-
-import static org.apache.cassandra.thrift.ThriftValidation.validateColumnFamily;
-
-public class AlterMaterializedViewStatement extends SchemaAlteringStatement
-{
- private final TableAttributes attrs;
-
- public AlterMaterializedViewStatement(CFName name, TableAttributes attrs)
- {
- super(name);
- this.attrs = attrs;
- }
-
- public void checkAccess(ClientState state) throws UnauthorizedException, InvalidRequestException
- {
- CFMetaData baseTable = MaterializedView.findBaseTable(keyspace(), columnFamily());
- if (baseTable != null)
- state.hasColumnFamilyAccess(keyspace(), baseTable.cfName, Permission.ALTER);
- }
-
- public void validate(ClientState state)
- {
- // validated in announceMigration()
- }
-
- public boolean announceMigration(boolean isLocalOnly) throws RequestValidationException
- {
- CFMetaData meta = validateColumnFamily(keyspace(), columnFamily());
- if (!meta.isMaterializedView())
- throw new InvalidRequestException("Cannot use ALTER MATERIALIZED VIEW on Table");
-
- CFMetaData cfm = meta.copy();
-
- if (attrs == null)
- throw new InvalidRequestException("ALTER MATERIALIZED VIEW WITH invoked, but no parameters found");
-
- attrs.validate();
-
- TableParams params = attrs.asAlteredTableParams(cfm.params);
- if (params.gcGraceSeconds == 0)
- {
- throw new InvalidRequestException("Cannot alter gc_grace_seconds of a materialized view to 0, since this " +
- "value is used to TTL undelivered updates. Setting gc_grace_seconds too " +
- "low might cause undelivered updates to expire before being replayed.");
- }
- cfm.params(params);
-
- MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
- return true;
- }
-
- public String toString()
- {
- return String.format("AlterMaterializedViewStatement(name=%s)", cfName);
- }
-
- public Event.SchemaChange changeEvent()
- {
- return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
index fac0c53..af9a75c 100644
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
@@ -19,6 +19,8 @@ package org.apache.cassandra.cql3.statements;
import java.util.*;
+import com.google.common.collect.Iterables;
+
import org.apache.cassandra.auth.Permission;
import org.apache.cassandra.config.*;
import org.apache.cassandra.cql3.CFName;
@@ -27,6 +29,7 @@ import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.CounterColumnType;
+import org.apache.cassandra.db.view.View;
import org.apache.cassandra.exceptions.*;
import org.apache.cassandra.schema.IndexMetadata;
import org.apache.cassandra.schema.Indexes;
@@ -81,7 +84,7 @@ public class AlterTableStatement extends SchemaAlteringStatement
public boolean announceMigration(boolean isLocalOnly) throws RequestValidationException
{
CFMetaData meta = validateColumnFamily(keyspace(), columnFamily());
- if (meta.isMaterializedView())
+ if (meta.isView())
throw new InvalidRequestException("Cannot use ALTER TABLE on Materialized View");
CFMetaData cfm = meta.copy();
@@ -95,7 +98,8 @@ public class AlterTableStatement extends SchemaAlteringStatement
def = cfm.getColumnDefinition(columnName);
}
- List<CFMetaData> materializedViewUpdates = null;
+ List<ViewDefinition> viewUpdates = null;
+ Iterable<ViewDefinition> views = View.findAll(keyspace(), columnFamily());
switch (oType)
{
@@ -156,19 +160,20 @@ public class AlterTableStatement extends SchemaAlteringStatement
? ColumnDefinition.staticDef(cfm, columnName.bytes, type)
: ColumnDefinition.regularDef(cfm, columnName.bytes, type));
- // Adding a column to a table which has an include all materialized view requires the column to be added
- // to the materialized view as well
- for (MaterializedViewDefinition mv : cfm.getMaterializedViews())
+ // Adding a column to a table which has an include all view requires the column to be added to the view
+ // as well
+ if (!isStatic)
{
- if (mv.includeAll)
+ for (ViewDefinition view : views)
{
- CFMetaData indexCfm = Schema.instance.getCFMetaData(keyspace(), mv.viewName).copy();
- indexCfm.addColumnDefinition(isStatic
- ? ColumnDefinition.staticDef(indexCfm, columnName.bytes, type)
- : ColumnDefinition.regularDef(indexCfm, columnName.bytes, type));
- if (materializedViewUpdates == null)
- materializedViewUpdates = new ArrayList<>();
- materializedViewUpdates.add(indexCfm);
+ if (view.includeAllColumns)
+ {
+ ViewDefinition viewCopy = view.copy();
+ viewCopy.metadata.addColumnDefinition(ColumnDefinition.regularDef(viewCopy.metadata, columnName.bytes, type));
+ if (viewUpdates == null)
+ viewUpdates = new ArrayList<>();
+ viewUpdates.add(viewCopy);
+ }
}
}
break;
@@ -221,17 +226,16 @@ public class AlterTableStatement extends SchemaAlteringStatement
// In any case, we update the column definition
cfm.addOrReplaceColumnDefinition(def.withNewType(validatorType));
- // We have to alter the schema of the materialized view table as well; it doesn't affect the definition however
- for (MaterializedViewDefinition mv : cfm.getMaterializedViews())
+ // We have to alter the schema of the view table as well; it doesn't affect the definition however
+ for (ViewDefinition view : views)
{
- if (!mv.includes(columnName)) continue;
- // We have to use the pre-adjusted CFM, otherwise we can't resolve the Index
- CFMetaData indexCfm = Schema.instance.getCFMetaData(keyspace(), mv.viewName).copy();
- indexCfm.addOrReplaceColumnDefinition(def.withNewType(validatorType));
-
- if (materializedViewUpdates == null)
- materializedViewUpdates = new ArrayList<>();
- materializedViewUpdates.add(indexCfm);
+ if (!view.includes(columnName)) continue;
+ ViewDefinition viewCopy = view.copy();
+ viewCopy.metadata.addOrReplaceColumnDefinition(def.withNewType(validatorType));
+
+ if (viewUpdates == null)
+ viewUpdates = new ArrayList<>();
+ viewUpdates.add(viewCopy);
}
break;
@@ -276,20 +280,16 @@ public class AlterTableStatement extends SchemaAlteringStatement
}
cfm.indexes(allIndexes);
- // If a column is dropped which is the target of a materialized view,
- // then we need to drop the view.
- // If a column is dropped which was selected into a materialized view,
- // we need to drop that column from the included materialzied view table
- // and definition.
+ // If a column is dropped which is included in a view, we don't allow the drop to take place.
boolean rejectAlter = false;
StringBuilder builder = new StringBuilder();
- for (MaterializedViewDefinition mv : cfm.getMaterializedViews())
+ for (ViewDefinition view : views)
{
- if (!mv.includes(columnName)) continue;
+ if (!view.includes(columnName)) continue;
if (rejectAlter)
builder.append(',');
rejectAlter = true;
- builder.append(mv.viewName);
+ builder.append(view.viewName);
}
if (rejectAlter)
throw new InvalidRequestException(String.format("Cannot drop column %s, depended on by materialized views (%s.{%s})",
@@ -304,7 +304,7 @@ public class AlterTableStatement extends SchemaAlteringStatement
TableParams params = attrs.asAlteredTableParams(cfm.params);
- if (cfm.hasMaterializedViews() && params.gcGraceSeconds == 0)
+ if (!Iterables.isEmpty(views) && params.gcGraceSeconds == 0)
{
throw new InvalidRequestException("Cannot alter gc_grace_seconds of the base table of a " +
"materialized view to 0, since this value is used to TTL " +
@@ -326,36 +326,31 @@ public class AlterTableStatement extends SchemaAlteringStatement
ColumnIdentifier to = entry.getValue().prepare(cfm);
cfm.renameColumn(from, to);
- // If the materialized view includes a renamed column, it must be renamed in the index table and the definition.
- for (MaterializedViewDefinition mv : cfm.getMaterializedViews())
+ // If the view includes a renamed column, it must be renamed in the view table and the definition.
+ for (ViewDefinition view : views)
{
- if (!mv.includes(from)) continue;
-
- CFMetaData indexCfm = Schema.instance.getCFMetaData(keyspace(), mv.viewName).copy();
- ColumnIdentifier indexFrom = entry.getKey().prepare(indexCfm);
- ColumnIdentifier indexTo = entry.getValue().prepare(indexCfm);
- indexCfm.renameColumn(indexFrom, indexTo);
+ if (!view.includes(from)) continue;
- MaterializedViewDefinition mvCopy = new MaterializedViewDefinition(mv);
- mvCopy.renameColumn(from, to);
+ ViewDefinition viewCopy = view.copy();
+ ColumnIdentifier viewFrom = entry.getKey().prepare(viewCopy.metadata);
+ ColumnIdentifier viewTo = entry.getValue().prepare(viewCopy.metadata);
+ viewCopy.metadata.renameColumn(viewFrom, viewTo);
- cfm.materializedViews(cfm.getMaterializedViews().replace(mvCopy));
-
- if (materializedViewUpdates == null)
- materializedViewUpdates = new ArrayList<>();
- materializedViewUpdates.add(indexCfm);
+ if (viewUpdates == null)
+ viewUpdates = new ArrayList<>();
+ viewUpdates.add(viewCopy);
}
}
break;
}
- if (materializedViewUpdates != null)
+ MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
+
+ if (viewUpdates != null)
{
- for (CFMetaData mvUpdates : materializedViewUpdates)
- MigrationManager.announceColumnFamilyUpdate(mvUpdates, false, isLocalOnly);
+ for (ViewDefinition viewUpdate : viewUpdates)
+ MigrationManager.announceViewUpdate(viewUpdate, isLocalOnly);
}
-
- MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
return true;
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
index 4298c22..e176cec 100644
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
@@ -115,6 +115,16 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement
MigrationManager.announceColumnFamilyUpdate(copy, false, isLocalOnly);
}
+ for (ViewDefinition view : ksm.views)
+ {
+ ViewDefinition copy = view.copy();
+ boolean modified = false;
+ for (ColumnDefinition def : copy.metadata.allColumns())
+ modified |= updateDefinition(copy.metadata, def, toUpdate.keyspace, toUpdate.name, updated);
+ if (modified)
+ MigrationManager.announceViewUpdate(copy, isLocalOnly);
+ }
+
// Other user types potentially using the updated type
for (UserType ut : ksm.types)
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/cql3/statements/AlterViewStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterViewStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterViewStatement.java
new file mode 100644
index 0000000..e578c4f
--- /dev/null
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterViewStatement.java
@@ -0,0 +1,94 @@
+/*
+ * 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.statements;
+
+import org.apache.cassandra.auth.Permission;
+import org.apache.cassandra.config.CFMetaData;
+import org.apache.cassandra.config.Schema;
+import org.apache.cassandra.config.ViewDefinition;
+import org.apache.cassandra.cql3.CFName;
+import org.apache.cassandra.db.view.View;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.exceptions.RequestValidationException;
+import org.apache.cassandra.exceptions.UnauthorizedException;
+import org.apache.cassandra.schema.TableParams;
+import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.service.MigrationManager;
+import org.apache.cassandra.transport.Event;
+
+import static org.apache.cassandra.thrift.ThriftValidation.validateColumnFamily;
+
+public class AlterViewStatement extends SchemaAlteringStatement
+{
+ private final TableAttributes attrs;
+
+ public AlterViewStatement(CFName name, TableAttributes attrs)
+ {
+ super(name);
+ this.attrs = attrs;
+ }
+
+ public void checkAccess(ClientState state) throws UnauthorizedException, InvalidRequestException
+ {
+ CFMetaData baseTable = View.findBaseTable(keyspace(), columnFamily());
+ if (baseTable != null)
+ state.hasColumnFamilyAccess(keyspace(), baseTable.cfName, Permission.ALTER);
+ }
+
+ public void validate(ClientState state)
+ {
+ // validated in announceMigration()
+ }
+
+ public boolean announceMigration(boolean isLocalOnly) throws RequestValidationException
+ {
+ CFMetaData meta = validateColumnFamily(keyspace(), columnFamily());
+ if (!meta.isView())
+ throw new InvalidRequestException("Cannot use ALTER MATERIALIZED VIEW on Table");
+
+ ViewDefinition view = Schema.instance.getView(keyspace(), columnFamily());
+ ViewDefinition viewCopy = view.copy();
+
+ if (attrs == null)
+ throw new InvalidRequestException("ALTER MATERIALIZED VIEW WITH invoked, but no parameters found");
+
+ attrs.validate();
+
+ TableParams params = attrs.asAlteredTableParams(view.metadata.params);
+ if (params.gcGraceSeconds == 0)
+ {
+ throw new InvalidRequestException("Cannot alter gc_grace_seconds of a materialized view to 0, since this " +
+ "value is used to TTL undelivered updates. Setting gc_grace_seconds too " +
+ "low might cause undelivered updates to expire before being replayed.");
+ }
+ view.metadata.params(params);
+
+ MigrationManager.announceViewUpdate(viewCopy, isLocalOnly);
+ return true;
+ }
+
+ public String toString()
+ {
+ return String.format("AlterViewStatement(name=%s)", cfName);
+ }
+
+ public Event.SchemaChange changeEvent()
+ {
+ return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/cql3/statements/CreateMaterializedViewStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateMaterializedViewStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateMaterializedViewStatement.java
deleted file mode 100644
index dee0577..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/CreateMaterializedViewStatement.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * 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.statements;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import com.google.common.collect.Iterables;
-
-import org.apache.cassandra.auth.Permission;
-import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.config.ColumnDefinition;
-import org.apache.cassandra.config.MaterializedViewDefinition;
-import org.apache.cassandra.cql3.CFName;
-import org.apache.cassandra.cql3.ColumnIdentifier;
-import org.apache.cassandra.cql3.selection.RawSelector;
-import org.apache.cassandra.cql3.selection.Selectable;
-import org.apache.cassandra.db.view.MaterializedView;
-import org.apache.cassandra.exceptions.AlreadyExistsException;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.exceptions.RequestValidationException;
-import org.apache.cassandra.exceptions.UnauthorizedException;
-import org.apache.cassandra.service.ClientState;
-import org.apache.cassandra.service.ClientWarn;
-import org.apache.cassandra.service.MigrationManager;
-import org.apache.cassandra.thrift.ThriftValidation;
-import org.apache.cassandra.transport.Event;
-
-public class CreateMaterializedViewStatement extends SchemaAlteringStatement
-{
- private final CFName baseName;
- private final List<RawSelector> selectClause;
- private final List<ColumnIdentifier.Raw> notNullWhereClause;
- private final List<ColumnIdentifier.Raw> partitionKeys;
- private final List<ColumnIdentifier.Raw> clusteringKeys;
- public final CFProperties properties = new CFProperties();
- private final boolean ifNotExists;
-
- public CreateMaterializedViewStatement(CFName viewName,
- CFName baseName,
- List<RawSelector> selectClause,
- List<ColumnIdentifier.Raw> notNullWhereClause,
- List<ColumnIdentifier.Raw> partitionKeys,
- List<ColumnIdentifier.Raw> clusteringKeys,
- boolean ifNotExists)
- {
- super(viewName);
- this.baseName = baseName;
- this.selectClause = selectClause;
- this.notNullWhereClause = notNullWhereClause;
- this.partitionKeys = partitionKeys;
- this.clusteringKeys = clusteringKeys;
- this.ifNotExists = ifNotExists;
- }
-
-
- public void checkAccess(ClientState state) throws UnauthorizedException, InvalidRequestException
- {
- if (!baseName.hasKeyspace())
- baseName.setKeyspace(keyspace(), true);
- state.hasColumnFamilyAccess(keyspace(), baseName.getColumnFamily(), Permission.ALTER);
- }
-
- public void validate(ClientState state) throws RequestValidationException
- {
- // We do validation in announceMigration to reduce doubling up of work
- }
-
- public boolean announceMigration(boolean isLocalOnly) throws RequestValidationException
- {
- // We need to make sure that:
- // - primary key includes all columns in base table's primary key
- // - make sure that the select statement does not have anything other than columns
- // and their names match the base table's names
- // - make sure that primary key does not include any collections
- // - make sure there is no where clause in the select statement
- // - make sure there is not currently a table or view
- // - make sure baseTable gcGraceSeconds > 0
-
- properties.validate();
-
- if (properties.useCompactStorage)
- throw new InvalidRequestException("Cannot use 'COMPACT STORAGE' when defining a materialized view");
-
- // We enforce the keyspace because if the RF is different, the logic to wait for a
- // specific replica would break
- if (!baseName.getKeyspace().equals(keyspace()))
- throw new InvalidRequestException("Cannot create a materialized view on a table in a separate keyspace");
-
- CFMetaData cfm = ThriftValidation.validateColumnFamily(baseName.getKeyspace(), baseName.getColumnFamily());
-
- if (cfm.isCounter())
- throw new InvalidRequestException("Materialized views are not supported on counter tables");
-
- if (cfm.isMaterializedView())
- throw new InvalidRequestException("Materialized views cannot be created against other materialized views");
-
- if (cfm.params.gcGraceSeconds == 0)
- {
- throw new InvalidRequestException(String.format("Cannot create materialized view '%s' for base table " +
- "'%s' with gc_grace_seconds of 0, since this value is " +
- "used to TTL undelivered updates. Setting gc_grace_seconds" +
- " too low might cause undelivered updates to expire " +
- "before being replayed.", cfName.getColumnFamily(),
- baseName.getColumnFamily()));
- }
-
- Set<ColumnIdentifier> included = new HashSet<>();
- for (RawSelector selector : selectClause)
- {
- Selectable.Raw selectable = selector.selectable;
- if (selectable instanceof Selectable.WithFieldSelection.Raw)
- throw new InvalidRequestException("Cannot select out a part of type when defining a materialized view");
- if (selectable instanceof Selectable.WithFunction.Raw)
- throw new InvalidRequestException("Cannot use function when defining a materialized view");
- if (selectable instanceof Selectable.WritetimeOrTTL.Raw)
- throw new InvalidRequestException("Cannot use function when defining a materialized view");
- ColumnIdentifier identifier = (ColumnIdentifier) selectable.prepare(cfm);
- if (selector.alias != null)
- throw new InvalidRequestException(String.format("Cannot alias column '%s' as '%s' when defining a materialized view", identifier.toString(), selector.alias.toString()));
-
- ColumnDefinition cdef = cfm.getColumnDefinition(identifier);
-
- if (cdef == null)
- throw new InvalidRequestException("Unknown column name detected in CREATE MATERIALIZED VIEW statement : "+identifier);
-
- if (cdef.isStatic())
- ClientWarn.warn(String.format("Unable to include static column '%s' in Materialized View SELECT statement", identifier));
- else
- included.add(identifier);
- }
-
- Set<ColumnIdentifier.Raw> targetPrimaryKeys = new HashSet<>();
- for (ColumnIdentifier.Raw identifier : Iterables.concat(partitionKeys, clusteringKeys))
- {
- if (!targetPrimaryKeys.add(identifier))
- throw new InvalidRequestException("Duplicate entry found in PRIMARY KEY: "+identifier);
-
- ColumnDefinition cdef = cfm.getColumnDefinition(identifier.prepare(cfm));
-
- if (cdef == null)
- throw new InvalidRequestException("Unknown column name detected in CREATE MATERIALIZED VIEW statement : "+identifier);
-
- if (cfm.getColumnDefinition(identifier.prepare(cfm)).type.isMultiCell())
- throw new InvalidRequestException(String.format("Cannot use MultiCell column '%s' in PRIMARY KEY of materialized view", identifier));
-
- if (cdef.isStatic())
- throw new InvalidRequestException(String.format("Cannot use Static column '%s' in PRIMARY KEY of materialized view", identifier));
- }
-
- Set<ColumnIdentifier> basePrimaryKeyCols = new HashSet<>();
- for (ColumnDefinition definition : Iterables.concat(cfm.partitionKeyColumns(), cfm.clusteringColumns()))
- basePrimaryKeyCols.add(definition.name);
-
- List<ColumnIdentifier> targetClusteringColumns = new ArrayList<>();
- List<ColumnIdentifier> targetPartitionKeys = new ArrayList<>();
- Set<ColumnIdentifier> notNullColumns = new HashSet<>();
- if (notNullWhereClause != null)
- {
- for (ColumnIdentifier.Raw raw : notNullWhereClause)
- {
- notNullColumns.add(raw.prepare(cfm));
- }
- }
-
- // This is only used as an intermediate state; this is to catch whether multiple non-PK columns are used
- boolean hasNonPKColumn = false;
- for (ColumnIdentifier.Raw raw : partitionKeys)
- {
- hasNonPKColumn = getColumnIdentifier(cfm, basePrimaryKeyCols, hasNonPKColumn, raw, targetPartitionKeys, notNullColumns);
- }
-
- for (ColumnIdentifier.Raw raw : clusteringKeys)
- {
- hasNonPKColumn = getColumnIdentifier(cfm, basePrimaryKeyCols, hasNonPKColumn, raw, targetClusteringColumns, notNullColumns);
- }
-
- // We need to include all of the primary key colums from the base table in order to make sure that we do not
- // overwrite values in the materialized view. We cannot support "collapsing" the base table into a smaller
- // number of rows in the view because if we need to generate a tombstone, we have no way of knowing which value
- // is currently being used in the view and whether or not to generate a tombstone.
- // In order to not surprise our users, we require that they include all of the columns. We provide them with
- // a list of all of the columns left to include.
- boolean missingClusteringColumns = false;
- StringBuilder columnNames = new StringBuilder();
- for (ColumnDefinition def : cfm.allColumns())
- {
- if (!def.isPrimaryKeyColumn()) continue;
-
- ColumnIdentifier identifier = def.name;
- if (!targetClusteringColumns.contains(identifier) && !targetPartitionKeys.contains(identifier))
- {
- if (missingClusteringColumns)
- columnNames.append(',');
- else
- missingClusteringColumns = true;
- columnNames.append(identifier);
- }
- }
- if (missingClusteringColumns)
- throw new InvalidRequestException(String.format("Cannot create Materialized View %s without primary key columns from base %s (%s)",
- columnFamily(), baseName.getColumnFamily(), columnNames.toString()));
-
- if (targetPartitionKeys.isEmpty())
- throw new InvalidRequestException("Must select at least a column for a Materialized View");
-
- if (targetClusteringColumns.isEmpty())
- throw new InvalidRequestException("No columns are defined for Materialized View other than primary key");
-
- MaterializedViewDefinition definition = new MaterializedViewDefinition(baseName.getColumnFamily(),
- columnFamily(),
- targetPartitionKeys,
- targetClusteringColumns,
- included);
-
- CFMetaData indexCf = MaterializedView.getCFMetaData(definition, cfm, properties);
- try
- {
- MigrationManager.announceNewColumnFamily(indexCf, isLocalOnly);
- }
- catch (AlreadyExistsException e)
- {
- if (ifNotExists)
- return false;
- throw e;
- }
-
- CFMetaData newCfm = cfm.copy();
- newCfm.materializedViews(newCfm.getMaterializedViews().with(definition));
-
- MigrationManager.announceColumnFamilyUpdate(newCfm, false, isLocalOnly);
-
- return true;
- }
-
- private static boolean getColumnIdentifier(CFMetaData cfm,
- Set<ColumnIdentifier> basePK,
- boolean hasNonPKColumn,
- ColumnIdentifier.Raw raw,
- List<ColumnIdentifier> columns,
- Set<ColumnIdentifier> allowedPKColumns)
- {
- ColumnIdentifier identifier = raw.prepare(cfm);
-
- boolean isPk = basePK.contains(identifier);
- if (!isPk && hasNonPKColumn)
- {
- throw new InvalidRequestException(String.format("Cannot include more than one non-primary key column '%s' in materialized view partition key", identifier));
- }
-
- // We don't need to include the "IS NOT NULL" filter on a non-composite partition key
- // because we will never allow a single partition key to be NULL
- boolean isSinglePartitionKey = cfm.getColumnDefinition(identifier).isPartitionKey()
- && cfm.partitionKeyColumns().size() == 1;
- if (!allowedPKColumns.remove(identifier) && !isSinglePartitionKey)
- {
- throw new InvalidRequestException(String.format("Primary key column '%s' is required to be filtered by 'IS NOT NULL'", identifier));
- }
-
- columns.add(identifier);
- return !isPk;
- }
-
- public Event.SchemaChange changeEvent()
- {
- return new Event.SchemaChange(Event.SchemaChange.Change.CREATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
- }
-}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/a3a8dbca/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
index 706cfea..2589622 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
@@ -59,7 +59,7 @@ public class CreateTriggerStatement extends SchemaAlteringStatement
public void validate(ClientState state) throws RequestValidationException
{
CFMetaData cfm = ThriftValidation.validateColumnFamily(keyspace(), columnFamily());
- if (cfm.isMaterializedView())
+ if (cfm.isView())
throw new InvalidRequestException("Cannot CREATE TRIGGER against a materialized view");
try