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,16 +540,16 @@ export const traverseFields = ({
}
case 'select': {
if (field.hasMany) {
if (select) {
if (
(selectMode === 'include' && !select[field.name]) ||
(selectMode === 'exclude' && select[field.name] === false)
) {
break
}
if (select && !selectAllOnCurrentLevel) {
if (
(selectMode === 'include' && !select[field.name]) ||
(selectMode === 'exclude' && select[field.name] === false)
) {
break
}
}
if (field.hasMany) {
const withSelect: Result = {
columns: {
id: false,
@@ -560,6 +560,17 @@ export const traverseFields = ({
}
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

View File

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

View File

@@ -14,6 +14,17 @@ export const PostsCollection: CollectionConfig = {
name: 'number',
type: 'number',
},
{
name: 'select',
type: 'select',
options: ['a', 'b'],
},
{
name: 'selectMany',
type: 'select',
options: ['a', 'b'],
hasMany: true,
},
{
name: '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 () => {
const res = await payload.findByID({
collection: 'posts',
@@ -367,6 +397,38 @@ describe('Select', () => {
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 () => {
const res = await payload.findByID({
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 () => {
const res = await payload.findByID({
collection: 'localized-posts',
@@ -877,6 +969,38 @@ describe('Select', () => {
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 () => {
const res = await payload.findByID({
collection: 'localized-posts',
@@ -1963,6 +2087,8 @@ function createPost() {
data: {
number: 1,
text: 'text',
select: 'a',
selectMany: ['a'],
group: {
number: 1,
text: 'text',
@@ -2002,6 +2128,8 @@ function createLocalizedPost() {
data: {
number: 1,
text: 'text',
select: 'a',
selectMany: ['a'],
group: {
number: 1,
text: 'text',

View File

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