You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

parser_protobuf.go 6.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package parser
  18. import (
  19. "encoding/json"
  20. "github.com/golang/protobuf/ptypes/any"
  21. "github.com/golang/protobuf/ptypes/wrappers"
  22. "google.golang.org/protobuf/proto"
  23. "google.golang.org/protobuf/types/known/anypb"
  24. "seata.apache.org/seata-go/pkg/datasource/sql/types"
  25. "seata.apache.org/seata-go/pkg/datasource/sql/undo"
  26. )
  27. type ProtobufParser struct {
  28. }
  29. // GetName get the name of parser
  30. func (p *ProtobufParser) GetName() string {
  31. return "protobuf"
  32. }
  33. // GetDefaultContent get default content of this parser
  34. func (p *ProtobufParser) GetDefaultContent() []byte {
  35. return []byte{}
  36. }
  37. // Encode branch undo log to byte array
  38. func (p *ProtobufParser) Encode(branchUndoLog *undo.BranchUndoLog) ([]byte, error) {
  39. protoLog := ConvertToProto(branchUndoLog)
  40. return proto.Marshal(protoLog)
  41. }
  42. // Decode byte array to branch undo log
  43. func (p *ProtobufParser) Decode(data []byte) (*undo.BranchUndoLog, error) {
  44. branchUndoLog := &BranchUndoLog{}
  45. err := proto.Unmarshal(data, branchUndoLog)
  46. if err != nil {
  47. return nil, err
  48. }
  49. return ConvertToIntree(branchUndoLog), nil
  50. }
  51. func ConvertToProto(intreeLog *undo.BranchUndoLog) *BranchUndoLog {
  52. protoLog := &BranchUndoLog{
  53. Xid: intreeLog.Xid,
  54. BranchID: intreeLog.BranchID,
  55. Logs: []*SQLUndoLog{},
  56. }
  57. for _, undolog := range intreeLog.Logs {
  58. protolog := &SQLUndoLog{
  59. SQLType: SQLType(undolog.SQLType),
  60. TableName: undolog.TableName,
  61. }
  62. if undolog.BeforeImage != nil {
  63. protolog.BeforeImage = &RecordImage{
  64. TableName: undolog.BeforeImage.TableName,
  65. SQLType: SQLType(undolog.BeforeImage.SQLType),
  66. Rows: []*RowImage{},
  67. }
  68. for _, row := range undolog.BeforeImage.Rows {
  69. protoRow := &RowImage{
  70. Columns: []*ColumnImage{},
  71. }
  72. for _, col := range row.Columns {
  73. anyValue, err := convertInterfaceToAny(col.GetActualValue())
  74. if err != nil {
  75. continue
  76. }
  77. protoCol := &ColumnImage{
  78. KeyType: IndexType(col.KeyType),
  79. ColumnName: col.ColumnName,
  80. ColumnType: JDBCType(col.ColumnType),
  81. Value: anyValue,
  82. }
  83. protoRow.Columns = append(protoRow.Columns, protoCol)
  84. }
  85. protolog.BeforeImage.Rows = append(protolog.BeforeImage.Rows, protoRow)
  86. }
  87. }
  88. if undolog.AfterImage != nil {
  89. protolog.AfterImage = &RecordImage{
  90. TableName: undolog.AfterImage.TableName,
  91. SQLType: SQLType(undolog.AfterImage.SQLType),
  92. Rows: []*RowImage{},
  93. }
  94. for _, row := range undolog.AfterImage.Rows {
  95. protoRow := &RowImage{
  96. Columns: []*ColumnImage{},
  97. }
  98. for _, col := range row.Columns {
  99. anyValue, err := convertInterfaceToAny(col.Value)
  100. if err != nil {
  101. continue
  102. }
  103. protoCol := &ColumnImage{
  104. KeyType: IndexType(col.KeyType),
  105. ColumnName: col.ColumnName,
  106. ColumnType: JDBCType(col.ColumnType),
  107. Value: anyValue,
  108. }
  109. protoRow.Columns = append(protoRow.Columns, protoCol)
  110. }
  111. protolog.AfterImage.Rows = append(protolog.AfterImage.Rows, protoRow)
  112. }
  113. }
  114. protoLog.Logs = append(protoLog.Logs, protolog)
  115. }
  116. return protoLog
  117. }
  118. func ConvertToIntree(protoLog *BranchUndoLog) *undo.BranchUndoLog {
  119. intreeLog := &undo.BranchUndoLog{
  120. Xid: protoLog.Xid,
  121. BranchID: protoLog.BranchID,
  122. Logs: []undo.SQLUndoLog{},
  123. }
  124. for _, pbSqlLog := range protoLog.Logs {
  125. undoSqlLog := undo.SQLUndoLog{
  126. SQLType: types.SQLType(pbSqlLog.SQLType),
  127. TableName: pbSqlLog.TableName,
  128. }
  129. if pbSqlLog.BeforeImage != nil {
  130. undoSqlLog.BeforeImage = &types.RecordImage{
  131. TableName: pbSqlLog.BeforeImage.TableName,
  132. SQLType: types.SQLType(pbSqlLog.BeforeImage.SQLType),
  133. Rows: []types.RowImage{},
  134. }
  135. for _, pbRow := range pbSqlLog.BeforeImage.Rows {
  136. undoRow := types.RowImage{
  137. Columns: []types.ColumnImage{},
  138. }
  139. for _, pbCol := range pbRow.Columns {
  140. anyValue, err := convertAnyToInterface(pbCol.Value)
  141. if err != nil {
  142. continue
  143. }
  144. undoCol := types.ColumnImage{
  145. KeyType: types.IndexType(pbCol.KeyType),
  146. ColumnName: pbCol.ColumnName,
  147. ColumnType: types.JDBCType(pbCol.ColumnType),
  148. Value: anyValue,
  149. }
  150. undoRow.Columns = append(undoRow.Columns, undoCol)
  151. }
  152. undoSqlLog.BeforeImage.Rows = append(undoSqlLog.BeforeImage.Rows, undoRow)
  153. }
  154. }
  155. if pbSqlLog.AfterImage != nil {
  156. undoSqlLog.AfterImage = &types.RecordImage{
  157. TableName: pbSqlLog.AfterImage.TableName,
  158. SQLType: types.SQLType(pbSqlLog.AfterImage.SQLType),
  159. Rows: []types.RowImage{},
  160. }
  161. for _, pbRow := range pbSqlLog.AfterImage.Rows {
  162. undoRow := types.RowImage{
  163. Columns: []types.ColumnImage{},
  164. }
  165. for _, pbCol := range pbRow.Columns {
  166. anyValue, err := convertAnyToInterface(pbCol.Value)
  167. if err != nil {
  168. continue
  169. }
  170. undoCol := types.ColumnImage{
  171. KeyType: types.IndexType(pbCol.KeyType),
  172. ColumnName: pbCol.ColumnName,
  173. ColumnType: types.JDBCType(pbCol.ColumnType),
  174. Value: anyValue,
  175. }
  176. undoRow.Columns = append(undoRow.Columns, undoCol)
  177. }
  178. undoSqlLog.AfterImage.Rows = append(undoSqlLog.AfterImage.Rows, undoRow)
  179. }
  180. }
  181. intreeLog.Logs = append(intreeLog.Logs, undoSqlLog)
  182. }
  183. return intreeLog
  184. }
  185. func convertAnyToInterface(anyValue *any.Any) (interface{}, error) {
  186. var value interface{}
  187. bytesValue := &wrappers.BytesValue{}
  188. err := anypb.UnmarshalTo(anyValue, bytesValue, proto.UnmarshalOptions{})
  189. if err != nil {
  190. return value, err
  191. }
  192. uErr := json.Unmarshal(bytesValue.Value, &value)
  193. if uErr != nil {
  194. return value, uErr
  195. }
  196. return value, nil
  197. }
  198. func convertInterfaceToAny(v interface{}) (*any.Any, error) {
  199. anyValue := &any.Any{}
  200. bytes, _ := json.Marshal(v)
  201. bytesValue := &wrappers.BytesValue{
  202. Value: bytes,
  203. }
  204. err := anypb.MarshalFrom(anyValue, bytesValue, proto.MarshalOptions{})
  205. return anyValue, err
  206. }