-
Notifications
You must be signed in to change notification settings - Fork 271
feat: update ChartFormData and QueryObject to support filters. #164
Changes from 9 commits
e349fa7
0ec5b5a
496e202
07435ee
1b4392e
711acfe
648dc8d
d1a4ab7
1e8853e
bb1d5b5
e9ac969
3bbe164
a005c71
f702ca1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { SimpleAdhocFilter, isBinaryAdhocFilter, isUnaryAdhocFilter } from '../types/Filter'; | ||
import { QueryObjectFilterClause } from '../types/Query'; | ||
|
||
export default function convertFilter(filter: SimpleAdhocFilter): QueryObjectFilterClause { | ||
const { subject } = filter; | ||
if (isUnaryAdhocFilter(filter)) { | ||
const { operator } = filter; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can put it outside the current block to reduce the duplication. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Has to be inside the block to infer the correct |
||
|
||
return { | ||
col: subject, | ||
op: operator, | ||
}; | ||
} else if (isBinaryAdhocFilter(filter)) { | ||
const { operator } = filter; | ||
|
||
return { | ||
col: subject, | ||
op: operator, | ||
val: filter.comparator, | ||
}; | ||
} | ||
|
||
const { operator } = filter; | ||
|
||
return { | ||
col: subject, | ||
op: operator, | ||
val: filter.comparator, | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { ChartFormDataMetric } from '../types/ChartFormData'; | ||
import { QueryObjectMetric } from '../types/Query'; | ||
import { AdhocMetric } from '../types/Metric'; | ||
|
||
export const LABEL_MAX_LENGTH = 43; | ||
|
||
function getDefaultLabel(metric: AdhocMetric) { | ||
let label: string; | ||
if (metric.expressionType === 'SIMPLE') { | ||
label = `${metric.aggregate}(${metric.column.columnName})`; | ||
} else { | ||
label = metric.sqlExpression; | ||
} | ||
|
||
return label.length <= LABEL_MAX_LENGTH | ||
? label | ||
: `${label.substring(0, LABEL_MAX_LENGTH - 3)}...`; | ||
} | ||
|
||
export default function convertMetric(metric: ChartFormDataMetric): QueryObjectMetric { | ||
let formattedMetric; | ||
if (typeof metric === 'string') { | ||
formattedMetric = { | ||
label: metric, | ||
}; | ||
} else { | ||
// Note we further sanitize the metric label for BigQuery datasources | ||
// TODO: move this logic to the client once client has more info on the | ||
// the datasource | ||
const label = metric.label || getDefaultLabel(metric); | ||
formattedMetric = { | ||
...metric, | ||
label, | ||
}; | ||
} | ||
|
||
return formattedMetric; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* eslint-disable camelcase */ | ||
import { ChartFormData, isDruidFormData } from '../types/ChartFormData'; | ||
import { QueryObjectExtras } from '../types/Query'; | ||
|
||
export default function processExtras(formData: ChartFormData): QueryObjectExtras { | ||
const { where = '' } = formData; | ||
|
||
if (isDruidFormData(formData)) { | ||
const { druid_time_origin, having_druid } = formData; | ||
|
||
return { druid_time_origin, having_druid, where }; | ||
} | ||
|
||
const { time_grain_sqla, having } = formData; | ||
|
||
return { having, time_grain_sqla, where }; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { ChartFormData } from '../types/ChartFormData'; | ||
import { QueryObjectFilterClause } from '../types/Query'; | ||
import { isSimpleAdhocFilter } from '../types/Filter'; | ||
import convertFilter from './convertFilter'; | ||
|
||
/** Logic formerly in viz.py's process_query_filters */ | ||
export default function processFilters(formData: ChartFormData) { | ||
// TODO: Implement | ||
// utils.convert_legacy_filters_into_adhoc(self.form_data) | ||
|
||
// TODO: Implement | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will these two in the scope of this PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These will be beyond the scope. Right now this PR will handle There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you think we should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The legacy filters are using fields I am wondering if we want to support this |
||
// merge_extra_filters(self.form_data) | ||
|
||
// utils.split_adhoc_filters_into_base_filters(self.form_data) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this just indicating what the logic below mapped to? (i.e., it's not part of the TODOs above) should we remove it or keep for context? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will remove or change to simple sentence. Seem not necessary any more |
||
// eslint-disable-next-line camelcase | ||
const { adhoc_filters } = formData; | ||
if (Array.isArray(adhoc_filters)) { | ||
const simpleWhere: QueryObjectFilterClause[] = []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (not blocking) the type helps but I find these a little confusing name-wise, not sure what to expect |
||
const simpleHaving: QueryObjectFilterClause[] = []; | ||
const freeformWhere: string[] = []; | ||
const freeformHaving: string[] = []; | ||
|
||
adhoc_filters.forEach(filter => { | ||
const { clause } = filter; | ||
if (isSimpleAdhocFilter(filter)) { | ||
const filterClause = convertFilter(filter); | ||
if (clause === 'WHERE') { | ||
simpleWhere.push(filterClause); | ||
} else { | ||
simpleHaving.push(filterClause); | ||
} | ||
} else { | ||
const { sqlExpression } = filter; | ||
if (clause === 'WHERE') { | ||
freeformWhere.push(sqlExpression); | ||
} else { | ||
freeformHaving.push(sqlExpression); | ||
} | ||
} | ||
}); | ||
|
||
return { | ||
filters: simpleWhere, | ||
having: freeformHaving.map(exp => `(${exp})`).join(' AND '), | ||
having_filters: simpleHaving, | ||
where: freeformWhere.map(exp => `(${exp})`).join(' AND '), | ||
}; | ||
} | ||
|
||
return {}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { ChartFormData } from '../types/ChartFormData'; | ||
import { QueryObjectMetric } from '../types/Query'; | ||
import { MetricKey } from '../types/Metric'; | ||
import convertMetric from './convertMetric'; | ||
|
||
export default function processMetrics(formData: ChartFormData) { | ||
// Use Array to maintain insertion order | ||
// for metrics that are order sensitive | ||
const metrics: QueryObjectMetric[] = []; | ||
|
||
Object.keys(MetricKey).forEach(key => { | ||
const metric = formData[MetricKey[key as keyof typeof MetricKey]]; | ||
if (metric) { | ||
if (Array.isArray(metric)) { | ||
metric.forEach(m => { | ||
metrics.push(convertMetric(m)); | ||
}); | ||
} else { | ||
metrics.push(convertMetric(metric)); | ||
} | ||
} | ||
}); | ||
|
||
return metrics; | ||
} |
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.
typeof order_desc === 'undefined'
?