hermez-node/db/utils.go
db/utils.goRaw
1package db
2
3import (
4 "encoding/base64"
5 "fmt"
6 "math/big"
7 "reflect"
8 "strings"
9
10 "github.com/russross/meddler"
11)
12
13// InitMeddler registers tags to be used to read/write from SQL DBs using meddler
14func InitMeddler() {
15 meddler.Register("bigint", BigIntMeddler{})
16}
17
18// BulkInsert performs a bulk insert with a single statement into the specified table. Example:
19// `db.BulkInsert(myDB, "INSERT INTO block (eth_block_num, timestamp, hash) VALUES %s", blocks[:])`
20// Note that all the columns must be specified in the query, and they must be in the same order as in the table.
21func BulkInsert(db meddler.DB, q string, args interface{}) error {
22 arrayValue := reflect.ValueOf(args)
23 arrayLen := arrayValue.Len()
24 valueStrings := make([]string, 0, arrayLen)
25 var arglist = make([]interface{}, 0)
26 for i := 0; i < arrayLen; i++ {
27 arg := arrayValue.Index(i).Addr().Interface()
28 elemArglist, err := meddler.Default.Values(arg, true)
29 if err != nil {
30 return err
31 }
32 arglist = append(arglist, elemArglist...)
33 value := "("
34 for j := 0; j < len(elemArglist); j++ {
35 value += fmt.Sprintf("$%d, ", i*len(elemArglist)+j+1)
36 }
37 value = value[:len(value)-2] + ")"
38 valueStrings = append(valueStrings, value)
39 }
40 stmt := fmt.Sprintf(q, strings.Join(valueStrings, ","))
41 _, err := db.Exec(stmt, arglist...)
42 return err
43}
44
45// BigIntMeddler encodes or decodes the field value to or from JSON
46type BigIntMeddler struct{}
47
48// PreRead is called before a Scan operation for fields that have the BigIntMeddler
49func (b BigIntMeddler) PreRead(fieldAddr interface{}) (scanTarget interface{}, err error) {
50 // give a pointer to a byte buffer to grab the raw data
51 return new(string), nil
52}
53
54// PostRead is called after a Scan operation for fields that have the BigIntMeddler
55func (b BigIntMeddler) PostRead(fieldPtr, scanTarget interface{}) error {
56 ptr := scanTarget.(*string)
57 if ptr == nil {
58 return fmt.Errorf("BigIntMeddler.PostRead: nil pointer")
59 }
60
61 data, err := base64.StdEncoding.DecodeString(*ptr)
62 if err != nil {
63 return fmt.Errorf("big.Int decode error: %v", err)
64 }
65 field := fieldPtr.(**big.Int)
66 *field = new(big.Int).SetBytes(data)
67
68 return nil
69}
70
71// PreWrite is called before an Insert or Update operation for fields that have the BigIntMeddler
72func (b BigIntMeddler) PreWrite(fieldPtr interface{}) (saveValue interface{}, err error) {
73 field := fieldPtr.(*big.Int)
74
75 str := base64.StdEncoding.EncodeToString(field.Bytes())
76
77 return str, nil
78}