gid-oss/dataui-nestjs-crud

@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.

image

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