[chore] bump bun library versions (#2837)
This commit is contained in:
parent
6bb43f3f9b
commit
1018cde107
10
go.mod
10
go.mod
|
@ -56,10 +56,10 @@ require (
|
||||||
github.com/technologize/otel-go-contrib v1.1.1
|
github.com/technologize/otel-go-contrib v1.1.1
|
||||||
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
|
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
|
||||||
github.com/ulule/limiter/v3 v3.11.2
|
github.com/ulule/limiter/v3 v3.11.2
|
||||||
github.com/uptrace/bun v1.1.17
|
github.com/uptrace/bun v1.2.1
|
||||||
github.com/uptrace/bun/dialect/pgdialect v1.1.17
|
github.com/uptrace/bun/dialect/pgdialect v1.2.1
|
||||||
github.com/uptrace/bun/dialect/sqlitedialect v1.1.17
|
github.com/uptrace/bun/dialect/sqlitedialect v1.2.1
|
||||||
github.com/uptrace/bun/extra/bunotel v1.1.17
|
github.com/uptrace/bun/extra/bunotel v1.2.1
|
||||||
github.com/wagslane/go-password-validator v0.3.0
|
github.com/wagslane/go-password-validator v0.3.0
|
||||||
github.com/yuin/goldmark v1.7.1
|
github.com/yuin/goldmark v1.7.1
|
||||||
go.opentelemetry.io/otel v1.25.0
|
go.opentelemetry.io/otel v1.25.0
|
||||||
|
@ -201,7 +201,7 @@ require (
|
||||||
github.com/toqueteos/webbrowser v1.2.0 // indirect
|
github.com/toqueteos/webbrowser v1.2.0 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.3 // indirect
|
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.4 // indirect
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||||
|
|
20
go.sum
20
go.sum
|
@ -667,16 +667,16 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E
|
||||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/ulule/limiter/v3 v3.11.2 h1:P4yOrxoEMJbOTfRJR2OzjL90oflzYPPmWg+dvwN2tHA=
|
github.com/ulule/limiter/v3 v3.11.2 h1:P4yOrxoEMJbOTfRJR2OzjL90oflzYPPmWg+dvwN2tHA=
|
||||||
github.com/ulule/limiter/v3 v3.11.2/go.mod h1:QG5GnFOCV+k7lrL5Y8kgEeeflPH3+Cviqlqa8SVSQxI=
|
github.com/ulule/limiter/v3 v3.11.2/go.mod h1:QG5GnFOCV+k7lrL5Y8kgEeeflPH3+Cviqlqa8SVSQxI=
|
||||||
github.com/uptrace/bun v1.1.17 h1:qxBaEIo0hC/8O3O6GrMDKxqyT+mw5/s0Pn/n6xjyGIk=
|
github.com/uptrace/bun v1.2.1 h1:2ENAcfeCfaY5+2e7z5pXrzFKy3vS8VXvkCag6N2Yzfk=
|
||||||
github.com/uptrace/bun v1.1.17/go.mod h1:hATAzivtTIRsSJR4B8AXR+uABqnQxr3myKDKEf5iQ9U=
|
github.com/uptrace/bun v1.2.1/go.mod h1:cNg+pWBUMmJ8rHnETgf65CEvn3aIKErrwOD6IA8e+Ec=
|
||||||
github.com/uptrace/bun/dialect/pgdialect v1.1.17 h1:NsvFVHAx1Az6ytlAD/B6ty3cVE6j9Yp82bjqd9R9hOs=
|
github.com/uptrace/bun/dialect/pgdialect v1.2.1 h1:ceP99r03u+s8ylaDE/RzgcajwGiC76Jz3nS2ZgyPQ4M=
|
||||||
github.com/uptrace/bun/dialect/pgdialect v1.1.17/go.mod h1:fLBDclNc7nKsZLzNjFL6BqSdgJzbj2HdnyOnLoDvAME=
|
github.com/uptrace/bun/dialect/pgdialect v1.2.1/go.mod h1:mv6B12cisvSc6bwKm9q9wcrr26awkZK8QXM+nso9n2U=
|
||||||
github.com/uptrace/bun/dialect/sqlitedialect v1.1.17 h1:i8NFU9r8YuavNFaYlNqi4ppn+MgoHtqLgpWQDrVTjm0=
|
github.com/uptrace/bun/dialect/sqlitedialect v1.2.1 h1:IprvkIKUjEjvt4VKpcmLpbMIucjrsmUPJOSlg19+a0Q=
|
||||||
github.com/uptrace/bun/dialect/sqlitedialect v1.1.17/go.mod h1:YF0FO4VVnY9GHNH6rM4r3STlVEBxkOc6L88Bm5X5mzA=
|
github.com/uptrace/bun/dialect/sqlitedialect v1.2.1/go.mod h1:mMQf4NUpgY8bnOanxGmxNiHCdALOggS4cZ3v63a9D/o=
|
||||||
github.com/uptrace/bun/extra/bunotel v1.1.17 h1:RLEJdHH06RI9BLg06Vu1JHJ3KNHQCfwa2Fa3x+56qkk=
|
github.com/uptrace/bun/extra/bunotel v1.2.1 h1:5oTy3Jh7Q1bhCd5vnPszBmJgYouw+PuuZ8iSCm+uNCQ=
|
||||||
github.com/uptrace/bun/extra/bunotel v1.1.17/go.mod h1:xV7AYrCFji4Sio6N9X+Cz+XJ+JuHq6TQQjuxaVbsypk=
|
github.com/uptrace/bun/extra/bunotel v1.2.1/go.mod h1:SWW3HyjiXPYM36q0QSpdtTP8v21nWHnTCxu4lYkpO90=
|
||||||
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.3 h1:LNi0Qa7869/loPjz2kmMvp/jwZZnMZ9scMJKhDJ1DIo=
|
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.4 h1:x3omFAG2XkvWFg1hvXRinY2ExAL1Aacl7W9ZlYjo6gc=
|
||||||
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.3/go.mod h1:jyigonKik3C5V895QNiAGpKYKEvFuqjw9qAEZks1mUg=
|
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.4/go.mod h1:qMKJr5fTnY0p7hqCQMNrAk62bCARWR5rAbTrGUFRuh4=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE=
|
github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE=
|
||||||
|
|
|
@ -1,3 +1,25 @@
|
||||||
|
## [1.2.1](https://github.com/uptrace/bun/compare/v1.2.0...v1.2.1) (2024-04-02)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.2.0](https://github.com/uptrace/bun/compare/v1.1.17...v1.2.0) (2024-04-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* embedding of scanonly fields ([ed6ed74](https://github.com/uptrace/bun/commit/ed6ed74d5379ea6badb09cc37709211a51f5792b))
|
||||||
|
* **table:** allow alt annotation ([#956](https://github.com/uptrace/bun/issues/956)) ([8a0397b](https://github.com/uptrace/bun/commit/8a0397b6e2219909d6b00d258eb7934170058edd))
|
||||||
|
* transactional migration file extension ([#959](https://github.com/uptrace/bun/issues/959)) ([921b15b](https://github.com/uptrace/bun/commit/921b15b80110d28251a9210c77397d29924ffbc5))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Allow overiding of Warn and Deprecated loggers ([#952](https://github.com/uptrace/bun/issues/952)) ([0e9d737](https://github.com/uptrace/bun/commit/0e9d737e4ca2deb86930237ee32a39cf3f7e8157))
|
||||||
|
* enable SNI ([#953](https://github.com/uptrace/bun/issues/953)) ([4071ffb](https://github.com/uptrace/bun/commit/4071ffb5bcb1b233cda239c92504d8139dcf1d2f))
|
||||||
|
* **idb:** add NewMerge method to IDB ([#966](https://github.com/uptrace/bun/issues/966)) ([664e2f1](https://github.com/uptrace/bun/commit/664e2f154f1153d2a80cd062a5074f1692edaee7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.1.17](https://github.com/uptrace/bun/compare/v1.1.16...v1.1.17) (2024-01-11)
|
## [1.1.17](https://github.com/uptrace/bun/compare/v1.1.16...v1.1.17) (2024-01-11)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ go_mod_tidy:
|
||||||
echo "go mod tidy in $${dir}"; \
|
echo "go mod tidy in $${dir}"; \
|
||||||
(cd "$${dir}" && \
|
(cd "$${dir}" && \
|
||||||
go get -u ./... && \
|
go get -u ./... && \
|
||||||
go mod tidy -go=1.19); \
|
go mod tidy -go=1.21); \
|
||||||
done
|
done
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
|
|
|
@ -20,11 +20,6 @@ type (
|
||||||
|
|
||||||
BeforeScanRowHook = schema.BeforeScanRowHook
|
BeforeScanRowHook = schema.BeforeScanRowHook
|
||||||
AfterScanRowHook = schema.AfterScanRowHook
|
AfterScanRowHook = schema.AfterScanRowHook
|
||||||
|
|
||||||
// DEPRECATED. Use BeforeScanRowHook instead.
|
|
||||||
BeforeScanHook = schema.BeforeScanHook
|
|
||||||
// DEPRECATED. Use AfterScanRowHook instead.
|
|
||||||
AfterScanHook = schema.AfterScanHook
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type BeforeSelectHook interface {
|
type BeforeSelectHook interface {
|
||||||
|
@ -77,7 +72,7 @@ type AfterDropTableHook interface {
|
||||||
|
|
||||||
// SetLogger overwriters default Bun logger.
|
// SetLogger overwriters default Bun logger.
|
||||||
func SetLogger(logger internal.Logging) {
|
func SetLogger(logger internal.Logging) {
|
||||||
internal.Logger = logger
|
internal.SetLogger(logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
func In(slice interface{}) schema.QueryAppender {
|
func In(slice interface{}) schema.QueryAppender {
|
||||||
|
|
|
@ -2,5 +2,5 @@ package pgdialect
|
||||||
|
|
||||||
// Version is the current release version.
|
// Version is the current release version.
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return "1.1.17"
|
return "1.2.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,5 @@ package sqlitedialect
|
||||||
|
|
||||||
// Version is the current release version.
|
// Version is the current release version.
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return "1.1.17"
|
return "1.2.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,26 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Warn = log.New(os.Stderr, "WARN: bun: ", log.LstdFlags)
|
|
||||||
|
|
||||||
var Deprecated = log.New(os.Stderr, "DEPRECATED: bun: ", log.LstdFlags)
|
|
||||||
|
|
||||||
type Logging interface {
|
type Logging interface {
|
||||||
Printf(format string, v ...interface{})
|
Printf(format string, v ...interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var defaultLogger = log.New(os.Stderr, "", log.LstdFlags)
|
||||||
|
|
||||||
|
var Logger Logging = &logger{
|
||||||
|
log: defaultLogger,
|
||||||
|
}
|
||||||
|
|
||||||
|
var Warn = &wrapper{
|
||||||
|
prefix: "WARN: bun: ",
|
||||||
|
logger: Logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
var Deprecated = &wrapper{
|
||||||
|
prefix: "DEPRECATED: bun: ",
|
||||||
|
logger: Logger,
|
||||||
|
}
|
||||||
|
|
||||||
type logger struct {
|
type logger struct {
|
||||||
log *log.Logger
|
log *log.Logger
|
||||||
}
|
}
|
||||||
|
@ -22,6 +34,21 @@ func (l *logger) Printf(format string, v ...interface{}) {
|
||||||
_ = l.log.Output(2, fmt.Sprintf(format, v...))
|
_ = l.log.Output(2, fmt.Sprintf(format, v...))
|
||||||
}
|
}
|
||||||
|
|
||||||
var Logger Logging = &logger{
|
type wrapper struct {
|
||||||
log: log.New(os.Stderr, "bun: ", log.LstdFlags|log.Lshortfile),
|
prefix string
|
||||||
|
logger Logging
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *wrapper) Printf(format string, v ...interface{}) {
|
||||||
|
w.logger.Printf(w.prefix+format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetLogger(newLogger Logging) {
|
||||||
|
if newLogger == nil {
|
||||||
|
Logger = &logger{log: defaultLogger}
|
||||||
|
} else {
|
||||||
|
Logger = newLogger
|
||||||
|
}
|
||||||
|
Warn.logger = Logger
|
||||||
|
Deprecated.logger = Logger
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,12 +274,12 @@ func (m *Migrator) CreateTxSQLMigrations(ctx context.Context, name string) ([]*M
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
up, err := m.createSQL(ctx, name+".up.tx.sql", true)
|
up, err := m.createSQL(ctx, name+".tx.up.sql", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
down, err := m.createSQL(ctx, name+".down.tx.sql", true)
|
down, err := m.createSQL(ctx, name+".tx.down.sql", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,9 +83,9 @@ func (m *hasManyModel) Scan(src interface{}) error {
|
||||||
column := m.columns[m.scanIndex]
|
column := m.columns[m.scanIndex]
|
||||||
m.scanIndex++
|
m.scanIndex++
|
||||||
|
|
||||||
field, err := m.table.Field(column)
|
field := m.table.LookupField(column)
|
||||||
if err != nil {
|
if field == nil {
|
||||||
return err
|
return fmt.Errorf("bun: %s does not have column %q", m.table.TypeName, column)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := field.ScanValue(m.strct, src); err != nil {
|
if err := field.ScanValue(m.strct, src); err != nil {
|
||||||
|
|
|
@ -116,9 +116,6 @@ func (m *structTableModel) BeforeScanRow(ctx context.Context) error {
|
||||||
if m.table.HasBeforeScanRowHook() {
|
if m.table.HasBeforeScanRowHook() {
|
||||||
return m.strct.Addr().Interface().(schema.BeforeScanRowHook).BeforeScanRow(ctx)
|
return m.strct.Addr().Interface().(schema.BeforeScanRowHook).BeforeScanRow(ctx)
|
||||||
}
|
}
|
||||||
if m.table.HasBeforeScanHook() {
|
|
||||||
return m.strct.Addr().Interface().(schema.BeforeScanHook).BeforeScan(ctx)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,21 +141,6 @@ func (m *structTableModel) AfterScanRow(ctx context.Context) error {
|
||||||
return firstErr
|
return firstErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.table.HasAfterScanHook() {
|
|
||||||
firstErr := m.strct.Addr().Interface().(schema.AfterScanHook).AfterScan(ctx)
|
|
||||||
|
|
||||||
for _, j := range m.joins {
|
|
||||||
switch j.Relation.Type {
|
|
||||||
case schema.HasOneRelation, schema.BelongsToRelation:
|
|
||||||
if err := j.JoinModel.AfterScanRow(ctx); err != nil && firstErr == nil {
|
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return firstErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +307,7 @@ func (m *structTableModel) scanColumn(column string, src interface{}) (bool, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if field, ok := m.table.FieldMap[column]; ok {
|
if field := m.table.LookupField(column); field != nil {
|
||||||
if src == nil && m.isNil() {
|
if src == nil && m.isNil() {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "gobun",
|
"name": "gobun",
|
||||||
"version": "1.1.17",
|
"version": "1.2.1",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"repository": "git@github.com:uptrace/bun.git",
|
"repository": "git@github.com:uptrace/bun.git",
|
||||||
"author": "Vladimir Mihailenco <vladimir.webdev@gmail.com>",
|
"author": "Vladimir Mihailenco <vladimir.webdev@gmail.com>",
|
||||||
|
|
|
@ -51,6 +51,7 @@ type IDB interface {
|
||||||
NewInsert() *InsertQuery
|
NewInsert() *InsertQuery
|
||||||
NewUpdate() *UpdateQuery
|
NewUpdate() *UpdateQuery
|
||||||
NewDelete() *DeleteQuery
|
NewDelete() *DeleteQuery
|
||||||
|
NewMerge() *MergeQuery
|
||||||
NewRaw(query string, args ...interface{}) *RawQuery
|
NewRaw(query string, args ...interface{}) *RawQuery
|
||||||
NewCreateTable() *CreateTableQuery
|
NewCreateTable() *CreateTableQuery
|
||||||
NewDropTable() *DropTableQuery
|
NewDropTable() *DropTableQuery
|
||||||
|
|
|
@ -262,7 +262,9 @@ func (j *relationJoin) appendBaseAlias(fmter schema.Formatter, b []byte) []byte
|
||||||
return append(b, j.BaseModel.Table().SQLAlias...)
|
return append(b, j.BaseModel.Table().SQLAlias...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *relationJoin) appendSoftDelete(fmter schema.Formatter, b []byte, flags internal.Flag) []byte {
|
func (j *relationJoin) appendSoftDelete(
|
||||||
|
fmter schema.Formatter, b []byte, flags internal.Flag,
|
||||||
|
) []byte {
|
||||||
b = append(b, '.')
|
b = append(b, '.')
|
||||||
|
|
||||||
field := j.JoinModel.Table().SoftDeleteField
|
field := j.JoinModel.Table().SoftDeleteField
|
||||||
|
|
|
@ -44,6 +44,15 @@ func (f *Field) String() string {
|
||||||
return f.Name
|
return f.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Field) WithIndex(path []int) *Field {
|
||||||
|
if len(path) == 0 {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
clone := *f
|
||||||
|
clone.Index = makeIndex(path, f.Index)
|
||||||
|
return &clone
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Field) Clone() *Field {
|
func (f *Field) Clone() *Field {
|
||||||
cp := *f
|
cp := *f
|
||||||
cp.Index = cp.Index[:len(f.Index):len(f.Index)]
|
cp.Index = cp.Index[:len(f.Index):len(f.Index)]
|
||||||
|
@ -103,13 +112,6 @@ func (f *Field) AppendValue(fmter Formatter, b []byte, strct reflect.Value) []by
|
||||||
return f.Append(fmter, b, fv)
|
return f.Append(fmter, b, fv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Field) ScanWithCheck(fv reflect.Value, src interface{}) error {
|
|
||||||
if f.Scan == nil {
|
|
||||||
return fmt.Errorf("bun: Scan(unsupported %s)", f.IndirectType)
|
|
||||||
}
|
|
||||||
return f.Scan(fv, src)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Field) ScanValue(strct reflect.Value, src interface{}) error {
|
func (f *Field) ScanValue(strct reflect.Value, src interface{}) error {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
if fv, ok := fieldByIndex(strct, f.Index); ok {
|
if fv, ok := fieldByIndex(strct, f.Index); ok {
|
||||||
|
@ -122,18 +124,13 @@ func (f *Field) ScanValue(strct reflect.Value, src interface{}) error {
|
||||||
return f.ScanWithCheck(fv, src)
|
return f.ScanWithCheck(fv, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Field) ScanWithCheck(fv reflect.Value, src interface{}) error {
|
||||||
|
if f.Scan == nil {
|
||||||
|
return fmt.Errorf("bun: Scan(unsupported %s)", f.IndirectType)
|
||||||
|
}
|
||||||
|
return f.Scan(fv, src)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Field) SkipUpdate() bool {
|
func (f *Field) SkipUpdate() bool {
|
||||||
return f.Tag.HasOption("skipupdate")
|
return f.Tag.HasOption("skipupdate")
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexEqual(ind1, ind2 []int) bool {
|
|
||||||
if len(ind1) != len(ind2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, ind := range ind1 {
|
|
||||||
if ind != ind2[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,22 +28,6 @@ var beforeAppendModelHookType = reflect.TypeOf((*BeforeAppendModelHook)(nil)).El
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
type BeforeScanHook interface {
|
|
||||||
BeforeScan(context.Context) error
|
|
||||||
}
|
|
||||||
|
|
||||||
var beforeScanHookType = reflect.TypeOf((*BeforeScanHook)(nil)).Elem()
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
type AfterScanHook interface {
|
|
||||||
AfterScan(context.Context) error
|
|
||||||
}
|
|
||||||
|
|
||||||
var afterScanHookType = reflect.TypeOf((*AfterScanHook)(nil)).Elem()
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
type BeforeScanRowHook interface {
|
type BeforeScanRowHook interface {
|
||||||
BeforeScanRow(context.Context) error
|
BeforeScanRow(context.Context) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jinzhu/inflection"
|
"github.com/jinzhu/inflection"
|
||||||
|
@ -52,12 +51,14 @@ type Table struct {
|
||||||
Alias string
|
Alias string
|
||||||
SQLAlias Safe
|
SQLAlias Safe
|
||||||
|
|
||||||
|
allFields []*Field // all fields including scanonly
|
||||||
Fields []*Field // PKs + DataFields
|
Fields []*Field // PKs + DataFields
|
||||||
PKs []*Field
|
PKs []*Field
|
||||||
DataFields []*Field
|
DataFields []*Field
|
||||||
|
relFields []*Field
|
||||||
|
|
||||||
fieldsMapMu sync.RWMutex
|
|
||||||
FieldMap map[string]*Field
|
FieldMap map[string]*Field
|
||||||
|
StructMap map[string]*structField
|
||||||
|
|
||||||
Relations map[string]*Relation
|
Relations map[string]*Relation
|
||||||
Unique map[string][]*Field
|
Unique map[string][]*Field
|
||||||
|
@ -65,23 +66,38 @@ type Table struct {
|
||||||
SoftDeleteField *Field
|
SoftDeleteField *Field
|
||||||
UpdateSoftDeleteField func(fv reflect.Value, tm time.Time) error
|
UpdateSoftDeleteField func(fv reflect.Value, tm time.Time) error
|
||||||
|
|
||||||
allFields []*Field // read only
|
|
||||||
|
|
||||||
flags internal.Flag
|
flags internal.Flag
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTable(dialect Dialect, typ reflect.Type) *Table {
|
type structField struct {
|
||||||
t := new(Table)
|
Index []int
|
||||||
t.dialect = dialect
|
Table *Table
|
||||||
t.Type = typ
|
}
|
||||||
t.ZeroValue = reflect.New(t.Type).Elem()
|
|
||||||
t.ZeroIface = reflect.New(t.Type).Interface()
|
func newTable(
|
||||||
t.TypeName = internal.ToExported(t.Type.Name())
|
dialect Dialect, typ reflect.Type, seen map[reflect.Type]*Table, canAddr bool,
|
||||||
t.ModelName = internal.Underscore(t.Type.Name())
|
) *Table {
|
||||||
tableName := tableNameInflector(t.ModelName)
|
if table, ok := seen[typ]; ok {
|
||||||
t.setName(tableName)
|
return table
|
||||||
t.Alias = t.ModelName
|
}
|
||||||
t.SQLAlias = t.quoteIdent(t.ModelName)
|
|
||||||
|
table := new(Table)
|
||||||
|
seen[typ] = table
|
||||||
|
|
||||||
|
table.dialect = dialect
|
||||||
|
table.Type = typ
|
||||||
|
table.ZeroValue = reflect.New(table.Type).Elem()
|
||||||
|
table.ZeroIface = reflect.New(table.Type).Interface()
|
||||||
|
table.TypeName = internal.ToExported(table.Type.Name())
|
||||||
|
table.ModelName = internal.Underscore(table.Type.Name())
|
||||||
|
tableName := tableNameInflector(table.ModelName)
|
||||||
|
table.setName(tableName)
|
||||||
|
table.Alias = table.ModelName
|
||||||
|
table.SQLAlias = table.quoteIdent(table.ModelName)
|
||||||
|
|
||||||
|
table.Fields = make([]*Field, 0, typ.NumField())
|
||||||
|
table.FieldMap = make(map[string]*Field, typ.NumField())
|
||||||
|
table.processFields(typ, seen, canAddr)
|
||||||
|
|
||||||
hooks := []struct {
|
hooks := []struct {
|
||||||
typ reflect.Type
|
typ reflect.Type
|
||||||
|
@ -89,45 +105,168 @@ func newTable(dialect Dialect, typ reflect.Type) *Table {
|
||||||
}{
|
}{
|
||||||
{beforeAppendModelHookType, beforeAppendModelHookFlag},
|
{beforeAppendModelHookType, beforeAppendModelHookFlag},
|
||||||
|
|
||||||
{beforeScanHookType, beforeScanHookFlag},
|
|
||||||
{afterScanHookType, afterScanHookFlag},
|
|
||||||
|
|
||||||
{beforeScanRowHookType, beforeScanRowHookFlag},
|
{beforeScanRowHookType, beforeScanRowHookFlag},
|
||||||
{afterScanRowHookType, afterScanRowHookFlag},
|
{afterScanRowHookType, afterScanRowHookFlag},
|
||||||
}
|
}
|
||||||
|
|
||||||
typ = reflect.PtrTo(t.Type)
|
typ = reflect.PtrTo(table.Type)
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
if typ.Implements(hook.typ) {
|
if typ.Implements(hook.typ) {
|
||||||
t.flags = t.flags.Set(hook.flag)
|
table.flags = table.flags.Set(hook.flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated.
|
return table
|
||||||
deprecatedHooks := []struct {
|
|
||||||
typ reflect.Type
|
|
||||||
flag internal.Flag
|
|
||||||
msg string
|
|
||||||
}{
|
|
||||||
{beforeScanHookType, beforeScanHookFlag, "rename BeforeScan hook to BeforeScanRow"},
|
|
||||||
{afterScanHookType, afterScanHookFlag, "rename AfterScan hook to AfterScanRow"},
|
|
||||||
}
|
}
|
||||||
for _, hook := range deprecatedHooks {
|
|
||||||
if typ.Implements(hook.typ) {
|
func (t *Table) init() {
|
||||||
internal.Deprecated.Printf("%s: %s", t.TypeName, hook.msg)
|
for _, field := range t.relFields {
|
||||||
t.flags = t.flags.Set(hook.flag)
|
t.processRelation(field)
|
||||||
|
}
|
||||||
|
t.relFields = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Table) processFields(
|
||||||
|
typ reflect.Type,
|
||||||
|
seen map[reflect.Type]*Table,
|
||||||
|
canAddr bool,
|
||||||
|
) {
|
||||||
|
type embeddedField struct {
|
||||||
|
prefix string
|
||||||
|
index []int
|
||||||
|
unexported bool
|
||||||
|
subtable *Table
|
||||||
|
subfield *Field
|
||||||
|
}
|
||||||
|
|
||||||
|
names := make(map[string]struct{})
|
||||||
|
embedded := make([]embeddedField, 0, 10)
|
||||||
|
|
||||||
|
for i, n := 0, typ.NumField(); i < n; i++ {
|
||||||
|
sf := typ.Field(i)
|
||||||
|
unexported := sf.PkgPath != ""
|
||||||
|
|
||||||
|
tagstr := sf.Tag.Get("bun")
|
||||||
|
if tagstr == "-" {
|
||||||
|
names[sf.Name] = struct{}{}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tag := tagparser.Parse(tagstr)
|
||||||
|
|
||||||
|
if unexported && !sf.Anonymous { // unexported
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if sf.Anonymous {
|
||||||
|
if sf.Name == "BaseModel" && sf.Type == baseModelType {
|
||||||
|
t.processBaseModelField(sf)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
sfType := sf.Type
|
||||||
|
if sfType.Kind() == reflect.Ptr {
|
||||||
|
sfType = sfType.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if sfType.Kind() != reflect.Struct { // ignore unexported non-struct types
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
subtable := newTable(t.dialect, sfType, seen, canAddr)
|
||||||
|
|
||||||
|
for _, subfield := range subtable.allFields {
|
||||||
|
embedded = append(embedded, embeddedField{
|
||||||
|
index: sf.Index,
|
||||||
|
unexported: unexported,
|
||||||
|
subtable: subtable,
|
||||||
|
subfield: subfield,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if tagstr != "" {
|
||||||
|
tag := tagparser.Parse(tagstr)
|
||||||
|
if tag.HasOption("inherit") || tag.HasOption("extend") {
|
||||||
|
t.Name = subtable.Name
|
||||||
|
t.TypeName = subtable.TypeName
|
||||||
|
t.SQLName = subtable.SQLName
|
||||||
|
t.SQLNameForSelects = subtable.SQLNameForSelects
|
||||||
|
t.Alias = subtable.Alias
|
||||||
|
t.SQLAlias = subtable.SQLAlias
|
||||||
|
t.ModelName = subtable.ModelName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return t
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) init1() {
|
if prefix, ok := tag.Option("embed"); ok {
|
||||||
t.initFields()
|
fieldType := indirectType(sf.Type)
|
||||||
|
if fieldType.Kind() != reflect.Struct {
|
||||||
|
panic(fmt.Errorf("bun: embed %s.%s: got %s, wanted reflect.Struct",
|
||||||
|
t.TypeName, sf.Name, fieldType.Kind()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) init2() {
|
subtable := newTable(t.dialect, fieldType, seen, canAddr)
|
||||||
t.initRelations()
|
for _, subfield := range subtable.allFields {
|
||||||
|
embedded = append(embedded, embeddedField{
|
||||||
|
prefix: prefix,
|
||||||
|
index: sf.Index,
|
||||||
|
unexported: unexported,
|
||||||
|
subtable: subtable,
|
||||||
|
subfield: subfield,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
field := t.newField(sf, tag)
|
||||||
|
t.addField(field)
|
||||||
|
names[field.Name] = struct{}{}
|
||||||
|
|
||||||
|
if field.IndirectType.Kind() == reflect.Struct {
|
||||||
|
if t.StructMap == nil {
|
||||||
|
t.StructMap = make(map[string]*structField)
|
||||||
|
}
|
||||||
|
t.StructMap[field.Name] = &structField{
|
||||||
|
Index: field.Index,
|
||||||
|
Table: newTable(t.dialect, field.IndirectType, seen, canAddr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only unambiguous embedded fields must be serialized.
|
||||||
|
ambiguousNames := make(map[string]int)
|
||||||
|
ambiguousTags := make(map[string]int)
|
||||||
|
|
||||||
|
// Embedded types can never override a field that was already present at
|
||||||
|
// the top-level.
|
||||||
|
for name := range names {
|
||||||
|
ambiguousNames[name]++
|
||||||
|
ambiguousTags[name]++
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range embedded {
|
||||||
|
ambiguousNames[f.prefix+f.subfield.Name]++
|
||||||
|
if !f.subfield.Tag.IsZero() {
|
||||||
|
ambiguousTags[f.prefix+f.subfield.Name]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, embfield := range embedded {
|
||||||
|
subfield := embfield.subfield.Clone()
|
||||||
|
|
||||||
|
if ambiguousNames[subfield.Name] > 1 &&
|
||||||
|
!(!subfield.Tag.IsZero() && ambiguousTags[subfield.Name] == 1) {
|
||||||
|
continue // ambiguous embedded field
|
||||||
|
}
|
||||||
|
|
||||||
|
subfield.Index = makeIndex(embfield.index, subfield.Index)
|
||||||
|
if embfield.prefix != "" {
|
||||||
|
subfield.Name = embfield.prefix + subfield.Name
|
||||||
|
subfield.SQLName = t.quoteIdent(subfield.Name)
|
||||||
|
}
|
||||||
|
t.addField(subfield)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) setName(name string) {
|
func (t *Table) setName(name string) {
|
||||||
|
@ -152,32 +291,69 @@ func (t *Table) CheckPKs() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) addField(field *Field) {
|
func (t *Table) addField(field *Field) {
|
||||||
|
t.allFields = append(t.allFields, field)
|
||||||
|
|
||||||
|
if field.Tag.HasOption("rel") || field.Tag.HasOption("m2m") {
|
||||||
|
t.relFields = append(t.relFields, field)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Tag.HasOption("join") {
|
||||||
|
internal.Warn.Printf(
|
||||||
|
`%s.%s "join" option must come together with "rel" option`,
|
||||||
|
t.TypeName, field.GoName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.FieldMap[field.Name] = field
|
||||||
|
if altName, ok := field.Tag.Option("alt"); ok {
|
||||||
|
t.FieldMap[altName] = field
|
||||||
|
}
|
||||||
|
|
||||||
|
if field.Tag.HasOption("scanonly") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := field.Tag.Options["soft_delete"]; ok {
|
||||||
|
t.SoftDeleteField = field
|
||||||
|
t.UpdateSoftDeleteField = softDeleteFieldUpdater(field)
|
||||||
|
}
|
||||||
|
|
||||||
t.Fields = append(t.Fields, field)
|
t.Fields = append(t.Fields, field)
|
||||||
if field.IsPK {
|
if field.IsPK {
|
||||||
t.PKs = append(t.PKs, field)
|
t.PKs = append(t.PKs, field)
|
||||||
} else {
|
} else {
|
||||||
t.DataFields = append(t.DataFields, field)
|
t.DataFields = append(t.DataFields, field)
|
||||||
}
|
}
|
||||||
t.FieldMap[field.Name] = field
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) removeField(field *Field) {
|
func (t *Table) LookupField(name string) *Field {
|
||||||
t.Fields = removeField(t.Fields, field)
|
if field, ok := t.FieldMap[name]; ok {
|
||||||
if field.IsPK {
|
|
||||||
t.PKs = removeField(t.PKs, field)
|
|
||||||
} else {
|
|
||||||
t.DataFields = removeField(t.DataFields, field)
|
|
||||||
}
|
|
||||||
delete(t.FieldMap, field.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) fieldWithLock(name string) *Field {
|
|
||||||
t.fieldsMapMu.RLock()
|
|
||||||
field := t.FieldMap[name]
|
|
||||||
t.fieldsMapMu.RUnlock()
|
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table := t
|
||||||
|
var index []int
|
||||||
|
for {
|
||||||
|
structName, columnName, ok := strings.Cut(name, "__")
|
||||||
|
if !ok {
|
||||||
|
field, ok := table.FieldMap[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return field.WithIndex(index)
|
||||||
|
}
|
||||||
|
name = columnName
|
||||||
|
|
||||||
|
strct := table.StructMap[structName]
|
||||||
|
if strct == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
table = strct.Table
|
||||||
|
index = append(index, strct.Index...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Table) HasField(name string) bool {
|
func (t *Table) HasField(name string) bool {
|
||||||
_, ok := t.FieldMap[name]
|
_, ok := t.FieldMap[name]
|
||||||
return ok
|
return ok
|
||||||
|
@ -200,59 +376,6 @@ func (t *Table) fieldByGoName(name string) *Field {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) initFields() {
|
|
||||||
t.Fields = make([]*Field, 0, t.Type.NumField())
|
|
||||||
t.FieldMap = make(map[string]*Field, t.Type.NumField())
|
|
||||||
t.addFields(t.Type, "", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) addFields(typ reflect.Type, prefix string, index []int) {
|
|
||||||
for i := 0; i < typ.NumField(); i++ {
|
|
||||||
f := typ.Field(i)
|
|
||||||
unexported := f.PkgPath != ""
|
|
||||||
|
|
||||||
if unexported && !f.Anonymous { // unexported
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if f.Tag.Get("bun") == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Anonymous {
|
|
||||||
if f.Name == "BaseModel" && f.Type == baseModelType {
|
|
||||||
if len(index) == 0 {
|
|
||||||
t.processBaseModelField(f)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// If field is an embedded struct, add each field of the embedded struct.
|
|
||||||
fieldType := indirectType(f.Type)
|
|
||||||
if fieldType.Kind() == reflect.Struct {
|
|
||||||
t.addFields(fieldType, "", withIndex(index, f.Index))
|
|
||||||
|
|
||||||
tag := tagparser.Parse(f.Tag.Get("bun"))
|
|
||||||
if tag.HasOption("inherit") || tag.HasOption("extend") {
|
|
||||||
embeddedTable := t.dialect.Tables().Ref(fieldType)
|
|
||||||
t.TypeName = embeddedTable.TypeName
|
|
||||||
t.SQLName = embeddedTable.SQLName
|
|
||||||
t.SQLNameForSelects = embeddedTable.SQLNameForSelects
|
|
||||||
t.Alias = embeddedTable.Alias
|
|
||||||
t.SQLAlias = embeddedTable.SQLAlias
|
|
||||||
t.ModelName = embeddedTable.ModelName
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If field is not a struct, add it.
|
|
||||||
// This will also add any embedded non-struct type as a field.
|
|
||||||
if field := t.newField(f, prefix, index); field != nil {
|
|
||||||
t.addField(field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) processBaseModelField(f reflect.StructField) {
|
func (t *Table) processBaseModelField(f reflect.StructField) {
|
||||||
tag := tagparser.Parse(f.Tag.Get("bun"))
|
tag := tagparser.Parse(f.Tag.Get("bun"))
|
||||||
|
|
||||||
|
@ -288,58 +411,34 @@ func (t *Table) processBaseModelField(f reflect.StructField) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
func (t *Table) newField(f reflect.StructField, prefix string, index []int) *Field {
|
func (t *Table) newField(sf reflect.StructField, tag tagparser.Tag) *Field {
|
||||||
tag := tagparser.Parse(f.Tag.Get("bun"))
|
sqlName := internal.Underscore(sf.Name)
|
||||||
|
|
||||||
if nextPrefix, ok := tag.Option("embed"); ok {
|
|
||||||
fieldType := indirectType(f.Type)
|
|
||||||
if fieldType.Kind() != reflect.Struct {
|
|
||||||
panic(fmt.Errorf("bun: embed %s.%s: got %s, wanted reflect.Struct",
|
|
||||||
t.TypeName, f.Name, fieldType.Kind()))
|
|
||||||
}
|
|
||||||
t.addFields(fieldType, prefix+nextPrefix, withIndex(index, f.Index))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlName := internal.Underscore(f.Name)
|
|
||||||
if tag.Name != "" && tag.Name != sqlName {
|
if tag.Name != "" && tag.Name != sqlName {
|
||||||
if isKnownFieldOption(tag.Name) {
|
if isKnownFieldOption(tag.Name) {
|
||||||
internal.Warn.Printf(
|
internal.Warn.Printf(
|
||||||
"%s.%s tag name %q is also an option name, is it a mistake? Try column:%s.",
|
"%s.%s tag name %q is also an option name, is it a mistake? Try column:%s.",
|
||||||
t.TypeName, f.Name, tag.Name, tag.Name,
|
t.TypeName, sf.Name, tag.Name, tag.Name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
sqlName = tag.Name
|
sqlName = tag.Name
|
||||||
}
|
}
|
||||||
if s, ok := tag.Option("column"); ok {
|
|
||||||
sqlName = s
|
|
||||||
}
|
|
||||||
sqlName = prefix + sqlName
|
|
||||||
|
|
||||||
for name := range tag.Options {
|
for name := range tag.Options {
|
||||||
if !isKnownFieldOption(name) {
|
if !isKnownFieldOption(name) {
|
||||||
internal.Warn.Printf("%s.%s has unknown tag option: %q", t.TypeName, f.Name, name)
|
internal.Warn.Printf("%s.%s has unknown tag option: %q", t.TypeName, sf.Name, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index = withIndex(index, f.Index)
|
|
||||||
if field := t.fieldWithLock(sqlName); field != nil {
|
|
||||||
if indexEqual(field.Index, index) {
|
|
||||||
return field
|
|
||||||
}
|
|
||||||
t.removeField(field)
|
|
||||||
}
|
|
||||||
|
|
||||||
field := &Field{
|
field := &Field{
|
||||||
StructField: f,
|
StructField: sf,
|
||||||
IsPtr: f.Type.Kind() == reflect.Ptr,
|
IsPtr: sf.Type.Kind() == reflect.Ptr,
|
||||||
|
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
IndirectType: indirectType(f.Type),
|
IndirectType: indirectType(sf.Type),
|
||||||
Index: index,
|
Index: sf.Index,
|
||||||
|
|
||||||
Name: sqlName,
|
Name: sqlName,
|
||||||
GoName: f.Name,
|
GoName: sf.Name,
|
||||||
SQLName: t.quoteIdent(sqlName),
|
SQLName: t.quoteIdent(sqlName),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,63 +485,21 @@ func (t *Table) newField(f reflect.StructField, prefix string, index []int) *Fie
|
||||||
field.Scan = FieldScanner(t.dialect, field)
|
field.Scan = FieldScanner(t.dialect, field)
|
||||||
field.IsZero = zeroChecker(field.StructField.Type)
|
field.IsZero = zeroChecker(field.StructField.Type)
|
||||||
|
|
||||||
if v, ok := tag.Option("alt"); ok {
|
|
||||||
t.FieldMap[v] = field
|
|
||||||
}
|
|
||||||
|
|
||||||
t.allFields = append(t.allFields, field)
|
|
||||||
if tag.HasOption("scanonly") {
|
|
||||||
t.FieldMap[field.Name] = field
|
|
||||||
if field.IndirectType.Kind() == reflect.Struct {
|
|
||||||
t.inlineFields(field, nil)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := tag.Options["soft_delete"]; ok {
|
|
||||||
t.SoftDeleteField = field
|
|
||||||
t.UpdateSoftDeleteField = softDeleteFieldUpdater(field)
|
|
||||||
}
|
|
||||||
|
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
func (t *Table) initRelations() {
|
func (t *Table) processRelation(field *Field) {
|
||||||
for i := 0; i < len(t.Fields); {
|
|
||||||
f := t.Fields[i]
|
|
||||||
if t.tryRelation(f) {
|
|
||||||
t.Fields = removeField(t.Fields, f)
|
|
||||||
t.DataFields = removeField(t.DataFields, f)
|
|
||||||
} else {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.IndirectType.Kind() == reflect.Struct {
|
|
||||||
t.inlineFields(f, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) tryRelation(field *Field) bool {
|
|
||||||
if rel, ok := field.Tag.Option("rel"); ok {
|
if rel, ok := field.Tag.Option("rel"); ok {
|
||||||
t.initRelation(field, rel)
|
t.initRelation(field, rel)
|
||||||
return true
|
return
|
||||||
}
|
}
|
||||||
if field.Tag.HasOption("m2m") {
|
if field.Tag.HasOption("m2m") {
|
||||||
t.addRelation(t.m2mRelation(field))
|
t.addRelation(t.m2mRelation(field))
|
||||||
return true
|
return
|
||||||
}
|
}
|
||||||
|
panic("not reached")
|
||||||
if field.Tag.HasOption("join") {
|
|
||||||
internal.Warn.Printf(
|
|
||||||
`%s.%s "join" option must come together with "rel" option`,
|
|
||||||
t.TypeName, field.GoName,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) initRelation(field *Field, rel string) {
|
func (t *Table) initRelation(field *Field, rel string) {
|
||||||
|
@ -470,7 +527,7 @@ func (t *Table) addRelation(rel *Relation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) belongsToRelation(field *Field) *Relation {
|
func (t *Table) belongsToRelation(field *Field) *Relation {
|
||||||
joinTable := t.dialect.Tables().Ref(field.IndirectType)
|
joinTable := t.dialect.Tables().InProgress(field.IndirectType)
|
||||||
if err := joinTable.CheckPKs(); err != nil {
|
if err := joinTable.CheckPKs(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -519,7 +576,7 @@ func (t *Table) belongsToRelation(field *Field) *Relation {
|
||||||
for i, baseColumn := range baseColumns {
|
for i, baseColumn := range baseColumns {
|
||||||
joinColumn := joinColumns[i]
|
joinColumn := joinColumns[i]
|
||||||
|
|
||||||
if f := t.fieldWithLock(baseColumn); f != nil {
|
if f := t.FieldMap[baseColumn]; f != nil {
|
||||||
rel.BaseFields = append(rel.BaseFields, f)
|
rel.BaseFields = append(rel.BaseFields, f)
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
|
@ -528,7 +585,7 @@ func (t *Table) belongsToRelation(field *Field) *Relation {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
if f := joinTable.fieldWithLock(joinColumn); f != nil {
|
if f := joinTable.FieldMap[joinColumn]; f != nil {
|
||||||
rel.JoinFields = append(rel.JoinFields, f)
|
rel.JoinFields = append(rel.JoinFields, f)
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
|
@ -544,12 +601,12 @@ func (t *Table) belongsToRelation(field *Field) *Relation {
|
||||||
fkPrefix := internal.Underscore(field.GoName) + "_"
|
fkPrefix := internal.Underscore(field.GoName) + "_"
|
||||||
for _, joinPK := range joinTable.PKs {
|
for _, joinPK := range joinTable.PKs {
|
||||||
fkName := fkPrefix + joinPK.Name
|
fkName := fkPrefix + joinPK.Name
|
||||||
if fk := t.fieldWithLock(fkName); fk != nil {
|
if fk := t.FieldMap[fkName]; fk != nil {
|
||||||
rel.BaseFields = append(rel.BaseFields, fk)
|
rel.BaseFields = append(rel.BaseFields, fk)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if fk := t.fieldWithLock(joinPK.Name); fk != nil {
|
if fk := t.FieldMap[joinPK.Name]; fk != nil {
|
||||||
rel.BaseFields = append(rel.BaseFields, fk)
|
rel.BaseFields = append(rel.BaseFields, fk)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -568,7 +625,7 @@ func (t *Table) hasOneRelation(field *Field) *Relation {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
joinTable := t.dialect.Tables().Ref(field.IndirectType)
|
joinTable := t.dialect.Tables().InProgress(field.IndirectType)
|
||||||
rel := &Relation{
|
rel := &Relation{
|
||||||
Type: HasOneRelation,
|
Type: HasOneRelation,
|
||||||
Field: field,
|
Field: field,
|
||||||
|
@ -582,7 +639,7 @@ func (t *Table) hasOneRelation(field *Field) *Relation {
|
||||||
if join, ok := field.Tag.Options["join"]; ok {
|
if join, ok := field.Tag.Options["join"]; ok {
|
||||||
baseColumns, joinColumns := parseRelationJoin(join)
|
baseColumns, joinColumns := parseRelationJoin(join)
|
||||||
for i, baseColumn := range baseColumns {
|
for i, baseColumn := range baseColumns {
|
||||||
if f := t.fieldWithLock(baseColumn); f != nil {
|
if f := t.FieldMap[baseColumn]; f != nil {
|
||||||
rel.BaseFields = append(rel.BaseFields, f)
|
rel.BaseFields = append(rel.BaseFields, f)
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
|
@ -592,7 +649,7 @@ func (t *Table) hasOneRelation(field *Field) *Relation {
|
||||||
}
|
}
|
||||||
|
|
||||||
joinColumn := joinColumns[i]
|
joinColumn := joinColumns[i]
|
||||||
if f := joinTable.fieldWithLock(joinColumn); f != nil {
|
if f := joinTable.FieldMap[joinColumn]; f != nil {
|
||||||
rel.JoinFields = append(rel.JoinFields, f)
|
rel.JoinFields = append(rel.JoinFields, f)
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
|
@ -608,12 +665,12 @@ func (t *Table) hasOneRelation(field *Field) *Relation {
|
||||||
fkPrefix := internal.Underscore(t.ModelName) + "_"
|
fkPrefix := internal.Underscore(t.ModelName) + "_"
|
||||||
for _, pk := range t.PKs {
|
for _, pk := range t.PKs {
|
||||||
fkName := fkPrefix + pk.Name
|
fkName := fkPrefix + pk.Name
|
||||||
if f := joinTable.fieldWithLock(fkName); f != nil {
|
if f := joinTable.FieldMap[fkName]; f != nil {
|
||||||
rel.JoinFields = append(rel.JoinFields, f)
|
rel.JoinFields = append(rel.JoinFields, f)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if f := joinTable.fieldWithLock(pk.Name); f != nil {
|
if f := joinTable.FieldMap[pk.Name]; f != nil {
|
||||||
rel.JoinFields = append(rel.JoinFields, f)
|
rel.JoinFields = append(rel.JoinFields, f)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -638,7 +695,7 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
joinTable := t.dialect.Tables().Ref(indirectType(field.IndirectType.Elem()))
|
joinTable := t.dialect.Tables().InProgress(indirectType(field.IndirectType.Elem()))
|
||||||
polymorphicValue, isPolymorphic := field.Tag.Option("polymorphic")
|
polymorphicValue, isPolymorphic := field.Tag.Option("polymorphic")
|
||||||
rel := &Relation{
|
rel := &Relation{
|
||||||
Type: HasManyRelation,
|
Type: HasManyRelation,
|
||||||
|
@ -662,7 +719,7 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if f := t.fieldWithLock(baseColumn); f != nil {
|
if f := t.FieldMap[baseColumn]; f != nil {
|
||||||
rel.BaseFields = append(rel.BaseFields, f)
|
rel.BaseFields = append(rel.BaseFields, f)
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
|
@ -671,7 +728,7 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
if f := joinTable.fieldWithLock(joinColumn); f != nil {
|
if f := joinTable.FieldMap[joinColumn]; f != nil {
|
||||||
rel.JoinFields = append(rel.JoinFields, f)
|
rel.JoinFields = append(rel.JoinFields, f)
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
|
@ -689,12 +746,12 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
||||||
|
|
||||||
for _, pk := range t.PKs {
|
for _, pk := range t.PKs {
|
||||||
joinColumn := fkPrefix + pk.Name
|
joinColumn := fkPrefix + pk.Name
|
||||||
if fk := joinTable.fieldWithLock(joinColumn); fk != nil {
|
if fk := joinTable.FieldMap[joinColumn]; fk != nil {
|
||||||
rel.JoinFields = append(rel.JoinFields, fk)
|
rel.JoinFields = append(rel.JoinFields, fk)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if fk := joinTable.fieldWithLock(pk.Name); fk != nil {
|
if fk := joinTable.FieldMap[pk.Name]; fk != nil {
|
||||||
rel.JoinFields = append(rel.JoinFields, fk)
|
rel.JoinFields = append(rel.JoinFields, fk)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -708,7 +765,7 @@ func (t *Table) hasManyRelation(field *Field) *Relation {
|
||||||
}
|
}
|
||||||
|
|
||||||
if isPolymorphic {
|
if isPolymorphic {
|
||||||
rel.PolymorphicField = joinTable.fieldWithLock(polymorphicColumn)
|
rel.PolymorphicField = joinTable.FieldMap[polymorphicColumn]
|
||||||
if rel.PolymorphicField == nil {
|
if rel.PolymorphicField == nil {
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
"bun: %s has-many %s: %s must have polymorphic column %s",
|
"bun: %s has-many %s: %s must have polymorphic column %s",
|
||||||
|
@ -732,7 +789,7 @@ func (t *Table) m2mRelation(field *Field) *Relation {
|
||||||
t.TypeName, field.GoName, field.IndirectType.Kind(),
|
t.TypeName, field.GoName, field.IndirectType.Kind(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
joinTable := t.dialect.Tables().Ref(indirectType(field.IndirectType.Elem()))
|
joinTable := t.dialect.Tables().InProgress(indirectType(field.IndirectType.Elem()))
|
||||||
|
|
||||||
if err := t.CheckPKs(); err != nil {
|
if err := t.CheckPKs(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -805,40 +862,6 @@ func (t *Table) m2mRelation(field *Field) *Relation {
|
||||||
return rel
|
return rel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) inlineFields(field *Field, seen map[reflect.Type]struct{}) {
|
|
||||||
if seen == nil {
|
|
||||||
seen = map[reflect.Type]struct{}{t.Type: {}}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := seen[field.IndirectType]; ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
seen[field.IndirectType] = struct{}{}
|
|
||||||
|
|
||||||
joinTable := t.dialect.Tables().Ref(field.IndirectType)
|
|
||||||
for _, f := range joinTable.allFields {
|
|
||||||
f = f.Clone()
|
|
||||||
f.GoName = field.GoName + "_" + f.GoName
|
|
||||||
f.Name = field.Name + "__" + f.Name
|
|
||||||
f.SQLName = t.quoteIdent(f.Name)
|
|
||||||
f.Index = withIndex(field.Index, f.Index)
|
|
||||||
|
|
||||||
t.fieldsMapMu.Lock()
|
|
||||||
if _, ok := t.FieldMap[f.Name]; !ok {
|
|
||||||
t.FieldMap[f.Name] = f
|
|
||||||
}
|
|
||||||
t.fieldsMapMu.Unlock()
|
|
||||||
|
|
||||||
if f.IndirectType.Kind() != reflect.Struct {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := seen[f.IndirectType]; !ok {
|
|
||||||
t.inlineFields(f, seen)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
func (t *Table) Dialect() Dialect { return t.dialect }
|
func (t *Table) Dialect() Dialect { return t.dialect }
|
||||||
|
@ -890,7 +913,7 @@ func isKnownTableOption(name string) bool {
|
||||||
func isKnownFieldOption(name string) bool {
|
func isKnownFieldOption(name string) bool {
|
||||||
switch name {
|
switch name {
|
||||||
case "column",
|
case "column",
|
||||||
"alias",
|
"alt",
|
||||||
"type",
|
"type",
|
||||||
"array",
|
"array",
|
||||||
"hstore",
|
"hstore",
|
||||||
|
@ -931,15 +954,6 @@ func isKnownFKRule(name string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeField(fields []*Field, field *Field) []*Field {
|
|
||||||
for i, f := range fields {
|
|
||||||
if f == field {
|
|
||||||
return append(fields[:i], fields[i+1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fields
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseRelationJoin(join []string) ([]string, []string) {
|
func parseRelationJoin(join []string) ([]string, []string) {
|
||||||
var ss []string
|
var ss []string
|
||||||
if len(join) == 1 {
|
if len(join) == 1 {
|
||||||
|
@ -1026,7 +1040,7 @@ func softDeleteFieldUpdaterFallback(field *Field) func(fv reflect.Value, tm time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func withIndex(a, b []int) []int {
|
func makeIndex(a, b []int) []int {
|
||||||
dest := make([]int, 0, len(a)+len(b))
|
dest := make([]int, 0, len(a)+len(b))
|
||||||
dest = append(dest, a...)
|
dest = append(dest, a...)
|
||||||
dest = append(dest, b...)
|
dest = append(dest, b...)
|
||||||
|
|
|
@ -6,48 +6,19 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type tableInProgress struct {
|
|
||||||
table *Table
|
|
||||||
|
|
||||||
init1Once sync.Once
|
|
||||||
init2Once sync.Once
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTableInProgress(table *Table) *tableInProgress {
|
|
||||||
return &tableInProgress{
|
|
||||||
table: table,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (inp *tableInProgress) init1() bool {
|
|
||||||
var inited bool
|
|
||||||
inp.init1Once.Do(func() {
|
|
||||||
inp.table.init1()
|
|
||||||
inited = true
|
|
||||||
})
|
|
||||||
return inited
|
|
||||||
}
|
|
||||||
|
|
||||||
func (inp *tableInProgress) init2() bool {
|
|
||||||
var inited bool
|
|
||||||
inp.init2Once.Do(func() {
|
|
||||||
inp.table.init2()
|
|
||||||
inited = true
|
|
||||||
})
|
|
||||||
return inited
|
|
||||||
}
|
|
||||||
|
|
||||||
type Tables struct {
|
type Tables struct {
|
||||||
dialect Dialect
|
dialect Dialect
|
||||||
tables sync.Map
|
tables sync.Map
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
seen map[reflect.Type]*Table
|
||||||
inProgress map[reflect.Type]*tableInProgress
|
inProgress map[reflect.Type]*tableInProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTables(dialect Dialect) *Tables {
|
func NewTables(dialect Dialect) *Tables {
|
||||||
return &Tables{
|
return &Tables{
|
||||||
dialect: dialect,
|
dialect: dialect,
|
||||||
|
seen: make(map[reflect.Type]*Table),
|
||||||
inProgress: make(map[reflect.Type]*tableInProgress),
|
inProgress: make(map[reflect.Type]*tableInProgress),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +33,7 @@ func (t *Tables) Get(typ reflect.Type) *Table {
|
||||||
return t.table(typ, false)
|
return t.table(typ, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tables) Ref(typ reflect.Type) *Table {
|
func (t *Tables) InProgress(typ reflect.Type) *Table {
|
||||||
return t.table(typ, true)
|
return t.table(typ, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +58,7 @@ func (t *Tables) table(typ reflect.Type, allowInProgress bool) *Table {
|
||||||
|
|
||||||
inProgress := t.inProgress[typ]
|
inProgress := t.inProgress[typ]
|
||||||
if inProgress == nil {
|
if inProgress == nil {
|
||||||
table = newTable(t.dialect, typ)
|
table = newTable(t.dialect, typ, t.seen, false)
|
||||||
inProgress = newTableInProgress(table)
|
inProgress = newTableInProgress(table)
|
||||||
t.inProgress[typ] = inProgress
|
t.inProgress[typ] = inProgress
|
||||||
} else {
|
} else {
|
||||||
|
@ -96,12 +67,11 @@ func (t *Tables) table(typ reflect.Type, allowInProgress bool) *Table {
|
||||||
|
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
|
|
||||||
inProgress.init1()
|
|
||||||
if allowInProgress {
|
if allowInProgress {
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
if !inProgress.init2() {
|
if !inProgress.init() {
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,3 +119,24 @@ func (t *Tables) ByName(name string) *Table {
|
||||||
})
|
})
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type tableInProgress struct {
|
||||||
|
table *Table
|
||||||
|
|
||||||
|
initOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTableInProgress(table *Table) *tableInProgress {
|
||||||
|
return &tableInProgress{
|
||||||
|
table: table,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (inp *tableInProgress) init() bool {
|
||||||
|
var inited bool
|
||||||
|
inp.initOnce.Do(func() {
|
||||||
|
inp.table.init()
|
||||||
|
inited = true
|
||||||
|
})
|
||||||
|
return inited
|
||||||
|
}
|
||||||
|
|
|
@ -2,5 +2,5 @@ package bun
|
||||||
|
|
||||||
// Version is the current release version.
|
// Version is the current release version.
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return "1.1.17"
|
return "1.2.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ func (t *dbInstrum) withSpan(
|
||||||
trace.WithSpanKind(trace.SpanKindClient),
|
trace.WithSpanKind(trace.SpanKindClient),
|
||||||
trace.WithAttributes(attrs...))
|
trace.WithAttributes(attrs...))
|
||||||
err := fn(ctx, span)
|
err := fn(ctx, span)
|
||||||
span.End()
|
defer span.End()
|
||||||
|
|
||||||
if query != "" {
|
if query != "" {
|
||||||
t.queryHistogram.Record(ctx, time.Since(startTime).Milliseconds(), metric.WithAttributes(t.attrs...))
|
t.queryHistogram.Record(ctx, time.Since(startTime).Milliseconds(), metric.WithAttributes(t.attrs...))
|
||||||
|
|
|
@ -2,5 +2,5 @@ package otelsql
|
||||||
|
|
||||||
// Version is the current release version.
|
// Version is the current release version.
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return "0.2.3"
|
return "0.2.4"
|
||||||
}
|
}
|
||||||
|
|
|
@ -852,8 +852,8 @@ github.com/ugorji/go/codec
|
||||||
github.com/ulule/limiter/v3
|
github.com/ulule/limiter/v3
|
||||||
github.com/ulule/limiter/v3/drivers/store/common
|
github.com/ulule/limiter/v3/drivers/store/common
|
||||||
github.com/ulule/limiter/v3/drivers/store/memory
|
github.com/ulule/limiter/v3/drivers/store/memory
|
||||||
# github.com/uptrace/bun v1.1.17
|
# github.com/uptrace/bun v1.2.1
|
||||||
## explicit; go 1.19
|
## explicit; go 1.21
|
||||||
github.com/uptrace/bun
|
github.com/uptrace/bun
|
||||||
github.com/uptrace/bun/dialect
|
github.com/uptrace/bun/dialect
|
||||||
github.com/uptrace/bun/dialect/feature
|
github.com/uptrace/bun/dialect/feature
|
||||||
|
@ -864,17 +864,17 @@ github.com/uptrace/bun/internal/parser
|
||||||
github.com/uptrace/bun/internal/tagparser
|
github.com/uptrace/bun/internal/tagparser
|
||||||
github.com/uptrace/bun/migrate
|
github.com/uptrace/bun/migrate
|
||||||
github.com/uptrace/bun/schema
|
github.com/uptrace/bun/schema
|
||||||
# github.com/uptrace/bun/dialect/pgdialect v1.1.17
|
# github.com/uptrace/bun/dialect/pgdialect v1.2.1
|
||||||
## explicit; go 1.19
|
## explicit; go 1.21
|
||||||
github.com/uptrace/bun/dialect/pgdialect
|
github.com/uptrace/bun/dialect/pgdialect
|
||||||
# github.com/uptrace/bun/dialect/sqlitedialect v1.1.17
|
# github.com/uptrace/bun/dialect/sqlitedialect v1.2.1
|
||||||
## explicit; go 1.19
|
## explicit; go 1.21
|
||||||
github.com/uptrace/bun/dialect/sqlitedialect
|
github.com/uptrace/bun/dialect/sqlitedialect
|
||||||
# github.com/uptrace/bun/extra/bunotel v1.1.17
|
# github.com/uptrace/bun/extra/bunotel v1.2.1
|
||||||
## explicit; go 1.19
|
## explicit; go 1.21
|
||||||
github.com/uptrace/bun/extra/bunotel
|
github.com/uptrace/bun/extra/bunotel
|
||||||
# github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.3
|
# github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.4
|
||||||
## explicit; go 1.18
|
## explicit; go 1.21
|
||||||
github.com/uptrace/opentelemetry-go-extra/otelsql
|
github.com/uptrace/opentelemetry-go-extra/otelsql
|
||||||
# github.com/vmihailenco/msgpack/v5 v5.4.1
|
# github.com/vmihailenco/msgpack/v5 v5.4.1
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
|
|
Loading…
Reference in New Issue