Files
de61635b81 refactor: move all packages under pkg/ for v5 (#559)
* refactor: move all packages under pkg/ for v5

Move all 13 top-level Go packages into pkg/ for a cleaner repository
structure. All internal import paths updated from
github.com/formancehq/go-libs/v5/<pkg> to
github.com/formancehq/go-libs/v5/pkg/<pkg>.

Also includes cleanup:
- Fix .golangci.yml stale v4 CircuitBreaker path
- Replace deprecated str.Contains with stdlib slices.Contains
- Update TODO(v4) markers to TODO
- Delete stale coverage.txt
- Fix pgtesting timeout not being propagated to docker pool
- Update docs/ARCHITECTURE.md to reflect new structure

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* chore: remove compatibility aliases, unused params, and stub files

- Remove unused type aliases (Authenticator, KeySet) from authnfx
- Remove unused `debug` parameter from S3ModuleFromFlags
- Delete comment-only stub files in messaging/publish/circuit/

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* chore: rename cli.go to flags.go for consistency

Standardize naming across all packages: cli.go -> flags.go
since these files all serve the same purpose (flag definitions).

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* chore: rename

* chore(deps): update all dependencies

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: resolve package name mismatches in generated mocks

Generated mock files had stale package names from before the pkg/ move,
causing import cycles and build failures with --build-tags it.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-03-20 09:17:12 +00:00

98 lines
1.8 KiB
Go

package explain
import (
"bytes"
"context"
"database/sql"
"fmt"
"strings"
"github.com/uptrace/bun"
)
type listener func(data string)
//nolint:unused
type explainHook struct {
listener listener
json bool
}
//nolint:unused
func (h *explainHook) AfterQuery(ctx context.Context, event *bun.QueryEvent) {}
//nolint:unused
func (h *explainHook) BeforeQuery(ctx context.Context, event *bun.QueryEvent) context.Context {
lowerQuery := strings.ToLower(event.Query)
if !strings.HasPrefix(lowerQuery, "select") && !strings.HasPrefix(lowerQuery, "with") {
return ctx
}
if err := event.DB.RunInTx(context.Background(), &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
query := "explain "
if h.json {
query += "(format json) "
} else {
query += "analyze verbose "
}
query += event.Query
rows, err := tx.Query(query)
if err != nil {
return err
}
defer func() {
_ = rows.Close()
}()
data := bytes.NewBufferString("")
for rows.Next() {
var line string
if err := rows.Scan(&line); err != nil {
return err
}
data.WriteString(line)
data.WriteString("\r\n")
}
if rows.Err() != nil {
return rows.Err()
}
h.listener(data.String())
return tx.Rollback()
}); err != nil {
// Nothing to do, let the original request fail
}
return ctx
}
func NewExplainHook(opts ...option) *explainHook {
ret := &explainHook{}
for _, opt := range append(defaultOptions, opts...) {
opt(ret)
}
return ret
}
type option func(hook *explainHook)
var defaultOptions = []option{
WithListener(func(data string) {
fmt.Println(data)
}),
}
var WithListener = func(w listener) option {
return func(hook *explainHook) {
hook.listener = w
}
}
var WithJSONFormat = func() option {
return func(hook *explainHook) {
hook.json = true
}
}