Add validation for invalid partitioned by granularities (#12589)

* Add validation for invalid partitioned by granularities

* review comments

* improve error message, change location of the method

* remove imports

* use StringUtils.lowercase

Co-authored-by: Adarsh Sanjeev <adarshsanjeev@gmail.com>
This commit is contained in:
Laksh Singla 2022-06-06 22:00:29 +05:30 committed by GitHub
parent 5a283964ca
commit 81c37c6515
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 0 deletions

View File

@ -65,6 +65,7 @@ org.apache.druid.java.util.common.Pair<Granularity, String> PartitionGranularity
e = Expression(ExprContext.ACCEPT_SUB_QUERY)
{
granularity = DruidSqlParserUtils.convertSqlNodeToGranularityThrowingParseExceptions(e);
DruidSqlParserUtils.throwIfUnsupportedGranularityInPartitionedBy(granularity);
unparseString = e.toString();
}
)

View File

@ -32,8 +32,10 @@ import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlOrderBy;
import org.apache.calcite.sql.SqlTimestampLiteral;
import org.apache.calcite.tools.ValidationException;
import org.apache.druid.java.util.common.IAE;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.common.granularity.Granularity;
import org.apache.druid.java.util.common.granularity.GranularityType;
import org.apache.druid.java.util.common.granularity.PeriodGranularity;
import org.apache.druid.java.util.common.logger.Logger;
import org.apache.druid.query.filter.AndDimFilter;
@ -56,6 +58,7 @@ import org.joda.time.base.AbstractInterval;
import java.sql.Timestamp;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -413,4 +416,24 @@ public class DruidSqlParserUtils
ZonedDateTime zonedTimestamp = sqlTimestamp.toLocalDateTime().atZone(timeZone.toTimeZone().toZoneId());
return String.valueOf(zonedTimestamp.toInstant().toEpochMilli());
}
/**
* Throws an IAE with appropriate message if the granularity supplied is not present in
* {@link org.apache.druid.java.util.common.granularity.Granularities}. It also filters out NONE as it is not a valid
* granularity that can be supplied in PARTITIONED BY
*/
public static void throwIfUnsupportedGranularityInPartitionedBy(Granularity granularity)
{
if (!GranularityType.isStandard(granularity)) {
throw new IAE(
"The granularity specified in PARTITIONED BY is not supported. "
+ "Please use an equivalent of these granularities: %s.",
Arrays.stream(GranularityType.values())
.filter(granularityType -> !granularityType.equals(GranularityType.NONE))
.map(Enum::name)
.map(StringUtils::toLowerCase)
.collect(Collectors.joining(", "))
);
}
}
}

View File

@ -738,4 +738,21 @@ public class CalciteInsertDmlTest extends CalciteIngestionDmlTest
)
.verify();
}
@Test
public void testInsertQueryWithInvalidGranularity()
{
testIngestionQuery()
.sql("insert into foo1 select __time, dim1 FROM foo partitioned by time_floor(__time, 'PT2H')")
.expectValidationError(
CoreMatchers.allOf(
CoreMatchers.instanceOf(SqlPlanningException.class),
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString(
"The granularity specified in PARTITIONED BY is not supported. "
+ "Please use an equivalent of these granularities: second, minute, five_minute, ten_minute, "
+ "fifteen_minute, thirty_minute, hour, six_hour, day, week, month, quarter, year, all."))
)
)
.verify();
}
}