Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/great-readers-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@hyperdx/common-utils": minor
"@hyperdx/app": minor
---

feat: Add new none aggregation function to allow fully user defined aggregations in SQL
1 change: 1 addition & 0 deletions packages/app/src/ChartUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const AGG_FNS = [
{ value: 'min' as const, label: 'Minimum' },
{ value: 'count_distinct' as const, label: 'Count Distinct' },
{ value: 'any' as const, label: 'Any' },
{ value: 'none' as const, label: 'None' },
];

export const getMetricAggFns = (
Expand Down
85 changes: 46 additions & 39 deletions packages/app/src/components/DBEditTimeChartForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,12 @@ function ChartSeriesEditorComponent({
</div>
)}
{tableSource?.kind !== SourceKind.Metric && aggFn !== 'count' && (
<div style={{ minWidth: 220 }}>
<div
style={{
minWidth: 220,
...(aggFn === 'none' && { width: '100%' }),
}}
>
<SQLInlineEditorControlled
tableConnections={{
databaseName,
Expand All @@ -289,44 +294,46 @@ function ChartSeriesEditorComponent({
/>
</div>
)}
<Flex align={'center'} gap={'xs'} className="flex-grow-1">
<Text size="sm">Where</Text>
{aggConditionLanguage === 'sql' ? (
<SQLInlineEditorControlled
tableConnections={{
databaseName,
tableName: tableName ?? '',
connectionId: connectionId ?? '',
}}
control={control}
name={`${namePrefix}aggCondition`}
placeholder="SQL WHERE clause (ex. column = 'foo')"
onLanguageChange={lang =>
setValue(`${namePrefix}aggConditionLanguage`, lang)
}
additionalSuggestions={attributeKeys}
language="sql"
onSubmit={onSubmit}
/>
) : (
<SearchInputV2
tableConnections={{
connectionId: connectionId ?? '',
databaseName: databaseName ?? '',
tableName: tableName ?? '',
}}
control={control}
name={`${namePrefix}aggCondition`}
onLanguageChange={lang =>
setValue(`${namePrefix}aggConditionLanguage`, lang)
}
language="lucene"
placeholder="Search your events w/ Lucene ex. column:foo"
onSubmit={onSubmit}
additionalSuggestions={attributeKeys}
/>
)}
</Flex>
{aggFn !== 'none' && (
<Flex align={'center'} gap={'xs'} className="flex-grow-1">
<Text size="sm">Where</Text>
{aggConditionLanguage === 'sql' ? (
<SQLInlineEditorControlled
tableConnections={{
databaseName,
tableName: tableName ?? '',
connectionId: connectionId ?? '',
}}
control={control}
name={`${namePrefix}aggCondition`}
placeholder="SQL WHERE clause (ex. column = 'foo')"
onLanguageChange={lang =>
setValue(`${namePrefix}aggConditionLanguage`, lang)
}
additionalSuggestions={attributeKeys}
language="sql"
onSubmit={onSubmit}
/>
) : (
<SearchInputV2
tableConnections={{
connectionId: connectionId ?? '',
databaseName: databaseName ?? '',
tableName: tableName ?? '',
}}
control={control}
name={`${namePrefix}aggCondition`}
onLanguageChange={lang =>
setValue(`${namePrefix}aggConditionLanguage`, lang)
}
language="lucene"
placeholder="Search your events w/ Lucene ex. column:foo"
onSubmit={onSubmit}
additionalSuggestions={attributeKeys}
/>
)}
</Flex>
)}
{showGroupBy && (
<Flex align={'center'} gap={'xs'}>
<Text size="sm" style={{ whiteSpace: 'nowrap' }}>
Expand Down
9 changes: 8 additions & 1 deletion packages/common-utils/src/renderChartConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,13 @@ const aggFnExpr = ({
where?: string;
}) => {
const isAny = fn === 'any';
const isNone = fn === 'none';
const isCount = fn.startsWith('count');
const isWhereUsed = isNonEmptyWhereExpr(where);
// Cast to float64 because the expr might not be a number
const unsafeExpr = {
UNSAFE_RAW_SQL: isAny ? `${expr}` : `toFloat64OrDefault(toString(${expr}))`,
UNSAFE_RAW_SQL:
isAny || isNone ? `${expr}` : `toFloat64OrDefault(toString(${expr}))`,
};
const whereWithExtraNullCheck = `${where} AND ${unsafeExpr.UNSAFE_RAW_SQL} IS NOT NULL`;

Expand Down Expand Up @@ -307,6 +309,11 @@ const aggFnExpr = ({
};
}

if (fn === 'none') {
// Can not use WHERE in none as we can not apply if to a custom aggregation function
return chSql`${{ UNSAFE_RAW_SQL: expr ?? '' }}`;
}

if (expr != null) {
if (fn === 'count_distinct') {
return chSql`count${isWhereUsed ? 'If' : ''}(DISTINCT ${{
Expand Down
1 change: 1 addition & 0 deletions packages/common-utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const AggregateFunctionSchema = z.enum([
'quantile',
'sum',
'any',
'none',
]);
export const AggregateFunctionWithCombinatorsSchema = z
.string()
Expand Down