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/trunk
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"));
     }

Reply via email to