func (s *SoExtTrxWrap) delSortKeyTrxId(sa *SoExtTrx) bool {
	if s.dba == nil || s.mainKey == nil {
		return false
	}
	val := SoListExtTrxByTrxId{}
	if sa == nil {
		val.TrxId = s.GetTrxId()
	} else {
		val.TrxId = sa.TrxId
	}
	subBuf, err := val.OpeEncode()
	if err != nil {
		return false
	}
	ordErr := s.dba.Delete(subBuf)
	return ordErr == nil
}
//////////// SECTION LKeys delete/insert ///////////////
package table
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"sync"
	"github.com/coschain/contentos-go/common/encoding/kope"
	"github.com/coschain/contentos-go/iservices"
	prototype "github.com/coschain/contentos-go/prototype"
	proto "github.com/golang/protobuf/proto"
)
var (
	ExtTrxTrxIdTable          uint32 = 1916120438
	ExtTrxBlockHeightTable    uint32 = 3799341326
	ExtTrxBlockTimeTable      uint32 = 1025113122
	ExtTrxTrxCreateOrderTable uint32 = 1760958085
	ExtTrxTrxIdUniTable       uint32 = 334659987
	ExtTrxTrxIdRow uint32 = 2158991352
)
type SoExtTrxWrap struct {
	dba         iservices.IDatabaseRW
	mainKey     *prototype.Sha256
	watcherFlag *ExtTrxWatcherFlag
	mKeyFlag    int     
	mKeyBuf     []byte  
	mBuf        []byte  
	mdFuncMap   map[string]interface{}
}
func NewSoExtTrxWrap(dba iservices.IDatabaseRW, key *prototype.Sha256) *SoExtTrxWrap {
	if dba == nil || key == nil {
		return nil
	}
	result := &SoExtTrxWrap{dba, key, nil, -1, nil, nil, nil}
	result.initWatcherFlag()
	return result
}
func (s *SoExtTrxWrap) CheckExist() bool {
	if s.dba == nil {
		return false
	}
	if s.mKeyFlag != -1 {
		if s.mKeyFlag == 0 {
			return false
		}
		return true
	}
	keyBuf, err := s.encodeMainKey()
	if err != nil {
		return false
	}
	res, err := s.dba.Has(keyBuf)
	if err != nil {
		return false
	}
	if res == false {
		s.mKeyFlag = 0
	} else {
		s.mKeyFlag = 1
	}
	return res
}
func (s *SoExtTrxWrap) MustExist(errMsgs ...interface{}) *SoExtTrxWrap {
	if !s.CheckExist() {
		panic(bindErrorInfo(fmt.Sprintf("SoExtTrxWrap.MustExist: %v not found", s.mainKey), errMsgs...))
	}
	return s
}
func (s *SoExtTrxWrap) MustNotExist(errMsgs ...interface{}) *SoExtTrxWrap {
	if s.CheckExist() {
		panic(bindErrorInfo(fmt.Sprintf("SoExtTrxWrap.MustNotExist: %v already exists", s.mainKey), errMsgs...))
	}
	return s
}
func (s *SoExtTrxWrap) initWatcherFlag() {
	if s.watcherFlag == nil {
		s.watcherFlag = new(ExtTrxWatcherFlag)
		*(s.watcherFlag) = ExtTrxWatcherFlagOfDb(s.dba.ServiceId())
	}
}
func (s *SoExtTrxWrap) create(f func(tInfo *SoExtTrx)) error {
	if s.dba == nil {
		return errors.New("the db is nil")
	}
	if s.mainKey == nil {
		return errors.New("the main key is nil")
	}
	val := &SoExtTrx{}
	f(val)
	if val.TrxId == nil {
		val.TrxId = s.mainKey
	}
	if s.CheckExist() {
		return errors.New("the main key is already exist")
	}
	keyBuf, err := s.encodeMainKey()
	if err != nil {
		return err
	}
	buf, err := proto.Marshal(val)
	if err != nil {
		return err
	}
	err = s.dba.Put(keyBuf, buf)
	if err != nil {
		return err
	}
	if err = s.insertAllSortKeys(val); err != nil {
		s.delAllSortKeys(false, val)
		s.dba.Delete(keyBuf)
		return err
	}
	if sucNames, err := s.insertAllUniKeys(val); err != nil {
		s.delAllSortKeys(false, val)
		s.delUniKeysWithNames(sucNames, val)
		s.dba.Delete(keyBuf)
		return err
	}
	s.mKeyFlag = 1
	s.initWatcherFlag()
	if s.watcherFlag.AnyWatcher {
		ReportTableRecordInsert(s.dba.ServiceId(), s.dba.BranchId(), s.mainKey, val)
	}
	return nil
}
func (s *SoExtTrxWrap) Create(f func(tInfo *SoExtTrx), errArgs ...interface{}) *SoExtTrxWrap {
	err := s.create(f)
	if err != nil {
		panic(bindErrorInfo(fmt.Errorf("SoExtTrxWrap.Create failed: %s", err.Error()), errArgs...))
	}
	return s
}
func (s *SoExtTrxWrap) getMainKeyBuf() ([]byte, error) {
	if s.mainKey == nil {
		return nil, errors.New("the main key is nil")
	}
	if s.mBuf == nil {
		var err error = nil
		s.mBuf, err = kope.Encode(s.mainKey)
		if err != nil {
			return nil, err
		}
	}
	return s.mBuf, nil
}
func (s *SoExtTrxWrap) modify(f func(tInfo *SoExtTrx)) error {
	if !s.CheckExist() {
		return errors.New("the SoExtTrx table does not exist. Please create a table first")
	}
	oriTable := s.getExtTrx()
	if oriTable == nil {
		return errors.New("fail to get origin table SoExtTrx")
	}
	curTable := s.getExtTrx()
	if curTable == nil {
		return errors.New("fail to create current table SoExtTrx")
	}
	f(curTable)
	if !reflect.DeepEqual(curTable.TrxId, oriTable.TrxId) {
		return errors.New("primary key does not support modification")
	}
	s.initWatcherFlag()
	modifiedFields, hasWatcher, err := s.getModifiedFields(oriTable, curTable)
	if err != nil {
		return err
	}
	if modifiedFields == nil || len(modifiedFields) < 1 {
		return nil
	}
	err = s.checkSortAndUniFieldValidity(curTable, modifiedFields)
	if err != nil {
		return err
	}
	err = s.handleFieldMd(FieldMdHandleTypeCheck, curTable, modifiedFields)
	if err != nil {
		return err
	}
	err = s.handleFieldMd(FieldMdHandleTypeDel, oriTable, modifiedFields)
	if err != nil {
		return err
	}
	err = s.updateExtTrx(curTable)
	if err != nil {
		return err
	}
	err = s.handleFieldMd(FieldMdHandleTypeInsert, curTable, modifiedFields)
	if err != nil {
		return err
	}
	if hasWatcher {
		ReportTableRecordUpdate(s.dba.ServiceId(), s.dba.BranchId(), s.mainKey, oriTable, curTable, modifiedFields)
	}
	return nil
}
func (s *SoExtTrxWrap) Modify(f func(tInfo *SoExtTrx), errArgs ...interface{}) *SoExtTrxWrap {
	err := s.modify(f)
	if err != nil {
		panic(bindErrorInfo(fmt.Sprintf("SoExtTrxWrap.Modify failed: %s", err.Error()), errArgs...))
	}
	return s
}
func (s *SoExtTrxWrap) SetBlockHeight(p uint64, errArgs ...interface{}) *SoExtTrxWrap {
	err := s.modify(func(r *SoExtTrx) {
		r.BlockHeight = p
	})
	if err != nil {
		panic(bindErrorInfo(fmt.Sprintf("SoExtTrxWrap.SetBlockHeight( %v ) failed: %s", p, err.Error()), errArgs...))
	}
	return s
}
func (s *SoExtTrxWrap) SetBlockId(p *prototype.Sha256, errArgs ...interface{}) *SoExtTrxWrap {
	err := s.modify(func(r *SoExtTrx) {
		r.BlockId = p
	})
	if err != nil {
		panic(bindErrorInfo(fmt.Sprintf("SoExtTrxWrap.SetBlockId( %v ) failed: %s", p, err.Error()), errArgs...))
	}
	return s
}
func (s *SoExtTrxWrap) SetBlockTime(p *prototype.TimePointSec, errArgs ...interface{}) *SoExtTrxWrap {
	err := s.modify(func(r *SoExtTrx) {
		r.BlockTime = p
	})
	if err != nil {
		panic(bindErrorInfo(fmt.Sprintf("SoExtTrxWrap.SetBlockTime( %v ) failed: %s", p, err.Error()), errArgs...))
	}
	return s
}
func (s *SoExtTrxWrap) SetTrxCreateOrder(p *prototype.UserTrxCreateOrder, errArgs ...interface{}) *SoExtTrxWrap {
	err := s.modify(func(r *SoExtTrx) {
		r.TrxCreateOrder = p
	})
	if err != nil {
		panic(bindErrorInfo(fmt.Sprintf("SoExtTrxWrap.SetTrxCreateOrder( %v ) failed: %s", p, err.Error()), errArgs...))
	}
	return s
}
func (s *SoExtTrxWrap) SetTrxWrap(p *prototype.TransactionWrapper, errArgs ...interface{}) *SoExtTrxWrap {
	err := s.modify(func(r *SoExtTrx) {
		r.TrxWrap = p
	})
	if err != nil {
		panic(bindErrorInfo(fmt.Sprintf("SoExtTrxWrap.SetTrxWrap( %v ) failed: %s", p, err.Error()), errArgs...))
	}
	return s
}
func (s *SoExtTrxWrap) checkSortAndUniFieldValidity(curTable *SoExtTrx, fields map[string]bool) error {
	if curTable != nil && fields != nil && len(fields) > 0 {
		if fields["BlockTime"] && curTable.BlockTime == nil {
			return errors.New("sort field BlockTime can't be modified to nil")
		}
		if fields["TrxCreateOrder"] && curTable.TrxCreateOrder == nil {
			return errors.New("sort field TrxCreateOrder can't be modified to nil")
		}
	}
	return nil
}
func (s *SoExtTrxWrap) getModifiedFields(oriTable *SoExtTrx, curTable *SoExtTrx) (map[string]bool, bool, error) {
	if oriTable == nil {
		return nil, false, errors.New("table info is nil, can't get modified fields")
	}
	hasWatcher := false
	fields := make(map[string]bool)
	if !reflect.DeepEqual(oriTable.BlockHeight, curTable.BlockHeight) {
		fields["BlockHeight"] = true
		hasWatcher = hasWatcher || s.watcherFlag.HasBlockHeightWatcher
	}
	if !reflect.DeepEqual(oriTable.BlockId, curTable.BlockId) {
		fields["BlockId"] = true
		hasWatcher = hasWatcher || s.watcherFlag.HasBlockIdWatcher
	}
	if !reflect.DeepEqual(oriTable.BlockTime, curTable.BlockTime) {
		fields["BlockTime"] = true
		hasWatcher = hasWatcher || s.watcherFlag.HasBlockTimeWatcher
	}
	if !reflect.DeepEqual(oriTable.TrxCreateOrder, curTable.TrxCreateOrder) {
		fields["TrxCreateOrder"] = true
		hasWatcher = hasWatcher || s.watcherFlag.HasTrxCreateOrderWatcher
	}
	if !reflect.DeepEqual(oriTable.TrxWrap, curTable.TrxWrap) {
		fields["TrxWrap"] = true
		hasWatcher = hasWatcher || s.watcherFlag.HasTrxWrapWatcher
	}
	hasWatcher = hasWatcher || s.watcherFlag.WholeWatcher
	return fields, hasWatcher, nil
}
func (s *SoExtTrxWrap) handleFieldMd(t FieldMdHandleType, so *SoExtTrx, fields map[string]bool) error {
	if so == nil {
		return errors.New("fail to modify empty table")
	}
	if fields == nil || len(fields) < 1 {
		return nil
	}
	errStr := ""
	if fields["BlockHeight"] {
		res := true
		if t == FieldMdHandleTypeCheck {
			res = s.mdFieldBlockHeight(so.BlockHeight, true, false, false, so)
			errStr = fmt.Sprintf("fail to modify exist value of %v", "BlockHeight")
		} else if t == FieldMdHandleTypeDel {
			res = s.mdFieldBlockHeight(so.BlockHeight, false, true, false, so)
			errStr = fmt.Sprintf("fail to delete  sort or unique field  %v", "BlockHeight")
		} else if t == FieldMdHandleTypeInsert {
			res = s.mdFieldBlockHeight(so.BlockHeight, false, false, true, so)
			errStr = fmt.Sprintf("fail to insert  sort or unique field  %v", "BlockHeight")
		}
		if !res {
			return errors.New(errStr)
		}
	}
	if fields["BlockId"] {
		res := true
		if t == FieldMdHandleTypeCheck {
			res = s.mdFieldBlockId(so.BlockId, true, false, false, so)
			errStr = fmt.Sprintf("fail to modify exist value of %v", "BlockId")
		} else if t == FieldMdHandleTypeDel {
			res = s.mdFieldBlockId(so.BlockId, false, true, false, so)
			errStr = fmt.Sprintf("fail to delete  sort or unique field  %v", "BlockId")
		} else if t == FieldMdHandleTypeInsert {
			res = s.mdFieldBlockId(so.BlockId, false, false, true, so)
			errStr = fmt.Sprintf("fail to insert  sort or unique field  %v", "BlockId")
		}
		if !res {
			return errors.New(errStr)
		}
	}
	if fields["BlockTime"] {
		res := true
		if t == FieldMdHandleTypeCheck {
			res = s.mdFieldBlockTime(so.BlockTime, true, false, false, so)
			errStr = fmt.Sprintf("fail to modify exist value of %v", "BlockTime")
		} else if t == FieldMdHandleTypeDel {
			res = s.mdFieldBlockTime(so.BlockTime, false, true, false, so)
			errStr = fmt.Sprintf("fail to delete  sort or unique field  %v", "BlockTime")
		} else if t == FieldMdHandleTypeInsert {
			res = s.mdFieldBlockTime(so.BlockTime, false, false, true, so)
			errStr = fmt.Sprintf("fail to insert  sort or unique field  %v", "BlockTime")
		}
		if !res {
			return errors.New(errStr)
		}
	}
	if fields["TrxCreateOrder"] {
		res := true
		if t == FieldMdHandleTypeCheck {
			res = s.mdFieldTrxCreateOrder(so.TrxCreateOrder, true, false, false, so)
			errStr = fmt.Sprintf("fail to modify exist value of %v", "TrxCreateOrder")
		} else if t == FieldMdHandleTypeDel {
			res = s.mdFieldTrxCreateOrder(so.TrxCreateOrder, false, true, false, so)
			errStr = fmt.Sprintf("fail to delete  sort or unique field  %v", "TrxCreateOrder")
		} else if t == FieldMdHandleTypeInsert {
			res = s.mdFieldTrxCreateOrder(so.TrxCreateOrder, false, false, true, so)
			errStr = fmt.Sprintf("fail to insert  sort or unique field  %v", "TrxCreateOrder")
		}
		if !res {
			return errors.New(errStr)
		}
	}
	if fields["TrxWrap"] {
		res := true
		if t == FieldMdHandleTypeCheck {
			res = s.mdFieldTrxWrap(so.TrxWrap, true, false, false, so)
			errStr = fmt.Sprintf("fail to modify exist value of %v", "TrxWrap")
		} else if t == FieldMdHandleTypeDel {
			res = s.mdFieldTrxWrap(so.TrxWrap, false, true, false, so)
			errStr = fmt.Sprintf("fail to delete  sort or unique field  %v", "TrxWrap")
		} else if t == FieldMdHandleTypeInsert {
			res = s.mdFieldTrxWrap(so.TrxWrap, false, false, true, so)
			errStr = fmt.Sprintf("fail to insert  sort or unique field  %v", "TrxWrap")
		}
		if !res {
			return errors.New(errStr)
		}
	}
	return nil
}