This is an automated email from the ASF dual-hosted git repository.

abhishekrb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new b20c3dbadfe Fix malformed period throwing `ADMIN` persona error 
(#16626)
b20c3dbadfe is described below

commit b20c3dbadfe299a8d4715d4ecc924ccfab432fc0
Author: Abhishek Radhakrishnan <[email protected]>
AuthorDate: Thu Jun 20 08:40:28 2024 -0700

    Fix malformed period throwing `ADMIN` persona error (#16626)
    
    * Turn invalid periods into user-facing exception providing more context.
    
    The current exception is targeting the ADMIN persona. Catch that and turn
    it into a USER persona instead. Also, provide more context in the error
    message.
    
    * Review comment: pass the wrapping expression and stringify.
    
    * Update 
processing/src/main/java/org/apache/druid/query/expression/ExprUtils.java
    
    Co-authored-by: Clint Wylie <[email protected]>
    
    ---------
    
    Co-authored-by: Clint Wylie <[email protected]>
---
 .../apache/druid/query/expression/ExprUtils.java   | 17 ++++++++++++++--
 .../query/expression/TimestampCeilExprMacro.java   | 11 ++++++++---
 .../query/expression/TimestampFloorExprMacro.java  | 11 ++++++++---
 .../druid/sql/calcite/planner/CalcitePlanner.java  |  2 +-
 .../druid/sql/calcite/CalciteSelectQueryTest.java  | 23 ++++++++++++++++++++++
 5 files changed, 55 insertions(+), 9 deletions(-)

diff --git 
a/processing/src/main/java/org/apache/druid/query/expression/ExprUtils.java 
b/processing/src/main/java/org/apache/druid/query/expression/ExprUtils.java
index e2bd808d7b9..be513b40248 100644
--- a/processing/src/main/java/org/apache/druid/query/expression/ExprUtils.java
+++ b/processing/src/main/java/org/apache/druid/query/expression/ExprUtils.java
@@ -20,6 +20,7 @@
 package org.apache.druid.query.expression;
 
 import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.error.InvalidInput;
 import org.apache.druid.java.util.common.DateTimes;
 import org.apache.druid.java.util.common.IAE;
 import org.apache.druid.java.util.common.granularity.PeriodGranularity;
@@ -45,13 +46,25 @@ public class ExprUtils
   }
 
   static PeriodGranularity toPeriodGranularity(
+      final Expr wrappingExpr,
       final Expr periodArg,
       @Nullable final Expr originArg,
       @Nullable final Expr timeZoneArg,
       final Expr.ObjectBinding bindings
   )
   {
-    final Period period = new Period(periodArg.eval(bindings).asString());
+    final Period period;
+    try {
+      period = new Period(periodArg.eval(bindings).asString());
+    }
+    catch (IllegalArgumentException iae) {
+      throw InvalidInput.exception(
+          "Invalid period[%s] specified for expression[%s]: [%s]",
+          periodArg.stringify(), 
+          wrappingExpr.stringify(),
+          iae.getMessage()
+      );
+    }
     final DateTime origin;
     final DateTimeZone timeZone;
 
@@ -69,7 +82,7 @@ public class ExprUtils
       final Object value = originArg.eval(bindings).valueOrDefault();
       if (value instanceof String && NullHandling.isNullOrEquivalent((String) 
value)) {
         // We get a blank string here, when sql compatible null handling is 
enabled
-        // and expression contains empty string for for origin
+        // and expression contains empty string for origin
         // e.g timestamp_floor(\"__time\",'PT1M','','UTC')
         origin = null;
       } else {
diff --git 
a/processing/src/main/java/org/apache/druid/query/expression/TimestampCeilExprMacro.java
 
b/processing/src/main/java/org/apache/druid/query/expression/TimestampCeilExprMacro.java
index cfd63f1ea61..3c5102ae7a2 100644
--- 
a/processing/src/main/java/org/apache/druid/query/expression/TimestampCeilExprMacro.java
+++ 
b/processing/src/main/java/org/apache/druid/query/expression/TimestampCeilExprMacro.java
@@ -63,7 +63,7 @@ public class TimestampCeilExprMacro implements 
ExprMacroTable.ExprMacro
     TimestampCeilExpr(final TimestampCeilExprMacro macro, final List<Expr> 
args)
     {
       super(macro, args);
-      this.granularity = getGranularity(args, InputBindings.nilBindings());
+      this.granularity = getGranularity(this, args, 
InputBindings.nilBindings());
     }
 
     @Nonnull
@@ -113,9 +113,14 @@ public class TimestampCeilExprMacro implements 
ExprMacroTable.ExprMacro
     }
   }
 
-  private static PeriodGranularity getGranularity(final List<Expr> args, final 
Expr.ObjectBinding bindings)
+  private static PeriodGranularity getGranularity(
+      final Expr expr,
+      final List<Expr> args,
+      final Expr.ObjectBinding bindings
+  )
   {
     return ExprUtils.toPeriodGranularity(
+        expr,
         args.get(1),
         args.size() > 2 ? args.get(2) : null,
         args.size() > 3 ? args.get(3) : null,
@@ -135,7 +140,7 @@ public class TimestampCeilExprMacro implements 
ExprMacroTable.ExprMacro
     @Override
     public ExprEval eval(final ObjectBinding bindings)
     {
-      final PeriodGranularity granularity = getGranularity(args, bindings);
+      final PeriodGranularity granularity = getGranularity(this, args, 
bindings);
       long argTime = args.get(0).eval(bindings).asLong();
       long bucketStartTime = granularity.bucketStart(argTime);
       if (argTime == bucketStartTime) {
diff --git 
a/processing/src/main/java/org/apache/druid/query/expression/TimestampFloorExprMacro.java
 
b/processing/src/main/java/org/apache/druid/query/expression/TimestampFloorExprMacro.java
index a243273b8f0..02eed7327f1 100644
--- 
a/processing/src/main/java/org/apache/druid/query/expression/TimestampFloorExprMacro.java
+++ 
b/processing/src/main/java/org/apache/druid/query/expression/TimestampFloorExprMacro.java
@@ -56,9 +56,14 @@ public class TimestampFloorExprMacro implements 
ExprMacroTable.ExprMacro
     }
   }
 
-  private static PeriodGranularity computeGranularity(final List<Expr> args, 
final Expr.ObjectBinding bindings)
+  private static PeriodGranularity computeGranularity(
+      final Expr expr,
+      final List<Expr> args,
+      final Expr.ObjectBinding bindings
+  )
   {
     return ExprUtils.toPeriodGranularity(
+        expr,
         args.get(1),
         args.size() > 2 ? args.get(2) : null,
         args.size() > 3 ? args.get(3) : null,
@@ -73,7 +78,7 @@ public class TimestampFloorExprMacro implements 
ExprMacroTable.ExprMacro
     TimestampFloorExpr(final TimestampFloorExprMacro macro, final List<Expr> 
args)
     {
       super(macro, args);
-      this.granularity = computeGranularity(args, InputBindings.nilBindings());
+      this.granularity = computeGranularity(this, args, 
InputBindings.nilBindings());
     }
 
     /**
@@ -170,7 +175,7 @@ public class TimestampFloorExprMacro implements 
ExprMacroTable.ExprMacro
     @Override
     public ExprEval eval(final ObjectBinding bindings)
     {
-      final PeriodGranularity granularity = computeGranularity(args, bindings);
+      final PeriodGranularity granularity = computeGranularity(this, args, 
bindings);
       return 
ExprEval.of(granularity.bucketStart(args.get(0).eval(bindings).asLong()));
     }
 
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/CalcitePlanner.java 
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/CalcitePlanner.java
index 933baaac9ba..8eb9541961c 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/CalcitePlanner.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/CalcitePlanner.java
@@ -200,7 +200,7 @@ public class CalcitePlanner implements Planner, ViewExpander
 
     state = CalcitePlanner.State.STATE_2_READY;
 
-    // If user specify own traitDef, instead of default default trait,
+    // If user specifies own traitDef, instead of default trait,
     // register the trait def specified in traitDefs.
     if (this.traitDefs == null) {
       planner.addRelTraitDef(ConventionTraitDef.INSTANCE);
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSelectQueryTest.java 
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSelectQueryTest.java
index 3203ae9915e..d1f256207d5 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSelectQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSelectQueryTest.java
@@ -22,6 +22,7 @@ package org.apache.druid.sql.calcite;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.error.DruidExceptionMatcher;
 import org.apache.druid.java.util.common.DateTimes;
 import org.apache.druid.java.util.common.Intervals;
 import org.apache.druid.java.util.common.granularity.Granularities;
@@ -130,6 +131,28 @@ public class CalciteSelectQueryTest extends 
BaseCalciteQueryTest
     );
   }
 
+  @Test
+  public void testTimeCeilExpressionContainingInvalidPeriod()
+  {
+    testQueryThrows(
+        "SELECT TIME_CEIL(__time, 'PT1Y') FROM foo",
+        DruidExceptionMatcher.invalidInput().expectMessageContains(
+            "Invalid period['PT1Y'] specified for 
expression[timestamp_ceil(\"__time\", 'PT1Y', null, 'UTC')]"
+        )
+    );
+  }
+
+  @Test
+  public void testTimeFloorExpressionContainingInvalidPeriod()
+  {
+    testQueryThrows(
+        "SELECT TIME_FLOOR(TIMESTAMPADD(DAY, -1, __time), 'PT1D') FROM foo",
+        DruidExceptionMatcher.invalidInput().expectMessageContains(
+            "Invalid period['PT1D'] specified for 
expression[timestamp_floor((\"__time\" + -86400000), 'PT1D', null, 'UTC')]"
+        )
+    );
+  }
+
   @Test
   public void testValuesContainingNull()
   {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to