Merge pull request #3094 from Budibase/fix/sql-auto-update

Fixing issue with SQL tables and automation update row action
This commit is contained in:
Michael Drury 2021-10-20 13:48:53 +01:00 committed by GitHub
commit 0c678d1cce
12 changed files with 44 additions and 57 deletions

View File

@ -9,11 +9,7 @@ const {
BudibaseInternalDB, BudibaseInternalDB,
} = require("../../../db/utils") } = require("../../../db/utils")
const { FieldTypes } = require("../../../constants") const { FieldTypes } = require("../../../constants")
const { TableSaveFunctions, getExternalTable } = require("./utils") const { TableSaveFunctions, getTable } = require("./utils")
const {
isExternalTable,
breakExternalTableId,
} = require("../../../integrations/utils")
exports.fetch = async function (ctx) { exports.fetch = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
@ -48,14 +44,8 @@ exports.fetch = async function (ctx) {
} }
exports.find = async function (ctx) { exports.find = async function (ctx) {
const db = new CouchDB(ctx.appId)
const tableId = ctx.params.id const tableId = ctx.params.id
if (isExternalTable(tableId)) { ctx.body = await getTable(ctx.appId, tableId)
let { datasourceId, tableName } = breakExternalTableId(tableId)
ctx.body = await getExternalTable(ctx.appId, datasourceId, tableName)
} else {
ctx.body = await db.get(ctx.params.id)
}
} }
exports.save = async function (ctx) { exports.save = async function (ctx) {

View File

@ -9,6 +9,10 @@ const { isEqual } = require("lodash/fp")
const { AutoFieldSubTypes, FieldTypes } = require("../../../constants") const { AutoFieldSubTypes, FieldTypes } = require("../../../constants")
const { inputProcessing } = require("../../../utilities/rowProcessor") const { inputProcessing } = require("../../../utilities/rowProcessor")
const { USERS_TABLE_SCHEMA } = require("../../../constants") const { USERS_TABLE_SCHEMA } = require("../../../constants")
const {
isExternalTable,
breakExternalTableId,
} = require("../../../integrations/utils")
exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => { exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
let updatedRows = [] let updatedRows = []
@ -223,4 +227,14 @@ exports.getExternalTable = async (appId, datasourceId, tableName) => {
return entities[tableName] return entities[tableName]
} }
exports.getTable = async (appId, tableId) => {
const db = new CouchDB(appId)
if (isExternalTable(tableId)) {
let { datasourceId, tableName } = breakExternalTableId(tableId)
return exports.getExternalTable(appId, datasourceId, tableName)
} else {
return db.get(tableId)
}
}
exports.TableSaveFunctions = TableSaveFunctions exports.TableSaveFunctions = TableSaveFunctions

View File

@ -1,9 +1,4 @@
const CouchDB = require("../db") const { getTable } = require("../api/controllers/table/utils")
const {
isExternalTable,
breakExternalTableId,
} = require("../integrations/utils")
const { getExternalTable } = require("../api/controllers/table/utils")
/** /**
* When values are input to the system generally they will be of type string as this is required for template strings. * When values are input to the system generally they will be of type string as this is required for template strings.
@ -21,7 +16,7 @@ const { getExternalTable } = require("../api/controllers/table/utils")
* @returns {object} The inputs object which has had all the various types supported by this function converted to their * @returns {object} The inputs object which has had all the various types supported by this function converted to their
* primitive types. * primitive types.
*/ */
module.exports.cleanInputValues = (inputs, schema) => { exports.cleanInputValues = (inputs, schema) => {
if (schema == null) { if (schema == null) {
return inputs return inputs
} }
@ -63,30 +58,11 @@ module.exports.cleanInputValues = (inputs, schema) => {
* @param {object} row The input row structure which requires clean-up after having been through template statements. * @param {object} row The input row structure which requires clean-up after having been through template statements.
* @returns {Promise<Object>} The cleaned up rows object, will should now have all the required primitive types. * @returns {Promise<Object>} The cleaned up rows object, will should now have all the required primitive types.
*/ */
module.exports.cleanUpRow = async (appId, tableId, row) => { exports.cleanUpRow = async (appId, tableId, row) => {
const db = new CouchDB(appId) let table = await getTable(appId, tableId)
let table return exports.cleanInputValues(row, { properties: table.schema })
if (isExternalTable(tableId)) {
const { datasourceId, tableName } = breakExternalTableId(tableId)
table = await getExternalTable(appId, datasourceId, tableName)
} else {
table = await db.get(tableId)
} }
return module.exports.cleanInputValues(row, { properties: table.schema }) exports.getError = err => {
} return typeof err !== "string" ? err.toString() : err
/**
* A utility function for the cleanUpRow, which can be used if only the row ID is known (not the table ID) to clean
* up a row after template statements have been replaced. This is specifically useful for the update row action.
*
* @param {string} appId The instance which the Table/Table is contained under.
* @param {string} rowId The ID of the row from which the tableId will be extracted, to get the Table/Table schema.
* @param {object} row The input row structure which requires clean-up after having been through template statements.
* @returns {Promise<Object>} The cleaned up rows object, which will now have all the required primitive types.
*/
module.exports.cleanUpRowById = async (appId, rowId, row) => {
const db = new CouchDB(appId)
const foundRow = await db.get(rowId)
return module.exports.cleanUpRow(appId, foundRow.tableId, row)
} }

View File

@ -1,5 +1,6 @@
const { execSync } = require("child_process") const { execSync } = require("child_process")
const { processStringSync } = require("@budibase/string-templates") const { processStringSync } = require("@budibase/string-templates")
const automationUtils = require("../automationUtils")
exports.definition = { exports.definition = {
name: "Bash Scripting", name: "Bash Scripting",
@ -63,7 +64,7 @@ exports.run = async function ({ inputs, context }) {
} catch (err) { } catch (err) {
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }

View File

@ -97,7 +97,7 @@ exports.run = async function ({ inputs, appId, emitter }) {
} catch (err) { } catch (err) {
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }

View File

@ -2,6 +2,7 @@ const rowController = require("../../api/controllers/row")
const env = require("../../environment") const env = require("../../environment")
const usage = require("../../utilities/usageQuota") const usage = require("../../utilities/usageQuota")
const { buildCtx } = require("./utils") const { buildCtx } = require("./utils")
const automationUtils = require("../automationUtils")
exports.definition = { exports.definition = {
description: "Delete a row from your database", description: "Delete a row from your database",
@ -85,7 +86,7 @@ exports.run = async function ({ inputs, appId, emitter }) {
} catch (err) { } catch (err) {
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }

View File

@ -1,5 +1,6 @@
const queryController = require("../../api/controllers/query") const queryController = require("../../api/controllers/query")
const { buildCtx } = require("./utils") const { buildCtx } = require("./utils")
const automationUtils = require("../automationUtils")
exports.definition = { exports.definition = {
name: "External Data Connector", name: "External Data Connector",
@ -74,7 +75,7 @@ exports.run = async function ({ inputs, appId, emitter }) {
} catch (err) { } catch (err) {
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }

View File

@ -1,5 +1,6 @@
const scriptController = require("../../api/controllers/script") const scriptController = require("../../api/controllers/script")
const { buildCtx } = require("./utils") const { buildCtx } = require("./utils")
const automationUtils = require("../automationUtils")
exports.definition = { exports.definition = {
name: "JS Scripting", name: "JS Scripting",
@ -63,7 +64,7 @@ exports.run = async function ({ inputs, appId, context, emitter }) {
} catch (err) { } catch (err) {
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }

View File

@ -1,5 +1,6 @@
const fetch = require("node-fetch") const fetch = require("node-fetch")
const { getFetchResponse } = require("./utils") const { getFetchResponse } = require("./utils")
const automationUtils = require("../automationUtils")
const RequestType = { const RequestType = {
POST: "POST", POST: "POST",
@ -127,7 +128,7 @@ exports.run = async function ({ inputs }) {
/* istanbul ignore next */ /* istanbul ignore next */
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }

View File

@ -2,6 +2,7 @@ const rowController = require("../../api/controllers/row")
const tableController = require("../../api/controllers/table") const tableController = require("../../api/controllers/table")
const { FieldTypes } = require("../../constants") const { FieldTypes } = require("../../constants")
const { buildCtx } = require("./utils") const { buildCtx } = require("./utils")
const automationUtils = require("../automationUtils")
const SortOrders = { const SortOrders = {
ASCENDING: "ascending", ASCENDING: "ascending",
@ -110,7 +111,7 @@ exports.run = async function ({ inputs, appId }) {
} catch (err) { } catch (err) {
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }

View File

@ -1,4 +1,5 @@
const { sendSmtpEmail } = require("../../utilities/workerRequests") const { sendSmtpEmail } = require("../../utilities/workerRequests")
const automationUtils = require("../automationUtils")
exports.definition = { exports.definition = {
description: "Send an email using SMTP", description: "Send an email using SMTP",
@ -61,7 +62,7 @@ exports.run = async function ({ inputs }) {
} catch (err) { } catch (err) {
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }

View File

@ -64,6 +64,7 @@ exports.run = async function ({ inputs, appId, emitter }) {
}, },
} }
} }
const tableId = inputs.row.tableId
// clear any falsy properties so that they aren't updated // clear any falsy properties so that they aren't updated
for (let propKey of Object.keys(inputs.row)) { for (let propKey of Object.keys(inputs.row)) {
@ -80,15 +81,14 @@ exports.run = async function ({ inputs, appId, emitter }) {
}, },
params: { params: {
rowId: inputs.rowId, rowId: inputs.rowId,
tableId: tableId,
}, },
}) })
try { try {
inputs.row = await automationUtils.cleanUpRowById( if (tableId) {
appId, inputs.row = await automationUtils.cleanUpRow(appId, tableId, inputs.row)
inputs.rowId, }
inputs.row
)
await rowController.patch(ctx) await rowController.patch(ctx)
return { return {
row: ctx.body, row: ctx.body,
@ -100,7 +100,7 @@ exports.run = async function ({ inputs, appId, emitter }) {
} catch (err) { } catch (err) {
return { return {
success: false, success: false,
response: err, response: automationUtils.getError(err),
} }
} }
} }