Improve and fix test

This commit is contained in:
Adria Navarro 2024-04-19 12:38:57 +02:00
parent 1732e14353
commit 1685568089
2 changed files with 197 additions and 123 deletions

View File

@ -5,10 +5,11 @@ import { context, events } from "@budibase/backend-core"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import tk from "timekeeper" import tk from "timekeeper"
import { generator, mocks } from "@budibase/backend-core/tests" import { mocks } from "@budibase/backend-core/tests"
import { import {
Datasource, Datasource,
FieldSchema, FieldSchema,
FieldSubtype,
FieldType, FieldType,
QueryPreview, QueryPreview,
RelationshipType, RelationshipType,
@ -250,7 +251,7 @@ describe("/datasources", () => {
const simpleTable = await config.api.table.save( const simpleTable = await config.api.table.save(
tableForDatasource(datasource, { tableForDatasource(datasource, {
name: generator.guid(), name: "simple",
schema: { schema: {
name: { name: {
name: "name", name: "name",
@ -259,20 +260,36 @@ describe("/datasources", () => {
}, },
}) })
) )
const fullSchema: { [type in FieldType]: FieldSchema & { type: type } } =
{ type SupportedTypes =
| FieldType.STRING
| FieldType.BARCODEQR
| FieldType.LONGFORM
| FieldType.OPTIONS
| FieldType.DATETIME
| FieldType.NUMBER
| FieldType.BOOLEAN
| FieldType.FORMULA
| FieldType.BIGINT
| FieldType.BB_REFERENCE
| FieldType.LINK
| FieldType.ARRAY
const fullSchema: {
[type in SupportedTypes]: FieldSchema & { type: type }
} = {
[FieldType.STRING]: { [FieldType.STRING]: {
name: "string", name: "string",
type: FieldType.STRING, type: FieldType.STRING,
}, },
// [FieldType.LONGFORM]: { [FieldType.LONGFORM]: {
// name: "longform", name: "longform",
// type: FieldType.LONGFORM, type: FieldType.LONGFORM,
// }, },
// [FieldType.OPTIONS]: { [FieldType.OPTIONS]: {
// name: "options", name: "options",
// type: FieldType.OPTIONS, type: FieldType.OPTIONS,
// }, },
[FieldType.NUMBER]: { [FieldType.NUMBER]: {
name: "number", name: "number",
type: FieldType.NUMBER, type: FieldType.NUMBER,
@ -281,64 +298,44 @@ describe("/datasources", () => {
name: "boolean", name: "boolean",
type: FieldType.BOOLEAN, type: FieldType.BOOLEAN,
}, },
// [FieldType.ARRAY]: { [FieldType.ARRAY]: {
// name: "array", name: "array",
// type: FieldType.ARRAY, type: FieldType.ARRAY,
// }, },
[FieldType.DATETIME]: { [FieldType.DATETIME]: {
name: "datetime", name: "datetime",
type: FieldType.DATETIME, type: FieldType.DATETIME,
}, },
// [FieldType.ATTACHMENTS]: { [FieldType.LINK]: {
// name: "attachments", name: "link",
// type: FieldType.ATTACHMENTS, type: FieldType.LINK,
// }, tableId: simpleTable._id!,
// [FieldType.ATTACHMENT_SINGLE]: { relationshipType: RelationshipType.ONE_TO_MANY,
// name: "attachment_single", fieldName: "link",
// type: FieldType.ATTACHMENT_SINGLE, },
// }, [FieldType.FORMULA]: {
// [FieldType.LINK]: { name: "formula",
// name: "link", type: FieldType.FORMULA,
// type: FieldType.LINK, formula: "any formula",
// tableId: simpleTable._id!, },
// relationshipType: RelationshipType.ONE_TO_MANY,
// fieldName: "link",
// foreignKey: "fk",
// },
// [FieldType.FORMULA]: {
// name: "formula",
// type: FieldType.FORMULA,
// formula: "any formula",
// },
// [FieldType.AUTO]: {
// name: "auto",
// type: FieldType.AUTO,
// },
// [FieldType.JSON]: {
// name: "json",
// type: FieldType.JSON,
// },
// [FieldType.INTERNAL]: {
// name: "internal",
// type: FieldType.INTERNAL,
// },
[FieldType.BARCODEQR]: { [FieldType.BARCODEQR]: {
name: "barcodeqr", name: "barcodeqr",
type: FieldType.BARCODEQR, type: FieldType.BARCODEQR,
}, },
// [FieldType.BIGINT]: { [FieldType.BIGINT]: {
// name: "bigint", name: "bigint",
// type: FieldType.BIGINT, type: FieldType.BIGINT,
// }, },
// [FieldType.BB_REFERENCE]: { [FieldType.BB_REFERENCE]: {
// name: "bb_reference", name: "bb_reference",
// type: FieldType.BB_REFERENCE, type: FieldType.BB_REFERENCE,
// }, subtype: FieldSubtype.USERS,
},
} }
const fullTable = await config.api.table.save( await config.api.table.save(
tableForDatasource(datasource, { tableForDatasource(datasource, {
name: generator.guid(), name: "full",
schema: fullSchema, schema: fullSchema,
}) })
) )
@ -362,9 +359,6 @@ describe("/datasources", () => {
(acc, [fieldName, field]) => { (acc, [fieldName, field]) => {
acc[fieldName] = expect.objectContaining({ acc[fieldName] = expect.objectContaining({
...field, ...field,
externalType: expect.not.stringMatching(
new RegExp(`^${field.externalType || ""}$`)
),
}) })
return acc return acc
}, },

View File

@ -15,7 +15,28 @@ const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}`
const ROW_ID_REGEX = /^\[.*]$/g const ROW_ID_REGEX = /^\[.*]$/g
const ENCODED_SPACE = encodeURIComponent(" ") const ENCODED_SPACE = encodeURIComponent(" ")
const SQL_NUMBER_TYPE_MAP = { type PrimitiveTypes =
| FieldType.STRING
| FieldType.NUMBER
| FieldType.BOOLEAN
| FieldType.DATETIME
| FieldType.JSON
| FieldType.BIGINT
| FieldType.OPTIONS
function isPrimitiveType(type: FieldType): type is PrimitiveTypes {
return [
FieldType.STRING,
FieldType.NUMBER,
FieldType.BOOLEAN,
FieldType.DATETIME,
FieldType.JSON,
FieldType.BIGINT,
FieldType.OPTIONS,
].includes(type)
}
const SQL_NUMBER_TYPE_MAP: Record<string, PrimitiveTypes> = {
integer: FieldType.NUMBER, integer: FieldType.NUMBER,
int: FieldType.NUMBER, int: FieldType.NUMBER,
decimal: FieldType.NUMBER, decimal: FieldType.NUMBER,
@ -35,7 +56,7 @@ const SQL_NUMBER_TYPE_MAP = {
smallmoney: FieldType.NUMBER, smallmoney: FieldType.NUMBER,
} }
const SQL_DATE_TYPE_MAP = { const SQL_DATE_TYPE_MAP: Record<string, PrimitiveTypes> = {
timestamp: FieldType.DATETIME, timestamp: FieldType.DATETIME,
time: FieldType.DATETIME, time: FieldType.DATETIME,
datetime: FieldType.DATETIME, datetime: FieldType.DATETIME,
@ -46,7 +67,7 @@ const SQL_DATE_TYPE_MAP = {
const SQL_DATE_ONLY_TYPES = ["date"] const SQL_DATE_ONLY_TYPES = ["date"]
const SQL_TIME_ONLY_TYPES = ["time"] const SQL_TIME_ONLY_TYPES = ["time"]
const SQL_STRING_TYPE_MAP = { const SQL_STRING_TYPE_MAP: Record<string, PrimitiveTypes> = {
varchar: FieldType.STRING, varchar: FieldType.STRING,
char: FieldType.STRING, char: FieldType.STRING,
nchar: FieldType.STRING, nchar: FieldType.STRING,
@ -58,22 +79,22 @@ const SQL_STRING_TYPE_MAP = {
text: FieldType.STRING, text: FieldType.STRING,
} }
const SQL_BOOLEAN_TYPE_MAP = { const SQL_BOOLEAN_TYPE_MAP: Record<string, PrimitiveTypes> = {
boolean: FieldType.BOOLEAN, boolean: FieldType.BOOLEAN,
bit: FieldType.BOOLEAN, bit: FieldType.BOOLEAN,
tinyint: FieldType.BOOLEAN, tinyint: FieldType.BOOLEAN,
} }
const SQL_OPTIONS_TYPE_MAP = { const SQL_OPTIONS_TYPE_MAP: Record<string, PrimitiveTypes> = {
"user-defined": FieldType.OPTIONS, "user-defined": FieldType.OPTIONS,
} }
const SQL_MISC_TYPE_MAP = { const SQL_MISC_TYPE_MAP: Record<string, PrimitiveTypes> = {
json: FieldType.JSON, json: FieldType.JSON,
bigint: FieldType.BIGINT, bigint: FieldType.BIGINT,
} }
const SQL_TYPE_MAP = { const SQL_TYPE_MAP: Record<string, PrimitiveTypes> = {
...SQL_NUMBER_TYPE_MAP, ...SQL_NUMBER_TYPE_MAP,
...SQL_DATE_TYPE_MAP, ...SQL_DATE_TYPE_MAP,
...SQL_STRING_TYPE_MAP, ...SQL_STRING_TYPE_MAP,
@ -317,6 +338,80 @@ function shouldCopySpecialColumn(
return fetchedIsNumber && column.type === FieldType.BOOLEAN return fetchedIsNumber && column.type === FieldType.BOOLEAN
} }
enum CopyAction {
ALWAYS_KEEP = "alwaysKeep",
COPY_IF_TYPE = "copyIfType",
}
SQL_TYPE_MAP
const SqlCopyTypeByFieldMapping: Record<
FieldType,
| { action: CopyAction.ALWAYS_KEEP }
| { action: CopyAction.COPY_IF_TYPE; types: PrimitiveTypes[] }
> = {
[FieldType.LINK]: { action: CopyAction.ALWAYS_KEEP },
[FieldType.FORMULA]: { action: CopyAction.ALWAYS_KEEP },
[FieldType.STRING]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.STRING],
},
[FieldType.OPTIONS]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.STRING],
},
[FieldType.LONGFORM]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.STRING],
},
[FieldType.NUMBER]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.BOOLEAN, FieldType.NUMBER],
},
[FieldType.BOOLEAN]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.BOOLEAN, FieldType.NUMBER],
},
[FieldType.ARRAY]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.JSON, FieldType.STRING],
},
[FieldType.DATETIME]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.DATETIME, FieldType.STRING],
},
[FieldType.ATTACHMENTS]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.JSON, FieldType.STRING],
},
[FieldType.ATTACHMENT_SINGLE]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.JSON, FieldType.STRING],
},
[FieldType.AUTO]: {
action: CopyAction.ALWAYS_KEEP,
},
[FieldType.JSON]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.JSON, FieldType.STRING],
},
[FieldType.INTERNAL]: {
action: CopyAction.ALWAYS_KEEP,
},
[FieldType.BARCODEQR]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.STRING],
},
[FieldType.BIGINT]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.BIGINT, FieldType.NUMBER],
},
[FieldType.BB_REFERENCE]: {
action: CopyAction.COPY_IF_TYPE,
types: [FieldType.JSON, FieldType.STRING],
},
}
/** /**
* Looks for columns which need to be copied over into the new table definitions, like relationships, * Looks for columns which need to be copied over into the new table definitions, like relationships,
* options types and views. * options types and views.
@ -338,6 +433,9 @@ function copyExistingPropsOver(
if (entities[tableName]?.created) { if (entities[tableName]?.created) {
table.created = entities[tableName]?.created table.created = entities[tableName]?.created
} }
if (entities[tableName]?.constrained) {
table.constrained = entities[tableName]?.constrained
}
table.views = entities[tableName].views table.views = entities[tableName].views
@ -351,36 +449,17 @@ function copyExistingPropsOver(
const existingColumnType = column?.type const existingColumnType = column?.type
const updatedColumnType = table.schema[key]?.type const updatedColumnType = table.schema[key]?.type
// If the db column type changed to a non-compatible one, we want to re-fetch it const map = SqlCopyTypeByFieldMapping[existingColumnType]
if (
updatedColumnType && let keepExistingSchema = map.action === CopyAction.ALWAYS_KEEP
updatedColumnType !== existingColumnType && if (map.action === CopyAction.COPY_IF_TYPE) {
!SWITCHABLE_TYPES[updatedColumnType]?.includes(existingColumnType) keepExistingSchema =
) { isPrimitiveType(updatedColumnType) &&
continue table.schema[key] &&
} map.types?.includes(updatedColumnType)
if (
column.type === FieldType.LINK &&
!shouldCopyRelationship(column, tableIds)
) {
continue
}
const specialTypes = [
FieldType.OPTIONS,
FieldType.LONGFORM,
FieldType.ARRAY,
FieldType.FORMULA,
FieldType.BB_REFERENCE,
]
if (
specialTypes.includes(column.type) &&
!shouldCopySpecialColumn(column, table.schema[key])
) {
continue
} }
if (keepExistingSchema) {
table.schema[key] = { table.schema[key] = {
...existingTableSchema[key], ...existingTableSchema[key],
externalType: externalType:
@ -389,6 +468,7 @@ function copyExistingPropsOver(
} }
} }
} }
}
return table return table
} }