|
| 1 | +package models |
| 2 | + |
| 3 | +import ( |
| 4 | + "database/sql" |
| 5 | + "time" |
| 6 | + |
| 7 | + "github.com/go-gorp/gorp" |
| 8 | +) |
| 9 | + |
| 10 | +// BlocksModel groups operations on Blocks. |
| 11 | +type BlocksModel struct{} |
| 12 | + |
| 13 | +// Block is a block. |
| 14 | +type Block struct { |
| 15 | + Height int `db:"height" json:"height"` // pk |
| 16 | + Hash string `db:"hash" json:"hash"` |
| 17 | + Timestamp int64 `db:"timestamp" json:"timestamp"` |
| 18 | + TimestampHuman time.Time `db:"-" json:"timestamp_human"` |
| 19 | + Version int32 `db:"version" json:"version"` |
| 20 | + Producer string `db:"producer" json:"producer"` |
| 21 | + MerkleRoot string `db:"merkle_root" json:"merkle_root"` |
| 22 | + Parent string `db:"parent" json:"parent"` |
| 23 | + TxCount int `db:"tx_count" json:"tx_count"` |
| 24 | +} |
| 25 | + |
| 26 | +// PostGet is the hook after SELECT query. |
| 27 | +func (b *Block) PostGet(s gorp.SqlExecutor) error { |
| 28 | + b.TimestampHuman = time.Unix(0, b.Timestamp) |
| 29 | + return nil |
| 30 | +} |
| 31 | + |
| 32 | +// GetBlockList get a list of blocks with height in [from, to). |
| 33 | +func (m *BlocksModel) GetBlockList(since, page, size int) (blocks []*Block, pagination *Pagination, err error) { |
| 34 | + var ( |
| 35 | + querySQL = ` |
| 36 | + SELECT |
| 37 | + height, |
| 38 | + hash, |
| 39 | + timestamp, |
| 40 | + version, |
| 41 | + producer, |
| 42 | + merkle_root, |
| 43 | + parent, |
| 44 | + tx_count |
| 45 | + FROM |
| 46 | + indexed_blocks |
| 47 | + ` |
| 48 | + countSQL = buildCountSQL(querySQL) |
| 49 | + conds []string |
| 50 | + args []interface{} |
| 51 | + ) |
| 52 | + |
| 53 | + pagination = NewPagination(page, size) |
| 54 | + if since > 0 { |
| 55 | + conds = append(conds, "height < ?") |
| 56 | + args = append(args, since) |
| 57 | + } |
| 58 | + |
| 59 | + querySQL, countSQL = buildSQLWithConds(querySQL, countSQL, conds) |
| 60 | + |
| 61 | + count, err := chaindb.SelectInt(countSQL, args...) |
| 62 | + if err != nil { |
| 63 | + return nil, pagination, err |
| 64 | + } |
| 65 | + pagination.SetTotal(int(count)) |
| 66 | + blocks = make([]*Block, 0) |
| 67 | + if pagination.Offset() > pagination.Total { |
| 68 | + return blocks, pagination, nil |
| 69 | + } |
| 70 | + |
| 71 | + querySQL += " ORDER BY height DESC" |
| 72 | + querySQL += " LIMIT ? OFFSET ?" |
| 73 | + args = append(args, pagination.Limit(), pagination.Offset()) |
| 74 | + |
| 75 | + _, err = chaindb.Select(&blocks, querySQL, args...) |
| 76 | + return blocks, pagination, err |
| 77 | +} |
| 78 | + |
| 79 | +// GetBlockByHeight get a block by its height. |
| 80 | +func (m *BlocksModel) GetBlockByHeight(height int) (block *Block, err error) { |
| 81 | + block = &Block{} |
| 82 | + query := `SELECT height, hash, timestamp, version, producer, merkle_root, parent, tx_count |
| 83 | + FROM indexed_blocks WHERE height = ?` |
| 84 | + err = chaindb.SelectOne(block, query, height) |
| 85 | + if err == sql.ErrNoRows { |
| 86 | + return nil, nil |
| 87 | + } |
| 88 | + return block, err |
| 89 | +} |
| 90 | + |
| 91 | +// GetBlockByHash get a block by its hash. |
| 92 | +func (m *BlocksModel) GetBlockByHash(hash string) (block *Block, err error) { |
| 93 | + block = &Block{} |
| 94 | + query := `SELECT height, hash, timestamp, version, producer, merkle_root, parent, tx_count |
| 95 | + FROM indexed_blocks WHERE hash = ?` |
| 96 | + err = chaindb.SelectOne(block, query, hash) |
| 97 | + if err == sql.ErrNoRows { |
| 98 | + return nil, nil |
| 99 | + } |
| 100 | + return block, err |
| 101 | +} |
0 commit comments