2023-06-01 17:26:05 +00:00
|
|
|
import { BaseQueryGenerator } from "../BaseQueryGenerator";
|
2023-07-16 18:49:41 +00:00
|
|
|
import { formatDialect, postgresql } from "sql-formatter";
|
2023-06-01 17:26:05 +00:00
|
|
|
import type {
|
2023-10-03 08:10:51 +00:00
|
|
|
ActionConfigurationSQL,
|
2023-06-01 17:26:05 +00:00
|
|
|
WidgetQueryGenerationConfig,
|
|
|
|
|
WidgetQueryGenerationFormConfig,
|
|
|
|
|
} from "../types";
|
2023-10-03 08:10:51 +00:00
|
|
|
import { QUERY_TYPE } from "../types";
|
2023-06-29 13:53:25 +00:00
|
|
|
import { removeSpecialChars } from "utils/helpers";
|
2023-07-20 06:22:20 +00:00
|
|
|
import { without } from "lodash";
|
|
|
|
|
import { DatasourceConnectionMode } from "entities/Datasource";
|
2023-10-03 08:10:51 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
export default abstract class PostgreSQL extends BaseQueryGenerator {
|
|
|
|
|
private static buildSelect(
|
|
|
|
|
widgetConfig: WidgetQueryGenerationConfig,
|
|
|
|
|
formConfig: WidgetQueryGenerationFormConfig,
|
|
|
|
|
) {
|
|
|
|
|
const { select } = widgetConfig;
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
//if no table name do not build query
|
|
|
|
|
if (!select || !formConfig.tableName) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { limit, offset, orderBy, sortOrder, where } = select;
|
|
|
|
|
|
|
|
|
|
const querySegments = [
|
|
|
|
|
{
|
|
|
|
|
isValuePresent: formConfig.tableName,
|
|
|
|
|
template: "SELECT * FROM $1",
|
|
|
|
|
params: {
|
|
|
|
|
1: formConfig.tableName,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
isValuePresent: formConfig.searchableColumn && where,
|
|
|
|
|
template: "WHERE $2 ilike $3",
|
|
|
|
|
params: {
|
|
|
|
|
2: `"${formConfig.searchableColumn}"`,
|
|
|
|
|
3: `'%{{${where}}}%'`,
|
|
|
|
|
},
|
|
|
|
|
},
|
2023-06-08 11:28:48 +00:00
|
|
|
formConfig.primaryColumn
|
|
|
|
|
? {
|
|
|
|
|
isValuePresent: orderBy,
|
|
|
|
|
template: `ORDER BY $4 $5`,
|
|
|
|
|
params: {
|
|
|
|
|
4: `"{{${orderBy} || '${formConfig.primaryColumn}'}}"`,
|
|
|
|
|
5: `{{${sortOrder} ? "" : "DESC"}}`,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
: {
|
|
|
|
|
isValuePresent: orderBy,
|
|
|
|
|
template: "$4",
|
|
|
|
|
params: {
|
|
|
|
|
4: `{{${orderBy} ? "ORDER BY " + ${orderBy} + " " + (${sortOrder} ? "" : "DESC") : ""}}`,
|
|
|
|
|
},
|
|
|
|
|
},
|
2023-06-01 17:26:05 +00:00
|
|
|
{
|
|
|
|
|
isValuePresent: limit,
|
|
|
|
|
template: "LIMIT $6",
|
|
|
|
|
params: {
|
|
|
|
|
6: `{{${limit}}}`,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
isValuePresent: offset,
|
|
|
|
|
template: "OFFSET $7",
|
|
|
|
|
params: {
|
|
|
|
|
7: `{{${offset}}}`,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const { params, template } = querySegments
|
|
|
|
|
//we need to filter out query segments which are not defined
|
|
|
|
|
.filter(({ isValuePresent }) => !!isValuePresent)
|
|
|
|
|
.reduce(
|
|
|
|
|
(acc, curr) => {
|
|
|
|
|
const { params, template } = curr;
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
return {
|
|
|
|
|
template: acc.template + " " + template,
|
|
|
|
|
params: { ...acc.params, ...params },
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
{ template: "", params: {} },
|
|
|
|
|
);
|
|
|
|
|
//formats sql string
|
2023-07-16 18:49:41 +00:00
|
|
|
const res = formatDialect(template, {
|
2023-06-01 17:26:05 +00:00
|
|
|
params,
|
2023-07-16 18:49:41 +00:00
|
|
|
dialect: postgresql,
|
2023-06-01 17:26:05 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
type: QUERY_TYPE.SELECT,
|
2023-06-29 13:53:25 +00:00
|
|
|
name: `Select_${removeSpecialChars(formConfig.tableName)}`,
|
2023-06-01 17:26:05 +00:00
|
|
|
payload: {
|
|
|
|
|
body: res,
|
|
|
|
|
},
|
|
|
|
|
dynamicBindingPathList: [
|
|
|
|
|
{
|
|
|
|
|
key: "body",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static buildUpdate(
|
|
|
|
|
widgetConfig: WidgetQueryGenerationConfig,
|
|
|
|
|
formConfig: WidgetQueryGenerationFormConfig,
|
|
|
|
|
) {
|
|
|
|
|
const { update } = widgetConfig;
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
//if no table name do not build query
|
|
|
|
|
if (!update || !update.where || !formConfig.tableName) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { value, where } = update;
|
|
|
|
|
|
2023-10-03 08:10:51 +00:00
|
|
|
const columns = without(
|
|
|
|
|
formConfig.columns.map((d) => d.name),
|
|
|
|
|
formConfig.primaryColumn,
|
|
|
|
|
);
|
2023-07-20 06:22:20 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
return {
|
|
|
|
|
type: QUERY_TYPE.UPDATE,
|
2023-06-29 13:53:25 +00:00
|
|
|
name: `Update_${removeSpecialChars(formConfig.tableName)}`,
|
2023-06-01 17:26:05 +00:00
|
|
|
payload: {
|
2023-07-20 06:22:20 +00:00
|
|
|
body: `UPDATE ${formConfig.tableName} SET ${columns
|
2023-06-01 17:26:05 +00:00
|
|
|
.map((column) => `"${column}"= '{{${value}.${column}}}'`)
|
|
|
|
|
.join(", ")} WHERE "${formConfig.primaryColumn}"= {{${where}.${
|
2023-10-03 08:10:51 +00:00
|
|
|
formConfig.dataIdentifier
|
2023-06-01 17:26:05 +00:00
|
|
|
}}};`,
|
|
|
|
|
},
|
|
|
|
|
dynamicBindingPathList: [
|
|
|
|
|
{
|
|
|
|
|
key: "body",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static buildInsert(
|
|
|
|
|
widgetConfig: WidgetQueryGenerationConfig,
|
|
|
|
|
formConfig: WidgetQueryGenerationFormConfig,
|
|
|
|
|
) {
|
|
|
|
|
const { create } = widgetConfig;
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
//if no table name do not build query
|
|
|
|
|
if (!create || !create.value || !formConfig.tableName) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-03 08:10:51 +00:00
|
|
|
const columns = without(
|
|
|
|
|
formConfig.columns.map((d) => d.name),
|
|
|
|
|
formConfig.primaryColumn,
|
|
|
|
|
);
|
2023-07-20 06:22:20 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
return {
|
|
|
|
|
type: QUERY_TYPE.CREATE,
|
2023-06-29 13:53:25 +00:00
|
|
|
name: `Insert_${removeSpecialChars(formConfig.tableName)}`,
|
2023-06-01 17:26:05 +00:00
|
|
|
payload: {
|
2023-07-20 06:22:20 +00:00
|
|
|
body: `INSERT INTO ${formConfig.tableName} (${columns.map(
|
2023-06-01 17:26:05 +00:00
|
|
|
(a) => `"${a}"`,
|
2023-07-20 06:22:20 +00:00
|
|
|
)}) VALUES (${columns
|
2023-06-01 17:26:05 +00:00
|
|
|
.map((d) => `'{{${create.value}.${d}}}'`)
|
|
|
|
|
.toString()})`,
|
|
|
|
|
},
|
|
|
|
|
dynamicBindingPathList: [
|
|
|
|
|
{
|
|
|
|
|
key: "body",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static buildTotal(
|
|
|
|
|
widgetConfig: WidgetQueryGenerationConfig,
|
|
|
|
|
formConfig: WidgetQueryGenerationFormConfig,
|
|
|
|
|
) {
|
|
|
|
|
const { select, totalRecord } = widgetConfig;
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
//if no table name do not build query
|
|
|
|
|
if (!totalRecord) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
type: QUERY_TYPE.TOTAL_RECORD,
|
2023-06-29 13:53:25 +00:00
|
|
|
name: `Total_record_${removeSpecialChars(formConfig.tableName)}`,
|
2023-06-01 17:26:05 +00:00
|
|
|
payload: {
|
|
|
|
|
body: `SELECT COUNT(*) from ${formConfig.tableName}${
|
|
|
|
|
formConfig.searchableColumn
|
|
|
|
|
? ` where ${formConfig.searchableColumn} ilike '%{{${select?.where}}}%'`
|
|
|
|
|
: ""
|
|
|
|
|
};`,
|
|
|
|
|
},
|
|
|
|
|
dynamicBindingPathList: [
|
|
|
|
|
{
|
|
|
|
|
key: "body",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static build(
|
|
|
|
|
widgetConfig: WidgetQueryGenerationConfig,
|
|
|
|
|
formConfig: WidgetQueryGenerationFormConfig,
|
2023-07-06 08:20:58 +00:00
|
|
|
pluginInitalValues: { actionConfiguration: ActionConfigurationSQL },
|
2023-06-01 17:26:05 +00:00
|
|
|
) {
|
|
|
|
|
const allBuildConfigs = [];
|
2024-09-18 16:35:28 +00:00
|
|
|
|
2023-06-01 17:26:05 +00:00
|
|
|
if (widgetConfig.select) {
|
|
|
|
|
allBuildConfigs.push(this.buildSelect(widgetConfig, formConfig));
|
|
|
|
|
}
|
2023-06-08 11:28:48 +00:00
|
|
|
|
2023-07-20 06:22:20 +00:00
|
|
|
if (
|
|
|
|
|
widgetConfig.update &&
|
2023-10-03 08:10:51 +00:00
|
|
|
(formConfig.primaryColumn || formConfig?.otherFields?.dataIdentifier) &&
|
2023-07-20 06:22:20 +00:00
|
|
|
formConfig.connectionMode === DatasourceConnectionMode.READ_WRITE
|
|
|
|
|
) {
|
2023-06-01 17:26:05 +00:00
|
|
|
allBuildConfigs.push(this.buildUpdate(widgetConfig, formConfig));
|
|
|
|
|
}
|
2023-06-08 11:28:48 +00:00
|
|
|
|
2023-07-20 06:22:20 +00:00
|
|
|
if (
|
|
|
|
|
widgetConfig.create &&
|
2023-10-03 08:10:51 +00:00
|
|
|
(formConfig.primaryColumn || formConfig?.otherFields?.dataIdentifier) &&
|
2023-07-20 06:22:20 +00:00
|
|
|
formConfig.connectionMode === DatasourceConnectionMode.READ_WRITE
|
|
|
|
|
) {
|
2023-06-01 17:26:05 +00:00
|
|
|
allBuildConfigs.push(this.buildInsert(widgetConfig, formConfig));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (widgetConfig.totalRecord) {
|
|
|
|
|
allBuildConfigs.push(this.buildTotal(widgetConfig, formConfig));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return allBuildConfigs
|
|
|
|
|
.filter((val) => !!val)
|
|
|
|
|
.map((val) => ({
|
|
|
|
|
...val,
|
|
|
|
|
payload: {
|
|
|
|
|
...(val?.payload || {}),
|
|
|
|
|
...(pluginInitalValues?.actionConfiguration || {}),
|
|
|
|
|
pluginSpecifiedTemplates: [
|
|
|
|
|
{
|
|
|
|
|
value: false,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static getTotalRecordExpression(binding: string) {
|
|
|
|
|
return `${binding}[0].count`;
|
|
|
|
|
}
|
|
|
|
|
}
|