Compare commits
22 Commits
Author | SHA1 | Date |
---|---|---|
|
174f52d948 | |
|
5801184782 | |
|
a84251e20d | |
|
afb9845d70 | |
|
19cbc17f35 | |
|
7c9d4c28dc | |
|
328bac49e0 | |
|
5af4d90edb | |
|
a4e2984934 | |
|
b61bdcf676 | |
|
85d358da90 | |
|
eb73f8d63b | |
|
218e470106 | |
|
b31ca726e2 | |
|
9dfbdbe878 | |
|
aba3ad40a6 | |
|
f588822664 | |
|
6cc373885c | |
|
1f6c2d45c5 | |
|
f7b4947db0 | |
|
4f471d7ea6 | |
|
fa12207e07 |
|
@ -8,6 +8,7 @@ import (
|
||||||
"git.bit5.ru/backend/meta"
|
"git.bit5.ru/backend/meta"
|
||||||
|
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/codes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataCollection struct {
|
type DataCollection struct {
|
||||||
|
@ -41,7 +42,10 @@ func (coll *DataCollection) Save(ctx context.Context) error {
|
||||||
fields := coll.GetDbFields()
|
fields := coll.GetDbFields()
|
||||||
countFields := len(fields)
|
countFields := len(fields)
|
||||||
if countFields == 0 {
|
if countFields == 0 {
|
||||||
return errors.New("Fields list is empty")
|
err := errors.New("Fields list is empty")
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
countRows := len(coll.Items)
|
countRows := len(coll.Items)
|
||||||
|
@ -60,10 +64,21 @@ func (coll *DataCollection) Save(ctx context.Context) error {
|
||||||
|
|
||||||
// NOTE: performance fix: if none of rows have mask we can save all data by one sql query
|
// NOTE: performance fix: if none of rows have mask we can save all data by one sql query
|
||||||
if allDataWithoutMask {
|
if allDataWithoutMask {
|
||||||
return coll.saveWithoutMask(ctx)
|
if err := coll.saveWithoutMask(ctx); err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return coll.saveByMask(ctx)
|
if err := coll.saveByMask(ctx); err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (coll *DataCollection) saveByMask(ctx context.Context) error {
|
func (coll *DataCollection) saveByMask(ctx context.Context) error {
|
||||||
|
@ -77,7 +92,8 @@ func (coll *DataCollection) saveByMask(ctx context.Context) error {
|
||||||
tableName := coll.GetTableName()
|
tableName := coll.GetTableName()
|
||||||
|
|
||||||
span.SetAttributes(
|
span.SetAttributes(
|
||||||
attribute.String("db.sql.table", tableName),
|
attribute.String("table", tableName),
|
||||||
|
attribute.Int("field_amount", countFields),
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, item := range coll.Items {
|
for _, item := range coll.Items {
|
||||||
|
@ -110,7 +126,10 @@ func (coll *DataCollection) saveByMask(ctx context.Context) error {
|
||||||
log_len = 200
|
log_len = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.Errorf("%s (%s)", err.Error(), sqlSmt[0:log_len])
|
resultErr := errors.Errorf("%s (%s)", err.Error(), sqlSmt[0:log_len])
|
||||||
|
span.RecordError(resultErr)
|
||||||
|
span.SetStatus(codes.Error, resultErr.Error())
|
||||||
|
return resultErr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -128,7 +147,7 @@ func (coll *DataCollection) saveWithoutMask(ctx context.Context) error {
|
||||||
countRows := len(coll.Items)
|
countRows := len(coll.Items)
|
||||||
|
|
||||||
span.SetAttributes(
|
span.SetAttributes(
|
||||||
attribute.String("db.sql.table", tableName),
|
attribute.String("table", tableName),
|
||||||
attribute.Int("field_amount", countFields),
|
attribute.Int("field_amount", countFields),
|
||||||
attribute.Int("item_amount", countRows),
|
attribute.Int("item_amount", countRows),
|
||||||
)
|
)
|
||||||
|
@ -143,7 +162,10 @@ func (coll *DataCollection) saveWithoutMask(ctx context.Context) error {
|
||||||
if ownerValue == uint32(0) {
|
if ownerValue == uint32(0) {
|
||||||
rows[start+coll.ownerFieldIndex] = coll.OwnerId
|
rows[start+coll.ownerFieldIndex] = coll.OwnerId
|
||||||
} else if ownerValue != coll.OwnerId {
|
} else if ownerValue != coll.OwnerId {
|
||||||
return errors.Errorf("Wrong owner_id in %s value %d (!= %d)", tableName, ownerValue, coll.OwnerId)
|
err := errors.Errorf("Wrong owner_id in %s value %d (!= %d)", tableName, ownerValue, coll.OwnerId)
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
offset++
|
offset++
|
||||||
}
|
}
|
||||||
|
@ -151,7 +173,10 @@ func (coll *DataCollection) saveWithoutMask(ctx context.Context) error {
|
||||||
sqlSmt := createInsertSQLForFields(ctx, tableName, fields, countRows)
|
sqlSmt := createInsertSQLForFields(ctx, tableName, fields, countRows)
|
||||||
_, err := coll.Db.UpdateBySQL(sqlSmt, rows...).Exec()
|
_, err := coll.Db.UpdateBySQL(sqlSmt, rows...).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("error: %s, sql: %s", err.Error(), sqlSmt)
|
resultErr := errors.Errorf("error: %s, sql: %s", err.Error(), sqlSmt)
|
||||||
|
span.RecordError(resultErr)
|
||||||
|
span.SetStatus(codes.Error, resultErr.Error())
|
||||||
|
return resultErr
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -3,10 +3,11 @@ module git.bit5.ru/backend/dbmeta
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.bit5.ru/backend/db v1.2.3
|
git.bit5.ru/backend/db v1.2.6
|
||||||
git.bit5.ru/backend/errors v1.0.0
|
git.bit5.ru/backend/errors v1.0.0
|
||||||
git.bit5.ru/backend/meta v1.0.0
|
git.bit5.ru/backend/meta v1.0.0
|
||||||
github.com/go-logr/stdr v1.2.2
|
github.com/go-logr/stdr v1.2.2
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
go.opentelemetry.io/otel v1.11.1
|
go.opentelemetry.io/otel v1.11.1
|
||||||
|
go.opentelemetry.io/otel/trace v1.11.1
|
||||||
)
|
)
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -1,7 +1,7 @@
|
||||||
git.bit5.ru/backend/db v1.2.3 h1:FYGUbu7nYMny9CoTU6oLrJuQdn+xG42cAHkWI6JLGgE=
|
git.bit5.ru/backend/db v1.2.6 h1:ANfRTQ+C4BaMKbG+7onjET7qCcsFwq71dbolt0Po7Y4=
|
||||||
git.bit5.ru/backend/db v1.2.3/go.mod h1:2PB9QennBZaH8u5i3IvnuVaWnAK5Ck5kCrJ9+5ZnQp8=
|
git.bit5.ru/backend/db v1.2.6/go.mod h1:+1VkFgSf3zkGlHmG3gw5HyWBoucZDQ+bixQ6rpO6AqU=
|
||||||
git.bit5.ru/backend/dbr v1.2.0 h1:SQndOC9KW/jPGRSFSPYRqmMd+EHEyZHWDO9B+imEEzU=
|
git.bit5.ru/backend/dbr v1.3.1 h1:O3fy+aztnNVzto/nMcydd9BVahAJTXPE8VuGY3dC1NY=
|
||||||
git.bit5.ru/backend/dbr v1.2.0/go.mod h1:3iCyHEkyj2M+lx3fSlv3lC1r5cLZZz+6QLVCml7ZAy8=
|
git.bit5.ru/backend/dbr v1.3.1/go.mod h1:oVVFv6hIzFkO4Wy0KcS4CYqkBjW1kFHYNLcmKmDlPow=
|
||||||
git.bit5.ru/backend/errors v1.0.0 h1:WWJ0sly44q1HQjN01X75ZAGKZwwY5Ml+XVDXMjCkToA=
|
git.bit5.ru/backend/errors v1.0.0 h1:WWJ0sly44q1HQjN01X75ZAGKZwwY5Ml+XVDXMjCkToA=
|
||||||
git.bit5.ru/backend/errors v1.0.0/go.mod h1:75faRwsnpM0Se00/Bh7fysWQXV8oMjNJFQ6f7+r9k3Y=
|
git.bit5.ru/backend/errors v1.0.0/go.mod h1:75faRwsnpM0Se00/Bh7fysWQXV8oMjNJFQ6f7+r9k3Y=
|
||||||
git.bit5.ru/backend/meta v1.0.0 h1:1mZgEoOSA/P+IrnKkoiULpFUFX3JxyxGU6OXVn7j2kY=
|
git.bit5.ru/backend/meta v1.0.0 h1:1mZgEoOSA/P+IrnKkoiULpFUFX3JxyxGU6OXVn7j2kY=
|
||||||
|
|
118
save.go
118
save.go
|
@ -12,10 +12,12 @@ import (
|
||||||
|
|
||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/codes"
|
||||||
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
|
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
const tracerName = "game/dbmeta"
|
const tracerName = "git.bit5.ru/backend/dbmeta"
|
||||||
|
|
||||||
var tracer = otel.Tracer(tracerName)
|
var tracer = otel.Tracer(tracerName)
|
||||||
|
|
||||||
|
@ -48,6 +50,8 @@ func SaveRow(ctx context.Context, db *db.DBC, dataItem meta.IMetaStruct) error {
|
||||||
|
|
||||||
info, err := makeDataRowInfo(dataItem)
|
info, err := makeDataRowInfo(dataItem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,25 +80,46 @@ func SaveRow(ctx context.Context, db *db.DBC, dataItem meta.IMetaStruct) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(fields) == 0 {
|
if len(fields) == 0 {
|
||||||
return errors.New("Fields list is empty")
|
err := errors.New("Fields list is empty")
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tableName := info.tableName
|
tableName := info.tableName
|
||||||
sqlSmt := createInsertSQLForFields(ctx, tableName, fields, 1 /*one_row*/)
|
sqlSmt := createInsertSQLForFields(ctx, tableName, fields, 1 /*one_row*/)
|
||||||
|
|
||||||
span.SetAttributes(
|
span.SetAttributes(
|
||||||
|
semconv.DBSystemKey.String("mysql"),
|
||||||
semconv.DBSQLTableKey.String(tableName),
|
semconv.DBSQLTableKey.String(tableName),
|
||||||
semconv.DBStatementKey.String(sqlSmt),
|
semconv.DBStatementKey.String(sqlSmt),
|
||||||
|
semconv.DBOperationKey.String("INSERT"),
|
||||||
)
|
)
|
||||||
|
|
||||||
updateBuilder := db.UpdateBySQL(sqlSmt, params...)
|
updateBuilder := db.UpdateBySQL(sqlSmt, params...)
|
||||||
|
|
||||||
res, err := updateBuilder.Exec()
|
res, err := updateBuilder.ExecContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if len(sqlSmt) > 200 {
|
if len(sqlSmt) > 200 {
|
||||||
sqlSmt = sqlSmt[0:200]
|
sqlSmt = sqlSmt[0:200]
|
||||||
}
|
}
|
||||||
return errors.Errorf("%s (%s)", err.Error(), sqlSmt)
|
|
||||||
|
span.SetAttributes(
|
||||||
|
attribute.Int("sql_param_amount", len(params)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Convert SQL request parameters to slice of strings.
|
||||||
|
paramStrs := convertInterfacesToStrings(ctx, params)
|
||||||
|
if len(paramStrs) > 0 {
|
||||||
|
span.SetAttributes(
|
||||||
|
attribute.StringSlice("sql_params", paramStrs),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
resultErr := errors.Errorf("Can not execute SaveRow. Got error from updateBuilder.ExecContext. %s (%s)", err.Error(), sqlSmt)
|
||||||
|
span.RecordError(resultErr)
|
||||||
|
span.SetStatus(codes.Error, resultErr.Error())
|
||||||
|
return resultErr
|
||||||
}
|
}
|
||||||
|
|
||||||
insertId, _ := res.LastInsertId()
|
insertId, _ := res.LastInsertId()
|
||||||
|
@ -105,6 +130,20 @@ func SaveRow(ctx context.Context, db *db.DBC, dataItem meta.IMetaStruct) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertInterfacesToStrings(ctx context.Context, items []interface{}) []string {
|
||||||
|
itemAmount := len(items)
|
||||||
|
if itemAmount == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
strs := make([]string, itemAmount)
|
||||||
|
for i, item := range items {
|
||||||
|
strs[i] = fmt.Sprint(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strs
|
||||||
|
}
|
||||||
|
|
||||||
func SaveMetaRootStruct(
|
func SaveMetaRootStruct(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
db *db.DBC,
|
db *db.DBC,
|
||||||
|
@ -114,7 +153,11 @@ func SaveMetaRootStruct(
|
||||||
deltaSave bool,
|
deltaSave bool,
|
||||||
) error {
|
) error {
|
||||||
|
|
||||||
ctx, span := tracer.Start(ctx, "SaveMetaRootStruct")
|
spanAttrs := trace.WithAttributes(
|
||||||
|
attribute.Int64("owner.id", int64(ownerId)),
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx, span := tracer.Start(ctx, "SaveMetaRootStruct", spanAttrs)
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
dataItem := reflect.ValueOf(data)
|
dataItem := reflect.ValueOf(data)
|
||||||
|
@ -164,11 +207,15 @@ func SaveMetaRootStruct(
|
||||||
switch tfield.Kind() {
|
switch tfield.Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
if err := SaveMetaCollection(ctx, db, dataItem.Field(i), ownerId, removedIds, deltaSave); err != nil {
|
if err := SaveMetaCollection(ctx, db, dataItem.Field(i), ownerId, removedIds, deltaSave); err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
return errors.WithMessagef(err, "Can not execute SaveMetaRootStruct. Got error from SaveMetaCollection. ownerId: %d.", ownerId)
|
return errors.WithMessagef(err, "Can not execute SaveMetaRootStruct. Got error from SaveMetaCollection. ownerId: %d.", ownerId)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if err := saveStruct(ctx, db, dataItem.Field(i), ownerId); err != nil {
|
if err := saveStruct(ctx, db, dataItem.Field(i), ownerId); err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
return errors.WithMessagef(err, "Can not execute SaveMetaRootStruct. Got error from saveStruct. ownerId: %d.", ownerId)
|
return errors.WithMessagef(err, "Can not execute SaveMetaRootStruct. Got error from saveStruct. ownerId: %d.", ownerId)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -185,7 +232,12 @@ func SaveMetaRootStruct(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveStruct(ctx context.Context, db *db.DBC, dataItem reflect.Value, ownerId uint32) error {
|
func saveStruct(
|
||||||
|
ctx context.Context,
|
||||||
|
db *db.DBC,
|
||||||
|
dataItem reflect.Value,
|
||||||
|
ownerId uint32,
|
||||||
|
) error {
|
||||||
|
|
||||||
ctx, span := tracer.Start(ctx, "saveStruct")
|
ctx, span := tracer.Start(ctx, "saveStruct")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
@ -201,14 +253,20 @@ func saveStruct(ctx context.Context, db *db.DBC, dataItem reflect.Value, ownerId
|
||||||
row, _ = dataItem.Addr().Interface().(meta.IMetaStruct)
|
row, _ = dataItem.Addr().Interface().(meta.IMetaStruct)
|
||||||
}
|
}
|
||||||
if row == nil {
|
if row == nil {
|
||||||
return errors.Errorf("Couldn't convert to IMetaStruct: %s", mType.Name())
|
err := errors.Errorf("Couldn't convert to IMetaStruct: %s", mType.Name())
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
props := *row.CLASS_PROPS()
|
props := *row.CLASS_PROPS()
|
||||||
if ownerField, ok := props["owner"]; ok {
|
if ownerField, ok := props["owner"]; ok {
|
||||||
field := dataItem.FieldByName(strings.Title(ownerField))
|
field := dataItem.FieldByName(strings.Title(ownerField))
|
||||||
if !field.IsValid() {
|
if !field.IsValid() {
|
||||||
return errors.Errorf("Owner field \"%s\" is not found in struct \"%s\"", ownerField, mType.Name())
|
err := errors.Errorf("Owner field \"%s\" is not found in struct \"%s\"", ownerField, mType.Name())
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// enforcing ownerId
|
// enforcing ownerId
|
||||||
|
@ -218,17 +276,34 @@ func saveStruct(ctx context.Context, db *db.DBC, dataItem reflect.Value, ownerId
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SaveRow(ctx, db, row)
|
if err := SaveRow(ctx, db, row); err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return errors.WithMessagef(err, "Can not execute saveStruct. Got error from SaveRow. ownerId: %d.", ownerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveMetaCollection(ctx context.Context, db *db.DBC, slice reflect.Value, ownerId uint32, removedIds meta.IRemovedIds, deltaSave bool) error {
|
func SaveMetaCollection(
|
||||||
|
ctx context.Context,
|
||||||
|
db *db.DBC,
|
||||||
|
slice reflect.Value,
|
||||||
|
ownerId uint32,
|
||||||
|
removedIds meta.IRemovedIds,
|
||||||
|
deltaSave bool,
|
||||||
|
) error {
|
||||||
|
|
||||||
ctx, span := tracer.Start(ctx, "SaveMetaCollection")
|
ctx, span := tracer.Start(ctx, "SaveMetaCollection")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
if slice.Type().Kind() != reflect.Slice {
|
if slice.Type().Kind() != reflect.Slice {
|
||||||
return errors.Errorf("It isn't slice: %s", slice.Type().Kind())
|
err := errors.Errorf("It isn't slice: %s", slice.Type().Kind())
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sliceItem := reflect.New(slice.Type().Elem().Elem())
|
sliceItem := reflect.New(slice.Type().Elem().Elem())
|
||||||
if sliceItem.Type().Kind() != reflect.Ptr {
|
if sliceItem.Type().Kind() != reflect.Ptr {
|
||||||
sliceItem = sliceItem.Addr()
|
sliceItem = sliceItem.Addr()
|
||||||
|
@ -240,29 +315,42 @@ func SaveMetaCollection(ctx context.Context, db *db.DBC, slice reflect.Value, ow
|
||||||
}
|
}
|
||||||
|
|
||||||
if row == nil {
|
if row == nil {
|
||||||
return errors.Errorf("Couldn't convert to IMetaStruct: %s", sliceItem.Kind())
|
err := errors.Errorf("Couldn't convert to IMetaStruct: %s", sliceItem.Kind())
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
item, _ := sliceItem.Interface().(meta.IMetaDataItem)
|
item, _ := sliceItem.Interface().(meta.IMetaDataItem)
|
||||||
if item == nil {
|
if item == nil {
|
||||||
return errors.Errorf("Couldn't convert to IMetaDataItem: %s", slice.Type())
|
err := errors.Errorf("Couldn't convert to IMetaDataItem: %s", slice.Type())
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !deltaSave {
|
if !deltaSave {
|
||||||
cond := fmt.Sprintf("`%s`=%d ", item.GetOwnerFieldName(), ownerId)
|
cond := fmt.Sprintf("`%s`=%d ", item.GetOwnerFieldName(), ownerId)
|
||||||
_, err := db.DeleteFrom(item.GetDbTableName()).Where(cond).Exec()
|
_, err := db.DeleteFrom(item.GetDbTableName()).Where(cond).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collection, err := NewDataCollection(db, ownerId, "", item)
|
collection, err := NewDataCollection(db, ownerId, "", item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for ind := 0; ind < slice.Len(); ind++ {
|
for ind := 0; ind < slice.Len(); ind++ {
|
||||||
ind_item, err := convertToIdataItem(slice.Index(ind))
|
ind_item, err := convertToIdataItem(slice.Index(ind))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// NOTE: we don't check here for error on purpose, here it's considered to be OK
|
// NOTE: we don't check here for error on purpose, here it's considered to be OK
|
||||||
|
@ -270,6 +358,8 @@ func SaveMetaCollection(ctx context.Context, db *db.DBC, slice reflect.Value, ow
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := collection.Save(ctx); err != nil {
|
if err := collection.Save(ctx); err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +369,8 @@ func SaveMetaCollection(ctx context.Context, db *db.DBC, slice reflect.Value, ow
|
||||||
if removedIds.HasList(classId) {
|
if removedIds.HasList(classId) {
|
||||||
err := deleteByIds(db, ownerId, item, removedIds.GetList(classId))
|
err := deleteByIds(db, ownerId, item, removedIds.GetList(classId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
span.RecordError(err)
|
||||||
|
span.SetStatus(codes.Error, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
179
save_test.go
179
save_test.go
|
@ -10,8 +10,8 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"git.bit5.ru/backend/dbmeta"
|
|
||||||
"git.bit5.ru/backend/db"
|
"git.bit5.ru/backend/db"
|
||||||
|
"git.bit5.ru/backend/dbmeta"
|
||||||
"git.bit5.ru/backend/meta"
|
"git.bit5.ru/backend/meta"
|
||||||
|
|
||||||
"github.com/go-logr/stdr"
|
"github.com/go-logr/stdr"
|
||||||
|
@ -19,38 +19,40 @@ import (
|
||||||
|
|
||||||
var logger = stdr.New(log.New(os.Stdout, "", log.Lshortfile))
|
var logger = stdr.New(log.New(os.Stdout, "", log.Lshortfile))
|
||||||
|
|
||||||
//TODO create the tables below before tests
|
|
||||||
//CREATE TABLE `player` (
|
|
||||||
// `id` int unsigned NOT NULL,
|
|
||||||
// `client_version` char(16) NOT NULL DEFAULT '',
|
|
||||||
// `reg_time` int unsigned NOT NULL DEFAULT '0',
|
|
||||||
// `name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
// `utc_delta` tinyint(1) NOT NULL DEFAULT '0',
|
|
||||||
// PRIMARY KEY (`id`)
|
|
||||||
//) ENGINE=InnoDB DEFAULT
|
|
||||||
//
|
|
||||||
// CREATE TABLE `item` (
|
|
||||||
// `player_id` int unsigned NOT NULL DEFAULT '0',
|
|
||||||
// `id` int unsigned NOT NULL DEFAULT '0',
|
|
||||||
// `proto_id` int unsigned NOT NULL DEFAULT '0',
|
|
||||||
// `amount` bigint NOT NULL DEFAULT '0',
|
|
||||||
// PRIMARY KEY (`player_id`,`id`),
|
|
||||||
// KEY `proto_id` (`proto_id`)
|
|
||||||
//) ENGINE=InnoDB DEFAULT
|
|
||||||
|
|
||||||
func getDBC() *db.DBC {
|
func getDBC() *db.DBC {
|
||||||
s := db.Settings{Host: "127.0.0.1", Port: "3306", User: "root", Pass: "test", Name: "tests_shard_1", Prefix: "tests"}
|
s := db.Settings{Host: "127.0.0.1", Port: "3306", User: "root", Pass: "test", Name: "tests", Prefix: "tests"}
|
||||||
dbc := db.GetDBC(db.OpenPool(s), logger)
|
dbc := db.GetDBC(db.OpenPool(s), logger)
|
||||||
return dbc
|
return dbc
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanStorage(db *db.DBC) {
|
func setupStorage(db *db.DBC) {
|
||||||
var tables []string
|
|
||||||
db.SelectBySQL("SHOW TABLES").LoadValues(&tables)
|
var sqls []string
|
||||||
for _, t := range tables {
|
sqls = append(sqls, "DROP TABLE IF EXISTS player")
|
||||||
_, err := db.DeleteFrom(t).Exec()
|
sqls = append(sqls, `CREATE TABLE player (
|
||||||
|
id int unsigned NOT NULL,
|
||||||
|
client_version char(16) NOT NULL DEFAULT '',
|
||||||
|
reg_time int unsigned NOT NULL DEFAULT '0',
|
||||||
|
name varchar(255) NOT NULL DEFAULT '',
|
||||||
|
utc_delta tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) ENGINE=InnoDB
|
||||||
|
`)
|
||||||
|
sqls = append(sqls, "DROP TABLE IF EXISTS item")
|
||||||
|
sqls = append(sqls, `CREATE TABLE item (
|
||||||
|
player_id int unsigned NOT NULL DEFAULT '0',
|
||||||
|
id int unsigned NOT NULL DEFAULT '0',
|
||||||
|
proto_id int unsigned NOT NULL DEFAULT '0',
|
||||||
|
amount bigint NOT NULL DEFAULT '0',
|
||||||
|
PRIMARY KEY (player_id,id),
|
||||||
|
KEY proto_id (proto_id)
|
||||||
|
) ENGINE=InnoDB
|
||||||
|
`)
|
||||||
|
|
||||||
|
for _, sql := range sqls {
|
||||||
|
_, err := db.DB().Exec(sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(sql)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +61,7 @@ func TestSaveRow(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
conn := getDBC()
|
conn := getDBC()
|
||||||
cleanStorage(conn)
|
setupStorage(conn)
|
||||||
|
|
||||||
//DataPlayer index
|
//DataPlayer index
|
||||||
//id 0
|
//id 0
|
||||||
|
@ -84,7 +86,7 @@ func TestSaveItemCollectionWithMask(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
conn := getDBC()
|
conn := getDBC()
|
||||||
cleanStorage(conn)
|
setupStorage(conn)
|
||||||
|
|
||||||
ownerId := uint32(1)
|
ownerId := uint32(1)
|
||||||
|
|
||||||
|
@ -128,7 +130,7 @@ func TestSaveItemCollectionWithoutMask(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
conn := getDBC()
|
conn := getDBC()
|
||||||
cleanStorage(conn)
|
setupStorage(conn)
|
||||||
|
|
||||||
ownerId := uint32(1)
|
ownerId := uint32(1)
|
||||||
|
|
||||||
|
@ -177,19 +179,17 @@ func TestRemoveIds(t *testing.T) {
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
type DataPlayer struct {
|
type DataPlayer struct {
|
||||||
|
|
||||||
Id uint32 `json:"id" db:"id"`
|
Id uint32 `json:"id" db:"id"`
|
||||||
Client_version string `json:"client_version" db:"client_version"`
|
Client_version string `json:"client_version" db:"client_version"`
|
||||||
Reg_time uint32 `json:"reg_time" db:"reg_time"`
|
Reg_time uint32 `json:"reg_time" db:"reg_time"`
|
||||||
Name string `json:"name" db:"name"`
|
Name string `json:"name" db:"name"`
|
||||||
Utc_delta int32 `json:"utc_delta" db:"utc_delta"`
|
Utc_delta int32 `json:"utc_delta" db:"utc_delta"`
|
||||||
fieldsMask meta.FieldsMask
|
fieldsMask meta.FieldsMask
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _DataPlayer_class_props map[string]string = map[string]string{"POD": "","bitfields": "","pkey": "id","table": "player","owner": "id","id": "id","cloneable": "",}
|
var _DataPlayer_class_props map[string]string = map[string]string{"POD": "", "bitfields": "", "pkey": "id", "table": "player", "owner": "id", "id": "id", "cloneable": ""}
|
||||||
var _DataPlayer_class_fields []string = []string{"id","client_version","reg_time","name","utc_delta"}
|
var _DataPlayer_class_fields []string = []string{"id", "client_version", "reg_time", "name", "utc_delta"}
|
||||||
var _DataPlayer_fields_props meta.ClassFieldsProps = map[string]map[string]string{"Id" : map[string]string{"optional": "1",},"Client_version" : map[string]string{"strmax": "16","optional": "1",},"Reg_time" : map[string]string{"default": "","optional": "1",},"Name" : map[string]string{"default": "\"\"","optional": "1",},"Utc_delta" : map[string]string{"default": "","optional": "1",}}
|
var _DataPlayer_fields_props meta.ClassFieldsProps = map[string]map[string]string{"Id": map[string]string{"optional": "1"}, "Client_version": map[string]string{"strmax": "16", "optional": "1"}, "Reg_time": map[string]string{"default": "", "optional": "1"}, "Name": map[string]string{"default": "\"\"", "optional": "1"}, "Utc_delta": map[string]string{"default": "", "optional": "1"}}
|
||||||
|
|
||||||
func DataPlayer_CLASS_ID() uint32 {
|
func DataPlayer_CLASS_ID() uint32 {
|
||||||
return 74407040
|
return 74407040
|
||||||
|
@ -234,7 +234,7 @@ func (self *DataPlayer) PtrDataPlayer() *DataPlayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDataPlayer() *DataPlayer {
|
func NewDataPlayer() *DataPlayer {
|
||||||
item := new (DataPlayer)
|
item := new(DataPlayer)
|
||||||
item.Reset()
|
item.Reset()
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ func (self *DataPlayer) Reset() {
|
||||||
self.Reg_time = 0
|
self.Reg_time = 0
|
||||||
self.Name = ""
|
self.Name = ""
|
||||||
self.Utc_delta = 0
|
self.Utc_delta = 0
|
||||||
self.fieldsMask = meta.FieldsMask{}
|
self.fieldsMask = meta.FieldsMask{}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +281,9 @@ func (self *DataPlayer) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(0)) {
|
if !use_mask || (use_mask && self.HasValue(0)) {
|
||||||
if err := reader.ReadU32(&self.Id, "id"); err != nil { return /*optional*/nil }
|
if err := reader.ReadU32(&self.Id, "id"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _cont_size <= 0 {
|
if _cont_size <= 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -290,7 +292,9 @@ func (self *DataPlayer) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(1)) {
|
if !use_mask || (use_mask && self.HasValue(1)) {
|
||||||
if err := reader.ReadString(&self.Client_version, "client_version"); err != nil { return /*optional*/nil }
|
if err := reader.ReadString(&self.Client_version, "client_version"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _cont_size <= 0 {
|
if _cont_size <= 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -299,7 +303,9 @@ func (self *DataPlayer) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(2)) {
|
if !use_mask || (use_mask && self.HasValue(2)) {
|
||||||
if err := reader.ReadU32(&self.Reg_time, "reg_time"); err != nil { return /*optional*/nil }
|
if err := reader.ReadU32(&self.Reg_time, "reg_time"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _cont_size <= 0 {
|
if _cont_size <= 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -308,7 +314,9 @@ func (self *DataPlayer) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(3)) {
|
if !use_mask || (use_mask && self.HasValue(3)) {
|
||||||
if err := reader.ReadString(&self.Name, "name"); err != nil { return /*optional*/nil }
|
if err := reader.ReadString(&self.Name, "name"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _cont_size <= 0 {
|
if _cont_size <= 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -317,7 +325,9 @@ func (self *DataPlayer) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(4)) {
|
if !use_mask || (use_mask && self.HasValue(4)) {
|
||||||
if err := reader.ReadI32(&self.Utc_delta, "utc_delta"); err != nil { return /*optional*/nil }
|
if err := reader.ReadI32(&self.Utc_delta, "utc_delta"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -328,45 +338,53 @@ func (self *DataPlayer) Write(writer meta.Writer) error {
|
||||||
|
|
||||||
func (self *DataPlayer) WriteFields(writer meta.Writer) error {
|
func (self *DataPlayer) WriteFields(writer meta.Writer) error {
|
||||||
|
|
||||||
if err := writer.WriteU32(self.Id, "id"); err != nil { return err }
|
if err := writer.WriteU32(self.Id, "id"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := writer.WriteString(self.Client_version, "client_version"); err != nil { return err }
|
if err := writer.WriteString(self.Client_version, "client_version"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := writer.WriteU32(self.Reg_time, "reg_time"); err != nil { return err }
|
if err := writer.WriteU32(self.Reg_time, "reg_time"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := writer.WriteString(self.Name, "name"); err != nil { return err }
|
if err := writer.WriteString(self.Name, "name"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := writer.WriteI32(self.Utc_delta, "utc_delta"); err != nil { return err }
|
if err := writer.WriteI32(self.Utc_delta, "utc_delta"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func(self *DataPlayer) HasValue(index uint64) bool {
|
func (self *DataPlayer) HasValue(index uint64) bool {
|
||||||
return self.fieldsMask.FieldChanged(index)
|
return self.fieldsMask.FieldChanged(index)
|
||||||
}
|
}
|
||||||
func(self *DataPlayer) SetFieldChanged(index uint64) {
|
func (self *DataPlayer) SetFieldChanged(index uint64) {
|
||||||
self.fieldsMask.SetFieldChanged(index)
|
self.fieldsMask.SetFieldChanged(index)
|
||||||
}
|
}
|
||||||
func(self *DataPlayer) IsMaskFilled() bool {
|
func (self *DataPlayer) IsMaskFilled() bool {
|
||||||
return self.fieldsMask.IsFilled()
|
return self.fieldsMask.IsFilled()
|
||||||
}
|
}
|
||||||
func(self *DataPlayer) GetMask() meta.FieldsMask {
|
func (self *DataPlayer) GetMask() meta.FieldsMask {
|
||||||
return self.fieldsMask
|
return self.fieldsMask
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataItem struct {
|
type DataItem struct {
|
||||||
|
|
||||||
Id uint32 `json:"id" db:"id"`
|
Id uint32 `json:"id" db:"id"`
|
||||||
Player_id uint32 `json:"player_id" db:"player_id"`
|
Player_id uint32 `json:"player_id" db:"player_id"`
|
||||||
Proto_id uint32 `json:"proto_id" db:"proto_id"`
|
Proto_id uint32 `json:"proto_id" db:"proto_id"`
|
||||||
Amount int64 `json:"amount" db:"amount"`
|
Amount int64 `json:"amount" db:"amount"`
|
||||||
fieldsMask meta.FieldsMask
|
fieldsMask meta.FieldsMask
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _DataItem_class_props map[string]string = map[string]string{"POD": "","table": "item","id": "id","owner": "player_id","bitfields": "",}
|
var _DataItem_class_props map[string]string = map[string]string{"POD": "", "table": "item", "id": "id", "owner": "player_id", "bitfields": ""}
|
||||||
var _DataItem_class_fields []string = []string{"id","player_id","proto_id","amount",}
|
var _DataItem_class_fields []string = []string{"id", "player_id", "proto_id", "amount"}
|
||||||
var _DataItem_fields_props meta.ClassFieldsProps = map[string]map[string]string{"Id" : map[string]string{"optional": "1",},"Player_id" : map[string]string{"optional": "1",},"Proto_id" : map[string]string{"obscured": "","optional": "1",},"Amount" : map[string]string{"obscured": "","optional": "1",},}
|
var _DataItem_fields_props meta.ClassFieldsProps = map[string]map[string]string{"Id": map[string]string{"optional": "1"}, "Player_id": map[string]string{"optional": "1"}, "Proto_id": map[string]string{"obscured": "", "optional": "1"}, "Amount": map[string]string{"obscured": "", "optional": "1"}}
|
||||||
|
|
||||||
func DataItem_CLASS_ID() uint32 {
|
func DataItem_CLASS_ID() uint32 {
|
||||||
return 263721017
|
return 263721017
|
||||||
|
@ -411,7 +429,7 @@ func (self *DataItem) PtrDataItem() *DataItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDataItem() *DataItem {
|
func NewDataItem() *DataItem {
|
||||||
item := new (DataItem)
|
item := new(DataItem)
|
||||||
item.Reset()
|
item.Reset()
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
@ -422,7 +440,7 @@ func (self *DataItem) Reset() {
|
||||||
self.Player_id = 0
|
self.Player_id = 0
|
||||||
self.Proto_id = 0
|
self.Proto_id = 0
|
||||||
self.Amount = 0
|
self.Amount = 0
|
||||||
self.fieldsMask = meta.FieldsMask{}
|
self.fieldsMask = meta.FieldsMask{}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +475,9 @@ func (self *DataItem) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(0)) {
|
if !use_mask || (use_mask && self.HasValue(0)) {
|
||||||
if err := reader.ReadU32(&self.Id, "id"); err != nil { return /*optional*/nil }
|
if err := reader.ReadU32(&self.Id, "id"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _cont_size <= 0 {
|
if _cont_size <= 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -466,7 +486,9 @@ func (self *DataItem) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(1)) {
|
if !use_mask || (use_mask && self.HasValue(1)) {
|
||||||
if err := reader.ReadU32(&self.Player_id, "player_id"); err != nil { return /*optional*/nil }
|
if err := reader.ReadU32(&self.Player_id, "player_id"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _cont_size <= 0 {
|
if _cont_size <= 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -475,7 +497,9 @@ func (self *DataItem) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(2)) {
|
if !use_mask || (use_mask && self.HasValue(2)) {
|
||||||
if err := reader.ReadU32(&self.Proto_id, "proto_id"); err != nil { return /*optional*/nil }
|
if err := reader.ReadU32(&self.Proto_id, "proto_id"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _cont_size <= 0 {
|
if _cont_size <= 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -484,7 +508,9 @@ func (self *DataItem) ReadFields(reader meta.Reader) error {
|
||||||
_cont_size--
|
_cont_size--
|
||||||
}
|
}
|
||||||
if !use_mask || (use_mask && self.HasValue(3)) {
|
if !use_mask || (use_mask && self.HasValue(3)) {
|
||||||
if err := reader.ReadI64(&self.Amount, "amount"); err != nil { return /*optional*/nil }
|
if err := reader.ReadI64(&self.Amount, "amount"); err != nil {
|
||||||
|
return /*optional*/ nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -495,27 +521,35 @@ func (self *DataItem) Write(writer meta.Writer) error {
|
||||||
|
|
||||||
func (self *DataItem) WriteFields(writer meta.Writer) error {
|
func (self *DataItem) WriteFields(writer meta.Writer) error {
|
||||||
|
|
||||||
if err := writer.WriteU32(self.Id, "id"); err != nil { return err }
|
if err := writer.WriteU32(self.Id, "id"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := writer.WriteU32(self.Player_id, "player_id"); err != nil { return err }
|
if err := writer.WriteU32(self.Player_id, "player_id"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := writer.WriteU32(self.Proto_id, "proto_id"); err != nil { return err }
|
if err := writer.WriteU32(self.Proto_id, "proto_id"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := writer.WriteI64(self.Amount, "amount"); err != nil { return err }
|
if err := writer.WriteI64(self.Amount, "amount"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func(self *DataItem) HasValue(index uint64) bool {
|
func (self *DataItem) HasValue(index uint64) bool {
|
||||||
return self.fieldsMask.FieldChanged(index)
|
return self.fieldsMask.FieldChanged(index)
|
||||||
}
|
}
|
||||||
func(self *DataItem) SetFieldChanged(index uint64) {
|
func (self *DataItem) SetFieldChanged(index uint64) {
|
||||||
self.fieldsMask.SetFieldChanged(index)
|
self.fieldsMask.SetFieldChanged(index)
|
||||||
}
|
}
|
||||||
func(self *DataItem) IsMaskFilled() bool {
|
func (self *DataItem) IsMaskFilled() bool {
|
||||||
return self.fieldsMask.IsFilled()
|
return self.fieldsMask.IsFilled()
|
||||||
}
|
}
|
||||||
func(self *DataItem) GetMask() meta.FieldsMask {
|
func (self *DataItem) GetMask() meta.FieldsMask {
|
||||||
return self.fieldsMask
|
return self.fieldsMask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,4 +601,3 @@ func (self *DataItem) Export(data []interface{}) {
|
||||||
data[2] = self.Proto_id
|
data[2] = self.Proto_id
|
||||||
data[3] = self.Amount
|
data[3] = self.Amount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue