Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.11 d56c64a88 -> 1a83efe20
  refs/heads/trunk 07c11ca45 -> 2304363e4


Reject multiple values for a key in CQL grammar.

Patch by Nachiket Patil; Reviewed by Ariel Weisberg for CASSANDRA-13369


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/1a83efe2
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/1a83efe2
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/1a83efe2

Branch: refs/heads/cassandra-3.11
Commit: 1a83efe2047d0138725d5e102cc40774f3b14641
Parents: d56c64a
Author: Nachiket Patil <nachiket_pa...@apple.com>
Authored: Mon May 8 16:23:13 2017 -0400
Committer: Ariel Weisberg <aweisb...@apple.com>
Committed: Mon May 8 16:25:41 2017 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 src/antlr/Parser.g                              |  5 +++-
 .../apache/cassandra/cql3/CqlParserTest.java    | 30 ++++++++++++++++++++
 .../cql3/validation/operations/AlterTest.java   | 19 +++++++++++++
 .../cql3/validation/operations/CreateTest.java  | 14 +++++++++
 5 files changed, 68 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/1a83efe2/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 6603911..3166780 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.11.0
+ * Reject multiple values for a key in CQL grammar. (CASSANDRA-13369)
  * UDA fails without input rows (CASSANDRA-13399)
  * Fix compaction-stress by using daemonInitialization (CASSANDRA-13188)
  * V5 protocol flags decoding broken (CASSANDRA-13443)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1a83efe2/src/antlr/Parser.g
----------------------------------------------------------------------
diff --git a/src/antlr/Parser.g b/src/antlr/Parser.g
index 3d06dc3..e5b7584 100644
--- a/src/antlr/Parser.g
+++ b/src/antlr/Parser.g
@@ -127,7 +127,10 @@ options {
                 break;
             }
 
-            res.put(((Constants.Literal)entry.left).getRawText(), 
((Constants.Literal)entry.right).getRawText());
+            if (res.put(((Constants.Literal)entry.left).getRawText(), 
((Constants.Literal)entry.right).getRawText()) != null)
+            {
+                addRecognitionError(String.format("Multiple definition for 
property " + ((Constants.Literal)entry.left).getRawText()));
+            }
         }
 
         return res;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1a83efe2/test/unit/org/apache/cassandra/cql3/CqlParserTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/CqlParserTest.java 
b/test/unit/org/apache/cassandra/cql3/CqlParserTest.java
index 4b76dbc..4871c09 100644
--- a/test/unit/org/apache/cassandra/cql3/CqlParserTest.java
+++ b/test/unit/org/apache/cassandra/cql3/CqlParserTest.java
@@ -25,6 +25,7 @@ import org.antlr.runtime.CharStream;
 import org.antlr.runtime.CommonTokenStream;
 import org.antlr.runtime.RecognitionException;
 import org.antlr.runtime.TokenStream;
+import org.apache.cassandra.cql3.statements.PropertyDefinitions;
 
 import static org.junit.Assert.*;
 
@@ -75,6 +76,35 @@ public class CqlParserTest
         assertEquals(0, secondCounter.count);
     }
 
+    @Test
+    public void testDuplicateProperties() throws Exception
+    {
+        parseAndCountErrors("properties = { 'foo' : 'value1', 'bar': 'value2' 
};", 0, (p) -> p.properties(new PropertyDefinitions()));
+        parseAndCountErrors("properties = { 'foo' : 'value1', 'foo': 'value2' 
};", 1, (p) -> p.properties(new PropertyDefinitions()));
+        parseAndCountErrors("foo = 'value1' AND bar = 'value2' };", 0, (p) -> 
p.properties(new PropertyDefinitions()));
+        parseAndCountErrors("foo = 'value1' AND foo = 'value2' };", 1, (p) -> 
p.properties(new PropertyDefinitions()));
+    }
+
+    private void parseAndCountErrors(String cql, int expectedErrors, 
ParserOperation operation) throws RecognitionException
+    {
+        SyntaxErrorCounter counter = new SyntaxErrorCounter();
+        CharStream stream = new ANTLRStringStream(cql);
+        CqlLexer lexer = new CqlLexer(stream);
+        TokenStream tokenStream = new CommonTokenStream(lexer);
+        CqlParser parser = new CqlParser(tokenStream);
+        parser.addErrorListener(counter);
+
+        operation.perform(parser);
+
+        assertEquals(expectedErrors, counter.count);
+    }
+
+    @FunctionalInterface
+    private interface ParserOperation
+    {
+        void perform(CqlParser cqlParser) throws RecognitionException;
+    }
+
     private static final class SyntaxErrorCounter implements ErrorListener
     {
         private int count;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1a83efe2/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java 
b/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
index 2d34967..b0ee566 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
@@ -229,6 +229,25 @@ public class AlterTest extends CQLTester
                                   "max_threshold", "32")));
     }
 
+    @Test
+    public void 
testAlterKeyspaceWithMultipleInstancesOfSameDCThrowsSyntaxException() throws 
Throwable
+    {
+        try
+        {
+            // Create a keyspace
+            execute("CREATE KEYSPACE testABC WITH replication = {'class' : 
'NetworkTopologyStrategy', 'dc1' : 2}");
+
+            // try modifying the keyspace
+            assertInvalidThrow(SyntaxException.class, "ALTER KEYSPACE testABC 
WITH replication = {'class' : 'NetworkTopologyStrategy', 'dc1' : 2, 'dc1' : 3 
}");
+            execute("ALTER KEYSPACE testABC WITH replication = {'class' : 
'NetworkTopologyStrategy', 'dc1' : 3}");
+        }
+        finally
+        {
+            // clean-up
+            execute("DROP KEYSPACE IF EXISTS testABC");
+        }
+    }
+
     /**
      * Test for bug of 5232,
      * migrated from cql_tests.py:TestCQL.alter_bug_test()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1a83efe2/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
----------------------------------------------------------------------
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 bb6ead9..3eaec23 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
@@ -499,6 +499,20 @@ public class CreateTest extends CQLTester
         execute("DROP KEYSPACE testXYZ");
     }
 
+    @Test
+    public void 
testCreateKeyspaceWithMultipleInstancesOfSameDCThrowsException() throws 
Throwable
+    {
+        try
+        {
+            assertInvalidThrow(SyntaxException.class, "CREATE KEYSPACE testABC 
WITH replication = {'class' : 'NetworkTopologyStrategy', 'dc1' : 2, 'dc1' : 3 
}");
+        }
+        finally
+        {
+            // clean-up
+            execute("DROP KEYSPACE IF EXISTS testABC");
+        }
+    }
+
     /**
      * Test create and drop table
      * migrated from cql_tests.py:TestCQL.table_test()


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

Reply via email to