You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by yc...@apache.org on 2021/02/12 05:19:07 UTC

[cassandra] branch trunk updated: Reduce new reserved keywords introduced since 3.0

This is an automated email from the ASF dual-hosted git repository.

ycai pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new b74d737  Reduce new reserved keywords introduced since 3.0
b74d737 is described below

commit b74d7370cc89fa899f47f50c825ddaed2dd05c3f
Author: Jon Meredith <jm...@apple.com>
AuthorDate: Thu Feb 11 13:51:00 2021 -0800

    Reduce new reserved keywords introduced since 3.0
    
    patch by Jon Meredith; reviewed by Alex Petrov, David Capwell, Yifan Cai for CASSANDRA-16439
---
 CHANGES.txt                                        |   1 +
 src/antlr/Parser.g                                 |   5 +
 .../apache/cassandra/cql3/ReservedKeywords.java    |   7 +-
 .../org/apache/cassandra/cql3/KeywordTest.java     | 112 +++++++++++++++++++++
 .../cql3/validation/operations/CreateTest.java     |  21 ----
 5 files changed, 119 insertions(+), 27 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 73bfff3..bc84b5e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0-beta5
+ * Reduce new reserved keywords introduced since 3.0 (CASSANDRA-16439)
  * Improve system tables handling in case of disk failures (CASSANDRA-14793)
  * Add access and datacenters to unreserved keywords (CASSANDRA-16398)
  * Fix nodetool ring, status output when DNS resolution or port printing are in use (CASSANDRA-16283)
diff --git a/src/antlr/Parser.g b/src/antlr/Parser.g
index 3f6f43f..b3ba7b3 100644
--- a/src/antlr/Parser.g
+++ b/src/antlr/Parser.g
@@ -1895,5 +1895,10 @@ basic_unreserved_keyword returns [String str]
         | K_GROUP
         | K_DATACENTERS
         | K_ACCESS
+        | K_DEFAULT
+        | K_MBEAN
+        | K_MBEANS
+        | K_REPLACE
+        | K_UNSET
         ) { $str = $k.text; }
     ;
diff --git a/src/java/org/apache/cassandra/cql3/ReservedKeywords.java b/src/java/org/apache/cassandra/cql3/ReservedKeywords.java
index c5b2202..982aff4 100644
--- a/src/java/org/apache/cassandra/cql3/ReservedKeywords.java
+++ b/src/java/org/apache/cassandra/cql3/ReservedKeywords.java
@@ -84,12 +84,7 @@ public final class ReservedKeywords
                                                      "NOT",
                                                      "NAN",
                                                      "INFINITY",
-                                                     "OR",
-                                                     "REPLACE",
-                                                     "DEFAULT",
-                                                     "UNSET",
-                                                     "MBEAN",
-                                                     "MBEANS"};
+                                                     "OR"};
 
     static final Set<String> reservedSet = ImmutableSet.copyOf(reservedKeywords);
 
diff --git a/test/unit/org/apache/cassandra/cql3/KeywordTest.java b/test/unit/org/apache/cassandra/cql3/KeywordTest.java
new file mode 100644
index 0000000..720bc6a
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/KeywordTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.Arrays;
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import org.apache.cassandra.exceptions.SyntaxException;
+
+@RunWith(Parameterized.class)
+public class KeywordTest extends CQLTester
+{
+    @Parameterized.Parameters(name = "keyword {0} isReserved {1}")
+    public static Collection<Object[]> keywords() {
+        return Arrays.stream(CqlParser.tokenNames)
+                     .filter(k -> k.startsWith("K_"))
+                     .map(k -> {
+                         String keyword = k.substring(2);
+                         return new Object[]{ keyword, ReservedKeywords.isReserved(keyword) };
+                     })
+                     .collect(Collectors.toSet());
+    }
+
+    String keyword;
+    boolean isReserved;
+    public KeywordTest(String keyword, boolean isReserved)
+    {
+        this.keyword = keyword;
+        this.isReserved = isReserved;
+    }
+
+    @Test
+    public void test() throws Throwable
+    {
+        String createStatement = String.format("CREATE TABLE %s.%s (c text, %s text, PRIMARY KEY (c, %s))",
+                                               KEYSPACE, keyword, keyword, keyword, keyword);
+        logger.info(createStatement);
+        if (isReserved)
+        {
+            try
+            {
+                schemaChange(createStatement);
+                Assert.fail(String.format("Reserved keyword %s should not have parsed", keyword));
+            }
+            catch (RuntimeException ignore) // SyntaxException is wrapped by CQLTester
+            {
+                Assert.assertEquals(SyntaxException.class, ignore.getCause().getClass());
+            }
+        }
+        else // not a reserved word
+        {
+            /* Create the table using the keyword as a tablename and column name, then call describe and re-create it
+             * using the create_statement result.
+             */
+            schemaChange(createStatement);
+            String describeStatement = String.format("DESCRIBE TABLE %s.%s", KEYSPACE, keyword);
+            UntypedResultSet rs = execute(describeStatement);
+            UntypedResultSet.Row row = rs.one();
+            String describedCreateStatement = row.getString("create_statement");
+
+            String recreateStatement = describedCreateStatement.replace(KEYSPACE, KEYSPACE_PER_TEST);
+            logger.info(recreateStatement);
+            schemaChange(recreateStatement);
+
+            /* Check it is possible to insert and select from the table/column, with the keyword used in the
+             * where clause
+             */
+            String insertStatement = String.format("INSERT INTO %s.%s(c,%s) VALUES ('x', '%s')",
+                                                   KEYSPACE, keyword, keyword, keyword);
+            logger.info(insertStatement);
+            execute(insertStatement);
+
+            String selectStatement = String.format("SELECT c, %s FROM %s.%s WHERE c = 'x' AND %s >= ''",
+                                                   keyword, KEYSPACE, keyword, keyword);
+            logger.info(selectStatement);
+            rs = execute(selectStatement);
+            row = rs.one();
+            String value = row.getString(keyword.toLowerCase());
+            Assert.assertEquals(keyword, value);
+
+            /* Make a materialized view using the fields (cannot re-use the name as MV must be in same keyspace).
+             * Added as CASSANDRA-11803 motivated adding the reserved/unreserved distinction
+            */
+            String createMV = String.format("CREATE MATERIALIZED VIEW %s.mv_%s AS %s PRIMARY KEY (c, %s)",
+                                            KEYSPACE, keyword, selectStatement, keyword);
+            logger.info(createMV);
+            schemaChange(createMV);
+        }
+    }
+}
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
index 10a4e87..b35b82f 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
@@ -19,20 +19,15 @@ package org.apache.cassandra.cql3.validation.operations;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Set;
 import java.util.UUID;
-import java.util.stream.Collectors;
 
 import org.junit.Test;
 
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.cql3.CQLTester;
-import org.apache.cassandra.cql3.CqlLexer;
 import org.apache.cassandra.cql3.Duration;
-import org.apache.cassandra.cql3.ReservedKeywords;
 import org.apache.cassandra.db.Mutation;
 import org.apache.cassandra.db.partitions.Partition;
 import org.apache.cassandra.exceptions.ConfigurationException;
@@ -688,22 +683,6 @@ public class CreateTest extends CQLTester
                                             + " WITH compression = { 'class' : 'SnappyCompressor', 'unknownOption' : 32 };");
     }
 
-    @Test
-    public void testUseUnreservedKeywordAsColumnName()
-    {
-        Set<String> unreservedKeywords = Arrays.stream(CqlLexer.class.getDeclaredFields())
-                                               .filter(f -> f.getName().startsWith("K_"))
-                                               .map(f -> f.getName().substring(2)) // remove the heading "K_"
-                                               .filter(name -> !ReservedKeywords.isReserved(name.toUpperCase()))
-                                               .collect(Collectors.toSet());
-        for (String colName : unreservedKeywords)
-        {
-            String format = "CREATE TABLE %%s (foo text PRIMARY KEY, %s text);";
-            createTable(KEYSPACE_PER_TEST, String.format(format, colName));
-            createTable(KEYSPACE_PER_TEST, String.format(format, colName.toLowerCase()));
-        }
-    }
-
     private void assertThrowsConfigurationException(String errorMsg, String createStmt)
     {
         try


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org