fix(db-postgres): handle select query on select fields (#9607)

Fixes https://github.com/payloadcms/payload/issues/9606

With Postgres / SQLite, select fields (non `hasMany: true`) weren't
properly handled in the `traverseFields.ts` function for `select` query.
This commit is contained in:
Sasha
2024-12-04 18:27:03 +02:00
committed by GitHub
parent 4a324a9de7
commit dff71eedaa
5 changed files with 177 additions and 8 deletions

View File

@@ -540,8 +540,7 @@ export const traverseFields = ({
} }
case 'select': { case 'select': {
if (field.hasMany) { if (select && !selectAllOnCurrentLevel) {
if (select) {
if ( if (
(selectMode === 'include' && !select[field.name]) || (selectMode === 'include' && !select[field.name]) ||
(selectMode === 'exclude' && select[field.name] === false) (selectMode === 'exclude' && select[field.name] === false)
@@ -550,6 +549,7 @@ export const traverseFields = ({
} }
} }
if (field.hasMany) {
const withSelect: Result = { const withSelect: Result = {
columns: { columns: {
id: false, id: false,
@@ -560,6 +560,17 @@ export const traverseFields = ({
} }
currentArgs.with[`${path}${field.name}`] = withSelect currentArgs.with[`${path}${field.name}`] = withSelect
break
}
if (select || selectAllOnCurrentLevel) {
const fieldPath = `${path}${field.name}`
if ((field.localized || withinLocalizedField) && _locales) {
_locales.columns[fieldPath] = true
} else if (adapter.tables[currentTableName]?.[fieldPath]) {
currentArgs.columns[fieldPath] = true
}
} }
break break

View File

@@ -16,6 +16,17 @@ export const LocalizedPostsCollection: CollectionConfig = {
localized: true, localized: true,
type: 'number', type: 'number',
}, },
{
name: 'select',
type: 'select',
options: ['a', 'b'],
},
{
name: 'selectMany',
type: 'select',
options: ['a', 'b'],
hasMany: true,
},
{ {
name: 'group', name: 'group',
localized: true, localized: true,

View File

@@ -14,6 +14,17 @@ export const PostsCollection: CollectionConfig = {
name: 'number', name: 'number',
type: 'number', type: 'number',
}, },
{
name: 'select',
type: 'select',
options: ['a', 'b'],
},
{
name: 'selectMany',
type: 'select',
options: ['a', 'b'],
hasMany: true,
},
{ {
name: 'group', name: 'group',
type: 'group', type: 'group',

View File

@@ -86,6 +86,36 @@ describe('Select', () => {
}) })
}) })
it('should select only select', async () => {
const res = await payload.findByID({
collection: 'posts',
id: postId,
select: {
select: true,
},
})
expect(res).toStrictEqual({
id: postId,
select: post.select,
})
})
it('should select only hasMany select', async () => {
const res = await payload.findByID({
collection: 'posts',
id: postId,
select: {
selectMany: true,
},
})
expect(res).toStrictEqual({
id: postId,
selectMany: post.selectMany,
})
})
it('should select number and text', async () => { it('should select number and text', async () => {
const res = await payload.findByID({ const res = await payload.findByID({
collection: 'posts', collection: 'posts',
@@ -367,6 +397,38 @@ describe('Select', () => {
expect(res).toStrictEqual(expected) expect(res).toStrictEqual(expected)
}) })
it('should exclude select', async () => {
const res = await payload.findByID({
collection: 'posts',
id: postId,
select: {
select: false,
},
})
const expected = { ...post }
delete expected['select']
expect(res).toStrictEqual(expected)
})
it('should exclude hasMany select', async () => {
const res = await payload.findByID({
collection: 'posts',
id: postId,
select: {
selectMany: false,
},
})
const expected = { ...post }
delete expected['selectMany']
expect(res).toStrictEqual(expected)
})
it('should exclude number and text', async () => { it('should exclude number and text', async () => {
const res = await payload.findByID({ const res = await payload.findByID({
collection: 'posts', collection: 'posts',
@@ -573,6 +635,36 @@ describe('Select', () => {
}) })
}) })
it('should select only select', async () => {
const res = await payload.findByID({
collection: 'localized-posts',
id: postId,
select: {
select: true,
},
})
expect(res).toStrictEqual({
id: postId,
select: post.select,
})
})
it('should select only hasMany select', async () => {
const res = await payload.findByID({
collection: 'localized-posts',
id: postId,
select: {
selectMany: true,
},
})
expect(res).toStrictEqual({
id: postId,
selectMany: post.selectMany,
})
})
it('should select number and text', async () => { it('should select number and text', async () => {
const res = await payload.findByID({ const res = await payload.findByID({
collection: 'localized-posts', collection: 'localized-posts',
@@ -877,6 +969,38 @@ describe('Select', () => {
expect(res).toStrictEqual(expected) expect(res).toStrictEqual(expected)
}) })
it('should exclude select', async () => {
const res = await payload.findByID({
collection: 'localized-posts',
id: postId,
select: {
select: false,
},
})
const expected = { ...post }
delete expected['select']
expect(res).toStrictEqual(expected)
})
it('should exclude hasMany select', async () => {
const res = await payload.findByID({
collection: 'localized-posts',
id: postId,
select: {
selectMany: false,
},
})
const expected = { ...post }
delete expected['selectMany']
expect(res).toStrictEqual(expected)
})
it('should exclude number and text', async () => { it('should exclude number and text', async () => {
const res = await payload.findByID({ const res = await payload.findByID({
collection: 'localized-posts', collection: 'localized-posts',
@@ -1963,6 +2087,8 @@ function createPost() {
data: { data: {
number: 1, number: 1,
text: 'text', text: 'text',
select: 'a',
selectMany: ['a'],
group: { group: {
number: 1, number: 1,
text: 'text', text: 'text',
@@ -2002,6 +2128,8 @@ function createLocalizedPost() {
data: { data: {
number: 1, number: 1,
text: 'text', text: 'text',
select: 'a',
selectMany: ['a'],
group: { group: {
number: 1, number: 1,
text: 'text', text: 'text',

View File

@@ -79,6 +79,8 @@ export interface Post {
id: string; id: string;
text?: string | null; text?: string | null;
number?: number | null; number?: number | null;
select?: ('a' | 'b') | null;
selectMany?: ('a' | 'b')[] | null;
group?: { group?: {
text?: string | null; text?: string | null;
number?: number | null; number?: number | null;
@@ -125,6 +127,8 @@ export interface LocalizedPost {
id: string; id: string;
text?: string | null; text?: string | null;
number?: number | null; number?: number | null;
select?: ('a' | 'b') | null;
selectMany?: ('a' | 'b')[] | null;
group?: { group?: {
text?: string | null; text?: string | null;
number?: number | null; number?: number | null;
@@ -424,6 +428,8 @@ export interface PayloadMigration {
export interface PostsSelect<T extends boolean = true> { export interface PostsSelect<T extends boolean = true> {
text?: T; text?: T;
number?: T; number?: T;
select?: T;
selectMany?: T;
group?: group?:
| T | T
| { | {
@@ -475,6 +481,8 @@ export interface PostsSelect<T extends boolean = true> {
export interface LocalizedPostsSelect<T extends boolean = true> { export interface LocalizedPostsSelect<T extends boolean = true> {
text?: T; text?: T;
number?: T; number?: T;
select?: T;
selectMany?: T;
group?: group?:
| T | T
| { | {