PromucFlow_constructor/app/client/src/WidgetQueryGenerators/PostgreSQL/index.ts
Ilia d6f249b42d
chore: add blank line eslint rule (#36369)
## Description
Added ESLint rule to force blank lines between statements. 


Fixes #`Issue Number`  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!CAUTION]
> 🔴 🔴 🔴 Some tests have failed.
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/10924926728>
> Commit: 34f57714a1575ee04e94e03cbcaf95e57a96c86c
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10924926728&attempt=1&selectiontype=test&testsstatus=failed&specsstatus=fail"
target="_blank">Cypress dashboard</a>.
> Tags: @tag.All
> Spec: 
> The following are new failures, please fix them before merging the PR:
<ol>
> <li>cypress/e2e/Regression/ClientSide/Anvil/AnvilModal_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCurrencyInputWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInputWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilPhoneInputWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilTableWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilZoneSectionWidgetSnapshot_spec.ts</ol>
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master"
target="_blank">List of identified flaky tests</a>.
> <hr>Wed, 18 Sep 2024 16:33:36 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No

---------

Co-authored-by: Valera Melnikov <valera@appsmith.com>
2024-09-18 19:35:28 +03:00

259 lines
6.7 KiB
TypeScript

import { BaseQueryGenerator } from "../BaseQueryGenerator";
import { formatDialect, postgresql } from "sql-formatter";
import type {
ActionConfigurationSQL,
WidgetQueryGenerationConfig,
WidgetQueryGenerationFormConfig,
} from "../types";
import { QUERY_TYPE } from "../types";
import { removeSpecialChars } from "utils/helpers";
import { without } from "lodash";
import { DatasourceConnectionMode } from "entities/Datasource";
export default abstract class PostgreSQL extends BaseQueryGenerator {
private static buildSelect(
widgetConfig: WidgetQueryGenerationConfig,
formConfig: WidgetQueryGenerationFormConfig,
) {
const { select } = widgetConfig;
//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}}}%'`,
},
},
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") : ""}}`,
},
},
{
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;
return {
template: acc.template + " " + template,
params: { ...acc.params, ...params },
};
},
{ template: "", params: {} },
);
//formats sql string
const res = formatDialect(template, {
params,
dialect: postgresql,
});
return {
type: QUERY_TYPE.SELECT,
name: `Select_${removeSpecialChars(formConfig.tableName)}`,
payload: {
body: res,
},
dynamicBindingPathList: [
{
key: "body",
},
],
};
}
private static buildUpdate(
widgetConfig: WidgetQueryGenerationConfig,
formConfig: WidgetQueryGenerationFormConfig,
) {
const { update } = widgetConfig;
//if no table name do not build query
if (!update || !update.where || !formConfig.tableName) {
return;
}
const { value, where } = update;
const columns = without(
formConfig.columns.map((d) => d.name),
formConfig.primaryColumn,
);
return {
type: QUERY_TYPE.UPDATE,
name: `Update_${removeSpecialChars(formConfig.tableName)}`,
payload: {
body: `UPDATE ${formConfig.tableName} SET ${columns
.map((column) => `"${column}"= '{{${value}.${column}}}'`)
.join(", ")} WHERE "${formConfig.primaryColumn}"= {{${where}.${
formConfig.dataIdentifier
}}};`,
},
dynamicBindingPathList: [
{
key: "body",
},
],
};
}
private static buildInsert(
widgetConfig: WidgetQueryGenerationConfig,
formConfig: WidgetQueryGenerationFormConfig,
) {
const { create } = widgetConfig;
//if no table name do not build query
if (!create || !create.value || !formConfig.tableName) {
return;
}
const columns = without(
formConfig.columns.map((d) => d.name),
formConfig.primaryColumn,
);
return {
type: QUERY_TYPE.CREATE,
name: `Insert_${removeSpecialChars(formConfig.tableName)}`,
payload: {
body: `INSERT INTO ${formConfig.tableName} (${columns.map(
(a) => `"${a}"`,
)}) VALUES (${columns
.map((d) => `'{{${create.value}.${d}}}'`)
.toString()})`,
},
dynamicBindingPathList: [
{
key: "body",
},
],
};
}
private static buildTotal(
widgetConfig: WidgetQueryGenerationConfig,
formConfig: WidgetQueryGenerationFormConfig,
) {
const { select, totalRecord } = widgetConfig;
//if no table name do not build query
if (!totalRecord) {
return;
}
return {
type: QUERY_TYPE.TOTAL_RECORD,
name: `Total_record_${removeSpecialChars(formConfig.tableName)}`,
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,
pluginInitalValues: { actionConfiguration: ActionConfigurationSQL },
) {
const allBuildConfigs = [];
if (widgetConfig.select) {
allBuildConfigs.push(this.buildSelect(widgetConfig, formConfig));
}
if (
widgetConfig.update &&
(formConfig.primaryColumn || formConfig?.otherFields?.dataIdentifier) &&
formConfig.connectionMode === DatasourceConnectionMode.READ_WRITE
) {
allBuildConfigs.push(this.buildUpdate(widgetConfig, formConfig));
}
if (
widgetConfig.create &&
(formConfig.primaryColumn || formConfig?.otherFields?.dataIdentifier) &&
formConfig.connectionMode === DatasourceConnectionMode.READ_WRITE
) {
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`;
}
}