nestjs / typeorm

TypeORM module for Nest framework (node.js) 🍇

Home Page:https://nestjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Many to many relation is finding a column that doesn't exists

crisdegraciadev opened this issue · comments

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

I'm having a very extrange problem with TypeORM trying to implement a many to many relation. I have a entity user that looks like this.

@Entity("authUser")
export class AuthUserModel extends BaseModel {
    @Column({ unique: true })
    @ApiProperty()
    @IsNotEmpty()
    public username?: string;

    @Column({ unique: true })
    @ApiProperty()
    @IsNotEmpty()
    public email: string;

    @Column()
    @ApiProperty()
    public password: string;

    @ManyToMany(() => TenancyModel, tenancy => tenancy.authUsers)
    @JoinTable({
        name: "users_tenants",
        joinColumn: { name: "authUserId", referencedColumnName: "id" },
        inverseJoinColumn: { name: "tenancyId", referencedColumnName: "id" }
    })
    public authorizedTenants?: Array<TenancyModel>;

    @OneToMany(() => RefreshTokenModel, token => token.user)
    @ApiPropertyOptional({ isArray: true, type: () => String })
    public refreshTokens?: Array<string>;

    @ManyToOne(() => TeamRoleModel, role => role.users)
    @ApiProperty({ type: () => TeamRoleModel })
    @ApiPropertyOptional()
    public role?: TeamRoleModel;
}

As you can see, I have defined the many to many relation in the field authorized tenants as show, there is a conjuction table on my database which links authUserId and tenancyId to create the many to many relation.

The relation is bi-directional, so in tenant entity I have something like this.

@Entity("tenancy")
export class TenancyModel extends BaseModel {
    @Column({ unique: true })
    @ApiProperty()
    public companyId: string;

   // ...

    @ManyToMany(() => AuthUserModel, user => user.authorizedTenants)
    public authUsers?: Array<AuthUserModel>;
}

This is was it's described in TypeORM docs. The problem comes when loading the entity. It seems like it's able to load it, but in background it executes an strange update looking for a column that doesn't exist on the table.

The error shows when this code is executed

public getAuthUserByEmail(emailToFind: string): Promise<AuthUserModel> {
        return this.repo.findOne({
            where: { email: emailToFind },
            relations: ["authorizedTenants"]
        });
    }

and the error thrown is this

/home/cristian/Workspace/ipatia/api/node_modules/.pnpm/typeorm@0.2.30/src/error/QueryFailedError.ts:9
        super();
        ^
QueryFailedError: column "authUserId" of relation "authUser" does not exist
    at new QueryFailedError (/home/cristian/Workspace/ipatia/api/node_modules/.pnpm/typeorm@0.2.30/src/error/QueryFailedError.ts:9:9)
    at PostgresQueryRunner.<anonymous> (/home/cristian/Workspace/ipatia/api/node_modules/.pnpm/typeorm@0.2.30/src/driver/postgres/PostgresQueryRunner.ts:228:19)
    at step (/home/cristian/Workspace/ipatia/api/node_modules/.pnpm/tslib@1.14.1/node_modules/tslib/tslib.js:141:27)
    at Object.throw (/home/cristian/Workspace/ipatia/api/node_modules/.pnpm/tslib@1.14.1/node_modules/tslib/tslib.js:122:57)
    at rejected (/home/cristian/Workspace/ipatia/api/node_modules/.pnpm/tslib@1.14.1/node_modules/tslib/tslib.js:113:69)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

As I said, the entity loads, if I console.log the results of this query I get this

user: {
    id: 4,
    createdAt: 2022-02-08T17:47:05.201Z,
    updatedAt: 2023-06-20T14:43:00.444Z,
   ...
    authorizedTenants: [ [TenancyModel] ]
  }

But now, the rest of the repos are crashed and I can't query with them to load other related entitites.

My ORM logs are this when executing this query

[2023-08-31T08:26:49.601Z][QUERY]: SELECT DISTINCT "distinctAlias"."AuthUserModel_id" as "ids_AuthUserModel_id" FROM (SELECT "AuthUserModel"."id" AS "AuthUserModel_id", "AuthUserModel"."createdAt" AS "AuthUserModel_createdAt", "AuthUserModel"."updatedAt" AS "AuthUserModel_updatedAt", "AuthUserModel"."enabled" AS "AuthUserModel_enabled", "AuthUserModel"."username" AS "AuthUserModel_username", "AuthUserModel"."email" AS "AuthUserModel_email", "AuthUserModel"."password" AS "AuthUserModel_password", "AuthUserModel"."firstName" AS "AuthUserModel_firstName", "AuthUserModel"."lastName" AS "AuthUserModel_lastName", "AuthUserModel"."availableLoginAttemps" AS "AuthUserModel_availableLoginAttemps", "AuthUserModel"."invitationDate" AS "AuthUserModel_invitationDate", "AuthUserModel"."isActive" AS "AuthUserModel_isActive", "AuthUserModel"."roleId" AS "AuthUserModel_roleId", "AuthUserModel__authorizedTenants"."id" AS "AuthUserModel__authorizedTenants_id", "AuthUserModel__authorizedTenants"."createdAt" AS "AuthUserModel__authorizedTenants_createdAt", "AuthUserModel__authorizedTenants"."updatedAt" AS "AuthUserModel__authorizedTenants_updatedAt", "AuthUserModel__authorizedTenants"."enabled" AS "AuthUserModel__authorizedTenants_enabled", "AuthUserModel__authorizedTenants"."companyId" AS "AuthUserModel__authorizedTenants_companyId", "AuthUserModel__authorizedTenants"."licenseType" AS "AuthUserModel__authorizedTenants_licenseType", "AuthUserModel__authorizedTenants"."teamRootFolderLink" AS "AuthUserModel__authorizedTenants_teamRootFolderLink", "AuthUserModel__authorizedTenants"."usersLimit" AS "AuthUserModel__authorizedTenants_usersLimit", "AuthUserModel__authorizedTenants"."hasAccess" AS "AuthUserModel__authorizedTenants_hasAccess", "AuthUserModel__authorizedTenants"."customFieldNames" AS "AuthUserModel__authorizedTenants_customFieldNames" FROM "authUser" "AuthUserModel" LEFT JOIN "users_tenants" "AuthUserModel_AuthUserModel__authorizedTenants" ON "AuthUserModel_AuthUserModel__authorizedTenants"."authUserId"="AuthUserModel"."id" LEFT JOIN "tenancy" "AuthUserModel__authorizedTenants" ON "AuthUserModel__authorizedTenants"."id"="AuthUserModel_AuthUserModel__authorizedTenants"."tenancyId" WHERE "AuthUserModel"."email" = $1) "distinctAlias"  ORDER BY "AuthUserModel_id" ASC LIMIT 1 -- PARAMETERS: ["this is the email"]
[2023-08-31T08:26:49.604Z][QUERY]: SELECT "AuthUserModel"."id" AS "AuthUserModel_id", "AuthUserModel"."createdAt" AS "AuthUserModel_createdAt", "AuthUserModel"."updatedAt" AS "AuthUserModel_updatedAt", "AuthUserModel"."enabled" AS "AuthUserModel_enabled", "AuthUserModel"."username" AS "AuthUserModel_username", "AuthUserModel"."email" AS "AuthUserModel_email", "AuthUserModel"."password" AS "AuthUserModel_password", "AuthUserModel"."firstName" AS "AuthUserModel_firstName", "AuthUserModel"."lastName" AS "AuthUserModel_lastName", "AuthUserModel"."availableLoginAttemps" AS "AuthUserModel_availableLoginAttemps", "AuthUserModel"."invitationDate" AS "AuthUserModel_invitationDate", "AuthUserModel"."isActive" AS "AuthUserModel_isActive", "AuthUserModel"."roleId" AS "AuthUserModel_roleId", "AuthUserModel__authorizedTenants"."id" AS "AuthUserModel__authorizedTenants_id", "AuthUserModel__authorizedTenants"."createdAt" AS "AuthUserModel__authorizedTenants_createdAt", "AuthUserModel__authorizedTenants"."updatedAt" AS "AuthUserModel__authorizedTenants_updatedAt", "AuthUserModel__authorizedTenants"."enabled" AS "AuthUserModel__authorizedTenants_enabled", "AuthUserModel__authorizedTenants"."companyId" AS "AuthUserModel__authorizedTenants_companyId", "AuthUserModel__authorizedTenants"."licenseType" AS "AuthUserModel__authorizedTenants_licenseType", "AuthUserModel__authorizedTenants"."teamRootFolderLink" AS "AuthUserModel__authorizedTenants_teamRootFolderLink", "AuthUserModel__authorizedTenants"."usersLimit" AS "AuthUserModel__authorizedTenants_usersLimit", "AuthUserModel__authorizedTenants"."hasAccess" AS "AuthUserModel__authorizedTenants_hasAccess", "AuthUserModel__authorizedTenants"."customFieldNames" AS "AuthUserModel__authorizedTenants_customFieldNames" FROM "authUser" "AuthUserModel" LEFT JOIN "users_tenants" "AuthUserModel_AuthUserModel__authorizedTenants" ON "AuthUserModel_AuthUserModel__authorizedTenants"."authUserId"="AuthUserModel"."id" LEFT JOIN "tenancy" "AuthUserModel__authorizedTenants" ON "AuthUserModel__authorizedTenants"."id"="AuthUserModel_AuthUserModel__authorizedTenants"."tenancyId" WHERE ( "AuthUserModel"."email" = $1 ) AND ( "AuthUserModel"."id" IN (4) ) -- PARAMETERS: ["this is the email"]
[2023-08-31T08:26:49.618Z][QUERY]: UPDATE "authUser" SET "id" = $2, "createdAt" = $3, "updatedAt" = $4, "enabled" = $5, "username" = $6, "email" = $7, "password" = $8, "firstName" = $9, "lastName" = $10, "availableLoginAttemps" = $11, "invitationDate" = $12, "isActive" = $13, "authUserId" = $14 WHERE "id" = $1 -- PARAMETERS: [4,4,"2022-02-08T17:47:05.201Z","2023-06-20T14:43:00.444Z",1,"this is the name","this is the email","$this is  a pass","","",3,null,1,null]
[2023-08-31T08:26:49.619Z][FAILED QUERY]: UPDATE "authUser" SET "id" = $2, "createdAt" = $3, "updatedAt" = $4, "enabled" = $5, "username" = $6, "email" = $7, "password" = $8, "firstName" = $9, "lastName" = $10, "availableLoginAttemps" = $11, "invitationDate" = $12, "isActive" = $13, "authUserId" = $14 WHERE "id" = $1 -- PARAMETERS: [4,4,"2022-02-08T17:47:05.201Z","2023-06-20T14:43:00.444Z",1,"this is the name","this is the email","this is the pass","","",3,null,1,null]
[2023-08-31T08:26:49.619Z][QUERY ERROR]: error: column "authUserId" of relation "authUser" does not exist

I'm using nest 7 with typeorm 0.2.30.

Minimum reproduction code

.

Steps to reproduce

Just what shown above.

Expected behavior

Be able to load many to many relations correclty.

Package version

7.1.5

NestJS version

8.4.7

Node.js version

16.20.2

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Please, use our Discord channel (support) for such questions. We are using GitHub to track bugs, feature requests, and potential improvements.