\ No newline at end of file
diff --git a/cassandra/src/main/resources/scalate/allAggregates.ssp b/cassandra/src/main/resources/scalate/allAggregates.ssp
new file mode 100644
index 00000000000..f093c507d97
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/allAggregates.ssp
@@ -0,0 +1,68 @@
+<%--
+/*
+* 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.
+*/
+--%>
+
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+#import(java.util.UUID)
+<%@ val allAggregates: Map[(UUID, String), List[AggregateSummary]] %>
+
+
\ No newline at end of file
diff --git a/cassandra/src/main/resources/scalate/allFunctions.ssp b/cassandra/src/main/resources/scalate/allFunctions.ssp
new file mode 100644
index 00000000000..fc756a42aa6
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/allFunctions.ssp
@@ -0,0 +1,68 @@
+<%--
+/*
+* 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.
+*/
+--%>
+
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+#import(java.util.UUID)
+<%@ val allFunctions: Map[(UUID, String), List[FunctionSummary]] %>
+
+
\ No newline at end of file
diff --git a/cassandra/src/main/resources/scalate/allMaterializedViews.ssp b/cassandra/src/main/resources/scalate/allMaterializedViews.ssp
new file mode 100644
index 00000000000..8ffee573a6c
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/allMaterializedViews.ssp
@@ -0,0 +1,68 @@
+<%--
+/*
+* 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.
+*/
+--%>
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+#import(java.util.UUID)
+<%@ val allMVs: Map[(UUID,String),List[MaterializedViewSummary]] %>
+
\ No newline at end of file
diff --git a/cassandra/src/main/resources/scalate/allTables.ssp b/cassandra/src/main/resources/scalate/allTables.ssp
index b363bee6b89..810881ba8ce 100644
--- a/cassandra/src/main/resources/scalate/allTables.ssp
+++ b/cassandra/src/main/resources/scalate/allTables.ssp
@@ -24,7 +24,6 @@
#for (((ksId,ksName), tables) <- allTables)
-
@@ -38,8 +37,6 @@
- #if (tables.nonEmpty)
-
Tables
@@ -52,10 +49,6 @@
- #else
-
No Table
-
- #end
@@ -63,7 +56,6 @@
#end
-
\ No newline at end of file
diff --git a/cassandra/src/main/resources/scalate/allUDTs.ssp b/cassandra/src/main/resources/scalate/allUDTs.ssp
new file mode 100644
index 00000000000..559ef41af5a
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/allUDTs.ssp
@@ -0,0 +1,61 @@
+<%--
+/*
+* 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.
+*/
+--%>
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+#import(java.util.UUID)
+<%@ val allUDTs: Map[(UUID,String),List[String]] %>
+
+ #end
+ #end
\ No newline at end of file
diff --git a/cassandra/src/main/resources/scalate/functionDetails.ssp b/cassandra/src/main/resources/scalate/functionDetails.ssp
new file mode 100644
index 00000000000..7d61400f7a5
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/functionDetails.ssp
@@ -0,0 +1,77 @@
+<%--
+/*
+* 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.
+*/
+--%>
+#import(org.apache.zeppelin.cassandra.MetaDataHierarchy._)
+<%@ val sameNameFunctionDetails: SameNameFunctionDetails %>
+<%@ val withCaption: Boolean%>
+
+ #end
+
\ No newline at end of file
diff --git a/cassandra/src/main/resources/scalate/keyspaceDetails.ssp b/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
index beaf182cd89..c0b9f8f413e 100644
--- a/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
+++ b/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
@@ -46,7 +46,7 @@
+ #if(tableDetails.indices.size > 0)
+
+
+
+
${tableDetails.tableName}'s indices
+
+
+
+
Name
+
Target
+
+
+
+ #for (index <- tableDetails.indices)
+
+
${index.name}
+
${index.target}
+
+ #end
+
+
+
+
+ #end
\ No newline at end of file
diff --git a/cassandra/src/main/resources/scalate/udtDetails.ssp b/cassandra/src/main/resources/scalate/udtDetails.ssp
index 80380a4943d..28858f2b757 100644
--- a/cassandra/src/main/resources/scalate/udtDetails.ssp
+++ b/cassandra/src/main/resources/scalate/udtDetails.ssp
@@ -46,7 +46,7 @@
@@ -342,9 +397,7 @@
II Schema Display
- The schema objects (cluster, keyspace, table & type) are displayed in a tabular format.
- There is a drop-down menu on the top left corner to expand objects details.
- On the top right menu is shown the Icon legend.
+ The schema objects (cluster, keyspace, table, type, view, function & aggregate) are displayed in a tabular format. There is a drop-down menu on the top left corner to expand objects details. On the top right menu is shown the Icon legend.
- It is possible to execute many paragraphs in parallel. However, at the back-end side, we’re still using synchronous queries. Asynchronous execution is only possible when it is possible to return a Future value in the InterpreterResult. It may be an interesting proposal for the Zeppelin project.
+ It is possible to execute many paragraphs in parallel. However, at the back-end side, we’re still using synchronous queries. Asynchronous execution is only possible when it is possible to return a Future value in the InterpreterResult. It may be an interesting proposal for the Zeppelin project.
+
+ Another caveat is that the same com.datastax.driver.core.Session object is used for all notebooks and paragraphs. Consequently, if you use the USE keyspace name; statement to log into a keyspace, it will change the keyspace for all current users of the Cassandra interpreter because we only create 1 com.datastax.driver.core.Session object per instance of Cassandra interpreter.
+
+ The same remark does apply to the prepared statement hash map, it is shared by all users using the same instance of Cassandra interpreter.
+
+ Until Zeppelin offers a real multi-users separation, there is a work-around to segregate user environment and states: create different Cassandra interpreter instances
+
+
+
First go to the Interpreter menu and click on the Create button
+
In the interpreter creation form, put cass-instance2 as Name and select the cassandra in the interpreter drop-down list
+
Click on Save to create the new interpreter instance. Now you should be able to see it in the interpreter list
+
Go back to your notebook and click on the Gear icon to configure interpreter bindings. You should be able to see and select the cass-instance2 interpreter instance in the available interpreter list instead of the standard cassandra instance
+ If you encounter a bug for this interpreter, please create a JIRA ticket and ping me on Twitter at @doanduyhai
+
+
\ No newline at end of file
From 7a5ac396c6157ba392e8884aae2231d60df12f75 Mon Sep 17 00:00:00 2001
From: DuyHai DOAN
Date: Wed, 6 Jan 2016 10:16:58 +0100
Subject: [PATCH 4/9] Update RegExp for UDF creation to fix multiple statements
match
---
.../zeppelin/cassandra/ParagraphParser.scala | 31 +++++++++++++--
.../cassandra/ParagraphParserTest.scala | 39 ++++++++++++++++++-
2 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
index b0dd1c50d5e..a26c7891c92 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
@@ -23,7 +23,16 @@ import scala.util.matching.Regex
import scala.util.parsing.combinator._
import org.apache.zeppelin.cassandra.TextBlockHierarchy._
+/**
+ * Parser using Scala combinator parsing
+ *
+ * (?i) means case-insensitive mode
+ * (?s) means DOT ALL mode
+ * (?is) means case-insensitive and DOT ALL mode
+ *
+ */
object ParagraphParser {
+
val CONSISTENCY_LEVEL_PATTERN = ConsistencyLevel.values().toList
.map(_.name()).filter(!_.contains("SERIAL")).mkString("""^\s*@consistency\s*=\s*(""", "|" , """)\s*$""").r
@@ -43,7 +52,21 @@ object ParagraphParser {
val BIND_PATTERN = """^\s*@bind\[([^]]+)\](?:=([^;]+))?""".r
val BATCH_PATTERN = """^(?i)\s*BEGIN\s+(UNLOGGED|COUNTER)?\s*BATCH""".r
- val UDF_PATTERN = """^(?is)\s*(CREATE(?: OR REPLACE)? FUNCTION(?: IF NOT EXISTS)?.+ AS (?:'|\$\$)[^']+(?:'|\$\$);)""".r
+ /**
+ * Very complicated RegExp
+ * (?: OR REPLACE)? -> optional presence of OR REPLACE
+ * .+? -> match ANY character in RELUCTANT mode
+ * (?:\s*|\n|\r|\f) -> white space OR line returns (\n, \r, \f)
+ * (?:\s*|\n|\r|\f)AS(?:\s*|\n|\r|\f) -> AS preceded and followed by white space or line return
+ * (?:'|\$\$) -> simple quote (') OR double dollar ($$) as source code separator
+ * (?:'|\$\$).+?(?:'|\$\$)\s*; ->
+ * source code separator (?:'|\$\$)
+ * followed by ANY character in RELUCTANT mode (.+?)
+ * followed by source code separator (?:'|\$\$)
+ * followed by optional white-space(s) (\s*)
+ * followed by semi-colon (;)
+ */
+ val UDF_PATTERN = """(?is)\s*(CREATE(?: OR REPLACE)? FUNCTION(?: IF NOT EXISTS)?.+?(?:\s+|\n|\r|\f)AS(?:\s+|\n|\r|\f)(?:'|\$\$).+?(?:'|\$\$)\s*;)""".r
val GENERIC_STATEMENT_PREFIX =
"""(?is)\s*(?:INSERT|UPDATE|DELETE|SELECT|CREATE|UPDATE|
@@ -125,9 +148,9 @@ class ParagraphParser extends RegexParsers{
def fetchSize: Parser[FetchSize] = """\s*@fetchSize.+""".r ^^ {case x => extractFetchSize(x.trim)}
//Statements
- def udfStatement: Parser[SimpleStm] = UDF_PATTERN ^^{case x => extractUdfStatement(x.trim)}
+ def createFunctionStatement: Parser[SimpleStm] = UDF_PATTERN ^^{case x => extractUdfStatement(x.trim)}
def genericStatement: Parser[SimpleStm] = s"""$GENERIC_STATEMENT_PREFIX[^;]+;""".r ^^ {case x => extractSimpleStatement(x.trim)}
- def allStatement: Parser[SimpleStm] = udfStatement | genericStatement
+// def allStatement: Parser[SimpleStm] = udfStatement | genericStatement
def prepare: Parser[PrepareStm] = """\s*@prepare.+""".r ^^ {case x => extractPreparedStatement(x.trim)}
def removePrepare: Parser[RemovePrepareStm] = """\s*@remove_prepare.+""".r ^^ {case x => extractRemovePreparedStatement(x.trim)}
@@ -172,7 +195,7 @@ class ParagraphParser extends RegexParsers{
describeFunction | describeFunctions |
describeAggregate | describeAggregates |
describeMaterializedView | describeMaterializedViews |
- helpCommand | allStatement)
+ helpCommand | createFunctionStatement | genericStatement)
def extractConsistency(text: String): Consistency = {
text match {
diff --git a/cassandra/src/test/scala/org/apache/zeppelin/cassandra/ParagraphParserTest.scala b/cassandra/src/test/scala/org/apache/zeppelin/cassandra/ParagraphParserTest.scala
index 9af1b78a698..c019d9847dc 100644
--- a/cassandra/src/test/scala/org/apache/zeppelin/cassandra/ParagraphParserTest.scala
+++ b/cassandra/src/test/scala/org/apache/zeppelin/cassandra/ParagraphParserTest.scala
@@ -821,7 +821,44 @@ class ParagraphParserTest extends FlatSpec
}
- "Parser" should "parse CREATE Materalized View" in {
+ "Parser" should "parse CREATE multiple FUNCTIONS" in {
+
+ val udf1 =
+ """CREATE FUNCTION IF NOT EXISTS keyspace.udf(input text) xxx
+ | CALLED ON NULL INPUT
+ | RETURN text
+ | LANGUAGE java
+ | AS '
+ | return input.toLowerCase("abc");
+ | ';""".stripMargin
+
+ val select = "SELECT * FROM keyspace.table;"
+
+ val udf2 = """CREATE FUNCTION IF NOT EXISTS keyspace.maxOf(val1 int, val2 int)
+ | CALLED ON NULL INPUT
+ | RETURN text
+ | LANGUAGE java
+ | AS '
+ | return Math.max(val1,val2);
+ | ';""".stripMargin
+
+ val queries =
+ s"""$udf1
+ |
+ |$select
+ |
+ |$udf2
+ """.stripMargin
+
+ val parsed = parser.parseAll(parser.queries, queries)
+
+ parsed.get.size should be(3)
+
+ parsed.get should be(List(SimpleStm(udf1), SimpleStm(select), SimpleStm(udf2)))
+
+ }
+
+ "Parser" should "parse CREATE Materialized View" in {
val query =
"""CREATE MATERIALIZED VIEW xxx
| AS SELECT * FROM myTable
From 6509da5e4b33288074ff60c2bd1a3dac4a003af7 Mon Sep 17 00:00:00 2001
From: DuyHai DOAN
Date: Tue, 5 Jan 2016 23:57:29 +0100
Subject: [PATCH 5/9] Fix failing tests
---
cassandra/pom.xml | 1 -
.../resources/scalate/DescribeCluster.html | 2 +-
.../scalate/DescribeKeyspace_live_data.html | 2 +-
.../resources/scalate/DescribeKeyspaces.html | 2 +-
...DescribeTable_live_data_complex_table.html | 2 +-
.../DescribeType_live_data_address.html | 2 +-
..._data_address_within_current_keyspace.html | 2 +-
.../src/test/resources/scalate/Help.html | 871 +-----------------
8 files changed, 7 insertions(+), 877 deletions(-)
diff --git a/cassandra/pom.xml b/cassandra/pom.xml
index 82bb412f1d1..ca8c5e81150 100644
--- a/cassandra/pom.xml
+++ b/cassandra/pom.xml
@@ -293,7 +293,6 @@
-
diff --git a/cassandra/src/test/resources/scalate/DescribeCluster.html b/cassandra/src/test/resources/scalate/DescribeCluster.html
index 0250301c914..3a5c0011e30 100644
--- a/cassandra/src/test/resources/scalate/DescribeCluster.html
+++ b/cassandra/src/test/resources/scalate/DescribeCluster.html
@@ -1 +1 @@
-
Test Cluster
Partitioner
org.apache.cassandra.dht.Murmur3Partitioner
\ No newline at end of file
+
Test Cluster
Partitioner
org.apache.cassandra.dht.Murmur3Partitioner
\ No newline at end of file
diff --git a/cassandra/src/test/resources/scalate/DescribeKeyspace_live_data.html b/cassandra/src/test/resources/scalate/DescribeKeyspace_live_data.html
index 80a04e81562..aec542b4337 100644
--- a/cassandra/src/test/resources/scalate/DescribeKeyspace_live_data.html
+++ b/cassandra/src/test/resources/scalate/DescribeKeyspace_live_data.html
@@ -1 +1 @@
-
\ No newline at end of file
diff --git a/cassandra/src/test/resources/scalate/DescribeKeyspaces.html b/cassandra/src/test/resources/scalate/DescribeKeyspaces.html
index 47d3386c52f..b5c364e69aa 100644
--- a/cassandra/src/test/resources/scalate/DescribeKeyspaces.html
+++ b/cassandra/src/test/resources/scalate/DescribeKeyspaces.html
@@ -1 +1 @@
-
\ No newline at end of file
diff --git a/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html b/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
index d072c6b85ec..3aefbae2db9 100644
--- a/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
+++ b/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
@@ -1 +1 @@
-
complex_table
Column Type
Column Name
Data Type
pk1
uuid
pk2
int
my_static1
text
my_static2
text
clustering1
timestamp
clustering2
int
clustering3
text
entries_indexed_map
map<int, text>
indexed1
text
indexed2
int
key_indexed_map
map<int, text>
my_list
list<text>
my_map
map<int, text>
my_udt
frozen<live_data.address>
my_udt_list
frozen<list<frozen<live_data.address>>>
simple
double
complex_table's indices
Name
Target
clustering2idx
clustering2
idx1
indexed1
idx2
indexed2
keys_map_idx
keys(key_indexed_map)
pk2idx
pk2
\ No newline at end of file
+
complex_table
Column Type
Column Name
Data Type
pk1
uuid
pk2
int
my_static1
text
my_static2
text
clustering1
timestamp
clustering2
int
clustering3
text
entries_indexed_map
map<int, text>
indexed1
text
indexed2
int
key_indexed_map
map<int, text>
my_list
list<text>
my_map
map<int, text>
my_udt
frozen<live_data.address>
my_udt_list
frozen<list<frozen<live_data.address>>>
simple
double
complex_table's indices
Name
Target
clustering2idx
clustering2
idx1
indexed1
idx2
indexed2
keys_map_idx
keys(key_indexed_map)
pk2idx
pk2
\ No newline at end of file
diff --git a/cassandra/src/test/resources/scalate/DescribeType_live_data_address.html b/cassandra/src/test/resources/scalate/DescribeType_live_data_address.html
index 3e34d2800e5..9d4aaffff90 100644
--- a/cassandra/src/test/resources/scalate/DescribeType_live_data_address.html
+++ b/cassandra/src/test/resources/scalate/DescribeType_live_data_address.html
@@ -1 +1 @@
-
address
Column Name
Data Type
number
int
street
text
zip
int
city
text
country
text
\ No newline at end of file
+
address
Column Name
Data Type
number
int
street
text
zip
int
city
text
country
text
\ No newline at end of file
diff --git a/cassandra/src/test/resources/scalate/DescribeType_live_data_address_within_current_keyspace.html b/cassandra/src/test/resources/scalate/DescribeType_live_data_address_within_current_keyspace.html
index 1a75e754223..13b1ce4fabc 100644
--- a/cassandra/src/test/resources/scalate/DescribeType_live_data_address_within_current_keyspace.html
+++ b/cassandra/src/test/resources/scalate/DescribeType_live_data_address_within_current_keyspace.html
@@ -1 +1 @@
-
address
Column Name
Data Type
number
int
street
text
zip
int
city
text
country
text
\ No newline at end of file
+
address
Column Name
Data Type
number
int
street
text
zip
int
city
text
country
text
\ No newline at end of file
diff --git a/cassandra/src/test/resources/scalate/Help.html b/cassandra/src/test/resources/scalate/Help.html
index de71d649c37..1c82c66dd13 100644
--- a/cassandra/src/test/resources/scalate/Help.html
+++ b/cassandra/src/test/resources/scalate/Help.html
@@ -1,870 +1 @@
-
-
-
-
This interpreter is compatible with any CQL statement supported by Cassandra. Ex:
-
-
-
-
-
- INSERT INTO users(login,name) VALUES('jdoe','John DOE');
- SELECT * FROM users WHERE login='jdoe';
-
-
-
-
- Each statement should be separated by a semi-colon (;).
-
- Multi-line statements as well as multiple statements on the same line
- are also supported as long as they are separated by a semi-colon. Ex:
-
-
-
-
-
-
- USE spark_demo;
-
- SELECT * FROM albums_by_country LIMIT 1; SELECT * FROM countries LIMIT 1;
-
- SELECT *
- FROM artists
- WHERE login='jlennon';
-
-
-
-
- Batch statements are supported and can span multiple lines, as well as
- DDL(CREATE/ALTER/DROP) statements:
-
-
-
-
-
-
- BEGIN BATCH
- INSERT INTO users(login,name) VALUES('jdoe','John DOE');
- INSERT INTO users_preferences(login,account_type) VALUES('jdoe','BASIC');
- APPLY BATCH;
-
- CREATE TABLE IF NOT EXISTS test(
- key int PRIMARY KEY,
- value text
- );
-
-
-
-
- CQL statements are case-insensitive (except for column names and values).
- This means that the following statements are equivalent and valid:
-
-
-
-
-
-
- INSERT INTO users(login,name) VALUES('jdoe','John DOE');
- Insert into users(login,name) vAlues('hsue','Helen SUE');
-
-
-
-
- The complete list of all CQL statements and versions can be found below:
-
- It is possible to add comments between statements. Single line comments start with the
- hash sign (#). Multi-line comments are enclosed between
- /** and **/. Ex:
-
-
-
-
-
-
-
- #First comment
- INSERT INTO users(login,name) VALUES('jdoe','John DOE');
-
- /**
- Multi line
- comments
- **/
- Insert into users(login,name) vAlues('hsue','Helen SUE');
-
-
-
-
-
-
-
III Syntax Validation
-
- The interpreters is shipped with a built-in syntax validator. This validator only
- checks for basic syntax errors. All CQL-related syntax validation is delegated
- directly to Cassandra
-
- Most of the time, syntax errors are due to missing semi-colons between statements or typo errors.
-
-
- To make schema discovery easier and more interactive, the following commands are supported:
-
-
-
-
Command
Description
-
-
-
-
DESCRIBE CLUSTER;
-
Show the current cluster name and its partitioner
-
-
-
DESCRIBE KEYSPACES;
-
List all existing keyspaces in the cluster and their configuration
- (replication factor, durable write ...)
-
-
-
DESCRIBE TABLES;
-
List all existing keyspaces in the cluster and for each, all the tables name
-
-
-
DESCRIBE KEYSPACE <keyspace name>;
-
Describe the given keyspace configuration and all its table details (name, columns, ...)
-
-
-
DESCRIBE TABLE (<keyspace name>).<table name>;
-
- Describe the given table. If the keyspace is not provided, the current
- logged in keyspace is used. If there is no logged in keyspace,
- the default system keyspace is used. If no table is found, an error message is raised
-
-
-
-
DESCRIBE TYPE (<keyspace name>).<type name>;
-
- Describe the given type(UDT). If the keyspace is not provided, the current
- logged in keyspace is used. If there is no logged in keyspace,
- the default system keyspace is used. If no type is found, an error message is raised
-
-
-
-
-
-
- Please note that each DESCRIBE command should be ended by a semi-colon.
-
-
-
II Schema Display
-
- The schema objects (cluster, keyspace, table & type) are displayed in a tabular format.
- There is a drop-down menu on the top left corner to expand objects details.
- On the top right menu is shown the Icon legend.
-
-
- Sometimes you want to be able to pass runtime query parameters to your statements.
- Those parameters are not part of the CQL specs and are specific to the interpreter.
- Below is the list of all parameters:
-
-
-
-
-
Query Parameters
-
-
-
-
Parameter
-
Syntax
-
Description
-
-
-
-
-
Consistency Level
-
@consistency=value
-
Apply the given consistency level to all queries in the paragraph
-
-
-
Serial Consistency Level
-
@serialConsistency=value
-
Apply the given serial consistency level to all queries in the paragraph
-
-
-
Timestamp
-
@timestamp=long value
-
Apply the given timestamp to all queries in the paragraph.
- Please note that timestamp value passed directly in CQL statement will override this value
-
-
-
-
Retry Policy
-
@retryPolicy=value
-
Apply the given retry policy to all queries in the paragraph
-
-
-
Fetch Size
-
@fetchSize=int value
-
Apply the given fetch size to all queries in the paragraph
-
-
-
-
- Some parameters only accept restricted values:
-
-
-
-
-
Allowed Values
-
-
-
-
Parameter
-
Possible Values
-
-
-
-
-
Consistency Level
-
ALL, ANY, ONE, TWO, THREE, QUORUM, LOCAL_ONE, LOCAL_QUORUM, EACH_QUORUM
- Please note that you should not add semi-colon (;) at the end of each parameter statement
-
-
- Some example:
-
-
-
-
-
- CREATE TABLE IF NOT EXISTS spark_demo.ts(
- key int PRIMARY KEY,
- value text
- );
- TRUNCATE spark_demo.ts;
-
- # Timestamp in the past
- @timestamp=10
-
- # Force timestamp directly in the first insert
- INSERT INTO spark_demo.ts(key,value) VALUES(1,'first insert') USING TIMESTAMP 100;
-
- # Select some data to make the clock turn
- SELECT * FROM spark_demo.albums LIMIT 100;
-
- # Now insert using the timestamp parameter set at the beginning(10)
- INSERT INTO spark_demo.ts(key,value) VALUES(1,'second insert');
-
- # Check for the result. You should see 'first insert'
- SELECT value FROM spark_demo.ts WHERE key=1;
-
-
-
-
-
- Some remarks about query parameters:
-
-
-
-
many query parameters can be set in the same paragraph
-
if the same query parameter is set many time with different values,
- the interpreter only take into account the first value
-
-
each query parameter applies to all CQL statement in the same paragraph,
- unless you override the option using plain CQL text (like forcing timestamp with the USING clause)
-
-
the order of each query parameter with regard to CQL statement does not matter
- For performance reason, it is better to prepare statements before-hand and reuse
- them later by providing bound values. This interpreter provides 3 commands to handle prepared and
- bound statements:
-
- You can use the syntax "@prepare[statement_name]=SELECT ..." to create a prepared statement.
- The statement_name is mandatory because the interpreter prepares the given statement with the
- Java driver and saves the generated prepared statement in an internal map, using the provided
- statement_name as search key.
-
-
- Please note that this internal prepared statement map is shared with all notebooks
- and all paragraphs because there is only one instance of the interpreter for Cassandra
-
-
-
- If the interpreter encounters many @prepare for the same statement_name (key),
- only the first statement will be taken into account.
-
-
- Example:
-
-
-
-
-
- @prepare[select]=SELECT * FROM spark_demo.albums LIMIT ?
-
- @prepare[select]=SELECT * FROM spark_demo.artists LIMIT ?
-
-
-
-
-
- For the above example, the prepared statement is "SELECT * FROM spark_demo.albums LIMIT ?".
- "SELECT * FROM spark_demo.artists LIMIT ?" is ignored because an entry already exists in the
- prepared statements map with the key select.
-
- In the context of Zeppelin, a notebook can be scheduled to be executed at regular interval,
- thus it is necessary to avoid re-preparing many time the same statement (considered an anti-pattern).
-
-
III @bind
-
-
- Once the statement is prepared (possibly in a separated notebook/paragraph). You can bind values to it:
-
-
-
-
-
- @bind[select_first]=10
-
-
-
-
- Bound values are not mandatory for the @bind statement.
- However if you provide bound values, they need to comply to some syntax:
-
-
-
String values should be enclosed between simple quotes ( ‘ )
-
Date values should be enclosed between simple quotes ( ‘ ) and respect the formats:
-
-
- tuple values should be enclosed between parenthesis
- (see tuple CQL syntax):
- (‘text’, 123, true)
-
-
- udt values should be enclosed between brackets
- (see udt CQL syntax):
- {stree_name: ‘Beverly Hills’, number: 104, zip_code: 90020, state: ‘California’, …}
-
-
-
-
- It is possible to use the @bind statement inside a batch:
-
- BEGIN BATCH
- @bind[insert_user]='jdoe','John DOE'
- UPDATE users SET age = 27 WHERE login='hsue';
- APPLY BATCH;
-
-
-
-
-
IV @remove_prepare
-
-
- To avoid for a prepared statement to stay forever in the prepared statement map, you can use the @remove_prepare[statement_name] syntax
- to remove it. Removing a non-existing prepared statement yields no error.
-
- Instead of hard-coding your CQL queries, it is possible to use the mustache syntax ({{ }})
- to inject simple value or multiple choices forms.
-
-
- The syntax for simple parameter is: {{input_Label=default value}}.
- The default value is mandatory because the first time the paragraph is executed,
- we launch the CQL query before rendering the form so at least one value should be provided.
-
- The syntax for multiple choices parameter is: {{input_Label=value1 | value2 | … | valueN }}.
- By default the first choice is used for CQL query the first time the paragraph is executed.
-
- Example:
-
-
-
-
-
- #Secondary index on performer style
- SELECT name, country, performer
- FROM spark_demo.performers
- WHERE name='{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}}'
- AND styles CONTAINS '{{style=Rock}}';
-
-
-
-
-
-
- In the above example, the first CQL query will be executed for performer='Sheryl Crow'
- AND style='Rock'. For subsequent queries, you can change the value directly using the form.
- Please note that we enclosed the {{ }} block between simple quotes (') because Cassandra expects a String here.
- We could have also use the {{style='Rock'}} syntax but this time, the value
- displayed on the form is 'Rock' and not Rock.
-
-
-
- It is also possible to use dynamic forms for prepared statements:
- @bind[select]=='{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}}', '{{style=Rock}}'
-
- It is possible to execute many paragraphs in parallel. However, at the back-end side, we’re still using synchronous queries. Asynchronous execution is only possible when it is possible to return a Future value in the InterpreterResult. It may be an interesting proposal for the Zeppelin project.
-
This interpreter is compatible with any CQL statement supported by Cassandra. Ex:
INSERT INTO users(login,name) VALUES('jdoe','John DOE');SELECT * FROM users WHERE login='jdoe';
Each statement should be separated by a semi-colon (;). Multi-line statements as well as multiple statements on the same lineare also supported as long as they are separated by a semi-colon. Ex:
USE spark_demo;SELECT * FROM albums_by_country LIMIT 1; SELECT * FROM countries LIMIT 1;SELECT *FROM artistsWHERE login='jlennon';
Batch statements are supported and can span multiple lines, as well asDDL(CREATE/ALTER/DROP) statements:
BEGIN BATCHINSERT INTO users(login,name) VALUES('jdoe','John DOE');INSERT INTO users_preferences(login,account_type) VALUES('jdoe','BASIC');APPLY BATCH;CREATE TABLE IF NOT EXISTS test(key int PRIMARY KEY,value text);
CQL statements are case-insensitive (except for column names and values).This means that the following statements are equivalent and valid:
INSERT INTO users(login,name) VALUES('jdoe','John DOE');Insert into users(login,name) vAlues('hsue','Helen SUE');
The complete list of all CQL statements and versions can be found below:
It is possible to add comments between statements. Single line comments start with thehash sign (#) or double slashes (//). Multi-line comments are enclosed between/** and **/. Ex:
#Single line comment style 1INSERT INTO users(login,name) VALUES('jdoe','John DOE');//Single line comment style 2/**Multi linecomments**/Insert into users(login,name) vAlues('hsue','Helen SUE');
III Syntax Validation
The interpreters is shipped with a built-in syntax validator. This validator onlychecks for basic syntax errors. All CQL-related syntax validation is delegateddirectly to Cassandra
Most of the time, syntax errors are due to missing semi-colons between statements or typo errors.
To make schema discovery easier and more interactive, the following commands are supported:
Command
Description
DESCRIBE CLUSTER;
Show the current cluster name and its partitioner
DESCRIBE KEYSPACES;
List all existing keyspaces in the cluster and their configuration(replication factor, durable write ...)
DESCRIBE TABLES;
List all existing keyspaces in the cluster and for each, all the tables name
DESCRIBE TYPES;
List all existing keyspaces in the cluster and for each, all the types name
DESCRIBE FUNCTIONS;
List all existing keyspaces in the cluster and for each, all the functions name and arguments
DESCRIBE AGGREGATES;
List all existing keyspaces in the cluster and for each, all the aggregates name and arguments
DESCRIBE MATERIALIZED VIEWS;
List all existing keyspaces in the cluster and for each, all the materialized view name
DESCRIBE KEYSPACE <keyspace name>;
Describe the given keyspace configuration and all its table details (name, columns, ...)
DESCRIBE TABLE (<keyspace name>).<table name>;
Describe the given table. If the keyspace is not provided, the currentlogged in keyspace is used. If there is no logged in keyspace,the default system keyspace is used. If no table is found, an error message is raised
DESCRIBE TYPE (<keyspace name>).<type name>;
Describe the given type(UDT). If the keyspace is not provided, the currentlogged in keyspace is used. If there is no logged in keyspace,the default system keyspace is used. If no type is found, an error message is raised
DESCRIBE FUNCTION (<keyspace name>).<function name>;
Describe the given function. If the keyspace is not provided, the currentlogged in keyspace is used. If there is no logged in keyspace,the default system keyspace is used. If no function is found, an error message is raised
Describe the given aggregate. If the keyspace is not provided, the currentlogged in keyspace is used. If there is no logged in keyspace,the default system keyspace is used. If no aggregate is found, an error message is raised
Describe the given materialized view. If the keyspace is not provided, the currentlogged in keyspace is used. If there is no logged in keyspace,the default system keyspace is used. If no materialized view is found, an error message is raised
Please note that each DESCRIBE command should be ended by a semi-colon.
II Schema Display
The schema objects (cluster, keyspace, table, type, view, function & aggregate) are displayed in a tabular format. There is a drop-down menu on the top left corner to expand objects details. On the top right menu is shown the Icon legend.
Sometimes you want to be able to pass runtime query parameters to your statements.Those parameters are not part of the CQL specs and are specific to the interpreter.Below is the list of all parameters:
Query Parameters
Parameter
Syntax
Description
Consistency Level
@consistency=value
Apply the given consistency level to all queries in the paragraph
Serial Consistency Level
@serialConsistency=value
Apply the given serial consistency level to all queries in the paragraph
Timestamp
@timestamp=long value
Apply the given timestamp to all queries in the paragraph. Please note that timestamp value passed directly in CQL statement will override this value
Retry Policy
@retryPolicy=value
Apply the given retry policy to all queries in the paragraph
Fetch Size
@fetchSize=int value
Apply the given fetch size to all queries in the paragraph
Some parameters only accept restricted values:
Allowed Values
Parameter
Possible Values
Consistency Level
ALL, ANY, ONE, TWO, THREE, QUORUM, LOCAL_ONE, LOCAL_QUORUM, EACH_QUORUM
Please note that you should not add semi-colon (;) at the end of each parameter statement
Some example:
CREATE TABLE IF NOT EXISTS spark_demo.ts(key int PRIMARY KEY,value text);TRUNCATE spark_demo.ts;# Timestamp in the past@timestamp=10# Force timestamp directly in the first insertINSERT INTO spark_demo.ts(key,value) VALUES(1,'first insert') USING TIMESTAMP 100;# Select some data to make the clock turnSELECT * FROM spark_demo.albums LIMIT 100;# Now insert using the timestamp parameter set at the beginning(10)INSERT INTO spark_demo.ts(key,value) VALUES(1,'second insert');# Check for the result. You should see 'first insert'SELECT value FROM spark_demo.ts WHERE key=1;
Some remarks about query parameters:
many query parameters can be set in the same paragraph
if the same query parameter is set many time with different values,the interpreter only take into account the first value
each query parameter applies to all CQL statement in the same paragraph,unless you override the option using plain CQL text (like forcing timestamp with the USING clause)
the order of each query parameter with regard to CQL statement does not matter
For performance reason, it is better to prepare statements before-hand and reusethem later by providing bound values. This interpreter provides 3 commands to handle prepared andbound statements:
You can use the syntax "@prepare[statement_name]=SELECT ..." to create a prepared statement.The statement_name is mandatory because the interpreter prepares the given statement with theJava driver and saves the generated prepared statement in an internal map, using the providedstatement_name as search key.
Please note that this internal prepared statement map is shared with all notebooksand all paragraphs because there is only one instance of the interpreter for Cassandra
If the interpreter encounters many @prepare for the same statement_name (key),only the first statement will be taken into account.
Example:
@prepare[select]=SELECT * FROM spark_demo.albums LIMIT ?@prepare[select]=SELECT * FROM spark_demo.artists LIMIT ?
For the above example, the prepared statement is "SELECT * FROM spark_demo.albums LIMIT ?"."SELECT * FROM spark_demo.artists LIMIT ?" is ignored because an entry already exists in theprepared statements map with the key select.
In the context of Zeppelin, a notebook can be scheduled to be executed at regular interval,thus it is necessary to avoid re-preparing many time the same statement (considered an anti-pattern).
III @bind
Once the statement is prepared (possibly in a separated notebook/paragraph). You can bind values to it:
@bind[select_first]=10
Bound values are not mandatory for the @bind statement.However if you provide bound values, they need to comply to some syntax:
String values should be enclosed between simple quotes ( ‘ )
Date values should be enclosed between simple quotes ( ‘ ) and respect the formats:
tuple values should be enclosed between parenthesis(see tuple CQL syntax):(‘text’, 123, true)
udt values should be enclosed between brackets(see udt CQL syntax):{stree_name: ‘Beverly Hills’, number: 104, zip_code: 90020, state: ‘California’, …}
It is possible to use the @bind statement inside a batch:
BEGIN BATCH@bind[insert_user]='jdoe','John DOE'UPDATE users SET age = 27 WHERE login='hsue';APPLY BATCH;
IV @remove_prepare
To avoid for a prepared statement to stay forever in the prepared statement map, you can use the @remove_prepare[statement_name] syntaxto remove it. Removing a non-existing prepared statement yields no error.
Instead of hard-coding your CQL queries, it is possible to use the mustache syntax ({{ }})to inject simple value or multiple choices forms.
The syntax for simple parameter is: {{input_Label=default value}}.The default value is mandatory because the first time the paragraph is executed,we launch the CQL query before rendering the form so at least one value should be provided.
The syntax for multiple choices parameter is: {{input_Label=value1 | value2 | … | valueN }}.By default the first choice is used for CQL query the first time the paragraph is executed.
Example:
#Secondary index on performer styleSELECT name, country, performerFROM spark_demo.performersWHERE name='{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}}'AND styles CONTAINS '{{style=Rock}}';
In the above example, the first CQL query will be executed for performer='Sheryl Crow'AND style='Rock'. For subsequent queries, you can change the value directly using the form.Please note that we enclosed the {{ }} block between simple quotes (') because Cassandra expects a String here.We could have also use the {{style='Rock'}} syntax but this time, the valuedisplayed on the form is 'Rock' and not Rock.
It is also possible to use dynamic forms for prepared statements: @bind[select]=='{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}}', '{{style=Rock}}'
It is possible to execute many paragraphs in parallel. However, at the back-end side, we’re still using synchronous queries. Asynchronous execution is only possible when it is possible to return a Future value in the InterpreterResult. It may be an interesting proposal for the Zeppelin project. Another caveat is that the same com.datastax.driver.core.Session object is used for all notebooks and paragraphs. Consequently, if you use the USE keyspace name; statement to log into a keyspace, it will change the keyspace for all current users of the Cassandra interpreter because we only create 1 com.datastax.driver.core.Session object per instance of Cassandra interpreter. The same remark does apply to the prepared statement hash map, it is shared by all users using the same instance of Cassandra interpreter. Until Zeppelin offers a real multi-users separation, there is a work-around to segregate user environment and states: create different Cassandra interpreter instances
First go to the Interpreter menu and click on the Create button
In the interpreter creation form, put cass-instance2 as Name and select the cassandra in the interpreter drop-down list
Click on Save to create the new interpreter instance. Now you should be able to see it in the interpreter list
Go back to your notebook and click on the Gear icon to configure interpreter bindings. You should be able to see and select the cass-instance2 interpreter instance in the available interpreter list instead of the standard cassandra instance
\ No newline at end of file
diff --git a/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html b/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
index 3aefbae2db9..bbb778b82db 100644
--- a/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
+++ b/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
@@ -1 +1 @@
-
complex_table
Column Type
Column Name
Data Type
pk1
uuid
pk2
int
my_static1
text
my_static2
text
clustering1
timestamp
clustering2
int
clustering3
text
entries_indexed_map
map<int, text>
indexed1
text
indexed2
int
key_indexed_map
map<int, text>
my_list
list<text>
my_map
map<int, text>
my_udt
frozen<live_data.address>
my_udt_list
frozen<list<frozen<live_data.address>>>
simple
double
complex_table's indices
Name
Target
clustering2idx
clustering2
idx1
indexed1
idx2
indexed2
keys_map_idx
keys(key_indexed_map)
pk2idx
pk2
\ No newline at end of file
+
complex_table
Column Type
Column Name
Data Type
pk1
uuid
pk2
int
my_static1
text
my_static2
text
clustering1
timestamp
clustering2
int
clustering3
text
entries_indexed_map
map<int, text>
indexed1
text
indexed2
int
key_indexed_map
map<int, text>
my_list
list<text>
my_map
map<int, text>
my_udt
frozen<live_data.address>
my_udt_list
frozen<list<frozen<live_data.address>>>
simple
double
complex_table's indices
Name
Target
clustering2idx
clustering2
idx1
indexed1
idx2
indexed2
keys_map_idx
keys(key_indexed_map)
pk2idx
pk2
\ No newline at end of file
From 41b86679d1c2975674c1438f2a3f32da360fe667 Mon Sep 17 00:00:00 2001
From: DuyHai DOAN
Date: Sat, 9 Jan 2016 11:41:29 +0100
Subject: [PATCH 7/9] Tune regular expression for FUNCTION creation pattern
---
.../scala/org/apache/zeppelin/cassandra/ParagraphParser.scala | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
index a26c7891c92..e2cb64dbbe8 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
@@ -66,7 +66,7 @@ object ParagraphParser {
* followed by optional white-space(s) (\s*)
* followed by semi-colon (;)
*/
- val UDF_PATTERN = """(?is)\s*(CREATE(?: OR REPLACE)? FUNCTION(?: IF NOT EXISTS)?.+?(?:\s+|\n|\r|\f)AS(?:\s+|\n|\r|\f)(?:'|\$\$).+?(?:'|\$\$)\s*;)""".r
+ val UDF_PATTERN = """(?is)\s*(CREATE(?:\s+OR REPLACE)?\s+FUNCTION(?:\s+IF\s+NOT\s+EXISTS)?.+?(?:\s+|\n|\r|\f)AS(?:\s+|\n|\r|\f)(?:'|\$\$).+?(?:'|\$\$)\s*;)""".r
val GENERIC_STATEMENT_PREFIX =
"""(?is)\s*(?:INSERT|UPDATE|DELETE|SELECT|CREATE|UPDATE|
From a2d831b8209e02b085d89e34dcfa6c8d3886f30c Mon Sep 17 00:00:00 2001
From: DuyHai DOAN
Date: Sun, 10 Jan 2016 14:31:11 +0100
Subject: [PATCH 8/9] Refactor after code review
---
.../cassandra/TextBlockHierarchy.scala | 16 +-
.../cassandra/ParagraphParserTest.scala | 260 +++++++++++-------
2 files changed, 175 insertions(+), 101 deletions(-)
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/TextBlockHierarchy.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/TextBlockHierarchy.scala
index 41a9468b4ab..61a2d8d9cb5 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/TextBlockHierarchy.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/TextBlockHierarchy.scala
@@ -110,25 +110,25 @@ object TextBlockHierarchy {
val statement: String
}
- class DescribeClusterCmd(override val statement: String = "DESCRIBE CLUSTER;")
+ case class DescribeClusterCmd(override val statement: String = "DESCRIBE CLUSTER;")
extends QueryStatement(DescribeClusterStatementType) with DescribeCommandStatement
- class DescribeKeyspacesCmd(override val statement: String = "DESCRIBE KEYSPACES;")
+ case class DescribeKeyspacesCmd(override val statement: String = "DESCRIBE KEYSPACES;")
extends QueryStatement(DescribeAllKeyspacesStatementType) with DescribeCommandStatement
- class DescribeTablesCmd(override val statement: String = "DESCRIBE TABLES;")
+ case class DescribeTablesCmd(override val statement: String = "DESCRIBE TABLES;")
extends QueryStatement(DescribeAllTablesStatementType) with DescribeCommandStatement
- class DescribeTypesCmd(override val statement: String = "DESCRIBE TYPES;")
+ case class DescribeTypesCmd(override val statement: String = "DESCRIBE TYPES;")
extends QueryStatement(DescribeAllTypesStatementType) with DescribeCommandStatement
- class DescribeFunctionsCmd(override val statement: String = "DESCRIBE FUNCTIONS;") extends QueryStatement(DescribeAllFunctionsStatementType)
+ case class DescribeFunctionsCmd(override val statement: String = "DESCRIBE FUNCTIONS;") extends QueryStatement(DescribeAllFunctionsStatementType)
with DescribeCommandStatement
- class DescribeAggregatesCmd(override val statement: String = "DESCRIBE AGGREGATES;") extends QueryStatement(DescribeAllAggregatesStatementType)
+ case class DescribeAggregatesCmd(override val statement: String = "DESCRIBE AGGREGATES;") extends QueryStatement(DescribeAllAggregatesStatementType)
with DescribeCommandStatement
- class DescribeMaterializedViewsCmd(override val statement: String = "DESCRIBE MATERIALIZED VIEWS;") extends QueryStatement(DescribeAllAggregatesStatementType)
+ case class DescribeMaterializedViewsCmd(override val statement: String = "DESCRIBE MATERIALIZED VIEWS;") extends QueryStatement(DescribeAllAggregatesStatementType)
with DescribeCommandStatement
case class DescribeKeyspaceCmd(keyspace: String) extends QueryStatement(DescribeKeyspaceStatementType)
@@ -176,6 +176,6 @@ object TextBlockHierarchy {
}
}
- class HelpCmd extends QueryStatement(HelpStatementType)
+ case class HelpCmd(val statement:String = "HELP;") extends QueryStatement(HelpStatementType)
}
diff --git a/cassandra/src/test/scala/org/apache/zeppelin/cassandra/ParagraphParserTest.scala b/cassandra/src/test/scala/org/apache/zeppelin/cassandra/ParagraphParserTest.scala
index c019d9847dc..520f7a61fc5 100644
--- a/cassandra/src/test/scala/org/apache/zeppelin/cassandra/ParagraphParserTest.scala
+++ b/cassandra/src/test/scala/org/apache/zeppelin/cassandra/ParagraphParserTest.scala
@@ -23,6 +23,8 @@ import org.scalatest.{BeforeAndAfterEach, FlatSpec, Matchers}
import org.apache.zeppelin.cassandra.ParagraphParser._
import org.apache.zeppelin.cassandra.TextBlockHierarchy._
+import scala.Option
+
class ParagraphParserTest extends FlatSpec
with BeforeAndAfterEach
with Matchers
@@ -57,39 +59,45 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parse(parser.queries,query)
- parsed.get should be(List(
- SimpleStm("SELECT * FROM albums LIMIT 10;"),
- BatchStm(BatchStatement.Type.UNLOGGED,
- List(
- SimpleStm("INSERT INTO users(id) VALUES(10);"),
- BoundStm("test","'a',12.34")
- )
- ),
- SimpleStm("SELECT * FROM users LIMIT 10;"),
- BatchStm(BatchStatement.Type.LOGGED,
- List(
- SimpleStm("Insert INTO users(id) VALUES(11);"),
- SimpleStm("INSERT INTO users(id) VALUES(12);")
- )
- ),
- BoundStm("toto","'a',12.34"),
- DescribeTableCmd(Option("zeppelin"),"users"),
- DescribeKeyspaceCmd("zeppelin")
- ))
+ parsed should matchPattern {
+ case parser.Success(List(
+ SimpleStm("SELECT * FROM albums LIMIT 10;"),
+ BatchStm(BatchStatement.Type.UNLOGGED,
+ List(
+ SimpleStm("INSERT INTO users(id) VALUES(10);"),
+ BoundStm("test","'a',12.34")
+ )
+ ),
+ SimpleStm("SELECT * FROM users LIMIT 10;"),
+ BatchStm(BatchStatement.Type.LOGGED,
+ List(
+ SimpleStm("Insert INTO users(id) VALUES(11);"),
+ SimpleStm("INSERT INTO users(id) VALUES(12);")
+ )
+ ),
+ BoundStm("toto","'a',12.34"),
+ DescribeTableCmd(Some("zeppelin"),"users"),
+ DescribeKeyspaceCmd("zeppelin")
+ ),_) =>
+ }
}
"Parser" should "parse hash single-line comment" in {
val query :CharSequence="""#This is a comment""".stripMargin
val parsed = parser.parseAll[Comment](parser.singleLineComment, query)
- parsed.get should be(Comment("This is a comment"))
+ parsed should matchPattern {
+ case parser.Success(Comment("This is a comment"), _) =>
+ }
}
- "Parser" should "parse double slashses single-line comment" in {
+ "Parser" should "parse double slashes single-line comment" in {
val query :CharSequence="""//This is another comment""".stripMargin
val parsed = parser.parseAll[Comment](parser.singleLineComment, query)
- parsed.get should be(Comment("This is another comment"))
+ parsed should matchPattern {
+ case parser.Success(Comment("This is another comment"), _) =>
+ }
}
"Parser" should "parse multi-line comment" in {
@@ -102,13 +110,17 @@ class ParagraphParserTest extends FlatSpec
""".stripMargin
val parsed = parser.parseAll(parser.multiLineComment, query)
- parsed.get should be(Comment("This is a comment\nline1\nline2\nline3\n"))
+ parsed should matchPattern {
+ case parser.Success(Comment("This is a comment\nline1\nline2\nline3\n"), _) =>
+ }
}
"Parser" should "parse consistency level" in {
val query:String =""" @consistency=ONE""".stripMargin
val parsed = parser.parseAll(parser.consistency, query)
- parsed.get should be(Consistency(ConsistencyLevel.ONE))
+ parsed should matchPattern {
+ case parser.Success(Consistency(ConsistencyLevel.ONE), _) =>
+ }
}
"Parser" should "fails parsing unknown consistency level" in {
@@ -122,7 +134,9 @@ class ParagraphParserTest extends FlatSpec
"Parser" should "parse serial consistency level" in {
val query:String =""" @serialConsistency=LOCAL_SERIAL""".stripMargin
val parsed = parser.parseAll(parser.serialConsistency, query)
- parsed.get should be(SerialConsistency(ConsistencyLevel.LOCAL_SERIAL))
+ parsed should matchPattern {
+ case parser.Success(SerialConsistency(ConsistencyLevel.LOCAL_SERIAL), _) =>
+ }
}
"Parser" should "fails parsing unknown serial consistency level" in {
@@ -136,7 +150,8 @@ class ParagraphParserTest extends FlatSpec
"Parser" should "parse timestamp" in {
val query:String =""" @timestamp=111""".stripMargin
val parsed = parser.parseAll(parser.timestamp, query)
- parsed.get should be(Timestamp(111L))
+ parsed should matchPattern {
+ case parser.Success(Timestamp(111L), _) => }
}
"Parser" should "fails parsing invalid timestamp" in {
@@ -150,7 +165,7 @@ class ParagraphParserTest extends FlatSpec
"Parser" should "parse retry policy" in {
val query:String ="@retryPolicy="+CassandraInterpreter.DOWNGRADING_CONSISTENCY_RETRY
val parsed = parser.parseAll(parser.retryPolicy, query)
- parsed.get should be(DowngradingRetryPolicy)
+ parsed should matchPattern {case parser.Success(DowngradingRetryPolicy, _) => }
}
"Parser" should "fails parsing invalid retry policy" in {
@@ -164,7 +179,7 @@ class ParagraphParserTest extends FlatSpec
"Parser" should "parse fetch size" in {
val query:String ="@fetchSize=100"
val parsed = parser.parseAll(parser.fetchSize, query)
- parsed.get should be(FetchSize(100))
+ parsed should matchPattern { case parser.Success(FetchSize(100), _) =>}
}
"Parser" should "fails parsing invalid fetch size" in {
@@ -183,7 +198,7 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.genericStatement, query)
//Then
- parsed.get should be(SimpleStm("sElecT * FROM users LIMIT ? ;"))
+ parsed should matchPattern { case parser.Success(SimpleStm("sElecT * FROM users LIMIT ? ;"), _) =>}
}
"Parser" should "parse prepare" in {
@@ -194,7 +209,7 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.prepare, query)
//Then
- parsed.get should be(PrepareStm("select_users","SELECT * FROM users LIMIT ?"))
+ parsed should matchPattern { case parser.Success(PrepareStm("select_users","SELECT * FROM users LIMIT ?"), _) => }
}
"Parser" should "fails parsing invalid prepared statement" in {
@@ -213,7 +228,7 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.removePrepare, query)
//Then
- parsed.get should be(RemovePrepareStm("select_users"))
+ parsed should matchPattern { case parser.Success(RemovePrepareStm("select_users"), _) => }
}
"Parser" should "fails parsing invalid remove prepared statement" in {
@@ -232,7 +247,7 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.bind, query)
//Then
- parsed.get should be(BoundStm("select_users","10,'toto'"))
+ parsed should matchPattern { case parser.Success(BoundStm("select_users","10,'toto'"), _) => }
}
"Parser" should "fails parsing invalid bind statement" in {
@@ -257,17 +272,17 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.batch, query)
//Then
- parsed.get should be(
- BatchStm(
- BatchStatement.Type.LOGGED,
- List[QueryStatement](
- SimpleStm("Insert INTO users(id) VALUES(10);"),
- BoundStm("select_users", "10,'toto'"),
- SimpleStm("update users SET name ='John DOE' WHERE id=10;"),
- SimpleStm("dElEtE users WHERE id=11;")
+ parsed should matchPattern {
+ case parser.Success(BatchStm(
+ BatchStatement.Type.LOGGED,
+ List(
+ SimpleStm("Insert INTO users(id) VALUES(10);"),
+ BoundStm("select_users", "10,'toto'"),
+ SimpleStm("update users SET name ='John DOE' WHERE id=10;"),
+ SimpleStm("dElEtE users WHERE id=11;")
)
- )
- )
+ ), _) =>
+ }
}
"Parser" should "fails parsing invalid batch type" in {
@@ -286,10 +301,12 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, query)
- parsed.get should be (List(
- SerialConsistency(ConsistencyLevel.SERIAL),
- SimpleStm("SELECT * FROM zeppelin.artists LIMIT 1;")
- ))
+ parsed should matchPattern {
+ case parser.Success(List(
+ SerialConsistency(ConsistencyLevel.SERIAL),
+ SimpleStm("SELECT * FROM zeppelin.artists LIMIT 1;")
+ ), _) =>
+ }
}
"Parser" should "parse multi-line single statement" in {
@@ -298,13 +315,15 @@ class ParagraphParserTest extends FlatSpec
" title text PRIMARY KEY,\n" +
" artist text,\n" +
" year int\n" +
- ");\n";
+ ");\n"
val parsed = parser.parseAll(parser.queries, query)
- parsed.get should be (List(
- SimpleStm("CREATE TABLE IF NOT EXISTS zeppelin.albums(\n title text PRIMARY KEY,\n artist text,\n year int\n);")
- ))
+ parsed should matchPattern {
+ case parser.Success(List(
+ SimpleStm("CREATE TABLE IF NOT EXISTS zeppelin.albums(\n title text PRIMARY KEY,\n artist text,\n year int\n);")
+ ), _) =>
+ }
}
"Parser" should "parse multi-line statements" in {
@@ -322,11 +341,12 @@ class ParagraphParserTest extends FlatSpec
"APPLY BATCH;\n"+
"@timestamp=10\n" +
"@retryPolicy=DOWNGRADING_CONSISTENCY\n" +
- "SELECT * FROM zeppelin.albums;";
+ "SELECT * FROM zeppelin.albums;"
val parsed = parser.parseAll(parser.queries, query)
- parsed.get should be (List(
+ parsed should matchPattern {
+ case parser.Success(List(
SimpleStm("CREATE TABLE IF NOT EXISTS zeppelin.albums(\n title text PRIMARY KEY,\n artist text,\n year int\n);"),
Consistency(ConsistencyLevel.THREE),
SerialConsistency(ConsistencyLevel.SERIAL),
@@ -340,7 +360,8 @@ class ParagraphParserTest extends FlatSpec
Timestamp(10L),
DowngradingRetryPolicy,
SimpleStm("SELECT * FROM zeppelin.albums;")
- ))
+ ), _) =>
+ }
}
"Parser" should "parse mixed single-line and multi-line statements" in {
@@ -355,11 +376,12 @@ class ParagraphParserTest extends FlatSpec
" INSERT INTO zeppelin.albums(title,artist,year) VALUES('The Way You Are','Tears for Fears',1983);"+
" INSERT INTO zeppelin.albums(title,artist,year) VALUES('Primitive','Soulfly',2003);\n"+
"APPLY BATCH;"+
- "SELECT * FROM zeppelin.albums;";
+ "SELECT * FROM zeppelin.albums;"
val parsed = parser.parseAll(parser.queries, query)
- parsed.get should be (List(
+ parsed should matchPattern {
+ case parser.Success(List(
SimpleStm("CREATE TABLE IF NOT EXISTS zeppelin.albums(\n title text PRIMARY KEY,\n artist text,\n year int\n);"),
BatchStm(BatchStatement.Type.LOGGED,
List(
@@ -369,7 +391,8 @@ class ParagraphParserTest extends FlatSpec
)
),
SimpleStm("SELECT * FROM zeppelin.albums;")
- ))
+ ), _) =>
+ }
}
"Parser" should "parse a block queries with comments" in {
@@ -401,7 +424,8 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, query)
- parsed.get should be (List(
+ parsed should matchPattern {
+ case parser.Success(List(
Comment("\n This example show how to force a\n timestamp on the query\n "),
Comment("Timestamp in the past"),
Timestamp(10L),
@@ -415,8 +439,9 @@ class ParagraphParserTest extends FlatSpec
SimpleStm("INSERT INTO spark_demo.ts(key,value) VALUES(1,'val2');"),
Comment("Check the result"),
SimpleStm("SELECT * FROM spark_demo.ts WHERE key=1;")
- )
- )
+ ), _
+ ) =>
+ }
}
"Parser" should "remove prepared statement" in {
@@ -432,13 +457,14 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(
+ parsed should matchPattern {
+ case parser.Success(List(
Comment("Removing an unknown statement should has no side effect"),
RemovePrepareStm("unknown_statement"),
RemovePrepareStm("select_artist_by_name"),
Comment("This should fail because the 'select_artist_by_name' has been removed"),
BoundStm("select_artist_by_name","'The Beatles'")
- ))
+ ), _) => }
}
"Parser" should "parse only parameter" in {
@@ -447,7 +473,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(FetchSize(1000)))
+ parsed should matchPattern {
+ case parser.Success(List(FetchSize(1000)), _) =>
+ }
}
@@ -456,7 +484,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get(0) shouldBe a [DescribeClusterCmd]
+ parsed should matchPattern {
+ case parser.Success(List(DescribeClusterCmd("DESCRIBE CLUSTER;")), _) =>
+ }
}
"Parser" should "fail parsing describe cluster" in {
@@ -473,7 +503,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeKeyspaceCmd("toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeKeyspaceCmd("toto")), _) =>
+ }
}
"Parser" should "fail parsing describe keyspace" in {
@@ -490,7 +522,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get(0) shouldBe a [DescribeKeyspacesCmd]
+ parsed should matchPattern {
+ case parser.Success(List(DescribeKeyspacesCmd("DESCRIBE KEYSPACES;")), _) =>
+ }
}
"Parser" should "fail parsing describe keyspaces" in {
@@ -533,7 +567,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get(0) shouldBe a [DescribeTablesCmd]
+ parsed should matchPattern {
+ case parser.Success(List(DescribeTablesCmd("DESCRIBE TABLES;")), _) =>
+ }
}
"Parser" should "fail parsing describe tables" in {
@@ -550,7 +586,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeTypeCmd(None,"toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeTypeCmd(None, "toto")), _) =>
+ }
}
"Parser" should "parse describe type with keyspace" in {
@@ -558,7 +596,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeTypeCmd(Some("ks"),"toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeTypeCmd(Some("ks"), "toto")), _) =>
+ }
}
"Parser" should "fail parsing describe type" in {
@@ -576,7 +616,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get(0) shouldBe a [DescribeTypesCmd]
+ parsed should matchPattern {
+ case parser.Success(List(DescribeTypesCmd("DESCRIBE TYPES;")), _) =>
+ }
}
"Parser" should "fail parsing describe types" in {
@@ -593,15 +635,21 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeFunctionCmd(None,"toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeFunctionCmd(None,"toto")),_) =>
+ }
}
+
+
"Parser" should "parse describe function with keyspace" in {
val queries ="Describe function ks.toto;"
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeFunctionCmd(Some("ks"),"toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeFunctionCmd(Some("ks"), "toto")), _) =>
+ }
}
"Parser" should "fail parsing describe function" in {
@@ -619,7 +667,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get(0) shouldBe a [DescribeFunctionsCmd]
+ parsed should matchPattern {
+ case parser.Success(List(DescribeFunctionsCmd("DESCRIBE FUNCTIONS;")), _) =>
+ }
}
"Parser" should "fail parsing describe functions" in {
@@ -638,7 +688,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeAggregateCmd(None,"toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeAggregateCmd(None, "toto")), _) =>
+ }
}
"Parser" should "parse describe aggregate with keyspace" in {
@@ -646,7 +698,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeAggregateCmd(Some("ks"),"toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeAggregateCmd(Some("ks"),"toto")), _) =>
+ }
}
"Parser" should "fail parsing describe aggregate" in {
@@ -664,7 +718,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get(0) shouldBe a [DescribeAggregatesCmd]
+ parsed should matchPattern {
+ case parser.Success(List(DescribeAggregatesCmd("DESCRIBE AGGREGATES;")), _) =>
+ }
}
"Parser" should "fail parsing describe aggregates" in {
@@ -682,7 +738,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeMaterializedViewCmd(None,"toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeMaterializedViewCmd(None, "toto")), _) =>
+ }
}
"Parser" should "parse describe materialized view with keyspace" in {
@@ -690,7 +748,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(DescribeMaterializedViewCmd(Some("ks"),"toto")))
+ parsed should matchPattern {
+ case parser.Success(List(DescribeMaterializedViewCmd(Some("ks"), "toto")), _) =>
+ }
}
"Parser" should "fail parsing describe materialized view" in {
@@ -708,7 +768,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get(0) shouldBe a [DescribeMaterializedViewsCmd]
+ parsed should matchPattern {
+ case parser.Success(List(DescribeMaterializedViewsCmd("DESCRIBE MATERIALIZED VIEWS;")), _) =>
+ }
}
"Parser" should "fail parsing describe materialized views" in {
@@ -726,7 +788,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get(0) shouldBe a [HelpCmd]
+ parsed should matchPattern {
+ case parser.Success(List(HelpCmd("HELP;")), _) =>
+ }
}
"Parser" should "fail parsing help" in {
@@ -744,7 +808,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, query)
- parsed.get(0) should be(SimpleStm(query))
+ parsed should matchPattern {
+ case parser.Success(List(SimpleStm(query)), _) =>
+ }
}
@@ -753,7 +819,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, query)
- parsed.get(0) should be(SimpleStm(query))
+ parsed should matchPattern {
+ case parser.Success(List(SimpleStm(query)), _) =>
+ }
}
@@ -762,8 +830,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, query)
- parsed.get(0) should be(SimpleStm(query))
-
+ parsed should matchPattern {
+ case parser.Success(List(SimpleStm(query)), _) =>
+ }
}
"Parser" should "parse CREATE FUNCTION multiline with simple quote" in {
@@ -778,8 +847,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, query)
- parsed.get(0) should be(SimpleStm(query))
-
+ parsed should matchPattern {
+ case parser.Success(List(SimpleStm(query)), _) =>
+ }
}
"Parser" should "parse CREATE FUNCTION multiline with double dollar" in {
@@ -794,8 +864,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, query)
- parsed.get(0) should be(SimpleStm(query))
-
+ parsed should matchPattern {
+ case parser.Success(List(SimpleStm(query)), _) =>
+ }
}
"Parser" should "parse CREATE FUNCTION multiline with SELECT" in {
@@ -817,8 +888,9 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, queries)
- parsed.get should be(List(SimpleStm(udf), SimpleStm(select)))
-
+ parsed should matchPattern {
+ case parser.Success(List(SimpleStm(udf), SimpleStm(select)), _) =>
+ }
}
"Parser" should "parse CREATE multiple FUNCTIONS" in {
@@ -854,8 +926,9 @@ class ParagraphParserTest extends FlatSpec
parsed.get.size should be(3)
- parsed.get should be(List(SimpleStm(udf1), SimpleStm(select), SimpleStm(udf2)))
-
+ parsed should matchPattern {
+ case parser.Success(List(SimpleStm(udf1), SimpleStm(select), SimpleStm(udf2)), _) =>
+ }
}
"Parser" should "parse CREATE Materialized View" in {
@@ -867,7 +940,8 @@ class ParagraphParserTest extends FlatSpec
val parsed = parser.parseAll(parser.queries, query)
- parsed.get(0) should be(SimpleStm(query))
-
+ parsed should matchPattern {
+ case parser.Success(List(SimpleStm(query)), _) =>
+ }
}
}
From 36e3bdb245336c675b2f748683b3438535f27aba Mon Sep 17 00:00:00 2001
From: DuyHai DOAN
Date: Sun, 10 Jan 2016 15:44:53 +0100
Subject: [PATCH 9/9] Fix random test failure
---
cassandra/pom.xml | 1 -
.../driver/core/TableMetadataWrapper.scala | 23 +++++++++++++++++++
.../zeppelin/cassandra/DisplaySystem.scala | 2 +-
.../cassandra/CassandraInterpreterTest.java | 21 +++++++++++++++++
.../scalate/DescribeKeyspace_live_data.html | 2 +-
...DescribeTable_live_data_complex_table.html | 2 +-
6 files changed, 47 insertions(+), 4 deletions(-)
create mode 100644 cassandra/src/main/scala/com/datastax/driver/core/TableMetadataWrapper.scala
diff --git a/cassandra/pom.xml b/cassandra/pom.xml
index ca8c5e81150..1b825b4f0da 100644
--- a/cassandra/pom.xml
+++ b/cassandra/pom.xml
@@ -167,7 +167,6 @@
-
diff --git a/cassandra/src/main/scala/com/datastax/driver/core/TableMetadataWrapper.scala b/cassandra/src/main/scala/com/datastax/driver/core/TableMetadataWrapper.scala
new file mode 100644
index 00000000000..feddbe1a174
--- /dev/null
+++ b/cassandra/src/main/scala/com/datastax/driver/core/TableMetadataWrapper.scala
@@ -0,0 +1,23 @@
+/*
+ * 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 com.datastax.driver.core
+
+case class TableMetadataWrapper(val meta: TableMetadata) {
+ def exportTableOnlyAsString(): String = {
+ meta.asCQLQuery(true)
+ }
+}
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
index 6380b1171ed..135d4cd780e 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
@@ -76,7 +76,7 @@ object DisplaySystem {
val indicesAsCQL = indicesDetails.map(_.asCQL).mkString("\n")
engine.layout(TABLE_DETAILS_TEMPLATE,
- Map[String, Any]("tableDetails" -> TableDetails(tableName, columnsDetails, indicesDetails, meta.exportAsString(), indicesAsCQL), "withCaption" -> withCaption))
+ Map[String, Any]("tableDetails" -> TableDetails(tableName, columnsDetails, indicesDetails, TableMetadataWrapper(meta).exportTableOnlyAsString(), indicesAsCQL), "withCaption" -> withCaption))
}
}
diff --git a/cassandra/src/test/java/org/apache/zeppelin/cassandra/CassandraInterpreterTest.java b/cassandra/src/test/java/org/apache/zeppelin/cassandra/CassandraInterpreterTest.java
index 4819e97ce3c..560c57e8239 100644
--- a/cassandra/src/test/java/org/apache/zeppelin/cassandra/CassandraInterpreterTest.java
+++ b/cassandra/src/test/java/org/apache/zeppelin/cassandra/CassandraInterpreterTest.java
@@ -599,6 +599,27 @@ public void should_describe_aggregate() throws Exception {
assertThat(actual.code()).isEqualTo(Code.SUCCESS);
}
+
+ @Test
+ @Ignore
+ //TODO activate test when using Java 8 and C* 3.x
+ public void should_describe_materialized_view() throws Exception {
+ //Given
+ Properties properties = new Properties();
+ properties.setProperty(CASSANDRA_HOSTS, "127.0.0.1");
+ properties.setProperty(CASSANDRA_PORT, "9042");
+ Interpreter interpreter = new CassandraInterpreter(properties);
+ interpreter.open();
+
+ final String query = "DESCRIBE MATERIALIZED VIEWS;";
+
+ //When
+ final InterpreterResult actual = interpreter.interpret(query, intrContext);
+
+ //Then
+ assertThat(actual.code()).isEqualTo(Code.SUCCESS);
+ }
+
@Test
public void should_describe_table() throws Exception {
//Given
diff --git a/cassandra/src/test/resources/scalate/DescribeKeyspace_live_data.html b/cassandra/src/test/resources/scalate/DescribeKeyspace_live_data.html
index cb06f7724e5..344780a9bae 100644
--- a/cassandra/src/test/resources/scalate/DescribeKeyspace_live_data.html
+++ b/cassandra/src/test/resources/scalate/DescribeKeyspace_live_data.html
@@ -1 +1 @@
-
\ No newline at end of file
diff --git a/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html b/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
index bbb778b82db..fd3ee67f7c1 100644
--- a/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
+++ b/cassandra/src/test/resources/scalate/DescribeTable_live_data_complex_table.html
@@ -1 +1 @@
-