blob: e72cf9b3f8517d53508bd326747c7fbb83664746 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.spark.sql.execution.command.timeseries
import scala.collection.mutable
import scala.util.control.Breaks._
import org.apache.spark.sql.execution.command.{DataMapField, Field}
import org.apache.carbondata.common.exceptions.sql.{MalformedCarbonCommandException, MalformedDataMapCommandException}
import org.apache.carbondata.core.constants.CarbonCommonConstants
import org.apache.carbondata.core.metadata.datatype.DataTypes
import org.apache.carbondata.core.metadata.schema.datamap.Granularity
import org.apache.carbondata.core.metadata.schema.table.CarbonTable
/**
* Utility class for time series to keep
*/
object TimeSeriesUtil {
val TIMESERIES_EVENTTIME = "event_time"
/**
* Below method will be used to validate whether column mentioned in time series
* is timestamp column or not
*
* @param dmproperties data map properties
* @param parentTable parent table
* @return whether time stamp column
*/
def validateTimeSeriesEventTime(dmproperties: Map[String, String],
parentTable: CarbonTable) {
val eventTime = dmproperties.get(TIMESERIES_EVENTTIME)
if (!eventTime.isDefined) {
throw new MalformedCarbonCommandException("event_time not defined in time series")
} else {
val carbonColumn = parentTable.getColumnByName(eventTime.get.trim)
if (carbonColumn.getDataType != DataTypes.TIMESTAMP) {
throw new MalformedCarbonCommandException(
"Timeseries event time is only supported on Timestamp " +
"column")
}
}
}
/**
* validate TimeSeries Granularity
*
* @param dmProperties datamap properties
* @param dmClassName datamap class name
* @return whether find only one granularity
*/
def validateTimeSeriesGranularity(
dmProperties: java.util.Map[String, String],
dmClassName: String): Boolean = {
var isFound = false
// 1. granularity only support one
for (granularity <- Granularity.values()) {
if (dmProperties.containsKey(granularity.getName)) {
if (isFound) {
throw new MalformedDataMapCommandException(
s"Only one granularity level can be defined")
} else {
isFound = true
}
}
}
isFound
}
/**
* get TimeSeries Granularity key and value
* check the value
*
* TODO:we will support value not only equal to 1 in the future
*
* @param dmProperties datamap properties
* @param dmClassName datamap class name
* @return key and value tuple
*/
def getTimeSeriesGranularityDetails(
dmProperties: java.util.Map[String, String],
dmClassName: String): (String, String) = {
val defaultValue = "1"
for (granularity <- Granularity.values()) {
if (dmProperties.containsKey(granularity.getName) &&
dmProperties.get(granularity.getName).trim.equalsIgnoreCase(defaultValue)) {
return (granularity.toString.toLowerCase, dmProperties.get(granularity.getName))
}
}
throw new MalformedDataMapCommandException(
s"Granularity only support $defaultValue")
}
/**
* Below method will be used to validate whether timeseries column present in
* select statement or not
*
* @param fieldMapping fields from select plan
* @param timeSeriesColumn timeseries column name
*/
def validateEventTimeColumnExitsInSelect(
fieldMapping: mutable.LinkedHashMap[Field, DataMapField],
timeSeriesColumn: String) : Any = {
val isTimeSeriesColumnExits = fieldMapping.exists { case (_, f) =>
f.columnTableRelationList.isDefined &&
f.columnTableRelationList.get.head.parentColumnName.equalsIgnoreCase(timeSeriesColumn) &&
f.aggregateFunction.isEmpty
}
if(!isTimeSeriesColumnExits) {
throw new MalformedCarbonCommandException(s"Time series column ${ timeSeriesColumn } does " +
s"not exists in select")
}
}
/**
* Below method will be used to validate whether timeseries column present in
* select statement or not
* @param fieldMapping
* fields from select plan
* @param timeSeriesColumn
* timeseries column name
*/
def updateTimeColumnSelect(
fieldMapping: scala.collection.mutable.LinkedHashMap[Field, DataMapField],
timeSeriesColumn: String,
timeSeriesFunction: String) : Any = {
val isTimeSeriesColumnExits = fieldMapping
.find(obj => obj._2.columnTableRelationList.isDefined &&
obj._2.columnTableRelationList.get(0).parentColumnName
.equalsIgnoreCase(timeSeriesColumn) &&
obj._2.aggregateFunction.isEmpty)
isTimeSeriesColumnExits.get._2.aggregateFunction = timeSeriesFunction
}
def validateTimeSeriesGranularityForDate(
timeSeriesFunction: String): Unit = {
for (granularity <- Granularity.values()) {
if (timeSeriesFunction.equalsIgnoreCase(granularity.getName
.substring(0, granularity.getName.indexOf(CarbonCommonConstants.UNDERSCORE)))) {
if (!supportedGranularitiesForDate.contains(granularity.getName)) {
throw new MalformedCarbonCommandException(
"Granularity should be DAY,MONTH or YEAR, for timeseries column of Date type")
}
}
}
}
val supportedGranularitiesForDate: Seq[String] = Seq(
Granularity.DAY.getName,
Granularity.WEEK.getName,
Granularity.MONTH.getName,
Granularity.YEAR.getName)
/**
* validate TimeSeries Granularity
*
* @param timeSeriesFunction user defined granularity
*/
def validateTimeSeriesGranularity(
timeSeriesFunction: String): Unit = {
var found = false
breakable {
for (granularity <- Granularity.values()) {
if (timeSeriesFunction.equalsIgnoreCase(granularity.getName
.substring(0, granularity.getName.lastIndexOf(CarbonCommonConstants.UNDERSCORE)))) {
found = true
break
}
}
}
if (!found) {
throw new MalformedCarbonCommandException(
"Granularity " + timeSeriesFunction + " is invalid")
}
}
}