Merge pull request #14416 from Budibase/fix/recursive-relationships

Fix for maximum call stack exceeded
This commit is contained in:
Michael Drury 2024-08-20 12:39:51 +01:00 committed by GitHub
commit 587d0f434e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 78 deletions

View File

@ -16,32 +16,32 @@ export const removeInvalidFilters = (
validFields = validFields.map(f => f.toLowerCase())
for (const filterKey of Object.keys(result) as (keyof SearchFilters)[]) {
if (typeof result[filterKey] !== "object") {
const filter = result[filterKey]
if (!filter || typeof filter !== "object") {
continue
}
if (isLogicalSearchOperator(filterKey)) {
const resultingConditions: SearchFilters[] = []
for (const condition of result[filterKey].conditions) {
for (const condition of filter.conditions) {
const resultingCondition = removeInvalidFilters(condition, validFields)
if (Object.keys(resultingCondition).length) {
resultingConditions.push(resultingCondition)
}
}
if (resultingConditions.length) {
result[filterKey].conditions = resultingConditions
filter.conditions = resultingConditions
} else {
delete result[filterKey]
}
continue
}
const filter = result[filterKey]
for (const columnKey of Object.keys(filter)) {
const possibleKeys = [columnKey, db.removeKeyNumbering(columnKey)].map(
c => c.toLowerCase()
)
if (!validFields.some(f => possibleKeys.includes(f.toLowerCase()))) {
delete filter[columnKey]
delete filter[columnKey as keyof typeof filter]
}
}
if (!Object.keys(filter).length) {
@ -59,24 +59,31 @@ export const getQueryableFields = async (
const extractTableFields = async (
table: Table,
allowedFields: string[],
fromTables: string[]
fromTables: string[],
opts?: { noRelationships?: boolean }
): Promise<string[]> => {
const result = []
for (const field of Object.keys(table.schema).filter(
f => allowedFields.includes(f) && table.schema[f].visible !== false
)) {
const subSchema = table.schema[field]
if (subSchema.type === FieldType.LINK) {
if (fromTables.includes(subSchema.tableId)) {
// avoid circular loops
continue
}
const isRelationship = subSchema.type === FieldType.LINK
// avoid relationship loops
if (
isRelationship &&
(opts?.noRelationships || fromTables.includes(subSchema.tableId))
) {
continue
}
if (isRelationship) {
try {
const relatedTable = await sdk.tables.getTable(subSchema.tableId)
const relatedFields = await extractTableFields(
relatedTable,
Object.keys(relatedTable.schema),
[...fromTables, subSchema.tableId]
[...fromTables, subSchema.tableId],
// don't let it recurse back and forth between relationships
{ noRelationships: true }
)
result.push(

View File

@ -386,35 +386,13 @@ describe("query utils", () => {
expect(result).toEqual([
"_id",
"name",
// deep 1 aux1 primitive props
// aux1 primitive props
"aux1.name",
"aux1Table.name",
// deep 2 aux1 primitive props
"aux1.aux2_1.title",
"aux1Table.aux2_1.title",
"aux1.aux2Table.title",
"aux1Table.aux2Table.title",
// deep 2 aux2 primitive props
"aux1.aux2_2.title",
"aux1Table.aux2_2.title",
"aux1.aux2Table.title",
"aux1Table.aux2Table.title",
// deep 1 aux2 primitive props
// aux2 primitive props
"aux2.title",
"aux2Table.title",
// deep 2 aux2 primitive props
"aux2.aux1_1.name",
"aux2Table.aux1_1.name",
"aux2.aux1Table.name",
"aux2Table.aux1Table.name",
"aux2.aux1_2.name",
"aux2Table.aux1_2.name",
"aux2.aux1Table.name",
"aux2Table.aux1Table.name",
])
})
@ -426,35 +404,17 @@ describe("query utils", () => {
"_id",
"name",
// deep 1 aux2_1 primitive props
// aux2_1 primitive props
"aux2_1.title",
"aux2Table.title",
// deep 2 aux2_1 primitive props
"aux2_1.table.name",
"aux2Table.table.name",
"aux2_1.TestTable.name",
"aux2Table.TestTable.name",
// deep 1 aux2_2 primitive props
// aux2_2 primitive props
"aux2_2.title",
"aux2Table.title",
// deep 2 aux2_2 primitive props
"aux2_2.table.name",
"aux2Table.table.name",
"aux2_2.TestTable.name",
"aux2Table.TestTable.name",
// deep 1 table primitive props
// table primitive props
"table.name",
"TestTable.name",
// deep 2 table primitive props
"table.aux2.title",
"TestTable.aux2.title",
"table.aux2Table.title",
"TestTable.aux2Table.title",
])
})
@ -466,35 +426,17 @@ describe("query utils", () => {
"_id",
"title",
// deep 1 aux1_1 primitive props
// aux1_1 primitive props
"aux1_1.name",
"aux1Table.name",
// deep 2 aux1_1 primitive props
"aux1_1.table.name",
"aux1Table.table.name",
"aux1_1.TestTable.name",
"aux1Table.TestTable.name",
// deep 1 aux1_2 primitive props
// aux1_2 primitive props
"aux1_2.name",
"aux1Table.name",
// deep 2 aux1_2 primitive props
"aux1_2.table.name",
"aux1Table.table.name",
"aux1_2.TestTable.name",
"aux1Table.TestTable.name",
// deep 1 table primitive props
// table primitive props
"table.name",
"TestTable.name",
// deep 2 table primitive props
"table.aux1.name",
"TestTable.aux1.name",
"table.aux1Table.name",
"TestTable.aux1Table.name",
])
})
})