Compare commits
No commits in common. "master" and "v1.1.9" have entirely different histories.
|
@ -8,7 +8,6 @@ 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 {
|
||||||
|
@ -42,10 +41,7 @@ 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 {
|
||||||
err := errors.New("Fields list is empty")
|
return 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)
|
||||||
|
@ -64,21 +60,10 @@ 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 {
|
||||||
if err := coll.saveWithoutMask(ctx); err != nil {
|
return coll.saveWithoutMask(ctx)
|
||||||
span.RecordError(err)
|
|
||||||
span.SetStatus(codes.Error, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := coll.saveByMask(ctx); err != nil {
|
return coll.saveByMask(ctx)
|
||||||
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 {
|
||||||
|
@ -92,8 +77,7 @@ func (coll *DataCollection) saveByMask(ctx context.Context) error {
|
||||||
tableName := coll.GetTableName()
|
tableName := coll.GetTableName()
|
||||||
|
|
||||||
span.SetAttributes(
|
span.SetAttributes(
|
||||||
attribute.String("table", tableName),
|
attribute.String("db.sql.table", tableName),
|
||||||
attribute.Int("field_amount", countFields),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, item := range coll.Items {
|
for _, item := range coll.Items {
|
||||||
|
@ -126,10 +110,7 @@ func (coll *DataCollection) saveByMask(ctx context.Context) error {
|
||||||
log_len = 200
|
log_len = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
resultErr := errors.Errorf("%s (%s)", err.Error(), sqlSmt[0:log_len])
|
return 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
|
||||||
|
@ -147,7 +128,7 @@ func (coll *DataCollection) saveWithoutMask(ctx context.Context) error {
|
||||||
countRows := len(coll.Items)
|
countRows := len(coll.Items)
|
||||||
|
|
||||||
span.SetAttributes(
|
span.SetAttributes(
|
||||||
attribute.String("table", tableName),
|
attribute.String("db.sql.table", tableName),
|
||||||
attribute.Int("field_amount", countFields),
|
attribute.Int("field_amount", countFields),
|
||||||
attribute.Int("item_amount", countRows),
|
attribute.Int("item_amount", countRows),
|
||||||
)
|
)
|
||||||
|
@ -162,10 +143,7 @@ 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 {
|
||||||
err := errors.Errorf("Wrong owner_id in %s value %d (!= %d)", tableName, ownerValue, coll.OwnerId)
|
return 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++
|
||||||
}
|
}
|
||||||
|
@ -173,10 +151,7 @@ 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 {
|
||||||
resultErr := errors.Errorf("error: %s, sql: %s", err.Error(), sqlSmt)
|
return errors.Errorf("error: %s, sql: %s", err.Error(), sqlSmt)
|
||||||
span.RecordError(resultErr)
|
|
||||||
span.SetStatus(codes.Error, resultErr.Error())
|
|
||||||
return resultErr
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -3,7 +3,7 @@ module git.bit5.ru/backend/dbmeta
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.bit5.ru/backend/db v1.2.6
|
git.bit5.ru/backend/db v1.2.5
|
||||||
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
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -1,7 +1,7 @@
|
||||||
git.bit5.ru/backend/db v1.2.6 h1:ANfRTQ+C4BaMKbG+7onjET7qCcsFwq71dbolt0Po7Y4=
|
git.bit5.ru/backend/db v1.2.5 h1:3s7hI9bjRdd9htLcaZmL8/5K2HD/JNcI3dhuUdLgKPM=
|
||||||
git.bit5.ru/backend/db v1.2.6/go.mod h1:+1VkFgSf3zkGlHmG3gw5HyWBoucZDQ+bixQ6rpO6AqU=
|
git.bit5.ru/backend/db v1.2.5/go.mod h1:LOPz0QYl7Ca3k8VkvQW39xrcu1s1Drcnbl2unUczAYw=
|
||||||
git.bit5.ru/backend/dbr v1.3.1 h1:O3fy+aztnNVzto/nMcydd9BVahAJTXPE8VuGY3dC1NY=
|
git.bit5.ru/backend/dbr v1.3.0 h1:1mpzmSuZ5Mt4wL7cqjtuWOADq9kWdFY3Iet9mctC8pw=
|
||||||
git.bit5.ru/backend/dbr v1.3.1/go.mod h1:oVVFv6hIzFkO4Wy0KcS4CYqkBjW1kFHYNLcmKmDlPow=
|
git.bit5.ru/backend/dbr v1.3.0/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=
|
||||||
|
|
87
save.go
87
save.go
|
@ -50,8 +50,6 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,20 +78,15 @@ func SaveRow(ctx context.Context, db *db.DBC, dataItem meta.IMetaStruct) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(fields) == 0 {
|
if len(fields) == 0 {
|
||||||
err := errors.New("Fields list is empty")
|
return 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...)
|
||||||
|
@ -103,23 +96,7 @@ func SaveRow(ctx context.Context, db *db.DBC, dataItem meta.IMetaStruct) error {
|
||||||
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()
|
||||||
|
@ -130,20 +107,6 @@ 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,
|
||||||
|
@ -253,20 +216,14 @@ func saveStruct(
|
||||||
row, _ = dataItem.Addr().Interface().(meta.IMetaStruct)
|
row, _ = dataItem.Addr().Interface().(meta.IMetaStruct)
|
||||||
}
|
}
|
||||||
if row == nil {
|
if row == nil {
|
||||||
err := errors.Errorf("Couldn't convert to IMetaStruct: %s", mType.Name())
|
return 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() {
|
||||||
err := errors.Errorf("Owner field \"%s\" is not found in struct \"%s\"", ownerField, mType.Name())
|
return 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
|
||||||
|
@ -285,25 +242,14 @@ func saveStruct(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveMetaCollection(
|
func SaveMetaCollection(ctx context.Context, db *db.DBC, slice reflect.Value, ownerId uint32, removedIds meta.IRemovedIds, deltaSave bool) error {
|
||||||
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 {
|
||||||
err := errors.Errorf("It isn't slice: %s", slice.Type().Kind())
|
return 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()
|
||||||
|
@ -315,42 +261,29 @@ func SaveMetaCollection(
|
||||||
}
|
}
|
||||||
|
|
||||||
if row == nil {
|
if row == nil {
|
||||||
err := errors.Errorf("Couldn't convert to IMetaStruct: %s", sliceItem.Kind())
|
return 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 {
|
||||||
err := errors.Errorf("Couldn't convert to IMetaDataItem: %s", slice.Type())
|
return 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
|
||||||
|
@ -358,8 +291,6 @@ func SaveMetaCollection(
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,8 +300,6 @@ func SaveMetaCollection(
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue