Addresses #5850 - when importing/migrating views and building new views it checks if calculations are used and if they are then it does an empty check to decide whether or not the fields should be included in the calculation, required for real CouchDB nodes.

This commit is contained in:
mike12345567 2022-05-13 18:09:39 +01:00
parent 0da2592077
commit 459e3c5edd
2 changed files with 28 additions and 11 deletions

View File

@ -7,6 +7,7 @@ const {
} = require("../../../db/utils") } = require("../../../db/utils")
const env = require("../../../environment") const env = require("../../../environment")
const { getAppDB } = require("@budibase/backend-core/context") const { getAppDB } = require("@budibase/backend-core/context")
const viewBuilder = require("./viewBuilder")
exports.getView = async viewName => { exports.getView = async viewName => {
const db = getAppDB() const db = getAppDB()
@ -114,7 +115,8 @@ exports.deleteView = async viewName => {
exports.migrateToInMemoryView = async (db, viewName) => { exports.migrateToInMemoryView = async (db, viewName) => {
// delete the view initially // delete the view initially
const designDoc = await db.get("_design/database") const designDoc = await db.get("_design/database")
const view = designDoc.views[viewName] // run the view back through the view builder to update it
const view = viewBuilder(designDoc.views[viewName].meta)
delete designDoc.views[viewName] delete designDoc.views[viewName]
await db.put(designDoc) await db.put(designDoc)
await exports.saveView(db, null, viewName, view) await exports.saveView(db, null, viewName, view)
@ -123,7 +125,7 @@ exports.migrateToInMemoryView = async (db, viewName) => {
exports.migrateToDesignView = async (db, viewName) => { exports.migrateToDesignView = async (db, viewName) => {
let view = await db.get(generateMemoryViewID(viewName)) let view = await db.get(generateMemoryViewID(viewName))
const designDoc = await db.get("_design/database") const designDoc = await db.get("_design/database")
designDoc.views[viewName] = view.view designDoc.views[viewName] = viewBuilder(view.view.meta)
await db.put(designDoc) await db.put(designDoc)
await db.remove(view._id, view._rev) await db.remove(view._id, view._rev)
} }

View File

@ -10,6 +10,12 @@ const TOKEN_MAP = {
OR: "||", OR: "||",
} }
const CONDITIONS = {
EMPTY: "EMPTY",
NOT_EMPTY: "NOT_EMPTY",
CONTAINS: "CONTAINS",
}
const isEmptyExpression = key => { const isEmptyExpression = key => {
return `( return `(
doc["${key}"] === undefined || doc["${key}"] === undefined ||
@ -77,13 +83,13 @@ function parseFilterExpression(filters) {
expression.push(TOKEN_MAP[filter.conjunction]) expression.push(TOKEN_MAP[filter.conjunction])
} }
if (filter.condition === "CONTAINS") { if (filter.condition === CONDITIONS.CONTAINS) {
expression.push( expression.push(
`doc["${filter.key}"].${TOKEN_MAP[filter.condition]}("${filter.value}")` `doc["${filter.key}"].${TOKEN_MAP[filter.condition]}("${filter.value}")`
) )
} else if (filter.condition === "EMPTY") { } else if (filter.condition === CONDITIONS.EMPTY) {
expression.push(isEmptyExpression(filter.key)) expression.push(isEmptyExpression(filter.key))
} else if (filter.condition === "NOT_EMPTY") { } else if (filter.condition === CONDITIONS.NOT_EMPTY) {
expression.push(`!${isEmptyExpression(filter.key)}`) expression.push(`!${isEmptyExpression(filter.key)}`)
} else { } else {
const value = const value =
@ -125,12 +131,6 @@ function viewTemplate({ field, tableId, groupBy, filters = [], calculation }) {
if (filters && filters.length > 0 && filters[0].conjunction) { if (filters && filters.length > 0 && filters[0].conjunction) {
delete filters[0].conjunction delete filters[0].conjunction
} }
const parsedFilters = parseFilterExpression(filters)
const filterExpression = parsedFilters ? `&& (${parsedFilters})` : ""
const emitExpression = parseEmitExpression(field, groupBy)
const reduction = field && calculation ? { reduce: `_${calculation}` } : {}
let schema = null let schema = null
@ -139,8 +139,23 @@ function viewTemplate({ field, tableId, groupBy, filters = [], calculation }) {
...(groupBy ? GROUP_PROPERTY : FIELD_PROPERTY), ...(groupBy ? GROUP_PROPERTY : FIELD_PROPERTY),
...SCHEMA_MAP[calculation], ...SCHEMA_MAP[calculation],
} }
if (
!filters.find(
filter =>
filter.key === field && filter.condition === CONDITIONS.NOT_EMPTY
)
) {
filters.push({ key: field, condition: CONDITIONS.NOT_EMPTY })
}
} }
const parsedFilters = parseFilterExpression(filters)
const filterExpression = parsedFilters ? `&& (${parsedFilters})` : ""
const emitExpression = parseEmitExpression(field, groupBy)
const reduction = field && calculation ? { reduce: `_${calculation}` } : {}
return { return {
meta: { meta: {
field, field,