2022-03-09 22:16:22 +01:00
|
|
|
import { transform } from "../../../utilities/csvParser"
|
|
|
|
import {
|
2021-04-09 18:33:21 +02:00
|
|
|
getRowParams,
|
|
|
|
generateRowID,
|
|
|
|
InternalTables,
|
2022-01-21 17:24:24 +01:00
|
|
|
getTableParams,
|
|
|
|
BudibaseInternalDB,
|
2022-03-09 22:16:22 +01:00
|
|
|
} from "../../../db/utils"
|
|
|
|
import { isEqual } from "lodash"
|
|
|
|
import { AutoFieldSubTypes, FieldTypes } from "../../../constants"
|
|
|
|
import {
|
2022-01-24 17:32:41 +01:00
|
|
|
inputProcessing,
|
|
|
|
cleanupAttachments,
|
2022-03-09 22:16:22 +01:00
|
|
|
} from "../../../utilities/rowProcessor"
|
|
|
|
import {
|
2022-01-26 19:50:13 +01:00
|
|
|
USERS_TABLE_SCHEMA,
|
|
|
|
SwitchableTypes,
|
|
|
|
CanSwitchTypes,
|
2022-03-09 22:16:22 +01:00
|
|
|
} from "../../../constants"
|
|
|
|
import {
|
2021-10-19 18:00:54 +02:00
|
|
|
isExternalTable,
|
|
|
|
breakExternalTableId,
|
2022-01-12 18:55:28 +01:00
|
|
|
isSQL,
|
2022-03-09 22:16:22 +01:00
|
|
|
} from "../../../integrations/utils"
|
|
|
|
import { getViews, saveView } from "../view/utils"
|
|
|
|
import viewTemplate from "../view/viewBuilder"
|
2022-01-27 19:18:31 +01:00
|
|
|
const { getAppDB } = require("@budibase/backend-core/context")
|
2022-03-09 22:16:22 +01:00
|
|
|
import { cloneDeep } from "lodash/fp"
|
2022-03-18 09:01:31 +01:00
|
|
|
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
|
2021-02-22 12:39:58 +01:00
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function clearColumns(table: any, columnNames: any) {
|
2022-01-31 18:00:22 +01:00
|
|
|
const db = getAppDB()
|
2022-01-24 17:32:41 +01:00
|
|
|
const rows = await db.allDocs(
|
|
|
|
getRowParams(table._id, null, {
|
|
|
|
include_docs: true,
|
|
|
|
})
|
|
|
|
)
|
|
|
|
return db.bulkDocs(
|
2022-03-09 22:16:22 +01:00
|
|
|
rows.rows.map(({ doc }: any) => {
|
|
|
|
columnNames.forEach((colName: any) => delete doc[colName])
|
2022-01-24 17:32:41 +01:00
|
|
|
return doc
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
2021-02-22 12:39:58 +01:00
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function checkForColumnUpdates(oldTable: any, updatedTable: any) {
|
2022-01-27 19:18:31 +01:00
|
|
|
const db = getAppDB()
|
2021-02-22 13:05:59 +01:00
|
|
|
let updatedRows = []
|
2021-02-22 12:39:58 +01:00
|
|
|
const rename = updatedTable._rename
|
2022-03-09 22:16:22 +01:00
|
|
|
let deletedColumns: any = []
|
2021-02-22 12:39:58 +01:00
|
|
|
if (oldTable && oldTable.schema && updatedTable.schema) {
|
|
|
|
deletedColumns = Object.keys(oldTable.schema).filter(
|
2021-05-04 12:32:22 +02:00
|
|
|
colName => updatedTable.schema[colName] == null
|
2021-02-22 12:39:58 +01:00
|
|
|
)
|
|
|
|
}
|
|
|
|
// check for renaming of columns or deleted columns
|
|
|
|
if (rename || deletedColumns.length !== 0) {
|
2021-10-20 21:01:49 +02:00
|
|
|
// Update all rows
|
2021-02-22 12:39:58 +01:00
|
|
|
const rows = await db.allDocs(
|
|
|
|
getRowParams(updatedTable._id, null, {
|
|
|
|
include_docs: true,
|
|
|
|
})
|
|
|
|
)
|
2022-03-09 22:16:22 +01:00
|
|
|
const rawRows = rows.rows.map(({ doc }: any) => doc)
|
|
|
|
updatedRows = rawRows.map((row: any) => {
|
2022-01-24 17:32:41 +01:00
|
|
|
row = cloneDeep(row)
|
2021-02-22 12:39:58 +01:00
|
|
|
if (rename) {
|
2022-01-24 17:32:41 +01:00
|
|
|
row[rename.updated] = row[rename.old]
|
|
|
|
delete row[rename.old]
|
2021-02-22 12:39:58 +01:00
|
|
|
} else if (deletedColumns.length !== 0) {
|
2022-03-09 22:16:22 +01:00
|
|
|
deletedColumns.forEach((colName: any) => delete row[colName])
|
2021-02-22 12:39:58 +01:00
|
|
|
}
|
2022-01-24 17:32:41 +01:00
|
|
|
return row
|
2021-02-22 12:39:58 +01:00
|
|
|
})
|
2021-10-20 21:01:49 +02:00
|
|
|
|
2022-01-24 17:32:41 +01:00
|
|
|
// cleanup any attachments from object storage for deleted attachment columns
|
2022-01-31 18:00:22 +01:00
|
|
|
await cleanupAttachments(updatedTable, { oldTable, rows: rawRows })
|
2021-10-20 21:01:49 +02:00
|
|
|
// Update views
|
2022-03-09 22:16:22 +01:00
|
|
|
await checkForViewUpdates(updatedTable, rename, deletedColumns)
|
2021-02-22 12:39:58 +01:00
|
|
|
delete updatedTable._rename
|
|
|
|
}
|
|
|
|
return { rows: updatedRows, table: updatedTable }
|
|
|
|
}
|
|
|
|
|
|
|
|
// makes sure the passed in table isn't going to reset the auto ID
|
2022-03-09 22:16:22 +01:00
|
|
|
export function makeSureTableUpToDate(table: any, tableToSave: any) {
|
2021-02-22 12:39:58 +01:00
|
|
|
if (!table) {
|
|
|
|
return tableToSave
|
|
|
|
}
|
|
|
|
// sure sure rev is up to date
|
|
|
|
tableToSave._rev = table._rev
|
|
|
|
// make sure auto IDs are always updated - these are internal
|
|
|
|
// so the client may not know they have changed
|
2022-03-09 22:16:22 +01:00
|
|
|
let field: any
|
|
|
|
let column: any
|
|
|
|
for ([field, column] of Object.entries(table.schema)) {
|
2021-02-22 12:39:58 +01:00
|
|
|
if (
|
|
|
|
column.autocolumn &&
|
|
|
|
column.subtype === AutoFieldSubTypes.AUTO_ID &&
|
|
|
|
tableToSave.schema[field]
|
|
|
|
) {
|
|
|
|
tableToSave.schema[field].lastID = column.lastID
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return tableToSave
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function handleDataImport(user: any, table: any, dataImport: any) {
|
2021-11-12 19:26:57 +01:00
|
|
|
if (!dataImport || !dataImport.csvString) {
|
|
|
|
return table
|
|
|
|
}
|
2021-12-02 17:17:10 +01:00
|
|
|
|
2022-01-27 19:18:31 +01:00
|
|
|
const db = getAppDB()
|
2021-11-12 19:26:57 +01:00
|
|
|
// Populate the table with rows imported from CSV in a bulk update
|
2022-03-09 22:16:22 +01:00
|
|
|
const data = await transform({
|
2021-11-12 19:26:57 +01:00
|
|
|
...dataImport,
|
|
|
|
existingTable: table,
|
|
|
|
})
|
2021-02-22 12:39:58 +01:00
|
|
|
|
2022-03-18 09:01:31 +01:00
|
|
|
let finalData: any = []
|
2021-11-12 19:26:57 +01:00
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
|
let row = data[i]
|
|
|
|
row._id = generateRowID(table._id)
|
|
|
|
row.tableId = table._id
|
2022-03-09 22:16:22 +01:00
|
|
|
const processed: any = inputProcessing(user, table, row, {
|
2021-11-12 19:26:57 +01:00
|
|
|
noAutoRelationships: true,
|
|
|
|
})
|
|
|
|
table = processed.table
|
|
|
|
row = processed.row
|
2021-08-26 15:13:30 +02:00
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
let fieldName: any
|
|
|
|
let schema: any
|
|
|
|
for ([fieldName, schema] of Object.entries(table.schema)) {
|
2021-11-12 19:26:57 +01:00
|
|
|
// check whether the options need to be updated for inclusion as part of the data import
|
|
|
|
if (
|
|
|
|
schema.type === FieldTypes.OPTIONS &&
|
|
|
|
(!schema.constraints.inclusion ||
|
|
|
|
schema.constraints.inclusion.indexOf(row[fieldName]) === -1)
|
|
|
|
) {
|
|
|
|
schema.constraints.inclusion = [
|
|
|
|
...schema.constraints.inclusion,
|
|
|
|
row[fieldName],
|
|
|
|
]
|
2021-02-22 12:39:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-12 19:26:57 +01:00
|
|
|
finalData.push(row)
|
2021-02-22 12:39:58 +01:00
|
|
|
}
|
2021-11-12 19:26:57 +01:00
|
|
|
|
2022-03-18 09:01:31 +01:00
|
|
|
await quotas.tryUpdateUsage(
|
|
|
|
() => db.bulkDocs(finalData),
|
2022-03-08 15:21:41 +01:00
|
|
|
finalData.length,
|
2022-03-18 09:01:31 +01:00
|
|
|
StaticQuotaName.ROWS,
|
|
|
|
QuotaUsageType.STATIC
|
2022-03-08 15:21:41 +01:00
|
|
|
)
|
2021-11-12 19:26:57 +01:00
|
|
|
let response = await db.put(table)
|
|
|
|
table._rev = response._rev
|
2021-02-22 12:39:58 +01:00
|
|
|
return table
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function handleSearchIndexes(table: any) {
|
2022-01-27 19:18:31 +01:00
|
|
|
const db = getAppDB()
|
2021-02-22 12:39:58 +01:00
|
|
|
// create relevant search indexes
|
|
|
|
if (table.indexes && table.indexes.length > 0) {
|
|
|
|
const currentIndexes = await db.getIndexes()
|
|
|
|
const indexName = `search:${table._id}`
|
|
|
|
|
|
|
|
const existingIndex = currentIndexes.indexes.find(
|
2022-03-09 22:16:22 +01:00
|
|
|
(existing: any) => existing.name === indexName
|
2021-02-22 12:39:58 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
if (existingIndex) {
|
|
|
|
const currentFields = existingIndex.def.fields.map(
|
2022-03-09 22:16:22 +01:00
|
|
|
(field: any) => Object.keys(field)[0]
|
2021-02-22 12:39:58 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// if index fields have changed, delete the original index
|
|
|
|
if (!isEqual(currentFields, table.indexes)) {
|
|
|
|
await db.deleteIndex(existingIndex)
|
|
|
|
// create/recreate the index with fields
|
|
|
|
await db.createIndex({
|
|
|
|
index: {
|
|
|
|
fields: table.indexes,
|
|
|
|
name: indexName,
|
|
|
|
ddoc: "search_ddoc",
|
|
|
|
type: "json",
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// create/recreate the index with fields
|
|
|
|
await db.createIndex({
|
|
|
|
index: {
|
|
|
|
fields: table.indexes,
|
|
|
|
name: indexName,
|
|
|
|
ddoc: "search_ddoc",
|
|
|
|
type: "json",
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return table
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export function checkStaticTables(table: any) {
|
2021-02-22 12:39:58 +01:00
|
|
|
// check user schema has all required elements
|
2021-04-09 18:33:21 +02:00
|
|
|
if (table._id === InternalTables.USER_METADATA) {
|
2021-02-22 12:39:58 +01:00
|
|
|
for (let [key, schema] of Object.entries(USERS_TABLE_SCHEMA.schema)) {
|
|
|
|
// check if the schema exists on the table to be created/updated
|
|
|
|
if (table.schema[key] == null) {
|
|
|
|
table.schema[key] = schema
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return table
|
|
|
|
}
|
|
|
|
|
|
|
|
class TableSaveFunctions {
|
2022-03-09 22:16:22 +01:00
|
|
|
db: any
|
|
|
|
user: any
|
|
|
|
oldTable: any
|
|
|
|
dataImport: any
|
|
|
|
rows: any
|
|
|
|
|
|
|
|
constructor({ user, oldTable, dataImport }: any) {
|
2022-01-27 19:18:31 +01:00
|
|
|
this.db = getAppDB()
|
|
|
|
this.user = user
|
2021-02-22 12:39:58 +01:00
|
|
|
this.oldTable = oldTable
|
|
|
|
this.dataImport = dataImport
|
|
|
|
// any rows that need updated
|
|
|
|
this.rows = []
|
|
|
|
}
|
|
|
|
|
|
|
|
// before anything is done
|
2022-03-09 22:16:22 +01:00
|
|
|
async before(table: any) {
|
2021-02-22 12:39:58 +01:00
|
|
|
if (this.oldTable) {
|
2022-03-09 22:16:22 +01:00
|
|
|
table = makeSureTableUpToDate(this.oldTable, table)
|
2021-02-22 12:39:58 +01:00
|
|
|
}
|
2022-03-09 22:16:22 +01:00
|
|
|
table = checkStaticTables(table)
|
2021-02-22 12:39:58 +01:00
|
|
|
return table
|
|
|
|
}
|
|
|
|
|
|
|
|
// when confirmed valid
|
2022-03-09 22:16:22 +01:00
|
|
|
async mid(table: any) {
|
|
|
|
let response = await checkForColumnUpdates(this.oldTable, table)
|
2021-02-22 13:05:59 +01:00
|
|
|
this.rows = this.rows.concat(response.rows)
|
2021-02-22 12:39:58 +01:00
|
|
|
return table
|
|
|
|
}
|
|
|
|
|
|
|
|
// after saving
|
2022-03-09 22:16:22 +01:00
|
|
|
async after(table: any) {
|
|
|
|
table = await handleSearchIndexes(table)
|
|
|
|
table = await handleDataImport(this.user, table, this.dataImport)
|
2021-02-22 12:39:58 +01:00
|
|
|
return table
|
|
|
|
}
|
|
|
|
|
|
|
|
getUpdatedRows() {
|
|
|
|
return this.rows
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function getAllInternalTables() {
|
2022-01-31 18:00:22 +01:00
|
|
|
const db = getAppDB()
|
2022-01-21 17:24:24 +01:00
|
|
|
const internalTables = await db.allDocs(
|
|
|
|
getTableParams(null, {
|
|
|
|
include_docs: true,
|
|
|
|
})
|
|
|
|
)
|
2022-03-09 22:16:22 +01:00
|
|
|
return internalTables.rows.map((tableDoc: any) => ({
|
2022-01-21 17:24:24 +01:00
|
|
|
...tableDoc.doc,
|
|
|
|
type: "internal",
|
|
|
|
sourceId: BudibaseInternalDB._id,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function getAllExternalTables(datasourceId: any) {
|
2022-01-27 19:18:31 +01:00
|
|
|
const db = getAppDB()
|
2021-06-16 17:27:33 +02:00
|
|
|
const datasource = await db.get(datasourceId)
|
|
|
|
if (!datasource || !datasource.entities) {
|
|
|
|
throw "Datasource is not configured fully."
|
|
|
|
}
|
2021-06-23 20:05:32 +02:00
|
|
|
return datasource.entities
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function getExternalTable(datasourceId: any, tableName: any) {
|
|
|
|
const entities = await getAllExternalTables(datasourceId)
|
2021-06-23 20:05:32 +02:00
|
|
|
return entities[tableName]
|
2021-06-16 17:27:33 +02:00
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function getTable(tableId: any) {
|
2022-01-27 19:18:31 +01:00
|
|
|
const db = getAppDB()
|
2021-10-19 18:00:54 +02:00
|
|
|
if (isExternalTable(tableId)) {
|
|
|
|
let { datasourceId, tableName } = breakExternalTableId(tableId)
|
2022-01-12 18:55:28 +01:00
|
|
|
const datasource = await db.get(datasourceId)
|
2022-03-09 22:16:22 +01:00
|
|
|
const table = await getExternalTable(datasourceId, tableName)
|
2022-01-12 18:55:28 +01:00
|
|
|
return { ...table, sql: isSQL(datasource) }
|
2021-10-19 18:00:54 +02:00
|
|
|
} else {
|
|
|
|
return db.get(tableId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export async function checkForViewUpdates(
|
|
|
|
table: any,
|
|
|
|
rename: any,
|
|
|
|
deletedColumns: any
|
|
|
|
) {
|
2022-01-27 19:18:31 +01:00
|
|
|
const views = await getViews()
|
2021-10-20 21:01:49 +02:00
|
|
|
const tableViews = views.filter(view => view.meta.tableId === table._id)
|
|
|
|
|
|
|
|
// Check each table view to see if impacted by this table action
|
|
|
|
for (let view of tableViews) {
|
|
|
|
let needsUpdated = false
|
|
|
|
|
|
|
|
// First check for renames, otherwise check for deletions
|
|
|
|
if (rename) {
|
|
|
|
// Update calculation field if required
|
|
|
|
if (view.meta.field === rename.old) {
|
|
|
|
view.meta.field = rename.updated
|
|
|
|
needsUpdated = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update group by field if required
|
|
|
|
if (view.meta.groupBy === rename.old) {
|
|
|
|
view.meta.groupBy = rename.updated
|
|
|
|
needsUpdated = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update filters if required
|
2021-10-21 11:24:41 +02:00
|
|
|
if (view.meta.filters) {
|
2022-03-09 22:16:22 +01:00
|
|
|
view.meta.filters.forEach((filter: any) => {
|
2021-10-21 11:24:41 +02:00
|
|
|
if (filter.key === rename.old) {
|
|
|
|
filter.key = rename.updated
|
|
|
|
needsUpdated = true
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
} else if (deletedColumns) {
|
2022-03-09 22:16:22 +01:00
|
|
|
deletedColumns.forEach((column: any) => {
|
2021-10-20 21:01:49 +02:00
|
|
|
// Remove calculation statement if required
|
|
|
|
if (view.meta.field === column) {
|
|
|
|
delete view.meta.field
|
|
|
|
delete view.meta.calculation
|
|
|
|
delete view.meta.groupBy
|
|
|
|
needsUpdated = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove group by field if required
|
|
|
|
if (view.meta.groupBy === column) {
|
|
|
|
delete view.meta.groupBy
|
|
|
|
needsUpdated = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove filters referencing deleted field if required
|
2021-10-21 11:24:41 +02:00
|
|
|
if (view.meta.filters && view.meta.filters.length) {
|
2021-10-20 21:01:49 +02:00
|
|
|
const initialLength = view.meta.filters.length
|
2022-03-09 22:16:22 +01:00
|
|
|
view.meta.filters = view.meta.filters.filter((filter: any) => {
|
2021-10-20 21:01:49 +02:00
|
|
|
return filter.key !== column
|
|
|
|
})
|
|
|
|
if (initialLength !== view.meta.filters.length) {
|
|
|
|
needsUpdated = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update view if required
|
|
|
|
if (needsUpdated) {
|
|
|
|
const newViewTemplate = viewTemplate(view.meta)
|
2022-01-27 19:18:31 +01:00
|
|
|
await saveView(null, view.name, newViewTemplate)
|
2021-10-20 21:01:49 +02:00
|
|
|
if (!newViewTemplate.meta.schema) {
|
|
|
|
newViewTemplate.meta.schema = table.schema
|
|
|
|
}
|
|
|
|
table.views[view.name] = newViewTemplate.meta
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export function generateForeignKey(column: any, relatedTable: any) {
|
2021-10-29 19:37:29 +02:00
|
|
|
return `fk_${relatedTable.name}_${column.fieldName}`
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export function generateJunctionTableName(
|
|
|
|
column: any,
|
|
|
|
table: any,
|
|
|
|
relatedTable: any
|
|
|
|
) {
|
2021-10-29 19:37:29 +02:00
|
|
|
return `jt_${table.name}_${relatedTable.name}_${column.name}_${column.fieldName}`
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export function foreignKeyStructure(keyName: any, meta = null) {
|
|
|
|
const structure: any = {
|
2021-10-29 19:37:29 +02:00
|
|
|
type: FieldTypes.NUMBER,
|
|
|
|
constraints: {},
|
|
|
|
name: keyName,
|
|
|
|
}
|
|
|
|
if (meta) {
|
|
|
|
structure.meta = meta
|
|
|
|
}
|
|
|
|
return structure
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export function areSwitchableTypes(type1: any, type2: any) {
|
2022-01-26 19:50:13 +01:00
|
|
|
if (
|
|
|
|
SwitchableTypes.indexOf(type1) === -1 &&
|
|
|
|
SwitchableTypes.indexOf(type2) === -1
|
|
|
|
) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for (let option of CanSwitchTypes) {
|
|
|
|
const index1 = option.indexOf(type1),
|
|
|
|
index2 = option.indexOf(type2)
|
|
|
|
if (index1 !== -1 && index2 !== -1 && index1 !== index2) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
export function hasTypeChanged(table: any, oldTable: any) {
|
2021-11-10 16:01:44 +01:00
|
|
|
if (!oldTable) {
|
|
|
|
return false
|
|
|
|
}
|
2022-03-09 22:16:22 +01:00
|
|
|
let key: any
|
|
|
|
let field: any
|
|
|
|
for ([key, field] of Object.entries(oldTable.schema)) {
|
2021-11-10 16:01:44 +01:00
|
|
|
const oldType = field.type
|
|
|
|
if (!table.schema[key]) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
const newType = table.schema[key].type
|
2022-03-09 22:16:22 +01:00
|
|
|
if (oldType !== newType && !areSwitchableTypes(oldType, newType)) {
|
2021-11-10 16:01:44 +01:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-03-09 22:16:22 +01:00
|
|
|
const _TableSaveFunctions = TableSaveFunctions
|
|
|
|
export { _TableSaveFunctions as TableSaveFunctions }
|