TypeORM / MySQL - QueryFailedError: Unknown column 'NaN' in 'where clause'

Viewed 1039

I need help. I'm developing an API using Express and NodeJS with TypeScript, and I'm using TypeORM for database operations. I'm trying to create a function where I list and return all the appointments that were made by a specific user, but this error keeps happening and I don't know why. I have searched for an answer and read some StackOverflow questions and answers, but nothing worked, and that's why I decide to ask for help.

Exception has occurred: QueryFailedError: Unknown column 'NaN' in 'where clause' at QueryFailedError.TypeORMError [as constructor] (D:\Pessoal\Vinicius\TCC\hexperience-api\src\error\TypeORMError.ts:7:9) at new QueryFailedError (D:\Pessoal\Vinicius\TCC\hexperience-api\src\error\QueryFailedError.ts:9:9) at Query.onResult (D:\Pessoal\Vinicius\TCC\hexperience-api\src\driver\mysql\MysqlQueryRunner.ts:195:37) at Query.execute (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\commands\command.js:31:14) at PoolConnection.handlePacket (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\connection.js:456:32) at PacketParser.onPacket (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\connection.js:85:12) at PacketParser.executeStart (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\packet_parser.js:75:16) at Socket. (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\connection.js:92:25) at Socket.emit (events.js:315:20) at addChunk (internal/streams/readable.js:309:12) at readableAddChunk (internal/streams/readable.js:284:9) at Socket.Readable.push (internal/streams/readable.js:223:10) at TCP.onStreamRead (internal/stream_base_commons.js:188:23) at TCP.callbackTrampoline (internal/async_hooks.js:131:14)

Here is the code:

User.ts

import {Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, OneToOne} from 'typeorm';
import { Exclude } from 'class-transformer';

import Host from './Host';

export enum typeEnum {
  user = 'user',
  host = 'host',
  admin = 'admin'
}

@Entity('User')
class User {
  @PrimaryGeneratedColumn('increment')
  id: number;

  @Column()
  name: string;

  @Column()
  email: string;

  @Column()
  @Exclude()
  password: string;

  @Column()
  avatar: string;

  @Column()
  phone_number: string;

  @Column()
  bio: string;

  @Column({ type: 'boolean' })
  is_blocked: boolean;

  @Column({
    type: 'enum',
    enum: typeEnum,
    default: typeEnum.user
  })
  type: typeEnum;

  @CreateDateColumn()
  created_at: Date;

  @UpdateDateColumn()
  updated_at: Date;

  @OneToOne(type => Host, host => host.user)
  host: Host;
}

export default User;

Appointment.ts

import {Column,Entity,PrimaryGeneratedColumn,CreateDateColumn,UpdateDateColumn,ManyToOne,JoinColumn} from "typeorm";

import Schedule from "../../../../experiences/infra/typeorm/entities/Schedule";
import User from "../../../../users/infra/typeorm/entities/User";

@Entity('Appointment')
class Appointment {
  @PrimaryGeneratedColumn('increment')
  id: number;

  @Column()
  guests: number;

  @Column({ type: 'boolean' })
  paid: boolean;

  @Column({ type: 'decimal', precision: 12, scale: 2 })
  final_price: number;

  @CreateDateColumn()
  created_at: Date;

  @UpdateDateColumn()
  updated_at: Date;

  @ManyToOne(() => User)
  @JoinColumn({ name: 'user_id' })
  user: User;

  @ManyToOne(() => Schedule)
  @JoinColumn({ name: 'schedule_id' })
  schedule: Schedule;
}

export default Appointment;

AppointmentsRepository.ts

import { getRepository, Repository } from "typeorm";

import Appointment from "../entities/Appointment";

import IAppointmentsRepository from "@modules/appointments/repositories/IAppointmentsRepository";
import ICreateAppointmentDTO from "@modules/appointments/dtos/ICreateAppointmentDTO";

class AppointmentsRepository implements IAppointmentsRepository {
  private ormRepository: Repository<Appointment>;

  constructor () {
    this.ormRepository = getRepository(Appointment);
  }

  // this function has the same idea as the one that has the problem but this one works normally
  public async findByExperienceId(exp_id: number): Promise<Appointment[]> {
    const appointments = await this.ormRepository.find({
      relations: ['user', 'schedule', 'schedule.experience'],
      where: {
        schedule: {
          experience: {
            id: exp_id,
          }
        }
      }
    });

    return appointments
  }

  // here is the function with the problem
  public async findByUserId(user_id: number): Promise<Appointment[]> {
    // this was my last attempt to fix the problem, didn't work
    const appointments = await this.ormRepository.query(
      'SELECT * FROM Appointment a ' +
      'LEFT JOIN `User` u ON u.id  = a.user_id ' +
      'LEFT JOIN Schedule s ON s.id = a.schedule_id ' +
      'LEFT JOIN Experience e ON e.id = s.exp_id ' +
      'WHERE a.user_id = ' + Number(user_id)
    );
    // This was the original code
    // const appointments = await this.ormRepository.find({
    //   relations: ['user', 'schedule', 'schedule.experience'],
    //   where: {
    //     user: {
    //       id: user_id
    //     }
    //   }
    // });

    return appointments;
  }
}

export default AppointmentsRepository;

ListUserAppointmentsService.ts

import { inject, injectable } from "tsyringe";

import AppError from "@shared/errors/AppError";

import Appointment from "../infra/typeorm/entities/Appointment";

import IUsersRepository from "@modules/users/repositories/IUsersRepository";
import IAppointmentsRepository from "../repositories/IAppointmentsRepository";

interface IRequest {
  id: number
}

@injectable()
class ListUserAppointmentsService {
  constructor (
    @inject('UsersRepository')
    private usersRepository: IUsersRepository,

    @inject('AppointmentsRepository')
    private appointmentsRepository: IAppointmentsRepository
  ) {}

  public async execute({ id }: IRequest): Promise<Appointment[]> {
    const user = await this.usersRepository.findById(id);

    if (!user) {
      throw new AppError('User does not exists');
    }

    // originally, I was passing the parameter id
    const appointments = await this.appointmentsRepository.findByUserId(user.id);

    return appointments;
  }
}

export default ListUserAppointmentsService;
1 Answers

in nestjs i have this issue too,
it's my code

@Injectable()
export class NavSiteCategoryService {
 
this.navSiteCategoryRepository.createQueryBuilder('category')
'sites.name','sites.desc','sites.url'])

  constructor(
    @InjectRepository(NavSiteCategory)
    private navSiteCategoryRepository: Repository<NavSiteCategory>,
  ) {
  }

  async create(createNavSiteCategoryDto: CreateNavSiteCategoryDto) {
    const newCategory =  this.navSiteCategoryRepository.create(createNavSiteCategoryDto);
    return  await this.navSiteCategoryRepository.save(newCategory)
  }

  async findAll() {
    return this.navSiteCategoryRepository.createQueryBuilder('category')
      .select(["category.id","category.name","category.desc"])
      .leftJoinAndSelect("category.sites", "sites").getMany()
  }

  async categoryOptions() {
    return this.navSiteCategoryRepository.createQueryBuilder('option')
      .select(["option.id","option.name","option.desc"])
      .getMany()
  }

  async findOne(id: number) {
    return this.navSiteCategoryRepository.createQueryBuilder('category')
      .select(["category.id","category.name","category.desc"])
      .leftJoinAndSelect("category.sites", "sites")
      .where({id})
      .getOne()
  }

  async update(id: number, updateNavSiteCategoryDto: UpdateNavSiteCategoryDto) {
    await  this.navSiteCategoryRepository.update(id, updateNavSiteCategoryDto );
  }

  async remove(id: number) {
    await this.navSiteCategoryRepository.delete(id);
  }
}

when the findAll method in service will show success the categoryOptions methsd has error like you above description ,

i don't know reason, only difference at controller,
error code is (Note: @Get('/options') , @Get() )

    @ApiTags('站点分类')
@Controller('nav-site-category')
export class NavSiteCategoryController {
  constructor(
    @Inject(forwardRef(() => NavSiteCategoryService))
    private readonly navSiteCategoryService: NavSiteCategoryService
  ) { }
  @Get()
  findAll() {
    return this.navSiteCategoryService.findAll();
  }


  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.navSiteCategoryService.findOne(+id);
  }

  @Post()
  create(@Body() createNavSiteCategoryDto: CreateNavSiteCategoryDto) {
    return this.navSiteCategoryService.create(createNavSiteCategoryDto);
  }


  @Patch(':id')
  update(@Param('id') id: string, @Body() updateNavSiteCategoryDto: UpdateNavSiteCategoryDto) {
    return this.navSiteCategoryService.update(+id, updateNavSiteCategoryDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.navSiteCategoryService.remove(+id);
  }

  @Get('/options')
  options() {
    return this.navSiteCategoryService.categoryOptions()
  }

}

Solution is put the Options method at the top , the error fixed, I don't know why, wish it will help other people

succcess code:

@ApiTags('站点分类')
@Controller('nav-site-category')
export class NavSiteCategoryController {
  constructor(
    @Inject(forwardRef(() => NavSiteCategoryService))
    private readonly navSiteCategoryService: NavSiteCategoryService
  ) { }
  @Get()
  findAll() {
    return this.navSiteCategoryService.findAll();
  }

  @Get('/options')
  options() {
    return this.navSiteCategoryService.categoryOptions()
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.navSiteCategoryService.findOne(+id);
  }

  @Post()
  create(@Body() createNavSiteCategoryDto: CreateNavSiteCategoryDto) {
    return this.navSiteCategoryService.create(createNavSiteCategoryDto);
  }


  @Patch(':id')
  update(@Param('id') id: string, @Body() updateNavSiteCategoryDto: UpdateNavSiteCategoryDto) {
    return this.navSiteCategoryService.update(+id, updateNavSiteCategoryDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.navSiteCategoryService.remove(+id);
  }

}
Related