diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js index 009baec9e0..112af96939 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.js @@ -7,7 +7,7 @@ const { BudibaseInternalDB, getTableParams, } = require("../../db/utils") -const { BuildSchemaErrors } = require("../../constants") +const { BuildSchemaErrors, InvalidColumns } = require("../../constants") const { integrations } = require("../../integrations") const { getDatasourceAndQuery } = require("./row/utils") @@ -152,6 +152,23 @@ exports.query = async function (ctx) { } } +function getErrorTables(errors, errorType) { + return Object.entries(errors) + .filter(entry => entry[1] === errorType) + .map(([name]) => name) +} + +function updateError(error, newError, tables) { + if (!error) { + error = "" + } + if (error.length > 0) { + error += " - " + } + error += `${newError} ${tables.join(", ")}` + return error +} + const buildSchemaHelper = async datasource => { const Connector = integrations[datasource.source] @@ -176,12 +193,23 @@ const buildSchemaHelper = async datasource => { const errors = connector.schemaErrors let error = null if (errors && Object.keys(errors).length > 0) { - const noKeyTables = Object.entries(errors) - .filter(entry => entry[1] === BuildSchemaErrors.NO_KEY) - .map(([name]) => name) - error = `No primary key constraint found for the following: ${noKeyTables.join( - ", " - )}` + const noKey = getErrorTables(errors, BuildSchemaErrors.NO_KEY) + const invalidCol = getErrorTables(errors, BuildSchemaErrors.INVALID_COLUMN) + if (noKey.length) { + error = updateError( + error, + "No primary key constraint found for the following:", + noKey + ) + } + if (invalidCol.length) { + const invalidCols = Object.values(InvalidColumns).join(", ") + error = updateError( + error, + `Cannot use columns ${invalidCols} found in following:`, + invalidCol + ) + } } return { tables: connector.tables, error } } diff --git a/packages/server/src/constants/index.js b/packages/server/src/constants/index.js index 31353a2e90..c3cb9b7a58 100644 --- a/packages/server/src/constants/index.js +++ b/packages/server/src/constants/index.js @@ -163,8 +163,15 @@ exports.MetadataTypes = { AUTOMATION_TEST_HISTORY: "automationTestHistory", } +exports.InvalidColumns = { + ID: "_id", + REV: "_rev", + TABLE_ID: "tableId", +} + exports.BuildSchemaErrors = { NO_KEY: "no_key", + INVALID_COLUMN: "invalid_column", } // pass through the list from the auth/core lib diff --git a/packages/server/src/integrations/utils.ts b/packages/server/src/integrations/utils.ts index 072cfd138f..59481bcfc3 100644 --- a/packages/server/src/integrations/utils.ts +++ b/packages/server/src/integrations/utils.ts @@ -2,7 +2,7 @@ import { SqlQuery } from "../definitions/datasource" import { Datasource, Table } from "../definitions/common" import { SourceNames } from "../definitions/datasource" const { DocumentTypes, SEPARATOR } = require("../db/utils") -const { FieldTypes, BuildSchemaErrors } = require("../constants") +const { FieldTypes, BuildSchemaErrors, InvalidColumns } = require("../constants") const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}` const ROW_ID_REGEX = /^\[.*]$/g @@ -161,13 +161,18 @@ export function finaliseExternalTables( tables: { [key: string]: any }, entities: { [key: string]: any } ) { + const invalidColumns = Object.values(InvalidColumns) const finalTables: { [key: string]: any } = {} const errors: { [key: string]: string } = {} for (let [name, table] of Object.entries(tables)) { + const schemaFields = Object.keys(table.schema) // make sure every table has a key if (table.primary == null || table.primary.length === 0) { errors[name] = BuildSchemaErrors.NO_KEY continue + } else if (schemaFields.find(field => invalidColumns.includes(field))) { + errors[name] = BuildSchemaErrors.INVALID_COLUMN + continue } // make sure all previous props have been added back finalTables[name] = copyExistingPropsOver(name, table, entities)