-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ISSUE]: Update failing when primary key is @PrimaryColumn instead of @PrimaryGeneratedColumn #529
Comments
another side effect is updating an entity that has a nested entity or a nested entity array that has PrimaryColumn as primary key also doesnt update them |
resolved |
re opening, update still failing, you can try the example of OneToOne in typeorm docs https://orkhan.gitbook.io/typeorm/docs/one-to-one-relations , if you try to update the profile, it always fails because its inserting the userId as null, also tried using params option in the update route, still fails |
hi, @chihabhajji Can you please check if the issue you have is the following?
if it is true, The currently implemented CRUD library is focused on You will be able to use it by separating endpoints per entity. CRUD for relation entities is features to will be implemented in the future. (like #419) I don't have an immediate need for this feature, but if someone contributes it, I'll include it. |
hello @jiho-kr , thank you for your swift responses as always. @Entity({
name: 'users',
schema: 'public',
})
export class User extends BaseEntity {
@Index({ unique: true })
@PrimaryColumn()
@IsString({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.PARAMS, GROUP.SEARCH] })
@IsOptional({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.SEARCH] })
username!: string;
@Index({ unique: true })
@Column()
@IsEmail(undefined, { groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.PARAMS, GROUP.SEARCH] })
@IsOptional({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.SEARCH] })
@ApiProperty({ type: String, description: 'Email of the user', format: 'email' })
email!: string;
@ApiHideProperty()
@Exclude()
@IsString({
groups: [GROUP.CREATE],
})
@IsOptional({ always: true })
@Column({
nullable: false,
})
password: string;
@IsEnum(ERole, { groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.PARAMS, GROUP.SEARCH] })
@IsOptional({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.SEARCH] })
@ApiProperty({ enum: ERole, description: 'Role of the user', type: String })
@Column({
type: 'enum',
enum: ERole,
default: ERole.USER,
nullable: false,
})
role: ERole;
@Type((_type) => Boolean)
@ApiProperty({ type: Boolean, description: 'Is the user active' })
@IsOptional({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.SEARCH] })
@IsOptional({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.SEARCH] })
@Column({
type: 'boolean',
default: true,
nullable: false,
})
isActive!: boolean;
@ValidateNested({ always: true })
@Type((_type) => UserProfile)
@Allow({
always: true,
})
@OneToOne((_type) => UserProfile, (profile) => profile.user, {
eager: true,
nullable: false,
cascade: true,
})
@JoinColumn()
profile: Relation<UserProfile>;
} @Entity({
name: 'user_profile',
schema: 'public',
})
export class UserProfile extends BaseEntity {
@IsOptional({ groups: [GROUP.READ_MANY, GROUP.UPSERT, GROUP.PARAMS, GROUP.SEARCH] })
@Allow({ always: true })
@ApiHideProperty()
@PrimaryColumn()
@OneToOne(() => User, (user) => user.profile)
user: string;
@IsOptional({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.SEARCH] })
@ApiProperty({ type: String, description: 'User avatar' })
@IsString({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.PARAMS, GROUP.SEARCH] })
@Column({ type: 'varchar', nullable: true, default: null })
avatar?: string;
@Column({ nullable: true, default: null })
@IsString({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.PARAMS, GROUP.SEARCH] })
@IsOptional({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.SEARCH] })
lastName?: string;
@Column({ nullable: true, default: null })
@IsString({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.PARAMS, GROUP.SEARCH] })
@IsOptional({ groups: [GROUP.CREATE, GROUP.UPDATE, GROUP.READ_MANY, GROUP.UPSERT, GROUP.SEARCH] })
firstName?: string;
constructor(partial: Partial<UserProfile>) {
super();
Object.assign(this, partial);
}
} @Crud({
entity: UserProfile,
routes: {
readMany: {
paginationType: 'offset',
numberOfTake: 10,
softDelete: false,
sort: 'ASC',
swagger: {
response: UserProfile,
},
relations: false,
},
readOne: {
params: ['user'] as (keyof UserProfile)[],
swagger: {
response: UserProfile,
},
},
update: {},
search: {
paginationType: 'offset',
numberOfTake: 10,
swagger: {
response: UserProfile,
},
},
},
only: [Method.READ_MANY, Method.READ_ONE, Method.UPDATE, Method.SEARCH],
})
@Controller('user-profile')
export class UserProfileController {
// noinspection JSUnusedLocalSymbols
constructor(private readonly crudService: UserProfileService) {}
} and when i try to edit a user-profile entity i get 409 error {
"query": "INSERT INTO \"public\".\"user_profile\"(\"user\", \"avatar\", \"last_name\", \"first_name\") VALUES (DEFAULT, $1, $2, $3) RETURNING \"avatar\", \"last_name\", \"first_name\"",
"parameters": [
"string",
"string",
"string"
],
"driverError": {
"length": 228,
"name": "error",
"severity": "ERROR",
"code": "23502",
"detail": "Failing row contains (null, string, string, string).",
"schema": "public",
"table": "user_profile",
"column": "user",
"file": "execMain.c",
"line": "2003",
"routine": "ExecConstraints"
},
"length": 228,
"severity": "ERROR",
"code": "23502",
"detail": "Failing row contains (null, string, string, string).",
"schema": "public",
"table": "user_profile",
"column": "user",
"file": "execMain.c",
"line": "2003",
"routine": "ExecConstraints"
} |
tried forcing the username by using this interceptor on the update class A implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler<any>) {
const r = context.switchToHttp().getRequest();
console.log(r.params.user);
if (r.params.user) {
r.body.user = r.params.user;
}
return next.handle();
}
} but got the following error: 422 {
"message": "Cannot changed value of primary key",
"error": "Unprocessable Entity",
"statusCode": 422
} |
Hello! In export class UserProfile extends BaseEntity {
@PrimaryColumn()
userProfileName: string;
@OneToOne(() => User, (user) => user.profile)
user: User;
} export class User extends BaseEntity {
@OneToOne((_type) => UserProfile, (profile) => profile.userProfileName)
@JoinColumn()
profile: Relation<UserProfile>;
} |
tried that i get the same error |
Is the custom interceptor disabled? |
yes, i disabled the interceptor, i can do a minimal reproduction repo if you want |
Yes, please share the modified code example again. |
Description:
When attempting to update an entity that has a PrimaryColumn decorator the update fails because it doesnt include the id of the entity in the mutation setting it to null. Tried using an interceptor to force the payload body to have he ID inferred from the path param but that resulted in a failed mutation too because it counted as a new insert that violates unique constraint.
Steps to Reproduce:
Define an entity with a PrimaryColumn primary key
Attempt to update
Expected Behavior:
Update successful and new entity returned.
Actual Behavior:
A 409 http error code exception is thrown that signals that the row's primary key is null
Screenshots:
Environment:
Database: Postgres SQL
Library Version: v0.12.0
Node version: v21.5.0
The text was updated successfully, but these errors were encountered: