Skip to content

Commit

Permalink
add pool indexes (0xPolygonHermez#2731)
Browse files Browse the repository at this point in the history
* add pool indexes

* add pool indexes

* add pool indexes

* add pool indexes

* add pool indexes

* add pool indexes

* add pool indexes
  • Loading branch information
ToniRamirezM authored Oct 30, 2023
1 parent 6d36aa2 commit 99b4749
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 0 deletions.
8 changes: 8 additions & 0 deletions db/migrations/pool/0011.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,13 @@ CREATE TABLE pool.whitelisted (
addr VARCHAR PRIMARY KEY
);

CREATE INDEX IF NOT EXISTS idx_transaction_from_nonce ON pool.transaction (from_address, nonce);
CREATE INDEX IF NOT EXISTS idx_transaction_status ON pool.transaction (status);
CREATE INDEX IF NOT EXISTS idx_transaction_hash ON pool.transaction (hash);

-- +migrate Down
DROP TABLE pool.whitelisted;

DROP INDEX IF EXISTS pool.idx_transaction_from_nonce;
DROP INDEX IF EXISTS pool.idx_transaction_status;
DROP INDEX IF EXISTS pool.idx_transaction_hash;
49 changes: 49 additions & 0 deletions db/migrations/pool/0011_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package pool_migrations_test

import (
"database/sql"
"testing"

"github.com/stretchr/testify/assert"
)

// this migration changes length of the token name
type migrationTest0011 struct{}

func (m migrationTest0011) InsertData(db *sql.DB) error {
return nil
}

var indexes = []string{
"idx_transaction_from_nonce",
"idx_transaction_status",
"idx_transaction_hash",
}

func (m migrationTest0011) RunAssertsAfterMigrationUp(t *testing.T, db *sql.DB) {
// Check indexes adding
for _, idx := range indexes {
// getIndex
const getIndex = `SELECT count(*) FROM pg_indexes WHERE indexname = $1;`
row := db.QueryRow(getIndex, idx)
var result int
assert.NoError(t, row.Scan(&result))
assert.Equal(t, 1, result)
}
}

func (m migrationTest0011) RunAssertsAfterMigrationDown(t *testing.T, db *sql.DB) {
// Check indexes removing
for _, idx := range indexes {
// getIndex
const getIndex = `SELECT count(*) FROM pg_indexes WHERE indexname = $1;`
row := db.QueryRow(getIndex, idx)
var result int
assert.NoError(t, row.Scan(&result))
assert.Equal(t, 0, result)
}
}

func TestMigration0011(t *testing.T) {
runMigrationTest(t, 11, migrationTest0011{})
}
116 changes: 116 additions & 0 deletions db/migrations/pool/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package pool_migrations_test

import (
"database/sql"
"fmt"
"testing"

"github.com/0xPolygonHermez/zkevm-node/db"
"github.com/0xPolygonHermez/zkevm-node/log"
"github.com/0xPolygonHermez/zkevm-node/test/dbutils"
"github.com/gobuffalo/packr/v2"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/stdlib"
migrate "github.com/rubenv/sql-migrate"
"github.com/stretchr/testify/require"
)

/*
Considerations tricks and tips for migration file testing:
- Functionality of the DB is tested by the rest of the packages, migration tests only have to check persistence across migrations (both UP and DOWN)
- It's recommended to use real data (from testnet/mainnet), but modifying NULL fields to check that those are migrated properly
- It's recommended to use some SQL tool (such as DBeaver) that generates insert queries from existing rows
- Any new migration file could be tested using the existing `migrationTester` interface.
*/

func init() {
log.Init(log.Config{
Level: "debug",
Outputs: []string{"stderr"},
})
}

type migrationTester interface {
// InsertData used to insert data in the affected tables of the migration that is being tested
// data will be inserted with the schema as it was previous the migration that is being tested
InsertData(*sql.DB) error
// RunAssertsAfterMigrationUp this function will be called after running the migration is being tested
// and should assert that the data inserted in the function InsertData is persisted properly
RunAssertsAfterMigrationUp(*testing.T, *sql.DB)
// RunAssertsAfterMigrationDown this function will be called after reverting the migration that is being tested
// and should assert that the data inserted in the function InsertData is persisted properly
RunAssertsAfterMigrationDown(*testing.T, *sql.DB)
}

var (
packrMigrations = map[string]*packr.Box{
db.PoolMigrationName: packr.New(db.PoolMigrationName, "./migrations/pool"),
}
)

func runMigrationTest(t *testing.T, migrationNumber int, miter migrationTester) {
// Initialize an empty DB
d, err := initCleanSQLDB(dbutils.NewPoolConfigFromEnv())
require.NoError(t, err)
require.NoError(t, runMigrationsDown(d, 0, db.PoolMigrationName))
// Run migrations until migration to test
require.NoError(t, runMigrationsUp(d, migrationNumber-1, db.PoolMigrationName))
// Insert data into table(s) affected by migration
require.NoError(t, miter.InsertData(d))
// Run migration that is being tested
require.NoError(t, runMigrationsUp(d, 1, db.PoolMigrationName))
// Check that data is persisted properly after migration up
miter.RunAssertsAfterMigrationUp(t, d)
// Revert migration to test
require.NoError(t, runMigrationsDown(d, 1, db.PoolMigrationName))
// Check that data is persisted properly after migration down
miter.RunAssertsAfterMigrationDown(t, d)
}

func initCleanSQLDB(config db.Config) (*sql.DB, error) {
// run migrations
if err := db.RunMigrationsDown(config, db.PoolMigrationName); err != nil {
return nil, err
}
c, err := pgx.ParseConfig(fmt.Sprintf("postgres://%s:%s@%s:%s/%s", config.User, config.Password, config.Host, config.Port, config.Name))
if err != nil {
return nil, err
}
sqlDB := stdlib.OpenDB(*c)
return sqlDB, nil
}

func runMigrationsUp(d *sql.DB, n int, packrName string) error {
box, ok := packrMigrations[packrName]
if !ok {
return fmt.Errorf("packr box not found with name: %v", packrName)
}

var migrations = &migrate.PackrMigrationSource{Box: box}
nMigrations, err := migrate.ExecMax(d, "postgres", migrations, migrate.Up, n)
if err != nil {
return err
}
if nMigrations != n {
return fmt.Errorf("Unexpected amount of migrations: expected: %d, actual: %d", n, nMigrations)
}
return nil
}

func runMigrationsDown(d *sql.DB, n int, packrName string) error {
box, ok := packrMigrations[packrName]
if !ok {
return fmt.Errorf("packr box not found with name: %v", packrName)
}

var migrations = &migrate.PackrMigrationSource{Box: box}
nMigrations, err := migrate.ExecMax(d, "postgres", migrations, migrate.Down, n)
if err != nil {
return err
}
if nMigrations != n {
return fmt.Errorf("Unexpected amount of migrations: expected: %d, actual: %d", n, nMigrations)
}
return nil
}

0 comments on commit 99b4749

Please sign in to comment.