feat(pgsql): add WhereGroup and a podman/docker hardening test

- PgSQLSelectQuery implements common.WhereGrouper so x-custom-sql-or
  is grouped with the client's own conditions on the pgx adapter too.
- Add a container test (opt-in via RESOLVESPEC_TEST_CONTAINERS=1) that
  starts PostgreSQL with podman or docker and checks the hardening
  against a real database: parenthesis escape, pg_sleep, catalog
  subquery, stacked statements, x-custom-sql-or grouping and the
  legacy behaviour when hardening is switched off.
This commit is contained in:
Hein
2026-10-01 14:41:46 +02:00
parent ca89cb8a73
commit f54b707040
5 changed files with 282 additions and 1 deletions
+26
View File
@@ -325,6 +325,32 @@ func (p *PgSQLSelectQuery) WhereOr(query string, args ...interface{}) common.Sel
return p
}
// WhereGroup wraps the conditions added by fn (Where = AND, WhereOr = OR) in one
// parenthesised group ANDed with the rest of the query. Inside the group the
// semantics match Bun: `w1 AND w2 OR o1 OR o2`.
func (p *PgSQLSelectQuery) WhereGroup(fn func(common.SelectQuery) common.SelectQuery) common.SelectQuery {
sub := &PgSQLSelectQuery{driverName: p.driverName, paramCounter: p.paramCounter, args: make([]interface{}, 0)}
res, ok := fn(sub).(*PgSQLSelectQuery)
if !ok {
res = sub
}
var group string
switch {
case len(res.whereClauses) > 0 && len(res.orClauses) > 0:
group = "(" + strings.Join(res.whereClauses, " AND ") + ") OR " + strings.Join(res.orClauses, " OR ")
case len(res.whereClauses) > 0:
group = strings.Join(res.whereClauses, " AND ")
case len(res.orClauses) > 0:
group = strings.Join(res.orClauses, " OR ")
default:
return p
}
p.whereClauses = append(p.whereClauses, "("+group+")")
p.args = append(p.args, res.args...)
p.paramCounter = res.paramCounter
return p
}
func (p *PgSQLSelectQuery) Join(query string, args ...interface{}) common.SelectQuery {
query = p.replacePlaceholders(query, len(args))
p.joins = append(p.joins, "JOIN "+query)