diff --git a/server/postgres/src/storage.ts b/server/postgres/src/storage.ts index 4afbd5b4b2..1c943786d0 100644 --- a/server/postgres/src/storage.ts +++ b/server/postgres/src/storage.ts @@ -88,6 +88,7 @@ import { DBCollectionHelper, type DBDoc, doFetchTypes, + filterProjection, getDBClient, inferType, isDataField, @@ -662,7 +663,9 @@ abstract class PostgresAdapterBase implements DbAdapter { const joins = this.buildJoins(_class, options) // Add workspace name as $1 - const select = `SELECT ${this.getProjection(vars, domain, options?.projection, joins, options?.associations)} FROM ${domain}` + const projection = this.localizeProjection(_class, options?.projection ?? undefined) + + const select = `SELECT ${this.getProjection(vars, domain, projection, joins, options?.associations)} FROM ${domain}` const showArchived = shouldShowArchived(query, options) const secJoin = this.addSecurity(vars, query, showArchived, domain, ctx.contextData) @@ -714,11 +717,11 @@ abstract class PostgresAdapterBase implements DbAdapter { options?.associations === undefined ) { return toFindResult( - result.map((p) => parseDocWithProjection(p, domain, options?.projection)), + result.map((p) => parseDocWithProjection(p, domain, projection)), total ) } else { - const res = this.parseLookup(result, joins, options?.projection, domain) + const res = this.parseLookup(result, joins, projection, domain) return toFindResult(res, total) } })) as FindResult @@ -739,6 +742,36 @@ abstract class PostgresAdapterBase implements DbAdapter { ) } + private localizeProjection( + _class: Ref>, + projection: Projection | undefined + ): Projection | undefined { + if (projection === undefined) return + + if (!this.hierarchy.isMixin(_class)) { + return projection + } + + projection = { ...projection } + for (const key in projection) { + if (key.includes('.')) continue + try { + const attr = this.hierarchy.findAttribute(_class, key) + if (attr !== undefined && this.hierarchy.isMixin(attr.attributeOf)) { + const newKey = `${attr.attributeOf}.${attr.name}` as keyof Projection + projection[newKey] = projection[key] + + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete projection[key] + } + } catch (err: any) { + // ignore, if + } + } + + return projection + } + private buildJoins(_class: Ref>, options: ServerFindOptions | undefined): JoinProps[] { const joins = this.buildJoin(_class, options?.lookup) if (options?.domainLookup !== undefined) { @@ -888,17 +921,8 @@ abstract class PostgresAdapterBase implements DbAdapter { continue } if (column === 'data') { - const data = row[column] - if (projection !== undefined) { - if (projection !== undefined) { - for (const key in data) { - if (!Object.prototype.hasOwnProperty.call(projection, key) || (projection as any)[key] === 0) { - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete data[key] - } - } - } - } + let data = row[column] + data = filterProjection(data, projection) doc = { ...doc, ...data } } else { if (column === 'createdOn' || column === 'modifiedOn') { diff --git a/server/postgres/src/utils.ts b/server/postgres/src/utils.ts index 8306ca0c02..fb05e31464 100644 --- a/server/postgres/src/utils.ts +++ b/server/postgres/src/utils.ts @@ -554,6 +554,9 @@ export function convertArrayParams (parameters?: ParameterOrJSON[]): any[] } export function filterProjection (data: any, projection: Projection | undefined): any { + if (projection === undefined) { + return data + } for (const key in data) { if (!Object.prototype.hasOwnProperty.call(projection, key) || (projection as any)[key] === 0) { // check nested projections in case of object