-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Dashboard] Support arbitrary non-aggregate expressions in dimensions #3702
Conversation
@@ -297,7 +297,7 @@ func columnIdentifierExpression(mv *runtimev1.MetricsViewSpec, aliases []*runtim | |||
// check if identifier is a dimension | |||
for _, dim := range mv.Dimensions { | |||
if dim.Name == name { | |||
return safeName(metricsViewDimensionColumn(dim)), true | |||
return metricsViewDimensionExpression(dim), true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will get templated into the where clause:
- Might it be problematic to put a free form expression in here? I think at the least it will need to be wrapped in parentheses
- Would it be better to template in just the dimension name (which the expression is aliased to in the
SELECT
clause)? But not sure if that works on Druid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with this is for queries where the dimension is not selected we would have issues with the column not being there. The other option is to only add it if is in the select caluse. That made these builder functions too complex.
As for adding parentheses, it gets added when the identifier is actually used.
I guess we are missing a validation to make sure there isnt sql injection happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The case where the dim is not selected makes sense. Agree on not making it conditional on the select clause, seems to complicated.
- About the parentheses, imagine if the expression is
col1 = 10
and the filter isdim1 = true
, then you're saying the parenthesis will be added such that the where clause becomes(col1 = 10) = true
(correct) and notcol1 = 10 = true
(which would error)? - How could SQL injection happen? For the where filters, I thought we were doing lookups to resolve identifiers and using
?
and args to pass values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Yes all binary expressions have it.
like
andin
do not seem to have it. Lemme add that. - It could happen in the dimension expression,
count(*)";drop table blah; --
or something like that.
dea5101
to
b2a89f5
Compare
Column string | ||
Expression string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we don't have validation to ensure that only one of these are set (exactly one of them should be non-nil)
@@ -297,7 +297,7 @@ func columnIdentifierExpression(mv *runtimev1.MetricsViewSpec, aliases []*runtim | |||
// check if identifier is a dimension | |||
for _, dim := range mv.Dimensions { | |||
if dim.Name == name { | |||
return safeName(metricsViewDimensionColumn(dim)), true | |||
return metricsViewDimensionExpression(dim), true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The case where the dim is not selected makes sense. Agree on not making it conditional on the select clause, seems to complicated.
- About the parentheses, imagine if the expression is
col1 = 10
and the filter isdim1 = true
, then you're saying the parenthesis will be added such that the where clause becomes(col1 = 10) = true
(correct) and notcol1 = 10 = true
(which would error)? - How could SQL injection happen? For the where filters, I thought we were doing lookups to resolve identifiers and using
?
and args to pass values?
runtime/reconcilers/metrics_view.go
Outdated
if d.Expression == "" { | ||
if d.Column == "" { | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be an error? (And ideally checked also at parser level)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. I guess we will never hit this without the parser running and dont need backwards compatibility right?
runtime/reconcilers/metrics_view.go
Outdated
} | ||
|
||
err := olap.Exec(ctx, &drivers.Statement{ | ||
Query: fmt.Sprintf("SELECT %s FROM %s GROUP BY 1", d.Expression, safeSQLName(t.Name)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we put parentheses around the expression, i.e. SELECT (%s) ...
? In case the expression is a sub-query
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might this also be needed elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes adding them
2c8d821
to
82c2e40
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
closes #3009
expression
to dashboard yaml.