diff --git a/packages/web/src/designer/DesignerQueryDumper.ts b/packages/web/src/designer/DesignerQueryDumper.ts
index d25bb2f22..6d367024b 100644
--- a/packages/web/src/designer/DesignerQueryDumper.ts
+++ b/packages/web/src/designer/DesignerQueryDumper.ts
@@ -8,6 +8,7 @@ import {
mergeConditions,
Source,
ResultField,
+ Expression,
} from 'dbgate-sqltree';
import { EngineDriver } from 'dbgate-types';
import { DesignerInfo, DesignerTableInfo, DesignerReferenceInfo, DesignerJoinType } from './types';
@@ -120,7 +121,7 @@ export class DesignerQueryDumper {
select.having,
_.cloneDeepWith(condition, expr => {
if (expr.exprType == 'placeholder') {
- return this.getColumnOutputExpression(column, selectIsGrouped);
+ return this.getColumnResultField(column, selectIsGrouped);
}
})
);
@@ -128,10 +129,29 @@ export class DesignerQueryDumper {
}
}
- getColumnOutputExpression(col, selectIsGrouped): ResultField {
+ getColumnExpression(col): Expression {
const source = findQuerySource(this.designer, col.designerId);
+ const { columnName, isCustomExpression, customExpression } = col;
+
+ const res: Expression = isCustomExpression
+ ? {
+ exprType: 'raw',
+ sql: customExpression,
+ }
+ : {
+ exprType: 'column',
+ columnName,
+ source,
+ };
+ return res;
+ }
+
+ getColumnResultField(col, selectIsGrouped): ResultField {
const { columnName } = col;
let { alias } = col;
+
+ const exprCore = this.getColumnExpression(col);
+
if (selectIsGrouped && !col.isGrouped) {
// use aggregate
const aggregate = col.aggregate == null || col.aggregate == '---' ? 'MAX' : col.aggregate;
@@ -142,20 +162,12 @@ export class DesignerQueryDumper {
func: aggregate == 'COUNT DISTINCT' ? 'COUNT' : aggregate,
argsPrefix: aggregate == 'COUNT DISTINCT' ? 'DISTINCT' : null,
alias,
- args: [
- {
- exprType: 'column',
- columnName,
- source,
- },
- ],
+ args: [exprCore],
};
} else {
return {
- exprType: 'column',
- columnName,
+ ...exprCore,
alias,
- source,
};
}
}
@@ -179,24 +191,21 @@ export class DesignerQueryDumper {
}
}
- const topLevelColumns = (this.designer.columns || []).filter(col =>
- topLevelTables.find(tbl => tbl.designerId == col.designerId)
+ const topLevelColumns = (this.designer.columns || []).filter(
+ col =>
+ topLevelTables.find(tbl => tbl.designerId == col.designerId) || (col.isCustomExpression && col.customExpression)
);
const selectIsGrouped = !!topLevelColumns.find(x => x.isGrouped || (x.aggregate && x.aggregate != '---'));
const outputColumns = topLevelColumns.filter(x => x.isOutput);
if (outputColumns.length == 0) {
res.selectAll = true;
} else {
- res.columns = outputColumns.map(col => this.getColumnOutputExpression(col, selectIsGrouped));
+ res.columns = outputColumns.map(col => this.getColumnResultField(col, selectIsGrouped));
}
const groupedColumns = topLevelColumns.filter(x => x.isGrouped);
if (groupedColumns.length > 0) {
- res.groupBy = groupedColumns.map(col => ({
- exprType: 'column',
- columnName: col.columnName,
- source: findQuerySource(this.designer, col.designerId),
- }));
+ res.groupBy = groupedColumns.map(col => this.getColumnExpression(col));
}
const orderColumns = _.sortBy(
@@ -205,10 +214,8 @@ export class DesignerQueryDumper {
);
if (orderColumns.length > 0) {
res.orderBy = orderColumns.map(col => ({
- exprType: 'column',
+ ...this.getColumnExpression(col),
direction: col.sortOrder < 0 ? 'DESC' : 'ASC',
- columnName: col.columnName,
- source: findQuerySource(this.designer, col.designerId),
}));
}
diff --git a/packages/web/src/designer/types.ts b/packages/web/src/designer/types.ts
index 000549de2..ee77e1e2f 100644
--- a/packages/web/src/designer/types.ts
+++ b/packages/web/src/designer/types.ts
@@ -31,6 +31,8 @@ export type DesignerColumnInfo = {
sortOrder?: number;
filter?: string;
groupFilter?: string;
+ isCustomExpression?: boolean;
+ customExpression?: string;
};
export type DesignerSettings = {
diff --git a/packages/web/src/elements/QueryDesignColumns.svelte b/packages/web/src/elements/QueryDesignColumns.svelte
index c643d2ec1..de73284df 100644
--- a/packages/web/src/elements/QueryDesignColumns.svelte
+++ b/packages/web/src/elements/QueryDesignColumns.svelte
@@ -13,8 +13,10 @@
import SelectField from '../forms/SelectField.svelte';
import TextField from '../forms/TextField.svelte';
import InlineButton from '../buttons/InlineButton.svelte';
+ import uuidv1 from 'uuid/v1';
import TableControl from './TableControl.svelte';
+ import FormStyledButton from '../buttons/FormStyledButton.svelte';
export let value;
export let onChange;
@@ -35,6 +37,13 @@
}));
};
+ const addExpressionColumn = () => {
+ onChange(current => ({
+ ...current,
+ columns: [...(current.columns || []), { isCustomExpression: true, isOutput: true, designerId: uuidv1() }],
+ }));
+ };
+
$: columns = value?.columns;
$: tables = value?.tables;
$: hasGroupedColumn = !!(columns || []).find(x => x.isGrouped);
@@ -44,7 +53,7 @@
getTableDisplayName(row, tables) },
{ fieldName: 'isOutput', header: 'Output', slot: 0 },
{ fieldName: 'alias', header: 'Alias', slot: 1 },
@@ -56,6 +65,19 @@
{ fieldName: 'actions', header: '', slot: 7 },
]}
>
+
+ {#if row.isCustomExpression}
+ {
+ changeColumn({ ...row, customExpression: e.target.value });
+ }}
+ />
+ {:else}
+ {row.columnName}
+ {/if}
+
+
removeColumn(row)}>Remove
+
\ No newline at end of file
+
diff --git a/packages/web/src/elements/TableControl.svelte b/packages/web/src/elements/TableControl.svelte
index d22a01524..0647aca69 100644
--- a/packages/web/src/elements/TableControl.svelte
+++ b/packages/web/src/elements/TableControl.svelte
@@ -92,6 +92,8 @@
{:else if col.slot == 5}
{:else if col.slot == 6}
{:else if col.slot == 7}
+ {:else if col.slot == 8}
+ {:else if col.slot == 9}
{/if}
{:else}
{row[col.fieldName] || ''}