Skip to content
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 ourterms of serviceand privacy statement.We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

database/gdb: postgresql Composite primary key for non-ID primary key LastInsertId() support #3675

Closed
thanatoskiraopened this issue Jul 4, 2024 · 1 comment

Comments

@thanatoskira
Copy link

Description

Cảnh tượng:

  • Cơ sở dữ liệu: Postgresql
  • Biểu kết cấu: Sử dụng không bao hàm ID(int64, auto_increment) mặt khác tự đoạn làm hợp lại chủ kiện, eg: (Name, ProjectId)
  • Liên hệ: ID đem làm ngoại kiện liên hệ sử dụng

Example:

_,err:=dao.Company.
OmitEmpty().
OnConflict(
dao.Company.Columns().Name,
dao.Company.Columns().ProjectId,
).
OnDuplicateEx(
dao.Company.Columns().Id,
dao.Company.Columns().Name,
dao.Company.Columns().ProjectId,
dao.Company.Columns().CreateTime,
).Save(companies)

Nhu cầu:

  • Yêu cầu sử dụng Save() tiến hành Upsert thao tác, cũng thu hoạch LastInsertId
  • Không hy vọng chọn dùng viết SQL RAW câu nói phương thức

Vấn đề:

  • Save() ở postgresql trung thực tế chấp hành vì INSERT INTO câu nói, Insert() thao tác sẽ tăng thêm RETURNING câu nói, nhưng Save() sẽ không
  • Insert() thao tác đối với không bao hàm ID int64 hợp lại chủ kiện cảnh tượng hạ, vô pháp thu hoạch LastInsertId() phản hồi giá trị, như trên thuật cảnh tượng đem chấp hành như sau câu nói:INSERT INTO... RETURNING "name",Ở chấp hành LastInsertId() khi đem phản hồiLastInsertId is not supported by primary key typeSai lầm

Lâm thời giải quyết phương án:

Từ như sau số hiệu trung có thể nhìn đến, có thể thông qua ở ctx trung phối trí internalPrimaryKeyInCtx giá trị tới khống chế RETURNING câu nói phản hồi tự đoạn

const(
internalPrimaryKeyInCtxgctx.StrKey="primary_key"
)
// Check if it is an insert operation with primary key.
ifvalue:=ctx.Value(internalPrimaryKeyInCtx);value!=nil{
varokbool
pkField,ok=value.(gdb.TableField)
if!ok{
isUseCoreDoExec=true
}
}else{
isUseCoreDoExec=true
}

// check if it is an insert operation.
if!isUseCoreDoExec&&pkField.Name!=""&&strings.Contains(sql,"INSERT INTO") {
primaryKey=pkField.Name
sql+=fmt.Sprintf(` RETURNING "%s" `,primaryKey)
}else{
// use default DoExec
returnd.Core.DoExec(ctx,link,sql,args...)
}

Như sau số hiệu triển lãm LastInsertId() thao tác yêu cầu RETURNING xxx trung tự đoạn yêu cầu vì int loại hình

affected:= len(out.Records)
if affected > 0 {
if!strings.Contains(pkField.Type, "int" ) {
return Result{
affected: int64(affected),
lastInsertId: 0,
lastInsertIdError: gerror.NewCodef(
gcode.CodeNotSupported,
"LastInsertId is not supported by primary key type: %s", pkField.Type),
}, nil
}
...

Bởi vậy sửa chữa vì như sau số hiệu sau nhưng bình thường thuyên chuyển LastInsertId():

result, err:= dao.Company.
Ctx(context.WithValue(ctx, consts.InternalPrimaryKeyInCtx, gdb.TableField{Name: "id", Type: "int64" })). // new add
OmitEmpty().
OnConflict(
dao.Company.Columns().Name,
dao.Company.Columns().ProjectId,
).
OnDuplicateEx(
dao.Company.Columns().Id,
dao.Company.Columns().Name,
dao.Company.Columns().ProjectId,
dao.Company.Columns().CreateTime,
).Save(companies)
if err!= nil {
return
}
id, err = result.LastInsertId()

Tổng kết:

  • Hay không có thể cung cấp tương quan tham số đối RETURNING tự đoạn tiến hành khống chế

Additional

No response

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


Description

Scenes:

  • Database: Postgresql
  • Table structure: Use other fields that do not contain ID(int64, auto_increment) as composite primary keys, eg: (Name, ProjectId)
  • Association: ID will be used as a foreign key association

Example:

_,err:=dao.Company.
OmitEmpty().
OnConflict(
dao.Company.Columns().Name,
dao.Company.Columns().ProjectId,
).
OnDuplicateEx(
dao.Company.Columns().Id,
dao.Company.Columns().Name,
dao.Company.Columns().ProjectId,
dao.Company.Columns().CreateTime,
).Save(companies)

need:

  • Need to use Save() to perform Upsert operation and obtain LastInsertId
  • Don’t want to write SQL RAW statements

question:

  • Save() is actually executed as an INSERT INTO statement in postgresql. The Insert() operation will add a RETURNING statement, but Save() will not
  • Insert() operation cannot obtain the return value of LastInsertId() in the scenario of composite primary key that does not contain ID int64. In the above scenario, the following statement will be executed:INSERT INTO... RETURNING "name",when executing LastInsertId() Will returnLastInsertId is not supported by primary key typeerror

Temporary solution:

As you can see from the following code, you can control the fields returned by the RETURNING statement by configuring the internalPrimaryKeyInCtx value in ctx

const(
internalPrimaryKeyInCtxgctx.StrKey="primary_key"
)
// Check if it is an insert operation with primary key.
ifvalue:=ctx.Value(internalPrimaryKeyInCtx);value!=nil{
varOKbool
pkField,ok=value.(gdb.TableField)
if!ok{
isUseCoreDoExec=true
}
}else{
isUseCoreDoExec=true
}

// check if it is an insert operation.
if!isUseCoreDoExec&&pkField.Name!=""&&strings.Contains(sql,"INSERT INTO") {
primaryKey=pkField.Name
sql+=fmt.Sprintf(` RETURNING "%s" `,primaryKey)
}else{
// use default DoExec
returnd.Core.DoExec(ctx,link,sql,args...)
}

The following code shows that the LastInsertId() operation requires RETURNING that the fields in xxx need to be of type int

affected:= len(out.Records)
if affected > 0 {
if!strings.Contains(pkField.Type, "int" ) {
return Result{
affected: int64(affected),
lastInsertId: 0,
lastInsertIdError: gerror.NewCodef(
gcode.CodeNotSupported,
"LastInsertId is not supported by primary key type: %s", pkField.Type),
}, nil
}
...

Therefore, after changing the code to the following, LastInsertId() can be called normally:

result, err:= dao.Company.
Ctx(context.WithValue(ctx, consts.InternalPrimaryKeyInCtx, gdb.TableField{Name: "id", Type: "int64" })). // new add
OmitEmpty().
OnConflict(
dao.Company.Columns().Name,
dao.Company.Columns().ProjectId,
).
OnDuplicateEx(
dao.Company.Columns().Id,
dao.Company.Columns().Name,
dao.Company.Columns().ProjectId,
dao.Company.Columns().CreateTime,
).Save(companies)
if err!= nil {
return
}
id, err = result.LastInsertId()

Summarize:

  • Whether relevant parameters can be provided to control the RETURNING field

Additional

No response

@Issues-translate-bot Issues-translate-bot changed the title database/gdb: postgresql phi ID chủ kiện hợp lại chủ kiện LastInsertId() duy trì database/gdb: postgresql Composite primary key for non-ID primary key LastInsertId() support Jul 4, 2024
@github-actions github-actions bot closed this asnot planned Won't fix, can't repro, duplicate, stale Aug 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants