[ZEPPELIN-559] Cassandra interpreter v2
### What is this PR for?
* Update the **Cassandra** interpreter to V2 to support new **schema commands**
to describe **Cassandra** 3.x features:
* User Defined Functions
* User Defined Aggregates
* Materialized Views
* Add support for single line comment using **double slashes** (//)
* Add **DESCRIBE TYPES**
* The Java driver version is bumped to **3.0.0-rc1**
* The contextual **HELP menu** is also updated and a _ChangeLog_ section is
added.
### What type of PR is it?
[Improvement]
### Todos
* [x] - Add new PR to update official Cassandra interpreter with new features
* [x] - Test steps executed and confirmed working by the community
* [x] - Code review by the community (warning, **Scala** inside)
### Is there a relevant Jira issue?
**[ZEPPELIN-559]**
**[ZEPPELIN-575]** for doc
### How should this be tested?
1. Download and install locally **[Cassandra 3.1.1]**
2. Start **Cassandra**
3. Clone this pull request locally with:
1. _git fetch origin pull/600/head:CassandraInterpreterV2_
2. _git checkout CassandraInterpreterV2_
4. Build this version of Zeppelin with _mvn clean package -DskipTests_
5. Start **Zeppelin** and update the property _cassandra.hosts_ of the
**Cassandra** interpreter (set it to _localhost_ or _127.0.0.1_ depending on
your configuration)
6. In a paragraph, execute all the **CQL** statements given in this
**[CassandraInterpreterV2TestData.cql]** by copy-pasting them
7. Start a new _%cassandra_ paragraph and execute **DESCRIBE FUNCTION
test.maxOf;**. You should be able to see:

8. Start a new _%cassandra_ paragraph and execute **DESCRIBE AGGREGATE
test.group_by;**. You should be able to see:

9. Start a new _%cassandra_ paragraph and execute **DESCRIBE MATERIALIZED VIEW
test.user_by_country;**. You should be able to see:

10. Start a new _%cassandra_ paragraph and execute **SELECT
id,val1,val2,maxOf(val1,val2) FROM test.test_max;**. You should be able to see:

11. Start a new _%cassandra_ paragraph and execute **SELECT
group_by(category,sales_count) FROM test.items;**. You should be able to see:

12. Start a new _%cassandra_ paragraph and execute **SELECT * FROM
test.user_by_country WHERE country='FR';**. You should be able to see:

### Questions:
* Does the licenses files need update? --> **No**
* Is there breaking changes for older versions? --> **No**
* Does this needs documentation? --> **Yes**
[ZEPPELIN-559]: https://issues.apache.org/jira/browse/ZEPPELIN-559
[ZEPPELIN-575]: https://issues.apache.org/jira/browse/ZEPPELIN-575
[Cassandra 3.1.1]: http://cassandra.apache.org/download/
[CassandraInterpreterV2TestData.cql]:
https://gist.githubusercontent.com/doanduyhai/5d88aaf3820be28474d2/raw/e5b5d9c325a17a58c2f27bff454db999fd3a3a66/CassandraInterpreterV2TestData.cql
Author: DuyHai DOAN <[email protected]>
Closes #600 from doanduyhai/CassandraInterpreter-V2 and squashes the following
commits:
36e3bdb [DuyHai DOAN] Fix random test failure
a2d831b [DuyHai DOAN] Refactor after code review
41b8667 [DuyHai DOAN] Tune regular expression for FUNCTION creation pattern
138804c [DuyHai DOAN] Fix CSS style for UDF & MV in menu display
6509da5 [DuyHai DOAN] Fix failing tests
7a5ac39 [DuyHai DOAN] Update RegExp for UDF creation to fix multiple statements
match
6ea9e55 [DuyHai DOAN] Update help menu and changelog
6b46076 [DuyHai DOAN] Add Support for UDF, UDA and Materialized Views
058161d [DuyHai DOAN] Upgrade Java driver version to 3.0.0-rc1
Project: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/repo
Commit:
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/commit/11a45e2e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/tree/11a45e2e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/diff/11a45e2e
Branch: refs/heads/master
Commit: 11a45e2e225b404e5ca5f2f2137217202895d2d8
Parents: 9308ee1
Author: DuyHai DOAN <[email protected]>
Authored: Sun Jan 10 15:44:53 2016 +0100
Committer: Felix Cheung <[email protected]>
Committed: Sun Jan 24 10:04:46 2016 -0800
----------------------------------------------------------------------
cassandra/pom.xml | 30 +-
.../main/resources/scalate/aggregateDetails.ssp | 81 ++
.../main/resources/scalate/allAggregates.ssp | 68 ++
.../src/main/resources/scalate/allFunctions.ssp | 68 ++
.../resources/scalate/allMaterializedViews.ssp | 68 ++
.../src/main/resources/scalate/allTables.ssp | 8 -
.../src/main/resources/scalate/allUDTs.ssp | 61 ++
.../scalate/dropDownMenuForKeyspace.ssp | 37 +-
.../main/resources/scalate/functionDetails.ssp | 77 ++
.../src/main/resources/scalate/helpMenu.ssp | 135 ++-
.../main/resources/scalate/keyspaceContent.ssp | 90 ++
.../main/resources/scalate/keyspaceDetails.ssp | 2 +-
.../scalate/materializedViewDetails.ssp | 109 +++
cassandra/src/main/resources/scalate/menu.ssp | 22 +-
.../src/main/resources/scalate/tableDetails.ssp | 83 +-
.../src/main/resources/scalate/udtDetails.ssp | 2 +-
.../driver/core/TableMetadataWrapper.scala | 23 +
.../zeppelin/cassandra/DisplaySystem.scala | 417 +++++++--
.../zeppelin/cassandra/EnhancedSession.scala | 108 ++-
.../zeppelin/cassandra/InterpreterLogic.scala | 25 +-
.../zeppelin/cassandra/MetaDataHierarchy.scala | 31 +-
.../zeppelin/cassandra/ParagraphParser.scala | 188 +++-
.../zeppelin/cassandra/TextBlockHierarchy.scala | 54 +-
.../cassandra/CassandraInterpreterTest.java | 114 ++-
.../cassandra/InterpreterLogicTest.java | 4 +-
.../test/resources/scalate/DescribeCluster.html | 99 +--
.../scalate/DescribeKeyspace_live_data.html | 820 +----------------
.../resources/scalate/DescribeKeyspaces.html | 401 +--------
.../DescribeTable_live_data_complex_table.html | 327 +------
.../scalate/DescribeType_live_data_address.html | 138 +--
...ve_data_address_within_current_keyspace.html | 138 +--
cassandra/src/test/resources/scalate/Help.html | 871 +------------------
.../cassandra/ParagraphParserTest.scala | 544 ++++++++++--
33 files changed, 2122 insertions(+), 3121 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/cassandra/pom.xml b/cassandra/pom.xml
index 57b501a..1b825b4 100644
--- a/cassandra/pom.xml
+++ b/cassandra/pom.xml
@@ -35,18 +35,19 @@
<url>http://zeppelin.incubator.apache.org</url>
<properties>
- <cassandra.driver.version>2.1.7.1</cassandra.driver.version>
+ <cassandra.driver.version>3.0.0-rc1</cassandra.driver.version>
<snappy.version>1.0.5.4</snappy.version>
- <lz4.version>1.2.0</lz4.version>
- <scala.version>2.11.7</scala.version>
- <scala.binary.version>2.11</scala.binary.version>
- <commons-lang.version>3.4</commons-lang.version>
+ <lz4.version>1.3.0</lz4.version>
+ <scala.version>2.10.4</scala.version>
+ <scala.binary.version>2.10</scala.binary.version>
+ <commons-lang.version>3.3.2</commons-lang.version>
<scalate.version>1.7.1</scalate.version>
+ <cassandra.guava.version>16.0.1</cassandra.guava.version>
<!--TEST-->
<scalatest.version>2.2.4</scalatest.version>
<junit.version>4.12</junit.version>
- <achilles.version>3.2.2</achilles.version>
+ <achilles.version>3.2.4-Zeppelin</achilles.version>
<assertj.version>1.7.0</assertj.version>
<mockito.version>1.9.5</mockito.version>
</properties>
@@ -65,6 +66,12 @@
<version>${cassandra.driver.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${cassandra.guava.version}</version>
+ </dependency>
+
<!-- Compression libraries for the cassandra-driver protocol. -->
<!-- Include both compression options to make to simplify deployment.
-->
@@ -130,7 +137,7 @@
<dependency>
<groupId>info.archinnov</groupId>
- <artifactId>achilles-junit</artifactId>
+ <artifactId>achilles-embedded</artifactId>
<version>${achilles.version}</version>
<scope>test</scope>
<exclusions>
@@ -146,13 +153,6 @@
</dependency>
<dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>16.0</version>
- <scope>test</scope>
- </dependency>
-
- <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
@@ -167,7 +167,6 @@
</dependency>
</dependencies>
-
<build>
<plugins>
<!-- Plugin to compile Scala code -->
@@ -293,7 +292,6 @@
</execution>
</executions>
</plugin>
-
</plugins>
</build>
</project>
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/aggregateDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/aggregateDetails.ssp
b/cassandra/src/main/resources/scalate/aggregateDetails.ssp
new file mode 100644
index 0000000..02800a2
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/aggregateDetails.ssp
@@ -0,0 +1,81 @@
+<%--
+/*
+* 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 sameNameAggregateDetails: SameNameAggregateDetails %>
+<%@ val withCaption: Boolean%>
+<div class="row">
+ <div class="col-md-2"/>
+ <div class="col-md-8 col-offset-md-2">
+ #for (aggregate <- sameNameAggregateDetails.aggregates)
+ <div class="panel panel-default table-responsive table-bordered">
+ <table class="table">
+ #if(withCaption)
+ <caption><h4 class="text-success"><i class="glyphicon
glyphicon-retweet"/> ${aggregate.name}</h4></caption>
+ #end
+ <tbody>
+ <tr>
+ <td class="col-md-6"><strong>Keyspace</strong></td>
+ <td class="col-md-6
text-danger">${aggregate.keyspace}</td>
+ </tr>
+ <tr>
+ <td class="col-md-6"><strong>Arguments</strong></td>
+ <td
class="col-md-6">${aggregate.arguments.toList.mkString(", ")}</td>
+ </tr>
+ <tr>
+ <td class="col-md-6"><strong>State
Function</strong></td>
+ <td class="col-md-6">${aggregate.sFunc}</td>
+ </tr>
+ <tr>
+ <td class="col-md-6"><strong>State Type</strong></td>
+ <td class="col-md-6">${aggregate.sType}</td>
+ </tr>
+ #if(aggregate.finalFunc.isDefined)
+ <tr>
+ <td class="col-md-6"><strong>Final
Function</strong></td>
+ <td class="col-md-6">${aggregate.finalFunc.get}</td>
+ </tr>
+ #end
+ #if(aggregate.initCond.isDefined)
+ <tr>
+ <td class="col-md-6"><strong>Initial
State</strong></td>
+ <td class="col-md-6">${aggregate.initCond.get}</td>
+ </tr>
+ #end
+ <tr>
+ <td class="col-md-6"><strong>Return type</strong></td>
+ <td class="col-md-6">${aggregate.returnType}</td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="panel-footer">
+ <a data-toggle="collapse"
data-target="#${aggregate.uniqueId}_asCQL">
+ <strong>As CQL statement</strong>
+ <span class="caret"></span>
+ </a>
+ <br/><br/>
+ <div class="text-success collapse"
id="${aggregate.uniqueId}_asCQL">
+ <pre class="well">${aggregate.asCQL}</pre>
+ </div>
+ </div>
+ </div>
+ <hr/>
+ #end
+ </div>
+ <div class="col-md-2"></div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/allAggregates.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/allAggregates.ssp
b/cassandra/src/main/resources/scalate/allAggregates.ssp
new file mode 100644
index 0000000..f093c50
--- /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]] %>
+
+<div class="container">
+
+ <div class="row">
+ <div class="panel-group" role="tablist" aria-multiselectable="true">
+ #for (((ksId,ksName), aggregates) <- allAggregates)
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${ksId}" aria-expanded="false">
+ <span class="text-danger"><i class="glyphicon
glyphicon-folder-open"/> ${ksName}</span>
+ </a>
+ </h4>
+ </div>
+ <div id="${ksId}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ <div class="row">
+ <div class="col-md-2"/>
+ <div class="col-md-8 col-offset-md-2
table-responsive table-bordered">
+ <table class="table">
+ <thead>
+ <tr>
+ <th>Aggregate</th>
+ <th>Return Type</th>
+ </tr>
+ </thead>
+ <tbody>
+ #for (aggregate <- aggregates)
+ <tr class="text-success">
+ <td>${aggregate.name +
aggregate.arguments.mkString("(", ", ", ")")}</td>
+ <td>${aggregate.returnType}</td>
+ </tr>
+ #end
+
+ </tbody>
+ </table>
+ </div>
+ <div class="col-md-2"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ #end
+ </div>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/allFunctions.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/allFunctions.ssp
b/cassandra/src/main/resources/scalate/allFunctions.ssp
new file mode 100644
index 0000000..fc756a4
--- /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]] %>
+
+<div class="container">
+
+ <div class="row">
+ <div class="panel-group" role="tablist" aria-multiselectable="true">
+ #for (((ksId,ksName), functions) <- allFunctions)
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${ksId}" aria-expanded="false">
+ <span class="text-danger"><i class="glyphicon
glyphicon-folder-open"/> ${ksName}</span>
+ </a>
+ </h4>
+ </div>
+ <div id="${ksId}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ <div class="row">
+ <div class="col-md-2"/>
+ <div class="col-md-8 col-offset-md-2
table-responsive table-bordered">
+ <table class="table">
+ <thead>
+ <tr>
+ <th>Function</th>
+ <th>Return Type</th>
+ </tr>
+ </thead>
+ <tbody>
+ #for (function <- functions)
+ <tr class="text-success">
+ <td>${function.name +
function.arguments.mkString("(",", ", ")")}</td>
+ <td>${function.returnType}</td>
+ </tr>
+ #end
+
+ </tbody>
+ </table>
+ </div>
+ <div class="col-md-2"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ #end
+ </div>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/allMaterializedViews.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/allMaterializedViews.ssp
b/cassandra/src/main/resources/scalate/allMaterializedViews.ssp
new file mode 100644
index 0000000..8ffee57
--- /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]] %>
+<div class="container">
+
+ <div class="row">
+ <div class="panel-group" role="tablist" aria-multiselectable="true">
+ #for (((ksId,ksName), mvs) <- allMVs)
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${ksId}" aria-expanded="false">
+ <span class="text-danger"><i class="glyphicon
glyphicon-folder-open"/> ${ksName}</span>
+ </a>
+ </h4>
+ </div>
+ <div id="${ksId}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ <div class="row">
+ <div class="col-md-2"/>
+ <div class="col-md-8 col-offset-md-2
table-responsive table-bordered">
+ <table class="table">
+ <thead>
+ <tr><th>Materialized View</th></tr>
+ </thead>
+ <tbody>
+ #for (mv <- mvs)
+
+ <tr class="text-primary">
+ <td>
+ ${mv.name}
+ <i class="glyphicon
glyphicon-arrow-right"/>
+ <i class="glyphicon
glyphicon-th-list"/>
+ ${mv.baseTable}
+ </td>
+ </tr>
+ #end
+
+ </tbody>
+ </table>
+ </div>
+ <div class="col-md-2"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ #end
+ </div>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/allTables.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/allTables.ssp
b/cassandra/src/main/resources/scalate/allTables.ssp
index b363bee..810881b 100644
--- a/cassandra/src/main/resources/scalate/allTables.ssp
+++ b/cassandra/src/main/resources/scalate/allTables.ssp
@@ -24,7 +24,6 @@
<div class="row">
<div class="panel-group" role="tablist" aria-multiselectable="true">
#for (((ksId,ksName), tables) <- allTables)
-
<div class="panel panel-default">
<div class="panel-heading" role="tab">
<h4 class="panel-title">
@@ -38,8 +37,6 @@
<div class="row">
<div class="col-md-2"/>
<div class="col-md-8 col-offset-md-2
table-responsive table-bordered">
- #if (tables.nonEmpty)
-
<table class="table">
<thead>
<tr><th>Tables</th></tr>
@@ -52,10 +49,6 @@
</tbody>
</table>
- #else
- <span><h4>No Table</h4></span>
-
- #end
</div>
<div class="col-md-2"/>
</div>
@@ -63,7 +56,6 @@
</div>
</div>
#end
-
</div>
</div>
</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/allUDTs.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/allUDTs.ssp
b/cassandra/src/main/resources/scalate/allUDTs.ssp
new file mode 100644
index 0000000..559ef41
--- /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]] %>
+<div class="container">
+
+ <div class="row">
+ <div class="panel-group" role="tablist" aria-multiselectable="true">
+ #for (((ksId,ksName), udts) <- allUDTs)
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${ksId}" aria-expanded="false">
+ <span class="text-danger"><i class="glyphicon
glyphicon-folder-open"/> ${ksName}</span>
+ </a>
+ </h4>
+ </div>
+ <div id="${ksId}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ <div class="row">
+ <div class="col-md-2"/>
+ <div class="col-md-8 col-offset-md-2
table-responsive table-bordered">
+ <table class="table">
+ <thead>
+ <tr><th>UDT</th></tr>
+ </thead>
+ <tbody>
+ #for (udt <- udts)
+
+ <tr
class="text-warning"><td>${udt}</td></tr>
+ #end
+
+ </tbody>
+ </table>
+ </div>
+ <div class="col-md-2"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ #end
+ </div>
+ </div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/dropDownMenuForKeyspace.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/dropDownMenuForKeyspace.ssp
b/cassandra/src/main/resources/scalate/dropDownMenuForKeyspace.ssp
index 74f6fbc..6c2aad1 100644
--- a/cassandra/src/main/resources/scalate/dropDownMenuForKeyspace.ssp
+++ b/cassandra/src/main/resources/scalate/dropDownMenuForKeyspace.ssp
@@ -35,8 +35,19 @@
#end
#end
- #if(ksContent.udts.nonEmpty)
+ #if(ksContent.views.nonEmpty)
+ <li role="separator" class="divider text-muted"></li>
+ <li class="dropdown-header"><span
class="text-primary">Materialized Views</span></li>
+ #for((id,name,_) <- ksContent.views)
+ <li>
+ <a role="button" data-toggle="collapse"
data-target="#${id}">
+ <span class="text-primary"><i class="glyphicon
glyphicon-eye-open"/> ${name}</span>
+ </a>
+ </li>
+ #end
+ #end
+ #if(ksContent.udts.nonEmpty)
<li role="separator" class="divider text-muted"></li>
<li class="dropdown-header"><span class="text-warning">User
Defined Types</span></li>
#for((id,name,_) <- ksContent.udts)
@@ -47,6 +58,30 @@
</li>
#end
#end
+
+ #if(ksContent.functions.nonEmpty)
+ <li role="separator" class="divider text-muted"></li>
+ <li class="dropdown-header"><span
class="text-success">Functions</span></li>
+ #for((id,name,_) <- ksContent.functions)
+ <li>
+ <a role="button" data-toggle="collapse"
data-target="#${id}">
+ <span class="text-success"><i class="glyphicon
glyphicon-random"/> ${name}</span>
+ </a>
+ </li>
+ #end
+ #end
+
+ #if(ksContent.aggregates.nonEmpty)
+ <li role="separator" class="divider text-muted"></li>
+ <li class="dropdown-header"><span
class="text-success">Aggregates</span></li>
+ #for((id,name,_) <- ksContent.aggregates)
+ <li>
+ <a role="button" data-toggle="collapse"
data-target="#${id}">
+ <span class="text-success"><i class="glyphicon
glyphicon-retweet"/> ${name}</span>
+ </a>
+ </li>
+ #end
+ #end
</ul>
</a>
</li>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/functionDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/functionDetails.ssp
b/cassandra/src/main/resources/scalate/functionDetails.ssp
new file mode 100644
index 0000000..7d61400
--- /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%>
+<div class="row">
+ <div class="col-md-2"/>
+ <div class="col-md-8 col-offset-md-2">
+ #for (function <- sameNameFunctionDetails.functions)
+ <div class="panel panel-default table-responsive table-bordered">
+ <table class="table">
+ #if(withCaption)
+ <caption><h4 class="text-success"><i class="glyphicon
glyphicon-random"/> ${function.name}</h4></caption>
+ #end
+ <tbody>
+ <tr>
+ <td class="col-md-6"><strong>Keyspace</strong></td>
+ <td class="col-md-6
text-danger">${function.keyspace}</td>
+ </tr>
+ <tr>
+ <td class="col-md-6"><strong>Arguments</strong></td>
+ <td
class="col-md-6">${function.arguments.toList.mkString(", ")}</td>
+ </tr>
+ <tr>
+ <td class="col-md-6"><strong>Null Input</strong></td>
+ #if(function.calledOnNullInput)
+ <td class="col-md-6">CALLED ON NULL INPUT</td>
+ #else
+ <td class="col-md-6">RETURN NULL ON NULL INPUT</td>
+ #end
+ </tr>
+ <tr>
+ <td class="col-md-6"><strong>Return type</strong></td>
+ <td class="col-md-6">${function.returnType}</td>
+ </tr>
+ <tr>
+ <td class="col-md-6"><strong>Language</strong></td>
+ <td class="col-md-6">${function.language}</td>
+ </tr>
+ <tr>
+ <td class="col-md-6"><strong>Body</strong></td>
+ <td class="col-md-6">${escape(function.body)}</td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="panel-footer">
+ <a data-toggle="collapse"
data-target="#${function.uniqueId}_asCQL">
+ <strong>As CQL statement</strong>
+ <span class="caret"></span>
+ </a>
+ <br/><br/>
+ <div class="text-success collapse"
id="${function.uniqueId}_asCQL">
+ <pre class="well">${function.asCQL}</pre>
+ </div>
+ </div>
+ </div>
+ <hr/>
+ #end
+ </div>
+ <div class="col-md-2"></div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/helpMenu.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/helpMenu.ssp
b/cassandra/src/main/resources/scalate/helpMenu.ssp
index 1c793ec..26ff117 100644
--- a/cassandra/src/main/resources/scalate/helpMenu.ssp
+++ b/cassandra/src/main/resources/scalate/helpMenu.ssp
@@ -27,7 +27,9 @@
<%@ val preparedStatementsId: UUID = UUIDs.random() %>
<%@ val dynamicFormsId: UUID = UUIDs.random() %>
<%@ val configurationId: UUID = UUIDs.random() %>
-<%@ val miscId: UUID = UUIDs.random() %>
+<%@ val sharedStatesId: UUID = UUIDs.random() %>
+<%@ val changelogId: UUID = UUIDs.random() %>
+<%@ val contactsId: UUID = UUIDs.random() %>
<br/>
<br/>
@@ -70,10 +72,20 @@
</a>
</li>
<li>
- <a role="button" data-toggle="collapse"
data-target="#${miscId}">
- <span class="text-info"><i class="glyphicon
glyphicon-bookmark"/> Misc</span>
+ <a role="button" data-toggle="collapse"
data-target="#${sharedStatesId}">
+ <span class="text-info"><i class="glyphicon
glyphicon-bookmark"/> Shared States</span>
</a>
</li>
+ <li>
+ <a role="button" data-toggle="collapse"
data-target="#${changelogId}">
+ <span class="text-info"><i class="glyphicon
glyphicon-bookmark"/> Change Log</span>
+ </a>
+ </li>
+ <li>
+ <a role="button" data-toggle="collapse"
data-target="#${contactsId}">
+ <span class="text-info"><i class="glyphicon
glyphicon-bookmark"/> Contacts & Bugs</span>
+ </a>
+ </li>
</ul>
</a>
</li>
@@ -91,12 +103,12 @@
<ul class="dropdown-menu">
<li>
<a role="button">
- <span class="text-info">Version
<strong>1.0</strong></span>
+ <span class="text-info">Version
<strong>2.0</strong></span>
</a>
</li>
<li>
<a role="button">
- <span class="text-info">Java Driver Version
<strong>2.1.7.1</strong></span>
+ <span class="text-info">Java Driver Version
<strong>3.0.0-rc1</strong></span>
</a>
</li>
<li>
@@ -237,7 +249,7 @@
<h3>II Comments</h3>
<p>
It is possible to add comments between statements.
Single line comments start with the
- <strong>hash</strong> sign (#). Multi-line comments
are enclosed between
+ <strong>hash</strong> sign (#) or <strong>double
slashes</strong> (//). Multi-line comments are enclosed between
<strong>/**</strong> and
<strong>**/</strong>. Ex:
<br/>
@@ -246,9 +258,12 @@
<div class="col-md-8 col-md-offset-2">
<pre>
- #First comment
+ #Single line comment style 1
INSERT INTO users(login,name) VALUES('jdoe','John DOE');
+ //Single line comment style 2
+
+
/**
Multi line
comments
@@ -314,6 +329,22 @@
<td>List all existing keyspaces in the
cluster and for each, all the tables name</td>
</tr>
<tr>
+ <td><strong>DESCRIBE TYPES;</strong></td>
+ <td>List all existing keyspaces in the
cluster and for each, all the types name</td>
+ </tr>
+ <tr>
+ <td><strong>DESCRIBE
FUNCTIONS;</strong></td>
+ <td>List all existing keyspaces in the
cluster and for each, all the functions name and arguments</td>
+ </tr>
+ <tr>
+ <td><strong>DESCRIBE
AGGREGATES;</strong></td>
+ <td>List all existing keyspaces in the
cluster and for each, all the aggregates name and arguments</td>
+ </tr>
+ <tr>
+ <td><strong>DESCRIBE MATERIALIZED
VIEWS;</strong></td>
+ <td>List all existing keyspaces in the
cluster and for each, all the materialized view name</td>
+ </tr>
+ <tr>
<td><strong>DESCRIBE KEYSPACE <keyspace
name>;</strong></td>
<td>Describe the given keyspace
configuration and all its table details (name, columns, ...)</td>
</tr>
@@ -333,6 +364,30 @@
the default <em>system</em> keyspace
is used. If no type is found, an error message is raised
</td>
</tr>
+ <tr>
+ <td><strong>DESCRIBE FUNCTION
<em>(<keyspace name>).</em><function name>;</strong></td>
+ <td>
+ Describe the given function. If the
keyspace is not provided, the current
+ <strong>logged in</strong> keyspace is
used. If there is no logged in keyspace,
+ the default <em>system</em> keyspace
is used. If no function is found, an error message is raised
+ </td>
+ </tr>
+ <tr>
+ <td><strong>DESCRIBE AGGREGATE
<em>(<keyspace name>).</em><aggregate name>;</strong></td>
+ <td>
+ Describe the given aggregate. If the
keyspace is not provided, the current
+ <strong>logged in</strong> keyspace is
used. If there is no logged in keyspace,
+ the default <em>system</em> keyspace
is used. If no aggregate is found, an error message is raised
+ </td>
+ </tr>
+ <tr>
+ <td><strong>DESCRIBE MATERIALIZED VIEW
<em>(<keyspace name>).</em><view name>;</strong></td>
+ <td>
+ Describe the given materialized view.
If the keyspace is not provided, the current
+ <strong>logged in</strong> keyspace is
used. If there is no logged in keyspace,
+ the default <em>system</em> keyspace
is used. If no materialized view is found, an error message is raised
+ </td>
+ </tr>
</tbody>
</table>
<br/>
@@ -342,9 +397,7 @@
</p>
<h3>II Schema Display</h3>
<p>
- The schema objects (cluster, keyspace, table &
type) are displayed in a tabular format.
- There is a <strong>drop-down</strong> 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
<strong>drop-down</strong> menu on the top left corner to expand objects
details. On the top right menu is shown the Icon legend.
</p>
</div>
@@ -886,16 +939,68 @@
<div class="panel panel-default">
<div class="panel-heading" role="tab">
<h4 class="panel-title">
- <a role="button" data-toggle="collapse"
data-target="#${miscId}" aria-expanded="false">
- <span
class="text-info"><strong>Miscellaneous</strong></span>
+ <a role="button" data-toggle="collapse"
data-target="#${sharedStatesId}" aria-expanded="false">
+ <span class="text-info"><strong>Shared
states</strong></span>
</a>
</h4>
</div>
- <div id="${miscId}" class="panel-collapse collapse" role="tabpanel">
+ <div id="${sharedStatesId}" class="panel-collapse collapse"
role="tabpanel">
<div class="panel-body">
- <h3>Execution parallelism</h3>
- It is possible to execute many paragraphs in parallel. However,
at the back-end side, weâre still using <strong>synchronous</strong> queries.
Asynchronous execution is only possible when it is possible to return a Future
value in the <strong>InterpreterResult</strong>. 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. <em>Asynchronous
execution</em> is only possible when it is possible to return a
<strong>Future</strong> value in the <strong>InterpreterResult</strong>. It may
be an interesting proposal for the <strong>Zeppelin</strong> project.
+ <br/>
+ Another caveat is that the same
<strong>com.datastax.driver.core.Session</strong> object is used for
<strong>all</strong> notebooks and paragraphs. Consequently, if you use the
<em>USE keyspace name;</em> statement to log into a keyspace, it will change
the keyspace for <strong>all current users</strong> of the Cassandra
interpreter because we only create 1
<strong>com.datastax.driver.core.Session</strong> object per instance of
<strong>Cassandra</strong> interpreter.
+ <br/>
+ The same remark does apply to the <strong>prepared statement
hash map</strong>, it is shared by <strong>all users</strong> using the same
instance of <strong>Cassandra</strong> interpreter.
+ <br/>
+ Until <strong>Zeppelin</strong> offers a real multi-users
separation, there is a work-around to segregate user environment and states:
<em>create different Cassandra interpreter instances</em>
+ <br/>
+ <ol>
+ <li>First go to the <strong>Interpreter</strong> menu and
click on the <strong>Create</strong> button</li>
+ <li>In the interpreter creation form, put
<strong>cass-instance2</strong> as <strong>Name</strong> and select the
<strong>cassandra</strong> in the interpreter drop-down list</li>
+ <li>Click on <strong>Save</strong> to create the new
interpreter instance. Now you should be able to see it in the interpreter
list</li>
+ <li>Go back to your notebook and click on the
<strong>Gear</strong> icon to configure interpreter bindings. You should be
able to see and select the <strong>cass-instance2</strong> interpreter instance
in the available interpreter list instead of the standard
<strong>cassandra</strong> instance</li>
+ </ol>
</div>
</div>
+ </div>
+
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${changelogId}" aria-expanded="false">
+ <span class="text-info"><strong>Change Log</strong></span>
+ </a>
+ </h4>
+ </div>
+ <div id="${changelogId}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ <strong>2.0</strong> :
+ <br/>
+ <ul>
+ <li>Update help menu and add changelog</li>
+ <li>Add Support for User Defined Functions, User Defined
Aggregates and Materialized Views</li>
+ <li>Upgrade Java driver version to
<strong>3.0.0-rc1</strong></li>
+ </ul>
+ <strong>1.0</strong> :
+ <br/>
+ <ul>
+ <li>Initial version</li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${contactsId}" aria-expanded="false">
+ <span class="text-info"><strong>Contact &
Bugs</strong></span>
+ </a>
+ </h4>
+ </div>
+ <div id="${contactsId}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ If you encounter a bug for this interpreter, please create a
<a
href="https://issues.apache.org/jira/browse/ZEPPELIN-382?jql=project%20%3D%20ZEPPELIN"
target="_blank"><strong>JIRA</strong></a> ticket and ping me on Twitter at <a
href="https://twitter.com/doanduyhai"
target="_blank"><strong>@doanduyhai</strong></a>
+ </div>
+ </div>
</div>
</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/keyspaceContent.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/keyspaceContent.ssp
b/cassandra/src/main/resources/scalate/keyspaceContent.ssp
index 5139069..152c657 100644
--- a/cassandra/src/main/resources/scalate/keyspaceContent.ssp
+++ b/cassandra/src/main/resources/scalate/keyspaceContent.ssp
@@ -57,6 +57,36 @@
</div>
#end
+ #if (ksContent.views.nonEmpty)
+ <!-- Materialized Views -->
+ <table width="100%">
+ <td><hr /></td>
+ <td style="width:1px; padding: 0 10px; white-space: nowrap;"><strong
class="text-primary">Materialized Views</strong></td>
+ <td><hr /></td>
+ </table>
+ <div class="row">
+ <div class="panel-group" role="tablist" aria-multiselectable="true">
+ #for((id,name,viewHTML) <- ksContent.views)
+
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${id}" aria-expanded="false">
+ <span class="text-primary"><i class="glyphicon
glyphicon-eye-open"/> ${name}</span>
+ </a>
+ </h4>
+ </div>
+ <div id="${id}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ ${unescape(viewHTML)}
+ </div>
+ </div>
+ </div>
+ #end
+ </div>
+ </div>
+ #end
+
#if (ksContent.udts.nonEmpty)
<!-- UDTs -->
<table width="100%">
@@ -88,4 +118,64 @@
</div>
#end
+ #if (ksContent.functions.nonEmpty)
+ <!-- Functions -->
+ <table width="100%">
+ <td><hr /></td>
+ <td style="width:1px; padding: 0 10px; white-space: nowrap;"><strong
class="text-success">Functions</strong></td>
+ <td><hr /></td>
+ </table>
+ <div class="row">
+ <div class="panel-group" role="tablist" aria-multiselectable="true">
+ #for((id,name,functionHTML) <- ksContent.functions)
+
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${id}" aria-expanded="false">
+ <span class="text-success"><i class="glyphicon
glyphicon-random"/> ${name}</span>
+ </a>
+ </h4>
+ </div>
+ <div id="${id}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ ${unescape(functionHTML)}
+ </div>
+ </div>
+ </div>
+ #end
+ </div>
+ </div>
+ #end
+
+ #if (ksContent.aggregates.nonEmpty)
+ <!-- Aggregates -->
+ <table width="100%">
+ <td><hr /></td>
+ <td style="width:1px; padding: 0 10px; white-space: nowrap;"><strong
class="text-success">Aggregates</strong></td>
+ <td><hr /></td>
+ </table>
+ <div class="row">
+ <div class="panel-group" role="tablist" aria-multiselectable="true">
+ #for((id,name,aggregateHTML) <- ksContent.aggregates)
+
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a role="button" data-toggle="collapse"
data-target="#${id}" aria-expanded="false">
+ <span class="text-success"><i class="glyphicon
glyphicon-retweet"/> ${name}</span>
+ </a>
+ </h4>
+ </div>
+ <div id="${id}" class="panel-collapse collapse"
role="tabpanel">
+ <div class="panel-body">
+ ${unescape(aggregateHTML)}
+ </div>
+ </div>
+ </div>
+ #end
+ </div>
+ </div>
+ #end
+
</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
b/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
index beaf182..c0b9f8f 100644
--- a/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
+++ b/cassandra/src/main/resources/scalate/keyspaceDetails.ssp
@@ -46,7 +46,7 @@
<tbody>
</table>
<div class="panel-footer">
- <a data-toggle="collapse"
data-target="#${ksDetails.uniqueId}_asCQL">
+ <a data-toggle="collapse"
data-target="#${ksDetails.uniqueId}_asCQL" class="text-danger">
<strong>As CQL statement</strong>
<span class="caret"></span>
</a>
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/materializedViewDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/materializedViewDetails.ssp
b/cassandra/src/main/resources/scalate/materializedViewDetails.ssp
new file mode 100644
index 0000000..459b5bc
--- /dev/null
+++ b/cassandra/src/main/resources/scalate/materializedViewDetails.ssp
@@ -0,0 +1,109 @@
+<%--
+/*
+* 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 mvDetails: MaterializedViewDetails %>
+<%@ val withCaption: Boolean%>
+<div class="row">
+ <div class="col-md-2"/>
+ <div class="col-md-8 col-offset-md-2">
+ <div class="panel panel-default table-responsive table-bordered">
+ <table class="table">
+ #if(withCaption)
+ <caption>
+ <h4 class="text-primary">
+ <i class="glyphicon glyphicon-eye-open"/>
+ ${mvDetails.name}
+ <i class="glyphicon glyphicon-arrow-right"/>
+ <i class="glyphicon glyphicon-th-list"/>
+ ${mvDetails.baseTable}
+ </h4>
+ </caption>
+ #end
+ <thead>
+ <tr>
+ <th class="col-md-4">Column Type</th>
+ <th class="col-md-4">Column Name</th>
+ <th class="col-md-4">Data Type</th>
+ </tr>
+ </thead>
+ <tbody>
+ #for (column <- mvDetails.columns)
+ #match (column.columnType)
+ #case(PartitionKey)
+
+ <tr class="info">
+ <td class="col-md-4">
+ <i class="glyphicon glyphicon-fullscreen"
title="Partition Key"/>
+ </td>
+ <td class="col-md-4">${column.name}</td>
+ <td class="col-md-4">${column.dataType}</td>
+ </tr>
+ #case(StaticColumn)
+ <tr class="warning">
+ <td class="col-md-4">
+ <i class="glyphicon glyphicon-pushpin"
title="Static Column"/>
+ </td>
+ <td class="col-md-4">${column.name}</td>
+ <td class="col-md-4">${column.dataType}</td>
+ </tr>
+ #case(ClusteringColumn(ASC))
+ <tr class="success">
+ <td class="col-md-4">
+ <i class="glyphicon glyphicon-sort"
title="Clustering Column"/>
+
+ <i class="glyphicon glyphicon-sort-by-attributes"
title="Sort ASC"/>
+ </td>
+ <td class="col-md-4">${column.name}</td>
+ <td class="col-md-4">${column.dataType}</td>
+ </tr>
+ #case(ClusteringColumn(DESC))
+ <tr class="success">
+ <td class="col-md-4">
+ <i class="glyphicon glyphicon-sort"
title="Clustering Column"/>
+
+ <i class="glyphicon
glyphicon-sort-by-attributes-alt" title="Sort DESC"/>
+ </td>
+ <td class="col-md-4">${column.name}</td>
+ <td class="col-md-4">${column.dataType}</td>
+ </tr>
+ #otherwise
+ <tr>
+ <td class="col-md-4"></td>
+ <td class="col-md-4">${column.name}</td>
+ <td class="col-md-4">${column.dataType}</td>
+ </tr>
+ #end
+ #end
+
+ </tbody>
+ </table>
+ <div class="panel-footer">
+ <a data-toggle="collapse"
data-target="#${mvDetails.uniqueId}_asCQL" class="text-primary">
+ <strong>As CQL statement</strong>
+ <span class="caret"></span>
+ </a>
+ <br/><br/>
+ <div class="collapse" id="${mvDetails.uniqueId}_asCQL">
+ <pre class="well">${mvDetails.asCQL}</pre>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="col-md-2"></div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/menu.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/menu.ssp
b/cassandra/src/main/resources/scalate/menu.ssp
index 91afc8b..0d5a36e 100644
--- a/cassandra/src/main/resources/scalate/menu.ssp
+++ b/cassandra/src/main/resources/scalate/menu.ssp
@@ -54,6 +54,23 @@
<i class="glyphicon glyphicon-th-list text-primary"
/> Table
</a>
</li>
+ <li>
+ <a role="button">
+ <i class="glyphicon glyphicon-eye-open text-primary"
/> Materialized View
+ </a>
+ </li>
+ <li>
+ <a role="button">
+ <i class="glyphicon glyphicon-random text-success"
/> Function
+ </a>
+ </li>
+ <li>
+ <a role="button">
+ <i class="glyphicon glyphicon-retweet text-success"
/> Aggregate
+ </a>
+ </li>
+ <li role="separator" class="divider text-muted"></li>
+ <li class="dropdown-header"><span class="text-primary">Table
icons</span></li>
<li class="bg-info">
<a role="button">
<i class="glyphicon glyphicon-fullscreen"
/> Partition Key
@@ -79,11 +96,6 @@
<i class="glyphicon glyphicon-sort-by-attributes-alt"
/> Clustering Order DESC
</a>
</li>
- <li>
- <a role="button">
- <i class="glyphicon glyphicon-info-sign"
/> Indexed Column
- </a>
- </li>
</ul>
</li>
<li>
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/tableDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/tableDetails.ssp
b/cassandra/src/main/resources/scalate/tableDetails.ssp
index 6cfbc49..41e4517 100644
--- a/cassandra/src/main/resources/scalate/tableDetails.ssp
+++ b/cassandra/src/main/resources/scalate/tableDetails.ssp
@@ -42,15 +42,6 @@
<tr class="info">
<td class="col-md-4">
<i class="glyphicon glyphicon-fullscreen"
title="Partition Key"/>
- #match (column.index)
- #case (Some(index))
-
- <i class="glyphicon glyphicon-info-sign"
title="Indexed Column"/>
- <em>${index.name}</em>
<strong>${index.info}</strong>
- #case (None)
- <span></span>
- #end
-
</td>
<td class="col-md-4">${column.name}</td>
<td class="col-md-4">${column.dataType}</td>
@@ -59,15 +50,6 @@
<tr class="warning">
<td class="col-md-4">
<i class="glyphicon glyphicon-pushpin"
title="Static Column"/>
- #match (column.index)
- #case (Some(index))
-
- <i class="glyphicon glyphicon-info-sign"
title="Indexed Column"/>
- <em>${index.name}</em>
<strong>${index.info}</strong>
- #case (None)
- <span></span>
- #end
-
</td>
<td class="col-md-4">${column.name}</td>
<td class="col-md-4">${column.dataType}</td>
@@ -78,15 +60,6 @@
<i class="glyphicon glyphicon-sort"
title="Clustering Column"/>
<i class="glyphicon glyphicon-sort-by-attributes"
title="Sort ASC"/>
- #match (column.index)
- #case (Some(index))
-
- <i class="glyphicon glyphicon-info-sign"
title="Indexed Column"/>
- <em>${index.name}</em>
<strong>${index.info}</strong>
- #case (None)
- <span></span>
- #end
-
</td>
<td class="col-md-4">${column.name}</td>
<td class="col-md-4">${column.dataType}</td>
@@ -97,32 +70,13 @@
<i class="glyphicon glyphicon-sort"
title="Clustering Column"/>
<i class="glyphicon
glyphicon-sort-by-attributes-alt" title="Sort DESC"/>
- #match (column.index)
- #case (Some(index))
-
- <i class="glyphicon glyphicon-info-sign"
title="Indexed Column"/>
- <em>${index.name}</em>
<strong>${index.info}</strong>
- #case (None)
- <span></span>
- #end
-
</td>
<td class="col-md-4">${column.name}</td>
<td class="col-md-4">${column.dataType}</td>
</tr>
#otherwise
<tr>
- <td class="col-md-4">
- #match (column.index)
- #case (Some(index))
-
- <i class="glyphicon glyphicon-info-sign"
title="Indexed Column"/>
- <em>${index.name}</em>
<strong>${index.info}</strong>
- #case (None)
- <span></span>
- #end
-
- </td>
+ <td class="col-md-4"></td>
<td class="col-md-4">${column.name}</td>
<td class="col-md-4">${column.dataType}</td>
</tr>
@@ -132,7 +86,7 @@
</tbody>
</table>
<div class="panel-footer">
- <a data-toggle="collapse"
data-target="#${tableDetails.uniqueId}_asCQL">
+ <a data-toggle="collapse"
data-target="#${tableDetails.uniqueId}_asCQL" class="text-primary">
<strong>As CQL statement</strong>
<span class="caret"></span>
</a>
@@ -142,6 +96,39 @@
</div>
</div>
</div>
+ #if(tableDetails.indices.size > 0)
+ <hr/>
+ <div class="panel panel-default table-responsive table-bordered">
+ <table class="table">
+ <caption><h4 class="text-danger"><i class="glyphicon
glyphicon-info-sign"/> ${tableDetails.tableName}'s indices</h4>
+ </caption>
+ <thead>
+ <tr>
+ <th class="col-md-6">Name</th>
+ <th class="col-md-6">Target</th>
+ </tr>
+ </thead>
+ <tbody>
+ #for (index <- tableDetails.indices)
+ <tr>
+ <td class="col-md-6">${index.name}</td>
+ <td class="col-md-6">${index.target}</td>
+ </tr>
+ #end
+ </tbody>
+ </table>
+ <div class="panel-footer">
+ <a data-toggle="collapse"
data-target="#${tableDetails.uniqueId}_indices_asCQL" class="text-danger">
+ <strong>As CQL statement</strong>
+ <span class="caret"></span>
+ </a>
+ <br/><br/>
+ <div class="collapse"
id="${tableDetails.uniqueId}_indices_asCQL">
+ <pre class="well">${tableDetails.indicesAsCQL}</pre>
+ </div>
+ </div>
+ </div>
+ #end
</div>
<div class="col-md-2"></div>
</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/resources/scalate/udtDetails.ssp
----------------------------------------------------------------------
diff --git a/cassandra/src/main/resources/scalate/udtDetails.ssp
b/cassandra/src/main/resources/scalate/udtDetails.ssp
index 80380a4..28858f2 100644
--- a/cassandra/src/main/resources/scalate/udtDetails.ssp
+++ b/cassandra/src/main/resources/scalate/udtDetails.ssp
@@ -46,7 +46,7 @@
<tbody>
</table>
<div class="panel-footer">
- <a data-toggle="collapse"
data-target="#${udtDetails.uniqueId}_asCQL">
+ <a data-toggle="collapse"
data-target="#${udtDetails.uniqueId}_asCQL" class="text-warning">
<strong>As CQL statement</strong>
<span class="caret"></span>
</a>
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/scala/com/datastax/driver/core/TableMetadataWrapper.scala
----------------------------------------------------------------------
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 0000000..feddbe1
--- /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)
+ }
+}