feat: Optimize PG source_kind, relation deletion using indices - BED-8832 - #101
feat: Optimize PG source_kind, relation deletion using indices - BED-8832#101StephenHinck wants to merge 8 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds PostgreSQL server-side deletion by node or relationship kind, including cached kind-ID resolution, parameterized SQL generation, undefined-kind handling, and unit/manual integration tests for filtering, cascades, and no-op behavior. ChangesPostgreSQL Bulk Delete by Kind
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant PGDriver
participant KindCache
participant PostgreSQL
Caller->>PGDriver: Request deletion by kind
PGDriver->>KindCache: Resolve graph kinds to IDs
KindCache-->>PGDriver: Return IDs and undefined kinds
PGDriver->>PostgreSQL: Execute parameterized DELETE
PostgreSQL-->>PGDriver: Return result
PGDriver-->>Caller: Return success or error
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@drivers/pg/driver.go`:
- Around line 231-254: The delete builder in the `Delete` flow is too tolerant
when resolving `excludeAny`, which can turn a protected delete into an unguarded
`delete from node`. Update the logic around `resolveKindIDs` in
`drivers/pg/driver.go` so unresolved exclude kinds fail closed instead of being
silently dropped, and make the `predicates`/`arguments` construction in the
delete statement require valid `excludeIDs` before adding the `not (kind_ids
operator ...)` clause. Keep `includeAny` behavior unchanged, but ensure
`excludeAny` cannot widen the delete when `resolveKindIDs` returns an empty or
partial match.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0dd1938a-2de7-4984-b84d-79a28b13ad41
⛔ Files ignored due to path filters (1)
go.sumis excluded by!**/*.sum
📒 Files selected for processing (6)
drivers/pg/driver.godrivers/pg/query/sql/schema_up.sqlgo.modintegration/pgsql_delete_by_kind_test.gointegration/pgsql_delete_cascade_test.gointegration/pgsql_delete_relationships_by_kind_test.go
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
drivers/pg/driver.go (1)
190-241: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick winBuild-breaking syntax error:
WipeGraphnever closes, andresolveKindIDsis duplicated with conflicting signatures.Line 212's
})only closes theWriteTransactioncall;WipeGraphitself is left unclosed, so theresolveKindIDsdoc comment andfuncdeclaration at lines 213-216 land insideWipeGraph's body — Go does not allow named function declarations nested inside another function, which is exactly the syntax error the pipeline reports at line 216. Immediately after that, lines 217-220 duplicate the same doc comment and redeclareresolveKindIDsagain with a different signature (([]int16, error)at line 216 vs([]int16, graph.Kinds, error)at line 220). Every call site (DeleteNodesByKinds,DeleteRelationshipsByKinds) uses the 3-return-value form, so line 220 is the intended final signature and lines 213-216 are stray leftovers from an unresolved merge/diff.This won't compile as-is.
🐛 Proposed fix: close `WipeGraph` and drop the duplicate `resolveKindIDs` block
return nil }) +} -// resolveKindIDs maps kinds to their integer IDs, refreshing the schema cache once on a miss. Kinds that remain -// undefined after the refresh are tolerated and omitted from the result so that callers match no nodes for them -// rather than erroring. -func (s *Driver) resolveKindIDs(ctx context.Context, kinds graph.Kinds) ([]int16, error) { // resolveKindIDs maps kinds to their integer IDs, refreshing the schema cache once on a miss. It returns the resolved // IDs alongside any kinds that remain undefined after the refresh, so callers can decide whether an unresolved kind is // a tolerable no-op (include predicates) or must fail closed (exclude predicates). func (s *Driver) resolveKindIDs(ctx context.Context, kinds graph.Kinds) ([]int16, graph.Kinds, error) {Based on the static analysis hint flagging
216-216: syntax error: unexpected name context in argument list; possibly missing comma or ), which corroborates this exact defect.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@drivers/pg/driver.go` around lines 190 - 241, Close WipeGraph after the WriteTransaction call so resolveKindIDs is declared at file scope. Remove the stray duplicate resolveKindIDs declaration and its duplicate comment, retaining the three-return-value signature used by DeleteNodesByKinds and DeleteRelationshipsByKinds.Source: Linters/SAST tools
🧹 Nitpick comments (1)
drivers/pg/driver.go (1)
269-277: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDuplicated acquire/exec/error-wrap pattern across the two delete methods.
DeleteNodesByKindsandDeleteRelationshipsByKindsboth acquire a pooled connection, defer-release it, execute, and wrap the error with"%s: %w". Consider extracting a small helper (e.g.execDelete(ctx, statement, args...)) to avoid the duplication as more kind-based bulk-delete methods are added.Also applies to: 328-336
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@drivers/pg/driver.go` around lines 269 - 277, Extract the duplicated pool acquire, deferred release, execution, and error-wrapping logic from DeleteNodesByKinds and DeleteRelationshipsByKinds into a shared helper such as execDelete. Update both delete methods to delegate to that helper while preserving their existing statement, arguments, and error messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@integration/pgsql_delete_relationships_by_kind_test.go`:
- Around line 131-143: Update the “undefined and empty kinds are a safe no-op”
test to also call DeleteRelationshipsByKinds with a non-nil empty graph.Kinds{}
value, while retaining the existing nil and missing-kind cases and asserting no
error.
---
Outside diff comments:
In `@drivers/pg/driver.go`:
- Around line 190-241: Close WipeGraph after the WriteTransaction call so
resolveKindIDs is declared at file scope. Remove the stray duplicate
resolveKindIDs declaration and its duplicate comment, retaining the
three-return-value signature used by DeleteNodesByKinds and
DeleteRelationshipsByKinds.
---
Nitpick comments:
In `@drivers/pg/driver.go`:
- Around line 269-277: Extract the duplicated pool acquire, deferred release,
execution, and error-wrapping logic from DeleteNodesByKinds and
DeleteRelationshipsByKinds into a shared helper such as execDelete. Update both
delete methods to delegate to that helper while preserving their existing
statement, arguments, and error messages.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 37f36512-cb99-4af5-b181-66e25a7b617f
📒 Files selected for processing (4)
drivers/pg/driver.godrivers/pg/driver_test.gointegration/pgsql_delete_by_kind_test.gointegration/pgsql_delete_relationships_by_kind_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
- integration/pgsql_delete_by_kind_test.go
- drivers/pg/driver_test.go
|
@coderabbitai full review |
✅ Action performedFull review finished. |
Description
Introduces new, optional functions for deleting nodes and relationships by kind, enabling the use of indices for more performant bulk deletes. This primarily supports the various database management capabilities built into BloodHound, but may be used for other bulk delete operations as necessary.
Implemented in SpecterOps/BloodHound#2942
Resolves: BED-8832
Type of Change
Testing
make test_allwithCONNECTION_STRINGset)Screenshots (if appropriate):
Driver Impact
drivers/pg)drivers/neo4j)Checklist
go.mod/go.sumare up to date if dependencies changedSummary by CodeRabbit