zeppelin-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From felixche...@apache.org
Subject [5/6] incubator-zeppelin git commit: [ZEPPELIN-559] Cassandra interpreter v2
Date Sun, 24 Jan 2016 18:04:59 GMT
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
----------------------------------------------------------------------
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 2881b4b..135d4cd 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/DisplaySystem.scala
@@ -18,7 +18,6 @@ package org.apache.zeppelin.cassandra
 
 import java.util.UUID
 
-import com.datastax.driver.core.ColumnMetadata.IndexMetadata
 import com.datastax.driver.core.utils.UUIDs
 import org.apache.zeppelin.cassandra.MetaDataHierarchy._
 import org.fusesource.scalate.TemplateEngine
@@ -39,16 +38,30 @@ object DisplaySystem {
 
   val CLUSTER_DETAILS_TEMPLATE = "scalate/clusterDetails.ssp"
   val KEYSPACE_DETAILS_TEMPLATE = "scalate/keyspaceDetails.ssp"
+
   val TABLE_DETAILS_TEMPLATE = "scalate/tableDetails.ssp"
+  val ALL_TABLES_TEMPLATE = "scalate/allTables.ssp"
+
   val UDT_DETAILS_TEMPLATE = "scalate/udtDetails.ssp"
+  val ALL_UDTS_TEMPLATE = "scalate/allUDTs.ssp"
+
+  val FUNCTION_DETAILS_TEMPLATE = "scalate/functionDetails.ssp"
+  val ALL_FUNCTIONS_TEMPLATE = "scalate/allFunctions.ssp"
+
+  val AGGREGATE_DETAILS_TEMPLATE = "scalate/aggregateDetails.ssp"
+  val ALL_AGGREGATES_TEMPLATE = "scalate/allAggregates.ssp"
+
+  val MATERIALIZED_VIEW_DETAILS_TEMPLATE = "scalate/materializedViewDetails.ssp"
+  val ALL_MATERIALIZED_VIEWS_TEMPLATE = "scalate/allMaterializedViews.ssp"
 
   val MENU_TEMPLATE = "scalate/menu.ssp"
   val CLUSTER_DROPDOWN_TEMPLATE = "scalate/dropDownMenuForCluster.ssp"
-  val KEYSPACE_DROPDOWN_TEMPLATE = "scalate/dropDownMenuForKeyspace.ssp"
 
+  val KEYSPACE_DROPDOWN_TEMPLATE = "scalate/dropDownMenuForKeyspace.ssp"
   val CLUSTER_CONTENT_TEMPLATE = "scalate/clusterContent.ssp"
   val KEYSPACE_CONTENT_TEMPLATE = "scalate/keyspaceContent.ssp"
-  val ALL_TABLES_TEMPLATE = "scalate/allTables.ssp"
+
+
 
   object TableDisplay {
 
@@ -58,10 +71,12 @@ object DisplaySystem {
 
     protected[DisplaySystem] def formatWithoutMenu(meta: TableMetadata, withCaption: Boolean): String = {
       val tableName: String = meta.getName
-      val columnsDetails = MetaDataConverter.tableMetaToColumnDetails(meta)
+      val columnsDetails = MetaDataConverter.Table.tableMetaToColumnDetails(meta)
+      val indicesDetails = MetaDataConverter.Table.tableMetaToIndexDetails(meta)
+      val indicesAsCQL = indicesDetails.map(_.asCQL).mkString("\n")
 
       engine.layout(TABLE_DETAILS_TEMPLATE,
-        Map[String, Any]("tableDetails" -> TableDetails(tableName, columnsDetails, meta.exportAsString), "withCaption" -> withCaption))
+        Map[String, Any]("tableDetails" -> TableDetails(tableName, columnsDetails, indicesDetails, TableMetadataWrapper(meta).exportTableOnlyAsString(), indicesAsCQL), "withCaption" -> withCaption))
     }
   }
 
@@ -72,13 +87,49 @@ object DisplaySystem {
 
     protected[DisplaySystem] def formatWithoutMenu(userType: UserType, withCaption: Boolean): String = {
       val udtName: String = userType.getTypeName
-      val columnsDetails = MetaDataConverter.userTypeToColumnDetails(userType)
+      val columnsDetails = MetaDataConverter.UDT.userTypeToColumnDetails(userType)
 
       engine.layout(UDT_DETAILS_TEMPLATE,
-        Map[String, Any]("udtDetails" -> UDTDetails(udtName, columnsDetails, userType.exportAsString), "withCaption" -> withCaption))
+        Map[String, Any]("udtDetails" -> UDTDetails(udtName,columnsDetails,userType.exportAsString()), "withCaption" -> withCaption))
+    }
+  }
+
+  object FunctionDisplay {
+    def format(statement: String, functions: List[FunctionMetadata], withCaption: Boolean): String = {
+      MenuDisplay.formatMenu(statement) ++ formatWithoutMenu(functions, withCaption)
+    }
+
+    protected[DisplaySystem] def formatWithoutMenu(functions: List[FunctionMetadata], withCaption: Boolean): String = {
+      val functionDetails: List[FunctionDetails] = functions.map(MetaDataConverter.functionMetaToFunctionDetails(_))
+      engine.layout(FUNCTION_DETAILS_TEMPLATE,
+        Map[String, Any]("sameNameFunctionDetails" -> SameNameFunctionDetails(functionDetails), "withCaption" -> withCaption))
     }
   }
-  
+
+  object AggregateDisplay {
+    def format(statement: String, aggregates: List[AggregateMetadata], withCaption: Boolean, codecRegistry: CodecRegistry): String = {
+      MenuDisplay.formatMenu(statement) ++ formatWithoutMenu(aggregates, withCaption, codecRegistry)
+    }
+
+    protected[DisplaySystem] def formatWithoutMenu(aggregates: List[AggregateMetadata], withCaption: Boolean, codecRegistry: CodecRegistry): String = {
+      val aggDetails: List[AggregateDetails] = aggregates.map(agg => MetaDataConverter.aggregateMetaToAggregateDetails(codecRegistry, agg))
+      engine.layout(AGGREGATE_DETAILS_TEMPLATE,
+        Map[String, Any]("sameNameAggregateDetails" -> SameNameAggregateDetails(aggDetails), "withCaption" -> withCaption))
+    }
+  }
+
+  object MaterializedViewDisplay {
+    def format(statement: String, mv: MaterializedViewMetadata, withCaption: Boolean): String = {
+      MenuDisplay.formatMenu(statement) ++ formatWithoutMenu(mv, withCaption)
+    }
+
+    protected[DisplaySystem] def formatWithoutMenu(mv: MaterializedViewMetadata, withCaption: Boolean): String = {
+      val mvDetails = MetaDataConverter.mvMetaToMaterializedViewDetails(mv)
+      engine.layout(MATERIALIZED_VIEW_DETAILS_TEMPLATE,
+        Map[String, Any]("mvDetails" -> mvDetails, "withCaption" -> withCaption))
+    }
+  }
+
   object KeyspaceDisplay {
 
     private def formatCQLQuery(cql: String): String = {
@@ -97,19 +148,32 @@ object DisplaySystem {
         Map[String, Any]("ksDetails" -> ksDetails, "withCaption" -> withCaption))
     }
 
-    def formatKeyspaceContent(statement: String, meta: KeyspaceMetadata): String = {
+    def formatKeyspaceContent(statement: String, meta: KeyspaceMetadata, codecRegistry: CodecRegistry): String = {
       val ksName: String = meta.getName
-      val ksDetails = formatKeyspaceOnly(meta, false)
+      val ksDetails = formatKeyspaceOnly(meta, true)
 
       val tableDetails: List[(UUID, String, String)] = meta.getTables.asScala.toList
-        .sortBy(meta => meta.getName)
-        .map(meta => (UUIDs.timeBased(), meta.getName, TableDisplay.formatWithoutMenu(meta, false)))
+        .sortBy(_.getName)
+        .map(table => (UUIDs.timeBased(), table.getName, TableDisplay.formatWithoutMenu(table, false)))
+
+      val viewDetails: List[(UUID, String, String)] = meta.getMaterializedViews.asScala.toList
+        .sortBy(_.getName)
+        .map(view => (UUIDs.timeBased(), view.getName, MaterializedViewDisplay.formatWithoutMenu(view, false)))
 
       val udtDetails: List[(UUID, String, String)] = meta.getUserTypes.asScala.toList
-        .sortBy(udt => udt.getTypeName)
+        .sortBy(_.getTypeName)
         .map(udt => (UUIDs.timeBased(), udt.getTypeName, UDTDisplay.formatWithoutMenu(udt, false)))
 
-      val ksContent: KeyspaceContent = KeyspaceContent(ksName, ksDetails, tableDetails, udtDetails)
+      val functionDetails: List[(UUID, String, String)] = meta.getFunctions.asScala.toList
+        .sortBy(_.getSimpleName)
+        .map(function => (UUIDs.timeBased(), function.getSimpleName, FunctionDisplay.formatWithoutMenu(List(function), false)))
+
+      val aggregateDetails: List[(UUID, String, String)] = meta.getAggregates.asScala.toList
+        .sortBy(_.getSimpleName)
+        .map(agg => (UUIDs.timeBased(), agg.getSimpleName, AggregateDisplay.formatWithoutMenu(List(agg), false, codecRegistry)))
+
+      val ksContent: KeyspaceContent = KeyspaceContent(ksName, ksDetails, tableDetails, viewDetails,
+        udtDetails, functionDetails, aggregateDetails)
 
       MenuDisplay.formatMenuForKeyspace(statement, ksContent) +
         engine.layout(KEYSPACE_CONTENT_TEMPLATE,
@@ -144,26 +208,152 @@ object DisplaySystem {
 
     def formatAllTables(statement: String, meta: Metadata): String = {
       val ksMetas: List[KeyspaceMetadata] = meta.getKeyspaces.asScala.toList
+        .filter(_.getTables.size > 0)
         .sortBy(ks => ks.getName)
+      if(ksMetas.isEmpty) {
+        NoResultDisplay.formatNoResult
+      } else {
+        val allTables: Map[(UUID, String), List[String]] = ListMap.empty ++
+          ksMetas
+            .map(ks => {
+              ((UUIDs.timeBased(), ks.getName),
+                ks.getTables.asScala.toList.map(table => table.getName).sortBy(name => name))
+            })
+            .sortBy{case ((id,name), _) => name}
+
+
+        val keyspaceDetails: List[(UUID, String, String)] = allTables
+          .keySet.toList.sortBy{case(id,ksName) => ksName}
+          .map{case(id,ksName) => (id,ksName, "")}
+
+        val clusterContent: ClusterContent = ClusterContent(meta.getClusterName, "", keyspaceDetails)
+
+        MenuDisplay.formatMenuForCluster(statement, clusterContent) +
+          engine.layout(ALL_TABLES_TEMPLATE,
+            Map[String, Any]("allTables" -> allTables))
+      }
+    }
 
-      val allTables: Map[(UUID, String), List[String]] = ListMap.empty ++
-        ksMetas
-        .map(ks => {
-          ((UUIDs.timeBased(), ks.getName),
-            ks.getTables.asScala.toList.map(table => table.getName).sortBy(name => name))
-         })
-        .sortBy{case ((id,name), _) => name}
+    def formatAllUDTs(statement: String, meta: Metadata): String = {
+      val ksMetas: List[KeyspaceMetadata] = meta.getKeyspaces.asScala.toList
+        .filter(_.getUserTypes.size > 0)
+        .sortBy(ks => ks.getName)
 
+      if(ksMetas.isEmpty) {
+        NoResultDisplay.formatNoResult
+      } else {
+        val allUDTs: Map[(UUID, String), List[String]] = ListMap.empty ++
+          ksMetas
+            .map(ks => {
+              ((UUIDs.timeBased(), ks.getName),
+                ks.getUserTypes.asScala.toList.map(udt => udt.getTypeName).sortBy(name => name))
+            })
+            .sortBy { case ((id, name), _) => name }
 
-      val keyspaceDetails: List[(UUID, String, String)] = allTables
-        .keySet.toList.sortBy{case(id,ksName) => ksName}
-        .map{case(id,ksName) => (id,ksName, "")}
 
-      val clusterContent: ClusterContent = ClusterContent(meta.getClusterName, "", keyspaceDetails)
+        val keyspaceDetails: List[(UUID, String, String)] = allUDTs
+          .keySet.toList.sortBy { case (id, ksName) => ksName }
+          .map { case (id, ksName) => (id, ksName, "") }
 
-      MenuDisplay.formatMenuForCluster(statement, clusterContent) +
-        engine.layout(ALL_TABLES_TEMPLATE,
-          Map[String, Any]("allTables" -> allTables))
+        val clusterContent: ClusterContent = ClusterContent(meta.getClusterName, "", keyspaceDetails)
+
+        MenuDisplay.formatMenuForCluster(statement, clusterContent) +
+          engine.layout(ALL_UDTS_TEMPLATE,
+            Map[String, Any]("allUDTs" -> allUDTs))
+      }
+    }
+
+    def formatAllFunctions(statement: String, meta: Metadata): String = {
+      val ksMetas: List[KeyspaceMetadata] = meta.getKeyspaces.asScala.toList
+        .filter(_.getFunctions.size > 0)
+        .sortBy(ks => ks.getName)
+
+      if(ksMetas.isEmpty) {
+        NoResultDisplay.formatNoResult
+      } else {
+        val allFunctions: Map[(UUID, String), List[FunctionSummary]] = ListMap.empty ++
+          ksMetas
+            .map(ks => {
+              ((UUIDs.timeBased(), ks.getName),
+                ks.getFunctions.asScala.toList
+                  .map(MetaDataConverter.functionMetaToFunctionSummary(_))
+                  .sortBy(_.name))
+            })
+            .sortBy { case ((id, name), _) => name }
+
+        val keyspaceDetails: List[(UUID, String, String)] = allFunctions
+          .keySet.toList.sortBy { case (id, ksName) => ksName }
+          .map { case (id, ksName) => (id, ksName, "") }
+
+
+        val clusterContent: ClusterContent = ClusterContent(meta.getClusterName, "", keyspaceDetails)
+
+        MenuDisplay.formatMenuForCluster(statement, clusterContent) +
+          engine.layout(ALL_FUNCTIONS_TEMPLATE,
+            Map[String, Any]("allFunctions" -> allFunctions))
+      }
+    }
+
+    def formatAllAggregates(statement: String, meta: Metadata): String = {
+      val ksMetas: List[KeyspaceMetadata] = meta.getKeyspaces.asScala.toList
+        .filter(_.getAggregates.size > 0)
+        .sortBy(ks => ks.getName)
+
+      if(ksMetas.isEmpty) {
+        NoResultDisplay.formatNoResult
+      } else {
+        val allAggregates: Map[(UUID, String), List[AggregateSummary]] = ListMap.empty ++
+          ksMetas
+            .map(ks => {
+              ((UUIDs.timeBased(), ks.getName),
+                ks.getAggregates.asScala.toList
+                  .map(MetaDataConverter.aggregateMetaToAggregateSummary(_))
+                  .sortBy(_.name))
+            })
+            .sortBy { case ((id, name), _) => name }
+
+        val keyspaceDetails: List[(UUID, String, String)] = allAggregates
+          .keySet.toList.sortBy { case (id, ksName) => ksName }
+          .map { case (id, ksName) => (id, ksName, "") }
+
+
+        val clusterContent: ClusterContent = ClusterContent(meta.getClusterName, "", keyspaceDetails)
+
+        MenuDisplay.formatMenuForCluster(statement, clusterContent) +
+          engine.layout(ALL_AGGREGATES_TEMPLATE,
+            Map[String, Any]("allAggregates" -> allAggregates))
+      }
+    }
+
+    def formatAllMaterializedViews(statement: String, meta: Metadata): String = {
+      val ksMetas: List[KeyspaceMetadata] = meta.getKeyspaces.asScala.toList
+        .filter(_.getMaterializedViews.size > 0)
+        .sortBy(ks => ks.getName)
+
+      if(ksMetas.isEmpty) {
+        NoResultDisplay.formatNoResult
+      } else {
+        val allMVs: Map[(UUID, String), List[MaterializedViewSummary]] = ListMap.empty ++
+          ksMetas
+            .map(ks => {
+              ((UUIDs.timeBased(), ks.getName),
+                ks.getMaterializedViews.asScala.toList
+                  .map(MetaDataConverter.mvMetaToMaterializedViewSummary(_))
+                  .sortBy(_.name))
+            })
+            .sortBy { case ((id, name), _) => name }
+
+        val keyspaceDetails: List[(UUID, String, String)] = allMVs
+          .keySet.toList.sortBy { case (id, ksName) => ksName }
+          .map { case (id, ksName) => (id, ksName, "") }
+
+
+        val clusterContent: ClusterContent = ClusterContent(meta.getClusterName, "", keyspaceDetails)
+
+        MenuDisplay.formatMenuForCluster(statement, clusterContent) +
+          engine.layout(ALL_MATERIALIZED_VIEWS_TEMPLATE,
+            Map[String, Any]("allMVs" -> allMVs))
+      }
     }
   }
 
@@ -233,63 +423,150 @@ class ColumnMetaWrapper(val columnMeta: ColumnMetadata) {
  */
 object MetaDataConverter {
 
-  def tableMetaToColumnDetails(meta: TableMetadata): List[ColumnDetails] = {
-    val partitionKeys: List[ColumnMetaWrapper] = meta.getPartitionKey.asScala.toList.map(new ColumnMetaWrapper(_))
-    val clusteringColumns: List[ColumnMetaWrapper] = meta.getClusteringColumns.asScala.toList.map(new ColumnMetaWrapper(_))
-    val columns: List[ColumnMetaWrapper] = meta.getColumns.asScala.toList.map(new ColumnMetaWrapper(_))
-      .diff(partitionKeys).diff(clusteringColumns)
-    val clusteringOrders = meta.getClusteringOrder.asScala.toList
-
-    convertPartitionKeys(partitionKeys):::
-      extractStaticColumns(columns):::
-      convertClusteringColumns(clusteringColumns, clusteringOrders):::
-      extractNormalColumns(columns)
-  }
-  
-  def userTypeToColumnDetails(userType: UserType): List[ColumnDetails] = {
-    userType.getFieldNames.asScala.toList
-      .map(name => new ColumnDetails(name, NormalColumn, userType.getFieldType(name), None))
+  type DriverClusteringOrder = com.datastax.driver.core.ClusteringOrder
+
+  def functionMetaToFunctionDetails(function: FunctionMetadata): FunctionDetails = {
+    new FunctionDetails(function.getKeyspace.getName,
+      function.getSimpleName,
+      function.getArguments.asScala
+        .toMap
+        .map{case(paramName, dataType) => paramName + " " + dataType.asFunctionParameterString()}
+        .toList,
+      function.isCalledOnNullInput,
+      function.getReturnType.asFunctionParameterString(),
+      function.getLanguage,
+      function.getBody,
+      function.exportAsString())
   }
 
-  private def extractNormalColumns(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
-    columns
-      .filter(_.columnMeta.isStatic == false)
-      .map(c => new ColumnDetails(c.columnMeta.getName, NormalColumn, c.columnMeta.getType, extractIndexDetail(c)))
+  def functionMetaToFunctionSummary(function: FunctionMetadata): FunctionSummary = {
+    new FunctionSummary(function.getKeyspace.getName,
+      function.getSimpleName,
+      function.getArguments.asScala.toMap
+        .mapValues(dataType => dataType.asFunctionParameterString())
+        .values.toList,
+      function.getReturnType.asFunctionParameterString()
+    )
   }
 
-  private def extractIndexDetail(column: ColumnMetaWrapper): Option[IndexDetails] = {
-    val indexOption = Option(column.columnMeta.getIndex)
+  def aggregateMetaToAggregateDetails(codecRegistry: CodecRegistry, aggregate: AggregateMetadata): AggregateDetails = {
+    val sFunc: FunctionSummary = functionMetaToFunctionSummary(aggregate.getStateFunc)
+    val finalFunc: Option[String] = Option(aggregate.getFinalFunc).map(func => {
+      val finalFunction = functionMetaToFunctionSummary(func)
+      finalFunction.name + finalFunction.arguments.mkString("(", ", ", ")")
+    })
+    val sType = aggregate.getStateType
+    val initCond: Option[String] = Option(aggregate.getInitCond).map(codecRegistry.codecFor(sType).format(_))
+    val returnType: String = Option(aggregate.getFinalFunc) match {
+      case Some(finalFunc) => functionMetaToFunctionSummary(finalFunc).returnType
+      case None => sFunc.returnType
+    }
+
+    new AggregateDetails(aggregate.getKeyspace.getName,
+      aggregate.getSimpleName,
+      aggregate.getArgumentTypes.asScala.toList.map(_.asFunctionParameterString()),
+      sFunc.name + sFunc.arguments.mkString("(",", ", ")"),
+      sType.asFunctionParameterString(),
+      finalFunc,
+      initCond,
+      returnType,
+      aggregate.exportAsString())
+  }
 
-    def buildIndexInfo(indexMeta: IndexMetadata): String = {
-      if(indexMeta.isKeys) "KEYS"
-      if(indexMeta.isEntries) "ENTRIES"
-      if(indexMeta.isFull) "FULL"
-      if(indexMeta.isCustomIndex) s"Class = ${indexMeta.getIndexClassName}"
-      else ""
+  def aggregateMetaToAggregateSummary(aggregate: AggregateMetadata): AggregateSummary = {
+    val returnType: String = Option(aggregate.getFinalFunc) match {
+      case Some(finalFunc) => functionMetaToFunctionSummary(finalFunc).returnType
+      case None => aggregate.getStateType.asFunctionParameterString()
     }
 
-    indexOption.map(index => IndexDetails(index.getName, buildIndexInfo(index)))
+    new AggregateSummary(aggregate.getKeyspace.getName,
+      aggregate.getSimpleName,
+      aggregate.getArgumentTypes.asScala.toList.map(_.asFunctionParameterString()),
+      returnType
+    )
+  }
+
+  def mvMetaToMaterializedViewDetails(mv: MaterializedViewMetadata): MaterializedViewDetails = {
+    new MaterializedViewDetails(mv.getName, MV.mvMetaToColumnDetails(mv), mv.exportAsString(), mv.getBaseTable.getName)
+  }
+
+  def mvMetaToMaterializedViewSummary(mv: MaterializedViewMetadata): MaterializedViewSummary = {
+    new MaterializedViewSummary(mv.getName, mv.getBaseTable.getName)
   }
 
-  private def extractStaticColumns(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
-    columns
-      .filter(_.columnMeta.isStatic == true)
-      .map(c => new ColumnDetails(c.columnMeta.getName, StaticColumn, c.columnMeta.getType, extractIndexDetail(c)))
+  trait TableOrView {
+    protected def extractNormalColumns(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
+      columns
+        .filter(_.columnMeta.isStatic == false)
+        .map(c => new ColumnDetails(c.columnMeta.getName, NormalColumn, c.columnMeta.getType))
+    }
+
+    protected def extractStaticColumns(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
+      columns
+        .filter(_.columnMeta.isStatic == true)
+        .map(c => new ColumnDetails(c.columnMeta.getName, StaticColumn, c.columnMeta.getType))
+    }
+
+    protected def convertClusteringColumns(columns: List[ColumnMetaWrapper], orders: List[DriverClusteringOrder]): List[ColumnDetails] = {
+      columns
+        .zip(orders)
+        .map{case(c,order) => new ColumnDetails(c.columnMeta.getName,
+          new ClusteringColumn(OrderConverter.convert(order)),c.columnMeta.getType)}
+
+    }
+
+    protected def convertPartitionKeys(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
+      columns
+        .map(c => new ColumnDetails(c.columnMeta.getName, PartitionKey, c.columnMeta.getType))
+    }
   }
 
-  private def convertClusteringColumns(columns: List[ColumnMetaWrapper], orders: List[TableMetadata.Order]): List[ColumnDetails] = {
-    columns
-      .zip(orders)
-      .map{case(c,order) => new ColumnDetails(c.columnMeta.getName,
-      new ClusteringColumn(OrderConverter.convert(order)),
-      c.columnMeta.getType, extractIndexDetail(c))}
+  object Table extends TableOrView {
+    def tableMetaToColumnDetails(meta: TableMetadata): List[ColumnDetails] = {
+      val partitionKeys: List[ColumnMetaWrapper] = meta.getPartitionKey.asScala.toList.map(new ColumnMetaWrapper(_))
+      val clusteringColumns: List[ColumnMetaWrapper] = meta.getClusteringColumns.asScala.toList.map(new ColumnMetaWrapper(_))
+      val columns: List[ColumnMetaWrapper] = meta.getColumns.asScala.toList.map(new ColumnMetaWrapper(_))
+        .diff(partitionKeys).diff(clusteringColumns)
+      val clusteringOrders = meta.getClusteringOrder.asScala.toList
+
+      convertPartitionKeys(partitionKeys):::
+        extractStaticColumns(columns):::
+        convertClusteringColumns(clusteringColumns, clusteringOrders):::
+        extractNormalColumns(columns)
+    }
+
+    def tableMetaToIndexDetails(meta: TableMetadata): List[IndexDetails] = {
+      meta.getIndexes.asScala.toList
+        .map(index => IndexDetails(index.getName, index.getTarget, index.asCQLQuery()))
+        .sortBy(index => index.name)
+    }
+
 
   }
 
-  private def convertPartitionKeys(columns: List[ColumnMetaWrapper]): List[ColumnDetails] = {
-    columns
-      .map(c => new ColumnDetails(c.columnMeta.getName, PartitionKey, c.columnMeta.getType, extractIndexDetail(c)))
+  object MV extends TableOrView {
+    def mvMetaToColumnDetails(meta: MaterializedViewMetadata): List[ColumnDetails] = {
+      val partitionKeys: List[ColumnMetaWrapper] = meta.getPartitionKey.asScala.toList.map(new ColumnMetaWrapper(_))
+      val clusteringColumns: List[ColumnMetaWrapper] = meta.getClusteringColumns.asScala.toList.map(new ColumnMetaWrapper(_))
+      val columns: List[ColumnMetaWrapper] = meta.getColumns.asScala.toList.map(new ColumnMetaWrapper(_))
+        .diff(partitionKeys).diff(clusteringColumns)
+      val clusteringOrders = meta.getClusteringOrder.asScala.toList
+
+      convertPartitionKeys(partitionKeys):::
+        convertClusteringColumns(clusteringColumns, clusteringOrders):::
+        extractNormalColumns(columns)
+    }
   }
+
+  object UDT {
+    def userTypeToColumnDetails(userType: UserType): List[ColumnDetails] = {
+      userType.getFieldNames.asScala.toList
+        .map(name => new ColumnDetails(name, NormalColumn, userType.getFieldType(name)))
+    }
+  }
+
+
+
 }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/scala/org/apache/zeppelin/cassandra/EnhancedSession.scala
----------------------------------------------------------------------
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/EnhancedSession.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/EnhancedSession.scala
index c636de9..a0c475a 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/EnhancedSession.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/EnhancedSession.scala
@@ -20,6 +20,7 @@ import com.datastax.driver.core._
 import org.apache.zeppelin.cassandra.TextBlockHierarchy._
 import org.apache.zeppelin.interpreter.InterpreterException
 
+import scala.collection.JavaConverters._
 
 /**
  * Enhance the Java driver session
@@ -32,6 +33,9 @@ class EnhancedSession(val session: Session) {
   val keyspaceDisplay = DisplaySystem.KeyspaceDisplay
   val tableDisplay = DisplaySystem.TableDisplay
   val udtDisplay = DisplaySystem.UDTDisplay
+  val functionDisplay = DisplaySystem.FunctionDisplay
+  val aggregateDisplay = DisplaySystem.AggregateDisplay
+  val materializedViewDisplay = DisplaySystem.MaterializedViewDisplay
   val helpDisplay = DisplaySystem.HelpDisplay
   private val noResultDisplay = DisplaySystem.NoResultDisplay
 
@@ -61,8 +65,12 @@ class EnhancedSession(val session: Session) {
 
   private def execute(describeKeyspace: DescribeKeyspaceCmd): String = {
     val keyspace: String = describeKeyspace.keyspace
-    val metadata: KeyspaceMetadata = session.getCluster.getMetadata.getKeyspace(keyspace)
-    HTML_MAGIC + keyspaceDisplay.formatKeyspaceContent(describeKeyspace.statement, metadata)
+    val metadata: Option[KeyspaceMetadata] = Option(session.getCluster.getMetadata.getKeyspace(keyspace))
+    metadata match {
+      case Some(ksMeta) => HTML_MAGIC + keyspaceDisplay.formatKeyspaceContent(describeKeyspace.statement, ksMeta,
+        session.getCluster.getConfiguration.getCodecRegistry)
+      case None => throw new InterpreterException(s"Cannot find keyspace $keyspace")
+    }
   }
 
   private def execute(describeTable: DescribeTableCmd): String = {
@@ -76,7 +84,7 @@ class EnhancedSession(val session: Session) {
     }
   }
 
-  private def execute(describeUDT: DescribeUDTCmd): String = {
+  private def execute(describeUDT: DescribeTypeCmd): String = {
     val metaData = session.getCluster.getMetadata
     val keyspace: String = describeUDT.keyspace.orElse(Option(session.getLoggedKeyspace)).getOrElse("system")
     val udtName: String = describeUDT.udtName
@@ -87,6 +95,87 @@ class EnhancedSession(val session: Session) {
     }
   }
 
+  private def execute(describeUDTs: DescribeTypesCmd): String = {
+    val metadata: Metadata = session.getCluster.getMetadata
+    HTML_MAGIC + clusterDisplay.formatAllUDTs(describeUDTs.statement, metadata)
+  }
+
+  private def execute(describeFunction: DescribeFunctionCmd): String = {
+    val metaData = session.getCluster.getMetadata
+    val keyspaceName: String = describeFunction.keyspace.orElse(Option(session.getLoggedKeyspace)).getOrElse("system")
+    val functionName: String = describeFunction.function;
+
+    Option(metaData.getKeyspace(keyspaceName)) match {
+      case Some(keyspace) => {
+        val functionMetas: List[FunctionMetadata] = keyspace.getFunctions.asScala.toList
+          .filter(func => func.getSimpleName.toLowerCase == functionName.toLowerCase)
+
+        if(functionMetas.isEmpty) {
+          throw new InterpreterException(s"Cannot find function ${keyspaceName}.$functionName")
+        } else {
+          HTML_MAGIC + functionDisplay.format(describeFunction.statement, functionMetas, true)
+        }
+      }
+      case None => throw new InterpreterException(s"Cannot find function ${keyspaceName}.$functionName")
+    }
+  }
+
+  private def execute(describeFunctions: DescribeFunctionsCmd): String = {
+    val metadata: Metadata = session.getCluster.getMetadata
+    HTML_MAGIC + clusterDisplay.formatAllFunctions(describeFunctions.statement, metadata)
+  }
+
+  private def execute(describeAggregate: DescribeAggregateCmd): String = {
+    val metaData = session.getCluster.getMetadata
+    val keyspaceName: String = describeAggregate.keyspace.orElse(Option(session.getLoggedKeyspace)).getOrElse("system")
+    val aggregateName: String = describeAggregate.aggregate;
+
+    Option(metaData.getKeyspace(keyspaceName)) match {
+      case Some(keyspace) => {
+        val aggMetas: List[AggregateMetadata] = keyspace.getAggregates.asScala.toList
+          .filter(agg => agg.getSimpleName.toLowerCase == aggregateName.toLowerCase)
+
+        if(aggMetas.isEmpty) {
+          throw new InterpreterException(s"Cannot find aggregate ${keyspaceName}.$aggregateName")
+        } else {
+          HTML_MAGIC + aggregateDisplay.format(describeAggregate.statement, aggMetas, true,
+            session
+            .getCluster
+            .getConfiguration
+            .getCodecRegistry)
+        }
+      }
+      case None => throw new InterpreterException(s"Cannot find aggregate ${keyspaceName}.$aggregateName")
+    }
+  }
+
+  private def execute(describeAggregates: DescribeAggregatesCmd): String = {
+    val metadata: Metadata = session.getCluster.getMetadata
+    HTML_MAGIC + clusterDisplay.formatAllAggregates(describeAggregates.statement, metadata)
+  }
+
+  private def execute(describeMV: DescribeMaterializedViewCmd): String = {
+    val metaData = session.getCluster.getMetadata
+    val keyspaceName: String = describeMV.keyspace.orElse(Option(session.getLoggedKeyspace)).getOrElse("system")
+    val viewName: String = describeMV.view
+
+    Option(metaData.getKeyspace(keyspaceName)) match {
+      case Some(keyspace) => {
+        val viewMeta: Option[MaterializedViewMetadata] = Option(keyspace.getMaterializedView(viewName))
+        viewMeta match {
+          case Some(vMeta) => HTML_MAGIC + materializedViewDisplay.format(describeMV.statement, vMeta, true)
+          case None => throw new InterpreterException(s"Cannot find materialized view ${keyspaceName}.$viewName")
+        }
+      }
+      case None => throw new InterpreterException(s"Cannot find materialized view ${keyspaceName}.$viewName")
+    }
+  }
+
+  private def execute(describeMVs: DescribeMaterializedViewsCmd): String = {
+    val metadata: Metadata = session.getCluster.getMetadata
+    HTML_MAGIC + clusterDisplay.formatAllMaterializedViews(describeMVs.statement, metadata)
+  }
+
   private def execute(helpCmd: HelpCmd): String = {
     HTML_MAGIC + helpDisplay.formatHelp()
   }
@@ -95,11 +184,18 @@ class EnhancedSession(val session: Session) {
   def execute(st: Any): Any = {
     st match {
       case x:DescribeClusterCmd => execute(x)
-      case x:DescribeKeyspacesCmd => execute(x)
-      case x:DescribeTablesCmd => execute(x)
       case x:DescribeKeyspaceCmd => execute(x)
+      case x:DescribeKeyspacesCmd => execute(x)
       case x:DescribeTableCmd => execute(x)
-      case x:DescribeUDTCmd => execute(x)
+      case x:DescribeTablesCmd => execute(x)
+      case x:DescribeTypeCmd => execute(x)
+      case x:DescribeTypesCmd => execute(x)
+      case x:DescribeFunctionCmd => execute(x)
+      case x:DescribeFunctionsCmd => execute(x)
+      case x:DescribeAggregateCmd => execute(x)
+      case x:DescribeAggregatesCmd => execute(x)
+      case x:DescribeMaterializedViewCmd => execute(x)
+      case x:DescribeMaterializedViewsCmd => execute(x)
       case x:HelpCmd => execute(x)
       case x:Statement => session.execute(x)
       case _ => throw new InterpreterException(s"Cannot execute statement '$st' of type ${st.getClass}")

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/scala/org/apache/zeppelin/cassandra/InterpreterLogic.scala
----------------------------------------------------------------------
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/InterpreterLogic.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/InterpreterLogic.scala
index 809bce7..707c16a8 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/InterpreterLogic.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/InterpreterLogic.scala
@@ -100,7 +100,7 @@ class InterpreterLogic(val session: Session)  {
     logger.info(s"Executing CQL statements : \n\n$stringStatements\n")
 
     try {
-      val protocolVersion = session.getCluster.getConfiguration.getProtocolOptions.getProtocolVersionEnum
+      val protocolVersion = session.getCluster.getConfiguration.getProtocolOptions.getProtocolVersion
 
       val queries:List[AnyBlock] = parseInput(stringStatements)
 
@@ -137,12 +137,12 @@ class InterpreterLogic(val session: Session)  {
           case x:BatchStm => {
             val builtStatements: List[Statement] = x.statements.map {
               case st:SimpleStm => generateSimpleStatement(st, queryOptions, context)
-              case st:BoundStm => generateBoundStatement(st, queryOptions, context)
+              case st:BoundStm => generateBoundStatement(session, st, queryOptions, context)
               case _ => throw new InterpreterException(s"Unknown statement type")
             }
             generateBatchStatement(x.batchType, queryOptions, builtStatements)
           }
-          case x:BoundStm => generateBoundStatement(x, queryOptions, context)
+          case x:BoundStm => generateBoundStatement(session, x, queryOptions, context)
           case x:DescribeCommandStatement => x
           case x:HelpCmd => x
           case x => throw new InterpreterException(s"Unknown statement type : ${x}")
@@ -208,7 +208,7 @@ class InterpreterLogic(val session: Session)  {
         row => {
           val data = columnsDefinitions.map {
             case (name, dataType) => {
-              if (row.isNull(name)) null else dataType.deserialize(row.getBytesUnsafe(name), protocolVersion)
+              if (row.isNull(name)) null else row.getObject(name)
             }
           }
           output.append(data.mkString("\t")).append("\n")
@@ -283,12 +283,12 @@ class InterpreterLogic(val session: Session)  {
     statement
   }
 
-  def generateBoundStatement(st: BoundStm, options: CassandraQueryOptions,context: InterpreterContext): BoundStatement = {
+  def generateBoundStatement(session: Session, st: BoundStm, options: CassandraQueryOptions,context: InterpreterContext): BoundStatement = {
     logger.debug(s"Generating bound statement with name : '${st.name}' and bound values : ${st.values}")
     preparedStatements.get(st.name) match {
       case Some(ps) => {
         val boundValues = maybeExtractVariables(st.values, context)
-        createBoundStatement(st.name, ps, boundValues)
+        createBoundStatement(session.getCluster.getConfiguration.getCodecRegistry, st.name, ps, boundValues)
       }
       case None => throw new InterpreterException(s"The statement '${st.name}' can not be bound to values. " +
           s"Are you sure you did prepare it with @prepare[${st.name}] ?")
@@ -342,7 +342,7 @@ class InterpreterLogic(val session: Session)  {
     options.fetchSize.foreach(statement.setFetchSize(_))
   }
 
-  private def createBoundStatement(name: String, ps: PreparedStatement, rawBoundValues: String): BoundStatement = {
+  private def createBoundStatement(codecRegistry: CodecRegistry, name: String, ps: PreparedStatement, rawBoundValues: String): BoundStatement = {
     val dataTypes = ps.getVariables.toList
       .map(cfDef => cfDef.getType)
 
@@ -357,6 +357,7 @@ class InterpreterLogic(val session: Session)  {
           if(value.trim == "null") {
             null
           } else {
+            val codec: TypeCodec[AnyRef] = codecRegistry.codecFor[AnyRef](dataType)
             dataType.getName match {
             case (ASCII | TEXT | VARCHAR) => value.trim.replaceAll("(?<!')'","")
             case (INT | VARINT) => value.trim.toInt
@@ -369,11 +370,11 @@ class InterpreterLogic(val session: Session)  {
             case INET => InetAddress.getByName(value.trim)
             case TIMESTAMP => parseDate(value.trim)
             case (UUID | TIMEUUID) => java.util.UUID.fromString(value.trim)
-            case LIST => dataType.parse(boundValuesParser.parse(boundValuesParser.list, value).get)
-            case SET => dataType.parse(boundValuesParser.parse(boundValuesParser.set, value).get)
-            case MAP => dataType.parse(boundValuesParser.parse(boundValuesParser.map, value).get)
-            case UDT => dataType.parse(boundValuesParser.parse(boundValuesParser.udt, value).get)
-            case TUPLE => dataType.parse(boundValuesParser.parse(boundValuesParser.tuple, value).get)
+            case LIST => codec.parse(boundValuesParser.parse(boundValuesParser.list, value).get)
+            case SET => codec.parse(boundValuesParser.parse(boundValuesParser.set, value).get)
+            case MAP => codec.parse(boundValuesParser.parse(boundValuesParser.map, value).get)
+            case UDT => codec.parse(boundValuesParser.parse(boundValuesParser.udt, value).get)
+            case TUPLE => codec.parse(boundValuesParser.parse(boundValuesParser.tuple, value).get)
             case _ => throw new InterpreterException(s"Cannot parse data of type : ${dataType.toString}")
           }
         }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/scala/org/apache/zeppelin/cassandra/MetaDataHierarchy.scala
----------------------------------------------------------------------
diff --git a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/MetaDataHierarchy.scala b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/MetaDataHierarchy.scala
index 66a0776..4b88776 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/MetaDataHierarchy.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/MetaDataHierarchy.scala
@@ -28,10 +28,10 @@ import scala.util.parsing.json.JSONObject
  */
 object MetaDataHierarchy {
   object OrderConverter {
-    def convert(clusteringOrder: TableMetadata.Order): ClusteringOrder = {
+    def convert(clusteringOrder: com.datastax.driver.core.ClusteringOrder): ClusteringOrder = {
       clusteringOrder match {
-        case TableMetadata.Order.ASC => ASC
-        case TableMetadata.Order.DESC => DESC
+        case com.datastax.driver.core.ClusteringOrder.ASC => ASC
+        case com.datastax.driver.core.ClusteringOrder.DESC => DESC
       }
     }
   }
@@ -46,9 +46,8 @@ object MetaDataHierarchy {
   case class ClusteringColumn(order: ClusteringOrder) extends ColumnType
   object StaticColumn extends ColumnType
   object NormalColumn extends ColumnType
-  case class IndexDetails(name: String, info: String)
-  case class ColumnDetails(name: String, columnType: ColumnType, dataType: DataType, index: Option[IndexDetails])
-
+  case class IndexDetails(name: String, target: String, asCQL: String)
+  case class ColumnDetails(name: String, columnType: ColumnType, dataType: DataType)
 
   case class ClusterDetails(name: String, partitioner: String)
   case class ClusterContent(clusterName: String, clusterDetails: String, keyspaces: List[(UUID, String, String)])
@@ -58,10 +57,26 @@ object MetaDataHierarchy {
       JSONObject(replication).toString().replaceAll(""""""","'")
     }
   }
-  case class KeyspaceContent(keyspaceName: String, keyspaceDetails: String, tables: List[(UUID,String, String)], udts: List[(UUID, String, String)])
-  case class TableDetails(tableName: String, columns: List[ColumnDetails], asCQL: String, uniqueId: UUID = UUIDs.timeBased())
+  case class KeyspaceContent(keyspaceName: String, keyspaceDetails: String,
+                             tables: List[(UUID,String, String)],
+                             views: List[(UUID,String, String)],
+                             udts: List[(UUID, String, String)],
+                             functions: List[(UUID, String, String)],
+                             aggregates: List[(UUID, String, String)])
+  case class TableDetails(tableName: String, columns: List[ColumnDetails], indices: List[IndexDetails], asCQL: String, indicesAsCQL: String, uniqueId: UUID = UUIDs.timeBased())
   case class UDTDetails(typeName: String, columns: List[ColumnDetails], asCQL: String, uniqueId: UUID = UUIDs.timeBased())
 
+  case class SameNameFunctionDetails(functions: List[FunctionDetails])
+  case class FunctionDetails(keyspace:String, name: String, arguments: List[String], calledOnNullInput: Boolean, returnType: String,
+    language:String, body: String, asCQL: String, uniqueId: UUID = UUIDs.timeBased())
+  case class FunctionSummary(keyspace:String, name: String, arguments: List[String], returnType: String)
 
+  case class AggregateDetails(keyspace:String, name: String, arguments: List[String], sFunc: String, sType: String,
+    finalFunc: Option[String], initCond: Option[String], returnType: String,
+    asCQL: String, uniqueId: UUID = UUIDs.timeBased())
+  case class AggregateSummary(keyspace:String, name: String, arguments: List[String], returnType: String)
+  case class SameNameAggregateDetails(aggregates: List[AggregateDetails])
 
+  case class MaterializedViewDetails(name: String, columns: List[ColumnDetails], asCQL: String, baseTable: String, uniqueId: UUID = UUIDs.timeBased())
+  case class MaterializedViewSummary(name: String, baseTable: String)
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
----------------------------------------------------------------------
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 0cd98ad..e2cb64d 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/ParagraphParser.scala
@@ -19,10 +19,20 @@ package org.apache.zeppelin.cassandra
 import com.datastax.driver.core._
 import org.apache.zeppelin.cassandra.CassandraInterpreter._
 import org.apache.zeppelin.interpreter.InterpreterException
+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
 
@@ -42,22 +52,43 @@ object ParagraphParser {
   val BIND_PATTERN = """^\s*@bind\[([^]]+)\](?:=([^;]+))?""".r
   val BATCH_PATTERN = """^(?i)\s*BEGIN\s+(UNLOGGED|COUNTER)?\s*BATCH""".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(?:\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|
       |DROP|GRANT|REVOKE|TRUNCATE|LIST|USE)\s+""".r
 
   val VALID_IDENTIFIER = "[a-z][a-z0-9_]*"
 
-  val DESCRIBE_CLUSTER_PATTERN = """^(?i)\s*(?:DESCRIBE|DESC)\s+CLUSTER;\s*$""".r
-  val DESCRIBE_KEYSPACES_PATTERN = """^(?i)\s*(?:DESCRIBE|DESC)\s+KEYSPACES;\s*$""".r
-  val DESCRIBE_TABLES_PATTERN = """^(?i)\s*(?:DESCRIBE|DESC)\s+TABLES;\s*$""".r
+  val DESCRIBE_CLUSTER_PATTERN = """^(?i)\s*(?:DESCRIBE|DESC)\s+CLUSTER\s*;\s*$""".r
+
+
   val DESCRIBE_KEYSPACE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+KEYSPACE\s*("""+VALID_IDENTIFIER+""");\s*$""").r
+  val DESCRIBE_KEYSPACES_PATTERN = """^(?i)\s*(?:DESCRIBE|DESC)\s+KEYSPACES\s*;\s*$""".r
+
+
   val DESCRIBE_TABLE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+TABLE\s*("""+VALID_IDENTIFIER+""");\s*$""").r
   val DESCRIBE_TABLE_WITH_KEYSPACE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+TABLE\s*(""" +
                                                 VALID_IDENTIFIER +
                                                 """)\.(""" +
                                                 VALID_IDENTIFIER +
                                                 """);\s*$""").r
+  val DESCRIBE_TABLES_PATTERN = """^(?i)\s*(?:DESCRIBE|DESC)\s+TABLES\s*;\s*$""".r
+
 
   val DESCRIBE_TYPE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+TYPE\s*("""+VALID_IDENTIFIER+""");\s*$""").r
   val DESCRIBE_TYPE_WITH_KEYSPACE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+TYPE\s*(""" +
@@ -65,6 +96,35 @@ object ParagraphParser {
                                                 """)\.(""" +
                                                 VALID_IDENTIFIER +
                                                 """);\s*$""").r
+  val DESCRIBE_TYPES_PATTERN = """^(?i)\s*(?:DESCRIBE|DESC)\s+TYPES\s*;\s*$""".r
+
+
+  val DESCRIBE_FUNCTION_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+FUNCTION\s*("""+VALID_IDENTIFIER+""");\s*$""").r
+  val DESCRIBE_FUNCTION_WITH_KEYSPACE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+FUNCTION\s*(""" +
+                                                  VALID_IDENTIFIER +
+                                                  """)\.(""" +
+                                                  VALID_IDENTIFIER +
+                                                  """);\s*$""").r
+  val DESCRIBE_FUNCTIONS_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+FUNCTIONS\s*;\s*$""").r
+
+
+  val DESCRIBE_AGGREGATE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+AGGREGATE\s*("""+VALID_IDENTIFIER+""");\s*$""").r
+  val DESCRIBE_AGGREGATE_WITH_KEYSPACE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+AGGREGATE\s*(""" +
+                                                    VALID_IDENTIFIER +
+                                                    """)\.(""" +
+                                                    VALID_IDENTIFIER +
+                                                    """);\s*$""").r
+  val DESCRIBE_AGGREGATES_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+AGGREGATES\s*;\s*$""").r
+
+
+  val DESCRIBE_MATERIALIZED_VIEW_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+MATERIALIZED\s+VIEW\s*("""+VALID_IDENTIFIER+""");\s*$""").r
+  val DESCRIBE_MATERIALIZED_VIEW_WITH_KEYSPACE_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+MATERIALIZED\s+VIEW\s*(""" +
+                                                            VALID_IDENTIFIER +
+                                                            """)\.(""" +
+                                                            VALID_IDENTIFIER +
+                                                            """);\s*$""").r
+  val DESCRIBE_MATERIALIZED_VIEWS_PATTERN = ("""^(?i)\s*(?:DESCRIBE|DESC)\s+MATERIALIZED\s+VIEWS\s*;\s*$""").r
+
 
   val HELP_PATTERN = """^(?i)\s*HELP;\s*$""".r
 }
@@ -74,7 +134,10 @@ class ParagraphParser extends RegexParsers{
 
   import ParagraphParser._
 
-  def singleLineComment: Parser[Comment] = """\s*#.*""".r ^^ {case text => Comment(text.trim.replaceAll("#",""))}
+  def singleLineCommentHash: Parser[Comment] = """\s*#.*""".r ^^ {case text => Comment(text.trim.replaceAll("#",""))}
+  def singleLineCommentDoubleSlashes: Parser[Comment] = """\s*//.*""".r ^^ {case text => Comment(text.trim.replaceAll("//",""))}
+  def singleLineComment: Parser[Comment] = singleLineCommentHash | singleLineCommentDoubleSlashes
+
   def multiLineComment: Parser[Comment] = """(?s)/\*(.*)\*/""".r ^^ {case text => Comment(text.trim.replaceAll("""/\*""","").replaceAll("""\*/""",""))}
 
   //Query parameters
@@ -85,7 +148,10 @@ class ParagraphParser extends RegexParsers{
   def fetchSize: Parser[FetchSize] = """\s*@fetchSize.+""".r ^^ {case x => extractFetchSize(x.trim)}
 
   //Statements
+  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 prepare: Parser[PrepareStm] = """\s*@prepare.+""".r ^^ {case x => extractPreparedStatement(x.trim)}
   def removePrepare: Parser[RemovePrepareStm] = """\s*@remove_prepare.+""".r ^^ {case x => extractRemovePreparedStatement(x.trim)}
   def bind: Parser[BoundStm] = """\s*@bind.+""".r ^^ {case x => extractBoundStatement(x.trim)}
@@ -95,9 +161,17 @@ class ParagraphParser extends RegexParsers{
   private def describeCluster: Parser[DescribeClusterCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+CLUSTER.*""".r ^^ {extractDescribeClusterCmd(_)}
   private def describeKeyspaces: Parser[DescribeKeyspacesCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+KEYSPACES.*""".r ^^ {extractDescribeKeyspacesCmd(_)}
   private def describeTables: Parser[DescribeTablesCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+TABLES.*""".r ^^ {extractDescribeTablesCmd(_)}
+  private def describeTypes: Parser[DescribeTypesCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+TYPES.*""".r ^^ {extractDescribeTypesCmd(_)}
+  private def describeFunctions: Parser[DescribeFunctionsCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+FUNCTIONS.*""".r ^^ {extractDescribeFunctionsCmd(_)}
+  private def describeAggregates: Parser[DescribeAggregatesCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+AGGREGATES.*""".r ^^ {extractDescribeAggregatesCmd(_)}
+  private def describeMaterializedViews: Parser[DescribeMaterializedViewsCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+MATERIALIZED\s+VIEWS.*""".r ^^ {extractDescribeMaterializedViewsCmd(_)}
   private def describeKeyspace: Parser[DescribeKeyspaceCmd] = """\s*(?i)(?:DESCRIBE|DESC)\s+KEYSPACE\s+.+""".r ^^ {extractDescribeKeyspaceCmd(_)}
   private def describeTable: Parser[DescribeTableCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+TABLE\s+.+""".r ^^ {extractDescribeTableCmd(_)}
-  private def describeType: Parser[DescribeUDTCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+TYPE\s+.*""".r ^^ {extractDescribeTypeCmd(_)}
+  private def describeType: Parser[DescribeTypeCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+TYPE\s+.*""".r ^^ {extractDescribeTypeCmd(_)}
+  private def describeFunction: Parser[DescribeFunctionCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+FUNCTION\s+.*""".r ^^ {extractDescribeFunctionCmd(_)}
+  private def describeAggregate: Parser[DescribeAggregateCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+AGGREGATE\s+.*""".r ^^ {extractDescribeAggregateCmd(_)}
+  private def describeMaterializedView: Parser[DescribeMaterializedViewCmd] = """(?i)\s*(?:DESCRIBE|DESC)\s+MATERIALIZED\s+VIEW\s+.*""".r ^^ {extractDescribeMaterializedViewCmd(_)}
+
 
   //Help
   private def helpCommand: Parser[HelpCmd] = """(?i)\s*HELP.*""".r ^^{extractHelpCmd(_)}
@@ -114,8 +188,14 @@ class ParagraphParser extends RegexParsers{
     case begin ~ cqls ~ end => BatchStm(extractBatchType(begin),cqls)}
 
   def queries:Parser[List[AnyBlock]] = rep(singleLineComment | multiLineComment | consistency | serialConsistency |
-    timestamp | retryPolicy | fetchSize | removePrepare | prepare | bind | batch | describeCluster | describeKeyspaces |
-    describeTables | describeKeyspace | describeTable | describeType | helpCommand | genericStatement)
+    timestamp | retryPolicy | fetchSize | removePrepare | prepare | bind | batch | describeCluster |
+    describeKeyspace | describeKeyspaces |
+    describeTable | describeTables |
+    describeType | describeTypes |
+    describeFunction | describeFunctions |
+    describeAggregate | describeAggregates |
+    describeMaterializedView | describeMaterializedViews |
+    helpCommand | createFunctionStatement | genericStatement)
 
   def extractConsistency(text: String): Consistency = {
     text match {
@@ -171,6 +251,13 @@ class ParagraphParser extends RegexParsers{
     }
   }
 
+  def extractUdfStatement(text: String): SimpleStm = {
+    text match {
+      case UDF_PATTERN(statement) => SimpleStm(statement)
+      case _ => throw new InterpreterException(s"Invalid statement '$text' for UDF creation. Did you forget to add ; (semi-colon) at the end of each CQL statement ?")
+    }
+  }
+
   def extractPreparedStatement(text: String): PrepareStm = {
     text match {
       case PREPARE_STATEMENT_PATTERN(name,queryString) => PrepareStm(name.trim,queryString.trim)
@@ -214,6 +301,14 @@ class ParagraphParser extends RegexParsers{
     }
   }
 
+  def extractDescribeKeyspaceCmd(text: String): DescribeKeyspaceCmd = {
+    text match {
+      case DESCRIBE_KEYSPACE_PATTERN(keyspace) => new DescribeKeyspaceCmd(keyspace)
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE KEYSPACE. " +
+        s"""It should comply to the pattern: ${DESCRIBE_KEYSPACE_PATTERN.toString}""")
+    }
+  }
+
   def extractDescribeKeyspacesCmd(text: String): DescribeKeyspacesCmd = {
     text match {
         case DESCRIBE_KEYSPACES_PATTERN() => new DescribeKeyspacesCmd
@@ -222,6 +317,15 @@ class ParagraphParser extends RegexParsers{
       }
   }
 
+  def extractDescribeTableCmd(text: String): DescribeTableCmd = {
+    text match {
+      case DESCRIBE_TABLE_WITH_KEYSPACE_PATTERN(keyspace,table) => new DescribeTableCmd(Option(keyspace),table)
+      case DESCRIBE_TABLE_PATTERN(table) => new DescribeTableCmd(Option.empty,table)
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE TABLE. " +
+        s"""It should comply to the patterns: ${DESCRIBE_TABLE_WITH_KEYSPACE_PATTERN.toString} or ${DESCRIBE_TABLE_PATTERN.toString}""".stripMargin)
+    }
+  }
+
   def extractDescribeTablesCmd(text: String): DescribeTablesCmd = {
     text match {
       case DESCRIBE_TABLES_PATTERN() => new DescribeTablesCmd
@@ -230,29 +334,71 @@ class ParagraphParser extends RegexParsers{
     }
   }
 
-  def extractDescribeKeyspaceCmd(text: String): DescribeKeyspaceCmd = {
+  def extractDescribeTypeCmd(text: String): DescribeTypeCmd = {
     text match {
-      case DESCRIBE_KEYSPACE_PATTERN(keyspace) => new DescribeKeyspaceCmd(keyspace)
-      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE KEYSPACE. " +
-        s"""It should comply to the pattern: ${DESCRIBE_KEYSPACE_PATTERN.toString}""")
+      case DESCRIBE_TYPE_WITH_KEYSPACE_PATTERN(keyspace,table) => new DescribeTypeCmd(Option(keyspace),table)
+      case DESCRIBE_TYPE_PATTERN(table) => new DescribeTypeCmd(Option.empty,table)
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE TYPE. " +
+        s"""It should comply to the patterns: ${DESCRIBE_TYPE_WITH_KEYSPACE_PATTERN.toString} or ${DESCRIBE_TYPE_PATTERN.toString}""".stripMargin)
     }
   }
 
-  def extractDescribeTableCmd(text: String): DescribeTableCmd = {
+  def extractDescribeTypesCmd(text: String): DescribeTypesCmd = {
     text match {
-      case DESCRIBE_TABLE_WITH_KEYSPACE_PATTERN(keyspace,table) => new DescribeTableCmd(Option(keyspace),table)
-      case DESCRIBE_TABLE_PATTERN(table) => new DescribeTableCmd(Option.empty,table)
-      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE TABLE. " +
-       s"""It should comply to the patterns: ${DESCRIBE_TABLE_WITH_KEYSPACE_PATTERN.toString} or ${DESCRIBE_TABLE_PATTERN.toString}""".stripMargin)
+      case DESCRIBE_TYPES_PATTERN() => new DescribeTypesCmd
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE TYPES. " +
+        s"""It should comply to the pattern: ${DESCRIBE_TYPES_PATTERN.toString}""")
     }
   }
 
-  def extractDescribeTypeCmd(text: String): DescribeUDTCmd = {
+  def extractDescribeFunctionCmd(text: String): DescribeFunctionCmd = {
     text match {
-      case DESCRIBE_TYPE_WITH_KEYSPACE_PATTERN(keyspace,table) => new DescribeUDTCmd(Option(keyspace),table)
-      case DESCRIBE_TYPE_PATTERN(table) => new DescribeUDTCmd(Option.empty,table)
-      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE TYPE. " +
-        s"""It should comply to the patterns: ${DESCRIBE_TYPE_WITH_KEYSPACE_PATTERN.toString} or ${DESCRIBE_TYPE_PATTERN.toString}""".stripMargin)
+      case DESCRIBE_FUNCTION_WITH_KEYSPACE_PATTERN(keyspace,function) => new DescribeFunctionCmd(Option(keyspace),function)
+      case DESCRIBE_FUNCTION_PATTERN(function) => new DescribeFunctionCmd(Option.empty,function)
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE FUNCTION. " +
+        s"""It should comply to the patterns: ${DESCRIBE_FUNCTION_WITH_KEYSPACE_PATTERN.toString} or ${DESCRIBE_FUNCTION_PATTERN.toString}""".stripMargin)
+    }
+  }
+
+  def extractDescribeFunctionsCmd(text: String): DescribeFunctionsCmd = {
+    text match {
+      case DESCRIBE_FUNCTIONS_PATTERN() => new DescribeFunctionsCmd
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE FUNCTIONS. " +
+        s"""It should comply to the pattern: ${DESCRIBE_FUNCTIONS_PATTERN.toString}""".stripMargin)
+    }
+  }
+
+  def extractDescribeAggregateCmd(text: String): DescribeAggregateCmd = {
+    text match {
+      case DESCRIBE_AGGREGATE_WITH_KEYSPACE_PATTERN(keyspace,aggregate) => new DescribeAggregateCmd(Option(keyspace),aggregate)
+      case DESCRIBE_AGGREGATE_PATTERN(aggregate) => new DescribeAggregateCmd(Option.empty,aggregate)
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE AGGREGATE. " +
+        s"""It should comply to the patterns: ${DESCRIBE_AGGREGATE_WITH_KEYSPACE_PATTERN.toString} or ${DESCRIBE_AGGREGATE_PATTERN.toString}""".stripMargin)
+    }
+  }
+
+  def extractDescribeAggregatesCmd(text: String): DescribeAggregatesCmd = {
+    text match {
+      case DESCRIBE_AGGREGATES_PATTERN() => new DescribeAggregatesCmd
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE AGGREGATES. " +
+        s"""It should comply to the pattern: ${DESCRIBE_AGGREGATES_PATTERN.toString}""".stripMargin)
+    }
+  }
+
+  def extractDescribeMaterializedViewCmd(text: String): DescribeMaterializedViewCmd = {
+    text match {
+      case DESCRIBE_MATERIALIZED_VIEW_WITH_KEYSPACE_PATTERN(keyspace,view) => new DescribeMaterializedViewCmd(Option(keyspace),view)
+      case DESCRIBE_MATERIALIZED_VIEW_PATTERN(view) => new DescribeMaterializedViewCmd(Option.empty,view)
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE MATERIALIZED VIEW. " +
+        s"""It should comply to the patterns: ${DESCRIBE_MATERIALIZED_VIEW_WITH_KEYSPACE_PATTERN.toString} or ${DESCRIBE_MATERIALIZED_VIEW_PATTERN.toString}""".stripMargin)
+    }
+  }
+
+  def extractDescribeMaterializedViewsCmd(text: String): DescribeMaterializedViewsCmd = {
+    text match {
+      case DESCRIBE_MATERIALIZED_VIEWS_PATTERN() => new DescribeMaterializedViewsCmd
+      case _ => throw new InterpreterException(s"Invalid syntax for DESCRIBE MATERIALIZED VIEWS. " +
+        s"""It should comply to the pattern: ${DESCRIBE_MATERIALIZED_VIEWS_PATTERN.toString}""".stripMargin)
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/main/scala/org/apache/zeppelin/cassandra/TextBlockHierarchy.scala
----------------------------------------------------------------------
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 70b2ce2..61a2d8d 100644
--- a/cassandra/src/main/scala/org/apache/zeppelin/cassandra/TextBlockHierarchy.scala
+++ b/cassandra/src/main/scala/org/apache/zeppelin/cassandra/TextBlockHierarchy.scala
@@ -77,10 +77,16 @@ object TextBlockHierarchy {
   object BatchStatementType extends StatementType
   object DescribeClusterStatementType extends StatementType
   object DescribeAllKeyspacesStatementType extends StatementType
-  object DescribeKeyspaceStatementType extends StatementType
   object DescribeAllTablesStatementType extends StatementType
+  object DescribeAllTypesStatementType extends StatementType
+  object DescribeAllFunctionsStatementType extends StatementType
+  object DescribeAllAggregatesStatementType extends StatementType
+  object DescribeKeyspaceStatementType extends StatementType
   object DescribeTableStatementType extends StatementType
   object DescribeTypeStatementType extends StatementType
+  object DescribeFunctionStatementType extends StatementType
+  object DescribeAggregateStatementType extends StatementType
+  object DescribeMaterializedView extends StatementType
   object HelpStatementType extends StatementType
 
   abstract class QueryStatement(val statementType: StatementType) extends AnyBlock(StatementBlock) {
@@ -104,15 +110,27 @@ 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
 
+  case class DescribeTypesCmd(override val statement: String = "DESCRIBE TYPES;")
+    extends QueryStatement(DescribeAllTypesStatementType) with DescribeCommandStatement
+
+  case class DescribeFunctionsCmd(override val statement: String = "DESCRIBE FUNCTIONS;") extends QueryStatement(DescribeAllFunctionsStatementType)
+    with DescribeCommandStatement
+
+  case class DescribeAggregatesCmd(override val statement: String = "DESCRIBE AGGREGATES;") extends QueryStatement(DescribeAllAggregatesStatementType)
+    with DescribeCommandStatement
+
+  case class DescribeMaterializedViewsCmd(override val statement: String = "DESCRIBE MATERIALIZED VIEWS;") extends QueryStatement(DescribeAllAggregatesStatementType)
+    with DescribeCommandStatement
+
   case class DescribeKeyspaceCmd(keyspace: String) extends QueryStatement(DescribeKeyspaceStatementType)
     with DescribeCommandStatement {
     override val statement: String = s"DESCRIBE KEYSPACE $keyspace;"
@@ -126,7 +144,7 @@ object TextBlockHierarchy {
     }
   }
 
-  case class DescribeUDTCmd(keyspace:Option[String],udtName: String) extends QueryStatement(DescribeTypeStatementType)
+  case class DescribeTypeCmd(keyspace:Option[String], udtName: String) extends QueryStatement(DescribeTypeStatementType)
     with DescribeCommandStatement {
     override val statement: String = keyspace match {
       case Some(ks) => s"DESCRIBE TYPE $ks.$udtName;"
@@ -134,6 +152,30 @@ object TextBlockHierarchy {
     }
   }
 
-  class HelpCmd extends QueryStatement(HelpStatementType)
+  case class DescribeFunctionCmd(keyspace:Option[String], function: String) extends QueryStatement(DescribeFunctionStatementType)
+    with DescribeCommandStatement {
+    override val statement: String = keyspace match {
+      case Some(ks) => s"DESCRIBE FUNCTION $ks.$function;"
+      case None => s"DESCRIBE FUNCTION $function;"
+    }
+  }
+
+  case class DescribeAggregateCmd(keyspace:Option[String], aggregate: String) extends QueryStatement(DescribeAggregateStatementType)
+    with DescribeCommandStatement {
+    override val statement: String = keyspace match {
+      case Some(ks) => s"DESCRIBE AGGREGATE $ks.$aggregate;"
+      case None => s"DESCRIBE AGGREGATE $aggregate;"
+    }
+  }
+
+  case class DescribeMaterializedViewCmd(keyspace:Option[String], view: String) extends QueryStatement(DescribeMaterializedView)
+  with DescribeCommandStatement {
+    override val statement: String = keyspace match {
+      case Some(ks) => s"DESCRIBE MATERIALIZED VIEW $ks.$view;"
+      case None => s"DESCRIBE MATERIALIZED VIEW $view;"
+    }
+  }
+
+  case class HelpCmd(val statement:String = "HELP;") extends QueryStatement(HelpStatementType)
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/test/java/org/apache/zeppelin/cassandra/CassandraInterpreterTest.java
----------------------------------------------------------------------
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 afca9de..560c57e 100644
--- a/cassandra/src/test/java/org/apache/zeppelin/cassandra/CassandraInterpreterTest.java
+++ b/cassandra/src/test/java/org/apache/zeppelin/cassandra/CassandraInterpreterTest.java
@@ -30,22 +30,20 @@ import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.when;
 
 import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.ProtocolVersion;
 import com.datastax.driver.core.Session;
-import info.archinnov.achilles.junit.AchillesResource;
-import info.archinnov.achilles.junit.AchillesResourceBuilder;
+
+import info.archinnov.achilles.embedded.CassandraEmbeddedServerBuilder;
+
+import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
+import org.junit.*;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
-import scala.io.Source;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
@@ -58,16 +56,14 @@ public class CassandraInterpreterTest {
 
     private static final String ARTISTS_TABLE = "zeppelin.artists";
 
-    @ClassRule
-    public static AchillesResource resource = AchillesResourceBuilder
+    public static Session session = CassandraEmbeddedServerBuilder
         .noEntityPackages()
         .withKeyspaceName("zeppelin")
         .withScript("prepare_schema.cql")
         .withScript("prepare_data.cql")
-        .build();
-
-    private static Session session = resource.getNativeSession();
-
+        .withProtocolVersion(ProtocolVersion.V3)
+        .buildNativeSessionOnly();
+//    public static Session session = null;
     private static CassandraInterpreter interpreter;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -76,7 +72,8 @@ public class CassandraInterpreterTest {
     @BeforeClass
     public static void setUp() {
         Properties properties = new Properties();
-        final Cluster cluster = resource.getNativeSession().getCluster();
+        final Cluster cluster = session.getCluster();
+//        final Cluster cluster = null;
         properties.setProperty(CASSANDRA_CLUSTER_NAME, cluster.getClusterName());
         properties.setProperty(CASSANDRA_COMPRESSION_PROTOCOL, "NONE");
         properties.setProperty(CASSANDRA_CREDENTIALS_USERNAME, "none");
@@ -131,7 +128,7 @@ public class CassandraInterpreterTest {
     @Test
     public void should_create_cluster_and_session_upon_call_to_open() throws Exception {
         assertThat(interpreter.cluster).isNotNull();
-        assertThat(interpreter.cluster.getClusterName()).isEqualTo(resource.getNativeSession().getCluster().getClusterName());
+        assertThat(interpreter.cluster.getClusterName()).isEqualTo(session.getCluster().getClusterName());
         assertThat(interpreter.session).isNotNull();
         assertThat(interpreter.helper).isNotNull();
     }
@@ -241,7 +238,7 @@ public class CassandraInterpreterTest {
         //Then
         assertThat(actual.code()).isEqualTo(Code.ERROR);
         assertThat(actual.message())
-                .contains("Not enough replica available for query at consistency THREE (3 required but only 1 alive)");
+                .contains("Not enough replicas available for query at consistency THREE (3 required but only 1 alive)");
     }
 
     @Test
@@ -329,14 +326,14 @@ public class CassandraInterpreterTest {
         assertThat(actual.message()).isEqualTo(
                 "login\taddresses\tage\tdeceased\tfirstname\tlast_update\tlastname\tlocation\n" +
                         "jdoe\t" +
-                        "{street_number:3, street_name:'Beverly Hills Bld', zip_code:90209," +
-                        " country:'USA', extra_info:['Right on the hills', 'Next to the post box'], " +
-                        "phone_numbers:{'office':2015790847, 'home':2016778524}}\tnull\t" +
+                        "{street_number:3,street_name:'Beverly Hills Bld',zip_code:90209," +
+                        "country:'USA',extra_info:['Right on the hills','Next to the post box']," +
+                        "phone_numbers:{'office':2015790847,'home':2016778524}}\tnull\t" +
                         "null\t" +
                         "John\t" +
                         "null\t" +
                         "DOE\t" +
-                        "('USA', 90209, 'Beverly Hills')\n");
+                        "('USA',90209,'Beverly Hills')\n");
     }
 
     @Test
@@ -554,6 +551,76 @@ public class CassandraInterpreterTest {
     }
 
     @Test
+    @Ignore
+    //TODO activate test when using Java 8 and C* 3.x
+    public void should_describe_function() 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();
+
+        String createFunction = "CREATE FUNCTION zeppelin.maxof(val1 int,val2 int) " +
+                "RETURNS NULL ON NULL INPUT " +
+                "RETURNS int " +
+                "LANGUAGE java " +
+                "AS $$" +
+                "    return Math.max(val1, val2);\n" +
+                "$$;";
+        interpreter.interpret(createFunction, intrContext);
+        String query = "DESCRIBE FUNCTION zeppelin.maxOf;";
+
+        //When
+        final InterpreterResult actual = interpreter.interpret(query, intrContext);
+
+        //Then
+        assertThat(actual.code()).isEqualTo(Code.SUCCESS);
+        assertThat(actual.message()).isEqualTo("xxxxx");
+    }
+
+    @Test
+    @Ignore
+    //TODO activate test when using Java 8 and C* 3.x
+    public void should_describe_aggregate() 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 AGGREGATES;";
+
+        //When
+        final InterpreterResult actual = interpreter.interpret(query, intrContext);
+
+        //Then
+        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
         String query = "DESCRIBE TABLE live_data.complex_table;";
@@ -601,6 +668,7 @@ public class CassandraInterpreterTest {
 
         assertThat(reformatHtml(actual.message())).isEqualTo(expected);
     }
+
     @Test
     public void should_error_describing_non_existing_table() throws Exception {
         //Given
@@ -647,8 +715,8 @@ public class CassandraInterpreterTest {
         return  rawHtml
                 .replaceAll("\\s*\n\\s*","")
                 .replaceAll(">\\s+<", "><")
-                .replaceAll("(?s)data-target=\"#[a-f0-9-]+(?:_asCQL)?\"", "")
-                .replaceAll("(?s)id=\"[a-f0-9-]+(?:_asCQL)?\"", "")
+                .replaceAll("(?s)data-target=\"#[a-f0-9-]+(?:_asCQL|_indices_asCQL)?\"", "")
+                .replaceAll("(?s)id=\"[a-f0-9-]+(?:_asCQL|_indices_asCQL)?\"", "")
                 .trim();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/test/java/org/apache/zeppelin/cassandra/InterpreterLogicTest.java
----------------------------------------------------------------------
diff --git a/cassandra/src/test/java/org/apache/zeppelin/cassandra/InterpreterLogicTest.java b/cassandra/src/test/java/org/apache/zeppelin/cassandra/InterpreterLogicTest.java
index f7993fb..bf685f1 100644
--- a/cassandra/src/test/java/org/apache/zeppelin/cassandra/InterpreterLogicTest.java
+++ b/cassandra/src/test/java/org/apache/zeppelin/cassandra/InterpreterLogicTest.java
@@ -302,10 +302,10 @@ public class InterpreterLogicTest {
     }
 
     private <A> scala.collection.immutable.List<A> toScalaList(java.util.List<A> list)  {
-        return scala.collection.JavaConverters.asScalaBufferConverter(list).asScala().toList();
+        return scala.collection.JavaConversions.asScalaIterable(list).toList();
     }
 
     private  <A> java.util.List<A> toJavaList(scala.collection.immutable.List<A> list){
-        return scala.collection.JavaConverters.seqAsJavaListConverter(list).asJava();
+        return scala.collection.JavaConversions.asJavaList(list);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/11a45e2e/cassandra/src/test/resources/scalate/DescribeCluster.html
----------------------------------------------------------------------
diff --git a/cassandra/src/test/resources/scalate/DescribeCluster.html b/cassandra/src/test/resources/scalate/DescribeCluster.html
index 5d32c7d..3a5c001 100644
--- a/cassandra/src/test/resources/scalate/DescribeCluster.html
+++ b/cassandra/src/test/resources/scalate/DescribeCluster.html
@@ -1,98 +1 @@
-<br/>
-<br/>
-<nav class="navbar navbar-default">
-    <ul class="nav navbar-nav">
-
-        <li>
-            <a><strong>DESCRIBE CLUSTER;</strong></a>
-        </li>
-    </ul>
-    <ul class="nav navbar-nav navbar-right">
-        <li class="dropdown">
-            <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
-                <strong>Legend</strong>
-                <span class="caret"></span>
-            </a>
-            <ul class="dropdown-menu">
-                <li>
-                    <a role="button">
-                        <i class="glyphicon glyphicon-dashboard text-muted" />&nbsp;Cluster
-                    </a>
-                </li>
-                <li>
-                    <a role="button">
-                        <i class="glyphicon glyphicon-folder-open text-danger" />&nbsp;&nbsp;Keyspace
-                    </a>
-                </li>
-                <li>
-                    <a role="button">
-                        <i class="glyphicon glyphicon-copyright-mark text-warning" />&nbsp;&nbsp;UDT
-                    </a>
-                </li>
-                <li>
-                    <a role="button">
-                        <i class="glyphicon glyphicon-th-list text-primary" />&nbsp;&nbsp;Table
-                    </a>
-                </li>
-                <li class="bg-info">
-                    <a role="button">
-                        <i class="glyphicon glyphicon-fullscreen" />&nbsp;&nbsp;Partition Key
-                    </a>
-                </li>
-                <li class="bg-warning">
-                    <a role="button">
-                        <i class="glyphicon glyphicon-pushpin" />&nbsp;&nbsp;Static Column
-                    </a>
-                </li>
-                <li class="bg-success">
-                    <a role="button">
-                        <i class="glyphicon glyphicon-sort" />&nbsp;&nbsp;Clustering Column
-                    </a>
-                </li>
-                <li class="bg-success">
-                    <a role="button">
-                        <i class="glyphicon glyphicon-sort-by-attributes" />&nbsp;&nbsp;Clustering Order ASC
-                    </a>
-                </li>
-                <li class="bg-success">
-                    <a role="button">
-                        <i class="glyphicon glyphicon-sort-by-attributes-alt" />&nbsp;&nbsp;Clustering Order DESC
-                    </a>
-                </li>
-                <li>
-                    <a role="button">
-                        <i class="glyphicon glyphicon-info-sign" />&nbsp;&nbsp;Indexed Column
-                    </a>
-                </li>
-            </ul>
-        </li>
-        <li>
-            <a href="#"></a>
-        </li>
-    </ul>
-</nav>
-<hr/>
-<div class="row">
-    <div class="col-md-4"></div>
-    <div class="col-md-4 col-offset-md-4">
-        <div class="table-responsive table-bordered">
-            <table class="table">
-                <caption>
-                    <h4 class="text-muted">
-                        <i class="glyphicon glyphicon-dashboard"/>&nbsp;Test Cluster
-                    </h4>
-                </caption>
-                <thead>
-                <tr>
-                    <th>Partitioner</th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr>
-                    <td>org.apache.cassandra.dht.Murmur3Partitioner</td>
-                </tr>
-                <tbody>
-            </table>
-        </div>
-    </div>
-</div>
\ No newline at end of file
+<br/><br/><nav class="navbar navbar-default"><ul class="nav navbar-nav"><li><a><strong>DESCRIBE CLUSTER;</strong></a></li></ul><ul class="nav navbar-nav navbar-right"><li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><strong>Legend</strong><span class="caret"></span></a><ul class="dropdown-menu"><li><a role="button"><i class="glyphicon glyphicon-dashboard text-muted" />&nbsp;Cluster</a></li><li><a role="button"><i class="glyphicon glyphicon-folder-open text-danger" />&nbsp;&nbsp;Keyspace</a></li><li><a role="button"><i class="glyphicon glyphicon-copyright-mark text-warning" />&nbsp;&nbsp;UDT</a></li><li><a role="button"><i class="glyphicon glyphicon-th-list text-primary" />&nbsp;&nbsp;Table</a></li><li><a role="button"><i class="glyphicon glyphicon-eye-open text-primary" />&nbsp;&nbsp;Materialized View</a></li><li><a role="button"><i class="glyphicon glyphicon-random text-success" />&nbsp;&nbsp;Function</a
 ></li><li><a role="button"><i class="glyphicon glyphicon-retweet text-success" />&nbsp;&nbsp;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" />&nbsp;&nbsp;Partition Key</a></li><li class="bg-warning"><a role="button"><i class="glyphicon glyphicon-pushpin" />&nbsp;&nbsp;Static Column</a></li><li class="bg-success"><a role="button"><i class="glyphicon glyphicon-sort" />&nbsp;&nbsp;Clustering Column</a></li><li class="bg-success"><a role="button"><i class="glyphicon glyphicon-sort-by-attributes" />&nbsp;&nbsp;Clustering Order ASC</a></li><li class="bg-success"><a role="button"><i class="glyphicon glyphicon-sort-by-attributes-alt" />&nbsp;&nbsp;Clustering Order DESC</a></li></ul></li><li><a href="#"></a></li></ul></nav><hr/><div class="row"><div class="col-md-4"></div><div class="col-md-4 col-offset-md-4"><div
  class="table-responsive table-bordered"><table class="table"><caption><h4 class="text-muted"><i class="glyphicon glyphicon-dashboard"/>&nbsp;Test Cluster</h4></caption><thead><tr><th>Partitioner</th></tr></thead><tbody><tr><td>org.apache.cassandra.dht.Murmur3Partitioner</td></tr><tbody></table></div></div></div>
\ No newline at end of file


Mime
View raw message