@Crud dynamic params and ManyToOne Relationships incorrect column mapping
Opened this issue · 0 comments
Hi everyone,
First of all, I'd like to extend my gratitude to the maintainers for your efforts in keeping this project both usable and up-to-date.
I'm encountering an issue when using the @Crud
controller's params
option, specifically when it involves ManyToOne
relationships. Below is a description of the problem and the technical context:
Dependencies:
"dependencies": {
"@dataui/crud": "^5.3.3",
"@dataui/crud-typeorm": "^5.3.3",
"@nestjs/common": "10.3.7",
"@nestjs/config": "3.2.2",
"@nestjs/core": "10.3.7",
"@nestjs/platform-express": "10.3.7",
"@nestjs/swagger": "7.3.1",
"@nestjs/typeorm": "10.0.2",
"class-transformer": "0.5.1",
"class-validator": "0.14.0",
"pg": "8.11.2",
"reflect-metadata": "0.1.13",
"typeorm": "0.3.20"
}
Relevant Code:
import { Crud, CrudController } from '@dataui/crud';
import { Controller } from '@nestjs/common';
import { ArticleService } from './article.service';
import { Article } from './entities/article.entity';
@Controller('/author/:authorId/article')
@Crud({
model: {
type: Article,
},
params: {
authorId: {
field: 'author',
type: 'number',
},
},
})
export class ArticleController implements CrudController<Article> {
constructor(public service: ArticleService) {}
}
import { Author } from 'src/author/entities/author.entity';
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Article {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToOne(() => Author, {
nullable: false,
})
author: Author;
}
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Author {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
}
Issue:
When I make a GET request to /author/1/article
, I encounter a 500 error with the following log:
error: error: column Article.authorId.id does not exist
ERROR [ExceptionsHandler] column Article.authorId.id does not exist
QueryFailedError: column Article.authorId.id does not exist
at PostgresQueryRunner.query (./api/src/driver/postgres/PostgresQueryRunner.ts:331:19)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at SelectQueryBuilder.loadRawResults (./api/src/query-builder/SelectQueryBuilder.ts:3805:25)
at SelectQueryBuilder.executeEntitiesAndRawResults (./api/src/query-builder/SelectQueryBuilder.ts:3551:26)
at SelectQueryBuilder.getRawAndEntities (./api/src/query-builder/SelectQueryBuilder.ts:1670:29)
at SelectQueryBuilder.getMany (./api/src/query-builder/SelectQueryBuilder.ts:1760:25)
The generated SQL query:
query failed: SELECT "Article"."id" AS "Article_id", "Article"."title" AS "Article_title", "Article"."authorId" FROM "article" "Article" WHERE ("Article"."authorId.id" = $1) -- PARAMETERS: [1]
Further Investigation:
I discovered that the TypeOrmCrudService
utilizes the getFieldWithAlias
function, potentially mishandling the mapping of properties to database columns. This function relies on entityColumnsHash
, which is initialized using TypeORM's column metadata in onInitMapEntityColumns. Intriguingly, TypeORM provides a databasePath = 'authorId.id'
, which doesn't seem correct.
Modifying the initialization line in the TypeOrmCrudService
to use databaseName
instead of databasePath
appears to solve the issue:
this.entityColumnsHash[prop.propertyName] = prop.databaseName;
Although this adjustment resolves the immediate problem, I'm uncertain if it's the correct fix, or if the underlying issue might be within TypeORM itself.
I would appreciate any help or comments