Repository: cassandra Updated Branches: refs/heads/cassandra-3.0 a88985270 -> 153583be5 refs/heads/cassandra-3.X 771a1a2fa -> 206a7bbac refs/heads/trunk 56bc77c4e -> 17bd6adc8
Preserve quoted reserved keyword column names in MV creation Patch by Carl Yeksigian; reviewed by Alex Petrov for CASSANDRA-11803 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/153583be Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/153583be Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/153583be Branch: refs/heads/cassandra-3.0 Commit: 153583be55e2a0bba74102bf1d5fc7a79d314b1f Parents: a889852 Author: Carl Yeksigian <c...@apache.org> Authored: Fri Oct 14 10:12:14 2016 -0400 Committer: Carl Yeksigian <c...@apache.org> Committed: Fri Oct 14 10:28:00 2016 -0400 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../apache/cassandra/cql3/ColumnIdentifier.java | 3 +- src/java/org/apache/cassandra/cql3/Cql.g | 2 + .../apache/cassandra/cql3/ReservedKeywords.java | 118 +++++++++++++++++++ .../org/apache/cassandra/cql3/ViewTest.java | 20 ++++ .../db/ColumnFamilyStoreCQLHelperTest.java | 4 +- 6 files changed, 145 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/153583be/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index f291674..e82eedd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.10 + * Preserve quoted reserved keyword column names in MV creation (CASSANDRA-11803) * nodetool stopdaemon errors out (CASSANDRA-12646) * Split materialized view mutations on build to prevent OOM (CASSANDRA-12268) * mx4j does not work in 3.0.8 (CASSANDRA-12274) http://git-wip-us.apache.org/repos/asf/cassandra/blob/153583be/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java b/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java index 1e25b23..ceb81be 100644 --- a/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java +++ b/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java @@ -362,8 +362,9 @@ public class ColumnIdentifier extends Selectable implements IMeasurableMemory, C public static String maybeQuote(String text) { - if (UNQUOTED_IDENTIFIER.matcher(text).matches()) + if (UNQUOTED_IDENTIFIER.matcher(text).matches() && !ReservedKeywords.isReserved(text)) return text; + return '"' + PATTERN_DOUBLE_QUOTE.matcher(text).replaceAll(Matcher.quoteReplacement("\"\"")) + '"'; } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/153583be/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 d50b979..3123877 100644 --- a/src/java/org/apache/cassandra/cql3/Cql.g +++ b/src/java/org/apache/cassandra/cql3/Cql.g @@ -1634,6 +1634,8 @@ basic_unreserved_keyword returns [String str] ; // Case-insensitive keywords +// When adding a new reserved keyword, add entry to o.a.c.cql3.ReservedKeywords as well +// When adding a new unreserved keyword, add entry to list above K_SELECT: S E L E C T; K_FROM: F R O M; K_AS: A S; http://git-wip-us.apache.org/repos/asf/cassandra/blob/153583be/src/java/org/apache/cassandra/cql3/ReservedKeywords.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/ReservedKeywords.java b/src/java/org/apache/cassandra/cql3/ReservedKeywords.java new file mode 100644 index 0000000..91b7e61 --- /dev/null +++ b/src/java/org/apache/cassandra/cql3/ReservedKeywords.java @@ -0,0 +1,118 @@ +/* + * 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.util.Set; + +import com.google.common.collect.ImmutableSet; + +class ReservedKeywords +{ + private static final String[] reservedKeywords = new String[] + { + "SELECT", + "FROM", + "WHERE", + "AND", + "KEY", + "ENTRIES", + "FULL", + "INSERT", + "UPDATE", + "WITH", + "LIMIT", + "USING", + "USE", + "COUNT", + "SET", + "BEGIN", + "UNLOGGED", + "BATCH", + "APPLY", + "TRUNCATE", + "DELETE", + "IN", + "CREATE", + "KEYSPACE", + "SCHEMA", + "COLUMNFAMILY", + "TABLE", + "MATERIALIZED", + "VIEW", + "INDEX", + "ON", + "TO", + "DROP", + "PRIMARY", + "INTO", + "TIMESTAMP", + "TTL", + "ALTER", + "RENAME", + "ADD", + "ORDER", + "BY", + "ASC", + "DESC", + "ALLOW", + "IF", + "IS", + "GRANT", + "OF", + "REVOKE", + "MODIFY", + "AUTHORIZE", + "DESCRIBE", + "EXECUTE", + "NORECURSIVE", + "ASCII", + "BIGINT", + "BLOB", + "BOOLEAN", + "COUNTER", + "DECIMAL", + "DOUBLE", + "FLOAT", + "INET", + "INT", + "SMALLINT", + "TINYINT", + "TEXT", + "UUID", + "VARCHAR", + "VARINT", + "TIMEUUID", + "TOKEN", + "WRITETIME", + "DATE", + "TIME", + "NULL", + "NOT", + "NAN", + "INFINITY", + "OR", + "REPLACE" }; + + private static final Set<String> reservedSet = ImmutableSet.copyOf(reservedKeywords); + + static boolean isReserved(String text) + { + return reservedSet.contains(text.toUpperCase()); + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/153583be/test/unit/org/apache/cassandra/cql3/ViewTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/ViewTest.java b/test/unit/org/apache/cassandra/cql3/ViewTest.java index c9ef401..a6de756 100644 --- a/test/unit/org/apache/cassandra/cql3/ViewTest.java +++ b/test/unit/org/apache/cassandra/cql3/ViewTest.java @@ -1137,4 +1137,24 @@ public class ViewTest extends CQLTester assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM %s"), row(0, 1, null, "rab")); assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM mv")); } + + @Test + public void testReservedKeywordsInMV() throws Throwable + { + createTable("CREATE TABLE %s (\"token\" int PRIMARY KEY, \"keyspace\" int)"); + + executeNet(protocolVersion, "USE " + keyspace()); + + createView("mv", + "CREATE MATERIALIZED VIEW %s AS" + + " SELECT \"keyspace\", \"token\"" + + " FROM %%s" + + " WHERE \"keyspace\" IS NOT NULL AND \"token\" IS NOT NULL" + + " PRIMARY KEY (\"keyspace\", \"token\")"); + + execute("INSERT INTO %s (\"token\", \"keyspace\") VALUES (?, ?)", 0, 1); + + assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM %s"), row(0, 1)); + assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM mv"), row(1, 0)); + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/153583be/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java b/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java index c2e5cb7..fdcc99c 100644 --- a/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java +++ b/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java @@ -635,10 +635,10 @@ public class ColumnFamilyStoreCQLHelperTest extends CQLTester assertTrue(ColumnFamilyStoreCQLHelper.getCFMetadataAsCQL(cfs.metadata, true).startsWith( "CREATE TABLE IF NOT EXISTS " + DYNAMIC_COMPOSITE + "." + DYNAMIC_COMPOSITE + " (\n" + - "\tkey ascii,\n" + + "\t\"key\" ascii,\n" + "\tcols 'org.apache.cassandra.db.marshal.DynamicCompositeType(a=>org.apache.cassandra.db.marshal.BytesType,b=>org.apache.cassandra.db.marshal.BytesType,c=>org.apache.cassandra.db.marshal.BytesType)',\n" + "\tval ascii,\n" + - "\tPRIMARY KEY (key, cols))\n" + + "\tPRIMARY KEY (\"key\", cols))\n" + "\tWITH ID = " + cfs.metadata.cfId + "\n" + "\tAND COMPACT STORAGE")); }