@payloadcms/drizzle 3.91.0 → 3.92.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/find/buildPolymorphicJoinQuery.d.ts +4 -2
- package/dist/find/buildPolymorphicJoinQuery.d.ts.map +1 -1
- package/dist/find/buildPolymorphicJoinQuery.js +16 -5
- package/dist/find/buildPolymorphicJoinQuery.js.map +1 -1
- package/dist/find/buildPolymorphicJoinQuery.spec.js +165 -2
- package/dist/find/buildPolymorphicJoinQuery.spec.js.map +1 -1
- package/dist/find/buildPolymorphicJoinWhere.js +6 -1
- package/dist/find/buildPolymorphicJoinWhere.js.map +1 -1
- package/dist/find/createPolymorphicJoinWherePlan.d.ts +2 -1
- package/dist/find/createPolymorphicJoinWherePlan.d.ts.map +1 -1
- package/dist/find/createPolymorphicJoinWherePlan.js +14 -5
- package/dist/find/createPolymorphicJoinWherePlan.js.map +1 -1
- package/dist/find/createPolymorphicJoinWherePlan.spec.js +76 -1
- package/dist/find/createPolymorphicJoinWherePlan.spec.js.map +1 -1
- package/dist/find/traverseFields.d.ts.map +1 -1
- package/dist/find/traverseFields.js +2 -0
- package/dist/find/traverseFields.js.map +1 -1
- package/package.json +4 -4
|
@@ -6,7 +6,9 @@ type BuildPolymorphicJoinQueryArgs = {
|
|
|
6
6
|
currentTableName: string;
|
|
7
7
|
field: FlattenedJoinField;
|
|
8
8
|
limit: number;
|
|
9
|
+
locale?: string;
|
|
9
10
|
page?: number;
|
|
11
|
+
pageSize?: number;
|
|
10
12
|
path: string;
|
|
11
13
|
shouldCount: boolean;
|
|
12
14
|
sort?: string | string[];
|
|
@@ -25,13 +27,13 @@ type PolymorphicJoinQuery = {
|
|
|
25
27
|
*
|
|
26
28
|
* `field.collection` must contain at least one configured collection. Each mapped table must have
|
|
27
29
|
* an `id` column and the column named by `field.on`. The supplied `limit` is used as-is; callers can
|
|
28
|
-
* include an extra look-ahead row
|
|
30
|
+
* include an extra look-ahead row and supply the original `pageSize` for offset calculation.
|
|
29
31
|
*
|
|
30
32
|
* @returns The stable projection name, the document projection, and the count projection when
|
|
31
33
|
* `shouldCount` is true.
|
|
32
34
|
* @throws If the join definition, target collection, mapped table, required columns, or sort shape
|
|
33
35
|
* cannot be represented by the polymorphic query.
|
|
34
36
|
*/
|
|
35
|
-
export declare const buildPolymorphicJoinQuery: ({ adapter, currentTableName, field, limit, page, path, shouldCount, sort, where, }: BuildPolymorphicJoinQueryArgs) => PolymorphicJoinQuery;
|
|
37
|
+
export declare const buildPolymorphicJoinQuery: ({ adapter, currentTableName, field, limit, locale, page, pageSize, path, shouldCount, sort, where, }: BuildPolymorphicJoinQueryArgs) => PolymorphicJoinQuery;
|
|
36
38
|
export {};
|
|
37
39
|
//# sourceMappingURL=buildPolymorphicJoinQuery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildPolymorphicJoinQuery.d.ts","sourceRoot":"","sources":["../../src/find/buildPolymorphicJoinQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAKtC,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAG7D,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,aAAa,CAAA;AAO/D,KAAK,6BAA6B,GAAG;IACnC,OAAO,EAAE,cAAc,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,KAAK,EAAE,kBAAkB,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACxB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,KAAK,oBAAoB,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACnB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAA;CACvB,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,yBAAyB,
|
|
1
|
+
{"version":3,"file":"buildPolymorphicJoinQuery.d.ts","sourceRoot":"","sources":["../../src/find/buildPolymorphicJoinQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAKtC,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAG7D,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,aAAa,CAAA;AAO/D,KAAK,6BAA6B,GAAG;IACnC,OAAO,EAAE,cAAc,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,KAAK,EAAE,kBAAkB,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACxB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,KAAK,oBAAoB,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACnB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAA;CACvB,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,yBAAyB,yGAYnC,6BAA6B,KAAG,oBAkJlC,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { asc, count, desc, eq, sql } from 'drizzle-orm';
|
|
1
|
+
import { and, asc, count, desc, eq, getTableName, sql } from 'drizzle-orm';
|
|
2
2
|
import toSnakeCase from 'to-snake-case';
|
|
3
3
|
import { jsonAggBuildObject } from '../utilities/json.js';
|
|
4
4
|
import { buildPolymorphicJoinWhere } from './buildPolymorphicJoinWhere.js';
|
|
@@ -11,13 +11,13 @@ import { createPolymorphicJoinWherePlan } from './createPolymorphicJoinWherePlan
|
|
|
11
11
|
*
|
|
12
12
|
* `field.collection` must contain at least one configured collection. Each mapped table must have
|
|
13
13
|
* an `id` column and the column named by `field.on`. The supplied `limit` is used as-is; callers can
|
|
14
|
-
* include an extra look-ahead row
|
|
14
|
+
* include an extra look-ahead row and supply the original `pageSize` for offset calculation.
|
|
15
15
|
*
|
|
16
16
|
* @returns The stable projection name, the document projection, and the count projection when
|
|
17
17
|
* `shouldCount` is true.
|
|
18
18
|
* @throws If the join definition, target collection, mapped table, required columns, or sort shape
|
|
19
19
|
* cannot be represented by the polymorphic query.
|
|
20
|
-
*/ export const buildPolymorphicJoinQuery = ({ adapter, currentTableName, field, limit, page, path, shouldCount, sort, where })=>{
|
|
20
|
+
*/ export const buildPolymorphicJoinQuery = ({ adapter, currentTableName, field, limit, locale, page, pageSize = limit, path, shouldCount, sort, where })=>{
|
|
21
21
|
if (!Array.isArray(field.collection)) {
|
|
22
22
|
throw new Error('A polymorphic join requires a collection array');
|
|
23
23
|
}
|
|
@@ -79,7 +79,18 @@ import { createPolymorphicJoinWherePlan } from './createPolymorphicJoinWherePlan
|
|
|
79
79
|
where,
|
|
80
80
|
wherePlan
|
|
81
81
|
}) : undefined;
|
|
82
|
-
|
|
82
|
+
const hasLocalizedWhere = [
|
|
83
|
+
...wherePlan.values()
|
|
84
|
+
].some((pathPlan)=>{
|
|
85
|
+
const collectionField = pathPlan.fieldsByCollection.get(collection);
|
|
86
|
+
return collectionField?.type === 'scalar' && collectionField.isLocalized;
|
|
87
|
+
});
|
|
88
|
+
const shouldDeduplicate = hasLocalizedWhere && (!locale || locale === 'all');
|
|
89
|
+
let collectionQuery = (shouldDeduplicate ? db.selectDistinct(selectFields) : db.select(selectFields)).from(table).$dynamic();
|
|
90
|
+
if (hasLocalizedWhere) {
|
|
91
|
+
const localesTable = adapter.tables[`${getTableName(table)}${adapter.localesSuffix}`];
|
|
92
|
+
collectionQuery = collectionQuery.leftJoin(localesTable, and(eq(table['id'], localesTable._parentID), locale && locale !== 'all' ? eq(localesTable._locale, locale) : undefined));
|
|
93
|
+
}
|
|
83
94
|
if (collectionWhere) {
|
|
84
95
|
collectionQuery = collectionQuery.where(collectionWhere);
|
|
85
96
|
}
|
|
@@ -101,7 +112,7 @@ import { createPolymorphicJoinWherePlan } from './createPolymorphicJoinWherePlan
|
|
|
101
112
|
limitOffsetSQL = sql` LIMIT ${limit}`;
|
|
102
113
|
}
|
|
103
114
|
if (page && limit !== 0) {
|
|
104
|
-
const offset = (page - 1) *
|
|
115
|
+
const offset = (page - 1) * pageSize;
|
|
105
116
|
if (offset > 0) {
|
|
106
117
|
limitOffsetSQL = sql`${limitOffsetSQL} OFFSET ${offset}`;
|
|
107
118
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/find/buildPolymorphicJoinQuery.ts"],"sourcesContent":["import type { SQL } from 'drizzle-orm'\nimport type { LibSQLDatabase } from 'drizzle-orm/libsql'\nimport type { SQLiteSelect } from 'drizzle-orm/sqlite-core'\n\nimport { asc, count, desc, eq, sql } from 'drizzle-orm'\nimport { type FlattenedJoinField, type Where } from 'payload'\nimport toSnakeCase from 'to-snake-case'\n\nimport type { DrizzleAdapter, GenericTable } from '../types.js'\nimport type { PolymorphicJoinWherePlan } from './createPolymorphicJoinWherePlan.js'\n\nimport { jsonAggBuildObject } from '../utilities/json.js'\nimport { buildPolymorphicJoinWhere } from './buildPolymorphicJoinWhere.js'\nimport { createPolymorphicJoinWherePlan } from './createPolymorphicJoinWherePlan.js'\n\ntype BuildPolymorphicJoinQueryArgs = {\n adapter: DrizzleAdapter\n currentTableName: string\n field: FlattenedJoinField\n limit: number\n page?: number\n path: string\n shouldCount: boolean\n sort?: string | string[]\n where?: Where\n}\n\ntype PolymorphicJoinQuery = {\n columnName: string\n count?: SQL.Aliased\n documents: SQL.Aliased\n}\n\n/**\n * Builds the correlated document and optional count projections for a join that targets multiple\n * collections. Every collection branch exposes the same `id`, parent, `relationTo`, and sort\n * columns before the branches are combined. A missing sort field resolves to SQL NULL so targets\n * with different schemas can still share one ordered union.\n *\n * `field.collection` must contain at least one configured collection. Each mapped table must have\n * an `id` column and the column named by `field.on`. The supplied `limit` is used as-is; callers can\n * include an extra look-ahead row when they calculate pagination.\n *\n * @returns The stable projection name, the document projection, and the count projection when\n * `shouldCount` is true.\n * @throws If the join definition, target collection, mapped table, required columns, or sort shape\n * cannot be represented by the polymorphic query.\n */\nexport const buildPolymorphicJoinQuery = ({\n adapter,\n currentTableName,\n field,\n limit,\n page,\n path,\n shouldCount,\n sort,\n where,\n}: BuildPolymorphicJoinQueryArgs): PolymorphicJoinQuery => {\n if (!Array.isArray(field.collection)) {\n throw new Error('A polymorphic join requires a collection array')\n }\n\n if (field.collection.length === 0) {\n throw new Error('A polymorphic join requires at least one collection')\n }\n\n if (Array.isArray(sort)) {\n throw new Error('Polymorphic joins do not support multiple sort fields')\n }\n\n const collections = field.collection\n const columnName = `${path.replaceAll('.', '_')}${field.name}`\n const db = adapter.drizzle as LibSQLDatabase\n const onPath = field.on.split('.').join('_')\n const collectionTables = collections.map((collection) => {\n if (!adapter.payload.collections[collection]) {\n throw new Error(`Unknown polymorphic join collection \"${collection}\"`)\n }\n\n const tableName = adapter.tableNameMap.get(toSnakeCase(collection))\n const table = tableName ? (adapter.tables[tableName] as GenericTable | undefined) : undefined\n\n if (!table) {\n throw new Error(`Polymorphic join collection \"${collection}\" has no database table`)\n }\n\n if (!table['id']) {\n throw new Error(`Polymorphic join collection \"${collection}\" has no \"id\" column`)\n }\n\n if (!table[onPath]) {\n throw new Error(`Polymorphic join collection \"${collection}\" has no \"${onPath}\" column`)\n }\n\n return { collection, table }\n })\n const sortField = getSortField({ adapter, collections, sort })\n const sortOrder = sortField.startsWith('-') ? desc : asc\n const sortPath = sortField.replace('-', '').split('.').join('_')\n const wherePlan: PolymorphicJoinWherePlan = where\n ? createPolymorphicJoinWherePlan({ adapter, collections, where })\n : new Map()\n let unionQuery: null | SQLiteSelect = null\n\n for (const { collection, table } of collectionTables) {\n const sortColumn = table[sortPath]\n const selectFields = {\n id: table['id'],\n parent: sql`${table[onPath]}`.as(onPath),\n relationTo: sql`${collection}`.as('relationTo'),\n sortPath: sql`${sortColumn ?? null}`.as('sortPath'),\n }\n const collectionWhere =\n where && Object.keys(where).length > 0\n ? buildPolymorphicJoinWhere({\n adapter,\n collection,\n table,\n where,\n wherePlan,\n })\n : undefined\n let collectionQuery = db.select(selectFields).from(table).$dynamic()\n\n if (collectionWhere) {\n collectionQuery = collectionQuery.where(collectionWhere)\n }\n\n if (unionQuery === null) {\n unionQuery = collectionQuery as unknown as SQLiteSelect\n } else {\n unionQuery = unionQuery.unionAll(collectionQuery)\n }\n }\n\n const subQueryAlias = `${columnName}_subquery`\n const parentConstraint = eq(\n sql.raw(`\"${currentTableName}\".\"id\"`),\n sql.raw(`\"${subQueryAlias}\".\"${onPath}\"`),\n )\n const countExpression = shouldCount\n ? sql`${db\n .select({ count: count() })\n .from(sql`${unionQuery.as(subQueryAlias)}`)\n .where(parentConstraint)}`.as(`${columnName}_count`)\n : undefined\n\n unionQuery = unionQuery.orderBy(sortOrder(sql`\"sortPath\"`))\n\n const sortedUnionAlias = `${columnName}_sorted`\n let limitOffsetSQL = sql.empty()\n\n if (limit) {\n limitOffsetSQL = sql` LIMIT ${limit}`\n }\n\n if (page && limit !== 0) {\n const offset = (page - 1) * limit\n\n if (offset > 0) {\n limitOffsetSQL = sql`${limitOffsetSQL} OFFSET ${offset}`\n }\n }\n\n const parentWhere = sql.raw(`\"${sortedUnionAlias}\".\"${onPath}\" = \"${currentTableName}\".\"id\"`)\n const documents = sql`(\n SELECT ${jsonAggBuildObject(adapter, {\n id: sql.raw(`\"${subQueryAlias}\".\"id\"`),\n relationTo: sql.raw(`\"${subQueryAlias}\".\"relationTo\"`),\n })}\n FROM (\n SELECT * FROM ${sql`${unionQuery.as(sortedUnionAlias)}`}\n WHERE ${parentWhere}${limitOffsetSQL}\n ) AS ${sql.raw(`\"${subQueryAlias}\"`)}\n )`.as(columnName)\n\n return {\n columnName,\n count: countExpression,\n documents,\n }\n}\n\nconst getSortField = ({\n adapter,\n collections,\n sort,\n}: {\n adapter: DrizzleAdapter\n collections: string[]\n sort?: string\n}): string => {\n if (sort) {\n return sort\n }\n\n const hasCreatedAt = collections.some((collection) =>\n adapter.payload.collections[collection].config.fields.some(\n (field) => field.type === 'date' && field.name === 'createdAt',\n ),\n )\n\n return hasCreatedAt ? '-createdAt' : 'id'\n}\n"],"names":["asc","count","desc","eq","sql","toSnakeCase","jsonAggBuildObject","buildPolymorphicJoinWhere","createPolymorphicJoinWherePlan","buildPolymorphicJoinQuery","adapter","currentTableName","field","limit","page","path","shouldCount","sort","where","Array","isArray","collection","Error","length","collections","columnName","replaceAll","name","db","drizzle","onPath","on","split","join","collectionTables","map","payload","tableName","tableNameMap","get","table","tables","undefined","sortField","getSortField","sortOrder","startsWith","sortPath","replace","wherePlan","Map","unionQuery","sortColumn","selectFields","id","parent","as","relationTo","collectionWhere","Object","keys","collectionQuery","select","from","$dynamic","unionAll","subQueryAlias","parentConstraint","raw","countExpression","orderBy","sortedUnionAlias","limitOffsetSQL","empty","offset","parentWhere","documents","hasCreatedAt","some","config","fields","type"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/find/buildPolymorphicJoinQuery.ts"],"sourcesContent":["import type { SQL } from 'drizzle-orm'\nimport type { LibSQLDatabase } from 'drizzle-orm/libsql'\nimport type { SQLiteSelect } from 'drizzle-orm/sqlite-core'\n\nimport { and, asc, count, desc, eq, getTableName, sql } from 'drizzle-orm'\nimport { type FlattenedJoinField, type Where } from 'payload'\nimport toSnakeCase from 'to-snake-case'\n\nimport type { DrizzleAdapter, GenericTable } from '../types.js'\nimport type { PolymorphicJoinWherePlan } from './createPolymorphicJoinWherePlan.js'\n\nimport { jsonAggBuildObject } from '../utilities/json.js'\nimport { buildPolymorphicJoinWhere } from './buildPolymorphicJoinWhere.js'\nimport { createPolymorphicJoinWherePlan } from './createPolymorphicJoinWherePlan.js'\n\ntype BuildPolymorphicJoinQueryArgs = {\n adapter: DrizzleAdapter\n currentTableName: string\n field: FlattenedJoinField\n limit: number\n locale?: string\n page?: number\n pageSize?: number\n path: string\n shouldCount: boolean\n sort?: string | string[]\n where?: Where\n}\n\ntype PolymorphicJoinQuery = {\n columnName: string\n count?: SQL.Aliased\n documents: SQL.Aliased\n}\n\n/**\n * Builds the correlated document and optional count projections for a join that targets multiple\n * collections. Every collection branch exposes the same `id`, parent, `relationTo`, and sort\n * columns before the branches are combined. A missing sort field resolves to SQL NULL so targets\n * with different schemas can still share one ordered union.\n *\n * `field.collection` must contain at least one configured collection. Each mapped table must have\n * an `id` column and the column named by `field.on`. The supplied `limit` is used as-is; callers can\n * include an extra look-ahead row and supply the original `pageSize` for offset calculation.\n *\n * @returns The stable projection name, the document projection, and the count projection when\n * `shouldCount` is true.\n * @throws If the join definition, target collection, mapped table, required columns, or sort shape\n * cannot be represented by the polymorphic query.\n */\nexport const buildPolymorphicJoinQuery = ({\n adapter,\n currentTableName,\n field,\n limit,\n locale,\n page,\n pageSize = limit,\n path,\n shouldCount,\n sort,\n where,\n}: BuildPolymorphicJoinQueryArgs): PolymorphicJoinQuery => {\n if (!Array.isArray(field.collection)) {\n throw new Error('A polymorphic join requires a collection array')\n }\n\n if (field.collection.length === 0) {\n throw new Error('A polymorphic join requires at least one collection')\n }\n\n if (Array.isArray(sort)) {\n throw new Error('Polymorphic joins do not support multiple sort fields')\n }\n\n const collections = field.collection\n const columnName = `${path.replaceAll('.', '_')}${field.name}`\n const db = adapter.drizzle as LibSQLDatabase\n const onPath = field.on.split('.').join('_')\n const collectionTables = collections.map((collection) => {\n if (!adapter.payload.collections[collection]) {\n throw new Error(`Unknown polymorphic join collection \"${collection}\"`)\n }\n\n const tableName = adapter.tableNameMap.get(toSnakeCase(collection))\n const table = tableName ? (adapter.tables[tableName] as GenericTable | undefined) : undefined\n\n if (!table) {\n throw new Error(`Polymorphic join collection \"${collection}\" has no database table`)\n }\n\n if (!table['id']) {\n throw new Error(`Polymorphic join collection \"${collection}\" has no \"id\" column`)\n }\n\n if (!table[onPath]) {\n throw new Error(`Polymorphic join collection \"${collection}\" has no \"${onPath}\" column`)\n }\n\n return { collection, table }\n })\n const sortField = getSortField({ adapter, collections, sort })\n const sortOrder = sortField.startsWith('-') ? desc : asc\n const sortPath = sortField.replace('-', '').split('.').join('_')\n const wherePlan: PolymorphicJoinWherePlan = where\n ? createPolymorphicJoinWherePlan({ adapter, collections, where })\n : new Map()\n let unionQuery: null | SQLiteSelect = null\n\n for (const { collection, table } of collectionTables) {\n const sortColumn = table[sortPath]\n const selectFields = {\n id: table['id'],\n parent: sql`${table[onPath]}`.as(onPath),\n relationTo: sql`${collection}`.as('relationTo'),\n sortPath: sql`${sortColumn ?? null}`.as('sortPath'),\n }\n const collectionWhere =\n where && Object.keys(where).length > 0\n ? buildPolymorphicJoinWhere({\n adapter,\n collection,\n table,\n where,\n wherePlan,\n })\n : undefined\n const hasLocalizedWhere = [...wherePlan.values()].some((pathPlan) => {\n const collectionField = pathPlan.fieldsByCollection.get(collection)\n\n return collectionField?.type === 'scalar' && collectionField.isLocalized\n })\n const shouldDeduplicate = hasLocalizedWhere && (!locale || locale === 'all')\n let collectionQuery = (\n shouldDeduplicate ? db.selectDistinct(selectFields) : db.select(selectFields)\n )\n .from(table)\n .$dynamic()\n\n if (hasLocalizedWhere) {\n const localesTable = adapter.tables[`${getTableName(table)}${adapter.localesSuffix}`]\n\n collectionQuery = collectionQuery.leftJoin(\n localesTable,\n and(\n eq(table['id'], localesTable._parentID),\n locale && locale !== 'all' ? eq(localesTable._locale, locale) : undefined,\n ),\n )\n }\n\n if (collectionWhere) {\n collectionQuery = collectionQuery.where(collectionWhere)\n }\n\n if (unionQuery === null) {\n unionQuery = collectionQuery as unknown as SQLiteSelect\n } else {\n unionQuery = unionQuery.unionAll(collectionQuery)\n }\n }\n\n const subQueryAlias = `${columnName}_subquery`\n const parentConstraint = eq(\n sql.raw(`\"${currentTableName}\".\"id\"`),\n sql.raw(`\"${subQueryAlias}\".\"${onPath}\"`),\n )\n const countExpression = shouldCount\n ? sql`${db\n .select({ count: count() })\n .from(sql`${unionQuery.as(subQueryAlias)}`)\n .where(parentConstraint)}`.as(`${columnName}_count`)\n : undefined\n\n unionQuery = unionQuery.orderBy(sortOrder(sql`\"sortPath\"`))\n\n const sortedUnionAlias = `${columnName}_sorted`\n let limitOffsetSQL = sql.empty()\n\n if (limit) {\n limitOffsetSQL = sql` LIMIT ${limit}`\n }\n\n if (page && limit !== 0) {\n const offset = (page - 1) * pageSize\n\n if (offset > 0) {\n limitOffsetSQL = sql`${limitOffsetSQL} OFFSET ${offset}`\n }\n }\n\n const parentWhere = sql.raw(`\"${sortedUnionAlias}\".\"${onPath}\" = \"${currentTableName}\".\"id\"`)\n const documents = sql`(\n SELECT ${jsonAggBuildObject(adapter, {\n id: sql.raw(`\"${subQueryAlias}\".\"id\"`),\n relationTo: sql.raw(`\"${subQueryAlias}\".\"relationTo\"`),\n })}\n FROM (\n SELECT * FROM ${sql`${unionQuery.as(sortedUnionAlias)}`}\n WHERE ${parentWhere}${limitOffsetSQL}\n ) AS ${sql.raw(`\"${subQueryAlias}\"`)}\n )`.as(columnName)\n\n return {\n columnName,\n count: countExpression,\n documents,\n }\n}\n\nconst getSortField = ({\n adapter,\n collections,\n sort,\n}: {\n adapter: DrizzleAdapter\n collections: string[]\n sort?: string\n}): string => {\n if (sort) {\n return sort\n }\n\n const hasCreatedAt = collections.some((collection) =>\n adapter.payload.collections[collection].config.fields.some(\n (field) => field.type === 'date' && field.name === 'createdAt',\n ),\n )\n\n return hasCreatedAt ? '-createdAt' : 'id'\n}\n"],"names":["and","asc","count","desc","eq","getTableName","sql","toSnakeCase","jsonAggBuildObject","buildPolymorphicJoinWhere","createPolymorphicJoinWherePlan","buildPolymorphicJoinQuery","adapter","currentTableName","field","limit","locale","page","pageSize","path","shouldCount","sort","where","Array","isArray","collection","Error","length","collections","columnName","replaceAll","name","db","drizzle","onPath","on","split","join","collectionTables","map","payload","tableName","tableNameMap","get","table","tables","undefined","sortField","getSortField","sortOrder","startsWith","sortPath","replace","wherePlan","Map","unionQuery","sortColumn","selectFields","id","parent","as","relationTo","collectionWhere","Object","keys","hasLocalizedWhere","values","some","pathPlan","collectionField","fieldsByCollection","type","isLocalized","shouldDeduplicate","collectionQuery","selectDistinct","select","from","$dynamic","localesTable","localesSuffix","leftJoin","_parentID","_locale","unionAll","subQueryAlias","parentConstraint","raw","countExpression","orderBy","sortedUnionAlias","limitOffsetSQL","empty","offset","parentWhere","documents","hasCreatedAt","config","fields"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { drizzle } from 'drizzle-orm/libsql';
|
|
|
4
4
|
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core';
|
|
5
5
|
import { flattenAllFields } from 'payload';
|
|
6
6
|
import toSnakeCase from 'to-snake-case';
|
|
7
|
-
import { afterAll, describe, expect, it } from 'vitest';
|
|
7
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
8
8
|
import { operatorMap } from '../queries/operatorMap.js';
|
|
9
9
|
import { createJSONQuery } from '../sqlite/createJSONQuery/index.js';
|
|
10
10
|
import { buildPolymorphicJoinQuery } from './buildPolymorphicJoinQuery.js';
|
|
@@ -19,6 +19,11 @@ const articlesTable = sqliteTable('join_articles', {
|
|
|
19
19
|
score: integer('score'),
|
|
20
20
|
title: text('title')
|
|
21
21
|
});
|
|
22
|
+
const articlesLocalesTable = sqliteTable('join_articles_locales', {
|
|
23
|
+
_parentID: integer('_parent_id'),
|
|
24
|
+
_locale: text('_locale'),
|
|
25
|
+
_status: text('_status')
|
|
26
|
+
});
|
|
22
27
|
const notesTable = sqliteTable('join_notes', {
|
|
23
28
|
id: integer('id').primaryKey(),
|
|
24
29
|
parent: integer('parent_id'),
|
|
@@ -135,12 +140,14 @@ const joinField = {
|
|
|
135
140
|
on: 'parent',
|
|
136
141
|
type: 'join'
|
|
137
142
|
};
|
|
138
|
-
const buildQuery = ({ adapter: adapterArg = adapter, field = joinField, limit = 0, page, path = '', shouldCount = false, sort, where } = {})=>buildPolymorphicJoinQuery({
|
|
143
|
+
const buildQuery = ({ adapter: adapterArg = adapter, field = joinField, limit = 0, locale, page, pageSize, path = '', shouldCount = false, sort, where } = {})=>buildPolymorphicJoinQuery({
|
|
139
144
|
adapter: adapterArg,
|
|
140
145
|
currentTableName: getTableName(parentsTable),
|
|
141
146
|
field,
|
|
142
147
|
limit,
|
|
148
|
+
locale,
|
|
143
149
|
page,
|
|
150
|
+
pageSize,
|
|
144
151
|
path,
|
|
145
152
|
shouldCount,
|
|
146
153
|
sort,
|
|
@@ -157,6 +164,162 @@ const renderQuery = (query)=>{
|
|
|
157
164
|
};
|
|
158
165
|
afterAll(()=>client.close());
|
|
159
166
|
describe('buildPolymorphicJoinQuery', ()=>{
|
|
167
|
+
describe('localized filters', ()=>{
|
|
168
|
+
const localizedAdapter = createAdapter({
|
|
169
|
+
articles: {
|
|
170
|
+
fields: [
|
|
171
|
+
{
|
|
172
|
+
name: 'parent',
|
|
173
|
+
relationTo: 'join-parents',
|
|
174
|
+
type: 'relationship'
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: '_status',
|
|
178
|
+
type: 'select',
|
|
179
|
+
localized: true,
|
|
180
|
+
options: [
|
|
181
|
+
'draft',
|
|
182
|
+
'published'
|
|
183
|
+
]
|
|
184
|
+
}
|
|
185
|
+
],
|
|
186
|
+
table: articlesTable
|
|
187
|
+
},
|
|
188
|
+
notes: {
|
|
189
|
+
fields: [
|
|
190
|
+
{
|
|
191
|
+
name: 'parent',
|
|
192
|
+
relationTo: 'join-parents',
|
|
193
|
+
type: 'relationship'
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
table: notesTable
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
localizedAdapter.localesSuffix = '_locales';
|
|
200
|
+
localizedAdapter.tables.join_articles_locales = articlesLocalesTable;
|
|
201
|
+
beforeAll(async ()=>{
|
|
202
|
+
await client.executeMultiple(`
|
|
203
|
+
CREATE TABLE join_parents (id INTEGER PRIMARY KEY);
|
|
204
|
+
CREATE TABLE join_articles (
|
|
205
|
+
id INTEGER PRIMARY KEY, parent_id INTEGER, created_at TEXT,
|
|
206
|
+
details_rank INTEGER, score INTEGER, title TEXT
|
|
207
|
+
);
|
|
208
|
+
CREATE TABLE join_notes (id INTEGER PRIMARY KEY, parent_id INTEGER, title TEXT);
|
|
209
|
+
CREATE TABLE join_articles_locales (_parent_id INTEGER, _locale TEXT, _status TEXT);
|
|
210
|
+
INSERT INTO join_parents VALUES (1);
|
|
211
|
+
INSERT INTO join_articles (id, parent_id) VALUES (1, 1), (2, 1), (3, 1);
|
|
212
|
+
INSERT INTO join_notes (id, parent_id) VALUES (4, 1);
|
|
213
|
+
INSERT INTO join_articles_locales VALUES
|
|
214
|
+
(1, 'en', 'published'), (1, 'fr', 'draft'),
|
|
215
|
+
(2, 'en', 'draft'), (2, 'fr', 'published'),
|
|
216
|
+
(3, 'en', 'published'), (3, 'fr', 'published');
|
|
217
|
+
`);
|
|
218
|
+
});
|
|
219
|
+
it.each([
|
|
220
|
+
{
|
|
221
|
+
locale: 'en',
|
|
222
|
+
ids: [
|
|
223
|
+
1,
|
|
224
|
+
3
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
locale: 'fr',
|
|
229
|
+
ids: [
|
|
230
|
+
2,
|
|
231
|
+
3
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
])('should filter published documents in locale $locale', async ({ locale, ids })=>{
|
|
235
|
+
const query = buildQuery({
|
|
236
|
+
adapter: localizedAdapter,
|
|
237
|
+
locale,
|
|
238
|
+
shouldCount: true,
|
|
239
|
+
sort: 'id',
|
|
240
|
+
where: {
|
|
241
|
+
_status: {
|
|
242
|
+
equals: 'published'
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
const [result] = await db.select({
|
|
247
|
+
documents: query.documents,
|
|
248
|
+
count: query.count
|
|
249
|
+
}).from(parentsTable);
|
|
250
|
+
expect(JSON.parse(result.documents)).toEqual(ids.map((id)=>({
|
|
251
|
+
id,
|
|
252
|
+
relationTo: 'articles'
|
|
253
|
+
})));
|
|
254
|
+
expect(result.count).toBe(2);
|
|
255
|
+
});
|
|
256
|
+
it.each([
|
|
257
|
+
'all',
|
|
258
|
+
undefined
|
|
259
|
+
])('should count matching documents once across locales with locale %s', async (locale)=>{
|
|
260
|
+
const query = buildQuery({
|
|
261
|
+
adapter: localizedAdapter,
|
|
262
|
+
locale,
|
|
263
|
+
shouldCount: true,
|
|
264
|
+
sort: 'id',
|
|
265
|
+
where: {
|
|
266
|
+
_status: {
|
|
267
|
+
equals: 'published'
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
const [result] = await db.select({
|
|
272
|
+
documents: query.documents,
|
|
273
|
+
count: query.count
|
|
274
|
+
}).from(parentsTable);
|
|
275
|
+
expect(JSON.parse(result.documents)).toEqual([
|
|
276
|
+
{
|
|
277
|
+
id: 1,
|
|
278
|
+
relationTo: 'articles'
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
id: 2,
|
|
282
|
+
relationTo: 'articles'
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
id: 3,
|
|
286
|
+
relationTo: 'articles'
|
|
287
|
+
}
|
|
288
|
+
]);
|
|
289
|
+
expect(result.count).toBe(3);
|
|
290
|
+
});
|
|
291
|
+
it('should paginate distinct documents using the page size before the look-ahead row', async ()=>{
|
|
292
|
+
const query = buildQuery({
|
|
293
|
+
adapter: localizedAdapter,
|
|
294
|
+
limit: 2,
|
|
295
|
+
locale: 'all',
|
|
296
|
+
page: 2,
|
|
297
|
+
pageSize: 1,
|
|
298
|
+
shouldCount: true,
|
|
299
|
+
sort: 'id',
|
|
300
|
+
where: {
|
|
301
|
+
_status: {
|
|
302
|
+
equals: 'published'
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
const [result] = await db.select({
|
|
307
|
+
documents: query.documents,
|
|
308
|
+
count: query.count
|
|
309
|
+
}).from(parentsTable);
|
|
310
|
+
expect(JSON.parse(result.documents)).toEqual([
|
|
311
|
+
{
|
|
312
|
+
id: 2,
|
|
313
|
+
relationTo: 'articles'
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: 3,
|
|
317
|
+
relationTo: 'articles'
|
|
318
|
+
}
|
|
319
|
+
]);
|
|
320
|
+
expect(result.count).toBe(3);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
160
323
|
it('combines every target into one fixed polymorphic document projection', ()=>{
|
|
161
324
|
const result = buildQuery({
|
|
162
325
|
path: 'content.'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/find/buildPolymorphicJoinQuery.spec.ts"],"sourcesContent":["import type { Client } from '@libsql/client'\nimport type { SQL } from 'drizzle-orm'\nimport type { Field, FlattenedJoinField, Where } from 'payload'\n\nimport { createClient } from '@libsql/client'\nimport { getTableName, like, notLike } from 'drizzle-orm'\nimport { drizzle } from 'drizzle-orm/libsql'\nimport { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'\nimport { flattenAllFields } from 'payload'\nimport toSnakeCase from 'to-snake-case'\nimport { afterAll, describe, expect, it } from 'vitest'\n\nimport type { DrizzleAdapter, GenericTable } from '../types.js'\n\nimport { operatorMap } from '../queries/operatorMap.js'\nimport { createJSONQuery } from '../sqlite/createJSONQuery/index.js'\nimport { buildPolymorphicJoinQuery } from './buildPolymorphicJoinQuery.js'\n\nconst parentsTable = sqliteTable('join_parents', {\n id: integer('id').primaryKey(),\n})\n\nconst articlesTable = sqliteTable('join_articles', {\n id: integer('id').primaryKey(),\n createdAt: text('created_at'),\n details_rank: integer('details_rank'),\n parent: integer('parent_id'),\n score: integer('score'),\n title: text('title'),\n})\n\nconst notesTable = sqliteTable('join_notes', {\n id: integer('id').primaryKey(),\n parent: integer('parent_id'),\n title: text('title'),\n})\n\nconst tableWithoutID = sqliteTable('join_without_id', {\n parent: integer('parent_id'),\n})\n\nconst tableWithoutParent = sqliteTable('join_without_parent', {\n id: integer('id').primaryKey(),\n})\n\nconst client: Client = createClient({ url: 'file::memory:' })\nconst db = drizzle(client, {\n schema: { articlesTable, notesTable, parentsTable, tableWithoutID, tableWithoutParent },\n})\n\ntype CollectionFixture = {\n fields: Field[]\n table: GenericTable\n}\n\nconst createAdapter = (fixtures: Record<string, CollectionFixture>): DrizzleAdapter => {\n const collections: Record<\n string,\n { config: { fields: Field[]; flattenedFields: ReturnType<typeof flattenAllFields> } }\n > = {}\n const tableNameMap = new Map<string, string>()\n const tables: Record<string, GenericTable> = {}\n\n for (const [slug, fixture] of Object.entries(fixtures)) {\n const tableName = getTableName(fixture.table)\n\n collections[slug] = {\n config: {\n fields: fixture.fields,\n flattenedFields: flattenAllFields({ fields: fixture.fields }),\n },\n }\n tableNameMap.set(toSnakeCase(slug), tableName)\n tables[tableName] = fixture.table\n }\n\n return {\n createJSONQuery,\n drizzle: db,\n idType: 'serial',\n name: 'sqlite',\n operatorHandlers: [],\n operators: {\n ...operatorMap,\n contains: like,\n like,\n not_like: notLike,\n },\n payload: { collections },\n tableNameMap,\n tables,\n } as unknown as DrizzleAdapter\n}\n\nconst adapter = createAdapter({\n articles: {\n fields: [\n { name: 'createdAt', type: 'date' },\n {\n name: 'details',\n type: 'group',\n fields: [{ name: 'rank', type: 'number' }],\n },\n { name: 'parent', relationTo: 'join-parents', type: 'relationship' },\n { name: 'score', type: 'number' },\n { name: 'title', type: 'text' },\n ],\n table: articlesTable,\n },\n notes: {\n fields: [\n { name: 'parent', relationTo: 'join-parents', type: 'relationship' },\n { name: 'title', type: 'text' },\n ],\n table: notesTable,\n },\n})\n\nconst joinField = {\n collection: ['articles', 'notes'],\n name: 'children',\n on: 'parent',\n type: 'join',\n} as unknown as FlattenedJoinField\n\nconst buildQuery = ({\n adapter: adapterArg = adapter,\n field = joinField,\n limit = 0,\n page,\n path = '',\n shouldCount = false,\n sort,\n where,\n}: {\n adapter?: DrizzleAdapter\n field?: FlattenedJoinField\n limit?: number\n page?: number\n path?: string\n shouldCount?: boolean\n sort?: string | string[]\n where?: Where\n} = {}) =>\n buildPolymorphicJoinQuery({\n adapter: adapterArg,\n currentTableName: getTableName(parentsTable),\n field,\n limit,\n page,\n path,\n shouldCount,\n sort,\n where,\n })\n\nconst renderQuery = (query: ReturnType<typeof buildPolymorphicJoinQuery>) => {\n const selection: Record<string, SQL.Aliased> = { documents: query.documents }\n\n if (query.count) {\n selection.count = query.count\n }\n\n return db.select(selection).from(parentsTable).toSQL()\n}\n\nafterAll(() => client.close())\n\ndescribe('buildPolymorphicJoinQuery', () => {\n it('combines every target into one fixed polymorphic document projection', () => {\n const result = buildQuery({ path: 'content.' })\n const query = renderQuery(result)\n\n expect(result.columnName).toBe('content_children')\n expect(result.count).toBeUndefined()\n expect(query.sql).toContain('union all')\n expect(query.sql).toContain('select \"id\"')\n expect(query.sql).toContain('from \"join_articles\" union all')\n expect(query.sql).toContain('from \"join_notes\"')\n expect(query.sql).toContain('as \"parent\"')\n expect(query.sql).toContain('as \"relationTo\"')\n expect(query.sql).toContain(\"json_object('id',\")\n expect(query.sql).toContain(\"'relationTo',\")\n expect(query.params).toContain('articles')\n expect(query.params).toContain('notes')\n })\n\n it('sorts by createdAt descending by default when one target has timestamps', () => {\n const query = renderQuery(buildQuery())\n\n expect(query.sql).toContain('\"created_at\" as \"sortPath\" from \"join_articles\"')\n expect(query.sql).toContain('? as \"sortPath\" from \"join_notes\"')\n expect(query.sql).toContain('order by \"sortPath\" desc')\n expect(query.params).toContain(null)\n })\n\n it('uses id ascending by default when no target has a createdAt field', () => {\n const adapterWithoutTimestamps = createAdapter({\n articles: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: articlesTable,\n },\n notes: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: notesTable,\n },\n })\n const query = renderQuery(buildQuery({ adapter: adapterWithoutTimestamps }))\n\n expect(query.sql).toContain('\"id\" as \"sortPath\" from \"join_articles\"')\n expect(query.sql).toContain('\"id\" as \"sortPath\" from \"join_notes\"')\n expect(query.sql).toContain('order by \"sortPath\" asc')\n })\n\n it('supports an explicit ascending nested sort and substitutes null when it is absent', () => {\n const query = renderQuery(buildQuery({ sort: 'details.rank' }))\n\n expect(query.sql).toContain('\"details_rank\" as \"sortPath\" from \"join_articles\"')\n expect(query.sql).toContain('? as \"sortPath\" from \"join_notes\"')\n expect(query.sql).toContain('order by \"sortPath\" asc')\n expect(query.params).toContain(null)\n })\n\n it('applies the shared where clause independently to each target branch', () => {\n const query = renderQuery(\n buildQuery({\n where: {\n AND: [{ title: { equals: 'available' } }, { relationTo: { equals: 'articles' } }],\n },\n }),\n )\n\n expect(query.sql.match(/\"title\" = \\?/g)).toHaveLength(2)\n expect(query.sql).toContain('? = ?')\n expect(query.params.filter((value) => value === 'available')).toHaveLength(2)\n expect(query.params).toContain('articles')\n expect(query.params).toContain('notes')\n })\n\n it('adds a correlated count only when requested', () => {\n const result = buildQuery({ shouldCount: true })\n const query = renderQuery(result)\n\n expect(result.count).toBeDefined()\n expect(query.sql).toContain('select count(*) from')\n expect(query.sql).toContain('\"join_parents\".\"id\" = \"children_subquery\".\"parent\"')\n })\n\n it('adds limit and page offset to the document query', () => {\n const query = renderQuery(buildQuery({ limit: 11, page: 3 }))\n\n expect(query.sql).toContain('LIMIT ? OFFSET ?')\n expect(query.params.slice(-2)).toEqual([11, 22])\n })\n\n it('does not add limit or offset when limit is zero', () => {\n const query = renderQuery(buildQuery({ limit: 0, page: 3 }))\n const normalizedSQL = query.sql.toLowerCase()\n\n expect(normalizedSQL).not.toContain(' limit ')\n expect(normalizedSQL).not.toContain(' offset ')\n })\n\n it('rejects a join field with a non-polymorphic collection', () => {\n const scalarJoinField = {\n ...joinField,\n collection: 'articles',\n } as unknown as FlattenedJoinField\n\n expect(() => buildQuery({ field: scalarJoinField })).toThrow(\n 'A polymorphic join requires a collection array',\n )\n })\n\n it('rejects a polymorphic join with no target collections', () => {\n const emptyJoinField = { ...joinField, collection: [] } as unknown as FlattenedJoinField\n\n expect(() => buildQuery({ field: emptyJoinField })).toThrow(\n 'A polymorphic join requires at least one collection',\n )\n })\n\n it('rejects multiple sort fields with a descriptive error', () => {\n expect(() => buildQuery({ sort: ['title', '-createdAt'] })).toThrow(\n 'Polymorphic joins do not support multiple sort fields',\n )\n })\n\n it('throws a descriptive error when a target collection is not configured', () => {\n const missingCollectionField = {\n ...joinField,\n collection: ['articles', 'missing'],\n } as unknown as FlattenedJoinField\n\n expect(() => buildQuery({ field: missingCollectionField })).toThrow(\n 'Unknown polymorphic join collection \"missing\"',\n )\n })\n\n it('throws a descriptive error when a configured collection has no database table', () => {\n const adapterWithoutTable = createAdapter({\n articles: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: articlesTable,\n },\n })\n\n adapterWithoutTable.tables = {}\n\n const singleCollectionField = {\n ...joinField,\n collection: ['articles'],\n } as unknown as FlattenedJoinField\n\n expect(() =>\n buildQuery({ adapter: adapterWithoutTable, field: singleCollectionField }),\n ).toThrow('Polymorphic join collection \"articles\" has no database table')\n })\n\n it.each([\n [\n 'id',\n createAdapter({\n articles: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: tableWithoutID,\n },\n }),\n ],\n [\n 'parent',\n createAdapter({\n articles: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: tableWithoutParent,\n },\n }),\n ],\n ] as const)('rejects a target whose table has no %s column', (column, adapterArg) => {\n const singleCollectionField = {\n ...joinField,\n collection: ['articles'],\n } as unknown as FlattenedJoinField\n\n expect(() => buildQuery({ adapter: adapterArg, field: singleCollectionField })).toThrow(\n `Polymorphic join collection \"articles\" has no \"${column}\" column`,\n )\n })\n})\n"],"names":["createClient","getTableName","like","notLike","drizzle","integer","sqliteTable","text","flattenAllFields","toSnakeCase","afterAll","describe","expect","it","operatorMap","createJSONQuery","buildPolymorphicJoinQuery","parentsTable","id","primaryKey","articlesTable","createdAt","details_rank","parent","score","title","notesTable","tableWithoutID","tableWithoutParent","client","url","db","schema","createAdapter","fixtures","collections","tableNameMap","Map","tables","slug","fixture","Object","entries","tableName","table","config","fields","flattenedFields","set","idType","name","operatorHandlers","operators","contains","not_like","payload","adapter","articles","type","relationTo","notes","joinField","collection","on","buildQuery","adapterArg","field","limit","page","path","shouldCount","sort","where","currentTableName","renderQuery","query","selection","documents","count","select","from","toSQL","close","result","columnName","toBe","toBeUndefined","sql","toContain","params","adapterWithoutTimestamps","AND","equals","match","toHaveLength","filter","value","toBeDefined","slice","toEqual","normalizedSQL","toLowerCase","not","scalarJoinField","toThrow","emptyJoinField","missingCollectionField","adapterWithoutTable","singleCollectionField","each","column"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/find/buildPolymorphicJoinQuery.spec.ts"],"sourcesContent":["import type { Client } from '@libsql/client'\nimport type { SQL } from 'drizzle-orm'\nimport type { Field, FlattenedJoinField, Where } from 'payload'\n\nimport { createClient } from '@libsql/client'\nimport { getTableName, like, notLike } from 'drizzle-orm'\nimport { drizzle } from 'drizzle-orm/libsql'\nimport { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'\nimport { flattenAllFields } from 'payload'\nimport toSnakeCase from 'to-snake-case'\nimport { afterAll, beforeAll, describe, expect, it } from 'vitest'\n\nimport type { DrizzleAdapter, GenericTable } from '../types.js'\n\nimport { operatorMap } from '../queries/operatorMap.js'\nimport { createJSONQuery } from '../sqlite/createJSONQuery/index.js'\nimport { buildPolymorphicJoinQuery } from './buildPolymorphicJoinQuery.js'\n\nconst parentsTable = sqliteTable('join_parents', {\n id: integer('id').primaryKey(),\n})\n\nconst articlesTable = sqliteTable('join_articles', {\n id: integer('id').primaryKey(),\n createdAt: text('created_at'),\n details_rank: integer('details_rank'),\n parent: integer('parent_id'),\n score: integer('score'),\n title: text('title'),\n})\n\nconst articlesLocalesTable = sqliteTable('join_articles_locales', {\n _parentID: integer('_parent_id'),\n _locale: text('_locale'),\n _status: text('_status'),\n})\n\nconst notesTable = sqliteTable('join_notes', {\n id: integer('id').primaryKey(),\n parent: integer('parent_id'),\n title: text('title'),\n})\n\nconst tableWithoutID = sqliteTable('join_without_id', {\n parent: integer('parent_id'),\n})\n\nconst tableWithoutParent = sqliteTable('join_without_parent', {\n id: integer('id').primaryKey(),\n})\n\nconst client: Client = createClient({ url: 'file::memory:' })\nconst db = drizzle(client, {\n schema: { articlesTable, notesTable, parentsTable, tableWithoutID, tableWithoutParent },\n})\n\ntype CollectionFixture = {\n fields: Field[]\n table: GenericTable\n}\n\nconst createAdapter = (fixtures: Record<string, CollectionFixture>): DrizzleAdapter => {\n const collections: Record<\n string,\n { config: { fields: Field[]; flattenedFields: ReturnType<typeof flattenAllFields> } }\n > = {}\n const tableNameMap = new Map<string, string>()\n const tables: Record<string, GenericTable> = {}\n\n for (const [slug, fixture] of Object.entries(fixtures)) {\n const tableName = getTableName(fixture.table)\n\n collections[slug] = {\n config: {\n fields: fixture.fields,\n flattenedFields: flattenAllFields({ fields: fixture.fields }),\n },\n }\n tableNameMap.set(toSnakeCase(slug), tableName)\n tables[tableName] = fixture.table\n }\n\n return {\n createJSONQuery,\n drizzle: db,\n idType: 'serial',\n name: 'sqlite',\n operatorHandlers: [],\n operators: {\n ...operatorMap,\n contains: like,\n like,\n not_like: notLike,\n },\n payload: { collections },\n tableNameMap,\n tables,\n } as unknown as DrizzleAdapter\n}\n\nconst adapter = createAdapter({\n articles: {\n fields: [\n { name: 'createdAt', type: 'date' },\n {\n name: 'details',\n type: 'group',\n fields: [{ name: 'rank', type: 'number' }],\n },\n { name: 'parent', relationTo: 'join-parents', type: 'relationship' },\n { name: 'score', type: 'number' },\n { name: 'title', type: 'text' },\n ],\n table: articlesTable,\n },\n notes: {\n fields: [\n { name: 'parent', relationTo: 'join-parents', type: 'relationship' },\n { name: 'title', type: 'text' },\n ],\n table: notesTable,\n },\n})\n\nconst joinField = {\n collection: ['articles', 'notes'],\n name: 'children',\n on: 'parent',\n type: 'join',\n} as unknown as FlattenedJoinField\n\nconst buildQuery = ({\n adapter: adapterArg = adapter,\n field = joinField,\n limit = 0,\n locale,\n page,\n pageSize,\n path = '',\n shouldCount = false,\n sort,\n where,\n}: {\n adapter?: DrizzleAdapter\n field?: FlattenedJoinField\n limit?: number\n locale?: string\n page?: number\n pageSize?: number\n path?: string\n shouldCount?: boolean\n sort?: string | string[]\n where?: Where\n} = {}) =>\n buildPolymorphicJoinQuery({\n adapter: adapterArg,\n currentTableName: getTableName(parentsTable),\n field,\n limit,\n locale,\n page,\n pageSize,\n path,\n shouldCount,\n sort,\n where,\n })\n\nconst renderQuery = (query: ReturnType<typeof buildPolymorphicJoinQuery>) => {\n const selection: Record<string, SQL.Aliased> = { documents: query.documents }\n\n if (query.count) {\n selection.count = query.count\n }\n\n return db.select(selection).from(parentsTable).toSQL()\n}\n\nafterAll(() => client.close())\n\ndescribe('buildPolymorphicJoinQuery', () => {\n describe('localized filters', () => {\n const localizedAdapter = createAdapter({\n articles: {\n fields: [\n { name: 'parent', relationTo: 'join-parents', type: 'relationship' },\n { name: '_status', type: 'select', localized: true, options: ['draft', 'published'] },\n ],\n table: articlesTable,\n },\n notes: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: notesTable,\n },\n })\n\n localizedAdapter.localesSuffix = '_locales'\n localizedAdapter.tables.join_articles_locales = articlesLocalesTable\n\n beforeAll(async () => {\n await client.executeMultiple(`\n CREATE TABLE join_parents (id INTEGER PRIMARY KEY);\n CREATE TABLE join_articles (\n id INTEGER PRIMARY KEY, parent_id INTEGER, created_at TEXT,\n details_rank INTEGER, score INTEGER, title TEXT\n );\n CREATE TABLE join_notes (id INTEGER PRIMARY KEY, parent_id INTEGER, title TEXT);\n CREATE TABLE join_articles_locales (_parent_id INTEGER, _locale TEXT, _status TEXT);\n INSERT INTO join_parents VALUES (1);\n INSERT INTO join_articles (id, parent_id) VALUES (1, 1), (2, 1), (3, 1);\n INSERT INTO join_notes (id, parent_id) VALUES (4, 1);\n INSERT INTO join_articles_locales VALUES\n (1, 'en', 'published'), (1, 'fr', 'draft'),\n (2, 'en', 'draft'), (2, 'fr', 'published'),\n (3, 'en', 'published'), (3, 'fr', 'published');\n `)\n })\n\n it.each([\n { locale: 'en', ids: [1, 3] },\n { locale: 'fr', ids: [2, 3] },\n ])('should filter published documents in locale $locale', async ({ locale, ids }) => {\n const query = buildQuery({\n adapter: localizedAdapter,\n locale,\n shouldCount: true,\n sort: 'id',\n where: { _status: { equals: 'published' } },\n })\n const [result] = await db\n .select({ documents: query.documents, count: query.count! })\n .from(parentsTable)\n\n expect(JSON.parse(result.documents as string)).toEqual(\n ids.map((id) => ({ id, relationTo: 'articles' })),\n )\n expect(result.count).toBe(2)\n })\n\n it.each(['all', undefined])(\n 'should count matching documents once across locales with locale %s',\n async (locale) => {\n const query = buildQuery({\n adapter: localizedAdapter,\n locale,\n shouldCount: true,\n sort: 'id',\n where: { _status: { equals: 'published' } },\n })\n const [result] = await db\n .select({ documents: query.documents, count: query.count! })\n .from(parentsTable)\n\n expect(JSON.parse(result.documents as string)).toEqual([\n { id: 1, relationTo: 'articles' },\n { id: 2, relationTo: 'articles' },\n { id: 3, relationTo: 'articles' },\n ])\n expect(result.count).toBe(3)\n },\n )\n\n it('should paginate distinct documents using the page size before the look-ahead row', async () => {\n const query = buildQuery({\n adapter: localizedAdapter,\n limit: 2,\n locale: 'all',\n page: 2,\n pageSize: 1,\n shouldCount: true,\n sort: 'id',\n where: { _status: { equals: 'published' } },\n })\n const [result] = await db\n .select({ documents: query.documents, count: query.count! })\n .from(parentsTable)\n\n expect(JSON.parse(result.documents as string)).toEqual([\n { id: 2, relationTo: 'articles' },\n { id: 3, relationTo: 'articles' },\n ])\n expect(result.count).toBe(3)\n })\n })\n\n it('combines every target into one fixed polymorphic document projection', () => {\n const result = buildQuery({ path: 'content.' })\n const query = renderQuery(result)\n\n expect(result.columnName).toBe('content_children')\n expect(result.count).toBeUndefined()\n expect(query.sql).toContain('union all')\n expect(query.sql).toContain('select \"id\"')\n expect(query.sql).toContain('from \"join_articles\" union all')\n expect(query.sql).toContain('from \"join_notes\"')\n expect(query.sql).toContain('as \"parent\"')\n expect(query.sql).toContain('as \"relationTo\"')\n expect(query.sql).toContain(\"json_object('id',\")\n expect(query.sql).toContain(\"'relationTo',\")\n expect(query.params).toContain('articles')\n expect(query.params).toContain('notes')\n })\n\n it('sorts by createdAt descending by default when one target has timestamps', () => {\n const query = renderQuery(buildQuery())\n\n expect(query.sql).toContain('\"created_at\" as \"sortPath\" from \"join_articles\"')\n expect(query.sql).toContain('? as \"sortPath\" from \"join_notes\"')\n expect(query.sql).toContain('order by \"sortPath\" desc')\n expect(query.params).toContain(null)\n })\n\n it('uses id ascending by default when no target has a createdAt field', () => {\n const adapterWithoutTimestamps = createAdapter({\n articles: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: articlesTable,\n },\n notes: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: notesTable,\n },\n })\n const query = renderQuery(buildQuery({ adapter: adapterWithoutTimestamps }))\n\n expect(query.sql).toContain('\"id\" as \"sortPath\" from \"join_articles\"')\n expect(query.sql).toContain('\"id\" as \"sortPath\" from \"join_notes\"')\n expect(query.sql).toContain('order by \"sortPath\" asc')\n })\n\n it('supports an explicit ascending nested sort and substitutes null when it is absent', () => {\n const query = renderQuery(buildQuery({ sort: 'details.rank' }))\n\n expect(query.sql).toContain('\"details_rank\" as \"sortPath\" from \"join_articles\"')\n expect(query.sql).toContain('? as \"sortPath\" from \"join_notes\"')\n expect(query.sql).toContain('order by \"sortPath\" asc')\n expect(query.params).toContain(null)\n })\n\n it('applies the shared where clause independently to each target branch', () => {\n const query = renderQuery(\n buildQuery({\n where: {\n AND: [{ title: { equals: 'available' } }, { relationTo: { equals: 'articles' } }],\n },\n }),\n )\n\n expect(query.sql.match(/\"title\" = \\?/g)).toHaveLength(2)\n expect(query.sql).toContain('? = ?')\n expect(query.params.filter((value) => value === 'available')).toHaveLength(2)\n expect(query.params).toContain('articles')\n expect(query.params).toContain('notes')\n })\n\n it('adds a correlated count only when requested', () => {\n const result = buildQuery({ shouldCount: true })\n const query = renderQuery(result)\n\n expect(result.count).toBeDefined()\n expect(query.sql).toContain('select count(*) from')\n expect(query.sql).toContain('\"join_parents\".\"id\" = \"children_subquery\".\"parent\"')\n })\n\n it('adds limit and page offset to the document query', () => {\n const query = renderQuery(buildQuery({ limit: 11, page: 3 }))\n\n expect(query.sql).toContain('LIMIT ? OFFSET ?')\n expect(query.params.slice(-2)).toEqual([11, 22])\n })\n\n it('does not add limit or offset when limit is zero', () => {\n const query = renderQuery(buildQuery({ limit: 0, page: 3 }))\n const normalizedSQL = query.sql.toLowerCase()\n\n expect(normalizedSQL).not.toContain(' limit ')\n expect(normalizedSQL).not.toContain(' offset ')\n })\n\n it('rejects a join field with a non-polymorphic collection', () => {\n const scalarJoinField = {\n ...joinField,\n collection: 'articles',\n } as unknown as FlattenedJoinField\n\n expect(() => buildQuery({ field: scalarJoinField })).toThrow(\n 'A polymorphic join requires a collection array',\n )\n })\n\n it('rejects a polymorphic join with no target collections', () => {\n const emptyJoinField = { ...joinField, collection: [] } as unknown as FlattenedJoinField\n\n expect(() => buildQuery({ field: emptyJoinField })).toThrow(\n 'A polymorphic join requires at least one collection',\n )\n })\n\n it('rejects multiple sort fields with a descriptive error', () => {\n expect(() => buildQuery({ sort: ['title', '-createdAt'] })).toThrow(\n 'Polymorphic joins do not support multiple sort fields',\n )\n })\n\n it('throws a descriptive error when a target collection is not configured', () => {\n const missingCollectionField = {\n ...joinField,\n collection: ['articles', 'missing'],\n } as unknown as FlattenedJoinField\n\n expect(() => buildQuery({ field: missingCollectionField })).toThrow(\n 'Unknown polymorphic join collection \"missing\"',\n )\n })\n\n it('throws a descriptive error when a configured collection has no database table', () => {\n const adapterWithoutTable = createAdapter({\n articles: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: articlesTable,\n },\n })\n\n adapterWithoutTable.tables = {}\n\n const singleCollectionField = {\n ...joinField,\n collection: ['articles'],\n } as unknown as FlattenedJoinField\n\n expect(() =>\n buildQuery({ adapter: adapterWithoutTable, field: singleCollectionField }),\n ).toThrow('Polymorphic join collection \"articles\" has no database table')\n })\n\n it.each([\n [\n 'id',\n createAdapter({\n articles: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: tableWithoutID,\n },\n }),\n ],\n [\n 'parent',\n createAdapter({\n articles: {\n fields: [{ name: 'parent', relationTo: 'join-parents', type: 'relationship' }],\n table: tableWithoutParent,\n },\n }),\n ],\n ] as const)('rejects a target whose table has no %s column', (column, adapterArg) => {\n const singleCollectionField = {\n ...joinField,\n collection: ['articles'],\n } as unknown as FlattenedJoinField\n\n expect(() => buildQuery({ adapter: adapterArg, field: singleCollectionField })).toThrow(\n `Polymorphic join collection \"articles\" has no \"${column}\" column`,\n )\n })\n})\n"],"names":["createClient","getTableName","like","notLike","drizzle","integer","sqliteTable","text","flattenAllFields","toSnakeCase","afterAll","beforeAll","describe","expect","it","operatorMap","createJSONQuery","buildPolymorphicJoinQuery","parentsTable","id","primaryKey","articlesTable","createdAt","details_rank","parent","score","title","articlesLocalesTable","_parentID","_locale","_status","notesTable","tableWithoutID","tableWithoutParent","client","url","db","schema","createAdapter","fixtures","collections","tableNameMap","Map","tables","slug","fixture","Object","entries","tableName","table","config","fields","flattenedFields","set","idType","name","operatorHandlers","operators","contains","not_like","payload","adapter","articles","type","relationTo","notes","joinField","collection","on","buildQuery","adapterArg","field","limit","locale","page","pageSize","path","shouldCount","sort","where","currentTableName","renderQuery","query","selection","documents","count","select","from","toSQL","close","localizedAdapter","localized","options","localesSuffix","join_articles_locales","executeMultiple","each","ids","equals","result","JSON","parse","toEqual","map","toBe","undefined","columnName","toBeUndefined","sql","toContain","params","adapterWithoutTimestamps","AND","match","toHaveLength","filter","value","toBeDefined","slice","normalizedSQL","toLowerCase","not","scalarJoinField","toThrow","emptyJoinField","missingCollectionField","adapterWithoutTable","singleCollectionField","column"],"mappings":"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"}
|
|
@@ -237,9 +237,14 @@ const resolveWherePath = ({ adapter, collection, schemaPath, table, wherePlan })
|
|
|
237
237
|
pathPlan
|
|
238
238
|
};
|
|
239
239
|
}
|
|
240
|
+
let column = sql`null`;
|
|
241
|
+
if (fieldContext) {
|
|
242
|
+
const fieldTable = fieldContext.isLocalized ? adapter.tables[`${getTableName(table)}${adapter.localesSuffix}`] : table;
|
|
243
|
+
column = fieldTable[pathPlan.columnPath];
|
|
244
|
+
}
|
|
240
245
|
return {
|
|
241
246
|
type: 'scalar',
|
|
242
|
-
column
|
|
247
|
+
column,
|
|
243
248
|
pathPlan,
|
|
244
249
|
queryValueContext
|
|
245
250
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/find/buildPolymorphicJoinWhere.ts"],"sourcesContent":["import type { Column, SQL } from 'drizzle-orm'\n\nimport { and, getTableName, isNotNull, isNull, or, sql } from 'drizzle-orm'\nimport { type FlattenedField, QueryError, type Where } from 'payload'\nimport toSnakeCase from 'to-snake-case'\n\nimport type { DrizzleAdapter, GenericTable } from '../types.js'\nimport type {\n PolymorphicJoinWherePlan,\n ScalarWhereField,\n WherePathPlan,\n} from './createPolymorphicJoinWherePlan.js'\n\nimport { sanitizeQueryValue } from '../queries/sanitizeQueryValue.js'\n\nconst supportedJSONQueryOperators = new Set(['contains', 'equals', 'exists', 'in', 'like'])\n\ntype BuildPolymorphicJoinWhereArgs = {\n adapter: DrizzleAdapter\n collection: string\n table: GenericTable\n where: Where\n wherePlan: PolymorphicJoinWherePlan\n}\n\ntype ResolvedWherePath =\n | {\n column: Column\n pathPlan: WherePathPlan\n queryValueContext: ScalarWhereField\n type: 'scalar'\n }\n | {\n fieldContext: FlattenedField\n jsonExpression: string\n pathPlan: WherePathPlan\n type: 'hasManySelect'\n }\n | {\n pathPlan: WherePathPlan\n type: 'invalid'\n }\n\n/**\n * Builds a where clause for one collection before the polymorphic branches are combined. A field\n * that is absent from this collection resolves to SQL NULL, and relationTo resolves to the current\n * collection slug.\n */\nexport const buildPolymorphicJoinWhere = ({\n adapter,\n collection,\n table,\n where,\n wherePlan,\n}: BuildPolymorphicJoinWhereArgs): SQL | undefined => {\n const constraints: SQL[] = []\n\n for (const key in where) {\n if (['AND', 'OR'].includes(key.toUpperCase())) {\n if (!Array.isArray(where[key])) {\n throw new QueryError([{ path: key }])\n }\n\n const combine = key.toUpperCase() === 'AND' ? and : or\n const nestedConstraints = where[key].map((nestedWhere) =>\n buildPolymorphicJoinWhere({\n adapter,\n collection,\n table,\n where: nestedWhere,\n wherePlan,\n }),\n )\n const nestedCondition = combine(...nestedConstraints)\n\n if (nestedCondition) {\n constraints.push(nestedCondition)\n }\n\n continue\n }\n\n const resolvedPath = resolveWherePath({\n adapter,\n collection,\n schemaPath: key,\n table,\n wherePlan,\n })\n\n for (let payloadOperator of Object.keys(where[key])) {\n const originalOperator = payloadOperator\n let value = where[key][payloadOperator]\n\n if (resolvedPath.type === 'invalid') {\n throw new QueryError([{ path: `${key}.${payloadOperator}` }])\n }\n\n if (resolvedPath.type === 'hasManySelect') {\n if (!supportedJSONQueryOperators.has(payloadOperator)) {\n throw new QueryError([{ path: `${key}.${payloadOperator}` }])\n }\n\n const sanitizedQueryValue = sanitizeQueryValue({\n adapter,\n field: resolvedPath.fieldContext,\n isUUID: false,\n operator: payloadOperator,\n relationOrPath: key,\n val: value,\n })\n\n if (sanitizedQueryValue === null || sanitizedQueryValue.columns) {\n throw new QueryError([{ path: `${key}.${originalOperator}` }])\n }\n\n value = sanitizedQueryValue.value\n\n if (payloadOperator === 'in' && Array.isArray(value) && value.length === 0) {\n constraints.push(sql.raw('false'))\n continue\n }\n\n const jsonQueryOperator =\n payloadOperator === 'exists' ? 'exists' : sanitizedQueryValue.operator\n\n constraints.push(\n sql.raw(\n adapter.createJSONQuery({\n column: resolvedPath.jsonExpression,\n operator: jsonQueryOperator,\n pathSegments: [resolvedPath.pathPlan.columnPath],\n value,\n }),\n ),\n )\n continue\n }\n\n if (payloadOperator === '$raw') {\n if (typeof value !== 'string') {\n throw new QueryError([{ path: `${key}.${payloadOperator}` }])\n }\n\n constraints.push(sql.raw(value))\n continue\n }\n\n const { column, queryValueContext } = resolvedPath\n\n if (\n payloadOperator === 'like' &&\n (queryValueContext.field.type === 'number' ||\n queryValueContext.field.type === 'relationship' ||\n queryValueContext.field.type === 'upload' ||\n queryValueContext.isUUID)\n ) {\n payloadOperator = 'equals'\n }\n\n const sanitizedQueryValue = sanitizeQueryValue({\n adapter,\n field: queryValueContext.field,\n isUUID: queryValueContext.isUUID,\n operator: payloadOperator,\n relationOrPath: key,\n val: value,\n })\n\n if (sanitizedQueryValue === null || sanitizedQueryValue.columns) {\n throw new QueryError([{ path: `${key}.${originalOperator}` }])\n }\n\n payloadOperator = sanitizedQueryValue.operator\n value = sanitizedQueryValue.value\n\n if (!(payloadOperator in adapter.operators)) {\n throw new QueryError([{ path: `${key}.${originalOperator}` }])\n }\n\n const operator = adapter.operators[payloadOperator as keyof typeof adapter.operators]\n\n if (originalOperator === 'equals' && value === null) {\n constraints.push(isNull(column))\n continue\n }\n\n if (originalOperator === 'not_equals') {\n if (value === null) {\n constraints.push(isNotNull(column))\n } else {\n const notEqualsConstraint = or(isNull(column), operator(column, value))\n\n if (notEqualsConstraint) {\n constraints.push(notEqualsConstraint)\n }\n }\n continue\n }\n\n if (originalOperator === 'in' && Array.isArray(value) && value.includes(null)) {\n const nonNullValues = value.filter((item) => item !== null)\n const inConstraint = nonNullValues.length ? operator(column, nonNullValues) : undefined\n const nullAwareInConstraint = inConstraint\n ? or(isNull(column), inConstraint)\n : isNull(column)\n\n if (nullAwareInConstraint) {\n constraints.push(nullAwareInConstraint)\n }\n continue\n }\n\n if (payloadOperator === 'like' && typeof value === 'string') {\n const wordConstraints = value.split(' ').map((word) => operator(column, `%${word}%`))\n const wordCondition = and(...wordConstraints)\n\n if (wordCondition) {\n constraints.push(wordCondition)\n }\n continue\n }\n\n constraints.push(operator(column, value))\n }\n }\n\n return and(...constraints)\n}\n\nconst resolveWherePath = ({\n adapter,\n collection,\n schemaPath,\n table,\n wherePlan,\n}: {\n schemaPath: string\n} & Omit<BuildPolymorphicJoinWhereArgs, 'where'>): ResolvedWherePath => {\n const pathPlan = wherePlan.get(schemaPath)\n\n if (!pathPlan) {\n throw new QueryError([{ path: schemaPath }])\n }\n\n if (pathPlan.type === 'invalid') {\n return { type: 'invalid', pathPlan }\n }\n\n if (schemaPath === 'relationTo') {\n return {\n type: 'scalar',\n column: sql`${collection}` as unknown as Column,\n pathPlan,\n queryValueContext: {\n type: 'scalar',\n field: { name: 'relationTo', type: 'text' },\n isUUID: false,\n },\n }\n }\n\n if (pathPlan.type === 'hasManySelect') {\n const fieldContext = [...pathPlan.fieldsByCollection.values()].find(\n (field) => field.type === 'hasManySelect',\n )?.field\n\n if (!fieldContext) {\n return { type: 'invalid', pathPlan }\n }\n\n return {\n type: 'hasManySelect',\n fieldContext,\n jsonExpression: getHasManySelectExpression({\n adapter,\n collection,\n pathPlan,\n table,\n }),\n pathPlan,\n }\n }\n\n const collectionField = pathPlan.fieldsByCollection.get(collection)\n const fieldContext = collectionField?.type === 'scalar' ? collectionField : undefined\n const queryValueContext =\n fieldContext ??\n [...pathPlan.fieldsByCollection.values()].find(\n (field): field is ScalarWhereField => field.type === 'scalar',\n )\n\n if (!queryValueContext) {\n return { type: 'invalid', pathPlan }\n }\n\n return {\n type: 'scalar',\n column: fieldContext ? table[pathPlan.columnPath] : (sql`null` as unknown as Column),\n pathPlan,\n queryValueContext,\n }\n}\n\nconst getHasManySelectExpression = ({\n adapter,\n collection,\n pathPlan,\n table,\n}: {\n adapter: DrizzleAdapter\n collection: string\n pathPlan: WherePathPlan\n table: GenericTable\n}): string => {\n if (pathPlan.fieldsByCollection.get(collection)?.type !== 'hasManySelect') {\n return adapter.name === 'postgres' ? `'[]'::jsonb` : `'[]'`\n }\n\n const selectTablePath = pathPlan.schemaPath\n .split('.')\n .map((pathSegment) => toSnakeCase(pathSegment))\n .join('_')\n const valuesTableName = adapter.tableNameMap.get(`${toSnakeCase(collection)}_${selectTablePath}`)\n\n if (!valuesTableName) {\n throw new Error(\n `Polymorphic join collection \"${collection}\" has no value table for \"${pathPlan.schemaPath}\"`,\n )\n }\n\n let qualifiedValuesTableName = valuesTableName\n let parentTableName = getTableName(table)\n\n if (adapter.schemaName) {\n qualifiedValuesTableName = `\"${adapter.schemaName}\".\"${valuesTableName}\"`\n parentTableName = `\"${adapter.schemaName}\".\"${parentTableName}\"`\n }\n\n if (adapter.name === 'postgres') {\n return `(select coalesce(jsonb_agg(${qualifiedValuesTableName}.value), '[]'::jsonb) from ${qualifiedValuesTableName} where ${qualifiedValuesTableName}.parent_id = ${parentTableName}.id)`\n }\n\n return `(select json_group_array(${qualifiedValuesTableName}.value) from ${qualifiedValuesTableName} where ${qualifiedValuesTableName}.parent_id = ${parentTableName}.id)`\n}\n"],"names":["and","getTableName","isNotNull","isNull","or","sql","QueryError","toSnakeCase","sanitizeQueryValue","supportedJSONQueryOperators","Set","buildPolymorphicJoinWhere","adapter","collection","table","where","wherePlan","constraints","key","includes","toUpperCase","Array","isArray","path","combine","nestedConstraints","map","nestedWhere","nestedCondition","push","resolvedPath","resolveWherePath","schemaPath","payloadOperator","Object","keys","originalOperator","value","type","has","sanitizedQueryValue","field","fieldContext","isUUID","operator","relationOrPath","val","columns","length","raw","jsonQueryOperator","createJSONQuery","column","jsonExpression","pathSegments","pathPlan","columnPath","queryValueContext","operators","notEqualsConstraint","nonNullValues","filter","item","inConstraint","undefined","nullAwareInConstraint","wordConstraints","split","word","wordCondition","get","name","fieldsByCollection","values","find","getHasManySelectExpression","collectionField","selectTablePath","pathSegment","join","valuesTableName","tableNameMap","Error","qualifiedValuesTableName","parentTableName","schemaName"],"mappings":"AAEA,SAASA,GAAG,EAAEC,YAAY,EAAEC,SAAS,EAAEC,MAAM,EAAEC,EAAE,EAAEC,GAAG,QAAQ,cAAa;AAC3E,SAA8BC,UAAU,QAAoB,UAAS;AACrE,OAAOC,iBAAiB,gBAAe;AASvC,SAASC,kBAAkB,QAAQ,mCAAkC;AAErE,MAAMC,8BAA8B,IAAIC,IAAI;IAAC;IAAY;IAAU;IAAU;IAAM;CAAO;AA4B1F;;;;CAIC,GACD,OAAO,MAAMC,4BAA4B,CAAC,EACxCC,OAAO,EACPC,UAAU,EACVC,KAAK,EACLC,KAAK,EACLC,SAAS,EACqB;IAC9B,MAAMC,cAAqB,EAAE;IAE7B,IAAK,MAAMC,OAAOH,MAAO;QACvB,IAAI;YAAC;YAAO;SAAK,CAACI,QAAQ,CAACD,IAAIE,WAAW,KAAK;YAC7C,IAAI,CAACC,MAAMC,OAAO,CAACP,KAAK,CAACG,IAAI,GAAG;gBAC9B,MAAM,IAAIZ,WAAW;oBAAC;wBAAEiB,MAAML;oBAAI;iBAAE;YACtC;YAEA,MAAMM,UAAUN,IAAIE,WAAW,OAAO,QAAQpB,MAAMI;YACpD,MAAMqB,oBAAoBV,KAAK,CAACG,IAAI,CAACQ,GAAG,CAAC,CAACC,cACxChB,0BAA0B;oBACxBC;oBACAC;oBACAC;oBACAC,OAAOY;oBACPX;gBACF;YAEF,MAAMY,kBAAkBJ,WAAWC;YAEnC,IAAIG,iBAAiB;gBACnBX,YAAYY,IAAI,CAACD;YACnB;YAEA;QACF;QAEA,MAAME,eAAeC,iBAAiB;YACpCnB;YACAC;YACAmB,YAAYd;YACZJ;YACAE;QACF;QAEA,KAAK,IAAIiB,mBAAmBC,OAAOC,IAAI,CAACpB,KAAK,CAACG,IAAI,EAAG;YACnD,MAAMkB,mBAAmBH;YACzB,IAAII,QAAQtB,KAAK,CAACG,IAAI,CAACe,gBAAgB;YAEvC,IAAIH,aAAaQ,IAAI,KAAK,WAAW;gBACnC,MAAM,IAAIhC,WAAW;oBAAC;wBAAEiB,MAAM,GAAGL,IAAI,CAAC,EAAEe,iBAAiB;oBAAC;iBAAE;YAC9D;YAEA,IAAIH,aAAaQ,IAAI,KAAK,iBAAiB;gBACzC,IAAI,CAAC7B,4BAA4B8B,GAAG,CAACN,kBAAkB;oBACrD,MAAM,IAAI3B,WAAW;wBAAC;4BAAEiB,MAAM,GAAGL,IAAI,CAAC,EAAEe,iBAAiB;wBAAC;qBAAE;gBAC9D;gBAEA,MAAMO,sBAAsBhC,mBAAmB;oBAC7CI;oBACA6B,OAAOX,aAAaY,YAAY;oBAChCC,QAAQ;oBACRC,UAAUX;oBACVY,gBAAgB3B;oBAChB4B,KAAKT;gBACP;gBAEA,IAAIG,wBAAwB,QAAQA,oBAAoBO,OAAO,EAAE;oBAC/D,MAAM,IAAIzC,WAAW;wBAAC;4BAAEiB,MAAM,GAAGL,IAAI,CAAC,EAAEkB,kBAAkB;wBAAC;qBAAE;gBAC/D;gBAEAC,QAAQG,oBAAoBH,KAAK;gBAEjC,IAAIJ,oBAAoB,QAAQZ,MAAMC,OAAO,CAACe,UAAUA,MAAMW,MAAM,KAAK,GAAG;oBAC1E/B,YAAYY,IAAI,CAACxB,IAAI4C,GAAG,CAAC;oBACzB;gBACF;gBAEA,MAAMC,oBACJjB,oBAAoB,WAAW,WAAWO,oBAAoBI,QAAQ;gBAExE3B,YAAYY,IAAI,CACdxB,IAAI4C,GAAG,CACLrC,QAAQuC,eAAe,CAAC;oBACtBC,QAAQtB,aAAauB,cAAc;oBACnCT,UAAUM;oBACVI,cAAc;wBAACxB,aAAayB,QAAQ,CAACC,UAAU;qBAAC;oBAChDnB;gBACF;gBAGJ;YACF;YAEA,IAAIJ,oBAAoB,QAAQ;gBAC9B,IAAI,OAAOI,UAAU,UAAU;oBAC7B,MAAM,IAAI/B,WAAW;wBAAC;4BAAEiB,MAAM,GAAGL,IAAI,CAAC,EAAEe,iBAAiB;wBAAC;qBAAE;gBAC9D;gBAEAhB,YAAYY,IAAI,CAACxB,IAAI4C,GAAG,CAACZ;gBACzB;YACF;YAEA,MAAM,EAAEe,MAAM,EAAEK,iBAAiB,EAAE,GAAG3B;YAEtC,IACEG,oBAAoB,UACnBwB,CAAAA,kBAAkBhB,KAAK,CAACH,IAAI,KAAK,YAChCmB,kBAAkBhB,KAAK,CAACH,IAAI,KAAK,kBACjCmB,kBAAkBhB,KAAK,CAACH,IAAI,KAAK,YACjCmB,kBAAkBd,MAAM,AAAD,GACzB;gBACAV,kBAAkB;YACpB;YAEA,MAAMO,sBAAsBhC,mBAAmB;gBAC7CI;gBACA6B,OAAOgB,kBAAkBhB,KAAK;gBAC9BE,QAAQc,kBAAkBd,MAAM;gBAChCC,UAAUX;gBACVY,gBAAgB3B;gBAChB4B,KAAKT;YACP;YAEA,IAAIG,wBAAwB,QAAQA,oBAAoBO,OAAO,EAAE;gBAC/D,MAAM,IAAIzC,WAAW;oBAAC;wBAAEiB,MAAM,GAAGL,IAAI,CAAC,EAAEkB,kBAAkB;oBAAC;iBAAE;YAC/D;YAEAH,kBAAkBO,oBAAoBI,QAAQ;YAC9CP,QAAQG,oBAAoBH,KAAK;YAEjC,IAAI,CAAEJ,CAAAA,mBAAmBrB,QAAQ8C,SAAS,AAAD,GAAI;gBAC3C,MAAM,IAAIpD,WAAW;oBAAC;wBAAEiB,MAAM,GAAGL,IAAI,CAAC,EAAEkB,kBAAkB;oBAAC;iBAAE;YAC/D;YAEA,MAAMQ,WAAWhC,QAAQ8C,SAAS,CAACzB,gBAAkD;YAErF,IAAIG,qBAAqB,YAAYC,UAAU,MAAM;gBACnDpB,YAAYY,IAAI,CAAC1B,OAAOiD;gBACxB;YACF;YAEA,IAAIhB,qBAAqB,cAAc;gBACrC,IAAIC,UAAU,MAAM;oBAClBpB,YAAYY,IAAI,CAAC3B,UAAUkD;gBAC7B,OAAO;oBACL,MAAMO,sBAAsBvD,GAAGD,OAAOiD,SAASR,SAASQ,QAAQf;oBAEhE,IAAIsB,qBAAqB;wBACvB1C,YAAYY,IAAI,CAAC8B;oBACnB;gBACF;gBACA;YACF;YAEA,IAAIvB,qBAAqB,QAAQf,MAAMC,OAAO,CAACe,UAAUA,MAAMlB,QAAQ,CAAC,OAAO;gBAC7E,MAAMyC,gBAAgBvB,MAAMwB,MAAM,CAAC,CAACC,OAASA,SAAS;gBACtD,MAAMC,eAAeH,cAAcZ,MAAM,GAAGJ,SAASQ,QAAQQ,iBAAiBI;gBAC9E,MAAMC,wBAAwBF,eAC1B3D,GAAGD,OAAOiD,SAASW,gBACnB5D,OAAOiD;gBAEX,IAAIa,uBAAuB;oBACzBhD,YAAYY,IAAI,CAACoC;gBACnB;gBACA;YACF;YAEA,IAAIhC,oBAAoB,UAAU,OAAOI,UAAU,UAAU;gBAC3D,MAAM6B,kBAAkB7B,MAAM8B,KAAK,CAAC,KAAKzC,GAAG,CAAC,CAAC0C,OAASxB,SAASQ,QAAQ,CAAC,CAAC,EAAEgB,KAAK,CAAC,CAAC;gBACnF,MAAMC,gBAAgBrE,OAAOkE;gBAE7B,IAAIG,eAAe;oBACjBpD,YAAYY,IAAI,CAACwC;gBACnB;gBACA;YACF;YAEApD,YAAYY,IAAI,CAACe,SAASQ,QAAQf;QACpC;IACF;IAEA,OAAOrC,OAAOiB;AAChB,EAAC;AAED,MAAMc,mBAAmB,CAAC,EACxBnB,OAAO,EACPC,UAAU,EACVmB,UAAU,EACVlB,KAAK,EACLE,SAAS,EAGqC;IAC9C,MAAMuC,WAAWvC,UAAUsD,GAAG,CAACtC;IAE/B,IAAI,CAACuB,UAAU;QACb,MAAM,IAAIjD,WAAW;YAAC;gBAAEiB,MAAMS;YAAW;SAAE;IAC7C;IAEA,IAAIuB,SAASjB,IAAI,KAAK,WAAW;QAC/B,OAAO;YAAEA,MAAM;YAAWiB;QAAS;IACrC;IAEA,IAAIvB,eAAe,cAAc;QAC/B,OAAO;YACLM,MAAM;YACNc,QAAQ/C,GAAG,CAAC,EAAEQ,WAAW,CAAC;YAC1B0C;YACAE,mBAAmB;gBACjBnB,MAAM;gBACNG,OAAO;oBAAE8B,MAAM;oBAAcjC,MAAM;gBAAO;gBAC1CK,QAAQ;YACV;QACF;IACF;IAEA,IAAIY,SAASjB,IAAI,KAAK,iBAAiB;QACrC,MAAMI,eAAe;eAAIa,SAASiB,kBAAkB,CAACC,MAAM;SAAG,CAACC,IAAI,CACjE,CAACjC,QAAUA,MAAMH,IAAI,KAAK,kBACzBG;QAEH,IAAI,CAACC,cAAc;YACjB,OAAO;gBAAEJ,MAAM;gBAAWiB;YAAS;QACrC;QAEA,OAAO;YACLjB,MAAM;YACNI;YACAW,gBAAgBsB,2BAA2B;gBACzC/D;gBACAC;gBACA0C;gBACAzC;YACF;YACAyC;QACF;IACF;IAEA,MAAMqB,kBAAkBrB,SAASiB,kBAAkB,CAACF,GAAG,CAACzD;IACxD,MAAM6B,eAAekC,iBAAiBtC,SAAS,WAAWsC,kBAAkBZ;IAC5E,MAAMP,oBACJf,gBACA;WAAIa,SAASiB,kBAAkB,CAACC,MAAM;KAAG,CAACC,IAAI,CAC5C,CAACjC,QAAqCA,MAAMH,IAAI,KAAK;IAGzD,IAAI,CAACmB,mBAAmB;QACtB,OAAO;YAAEnB,MAAM;YAAWiB;QAAS;IACrC;IAEA,OAAO;QACLjB,MAAM;QACNc,QAAQV,eAAe5B,KAAK,CAACyC,SAASC,UAAU,CAAC,GAAInD,GAAG,CAAC,IAAI,CAAC;QAC9DkD;QACAE;IACF;AACF;AAEA,MAAMkB,6BAA6B,CAAC,EAClC/D,OAAO,EACPC,UAAU,EACV0C,QAAQ,EACRzC,KAAK,EAMN;IACC,IAAIyC,SAASiB,kBAAkB,CAACF,GAAG,CAACzD,aAAayB,SAAS,iBAAiB;QACzE,OAAO1B,QAAQ2D,IAAI,KAAK,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7D;IAEA,MAAMM,kBAAkBtB,SAASvB,UAAU,CACxCmC,KAAK,CAAC,KACNzC,GAAG,CAAC,CAACoD,cAAgBvE,YAAYuE,cACjCC,IAAI,CAAC;IACR,MAAMC,kBAAkBpE,QAAQqE,YAAY,CAACX,GAAG,CAAC,GAAG/D,YAAYM,YAAY,CAAC,EAAEgE,iBAAiB;IAEhG,IAAI,CAACG,iBAAiB;QACpB,MAAM,IAAIE,MACR,CAAC,6BAA6B,EAAErE,WAAW,0BAA0B,EAAE0C,SAASvB,UAAU,CAAC,CAAC,CAAC;IAEjG;IAEA,IAAImD,2BAA2BH;IAC/B,IAAII,kBAAkBnF,aAAaa;IAEnC,IAAIF,QAAQyE,UAAU,EAAE;QACtBF,2BAA2B,CAAC,CAAC,EAAEvE,QAAQyE,UAAU,CAAC,GAAG,EAAEL,gBAAgB,CAAC,CAAC;QACzEI,kBAAkB,CAAC,CAAC,EAAExE,QAAQyE,UAAU,CAAC,GAAG,EAAED,gBAAgB,CAAC,CAAC;IAClE;IAEA,IAAIxE,QAAQ2D,IAAI,KAAK,YAAY;QAC/B,OAAO,CAAC,2BAA2B,EAAEY,yBAAyB,2BAA2B,EAAEA,yBAAyB,OAAO,EAAEA,yBAAyB,aAAa,EAAEC,gBAAgB,IAAI,CAAC;IAC5L;IAEA,OAAO,CAAC,yBAAyB,EAAED,yBAAyB,aAAa,EAAEA,yBAAyB,OAAO,EAAEA,yBAAyB,aAAa,EAAEC,gBAAgB,IAAI,CAAC;AAC5K"}
|
|
1
|
+
{"version":3,"sources":["../../src/find/buildPolymorphicJoinWhere.ts"],"sourcesContent":["import type { Column, SQL } from 'drizzle-orm'\n\nimport { and, getTableName, isNotNull, isNull, or, sql } from 'drizzle-orm'\nimport { type FlattenedField, QueryError, type Where } from 'payload'\nimport toSnakeCase from 'to-snake-case'\n\nimport type { DrizzleAdapter, GenericTable } from '../types.js'\nimport type {\n PolymorphicJoinWherePlan,\n ScalarWhereField,\n WherePathPlan,\n} from './createPolymorphicJoinWherePlan.js'\n\nimport { sanitizeQueryValue } from '../queries/sanitizeQueryValue.js'\n\nconst supportedJSONQueryOperators = new Set(['contains', 'equals', 'exists', 'in', 'like'])\n\ntype BuildPolymorphicJoinWhereArgs = {\n adapter: DrizzleAdapter\n collection: string\n table: GenericTable\n where: Where\n wherePlan: PolymorphicJoinWherePlan\n}\n\ntype ResolvedWherePath =\n | {\n column: Column\n pathPlan: WherePathPlan\n queryValueContext: ScalarWhereField\n type: 'scalar'\n }\n | {\n fieldContext: FlattenedField\n jsonExpression: string\n pathPlan: WherePathPlan\n type: 'hasManySelect'\n }\n | {\n pathPlan: WherePathPlan\n type: 'invalid'\n }\n\n/**\n * Builds a where clause for one collection before the polymorphic branches are combined. A field\n * that is absent from this collection resolves to SQL NULL, and relationTo resolves to the current\n * collection slug.\n */\nexport const buildPolymorphicJoinWhere = ({\n adapter,\n collection,\n table,\n where,\n wherePlan,\n}: BuildPolymorphicJoinWhereArgs): SQL | undefined => {\n const constraints: SQL[] = []\n\n for (const key in where) {\n if (['AND', 'OR'].includes(key.toUpperCase())) {\n if (!Array.isArray(where[key])) {\n throw new QueryError([{ path: key }])\n }\n\n const combine = key.toUpperCase() === 'AND' ? and : or\n const nestedConstraints = where[key].map((nestedWhere) =>\n buildPolymorphicJoinWhere({\n adapter,\n collection,\n table,\n where: nestedWhere,\n wherePlan,\n }),\n )\n const nestedCondition = combine(...nestedConstraints)\n\n if (nestedCondition) {\n constraints.push(nestedCondition)\n }\n\n continue\n }\n\n const resolvedPath = resolveWherePath({\n adapter,\n collection,\n schemaPath: key,\n table,\n wherePlan,\n })\n\n for (let payloadOperator of Object.keys(where[key])) {\n const originalOperator = payloadOperator\n let value = where[key][payloadOperator]\n\n if (resolvedPath.type === 'invalid') {\n throw new QueryError([{ path: `${key}.${payloadOperator}` }])\n }\n\n if (resolvedPath.type === 'hasManySelect') {\n if (!supportedJSONQueryOperators.has(payloadOperator)) {\n throw new QueryError([{ path: `${key}.${payloadOperator}` }])\n }\n\n const sanitizedQueryValue = sanitizeQueryValue({\n adapter,\n field: resolvedPath.fieldContext,\n isUUID: false,\n operator: payloadOperator,\n relationOrPath: key,\n val: value,\n })\n\n if (sanitizedQueryValue === null || sanitizedQueryValue.columns) {\n throw new QueryError([{ path: `${key}.${originalOperator}` }])\n }\n\n value = sanitizedQueryValue.value\n\n if (payloadOperator === 'in' && Array.isArray(value) && value.length === 0) {\n constraints.push(sql.raw('false'))\n continue\n }\n\n const jsonQueryOperator =\n payloadOperator === 'exists' ? 'exists' : sanitizedQueryValue.operator\n\n constraints.push(\n sql.raw(\n adapter.createJSONQuery({\n column: resolvedPath.jsonExpression,\n operator: jsonQueryOperator,\n pathSegments: [resolvedPath.pathPlan.columnPath],\n value,\n }),\n ),\n )\n continue\n }\n\n if (payloadOperator === '$raw') {\n if (typeof value !== 'string') {\n throw new QueryError([{ path: `${key}.${payloadOperator}` }])\n }\n\n constraints.push(sql.raw(value))\n continue\n }\n\n const { column, queryValueContext } = resolvedPath\n\n if (\n payloadOperator === 'like' &&\n (queryValueContext.field.type === 'number' ||\n queryValueContext.field.type === 'relationship' ||\n queryValueContext.field.type === 'upload' ||\n queryValueContext.isUUID)\n ) {\n payloadOperator = 'equals'\n }\n\n const sanitizedQueryValue = sanitizeQueryValue({\n adapter,\n field: queryValueContext.field,\n isUUID: queryValueContext.isUUID,\n operator: payloadOperator,\n relationOrPath: key,\n val: value,\n })\n\n if (sanitizedQueryValue === null || sanitizedQueryValue.columns) {\n throw new QueryError([{ path: `${key}.${originalOperator}` }])\n }\n\n payloadOperator = sanitizedQueryValue.operator\n value = sanitizedQueryValue.value\n\n if (!(payloadOperator in adapter.operators)) {\n throw new QueryError([{ path: `${key}.${originalOperator}` }])\n }\n\n const operator = adapter.operators[payloadOperator as keyof typeof adapter.operators]\n\n if (originalOperator === 'equals' && value === null) {\n constraints.push(isNull(column))\n continue\n }\n\n if (originalOperator === 'not_equals') {\n if (value === null) {\n constraints.push(isNotNull(column))\n } else {\n const notEqualsConstraint = or(isNull(column), operator(column, value))\n\n if (notEqualsConstraint) {\n constraints.push(notEqualsConstraint)\n }\n }\n continue\n }\n\n if (originalOperator === 'in' && Array.isArray(value) && value.includes(null)) {\n const nonNullValues = value.filter((item) => item !== null)\n const inConstraint = nonNullValues.length ? operator(column, nonNullValues) : undefined\n const nullAwareInConstraint = inConstraint\n ? or(isNull(column), inConstraint)\n : isNull(column)\n\n if (nullAwareInConstraint) {\n constraints.push(nullAwareInConstraint)\n }\n continue\n }\n\n if (payloadOperator === 'like' && typeof value === 'string') {\n const wordConstraints = value.split(' ').map((word) => operator(column, `%${word}%`))\n const wordCondition = and(...wordConstraints)\n\n if (wordCondition) {\n constraints.push(wordCondition)\n }\n continue\n }\n\n constraints.push(operator(column, value))\n }\n }\n\n return and(...constraints)\n}\n\nconst resolveWherePath = ({\n adapter,\n collection,\n schemaPath,\n table,\n wherePlan,\n}: {\n schemaPath: string\n} & Omit<BuildPolymorphicJoinWhereArgs, 'where'>): ResolvedWherePath => {\n const pathPlan = wherePlan.get(schemaPath)\n\n if (!pathPlan) {\n throw new QueryError([{ path: schemaPath }])\n }\n\n if (pathPlan.type === 'invalid') {\n return { type: 'invalid', pathPlan }\n }\n\n if (schemaPath === 'relationTo') {\n return {\n type: 'scalar',\n column: sql`${collection}` as unknown as Column,\n pathPlan,\n queryValueContext: {\n type: 'scalar',\n field: { name: 'relationTo', type: 'text' },\n isUUID: false,\n },\n }\n }\n\n if (pathPlan.type === 'hasManySelect') {\n const fieldContext = [...pathPlan.fieldsByCollection.values()].find(\n (field) => field.type === 'hasManySelect',\n )?.field\n\n if (!fieldContext) {\n return { type: 'invalid', pathPlan }\n }\n\n return {\n type: 'hasManySelect',\n fieldContext,\n jsonExpression: getHasManySelectExpression({\n adapter,\n collection,\n pathPlan,\n table,\n }),\n pathPlan,\n }\n }\n\n const collectionField = pathPlan.fieldsByCollection.get(collection)\n const fieldContext = collectionField?.type === 'scalar' ? collectionField : undefined\n const queryValueContext =\n fieldContext ??\n [...pathPlan.fieldsByCollection.values()].find(\n (field): field is ScalarWhereField => field.type === 'scalar',\n )\n\n if (!queryValueContext) {\n return { type: 'invalid', pathPlan }\n }\n\n let column = sql`null` as unknown as Column\n\n if (fieldContext) {\n const fieldTable = fieldContext.isLocalized\n ? adapter.tables[`${getTableName(table)}${adapter.localesSuffix}`]\n : table\n\n column = fieldTable[pathPlan.columnPath]\n }\n\n return {\n type: 'scalar',\n column,\n pathPlan,\n queryValueContext,\n }\n}\n\nconst getHasManySelectExpression = ({\n adapter,\n collection,\n pathPlan,\n table,\n}: {\n adapter: DrizzleAdapter\n collection: string\n pathPlan: WherePathPlan\n table: GenericTable\n}): string => {\n if (pathPlan.fieldsByCollection.get(collection)?.type !== 'hasManySelect') {\n return adapter.name === 'postgres' ? `'[]'::jsonb` : `'[]'`\n }\n\n const selectTablePath = pathPlan.schemaPath\n .split('.')\n .map((pathSegment) => toSnakeCase(pathSegment))\n .join('_')\n const valuesTableName = adapter.tableNameMap.get(`${toSnakeCase(collection)}_${selectTablePath}`)\n\n if (!valuesTableName) {\n throw new Error(\n `Polymorphic join collection \"${collection}\" has no value table for \"${pathPlan.schemaPath}\"`,\n )\n }\n\n let qualifiedValuesTableName = valuesTableName\n let parentTableName = getTableName(table)\n\n if (adapter.schemaName) {\n qualifiedValuesTableName = `\"${adapter.schemaName}\".\"${valuesTableName}\"`\n parentTableName = `\"${adapter.schemaName}\".\"${parentTableName}\"`\n }\n\n if (adapter.name === 'postgres') {\n return `(select coalesce(jsonb_agg(${qualifiedValuesTableName}.value), '[]'::jsonb) from ${qualifiedValuesTableName} where ${qualifiedValuesTableName}.parent_id = ${parentTableName}.id)`\n }\n\n return `(select json_group_array(${qualifiedValuesTableName}.value) from ${qualifiedValuesTableName} where ${qualifiedValuesTableName}.parent_id = ${parentTableName}.id)`\n}\n"],"names":["and","getTableName","isNotNull","isNull","or","sql","QueryError","toSnakeCase","sanitizeQueryValue","supportedJSONQueryOperators","Set","buildPolymorphicJoinWhere","adapter","collection","table","where","wherePlan","constraints","key","includes","toUpperCase","Array","isArray","path","combine","nestedConstraints","map","nestedWhere","nestedCondition","push","resolvedPath","resolveWherePath","schemaPath","payloadOperator","Object","keys","originalOperator","value","type","has","sanitizedQueryValue","field","fieldContext","isUUID","operator","relationOrPath","val","columns","length","raw","jsonQueryOperator","createJSONQuery","column","jsonExpression","pathSegments","pathPlan","columnPath","queryValueContext","operators","notEqualsConstraint","nonNullValues","filter","item","inConstraint","undefined","nullAwareInConstraint","wordConstraints","split","word","wordCondition","get","name","fieldsByCollection","values","find","getHasManySelectExpression","collectionField","fieldTable","isLocalized","tables","localesSuffix","selectTablePath","pathSegment","join","valuesTableName","tableNameMap","Error","qualifiedValuesTableName","parentTableName","schemaName"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { type FlattenedField, type Where } from 'payload';
|
|
|
2
2
|
import type { DrizzleAdapter } from '../types.js';
|
|
3
3
|
export type ScalarWhereField = {
|
|
4
4
|
field: FlattenedField;
|
|
5
|
+
isLocalized?: boolean;
|
|
5
6
|
isUUID: boolean;
|
|
6
7
|
type: 'scalar';
|
|
7
8
|
};
|
|
@@ -22,7 +23,7 @@ export type PolymorphicJoinWherePlan = Map<string, WherePathPlan>;
|
|
|
22
23
|
* whether the path uses a scalar column or a has-many select value table. A field may be absent
|
|
23
24
|
* from some target collections; those branches compare against SQL NULL or an empty JSON array.
|
|
24
25
|
*
|
|
25
|
-
* Paths are marked as invalid when their storage shapes conflict, require
|
|
26
|
+
* Paths are marked as invalid when their storage shapes conflict, require separate-row
|
|
26
27
|
* traversal, have no matching field, lack a required column, or collide after path flattening.
|
|
27
28
|
*
|
|
28
29
|
* @returns A plan keyed by each unique schema path in `where`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPolymorphicJoinWherePlan.d.ts","sourceRoot":"","sources":["../../src/find/createPolymorphicJoinWherePlan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAkB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,aAAa,CAAA;AAK/D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,cAAc,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAED,KAAK,oBAAoB,GAAG;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAAG,gBAAgB,CAAA;AAE/F,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;AAEjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,qCAIxC;IACD,OAAO,EAAE,cAAc,CAAA;IACvB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,KAAK,EAAE,KAAK,CAAA;CACb,KAAG,
|
|
1
|
+
{"version":3,"file":"createPolymorphicJoinWherePlan.d.ts","sourceRoot":"","sources":["../../src/find/createPolymorphicJoinWherePlan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAkB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,aAAa,CAAA;AAK/D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,cAAc,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAED,KAAK,oBAAoB,GAAG;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAAG,gBAAgB,CAAA;AAE/F,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;AAEjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,qCAIxC;IACD,OAAO,EAAE,cAAc,CAAA;IACvB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,KAAK,EAAE,KAAK,CAAA;CACb,KAAG,wBA0IH,CAAA"}
|