From f5a12a8d3f7ae9eeb7164a6c163f4a321e41479b Mon Sep 17 00:00:00 2001 From: Ian Norden Date: Thu, 10 Sep 2020 22:53:34 -0500 Subject: [PATCH] Iterator.Next() method --- postgres/database.go | 2 +- postgres/iterator.go | 42 ++++++++++++++++++++++++------------------ postgres/util.go | 2 +- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/postgres/database.go b/postgres/database.go index b2d9f71..0774bd3 100644 --- a/postgres/database.go +++ b/postgres/database.go @@ -29,7 +29,7 @@ import ( var errNotSupported = errors.New("this operation is not supported") -var ( +const ( hasPgStr = "SELECT exists(select 1 from eth.key_preimages WHERE eth_key = $1)" getPgStr = "SELECT data FROM public.blocks INNER JOIN eth.key_preimages ON (ipfs_key = blocks.key) WHERE eth_key = $1" putPgStr = "INSERT INTO public.blocks (key, data) VALUES ($1, $2) ON CONFLICT (key) DO NOTHING" diff --git a/postgres/iterator.go b/postgres/iterator.go index f673729..656a56e 100644 --- a/postgres/iterator.go +++ b/postgres/iterator.go @@ -19,17 +19,25 @@ package pgipfsethdb import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/jmoiron/sqlx" + "github.com/sirupsen/logrus" ) +const ( + nextPgStr = `SELECT key, data FROM public.blocks + INNER JOIN eth.key_preimages ON (ipfs_key = key) + WHERE eth_key > $1 ORDER BY eth_key LIMIT 1` +) + +type nextModel struct { + Key []byte `db:"eth_key"` + Value []byte `db:"data"` +} + // Iterator is the type that satisfies the ethdb.Iterator interface for PG-IPFS Ethereum data using a direct Postgres connection -// Iteratee interface is used in Geth for various tests, trie/sync_bloom.go (for fast sync), -// rawdb.InspectDatabase, and the new core/state/snapshot features. -// This should not be confused with trie.NodeIterator or state.NodeIteraor (which can be constructed -// from the ethdb.KeyValueStoreand ethdb.Database interfaces) type Iterator struct { - db *sqlx.DB - currentKey, prefix []byte - err error + db *sqlx.DB + currentKey, prefix, currentValue []byte + err error } // NewIterator returns an ethdb.Iterator interface for PG-IPFS @@ -45,9 +53,14 @@ func NewIterator(start, prefix []byte, db *sqlx.DB) ethdb.Iterator { // Next moves the iterator to the next key/value pair // It returns whether the iterator is exhausted func (i *Iterator) Next() bool { - // this is complicated by the ipfs db keys not being the keccak256 hashes - // go-ethereum usage of this method expects the iteration to occur over keccak256 keys - panic("implement me: Next") + next := new(nextModel) + if err := i.db.Get(next, nextPgStr, i.currentKey); err != nil { + logrus.Errorf("iterator.Next() error: %v", err) + i.currentKey, i.currentValue = nil, nil + return false + } + i.currentKey, i.currentValue = next.Key, next.Value + return true } // Error satisfies the ethdb.Iterator interface @@ -70,14 +83,7 @@ func (i *Iterator) Key() []byte { // The caller should not modify the contents of the returned slice // and its contents may change on the next call to Next func (i *Iterator) Value() []byte { - mhKey, err := MultihashKeyFromKeccak256(i.currentKey) - if err != nil { - i.err = err - return nil - } - var data []byte - i.err = i.db.Get(&data, getPgStr, mhKey) - return data + return i.currentValue } // Release satisfies the ethdb.Iterator interface diff --git a/postgres/util.go b/postgres/util.go index e2a11fe..19d02b3 100644 --- a/postgres/util.go +++ b/postgres/util.go @@ -49,9 +49,9 @@ func DatastoreKeyFromGethKey(h []byte) (string, error) { case Prefixed, Suffixed: // This data is not mapped by hash => content by geth, store it using the prefixed/suffixed key directly // I.e. the public.blocks datastore key == the hex representation of the geth key + // Alternatively, decompose the data and derive the hash return common.Bytes2Hex(h), nil default: return "", fmt.Errorf("invalid formatting of database key: %x", h) } - }