diff --git a/.all-contributorsrc b/.all-contributorsrc index d6101a9da1..dee87b2a16 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -240,6 +240,15 @@ "contributions": [ "design" ] + }, + { + "login": "dstotijn", + "name": "David Stotijn", + "avatar_url": "https://avatars.githubusercontent.com/u/983924?v=4", + "profile": "https://v0x.nl", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/.goreleaser.yml b/.goreleaser.yml index 54568e9798..5d2ada11ac 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -6,7 +6,7 @@ monorepo: builds: - main: ./cmd/flipt/. ldflags: - - -s -w -X main.version={{ .Version }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X main.analyticsKey={{ .Env.ANALYTICS_KEY }} + - -s -w -X main.version={{ .PrefixedTag }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X main.analyticsKey={{ .Env.ANALYTICS_KEY }} - -linkmode external -extldflags -static goos: - linux diff --git a/CHANGELOG.md b/CHANGELOG.md index cd57b4c59f..42fba1e7cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,24 @@ This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v1.23.1](https://github.com/flipt-io/flipt/releases/tag/v1.23.1) - 2023-06-15 + +### Added + +- Ability to configure use of prepared statements (for enabling PGBouncer) (#1750) +- `telemetry`: track storage type and experimental features (#1745) + +### Changed + +- Dependency updates + +### Fixed + +- `storage/sql`: set binary_parameters=yes for lib/pq when prepared statements disabled (#1753) +- UI: input bg / text in darkmode (#1752) +- count rules was not taking flagKey into account (#1738) +- tag prefix for build info/release links (#1757) + ## [v1.23.0](https://github.com/flipt-io/flipt/releases/tag/v1.23.0) - 2023-06-12 ### Added diff --git a/README.md b/README.md index 3116c533f9..52851f55a0 100644 --- a/README.md +++ b/README.md @@ -316,6 +316,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Darin McLain
Darin McLain

💻 Adam Weiss
Adam Weiss

💡 Yuval Goihberg
Yuval Goihberg

🎨 + David Stotijn
David Stotijn

💻 diff --git a/cmd/flipt/server.go b/cmd/flipt/server.go index e6a15d804f..c20f0ae93b 100644 --- a/cmd/flipt/server.go +++ b/cmd/flipt/server.go @@ -25,15 +25,19 @@ func fliptServer(logger *zap.Logger, cfg *config.Config) (*server.Server, func() return nil, nil, fmt.Errorf("opening db: %w", err) } + logger.Debug("constructing builder", zap.Bool("prepared_statements", cfg.Database.PreparedStatementsEnabled)) + + builder := sql.BuilderFor(db, driver, cfg.Database.PreparedStatementsEnabled) + var store storage.Store switch driver { case sql.SQLite: - store = sqlite.NewStore(db, logger) + store = sqlite.NewStore(db, builder, logger) case sql.Postgres, sql.CockroachDB: - store = postgres.NewStore(db, logger) + store = postgres.NewStore(db, builder, logger) case sql.MySQL: - store = mysql.NewStore(db, logger) + store = mysql.NewStore(db, builder, logger) } return server.New(logger, store), func() { _ = db.Close() }, nil diff --git a/config/flipt.schema.cue b/config/flipt.schema.cue index 8e5be8dea6..f0da6d312c 100644 --- a/config/flipt.schema.cue +++ b/config/flipt.schema.cue @@ -101,6 +101,7 @@ import "strings" max_idle_conn?: int | *2 max_open_conn?: int conn_max_lifetime?: int + prepared_statements_enabled?: boolean | *true } _#lower: ["debug", "error", "fatal", "info", "panic", "trace", "warn"] diff --git a/config/flipt.schema.json b/config/flipt.schema.json index b23c33e189..f3cde86083 100644 --- a/config/flipt.schema.json +++ b/config/flipt.schema.json @@ -325,6 +325,9 @@ }, "conn_max_lifetime": { "type": "integer" + }, + "prepared_statements_enabled": { + "type": "boolean" } }, "required": [], diff --git a/internal/cmd/auth.go b/internal/cmd/auth.go index 7f933fb13f..bc6d600b6c 100644 --- a/internal/cmd/auth.go +++ b/internal/cmd/auth.go @@ -20,7 +20,6 @@ import ( "go.flipt.io/flipt/internal/storage/auth/memory" authsql "go.flipt.io/flipt/internal/storage/auth/sql" oplocksql "go.flipt.io/flipt/internal/storage/oplock/sql" - fliptsql "go.flipt.io/flipt/internal/storage/sql" rpcauth "go.flipt.io/flipt/rpc/flipt/auth" "go.uber.org/zap" "google.golang.org/grpc" @@ -43,18 +42,17 @@ func authenticationGRPC( }, nil, func(ctx context.Context) error { return nil }, nil } - db, driver, shutdown, err := getDB(ctx, logger, cfg, forceMigrate) + _, builder, driver, shutdown, err := getDB(ctx, logger, cfg, forceMigrate) if err != nil { return nil, nil, nil, err } var ( - authCfg = cfg.Authentication - sqlBuilder = fliptsql.BuilderFor(db, driver) - store = authsql.NewStore(driver, sqlBuilder, logger) - oplock = oplocksql.New(logger, driver, sqlBuilder) - public = public.NewServer(logger, authCfg) - register = grpcRegisterers{ + authCfg = cfg.Authentication + store = authsql.NewStore(driver, builder, logger) + oplock = oplocksql.New(logger, driver, builder) + public = public.NewServer(logger, authCfg) + register = grpcRegisterers{ public, auth.NewServer(logger, store, auth.WithAuditLoggingEnabled(cfg.Audit.Enabled())), } diff --git a/internal/cmd/grpc.go b/internal/cmd/grpc.go index dc214ef535..9f6598fbeb 100644 --- a/internal/cmd/grpc.go +++ b/internal/cmd/grpc.go @@ -10,6 +10,7 @@ import ( "sync" "time" + sq "github.com/Masterminds/squirrel" "go.flipt.io/flipt/internal/config" "go.flipt.io/flipt/internal/containers" "go.flipt.io/flipt/internal/info" @@ -116,7 +117,7 @@ func NewGRPCServer( switch cfg.Storage.Type { case "", config.DatabaseStorageType: - db, driver, shutdown, err := getDB(ctx, logger, cfg, forceMigrate) + db, builder, driver, shutdown, err := getDB(ctx, logger, cfg, forceMigrate) if err != nil { return nil, err } @@ -125,11 +126,11 @@ func NewGRPCServer( switch driver { case fliptsql.SQLite: - store = sqlite.NewStore(db, logger) + store = sqlite.NewStore(db, builder, logger) case fliptsql.Postgres, fliptsql.CockroachDB: - store = postgres.NewStore(db, logger) + store = postgres.NewStore(db, builder, logger) case fliptsql.MySQL: - store = mysql.NewStore(db, logger) + store = mysql.NewStore(db, builder, logger) default: return nil, fmt.Errorf("unsupported driver: %s", driver) } @@ -390,14 +391,15 @@ func (s *GRPCServer) onShutdown(fn errFunc) { } var ( - once sync.Once - db *sql.DB - driver fliptsql.Driver - dbFunc errFunc = func(context.Context) error { return nil } - dbErr error + once sync.Once + db *sql.DB + builder sq.StatementBuilderType + driver fliptsql.Driver + dbFunc errFunc = func(context.Context) error { return nil } + dbErr error ) -func getDB(ctx context.Context, logger *zap.Logger, cfg *config.Config, forceMigrate bool) (*sql.DB, fliptsql.Driver, errFunc, error) { +func getDB(ctx context.Context, logger *zap.Logger, cfg *config.Config, forceMigrate bool) (*sql.DB, sq.StatementBuilderType, fliptsql.Driver, errFunc, error) { once.Do(func() { migrator, err := fliptsql.NewMigrator(*cfg, logger) if err != nil { @@ -419,6 +421,10 @@ func getDB(ctx context.Context, logger *zap.Logger, cfg *config.Config, forceMig return } + logger.Debug("constructing builder", zap.Bool("prepared_statements", cfg.Database.PreparedStatementsEnabled)) + + builder = fliptsql.BuilderFor(db, driver, cfg.Database.PreparedStatementsEnabled) + dbFunc = func(context.Context) error { return db.Close() } @@ -432,5 +438,5 @@ func getDB(ctx context.Context, logger *zap.Logger, cfg *config.Config, forceMig } }) - return db, driver, dbFunc, dbErr + return db, builder, driver, dbFunc, dbErr } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 0a56e62a79..9bc1908d7d 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -261,8 +261,9 @@ func defaultConfig() *Config { }, Database: DatabaseConfig{ - URL: "file:/var/opt/flipt/flipt.db", - MaxIdleConn: 2, + URL: "file:/var/opt/flipt/flipt.db", + MaxIdleConn: 2, + PreparedStatementsEnabled: true, }, Meta: MetaConfig{ @@ -419,13 +420,14 @@ func TestLoad(t *testing.T) { expected: func() *Config { cfg := defaultConfig() cfg.Database = DatabaseConfig{ - Protocol: DatabaseMySQL, - Host: "localhost", - Port: 3306, - User: "flipt", - Password: "s3cr3t!", - Name: "flipt", - MaxIdleConn: 2, + Protocol: DatabaseMySQL, + Host: "localhost", + Port: 3306, + User: "flipt", + Password: "s3cr3t!", + Name: "flipt", + MaxIdleConn: 2, + PreparedStatementsEnabled: true, } return cfg }, @@ -591,10 +593,11 @@ func TestLoad(t *testing.T) { Type: StorageType("database"), } cfg.Database = DatabaseConfig{ - URL: "postgres://postgres@localhost:5432/flipt?sslmode=disable", - MaxIdleConn: 10, - MaxOpenConn: 50, - ConnMaxLifetime: 30 * time.Minute, + URL: "postgres://postgres@localhost:5432/flipt?sslmode=disable", + MaxIdleConn: 10, + MaxOpenConn: 50, + ConnMaxLifetime: 30 * time.Minute, + PreparedStatementsEnabled: true, } cfg.Meta = MetaConfig{ CheckForUpdates: false, diff --git a/internal/config/database.go b/internal/config/database.go index fdcb59b61b..db44603967 100644 --- a/internal/config/database.go +++ b/internal/config/database.go @@ -27,16 +27,17 @@ const ( // // Flipt currently supports SQLite, Postgres and MySQL backends. type DatabaseConfig struct { - URL string `json:"url,omitempty" mapstructure:"url"` - MaxIdleConn int `json:"maxIdleConn,omitempty" mapstructure:"max_idle_conn"` - MaxOpenConn int `json:"maxOpenConn,omitempty" mapstructure:"max_open_conn"` - ConnMaxLifetime time.Duration `json:"connMaxLifetime,omitempty" mapstructure:"conn_max_lifetime"` - Name string `json:"name,omitempty" mapstructure:"name"` - User string `json:"user,omitempty" mapstructure:"user"` - Password string `json:"password,omitempty" mapstructure:"password"` - Host string `json:"host,omitempty" mapstructure:"host"` - Port int `json:"port,omitempty" mapstructure:"port"` - Protocol DatabaseProtocol `json:"protocol,omitempty" mapstructure:"protocol"` + URL string `json:"url,omitempty" mapstructure:"url"` + MaxIdleConn int `json:"maxIdleConn,omitempty" mapstructure:"max_idle_conn"` + MaxOpenConn int `json:"maxOpenConn,omitempty" mapstructure:"max_open_conn"` + ConnMaxLifetime time.Duration `json:"connMaxLifetime,omitempty" mapstructure:"conn_max_lifetime"` + Name string `json:"name,omitempty" mapstructure:"name"` + User string `json:"user,omitempty" mapstructure:"user"` + Password string `json:"password,omitempty" mapstructure:"password"` + Host string `json:"host,omitempty" mapstructure:"host"` + Port int `json:"port,omitempty" mapstructure:"port"` + Protocol DatabaseProtocol `json:"protocol,omitempty" mapstructure:"protocol"` + PreparedStatementsEnabled bool `json:"preparedStatementsEnabled,omitempty" mapstructure:"prepared_statements_enabled"` } func (c *DatabaseConfig) setDefaults(v *viper.Viper) { @@ -54,6 +55,8 @@ func (c *DatabaseConfig) setDefaults(v *viper.Viper) { if setDefaultURL { v.SetDefault("db.url", "file:/var/opt/flipt/flipt.db") } + + v.SetDefault("db.prepared_statements_enabled", true) } func (c *DatabaseConfig) deprecations(v *viper.Viper) []deprecation { diff --git a/internal/storage/auth/sql/store_test.go b/internal/storage/auth/sql/store_test.go index a1b3eddcdd..0faf8a71da 100644 --- a/internal/storage/auth/sql/store_test.go +++ b/internal/storage/auth/sql/store_test.go @@ -359,7 +359,7 @@ func newTestStore(t *testing.T, seed ...authentication) func(...Option) *Store { storeFn = func(opts ...Option) *Store { return NewStore( db.Driver, - storagesql.BuilderFor(db.DB, db.Driver), + storagesql.BuilderFor(db.DB, db.Driver, true), logger, opts..., ) diff --git a/internal/storage/oplock/sql/sql_test.go b/internal/storage/oplock/sql/sql_test.go index 3ed7defe02..cf1d24bd0e 100644 --- a/internal/storage/oplock/sql/sql_test.go +++ b/internal/storage/oplock/sql/sql_test.go @@ -21,6 +21,6 @@ func Test_Harness(t *testing.T) { New( logger, db.Driver, - storagesql.BuilderFor(db.DB, db.Driver), + storagesql.BuilderFor(db.DB, db.Driver, true), )) } diff --git a/internal/storage/sql/db.go b/internal/storage/sql/db.go index a716e8a253..72c63f961e 100644 --- a/internal/storage/sql/db.go +++ b/internal/storage/sql/db.go @@ -39,8 +39,13 @@ func Open(cfg config.Config, opts ...Option) (*sql.DB, Driver, error) { // BuilderFor returns a squirrel statement builder which decorates // the provided sql.DB configured for the provided driver. -func BuilderFor(db *sql.DB, driver Driver) sq.StatementBuilderType { - builder := sq.StatementBuilder.RunWith(sq.NewStmtCacher(db)) +func BuilderFor(db *sql.DB, driver Driver, preparedStatementsEnabled bool) sq.StatementBuilderType { + var brdb sq.BaseRunner = db + if preparedStatementsEnabled { + brdb = sq.NewStmtCacher(db) + } + + builder := sq.StatementBuilder.RunWith(brdb) if driver == Postgres || driver == CockroachDB { builder = builder.PlaceholderFormat(sq.Dollar) } @@ -203,36 +208,32 @@ func parse(cfg config.Config, opts Options) (Driver, *dburl.URL, error) { return 0, nil, fmt.Errorf("unknown database driver for: %q", url.Driver) } + v := url.Query() switch driver { case Postgres, CockroachDB: if opts.sslDisabled { - v := url.Query() v.Set("sslmode", "disable") - url.RawQuery = v.Encode() - // we need to re-parse since we modified the query params - url, err = dburl.Parse(url.URL.String()) + } + + // see: https://github.com/lib/pq/issues/389 + if !cfg.Database.PreparedStatementsEnabled { + v.Set("binary_parameters", "yes") } case MySQL: - v := url.Query() v.Set("multiStatements", "true") v.Set("parseTime", "true") if !opts.migrate { v.Set("sql_mode", "ANSI") } - url.RawQuery = v.Encode() - // we need to re-parse since we modified the query params - url, err = dburl.Parse(url.URL.String()) - case SQLite: - v := url.Query() v.Set("cache", "shared") v.Set("mode", "rwc") v.Set("_fk", "true") - url.RawQuery = v.Encode() - - // we need to re-parse since we modified the query params - url, err = dburl.Parse(url.URL.String()) } + url.RawQuery = v.Encode() + // we need to re-parse since we modified the query params + url, err = dburl.Parse(url.URL.String()) + return driver, url, err } diff --git a/internal/storage/sql/db_internal_test.go b/internal/storage/sql/db_internal_test.go index 037754b981..66fdcf1f2c 100644 --- a/internal/storage/sql/db_internal_test.go +++ b/internal/storage/sql/db_internal_test.go @@ -34,13 +34,22 @@ func TestParse(t *testing.T) { driver: SQLite, dsn: "flipt.db?_fk=true&cache=shared&mode=rwc", }, + { + name: "postgres url prepared statements enabled", + cfg: config.DatabaseConfig{ + URL: "postgres://postgres@localhost:5432/flipt?sslmode=disable", + PreparedStatementsEnabled: true, + }, + driver: Postgres, + dsn: "dbname=flipt host=localhost port=5432 sslmode=disable user=postgres", + }, { name: "postgres url", cfg: config.DatabaseConfig{ URL: "postgres://postgres@localhost:5432/flipt?sslmode=disable", }, driver: Postgres, - dsn: "dbname=flipt host=localhost port=5432 sslmode=disable user=postgres", + dsn: "binary_parameters=yes dbname=flipt host=localhost port=5432 sslmode=disable user=postgres", }, { name: "postgres no disable sslmode", @@ -48,7 +57,7 @@ func TestParse(t *testing.T) { URL: "postgres://postgres@localhost:5432/flipt", }, driver: Postgres, - dsn: "dbname=flipt host=localhost port=5432 user=postgres", + dsn: "binary_parameters=yes dbname=flipt host=localhost port=5432 user=postgres", }, { name: "postgres disable sslmode via opts", @@ -61,7 +70,7 @@ func TestParse(t *testing.T) { }, options: []Option{WithSSLDisabled}, driver: Postgres, - dsn: "dbname=flipt host=localhost port=5432 sslmode=disable user=postgres", + dsn: "binary_parameters=yes dbname=flipt host=localhost port=5432 sslmode=disable user=postgres", }, { name: "postgres no port", @@ -72,7 +81,7 @@ func TestParse(t *testing.T) { User: "postgres", }, driver: Postgres, - dsn: "dbname=flipt host=localhost user=postgres", + dsn: "binary_parameters=yes dbname=flipt host=localhost user=postgres", }, { name: "postgres no password", @@ -84,7 +93,7 @@ func TestParse(t *testing.T) { User: "postgres", }, driver: Postgres, - dsn: "dbname=flipt host=localhost port=5432 user=postgres", + dsn: "binary_parameters=yes dbname=flipt host=localhost port=5432 user=postgres", }, { name: "postgres with password", @@ -97,7 +106,7 @@ func TestParse(t *testing.T) { Password: "foo", }, driver: Postgres, - dsn: "dbname=flipt host=localhost password=foo port=5432 user=postgres", + dsn: "binary_parameters=yes dbname=flipt host=localhost password=foo port=5432 user=postgres", }, { name: "mysql url", @@ -159,13 +168,22 @@ func TestParse(t *testing.T) { driver: MySQL, dsn: "mysql:foo@tcp(localhost:3306)/flipt?multiStatements=true&parseTime=true&sql_mode=ANSI", }, + { + name: "cockroachdb url prepared statements enabled", + cfg: config.DatabaseConfig{ + URL: "cockroachdb://cockroachdb@localhost:26257/flipt?sslmode=disable", + PreparedStatementsEnabled: true, + }, + driver: CockroachDB, + dsn: "postgres://cockroachdb@localhost:26257/flipt?sslmode=disable", + }, { name: "cockroachdb url", cfg: config.DatabaseConfig{ URL: "cockroachdb://cockroachdb@localhost:26257/flipt?sslmode=disable", }, driver: CockroachDB, - dsn: "postgres://cockroachdb@localhost:26257/flipt?sslmode=disable", + dsn: "postgres://cockroachdb@localhost:26257/flipt?binary_parameters=yes&sslmode=disable", }, { name: "cockroachdb url alternative (cockroach://", @@ -173,7 +191,7 @@ func TestParse(t *testing.T) { URL: "cockroach://cockroachdb@localhost:26257/flipt?sslmode=disable", }, driver: CockroachDB, - dsn: "postgres://cockroachdb@localhost:26257/flipt?sslmode=disable", + dsn: "postgres://cockroachdb@localhost:26257/flipt?binary_parameters=yes&sslmode=disable", }, { name: "cockroachdb url alternative (crdb://", @@ -181,7 +199,7 @@ func TestParse(t *testing.T) { URL: "crdb://cockroachdb@localhost:26257/flipt?sslmode=disable", }, driver: CockroachDB, - dsn: "postgres://cockroachdb@localhost:26257/flipt?sslmode=disable", + dsn: "postgres://cockroachdb@localhost:26257/flipt?binary_parameters=yes&sslmode=disable", }, { name: "cockroachdb default disable sslmode", @@ -191,7 +209,7 @@ func TestParse(t *testing.T) { URL: "cockroachdb://cockroachdb@localhost:26257/flipt", }, driver: CockroachDB, - dsn: "postgres://cockroachdb@localhost:26257/flipt?sslmode=disable", + dsn: "postgres://cockroachdb@localhost:26257/flipt?binary_parameters=yes&sslmode=disable", }, { name: "cockroachdb disable sslmode via opts", @@ -206,7 +224,7 @@ func TestParse(t *testing.T) { WithSSLDisabled, }, driver: CockroachDB, - dsn: "postgres://cockroachdb@localhost:26257/flipt?sslmode=disable", + dsn: "postgres://cockroachdb@localhost:26257/flipt?binary_parameters=yes&sslmode=disable", }, { name: "cockroachdb no port", @@ -217,7 +235,7 @@ func TestParse(t *testing.T) { User: "cockroachdb", }, driver: CockroachDB, - dsn: "postgres://cockroachdb@localhost:26257/flipt?sslmode=disable", + dsn: "postgres://cockroachdb@localhost:26257/flipt?binary_parameters=yes&sslmode=disable", }, { name: "cockroachdb no password", @@ -229,7 +247,7 @@ func TestParse(t *testing.T) { User: "cockroachdb", }, driver: CockroachDB, - dsn: "postgres://cockroachdb@localhost:26257/flipt?sslmode=disable", + dsn: "postgres://cockroachdb@localhost:26257/flipt?binary_parameters=yes&sslmode=disable", }, { name: "cockroachdb with password", @@ -242,7 +260,7 @@ func TestParse(t *testing.T) { Password: "foo", }, driver: CockroachDB, - dsn: "postgres://cockroachdb:foo@localhost:26257/flipt?sslmode=disable", + dsn: "postgres://cockroachdb:foo@localhost:26257/flipt?binary_parameters=yes&sslmode=disable", }, { name: "invalid url", diff --git a/internal/storage/sql/db_test.go b/internal/storage/sql/db_test.go index 943be09786..84c8e0eea6 100644 --- a/internal/storage/sql/db_test.go +++ b/internal/storage/sql/db_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + sq "github.com/Masterminds/squirrel" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -134,15 +135,17 @@ func (s *DBTestSuite) SetupSuite() { s.db = db + builder := sq.StatementBuilder.RunWith(sq.NewStmtCacher(db.DB)) + var store storage.Store switch db.Driver { case fliptsql.SQLite: - store = sqlite.NewStore(db.DB, logger) + store = sqlite.NewStore(db.DB, builder, logger) case fliptsql.Postgres, fliptsql.CockroachDB: - store = postgres.NewStore(db.DB, logger) + store = postgres.NewStore(db.DB, builder, logger) case fliptsql.MySQL: - store = mysql.NewStore(db.DB, logger) + store = mysql.NewStore(db.DB, builder, logger) } namespace := randomString(6) diff --git a/internal/storage/sql/mysql/mysql.go b/internal/storage/sql/mysql/mysql.go index bce01fb581..a99d010920 100644 --- a/internal/storage/sql/mysql/mysql.go +++ b/internal/storage/sql/mysql/mysql.go @@ -22,9 +22,7 @@ const ( var _ storage.Store = &Store{} -func NewStore(db *sql.DB, logger *zap.Logger) *Store { - builder := sq.StatementBuilder.RunWith(sq.NewStmtCacher(db)) - +func NewStore(db *sql.DB, builder sq.StatementBuilderType, logger *zap.Logger) *Store { return &Store{ Store: common.NewStore(db, builder, logger), } diff --git a/internal/storage/sql/postgres/postgres.go b/internal/storage/sql/postgres/postgres.go index c2a0b28cfd..0d856fc29e 100644 --- a/internal/storage/sql/postgres/postgres.go +++ b/internal/storage/sql/postgres/postgres.go @@ -22,11 +22,9 @@ const ( var _ storage.Store = &Store{} -func NewStore(db *sql.DB, logger *zap.Logger) *Store { - builder := sq.StatementBuilder.PlaceholderFormat(sq.Dollar).RunWith(sq.NewStmtCacher(db)) - +func NewStore(db *sql.DB, builder sq.StatementBuilderType, logger *zap.Logger) *Store { return &Store{ - Store: common.NewStore(db, builder, logger), + Store: common.NewStore(db, builder.PlaceholderFormat(sq.Dollar), logger), } } diff --git a/internal/storage/sql/sqlite/sqlite.go b/internal/storage/sql/sqlite/sqlite.go index ce27262608..79f6c10492 100644 --- a/internal/storage/sql/sqlite/sqlite.go +++ b/internal/storage/sql/sqlite/sqlite.go @@ -18,9 +18,7 @@ import ( var _ storage.Store = &Store{} // NewStore creates a new sqlite.Store -func NewStore(db *sql.DB, logger *zap.Logger) *Store { - builder := sq.StatementBuilder.RunWith(sq.NewStmtCacher(db)) - +func NewStore(db *sql.DB, builder sq.StatementBuilderType, logger *zap.Logger) *Store { return &Store{ Store: common.NewStore(db, builder, logger), } diff --git a/ui/package-lock.json b/ui/package-lock.json index d6133e6356..e3dc78db22 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -22,7 +22,7 @@ "buffer": "^6.0.3", "date-fns": "^2.30.0", "dotenv": "^16.1.4", - "formik": "^2.4.1", + "formik": "^2.4.2", "highlight.js": "^11.8.0", "lodash": "^4.17.21", "moment": "^2.29.4", @@ -31,7 +31,7 @@ "react-dom": "^18.2.0", "react-helmet": "^6.1.0", "react-redux": "^8.0.7", - "react-router-dom": "^6.12.1", + "react-router-dom": "^6.13.0", "swr": "^2.1.5", "uuid": "^9.0.0", "yup": "^0.32.11" @@ -7030,9 +7030,9 @@ } }, "node_modules/formik": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.1.tgz", - "integrity": "sha512-ajOB9EmFhXb4PACTlaooVEn7PLtLtBJEZ8fPs+wFZjL5KSGwgAoU+n9DHN8JcqNKcXkloEYYtn1lxrLav18ecQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.2.tgz", + "integrity": "sha512-C6nx0hifW2uENP3M6HpPmnAE6HFWCcd8/sqBZEOHZY6lpHJ5qehsfAy43ktpFLEmkBmhiZDei726utcUB9leqg==", "funding": [ { "type": "individual", @@ -7046,17 +7046,12 @@ "lodash-es": "^4.17.21", "react-fast-compare": "^2.0.1", "tiny-warning": "^1.0.2", - "tslib": "^1.10.0" + "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, - "node_modules/formik/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -10899,9 +10894,9 @@ } }, "node_modules/react-router": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.12.1.tgz", - "integrity": "sha512-evd/GrKJOeOypD0JB9e1r7pQh2gWCsTbUfq059Wm1AFT/K2MNZuDo19lFtAgIhlBrp0MmpgpqtvZC7LPAs7vSw==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.13.0.tgz", + "integrity": "sha512-Si6KnfEnJw7gUQkNa70dlpI1bul46FuSxX5t5WwlUBxE25DAz2BjVkwaK8Y2s242bQrZPXCpmwLPtIO5pv4tXg==", "dependencies": { "@remix-run/router": "1.6.3" }, @@ -10913,12 +10908,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.12.1.tgz", - "integrity": "sha512-POIZN9UDKWwEDga054LvYr2KnK8V+0HR4Ny4Bwv8V7/FZCPxJgsCjYxXGxqxzHs7VBxMKZfgvtKhafuJkJSPGA==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.13.0.tgz", + "integrity": "sha512-6Nqoqd7fgwxxVGdbiMHTpDHCYPq62d7Wk1Of7B82vH7ZPwwsRaIa22zRZKPPg413R5REVNiyuQPKDG1bubcOFA==", "dependencies": { "@remix-run/router": "1.6.3", - "react-router": "6.12.1" + "react-router": "6.13.0" }, "engines": { "node": ">=14" @@ -17260,9 +17255,9 @@ } }, "formik": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.1.tgz", - "integrity": "sha512-ajOB9EmFhXb4PACTlaooVEn7PLtLtBJEZ8fPs+wFZjL5KSGwgAoU+n9DHN8JcqNKcXkloEYYtn1lxrLav18ecQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.2.tgz", + "integrity": "sha512-C6nx0hifW2uENP3M6HpPmnAE6HFWCcd8/sqBZEOHZY6lpHJ5qehsfAy43ktpFLEmkBmhiZDei726utcUB9leqg==", "requires": { "deepmerge": "^2.1.1", "hoist-non-react-statics": "^3.3.0", @@ -17270,14 +17265,7 @@ "lodash-es": "^4.17.21", "react-fast-compare": "^2.0.1", "tiny-warning": "^1.0.2", - "tslib": "^1.10.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } + "tslib": "^2.0.0" } }, "fraction.js": { @@ -19949,20 +19937,20 @@ "dev": true }, "react-router": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.12.1.tgz", - "integrity": "sha512-evd/GrKJOeOypD0JB9e1r7pQh2gWCsTbUfq059Wm1AFT/K2MNZuDo19lFtAgIhlBrp0MmpgpqtvZC7LPAs7vSw==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.13.0.tgz", + "integrity": "sha512-Si6KnfEnJw7gUQkNa70dlpI1bul46FuSxX5t5WwlUBxE25DAz2BjVkwaK8Y2s242bQrZPXCpmwLPtIO5pv4tXg==", "requires": { "@remix-run/router": "1.6.3" } }, "react-router-dom": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.12.1.tgz", - "integrity": "sha512-POIZN9UDKWwEDga054LvYr2KnK8V+0HR4Ny4Bwv8V7/FZCPxJgsCjYxXGxqxzHs7VBxMKZfgvtKhafuJkJSPGA==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.13.0.tgz", + "integrity": "sha512-6Nqoqd7fgwxxVGdbiMHTpDHCYPq62d7Wk1Of7B82vH7ZPwwsRaIa22zRZKPPg413R5REVNiyuQPKDG1bubcOFA==", "requires": { "@remix-run/router": "1.6.3", - "react-router": "6.12.1" + "react-router": "6.13.0" } }, "react-side-effect": { diff --git a/ui/package.json b/ui/package.json index 39be78d56d..dc049188cb 100644 --- a/ui/package.json +++ b/ui/package.json @@ -26,7 +26,7 @@ "buffer": "^6.0.3", "date-fns": "^2.30.0", "dotenv": "^16.1.4", - "formik": "^2.4.1", + "formik": "^2.4.2", "highlight.js": "^11.8.0", "lodash": "^4.17.21", "moment": "^2.29.4", @@ -35,7 +35,7 @@ "react-dom": "^18.2.0", "react-helmet": "^6.1.0", "react-redux": "^8.0.7", - "react-router-dom": "^6.12.1", + "react-router-dom": "^6.13.0", "swr": "^2.1.5", "uuid": "^9.0.0", "yup": "^0.32.11" diff --git a/ui/src/components/Footer.tsx b/ui/src/components/Footer.tsx index 428cc78469..391c30b408 100644 --- a/ui/src/components/Footer.tsx +++ b/ui/src/components/Footer.tsx @@ -13,7 +13,7 @@ export default function Footer() { const ref = () => { if (info?.isRelease && info?.version) { - return `v${info.version}`; + return info.version; } if (info?.commit) { return info.commit.substring(0, 7);