/
transaction.go
127 lines (120 loc) · 4.62 KB
/
transaction.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (C) 2017, 2018, 2019 EGAAS S.A.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package rollback
import (
"encoding/json"
"fmt"
"strings"
"github.com/AplaProject/go-apla/packages/consts"
"github.com/AplaProject/go-apla/packages/converter"
"github.com/AplaProject/go-apla/packages/model"
"github.com/AplaProject/go-apla/packages/smart"
log "github.com/sirupsen/logrus"
)
func rollbackUpdatedRow(tx map[string]string, where string, dbTransaction *model.DbTransaction, logger *log.Entry) error {
var rollbackInfo map[string]string
if err := json.Unmarshal([]byte(tx["data"]), &rollbackInfo); err != nil {
logger.WithFields(log.Fields{"type": consts.JSONUnmarshallError, "error": err}).Error("unmarshalling rollback.Data from json")
return err
}
addSQLUpdate := ""
for k, v := range rollbackInfo {
if v == "NULL" {
addSQLUpdate += k + `=NULL,`
} else if converter.IsByteColumn(tx["table_name"], k) && len(v) != 0 {
addSQLUpdate += k + `=decode('` + string(converter.BinToHex([]byte(v))) + `','HEX'),`
} else {
addSQLUpdate += k + `='` + strings.Replace(v, `'`, `''`, -1) + `',`
}
}
addSQLUpdate = addSQLUpdate[0 : len(addSQLUpdate)-1]
if err := model.Update(dbTransaction, tx["table_name"], addSQLUpdate, where); err != nil {
logger.WithFields(log.Fields{"type": consts.JSONUnmarshallError, "error": err, "query": addSQLUpdate}).Error("updating table")
return err
}
return nil
}
func rollbackInsertedRow(tx map[string]string, where string, dbTransaction *model.DbTransaction, logger *log.Entry) error {
if err := model.Delete(dbTransaction, tx["table_name"], where); err != nil {
logger.WithFields(log.Fields{"type": consts.DBError, "error": err}).Error("deleting from table")
return err
}
return nil
}
func rollbackTransaction(txHash []byte, dbTransaction *model.DbTransaction, logger *log.Entry) error {
rollbackTx := &model.RollbackTx{}
txs, err := rollbackTx.GetRollbackTransactions(dbTransaction, txHash)
if err != nil {
logger.WithFields(log.Fields{"type": consts.DBError, "error": err}).Error("getting rollback transactions")
return err
}
for _, tx := range txs {
if tx["table_name"] == smart.SysName {
var sysData smart.SysRollData
err := json.Unmarshal([]byte(tx["data"]), &sysData)
if err != nil {
logger.WithFields(log.Fields{"type": consts.JSONUnmarshallError, "error": err}).Error("unmarshalling rollback.Data from json")
return err
}
switch sysData.Type {
case "NewTable":
smart.SysRollbackTable(dbTransaction, sysData)
case "NewColumn":
smart.SysRollbackColumn(dbTransaction, sysData)
case "NewContract":
smart.SysRollbackNewContract(sysData, tx["table_id"])
case "EditContract":
smart.SysRollbackEditContract(dbTransaction, sysData, tx["table_id"])
case "NewEcosystem":
smart.SysRollbackEcosystem(dbTransaction, sysData)
case "ActivateContract":
smart.SysRollbackActivate(sysData)
case "DeactivateContract":
smart.SysRollbackDeactivate(sysData)
case "DeleteColumn":
smart.SysRollbackDeleteColumn(dbTransaction, sysData)
case "DeleteTable":
smart.SysRollbackDeleteTable(dbTransaction, sysData)
}
continue
}
where := " WHERE id='" + tx["table_id"] + `'`
table := tx[`table_name`]
if under := strings.IndexByte(table, '_'); under > 0 {
keyName := table[under+1:]
if v, ok := converter.FirstEcosystemTables[keyName]; ok && !v {
where += fmt.Sprintf(` AND ecosystem='%d'`, converter.StrToInt64(table[:under]))
tx[`table_name`] = `1_` + keyName
}
}
if len(tx["data"]) > 0 {
if err := rollbackUpdatedRow(tx, where, dbTransaction, logger); err != nil {
return err
}
} else {
if err := rollbackInsertedRow(tx, where, dbTransaction, logger); err != nil {
return err
}
}
}
txForDelete := &model.RollbackTx{TxHash: txHash}
err = txForDelete.DeleteByHash(dbTransaction)
if err != nil {
logger.WithFields(log.Fields{"type": consts.DBError, "error": err}).Error("deleting rollback transaction by hash")
return err
}
return nil
}