Skip to content

Commit

Permalink
Merge pull request #14695 from Budibase/fix/related-rows-dont-exist
Browse files Browse the repository at this point in the history
Handle internal relationships referencing rows that don't exist
  • Loading branch information
samwho authored Oct 9, 2024
2 parents abd7b3b + 64492dc commit 9812e88
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 6 deletions.
12 changes: 8 additions & 4 deletions packages/backend-core/src/db/couch/DatabaseImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,21 @@ export class DatabaseImpl implements Database {

async getMultiple<T extends Document>(
ids: string[],
opts?: { allowMissing?: boolean }
opts?: { allowMissing?: boolean; excludeDocs?: boolean }
): Promise<T[]> {
// get unique
ids = [...new Set(ids)]
const includeDocs = !opts?.excludeDocs
const response = await this.allDocs<T>({
keys: ids,
include_docs: true,
include_docs: includeDocs,
})
const rowUnavailable = (row: RowResponse<T>) => {
// row is deleted - key lookup can return this
if (row.doc == null || ("deleted" in row.value && row.value.deleted)) {
if (
(includeDocs && row.doc == null) ||
(row.value && "deleted" in row.value && row.value.deleted)
) {
return true
}
return row.error === "not_found"
Expand All @@ -237,7 +241,7 @@ export class DatabaseImpl implements Database {
const missingIds = missing.map(row => row.key).join(", ")
throw new Error(`Unable to get documents: ${missingIds}`)
}
return rows.map(row => row.doc!)
return rows.map(row => (includeDocs ? row.doc! : row.value))
}

async remove(idOrDoc: string | Document, rev?: string) {
Expand Down
8 changes: 7 additions & 1 deletion packages/server/src/db/linkedRows/LinkController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,15 @@ class LinkController {
link.id !== row._id && link.fieldName === linkedSchema.name
)

// check all the related rows exist
const foundRecords = await this._db.getMultiple(
links.map(l => l.id),
{ allowMissing: true, excludeDocs: true }
)

// The 1 side of 1:N is already related to something else
// You must remove the existing relationship
if (links.length > 0) {
if (foundRecords.length > 0) {
throw new Error(
`1:N Relationship Error: Record already linked to another.`
)
Expand Down
2 changes: 1 addition & 1 deletion packages/types/src/sdk/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export interface Database {
exists(docId: string): Promise<boolean>
getMultiple<T extends Document>(
ids: string[],
opts?: { allowMissing?: boolean }
opts?: { allowMissing?: boolean; excludeDocs?: boolean }
): Promise<T[]>
remove(idOrDoc: Document): Promise<Nano.DocumentDestroyResponse>
remove(idOrDoc: string, rev?: string): Promise<Nano.DocumentDestroyResponse>
Expand Down

0 comments on commit 9812e88

Please sign in to comment.