From e88c138760a3ab065bc6d0cd08eacc6b516400d5 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Wed, 21 Aug 2024 10:49:02 -0400 Subject: [PATCH] refactor(indexer/postgres)!: use schema/indexer API and hide types/methods (#21363) --- indexer/postgres/base_sql.go | 4 +- indexer/postgres/column.go | 4 +- indexer/postgres/conn.go | 4 +- indexer/postgres/create_table.go | 20 ++-- indexer/postgres/create_table_test.go | 17 ++-- indexer/postgres/enum.go | 14 +-- indexer/postgres/enum_test.go | 4 +- indexer/postgres/indexer.go | 93 ++++++++++++------- indexer/postgres/listener.go | 38 ++++++++ indexer/postgres/module.go | 31 +++---- indexer/postgres/object.go | 16 ++-- indexer/postgres/options.go | 14 +-- indexer/postgres/tests/config.go | 26 ++++++ indexer/postgres/tests/init_schema_test.go | 25 +++-- indexer/postgres/tests/log.go | 44 +++++++++ .../postgres/tests/testdata/init_schema.txt | 28 +++--- .../testdata/init_schema_no_retain_delete.txt | 28 +++--- 17 files changed, 266 insertions(+), 144 deletions(-) create mode 100644 indexer/postgres/listener.go create mode 100644 indexer/postgres/tests/config.go create mode 100644 indexer/postgres/tests/log.go diff --git a/indexer/postgres/base_sql.go b/indexer/postgres/base_sql.go index 32eb38f364c0..ac79b0929a49 100644 --- a/indexer/postgres/base_sql.go +++ b/indexer/postgres/base_sql.go @@ -1,7 +1,7 @@ package postgres -// BaseSQL is the base SQL that is always included in the schema. -const BaseSQL = ` +// baseSQL is the base SQL that is always included in the schema. +const baseSQL = ` CREATE OR REPLACE FUNCTION nanos_to_timestamptz(nanos bigint) RETURNS timestamptz AS $$ SELECT to_timestamp(nanos / 1000000000) + (nanos / 1000000000) * INTERVAL '1 microsecond' $$ LANGUAGE SQL IMMUTABLE; diff --git a/indexer/postgres/column.go b/indexer/postgres/column.go index 188e9d8da651..e1c4f7b7f708 100644 --- a/indexer/postgres/column.go +++ b/indexer/postgres/column.go @@ -8,7 +8,7 @@ import ( ) // createColumnDefinition writes a column definition within a CREATE TABLE statement for the field. -func (tm *ObjectIndexer) createColumnDefinition(writer io.Writer, field schema.Field) error { +func (tm *objectIndexer) createColumnDefinition(writer io.Writer, field schema.Field) error { _, err := fmt.Fprintf(writer, "%q ", field.Name) if err != nil { return err @@ -110,7 +110,7 @@ func simpleColumnType(kind schema.Kind) string { // updatableColumnName is the name of the insertable/updatable column name for the field. // This is the field name in most cases, except for time columns which are stored as nanos // and then converted to timestamp generated columns. -func (tm *ObjectIndexer) updatableColumnName(field schema.Field) (name string, err error) { +func (tm *objectIndexer) updatableColumnName(field schema.Field) (name string, err error) { name = field.Name if field.Kind == schema.TimeKind { name = fmt.Sprintf("%s_nanos", name) diff --git a/indexer/postgres/conn.go b/indexer/postgres/conn.go index de8c1cac6b47..2e9c96c7c5ad 100644 --- a/indexer/postgres/conn.go +++ b/indexer/postgres/conn.go @@ -5,8 +5,8 @@ import ( "database/sql" ) -// DBConn is an interface that abstracts the *sql.DB, *sql.Tx and *sql.Conn types. -type DBConn interface { +// dbConn is an interface that abstracts the *sql.DB, *sql.Tx and *sql.Conn types. +type dbConn interface { ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) diff --git a/indexer/postgres/create_table.go b/indexer/postgres/create_table.go index 8f5f0e6ca206..0f8dc652190e 100644 --- a/indexer/postgres/create_table.go +++ b/indexer/postgres/create_table.go @@ -7,25 +7,25 @@ import ( "strings" ) -// CreateTable creates the table for the object type. -func (tm *ObjectIndexer) CreateTable(ctx context.Context, conn DBConn) error { +// createTable creates the table for the object type. +func (tm *objectIndexer) createTable(ctx context.Context, conn dbConn) error { buf := new(strings.Builder) - err := tm.CreateTableSql(buf) + err := tm.createTableSql(buf) if err != nil { return err } sqlStr := buf.String() - if tm.options.Logger != nil { - tm.options.Logger(fmt.Sprintf("Creating table %s", tm.TableName()), sqlStr) + if tm.options.logger != nil { + tm.options.logger.Debug("Creating table %s", "table", tm.tableName(), "sql", sqlStr) } _, err = conn.ExecContext(ctx, sqlStr) return err } -// CreateTableSql generates a CREATE TABLE statement for the object type. -func (tm *ObjectIndexer) CreateTableSql(writer io.Writer) error { - _, err := fmt.Fprintf(writer, "CREATE TABLE IF NOT EXISTS %q (\n\t", tm.TableName()) +// createTableSql generates a CREATE TABLE statement for the object type. +func (tm *objectIndexer) createTableSql(writer io.Writer) error { + _, err := fmt.Fprintf(writer, "CREATE TABLE IF NOT EXISTS %q (\n\t", tm.tableName()) if err != nil { return err } @@ -53,7 +53,7 @@ func (tm *ObjectIndexer) CreateTableSql(writer io.Writer) error { } // add _deleted column when we have RetainDeletions set and enabled - if !tm.options.DisableRetainDeletions && tm.typ.RetainDeletions { + if !tm.options.disableRetainDeletions && tm.typ.RetainDeletions { _, err = fmt.Fprintf(writer, "_deleted BOOLEAN NOT NULL DEFAULT FALSE,\n\t") if err != nil { return err @@ -87,7 +87,7 @@ func (tm *ObjectIndexer) CreateTableSql(writer io.Writer) error { // we GRANT SELECT on the table to PUBLIC so that the table is automatically available // for querying using off-the-shelf tools like pg_graphql, Postgrest, Postgraphile, etc. // without any login permissions - _, err = fmt.Fprintf(writer, "GRANT SELECT ON TABLE %q TO PUBLIC;", tm.TableName()) + _, err = fmt.Fprintf(writer, "GRANT SELECT ON TABLE %q TO PUBLIC;", tm.tableName()) if err != nil { return err } diff --git a/indexer/postgres/create_table_test.go b/indexer/postgres/create_table_test.go index 2538338319e7..67851008e40b 100644 --- a/indexer/postgres/create_table_test.go +++ b/indexer/postgres/create_table_test.go @@ -5,9 +5,10 @@ import ( "cosmossdk.io/indexer/postgres/internal/testdata" "cosmossdk.io/schema" + "cosmossdk.io/schema/logutil" ) -func ExampleObjectIndexer_CreateTableSql_allKinds() { +func Example_objectIndexer_createTableSql_allKinds() { exampleCreateTable(testdata.AllKindsObject) // Output: // CREATE TABLE IF NOT EXISTS "test_all_kinds" ( @@ -40,7 +41,7 @@ func ExampleObjectIndexer_CreateTableSql_allKinds() { // GRANT SELECT ON TABLE "test_all_kinds" TO PUBLIC; } -func ExampleObjectIndexer_CreateTableSql_singleton() { +func Example_objectIndexer_createTableSql_singleton() { exampleCreateTable(testdata.SingletonObject) // Output: // CREATE TABLE IF NOT EXISTS "test_singleton" ( @@ -53,7 +54,7 @@ func ExampleObjectIndexer_CreateTableSql_singleton() { // GRANT SELECT ON TABLE "test_singleton" TO PUBLIC; } -func ExampleObjectIndexer_CreateTableSql_vote() { +func Example_objectIndexer_createTableSql_vote() { exampleCreateTable(testdata.VoteObject) // Output: // CREATE TABLE IF NOT EXISTS "test_vote" ( @@ -66,7 +67,7 @@ func ExampleObjectIndexer_CreateTableSql_vote() { // GRANT SELECT ON TABLE "test_vote" TO PUBLIC; } -func ExampleObjectIndexer_CreateTableSql_vote_no_retain_delete() { +func Example_objectIndexer_createTableSql_vote_no_retain_delete() { exampleCreateTableOpt(testdata.VoteObject, true) // Output: // CREATE TABLE IF NOT EXISTS "test_vote" ( @@ -83,11 +84,11 @@ func exampleCreateTable(objectType schema.ObjectType) { } func exampleCreateTableOpt(objectType schema.ObjectType, noRetainDelete bool) { - tm := NewObjectIndexer("test", objectType, Options{ - Logger: func(msg, sql string, params ...interface{}) {}, - DisableRetainDeletions: noRetainDelete, + tm := newObjectIndexer("test", objectType, options{ + logger: logutil.NoopLogger{}, + disableRetainDeletions: noRetainDelete, }) - err := tm.CreateTableSql(os.Stdout) + err := tm.createTableSql(os.Stdout) if err != nil { panic(err) } diff --git a/indexer/postgres/enum.go b/indexer/postgres/enum.go index 709fc9039562..716ea4d7701e 100644 --- a/indexer/postgres/enum.go +++ b/indexer/postgres/enum.go @@ -10,8 +10,8 @@ import ( "cosmossdk.io/schema" ) -// CreateEnumType creates an enum type in the database. -func (m *ModuleIndexer) CreateEnumType(ctx context.Context, conn DBConn, enum schema.EnumType) error { +// createEnumType creates an enum type in the database. +func (m *moduleIndexer) createEnumType(ctx context.Context, conn dbConn, enum schema.EnumType) error { typeName := enumTypeName(m.moduleName, enum) row := conn.QueryRowContext(ctx, "SELECT 1 FROM pg_type WHERE typname = $1", typeName) var res interface{} @@ -25,21 +25,21 @@ func (m *ModuleIndexer) CreateEnumType(ctx context.Context, conn DBConn, enum sc } buf := new(strings.Builder) - err := CreateEnumTypeSql(buf, m.moduleName, enum) + err := createEnumTypeSql(buf, m.moduleName, enum) if err != nil { return err } sqlStr := buf.String() - if m.options.Logger != nil { - m.options.Logger("Creating enum type", sqlStr) + if m.options.logger != nil { + m.options.logger.Debug("Creating enum type", "sql", sqlStr) } _, err = conn.ExecContext(ctx, sqlStr) return err } -// CreateEnumTypeSql generates a CREATE TYPE statement for the enum definition. -func CreateEnumTypeSql(writer io.Writer, moduleName string, enum schema.EnumType) error { +// createEnumTypeSql generates a CREATE TYPE statement for the enum definition. +func createEnumTypeSql(writer io.Writer, moduleName string, enum schema.EnumType) error { _, err := fmt.Fprintf(writer, "CREATE TYPE %q AS ENUM (", enumTypeName(moduleName, enum)) if err != nil { return err diff --git a/indexer/postgres/enum_test.go b/indexer/postgres/enum_test.go index 22d8870171c3..c65475d0dd39 100644 --- a/indexer/postgres/enum_test.go +++ b/indexer/postgres/enum_test.go @@ -6,8 +6,8 @@ import ( "cosmossdk.io/indexer/postgres/internal/testdata" ) -func ExampleCreateEnumTypeSql() { - err := CreateEnumTypeSql(os.Stdout, "test", testdata.MyEnum) +func Example_createEnumTypeSql() { + err := createEnumTypeSql(os.Stdout, "test", testdata.MyEnum) if err != nil { panic(err) } diff --git a/indexer/postgres/indexer.go b/indexer/postgres/indexer.go index ab911d8d22ba..2c37e9a79b11 100644 --- a/indexer/postgres/indexer.go +++ b/indexer/postgres/indexer.go @@ -3,10 +3,11 @@ package postgres import ( "context" "database/sql" + "encoding/json" "errors" - "fmt" - "cosmossdk.io/schema/appdata" + "cosmossdk.io/schema/indexer" + "cosmossdk.io/schema/logutil" ) type Config struct { @@ -22,9 +23,28 @@ type Config struct { type SqlLogger = func(msg, sql string, params ...interface{}) -func StartIndexer(ctx context.Context, logger SqlLogger, config Config) (appdata.Listener, error) { +type indexerImpl struct { + ctx context.Context + db *sql.DB + tx *sql.Tx + opts options + modules map[string]*moduleIndexer + logger logutil.Logger +} + +func StartIndexer(params indexer.InitParams) (indexer.InitResult, error) { + config, err := decodeConfig(params.Config.Config) + if err != nil { + return indexer.InitResult{}, err + } + + ctx := params.Context + if ctx == nil { + ctx = context.Background() + } + if config.DatabaseURL == "" { - return appdata.Listener{}, errors.New("missing database URL") + return indexer.InitResult{}, errors.New("missing database URL") } driver := config.DatabaseDriver @@ -34,48 +54,51 @@ func StartIndexer(ctx context.Context, logger SqlLogger, config Config) (appdata db, err := sql.Open(driver, config.DatabaseURL) if err != nil { - return appdata.Listener{}, err + return indexer.InitResult{}, err } tx, err := db.BeginTx(ctx, nil) if err != nil { - return appdata.Listener{}, err + return indexer.InitResult{}, err } // commit base schema - _, err = tx.Exec(BaseSQL) + _, err = tx.Exec(baseSQL) if err != nil { - return appdata.Listener{}, err + return indexer.InitResult{}, err + } + + moduleIndexers := map[string]*moduleIndexer{} + opts := options{ + disableRetainDeletions: config.DisableRetainDeletions, + logger: params.Logger, } - moduleIndexers := map[string]*ModuleIndexer{} - opts := Options{ - DisableRetainDeletions: config.DisableRetainDeletions, - Logger: logger, + idx := &indexerImpl{ + ctx: ctx, + db: db, + tx: tx, + opts: opts, + modules: moduleIndexers, + logger: params.Logger, } - return appdata.Listener{ - InitializeModuleData: func(data appdata.ModuleInitializationData) error { - moduleName := data.ModuleName - modSchema := data.Schema - _, ok := moduleIndexers[moduleName] - if ok { - return fmt.Errorf("module %s already initialized", moduleName) - } - - mm := NewModuleIndexer(moduleName, modSchema, opts) - moduleIndexers[moduleName] = mm - - return mm.InitializeSchema(ctx, tx) - }, - Commit: func(data appdata.CommitData) (completionCallback func() error, err error) { - err = tx.Commit() - if err != nil { - return nil, err - } - - tx, err = db.BeginTx(ctx, nil) - return nil, err - }, + return indexer.InitResult{ + Listener: idx.listener(), }, nil } + +func decodeConfig(rawConfig map[string]interface{}) (*Config, error) { + bz, err := json.Marshal(rawConfig) + if err != nil { + return nil, err + } + + var config Config + err = json.Unmarshal(bz, &config) + if err != nil { + return nil, err + } + + return &config, nil +} diff --git a/indexer/postgres/listener.go b/indexer/postgres/listener.go new file mode 100644 index 000000000000..1f46c1c7c55c --- /dev/null +++ b/indexer/postgres/listener.go @@ -0,0 +1,38 @@ +package postgres + +import ( + "fmt" + + "cosmossdk.io/schema/appdata" +) + +func (i *indexerImpl) listener() appdata.Listener { + return appdata.Listener{ + InitializeModuleData: func(data appdata.ModuleInitializationData) error { + moduleName := data.ModuleName + modSchema := data.Schema + _, ok := i.modules[moduleName] + if ok { + return fmt.Errorf("module %s already initialized", moduleName) + } + + mm := newModuleIndexer(moduleName, modSchema, i.opts) + i.modules[moduleName] = mm + + return mm.initializeSchema(i.ctx, i.tx) + }, + StartBlock: func(data appdata.StartBlockData) error { + _, err := i.tx.Exec("INSERT INTO block (number) VALUES ($1)", data.Height) + return err + }, + Commit: func(data appdata.CommitData) (func() error, error) { + err := i.tx.Commit() + if err != nil { + return nil, err + } + + i.tx, err = i.db.BeginTx(i.ctx, nil) + return nil, err + }, + } +} diff --git a/indexer/postgres/module.go b/indexer/postgres/module.go index 0d6a28e2ef72..ffba1a4b2da9 100644 --- a/indexer/postgres/module.go +++ b/indexer/postgres/module.go @@ -7,32 +7,32 @@ import ( "cosmossdk.io/schema" ) -// ModuleIndexer manages the tables for a module. -type ModuleIndexer struct { +// moduleIndexer manages the tables for a module. +type moduleIndexer struct { moduleName string schema schema.ModuleSchema - tables map[string]*ObjectIndexer + tables map[string]*objectIndexer definedEnums map[string]schema.EnumType - options Options + options options } -// NewModuleIndexer creates a new ModuleIndexer for the given module schema. -func NewModuleIndexer(moduleName string, modSchema schema.ModuleSchema, options Options) *ModuleIndexer { - return &ModuleIndexer{ +// newModuleIndexer creates a new moduleIndexer for the given module schema. +func newModuleIndexer(moduleName string, modSchema schema.ModuleSchema, options options) *moduleIndexer { + return &moduleIndexer{ moduleName: moduleName, schema: modSchema, - tables: map[string]*ObjectIndexer{}, + tables: map[string]*objectIndexer{}, definedEnums: map[string]schema.EnumType{}, options: options, } } -// InitializeSchema creates tables for all object types in the module schema and creates enum types. -func (m *ModuleIndexer) InitializeSchema(ctx context.Context, conn DBConn) error { +// initializeSchema creates tables for all object types in the module schema and creates enum types. +func (m *moduleIndexer) initializeSchema(ctx context.Context, conn dbConn) error { // create enum types var err error m.schema.EnumTypes(func(enumType schema.EnumType) bool { - err = m.CreateEnumType(ctx, conn, enumType) + err = m.createEnumType(ctx, conn, enumType) return err == nil }) if err != nil { @@ -41,9 +41,9 @@ func (m *ModuleIndexer) InitializeSchema(ctx context.Context, conn DBConn) error // create tables for all object types m.schema.ObjectTypes(func(typ schema.ObjectType) bool { - tm := NewObjectIndexer(m.moduleName, typ, m.options) + tm := newObjectIndexer(m.moduleName, typ, m.options) m.tables[typ.Name] = tm - err = tm.CreateTable(ctx, conn) + err = tm.createTable(ctx, conn) if err != nil { err = fmt.Errorf("failed to create table for %s in module %s: %v", typ.Name, m.moduleName, err) //nolint:errorlint // using %v for go 1.12 compat } @@ -52,8 +52,3 @@ func (m *ModuleIndexer) InitializeSchema(ctx context.Context, conn DBConn) error return err } - -// ObjectIndexers returns the object indexers for the module. -func (m *ModuleIndexer) ObjectIndexers() map[string]*ObjectIndexer { - return m.tables -} diff --git a/indexer/postgres/object.go b/indexer/postgres/object.go index 78bbfdf636b1..ce98790a73bb 100644 --- a/indexer/postgres/object.go +++ b/indexer/postgres/object.go @@ -6,17 +6,17 @@ import ( "cosmossdk.io/schema" ) -// ObjectIndexer is a helper struct that generates SQL for a given object type. -type ObjectIndexer struct { +// objectIndexer is a helper struct that generates SQL for a given object type. +type objectIndexer struct { moduleName string typ schema.ObjectType valueFields map[string]schema.Field allFields map[string]schema.Field - options Options + options options } -// NewObjectIndexer creates a new ObjectIndexer for the given object type. -func NewObjectIndexer(moduleName string, typ schema.ObjectType, options Options) *ObjectIndexer { +// newObjectIndexer creates a new objectIndexer for the given object type. +func newObjectIndexer(moduleName string, typ schema.ObjectType, options options) *objectIndexer { allFields := make(map[string]schema.Field) valueFields := make(map[string]schema.Field) @@ -29,7 +29,7 @@ func NewObjectIndexer(moduleName string, typ schema.ObjectType, options Options) allFields[field.Name] = field } - return &ObjectIndexer{ + return &objectIndexer{ moduleName: moduleName, typ: typ, allFields: allFields, @@ -38,7 +38,7 @@ func NewObjectIndexer(moduleName string, typ schema.ObjectType, options Options) } } -// TableName returns the name of the table for the object type scoped to its module. -func (tm *ObjectIndexer) TableName() string { +// tableName returns the name of the table for the object type scoped to its module. +func (tm *objectIndexer) tableName() string { return fmt.Sprintf("%s_%s", tm.moduleName, tm.typ.Name) } diff --git a/indexer/postgres/options.go b/indexer/postgres/options.go index be93d43b6c76..d18a4c4d7f2c 100644 --- a/indexer/postgres/options.go +++ b/indexer/postgres/options.go @@ -1,10 +1,12 @@ package postgres -// Options are the options for module and object indexers. -type Options struct { - // DisableRetainDeletions disables retain deletions functionality even on object types that have it set. - DisableRetainDeletions bool +import "cosmossdk.io/schema/logutil" - // Logger is the logger for the indexer to use. - Logger SqlLogger +// options are the options for module and object indexers. +type options struct { + // disableRetainDeletions disables retain deletions functionality even on object types that have it set. + disableRetainDeletions bool + + // logger is the logger for the indexer to use. It may be nil. + logger logutil.Logger } diff --git a/indexer/postgres/tests/config.go b/indexer/postgres/tests/config.go new file mode 100644 index 000000000000..78e41f6059b5 --- /dev/null +++ b/indexer/postgres/tests/config.go @@ -0,0 +1,26 @@ +package tests + +import ( + "encoding/json" + + "cosmossdk.io/indexer/postgres" + "cosmossdk.io/schema/indexer" +) + +func postgresConfigToIndexerConfig(cfg postgres.Config) (indexer.Config, error) { + cfgBz, err := json.Marshal(cfg) + if err != nil { + return indexer.Config{}, err + } + + var cfgMap map[string]interface{} + err = json.Unmarshal(cfgBz, &cfgMap) + if err != nil { + return indexer.Config{}, err + } + + return indexer.Config{ + Type: "postgres", + Config: cfgMap, + }, nil +} diff --git a/indexer/postgres/tests/init_schema_test.go b/indexer/postgres/tests/init_schema_test.go index ae7da66c525a..4257f37d5ab7 100644 --- a/indexer/postgres/tests/init_schema_test.go +++ b/indexer/postgres/tests/init_schema_test.go @@ -2,7 +2,6 @@ package tests import ( "context" - "fmt" "os" "strings" "testing" @@ -16,6 +15,7 @@ import ( "cosmossdk.io/indexer/postgres" "cosmossdk.io/indexer/postgres/internal/testdata" "cosmossdk.io/schema/appdata" + "cosmossdk.io/schema/indexer" ) func TestInitSchema(t *testing.T) { @@ -33,24 +33,21 @@ func testInitSchema(t *testing.T, disableRetainDeletions bool, goldenFileName st connectionUrl := createTestDB(t) buf := &strings.Builder{} - logger := func(msg, sql string, params ...interface{}) { - _, err := fmt.Fprintln(buf, msg) - require.NoError(t, err) - _, err = fmt.Fprintln(buf, sql) - require.NoError(t, err) - if len(params) != 0 { - _, err = fmt.Fprintln(buf, "Params:", params) - require.NoError(t, err) - } - _, err = fmt.Fprintln(buf) - require.NoError(t, err) - } - listener, err := postgres.StartIndexer(context.Background(), logger, postgres.Config{ + + cfg, err := postgresConfigToIndexerConfig(postgres.Config{ DatabaseURL: connectionUrl, DisableRetainDeletions: disableRetainDeletions, }) require.NoError(t, err) + res, err := postgres.StartIndexer(indexer.InitParams{ + Config: cfg, + Context: context.Background(), + Logger: &prettyLogger{buf}, + }) + require.NoError(t, err) + listener := res.Listener + require.NotNil(t, listener.InitializeModuleData) require.NoError(t, listener.InitializeModuleData(appdata.ModuleInitializationData{ ModuleName: "test", diff --git a/indexer/postgres/tests/log.go b/indexer/postgres/tests/log.go new file mode 100644 index 000000000000..533a401305cc --- /dev/null +++ b/indexer/postgres/tests/log.go @@ -0,0 +1,44 @@ +package tests + +import ( + "fmt" + "io" + + "cosmossdk.io/schema/logutil" +) + +type prettyLogger struct { + out io.Writer +} + +func (l prettyLogger) Info(msg string, keyVals ...interface{}) { + l.write("INFO", msg, keyVals...) +} + +func (l prettyLogger) Warn(msg string, keyVals ...interface{}) { + l.write("WARN", msg, keyVals...) +} + +func (l prettyLogger) Error(msg string, keyVals ...interface{}) { + l.write("ERROR", msg, keyVals...) +} + +func (l prettyLogger) Debug(msg string, keyVals ...interface{}) { + l.write("DEBUG", msg, keyVals...) +} + +func (l prettyLogger) write(level, msg string, keyVals ...interface{}) { + _, err := fmt.Fprintf(l.out, "%s: %s\n", level, msg) + if err != nil { + panic(err) + } + + for i := 0; i < len(keyVals); i += 2 { + _, err = fmt.Fprintf(l.out, " %s: %v\n", keyVals[i], keyVals[i+1]) + if err != nil { + panic(err) + } + } +} + +var _ logutil.Logger = &prettyLogger{} diff --git a/indexer/postgres/tests/testdata/init_schema.txt b/indexer/postgres/tests/testdata/init_schema.txt index ce807a8f7d17..4d18d2fb23b1 100644 --- a/indexer/postgres/tests/testdata/init_schema.txt +++ b/indexer/postgres/tests/testdata/init_schema.txt @@ -1,11 +1,10 @@ -Creating enum type -CREATE TYPE "test_my_enum" AS ENUM ('a', 'b', 'c'); - -Creating enum type -CREATE TYPE "test_vote_type" AS ENUM ('yes', 'no', 'abstain'); - -Creating table test_all_kinds -CREATE TABLE IF NOT EXISTS "test_all_kinds" ( +DEBUG: Creating enum type + sql: CREATE TYPE "test_my_enum" AS ENUM ('a', 'b', 'c'); +DEBUG: Creating enum type + sql: CREATE TYPE "test_vote_type" AS ENUM ('yes', 'no', 'abstain'); +DEBUG: Creating table %s + table: test_all_kinds + sql: CREATE TABLE IF NOT EXISTS "test_all_kinds" ( "id" BIGINT NOT NULL, "ts" TIMESTAMPTZ GENERATED ALWAYS AS (nanos_to_timestamptz("ts_nanos")) STORED, "ts_nanos" BIGINT NOT NULL, @@ -33,9 +32,9 @@ CREATE TABLE IF NOT EXISTS "test_all_kinds" ( PRIMARY KEY ("id", "ts_nanos") ); GRANT SELECT ON TABLE "test_all_kinds" TO PUBLIC; - -Creating table test_singleton -CREATE TABLE IF NOT EXISTS "test_singleton" ( +DEBUG: Creating table %s + table: test_singleton + sql: CREATE TABLE IF NOT EXISTS "test_singleton" ( _id INTEGER NOT NULL CHECK (_id = 1), "foo" TEXT NOT NULL, "bar" INTEGER NULL, @@ -43,9 +42,9 @@ CREATE TABLE IF NOT EXISTS "test_singleton" ( PRIMARY KEY (_id) ); GRANT SELECT ON TABLE "test_singleton" TO PUBLIC; - -Creating table test_vote -CREATE TABLE IF NOT EXISTS "test_vote" ( +DEBUG: Creating table %s + table: test_vote + sql: CREATE TABLE IF NOT EXISTS "test_vote" ( "proposal" BIGINT NOT NULL, "address" TEXT NOT NULL, "vote" "test_vote_type" NOT NULL, @@ -53,4 +52,3 @@ CREATE TABLE IF NOT EXISTS "test_vote" ( PRIMARY KEY ("proposal", "address") ); GRANT SELECT ON TABLE "test_vote" TO PUBLIC; - diff --git a/indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt b/indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt index 0dbfbddb4e0e..0ec17ae1ea1d 100644 --- a/indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt +++ b/indexer/postgres/tests/testdata/init_schema_no_retain_delete.txt @@ -1,11 +1,10 @@ -Creating enum type -CREATE TYPE "test_my_enum" AS ENUM ('a', 'b', 'c'); - -Creating enum type -CREATE TYPE "test_vote_type" AS ENUM ('yes', 'no', 'abstain'); - -Creating table test_all_kinds -CREATE TABLE IF NOT EXISTS "test_all_kinds" ( +DEBUG: Creating enum type + sql: CREATE TYPE "test_my_enum" AS ENUM ('a', 'b', 'c'); +DEBUG: Creating enum type + sql: CREATE TYPE "test_vote_type" AS ENUM ('yes', 'no', 'abstain'); +DEBUG: Creating table %s + table: test_all_kinds + sql: CREATE TABLE IF NOT EXISTS "test_all_kinds" ( "id" BIGINT NOT NULL, "ts" TIMESTAMPTZ GENERATED ALWAYS AS (nanos_to_timestamptz("ts_nanos")) STORED, "ts_nanos" BIGINT NOT NULL, @@ -33,9 +32,9 @@ CREATE TABLE IF NOT EXISTS "test_all_kinds" ( PRIMARY KEY ("id", "ts_nanos") ); GRANT SELECT ON TABLE "test_all_kinds" TO PUBLIC; - -Creating table test_singleton -CREATE TABLE IF NOT EXISTS "test_singleton" ( +DEBUG: Creating table %s + table: test_singleton + sql: CREATE TABLE IF NOT EXISTS "test_singleton" ( _id INTEGER NOT NULL CHECK (_id = 1), "foo" TEXT NOT NULL, "bar" INTEGER NULL, @@ -43,13 +42,12 @@ CREATE TABLE IF NOT EXISTS "test_singleton" ( PRIMARY KEY (_id) ); GRANT SELECT ON TABLE "test_singleton" TO PUBLIC; - -Creating table test_vote -CREATE TABLE IF NOT EXISTS "test_vote" ( +DEBUG: Creating table %s + table: test_vote + sql: CREATE TABLE IF NOT EXISTS "test_vote" ( "proposal" BIGINT NOT NULL, "address" TEXT NOT NULL, "vote" "test_vote_type" NOT NULL, PRIMARY KEY ("proposal", "address") ); GRANT SELECT ON TABLE "test_vote" TO PUBLIC; -