-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Only select required columns from sql databases #15169
base: master
Are you sure you want to change the base?
Changes from 53 commits
544302a
0e0b647
191b632
a415095
74e1bbc
e3c9156
00557e5
910faa6
be00741
112b7c7
bbb60af
80dcc51
f92fcea
f8ece82
e6a27ad
2d771c9
14b5a42
d60cc7a
0ef4a15
fc22db3
aa28896
eb7fcd0
df62845
740069e
7cd412b
fc75728
7932ee7
499d3f2
51ba1f0
c398412
95f7eea
8765a28
8eb82d3
23531e1
bcc9bba
b05b523
7d8cfeb
3de0795
27d1929
875319e
96bddbb
e23753a
14da902
8da96ab
460b5fd
9396292
92e791f
8891976
0ee432d
5a9ed4f
7cc03b1
16fb865
8905f9d
3168b42
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,9 @@ export async function handleRequest<T extends Operation>( | |
export async function patch(ctx: UserCtx<PatchRowRequest, PatchRowResponse>) { | ||
const source = await utils.getSource(ctx) | ||
|
||
const { viewId, tableId } = utils.getSourceId(ctx) | ||
const sourceId = viewId || tableId | ||
|
||
if (sdk.views.isView(source) && helpers.views.isCalculationView(source)) { | ||
ctx.throw(400, "Cannot update rows through a calculation view") | ||
} | ||
|
@@ -86,7 +89,7 @@ export async function patch(ctx: UserCtx<PatchRowRequest, PatchRowResponse>) { | |
// The id might have been changed, so the refetching would fail. Recalculating the id just in case | ||
const updatedId = | ||
generateIdForRow({ ...beforeRow, ...dataToUpdate }, table) || _id | ||
const row = await sdk.rows.external.getRow(table._id!, updatedId, { | ||
const row = await sdk.rows.external.getRow(sourceId, updatedId, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice find! |
||
relationships: true, | ||
}) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,8 @@ import { | |
import { breakExternalTableId } from "../../../../integrations/utils" | ||
import { generateJunctionTableID } from "../../../../db/utils" | ||
import sdk from "../../../../sdk" | ||
import { helpers } from "@budibase/shared-core" | ||
import { helpers, PROTECTED_INTERNAL_COLUMNS } from "@budibase/shared-core" | ||
import { sql } from "@budibase/backend-core" | ||
|
||
type TableMap = Record<string, Table> | ||
|
||
|
@@ -118,45 +119,131 @@ export async function buildSqlFieldList( | |
opts?: { relationships: boolean } | ||
) { | ||
const { relationships } = opts || {} | ||
|
||
const nonMappedColumns = [FieldType.LINK, FieldType.FORMULA, FieldType.AI] | ||
|
||
function extractRealFields(table: Table, existing: string[] = []) { | ||
return Object.entries(table.schema) | ||
.filter( | ||
([columnName, column]) => | ||
column.type !== FieldType.LINK && | ||
column.type !== FieldType.FORMULA && | ||
column.type !== FieldType.AI && | ||
!existing.find( | ||
(field: string) => field === `${table.name}.${columnName}` | ||
) | ||
!nonMappedColumns.includes(column.type) && | ||
!existing.find((field: string) => field === columnName) | ||
) | ||
.map(([columnName]) => `${table.name}.${columnName}`) | ||
.map(([columnName]) => columnName) | ||
} | ||
|
||
let fields: string[] = [] | ||
if (sdk.views.isView(source)) { | ||
fields = Object.keys(helpers.views.basicFields(source)) | ||
} else { | ||
fields = extractRealFields(source) | ||
function getRequiredFields(table: Table, existing: string[] = []) { | ||
const requiredFields: string[] = [] | ||
if (table.primary) { | ||
requiredFields.push(...table.primary) | ||
} | ||
if (table.primaryDisplay) { | ||
requiredFields.push(table.primaryDisplay) | ||
} | ||
|
||
if (!sql.utils.isExternalTable(table)) { | ||
requiredFields.push(...PROTECTED_INTERNAL_COLUMNS) | ||
mike12345567 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
return requiredFields.filter( | ||
column => | ||
!existing.find((field: string) => field === column) && | ||
table.schema[column] && | ||
!nonMappedColumns.includes(table.schema[column].type) | ||
) | ||
} | ||
|
||
let fields: string[] = [] | ||
|
||
const isView = sdk.views.isView(source) | ||
|
||
let table: Table | ||
if (sdk.views.isView(source)) { | ||
if (isView) { | ||
table = await sdk.views.getTable(source.id) | ||
|
||
fields = Object.keys(helpers.views.basicFields(source)).filter( | ||
f => table.schema[f].type !== FieldType.LINK | ||
) | ||
} else { | ||
table = source | ||
fields = extractRealFields(source).filter( | ||
f => table.schema[f].visible !== false | ||
) | ||
} | ||
|
||
for (let field of Object.values(table.schema)) { | ||
const containsFormula = (isView ? fields : Object.keys(table.schema)).some( | ||
f => table.schema[f]?.type === FieldType.FORMULA | ||
) | ||
// If are requesting for a formula field, we need to retrieve all fields | ||
if (containsFormula) { | ||
fields = extractRealFields(table) | ||
} | ||
|
||
if (!isView || !helpers.views.isCalculationView(source)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For calculation views, I assume this ends up just leaving the fields empty (since its up to the SQL layer to generate the select statements for these) |
||
fields.push( | ||
...getRequiredFields( | ||
{ | ||
...table, | ||
primaryDisplay: source.primaryDisplay || table.primaryDisplay, | ||
}, | ||
fields | ||
) | ||
) | ||
} | ||
|
||
fields = fields.map(c => `${table.name}.${c}`) | ||
|
||
for (const field of Object.values(table.schema)) { | ||
if (field.type !== FieldType.LINK || !relationships || !field.tableId) { | ||
continue | ||
} | ||
|
||
if ( | ||
isView && | ||
(!source.schema?.[field.name] || | ||
!helpers.views.isVisible(source.schema[field.name])) && | ||
!containsFormula | ||
) { | ||
continue | ||
} | ||
|
||
const { tableName } = breakExternalTableId(field.tableId) | ||
if (tables[tableName]) { | ||
fields = fields.concat(extractRealFields(tables[tableName], fields)) | ||
const relatedTable = tables[tableName] | ||
if (!relatedTable) { | ||
continue | ||
} | ||
|
||
const viewFields = new Set<string>() | ||
if (containsFormula) { | ||
extractRealFields(relatedTable).forEach(f => viewFields.add(f)) | ||
} else { | ||
relatedTable.primary?.forEach(f => viewFields.add(f)) | ||
if (relatedTable.primaryDisplay) { | ||
viewFields.add(relatedTable.primaryDisplay) | ||
} | ||
|
||
if (isView) { | ||
Object.entries(source.schema?.[field.name]?.columns || {}) | ||
.filter( | ||
([columnName, columnConfig]) => | ||
relatedTable.schema[columnName] && | ||
helpers.views.isVisible(columnConfig) && | ||
![FieldType.LINK, FieldType.FORMULA].includes( | ||
relatedTable.schema[columnName].type | ||
) | ||
) | ||
.forEach(([field]) => viewFields.add(field)) | ||
} | ||
} | ||
|
||
const fieldsToAdd = Array.from(viewFields) | ||
.filter(f => !nonMappedColumns.includes(relatedTable.schema[f].type)) | ||
.map(f => `${relatedTable.name}.${f}`) | ||
.filter(f => !fields.includes(f)) | ||
fields.push(...fieldsToAdd) | ||
} | ||
|
||
return fields | ||
return [...new Set(fields)] | ||
} | ||
|
||
export function isKnexEmptyReadResponse(resp: DatasourcePlusQueryResponse) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for it has been moved to
sqlUtils