Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@zinic
Copy link
Contributor

@zinic zinic commented Jun 27, 2025

Summary by CodeRabbit

  • New Features

    • Added comprehensive PostgreSQL v2 driver supporting Cypher queries, node/edge creation, graph schema management, partitioned tables, and traversal utilities.
    • Introduced Neo4j schema manager with transactional schema assertion and index/constraint lifecycle management.
    • Added CREATE clause support and parameterized queries in the query builder.
    • Implemented new composite types and mapping utilities for nodes, edges, and paths.
    • Enhanced driver interfaces with graph context management, schema assertions, and error result handling.
    • Added PostgreSQL schema manager for kinds and graphs with concurrency-safe caching and assertion.
    • Embedded SQL files for schema creation, teardown, and metadata queries.
  • Improvements

    • Refined visitor pattern interfaces for Cypher syntax traversal with expanded handler capabilities.
    • Streamlined value mapping and result scanning by replacing deprecated methods.
    • Improved query identifier extraction, pattern preparation, and parameter handling with structured tracking.
    • Modularized query building with distinct handling for CREATE, UPDATE, DELETE, and RETURN clauses.
    • Enhanced error handling and simplified variable type assertions in query visitors.
  • Bug Fixes

    • Corrected session option constants and improved session access mode handling.
    • Fixed mapping and type casting logic for composite graph types.
  • Documentation

    • Added and updated test cases reflecting new features and interface changes.
    • Embedded and managed SQL scripts for schema and graph metadata operations.
  • Chores

    • Added utility and placeholder files for future extensions.
    • Updated internal type handling and refactored code for clarity and maintainability.

@coderabbitai
Copy link

coderabbitai bot commented Jun 27, 2025

Walkthrough

This update introduces a comprehensive PostgreSQL v2 driver with schema management, query building, and graph data support. It adds transactional schema assertion, partitioned graph tables, composite type mapping, and Cypher-to-SQL translation. Neo4j driver enhancements include schema assertion and node creation. The visitor pattern is refactored, and value mapping APIs are streamlined.

Changes

File(s) / Group Change Summary
cypher/models/cypher/model.go Struct field types narrowed from interface to concrete types; new constructor for projection; generalized remove property.
cypher/models/pgsql/test/testcase.go, cypher/models/pgsql/translate/constraints.go, cypher/models/pgsql/translate/expression.go, cypher/models/pgsql/translate/function.go, cypher/models/walk/walk_test.go, query/builder.go, query/neo4j/neo4j.go Visitor function parameter updated from CancelableErrorHandler to VisitorHandler.
cypher/models/pgsql/translate/model.go Simplified variable extraction logic, assuming always *cypher.Variable.
cypher/models/walk/walk.go Refactored visitor pattern: renamed/expanded handler interface, added consumption tracking, updated related structs and types.
drivers/neo4j/result_internal_test.go, graph/query.go, ops/ops.go Replaced TryMap with Map for value mapping in tests and utility functions.
drivers/neo4j/v2/database.go Removed batch/write fields, added schema manager, new schema assertion method, fixed session option constant.
drivers/neo4j/v2/driver.go Refactored query execution: removed First, renamed Execute to CypherQuery, added WithGraph, CreateNode, Raw, updated error handling.
drivers/neo4j/v2/schema.go New: Implements Neo4j schema manager for indexes/constraints, transactional schema assertion, schema comparison, and modification.
drivers/pg/query/sql/schema_up.sql Added debug logging to path harness loop.
drivers/pg/v2/database.go New: PostgreSQL v2 database abstraction with session, transaction, schema assertion, and pool management.
drivers/pg/v2/driver.go New: PostgreSQL v2 driver: Cypher-to-SQL translation, query execution, result mapping, node creation, and graph context.
drivers/pg/v2/manager.go New: Schema manager for kind/graph mapping, concurrency-safe, schema assertion, and in-memory caching.
drivers/pg/v2/mapper.go New: Kind/value mapping logic for mapping database results to graph entities.
drivers/pg/v2/model/format.go New: Partition/index/constraint name generation utilities for PostgreSQL tables.
drivers/pg/v2/model/model.go New: Data structures for index/constraint change sets, graph partitions, and graph metadata.
drivers/pg/v2/pg.go New: PostgreSQL v2 driver integration, pool setup, composite type registration, driver registry.
drivers/pg/v2/query/definitions.go New: Regex definitions/constants for parsing PostgreSQL index creation statements.
drivers/pg/v2/query/format.go New: SQL formatting/batching for property graph operations, upsert, index/constraint DDL, and batch update validation.
drivers/pg/v2/query/query.go New: Transactional interface for graph/partition/index/constraint management and metadata querying.
drivers/pg/v2/query/sql.go New: Embeds SQL files, provides SQL-loading utilities, exposes schema/query SQL as package variables.
drivers/pg/v2/query/sql/insert_graph.sql, drivers/pg/v2/query/sql/insert_or_get_kind.sql, drivers/pg/v2/query/sql/schema_down.sql, drivers/pg/v2/query/sql/schema_up.sql, drivers/pg/v2/query/sql/select_graph_by_name.sql, drivers/pg/v2/query/sql/select_graphs.sql, drivers/pg/v2/query/sql/select_kind_id.sql, drivers/pg/v2/query/sql/select_kinds.sql, drivers/pg/v2/query/sql/select_table_indexes.sql New: SQL scripts for schema/table/graph/kind/index management and introspection.
drivers/pg/v2/statements.go New: SQL statement constants for node/edge CRUD and property updates.
drivers/pg/v2/types.go New: Composite type mapping for nodes/edges/paths, conversion to graph entities, error handling.
drivers/pg/v2/util.go New: Placeholder utility file.
graph/mapper.go Renamed TryMapMap, added MapAll for batch mapping.
v2/driver.go Refactored driver/database interfaces: renamed session options, removed First/Execute, added schema assertion, error result, and graph/node methods.
v2/ops.go FetchNodes now uses PreparedQuery and CypherQuery, removed direct cypher import.
v2/query.go Refactored query builder: supports CREATE, modularized, new interfaces for entity/property/identity, parameter extraction, returns PreparedQuery.
v2/query_test.go Refactored tests: direct query formatting, added node and relationship creation scenarios.
v2/registry.go Added DriverConfig field to Config for driver-specific config.
v2/registry_integration_test.go Test updated: schema assertion, node creation, updated query execution, commented alternative driver and transaction example.
v2/schema.go New: Schema types for graphs, indexes, constraints, and schema construction.
v2/util.go Refactored identifier extraction: structured sets, context-aware visitor, pattern preparation, and utility functions.

Sequence Diagram(s)

sequenceDiagram
    participant App
    participant PGDatabase
    participant SchemaManager
    participant QueryBuilder
    participant Driver
    participant PGXPool

    App->>PGDatabase: NewDatabase(pool, config)
    App->>PGDatabase: AssertSchema(schema)
    PGDatabase->>SchemaManager: AssertSchema(schema)
    SchemaManager->>PGXPool: Begin Transaction
    SchemaManager->>PGXPool: Query current schema
    SchemaManager->>PGXPool: Compare/Add/Remove indexes/constraints
    SchemaManager->>PGXPool: Commit Transaction

    App->>QueryBuilder: Build Cypher Query
    QueryBuilder->>App: PreparedQuery{Query, Parameters}

    App->>Driver: CypherQuery(ctx, PreparedQuery.Query, PreparedQuery.Parameters)
    Driver->>SchemaManager: getTargetGraph(ctx)
    Driver->>PGXPool: Translate Cypher to SQL, Query(pg_query, args)
    PGXPool->>Driver: Rows
    Driver->>App: Result
Loading

Poem

In burrows deep, the schemas grow,
New drivers hop in tidy rows.
With Cypher’s charm and SQL’s might,
The graphs now dance from day to night.
Indexes pruned, constraints in place—
A rabbit’s code, a data race!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f85e0d1 and 94736d1.

📒 Files selected for processing (1)
  • drivers/pg/v2/manager.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • drivers/pg/v2/manager.go
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🔭 Outside diff range comments (1)
drivers/pg/v2/util.go (1)

1-2: File stubbed but referenced elsewhere – build will fail

The file currently only declares the package:

package v2

The AI summary and surrounding codebase reference numerous new types & functions (queryIdentifiers, identifierExtractor, etc.).
With just this stub, any code importing drivers/pg/v2 and using those symbols will not compile.

Provide the full implementation or revert dependent changes. Minimal fix to keep the tree building:

-package v2
+package v2
+
+// TODO: implement query identifier utilities.

…but compilation errors will persist until the real code is added.

🧹 Nitpick comments (17)
drivers/pg/v2/query/sql/select_graphs.sql (1)

1-3: Add explicit ordering for predictable results

Same reasoning as for select_kinds.sql; enumerating graphs in a predictable order avoids flaky tests and makes diff-based deployments clearer.

-select id, name
-from graph;
+select id, name
+from graph
+order by name;
drivers/pg/v2/query/sql/select_graph_by_name.sql (1)

2-4: Enforce uniqueness & limit result set

If graph.name has a UNIQUE constraint (recommended), add limit 1 to signal the expectation and save work.
Also, qualify the placeholder comment to avoid ambiguity for future maintainers.

-select id
-from graph
-where name = @name;
+-- @name is a bound parameter supplied by the caller.
+select id
+from graph
+where name = @name
+limit 1;
v2/registry.go (1)

25-25: Add documentation for the DriverConfig field.

The new DriverConfig field lacks documentation explaining its purpose and expected usage. Consider adding a comment to clarify what type of configuration should be passed and how it will be used by different drivers.

type Config struct {
	GraphQueryMemoryLimit size.Size
	ConnectionString      string
+	// DriverConfig holds driver-specific configuration data that will be passed
+	// to the driver constructor. The type and structure depend on the specific driver.
	DriverConfig          any
}
graph/properties.go (1)

233-239: Consider clarifying the difference from MapOrEmpty().

The new ToMap() method is very similar to the existing MapOrEmpty() method (lines 260-266), but doesn't handle the case where the Properties struct itself is nil. This could lead to confusion about which method to use in different scenarios.

Consider either:

  1. Adding documentation to clarify when to use each method
  2. Consolidating the functionality if both methods serve the same purpose
+// ToMap returns the underlying Map if it exists, otherwise returns an empty map.
+// Note: This method assumes the Properties struct is not nil. Use MapOrEmpty() if
+// you need to handle nil Properties structs.
func (s *Properties) ToMap() map[string]any {
	if s.Map == nil {
		return map[string]any{}
	}

	return s.Map
}
v2/registry_integration_test.go (2)

11-11: Clean up or document commented PostgreSQL import.

The commented import suggests PostgreSQL support exists but isn't being used in this test. Consider either removing it or adding a comment explaining why it's disabled.

-	//pg_v2 "github.com/specterops/dawgs/drivers/pg/v2"

66-78: Remove or activate commented transaction example.

The commented code shows an alternative transaction pattern with query builder and parameters. Either remove it or activate it as a separate test case.

Consider converting this to a separate test case:

func TestTransactionWithQueryBuilder(t *testing.T) {
	// Implementation from commented code
}
drivers/pg/v2/query/sql/schema_down.sql (1)

1-80: Add data loss warning to schema teardown script.

This script performs destructive operations that will permanently delete all graph data. Consider adding a prominent warning comment at the top of the file.

Add a warning header like:

-- WARNING: This script will permanently delete ALL graph data
-- including nodes, edges, kinds, and related metadata.
-- Ensure you have a backup before running this script.
-- This operation is IRREVERSIBLE.
drivers/pg/v2/model/format.go (3)

15-17: Consider input validation and potential naming conflicts.

The partitionTableName function doesn't validate that graphID is positive or that parent is a valid table name. Additionally, the underscore-based naming convention could cause conflicts if field names already contain underscores.

Consider adding input validation:

 func partitionTableName(parent string, graphID int32) string {
+	if parent == "" {
+		panic("parent table name cannot be empty")
+	}
+	if graphID < 0 {
+		panic("graphID must be non-negative")
+	}
 	return parent + "_" + strconv.FormatInt(int64(graphID), 10)
 }

27-36: Consider sanitizing field names to prevent naming conflicts.

The IndexName function could generate conflicting names if index.Field contains underscores. For example, fields "user_id" and "user" with "id" suffix would both generate similar patterns.

Consider using a more robust naming strategy:

 func IndexName(table string, index v2.Index) string {
 	stringBuilder := strings.Builder{}
 
 	stringBuilder.WriteString(table)
 	stringBuilder.WriteString("_")
-	stringBuilder.WriteString(index.Field)
+	stringBuilder.WriteString(strings.ReplaceAll(index.Field, "_", "__"))
 	stringBuilder.WriteString("_index")
 
 	return stringBuilder.String()
 }

38-47: Apply consistent naming strategy for constraints.

Similar to the IndexName function, this could benefit from field name sanitization to prevent conflicts.

Apply the same sanitization approach as suggested for IndexName:

 func ConstraintName(table string, constraint v2.Constraint) string {
 	stringBuilder := strings.Builder{}
 
 	stringBuilder.WriteString(table)
 	stringBuilder.WriteString("_")
-	stringBuilder.WriteString(constraint.Field)
+	stringBuilder.WriteString(strings.ReplaceAll(constraint.Field, "_", "__"))
 	stringBuilder.WriteString("_constraint")
 
 	return stringBuilder.String()
 }
drivers/pg/v2/pg.go (1)

66-68: Address TODO: Make pool configuration configurable.

The hard-coded minimum and maximum connection values should be configurable to allow for different deployment scenarios and load requirements.

+// PoolConfig holds configuration for the connection pool
+type PoolConfig struct {
+	MinConns int32
+	MaxConns int32
+}
+
+// DefaultPoolConfig returns sensible defaults for the connection pool
+func DefaultPoolConfig() PoolConfig {
+	return PoolConfig{
+		MinConns: 5,
+		MaxConns: 50,
+	}
+}
+
-func NewPool(connectionString string) (*pgxpool.Pool, error) {
+func NewPool(connectionString string) (*pgxpool.Pool, error) {
+	return NewPoolWithConfig(connectionString, DefaultPoolConfig())
+}
+
+func NewPoolWithConfig(connectionString string, poolConfig PoolConfig) (*pgxpool.Pool, error) {
 	if connectionString == "" {
 		return nil, fmt.Errorf("graph connection requires a connection url to be set")
 	}
 
 	poolCtx, done := context.WithTimeout(context.Background(), poolInitConnectionTimeout)
 	defer done()
 
 	poolCfg, err := pgxpool.ParseConfig(connectionString)
 	if err != nil {
 		return nil, err
 	}
 
-	// TODO: Min and Max connections for the pool should be configurable
-	poolCfg.MinConns = 5
-	poolCfg.MaxConns = 50
+	poolCfg.MinConns = poolConfig.MinConns
+	poolCfg.MaxConns = poolConfig.MaxConns

Would you like me to open an issue to track this improvement?

drivers/pg/v2/database.go (1)

66-70: Transaction rollback after successful commit will generate harmless errors.

The deferred rollback will execute even after a successful commit, causing harmless but unnecessary error logs. Consider checking transaction state or using a different pattern.

 		} else {
+			var committed bool
 			defer func() {
-				if err := transaction.Rollback(ctx); err != nil {
-					slog.DebugContext(ctx, "failed to rollback transaction", slog.String("err", err.Error()))
+				if !committed {
+					if err := transaction.Rollback(ctx); err != nil {
+						slog.DebugContext(ctx, "failed to rollback transaction", slog.String("err", err.Error()))
+					}
 				}
 			}()
 
 			if err := driverLogic(ctx, newInternalDriver(transaction, s.schemaManager)); err != nil {
 				return err
 			}
 
-			return transaction.Commit(ctx)
+			if err := transaction.Commit(ctx); err != nil {
+				return err
+			}
+			committed = true
+			return nil
 		}
drivers/neo4j/v2/driver.go (1)

156-159: Implement graph context switching

The WithGraph method is currently a no-op. This needs to be implemented to support multi-graph operations.

Would you like me to create an issue to track the implementation of graph context switching for the Neo4j driver?

drivers/pg/v2/manager.go (1)

245-250: Remove empty else block.

The empty else block is unnecessary and reduces readability.

 	return s.defineKinds(ctx, transaction, missingKinds)
 }); err != nil {
 	return nil, err
-} else {
-
 }
drivers/pg/v2/types.go (1)

47-123: Consider simplifying the type casting logic.

While the extensive type handling is necessary for database interoperability, consider using a type switch or reflection to reduce code duplication.

Would you like me to provide a more maintainable implementation using reflection that reduces the code duplication while maintaining type safety?

v2/query.go (1)

546-548: Refactor condition check for readability.

The condition is hard to read. Consider extracting to a helper method.

-	if len(s.projections) == 0 && len(s.setItems) == 0 && len(s.removeItems) == 0 && len(s.creates) == 0 && len(s.deleteItems) == 0 {
+	if !s.hasActions() {
 		return nil, fmt.Errorf("query has no action specified")
 	}

Add helper method:

func (s *builder) hasActions() bool {
	return len(s.projections) > 0 || len(s.setItems) > 0 || 
	       len(s.removeItems) > 0 || len(s.creates) > 0 || 
	       len(s.deleteItems) > 0
}
drivers/pg/v2/query/sql/schema_up.sql (1)

498-567: Sophisticated graph traversal implementation.

The shortest path algorithms correctly implement both unidirectional and bidirectional search with proper frontier management and cycle detection. Consider adding documentation for the algorithm complexity (O(V+E) for BFS-based shortest path).

Also applies to: 568-620, 621-715

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 411d10d and 8ffc441.

📒 Files selected for processing (50)
  • cypher/models/cypher/model.go (6 hunks)
  • cypher/models/pgsql/test/testcase.go (3 hunks)
  • cypher/models/pgsql/translate/constraints.go (1 hunks)
  • cypher/models/pgsql/translate/expression.go (1 hunks)
  • cypher/models/pgsql/translate/function.go (1 hunks)
  • cypher/models/pgsql/translate/model.go (2 hunks)
  • cypher/models/walk/walk.go (4 hunks)
  • cypher/models/walk/walk_test.go (1 hunks)
  • drivers/neo4j/result_internal_test.go (1 hunks)
  • drivers/neo4j/v2/database.go (2 hunks)
  • drivers/neo4j/v2/driver.go (3 hunks)
  • drivers/neo4j/v2/schema.go (1 hunks)
  • drivers/pg/query/sql/schema_up.sql (1 hunks)
  • drivers/pg/v2/database.go (1 hunks)
  • drivers/pg/v2/driver.go (1 hunks)
  • drivers/pg/v2/manager.go (1 hunks)
  • drivers/pg/v2/mapper.go (1 hunks)
  • drivers/pg/v2/model/format.go (1 hunks)
  • drivers/pg/v2/model/model.go (1 hunks)
  • drivers/pg/v2/pg.go (1 hunks)
  • drivers/pg/v2/query/definitions.go (1 hunks)
  • drivers/pg/v2/query/format.go (1 hunks)
  • drivers/pg/v2/query/query.go (1 hunks)
  • drivers/pg/v2/query/sql.go (1 hunks)
  • drivers/pg/v2/query/sql/insert_graph.sql (1 hunks)
  • drivers/pg/v2/query/sql/insert_or_get_kind.sql (1 hunks)
  • drivers/pg/v2/query/sql/schema_down.sql (1 hunks)
  • drivers/pg/v2/query/sql/schema_up.sql (1 hunks)
  • drivers/pg/v2/query/sql/select_graph_by_name.sql (1 hunks)
  • drivers/pg/v2/query/sql/select_graphs.sql (1 hunks)
  • drivers/pg/v2/query/sql/select_kind_id.sql (1 hunks)
  • drivers/pg/v2/query/sql/select_kinds.sql (1 hunks)
  • drivers/pg/v2/query/sql/select_table_indexes.sql (1 hunks)
  • drivers/pg/v2/statements.go (1 hunks)
  • drivers/pg/v2/types.go (1 hunks)
  • drivers/pg/v2/util.go (1 hunks)
  • graph/mapper.go (2 hunks)
  • graph/properties.go (1 hunks)
  • graph/query.go (1 hunks)
  • ops/ops.go (2 hunks)
  • query/builder.go (2 hunks)
  • query/neo4j/neo4j.go (3 hunks)
  • v2/driver.go (2 hunks)
  • v2/ops.go (1 hunks)
  • v2/query.go (7 hunks)
  • v2/query_test.go (2 hunks)
  • v2/registry.go (1 hunks)
  • v2/registry_integration_test.go (2 hunks)
  • v2/schema.go (1 hunks)
  • v2/util.go (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (20)
cypher/models/pgsql/translate/function.go (2)
cypher/models/walk/walk.go (3)
  • PgSQL (216-218)
  • NewSimpleVisitor (111-116)
  • VisitorHandler (11-19)
cypher/models/cypher/model.go (1)
  • SyntaxNode (28-28)
graph/properties.go (1)
cypher/models/cypher/model.go (1)
  • Properties (1251-1254)
cypher/models/walk/walk_test.go (2)
cypher/models/walk/walk.go (2)
  • NewSimpleVisitor (111-116)
  • VisitorHandler (11-19)
cypher/models/cypher/model.go (1)
  • SyntaxNode (28-28)
cypher/models/pgsql/translate/constraints.go (1)
cypher/models/walk/walk.go (1)
  • VisitorHandler (11-19)
cypher/models/pgsql/test/testcase.go (2)
cypher/models/walk/walk.go (3)
  • Cypher (220-222)
  • NewSimpleVisitor (111-116)
  • VisitorHandler (11-19)
cypher/models/cypher/model.go (1)
  • SyntaxNode (28-28)
v2/ops.go (2)
v2/query.go (3)
  • PreparedQuery (536-539)
  • Node (98-102)
  • Query (318-320)
v2/driver.go (2)
  • DriverLogic (29-29)
  • Driver (22-27)
query/neo4j/neo4j.go (2)
cypher/models/walk/walk.go (3)
  • NewSimpleVisitor (111-116)
  • VisitorHandler (11-19)
  • Cypher (220-222)
cypher/models/cypher/model.go (4)
  • SyntaxNode (28-28)
  • NodePattern (1266-1270)
  • Variable (1136-1138)
  • RelationshipPattern (1294-1300)
cypher/models/pgsql/translate/expression.go (2)
cypher/models/cypher/model.go (1)
  • SyntaxNode (28-28)
cypher/models/walk/walk.go (1)
  • VisitorHandler (11-19)
drivers/pg/v2/model/format.go (1)
v2/schema.go (2)
  • Index (26-30)
  • Constraint (32-32)
drivers/pg/v2/model/model.go (2)
v2/schema.go (2)
  • Index (26-30)
  • Constraint (32-32)
drivers/pg/v2/model/format.go (2)
  • IndexName (27-36)
  • ConstraintName (38-47)
drivers/pg/v2/database.go (5)
v2/driver.go (4)
  • Option (11-11)
  • OptionReadOnly (14-14)
  • Database (31-36)
  • DriverLogic (29-29)
drivers/pg/v2/manager.go (2)
  • SchemaManager (37-45)
  • NewSchemaManager (47-56)
v2/registry.go (1)
  • Config (22-26)
v2/schema.go (1)
  • Schema (44-47)
graph/graph.go (1)
  • Transaction (322-360)
query/builder.go (2)
cypher/models/walk/walk.go (3)
  • NewSimpleVisitor (111-116)
  • VisitorHandler (11-19)
  • Cypher (220-222)
cypher/models/cypher/model.go (4)
  • SyntaxNode (28-28)
  • NodePattern (1266-1270)
  • Variable (1136-1138)
  • RelationshipPattern (1294-1300)
cypher/models/pgsql/translate/model.go (1)
cypher/models/cypher/model.go (1)
  • Variable (1136-1138)
drivers/pg/v2/mapper.go (3)
drivers/pg/v2/manager.go (1)
  • KindMapper (20-26)
graph/mapper.go (3)
  • MapFunc (356-356)
  • ValueMapper (358-360)
  • NewValueMapper (362-366)
graph/path.go (1)
  • Path (12-15)
v2/schema.go (2)
cypher/models/pgsql/translate/constraints.go (1)
  • Constraint (197-200)
drivers/pg/v2/model/model.go (1)
  • Graph (64-68)
v2/query_test.go (4)
v2/query.go (4)
  • Query (318-320)
  • Node (98-102)
  • Start (104-108)
  • Relationship (110-114)
cypher/models/cypher/model.go (5)
  • RegularQuery (134-136)
  • Create (640-645)
  • NodePattern (1266-1270)
  • NewParameter (808-813)
  • RelationshipPattern (1294-1300)
cypher/models/cypher/format/format.go (1)
  • RegularQuery (1211-1219)
graph/graph.go (1)
  • DirectionOutbound (17-17)
drivers/pg/v2/query/format.go (3)
v2/schema.go (5)
  • IndexType (5-5)
  • IndexTypeBTree (9-9)
  • IndexTypeTextSearch (10-10)
  • IndexTypeUnsupported (8-8)
  • Graph (34-42)
drivers/pg/v2/model/model.go (1)
  • Graph (64-68)
graph/graph.go (1)
  • ID (95-95)
v2/query.go (3)
graph/graph.go (1)
  • Direction (26-26)
cypher/models/cypher/model.go (37)
  • Expression (29-29)
  • Set (594-596)
  • Remove (546-548)
  • Operator (16-16)
  • NewComparison (1069-1077)
  • NewLiteral (772-777)
  • NewSetItem (620-626)
  • RemoveProperty (577-581)
  • Variable (1136-1138)
  • RelationshipPattern (1294-1300)
  • Properties (1251-1254)
  • NodePattern (1266-1270)
  • RemoveKindsByMatcher (571-575)
  • NewKindMatcher (749-754)
  • KindMatcher (744-747)
  • FunctionInvocation (1019-1026)
  • NewPropertyLookup (1208-1215)
  • Create (640-645)
  • Delete (519-522)
  • SinglePartQuery (305-311)
  • PatternPart (1425-1430)
  • NewVariableWithSymbol (1144-1148)
  • NewUpdatingClause (465-469)
  • NewProjection (1377-1381)
  • NewProjectionItemWithExpr (1169-1173)
  • Skip (1487-1489)
  • NewSkip (1491-1495)
  • Limit (1467-1469)
  • NewLimit (1471-1475)
  • RegularQuery (134-136)
  • SyntaxNode (28-28)
  • Parameter (803-806)
  • NewRegularQueryWithSingleQuery (142-150)
  • Match (411-415)
  • NewWhere (1324-1326)
  • Comparison (1064-1067)
  • NewReadingClause (207-209)
cypher/models/walk/walk.go (3)
  • Cypher (220-222)
  • NewSimpleVisitor (111-116)
  • VisitorHandler (11-19)
drivers/pg/v2/driver.go (8)
graph/mapper.go (1)
  • ValueMapper (358-360)
v2/driver.go (3)
  • Result (38-43)
  • Driver (22-27)
  • NewErrorResult (65-69)
drivers/pg/v2/manager.go (1)
  • SchemaManager (37-45)
drivers/pg/v2/model/model.go (1)
  • Graph (64-68)
cypher/models/cypher/model.go (2)
  • RegularQuery (134-136)
  • Properties (1251-1254)
cypher/models/pgsql/translate/translator.go (1)
  • Translate (425-433)
graph/properties.go (1)
  • Properties (227-231)
graph/graph.go (1)
  • ID (95-95)
drivers/pg/v2/query/query.go (4)
drivers/pg/v2/model/model.go (7)
  • GraphPartition (27-31)
  • NewGraphPartition (33-39)
  • GraphPartitions (59-62)
  • Graph (64-68)
  • IndexChangeSet (7-16)
  • NewGraphPartitionFromSchema (41-57)
  • NewIndexChangeSet (18-25)
v2/schema.go (5)
  • Constraint (32-32)
  • Index (26-30)
  • Graph (34-42)
  • IndexType (5-5)
  • IndexTypeBTree (9-9)
drivers/pg/v2/model/format.go (4)
  • NodePartitionTableName (19-21)
  • EdgePartitionTableName (23-25)
  • NodeTable (11-11)
  • EdgeTable (12-12)
graph/graph.go (1)
  • ID (95-95)
🔇 Additional comments (91)
drivers/pg/v2/query/sql/select_kinds.sql (1)

1-3: Consider adding a deterministic ordering clause

Without an ORDER BY, consecutive calls can return rows in different orders depending on the planner.
If client-side tests or caches rely on a stable order, append an explicit sort (e.g. ORDER BY name).
[ suggest_optional_refactor ]

-select id, name
-from kind;
+select id, name
+from kind
+order by name;
cypher/models/pgsql/translate/function.go (1)

16-16: Signature updated – confirm all visitors use the new interface

walk.NewSimpleVisitor now receives a walk.VisitorHandler.
The change is correct but breaks callers still passing walk.CancelableErrorHandler. Make sure:

  1. All custom visitors in the repo import the new interface.
  2. Down-stream libraries/modules depending on this package are updated before release.
#!/bin/bash
# Find any remaining references to the old interface
rg --no-heading --line-number "CancelableErrorHandler"
drivers/pg/v2/query/sql/select_kind_id.sql (1)

1-4: LGTM! Clean and secure SQL query.

The query correctly uses parameter binding (@name) to prevent SQL injection and has a clear, focused purpose.

graph/query.go (1)

26-26: LGTM! Consistent with the mapper interface refactoring.

The method name change from TryMap to Map aligns with the broader refactoring of the ValueMapper interface mentioned in the AI summary.

drivers/pg/v2/query/sql/insert_graph.sql (1)

1-4: LGTM! Efficient and secure SQL implementation.

The INSERT statement correctly uses parameter binding (@name) and efficiently returns the new ID with the RETURNING clause, avoiding the need for a separate SELECT query.

drivers/pg/query/sql/schema_up.sql (1)

535-535: LGTM! Helpful debug logging for graph traversal monitoring.

The debug statement provides valuable runtime insights during path expansion operations, including the current step, available paths, and satisfied paths count. This will aid in troubleshooting and performance analysis of the graph traversal harness.

drivers/pg/v2/query/sql/select_table_indexes.sql (1)

1-6: LGTM! Clean and focused index introspection query.

The SQL query properly filters by schema and uses parameterized table name for safe index definition retrieval. This supports the schema management framework for comparing existing vs. required indexes.

cypher/models/walk/walk_test.go (1)

15-15: LGTM! Interface type updated to align with visitor pattern refactoring.

The parameter type change from CancelableErrorHandler to VisitorHandler correctly reflects the interface refactoring in cypher/models/walk/walk.go where the interface was renamed and expanded with additional methods like Consume() and WasConsumed().

drivers/neo4j/result_internal_test.go (1)

18-18: LGTM! Method call updated to reflect mapper interface refactoring.

The change from TryMap to Map correctly aligns with the method rename in the ValueMapper interface as mentioned in the AI summary. The test logic and assertions remain unchanged.

cypher/models/pgsql/test/testcase.go (1)

103-103: LGTM! Consistent interface type updates across test methods.

The parameter type changes from CancelableErrorHandler to VisitorHandler in the WriteTo, Assert, and AssertLive methods correctly align with the visitor pattern refactoring in cypher/models/walk/walk.go. All three methods are consistently updated to use the new VisitorHandler interface.

Also applies to: 155-155, 186-186

cypher/models/pgsql/translate/constraints.go (1)

179-179: Interface refactoring looks good.

The update from walk.CancelableErrorHandler to walk.VisitorHandler aligns with the broader visitor pattern standardization across the codebase. The function logic remains unchanged, and the new interface provides additional consumption tracking capabilities.

ops/ops.go (1)

53-53: Method renaming looks correct.

The update from mapper.TryMap to mapper.Map aligns with the ValueMapper interface refactoring. The method calls maintain the same boolean return pattern and error handling logic.

Also applies to: 196-196, 199-199, 202-202

drivers/pg/v2/query/sql/insert_or_get_kind.sql (1)

1-12: Well-structured upsert implementation.

The SQL correctly implements an upsert pattern using CTE and UNION to handle both existing and new kind records. The use of ON CONFLICT (name) DO NOTHING prevents duplicate key violations while ensuring a single ID is always returned.

cypher/models/pgsql/translate/expression.go (1)

116-116: Consistent interface update.

The change from walk.CancelableErrorHandler to walk.VisitorHandler is consistent with the visitor pattern refactoring across the codebase. The function continues to extract syntax node references correctly with the enhanced interface.

v2/ops.go (1)

9-13: Architectural improvement with separated query preparation.

The refactoring from *cypher.RegularQuery to *PreparedQuery and the corresponding driver method change from Execute to CypherQuery represents a cleaner separation of concerns. The new approach explicitly handles query parameters through the PreparedQuery structure, improving type safety and making parameter management more transparent.

v2/registry_integration_test.go (3)

34-45: Verify schema assertion integrates properly with the driver.

The schema assertion defines node/edge kinds and a text search index. The implementation looks correct for demonstrating the new schema management capabilities.


47-48: Good separation of query building and execution.

The pattern of building a prepared query first, then using it in sessions/transactions is a good architectural choice that separates concerns.


50-54: Verify CreateNode method handles node properties correctly.

The node creation uses graph.PrepareNode with properties and kinds. Ensure the implementation properly validates and persists the node data.

#!/bin/bash
# Description: Verify CreateNode method implementation and error handling

# Search for CreateNode method implementations
ast-grep --pattern $'func ($$$) CreateNode($_, $_) $_ {
  $$$
}'

# Look for error handling in CreateNode calls
rg -A 10 "CreateNode.*error"
graph/mapper.go (2)

368-376: Method rename from TryMap to Map is a breaking change.

This rename appears intentional and aligns with similar changes across the codebase. The implementation remains unchanged which is good for consistency.


378-390: MapAll implementation is correct and follows good practices.

The method properly validates input lengths and fails fast on any mapping error. The sequential processing approach is appropriate for the use case.

v2/query_test.go (3)

15-36: Simplified query string generation improves readability.

The direct use of format.RegularQuery instead of buffer/emitter makes the test more concise and easier to understand.


37-46: CREATE node test case validates parameterized properties correctly.

The test correctly validates that a node creation with kinds and parameters generates the expected Cypher syntax create (n:A $props).


48-59: CREATE relationship test demonstrates complex pattern building.

The test shows creating a relationship from a node identified by ID with parameterized properties. The expected Cypher match (s), (e) where id(s) = 1234 create (s)-[r:A $props]->(e) looks correct.

query/neo4j/neo4j.go (3)

112-132: Visitor interface update aligns with codebase refactoring.

The change from CancelableErrorHandler to VisitorHandler is consistent with the broader visitor pattern updates across the codebase.


145-167: Simplified variable symbol access improves code clarity.

The direct access to typedElement.Variable.Symbol without type assertion suggests improved type safety in the underlying model. This simplification makes the code cleaner.


263-269: Error compilation visitor update is consistent.

The visitor interface update maintains the same error collection logic while using the new VisitorHandler interface.

query/builder.go (2)

67-87: Visitor interface update maintains consistency across query builders.

The change to VisitorHandler is consistent with the same updates in query/neo4j/neo4j.go, ensuring uniform visitor pattern usage across the codebase.


100-122: Variable symbol access simplification improves maintainability.

The direct access to typedNode.Variable.Symbol without type assertions matches the pattern used in the Neo4j query builder, providing consistency across implementations.

cypher/models/pgsql/translate/model.go (1)

543-543: Variable declaration is more explicit and clear.

The explicit declaration of variableExpression as *cypher.Variable improves code readability. The function logic remains sound with proper nil checking before accessing the Symbol field.

Note: The AI summary incorrectly states that the type switch and error handling were removed, but they are still present in the code.

Also applies to: 569-569

Likely an incorrect or invalid review comment.

drivers/neo4j/v2/database.go (3)

20-20: Schema manager integration follows good patterns.

The addition of the schemaManager field and its initialization in the constructor properly integrates schema management capabilities into the database abstraction.

Also applies to: 29-29


33-35: Method delegation is clean and appropriate.

The AssertSchema method correctly delegates to the schema manager, maintaining separation of concerns.


51-51: Constant name update aligns with interface changes.

The change from v2.SessionOptionReadOnly to v2.OptionReadOnly is consistent with the v2 package interface updates.

drivers/pg/v2/query/definitions.go (3)

7-7: Column index regex pattern looks more robust.

The column index regex (?i)^create\s+(unique)?(?:\s+)?index\s+([^ ]+)\s+on\s+\S+\s+using\s+([^ ]+)\s+\(([^)]+)\)$ appears more straightforward and less prone to ReDoS vulnerabilities than the property index pattern.


10-21: Constants correctly map to regex capture groups.

The constants properly define the expected regex group indices and values, making the code maintainable and reducing magic numbers.


6-6: Review regex pattern for potential ReDoS vulnerabilities.

The property index regex pattern is complex with multiple optional groups and could be vulnerable to ReDoS attacks. The pattern (?i)^create\s+(unique)?(?:\s+)?index\s+([^ ]+)\s+on\s+\S+\s+using\s+([^ ]+)\s+\(+properties\s+->>\s+'([^:]+)::.+$ contains potentially problematic constructs.

#!/bin/bash
# Test the regex patterns for potential ReDoS vulnerabilities by checking against malicious inputs
# This will help identify if the regex can cause catastrophic backtracking

echo "Testing PostgreSQL index regex patterns for ReDoS vulnerabilities..."

# Create a test file to analyze the regex patterns
cat > test_regex.go << 'EOF'
package main

import (
	"fmt"
	"regexp"
	"time"
)

func testRegex(pattern string, input string, description string) {
	re := regexp.MustCompile(pattern)
	start := time.Now()
	
	// Test with timeout to catch ReDoS
	done := make(chan bool, 1)
	go func() {
		_ = re.MatchString(input)
		done <- true
	}()
	
	select {
	case <-done:
		duration := time.Since(start)
		fmt.Printf("%s: Completed in %v\n", description, duration)
	case <-time.After(5 * time.Second):
		fmt.Printf("%s: TIMEOUT - Potential ReDoS vulnerability\n", description)
	}
}

func main() {
	// Test patterns from the file
	pgPropertyIndexRegex := `(?i)^create\s+(unique)?(?:\s+)?index\s+([^ ]+)\s+on\s+\S+\s+using\s+([^ ]+)\s+\(+properties\s+->>\s+'([^:]+)::.+$`
	pgColumnIndexRegex := `(?i)^create\s+(unique)?(?:\s+)?index\s+([^ ]+)\s+on\s+\S+\s+using\s+([^ ]+)\s+\(([^)]+)\)$`
	
	// Malicious inputs that could cause ReDoS
	maliciousInput1 := "create    " + strings.Repeat(" ", 1000) + "index"
	maliciousInput2 := "create unique" + strings.Repeat("  ", 1000) + "index"
	
	testRegex(pgPropertyIndexRegex, maliciousInput1, "Property index regex with excessive spaces")
	testRegex(pgColumnIndexRegex, maliciousInput2, "Column index regex with excessive spaces")
}
EOF

# Check if we can compile and run the test (but don't actually run it to avoid security issues)
go mod init test-regex 2>/dev/null || true
echo "Created test file to analyze regex patterns."
echo "The regex patterns should be reviewed for catastrophic backtracking vulnerabilities."
drivers/pg/v2/statements.go (2)

4-7: Node creation statements look correct.

The SQL statements for node creation properly use parameterized queries and PostgreSQL-specific syntax like unnest for batch operations. The return of composite types is well-structured.


18-21: Property update statements use secure JSONB operations.

The edge property update statements correctly use PostgreSQL's JSONB operators (|| for merge, - for deletion) and parameterized queries to prevent SQL injection.

drivers/pg/v2/query/sql/schema_down.sql (3)

1-29: Comprehensive function and trigger cleanup.

The script systematically drops all graph-related functions and triggers in a logical order. The cleanup is thorough and covers all the components needed for the graph database functionality.


30-35: Table dropping follows proper dependency order.

The tables are dropped in the correct dependency order (node, edge, kind, graph) to avoid foreign key constraint violations.


37-71: Good error handling for custom types.

The use of DO blocks with exception handling ensures the script doesn't fail if custom types don't exist, making it safe to run multiple times.

drivers/pg/v2/model/model.go (3)

18-25: Efficient constructor pattern with proper initialization.

Good use of map initialization with empty maps for the "add" fields while leaving slice fields as nil, which is appropriate for their usage pattern.


41-46: Efficient memory allocation using make with capacity.

Good practice using make() with explicit capacity based on slice length to avoid map reallocations during population.


48-54: Missing import for IndexName and ConstraintName functions.

The code calls IndexName and ConstraintName functions, but these aren't imported or defined in this file. This will cause compilation errors.

Add the missing function calls by importing from the same package:

 	for _, index := range indexes {
-		graphPartition.Indexes[IndexName(name, index)] = index
+		graphPartition.Indexes[IndexName(name, index)] = index
 	}
 
 	for _, constraint := range constraints {
-		graphPartition.Constraints[ConstraintName(name, constraint)] = constraint
+		graphPartition.Constraints[ConstraintName(name, constraint)] = constraint
 	}

Since these functions are in the same package (model), they should be accessible without additional imports. Verify that the functions are properly defined in the package.

Likely an incorrect or invalid review comment.

drivers/pg/v2/pg.go (3)

40-51: Efficient connection lifecycle management with proper logging.

The connection release hook correctly identifies and destroys connections missing composite types. The warning log provides good visibility into connection pool health.


26-38: Robust composite type registration with error handling.

Good error handling that distinguishes between "object does not exist" errors and other failures. The type registration is essential for proper PostgreSQL composite type support.


88-102: Verify driver registration pattern for potential conflicts.

The driver registration follows Go conventions but should verify that the driver name "pg_v2" doesn't conflict with existing drivers.

#!/bin/bash
# Description: Check for potential driver name conflicts in the codebase
# Expected: No other drivers using "pg_v2" name

# Search for other driver registrations
rg -A 3 -B 3 'Register.*"pg.*"'

# Search for references to pg_v2 driver name
rg '"pg_v2"'
drivers/pg/v2/database.go (2)

13-28: Clean transaction option handling with proper defaults.

The beginTx function correctly defaults to read-write mode and properly handles the read-only option. The transaction options setup is well-structured.


48-55: Proper resource management in Session method.

The connection acquisition and release pattern with defer is correctly implemented. The error handling ensures connections are released even when acquisition succeeds but driver logic fails.

drivers/pg/v2/query/sql.go (3)

15-31: Efficient SQL comment stripping with clean implementation.

The comment stripping logic correctly handles empty lines and SQL comments while preserving the essential SQL content. Using strings.Builder for concatenation is efficient.


33-39: Appropriate use of panic for build-time errors.

Using panic() for missing embedded files is correct since this represents a build-time configuration error that should be caught during development.


10-13: Proper embed directive usage for SQL file management.

The //go:embed sql directive is correctly used to embed the SQL directory, enabling self-contained binary deployment.

v2/schema.go (2)

34-47: Well-structured schema types

The Graph and Schema structs are well-designed with appropriate encapsulation. The unexported defaultGraph field ensures controlled access through the DefaultGraph() method.


49-65: Idiomatic Go constructor and accessor methods

The NewSchema constructor and DefaultGraph() method follow Go best practices, including the comma-ok idiom for map lookups.

drivers/neo4j/v2/driver.go (2)

36-38: Correct migration to new mapper interface

The update from TryMap to Map is correctly implemented with appropriate error handling.

Also applies to: 113-115


161-194: Well-implemented driver methods

The new methods CreateNode, Raw, and CypherQuery are correctly implemented with proper error handling and delegation patterns.

v2/driver.go (3)

14-16: Improved option naming

The renamed constants OptionReadOnly and OptionReadWrite are more descriptive than the previous names.


23-36: Well-designed interface updates

The updated Driver and Database interfaces provide better separation of concerns with dedicated methods for graph operations and schema management.


45-69: Correct error result implementation

The errorResult type correctly implements the Result interface for error cases, providing a clean error handling pattern.

cypher/models/cypher/model.go (2)

162-162: Improved type safety with specific pointer types

The refinement from generic Expression to specific *Variable pointers improves type safety and makes the API clearer. The RemoveItem.Property change to Expression appropriately increases flexibility.

Also applies to: 267-267, 295-295, 426-426, 568-568


169-174: Useful constructor addition

The NewProjectionItemWithExpr constructor provides a convenient way to create projection items with expressions.

drivers/pg/v2/mapper.go (2)

49-102: Well-structured mapping function

The newMapFunc implementation correctly handles all target types with proper type assertions and error handling.


104-106: Clean factory function

The newValueMapper constructor properly encapsulates the mapping logic for use with the graph package.

cypher/models/walk/walk.go (1)

11-19: Well-designed consumption tracking mechanism.

The addition of Consume() and WasConsumed() methods provides a clean way to control syntax tree traversal, allowing visitors to stop processing of subtrees when needed. The implementation correctly resets the consumption state after checking.

Also applies to: 58-67, 188-188

drivers/pg/v2/manager.go (1)

37-56: Excellent thread-safe design with efficient caching.

The SchemaManager implements a well-designed concurrent access pattern with RWMutex, proper lock escalation from read to write locks when cache misses occur, and efficient caching of kinds and graphs. The public getter methods correctly protect read access.

Also applies to: 98-102, 272-277

drivers/pg/v2/driver.go (2)

16-76: Well-implemented result handling with proper value mapping.

The queryResult implementation correctly handles iteration, scanning with type safety through the ValueMapper, and error propagation. The takeFirst optimization for single results is a nice touch.


165-182: Clean node creation with proper schema assertion.

The CreateNode method correctly asserts the graph and kinds before creating the node, ensuring schema consistency. The JSONB conversion for properties is handled appropriately.

drivers/pg/v2/types.go (1)

12-18: Well-designed composite types for graph entities.

The composite structs provide clean abstractions for nodes, edges, and paths with proper conversion methods to domain types. The TryMap pattern for optional mapping is elegant.

Also applies to: 125-166, 168-207, 209-292

drivers/neo4j/v2/schema.go (2)

284-333: Excellent schema synchronization implementation.

The AssertSchema method properly compares the required schema with the present schema, handling additions, removals, and type changes for both indexes and constraints. The separation of index and constraint operations into different transactions is appropriate for Neo4j.


222-282: Robust schema fetching with proper Neo4j 4.4+ handling.

The fetchPresentSchema method correctly handles the Neo4j 4.4+ default index edge case and validates against composite indexes. The value mapping using the Neo4j mapper is clean and type-safe.

v2/util.go (6)

27-39: LGTM!

The function correctly validates that node and relationship patterns aren't mixed and conditionally adds a node pattern.


41-85: Well-structured relationship pattern preparation.

The function correctly handles the mutual exclusivity of creation and constraint operations on relationships, and properly constructs pattern elements based on the identifier states.


87-108: LGTM!

The variable extraction correctly handles all relevant Cypher expression types.


110-133: LGTM!

Clean implementation of a string set with union operation.


165-223: LGTM!

The visitor correctly tracks clause context and categorizes identifiers appropriately. The default behavior of treating identifiers in non-updating clauses as constrained is sensible.


225-232: LGTM!

Clean wrapper function with proper error propagation.

drivers/pg/v2/query/format.go (6)

44-46: Implementation is correct for PostgreSQL.

In PostgreSQL, unique constraints are implemented as unique indexes, so using DROP INDEX to remove constraints is the correct approach.


195-205: LGTM!

The validation functions properly accumulate updates and propagate errors.

Also applies to: 290-300


236-288: LGTM!

The relationship batch update correctly manages both node and relationship updates with proper validation.


207-215: Consider thread safety for Future type.

If Future values are accessed concurrently, consider adding synchronization or documenting that they should only be accessed from a single goroutine.

#!/bin/bash
# Check if Future is used in concurrent contexts
rg -B 3 -A 3 "Future\[" --type go | grep -E "(go |goroutine|concurrent|parallel)"

84-104: Ensure property names are validated.

The function concatenates property names directly into SQL. Verify that propertyNames are validated or sanitized before use.

#!/bin/bash
# Search for usage of formatConflictMatcher to check property name sources
rg -B 5 -A 2 "formatConflictMatcher" --type go

48-68: Validate inputs to prevent SQL injection.

While the current usage appears safe, ensure that constraintName, tableName, and fieldName are validated or come from trusted sources to prevent SQL injection.

#!/bin/bash
# Search for callers of these format functions to verify input sources
rg -A 5 "formatCreateProperty(Index|Constraint)" --type go
v2/query.go (3)

517-534: LGTM!

The parameter extraction correctly handles duplicates and clears values from the AST.


208-272: LGTM!

Clean implementation of the entity builder with good use of generics for type safety.


156-190: LGTM!

The comparison continuation correctly generates comparison expressions for all supported operators.

drivers/pg/v2/query/sql/schema_up.sql (3)

56-74: Well-designed schema with appropriate partitioning.

The table structure correctly uses partitioning for scalability and includes appropriate constraints to maintain data integrity.

Also applies to: 93-102, 134-147


111-114: LGTM! Comprehensive index coverage.

The indexes cover all common query patterns including array containment queries with GIN indexes.

Also applies to: 180-189


152-171: Appropriate use of triggers for cascading deletes.

The trigger-based approach correctly handles cascading deletes across partitions where foreign keys would be impractical.

drivers/pg/v2/query/query.go (4)

26-41: LGTM!

The query execution helpers correctly handle both positional and named arguments using pgx's NamedArgs feature.


374-457: Excellent schema assertion implementation.

The method correctly computes the minimal changeset by comparing required and present indexes/constraints, and properly handles type changes by removing and re-adding indexes.


121-147: LGTM! Proper error handling.

The method correctly distinguishes between actual errors and no rows found, returning the appropriate pgx.ErrNoRows.


43-76: Consider the fragility of regex-based parsing.

While the regex approach works, it's fragile to PostgreSQL version changes. Consider adding version checks or more robust parsing if this becomes an issue.

#!/bin/bash
# Check regex definitions to understand the expected formats
rg "pgPropertyIndexRegex|pgColumnIndexRegex" --type go

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (3)
drivers/pg/v2/manager.go (1)

69-73: Transaction rollback handling looks correct.

The deferred rollback properly checks for pgx.ErrTxClosed to avoid unnecessary error logging after successful commits.

drivers/pg/v2/types.go (1)

221-221: Error messages have been properly fixed.

The descriptive error messages for type assertion failures are now clear and helpful for debugging.

Also applies to: 243-243

v2/query.go (1)

448-448: LGTM! Proper error handling.

The method correctly returns the error immediately instead of adding it to a clause, which aligns with the established pattern and previous review feedback.

🧹 Nitpick comments (6)
drivers/neo4j/v2/schema.go (2)

175-180: Consider using consistent map type

The code uses map[string]interface{} in these parameter maps, but Go 1.18+ typically uses map[string]any for consistency. However, this may be required by the Neo4j driver API.

-			}); err != nil {
-				return err
-			} else if _, err := result.Consume(ctx); err != nil {
+			}); err != nil {
+				return err
+			} else if _, err := result.Consume(ctx); err != nil {

Also applies to: 206-210


253-255: Enhance composite index error message

The error message for unsupported composite indexes could be more descriptive to help users understand the limitation.

-						return fmt.Errorf("composite index types are currently not supported")
+						return fmt.Errorf("composite indexes with multiple labels (%v) or properties (%v) are currently not supported", labels, properties)
drivers/pg/v2/manager.go (1)

140-161: Consider potential inefficiency in lock upgrade pattern.

While the lock upgrade pattern is implemented correctly, calling s.Fetch(ctx) while holding the write lock (line 152) creates a new transaction unnecessarily. Since you already have a write lock, consider fetching data directly within the current context rather than creating a separate transaction.

Consider refactoring to avoid the extra transaction:

-func (s *SchemaManager) MapKind(ctx context.Context, kind graph.Kind) (int16, error) {
-	s.lock.RLock()
-
-	if id, hasID := s.kindsByID[kind]; hasID {
-		s.lock.RUnlock()
-		return id, nil
-	}
-
-	s.lock.RUnlock()
-	s.lock.Lock()
-	defer s.lock.Unlock()
-
-	if err := s.Fetch(ctx); err != nil {
-		return -1, err
-	}
-
-	if id, hasID := s.kindsByID[kind]; hasID {
-		return id, nil
-	} else {
-		return -1, fmt.Errorf("unable to map kind: %s", kind.String())
-	}
-}
+func (s *SchemaManager) MapKind(ctx context.Context, kind graph.Kind) (int16, error) {
+	s.lock.RLock()
+
+	if id, hasID := s.kindsByID[kind]; hasID {
+		s.lock.RUnlock()
+		return id, nil
+	}
+
+	s.lock.RUnlock()
+	s.lock.Lock()
+	defer s.lock.Unlock()
+
+	// Check again after acquiring write lock
+	if id, hasID := s.kindsByID[kind]; hasID {
+		return id, nil
+	}
+
+	// Fetch directly within transaction instead of creating new one
+	if err := s.transaction(ctx, func(transaction pgx.Tx) error {
+		return s.fetch(ctx, transaction)
+	}); err != nil {
+		return -1, err
+	}
+
+	if id, hasID := s.kindsByID[kind]; hasID {
+		return id, nil
+	} else {
+		return -1, fmt.Errorf("unable to map kind: %s", kind.String())
+	}
+}
drivers/pg/v2/types.go (2)

246-246: Fix variable naming inconsistency.

The variable is named typedNode but it represents an edge, which is confusing.

-			switch typedNode := rawEdge.(type) {
+			switch typedEdge := rawEdge.(type) {
 			case map[string]any:
 				var edge edgeComposite
 
-				if err := edge.FromMap(typedNode); err != nil {
+				if err := edge.FromMap(typedEdge); err != nil {
 					return err
 				}

94-102: Consider potential overflow in int64 to int conversion.

On 32-bit systems, converting int64 to int could cause overflow. While this may be acceptable in your context, consider adding bounds checking or documenting this limitation.

Add bounds checking for safer conversion:

 case int64:
 	switch typedDst := any(dst).(type) {
 	case *int64:
 		*typedDst = typedSrc
 	case *int:
+		if typedSrc > int64(^uint(0)>>1) || typedSrc < int64(-1<<(^uint(0)>>1)) {
+			return fmt.Errorf("int64 value %d overflows int type", typedSrc)
+		}
 		*typedDst = int(typedSrc)
 	default:
 		return fmt.Errorf("unable to cast and assign value type: %T", src)
 	}
v2/query.go (1)

401-454: Approve the error handling approach but consider refactoring for complexity.

The buildCreates method correctly returns errors immediately rather than adding them to clauses (aligning with previous feedback). The type switching logic properly handles different create scenarios.

However, the method is quite complex with nested type switches and multiple responsibilities.

Consider extracting helper methods for each create type:

func (s *builder) handleQualifiedExpression(expr QualifiedExpression, pattern *cypher.PatternPart) error {
    // Handle QualifiedExpression logic
}

func (s *builder) handleNodePattern(node *cypher.NodePattern, pattern *cypher.PatternPart) error {
    // Handle NodePattern logic  
}

func (s *builder) handleRelationshipPattern(rel *cypher.RelationshipPattern, pattern *cypher.PatternPart) error {
    // Handle RelationshipPattern logic
}

This would improve readability and make the method easier to test and maintain.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ffc441 and f85e0d1.

📒 Files selected for processing (12)
  • cypher/models/walk/walk.go (4 hunks)
  • drivers/neo4j/v2/driver.go (3 hunks)
  • drivers/neo4j/v2/schema.go (1 hunks)
  • drivers/pg/v2/manager.go (1 hunks)
  • drivers/pg/v2/mapper.go (1 hunks)
  • drivers/pg/v2/query/sql.go (1 hunks)
  • drivers/pg/v2/query/sql/select_graph_by_name.sql (1 hunks)
  • drivers/pg/v2/query/sql/select_graphs.sql (1 hunks)
  • drivers/pg/v2/types.go (1 hunks)
  • v2/query.go (7 hunks)
  • v2/registry.go (1 hunks)
  • v2/schema.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • v2/registry.go
  • drivers/pg/v2/query/sql/select_graphs.sql
  • drivers/pg/v2/query/sql/select_graph_by_name.sql
  • drivers/pg/v2/query/sql.go
  • v2/schema.go
  • drivers/pg/v2/mapper.go
  • cypher/models/walk/walk.go
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/pg/v2/query/format.go:14-23
Timestamp: 2025-06-27T15:34:42.077Z
Learning: In the PostgreSQL v2 driver codebase, the team prefers to let invalid index type conversions (like "NOT SUPPORTED") fail at the SQL query execution level rather than returning errors from conversion functions like `postgresIndexType`. This allows error handling to occur with full query context rather than at the individual type conversion level.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 may not have the same transaction rollback error handling patterns as suggested. Check the specific v5 documentation before recommending `errors.Is(err, neo4j.ErrTransactionTerminated)` or similar patterns.
drivers/neo4j/v2/driver.go (3)
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 may not have the same transaction rollback error handling patterns as suggested. Check the specific v5 documentation before recommending `errors.Is(err, neo4j.ErrTransactionTerminated)` or similar patterns.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 does not export an `ErrTransactionTerminated` constant. Errors are handled as `Neo4jError` types with status codes like "Neo.TransientError.Transaction.Terminated". Do not suggest using `errors.Is(err, neo4j.ErrTransactionTerminated)` for Neo4j Go driver v5.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: When zinic corrects suggestions about Neo4j Go driver v5 transaction rollback error handling, defer to their expertise as they have direct experience with the actual library version being used in the codebase. Don't assume API availability based on general documentation searches.
drivers/neo4j/v2/schema.go (7)
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 may not have the same transaction rollback error handling patterns as suggested. Check the specific v5 documentation before recommending `errors.Is(err, neo4j.ErrTransactionTerminated)` or similar patterns.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 does not export an `ErrTransactionTerminated` constant. Errors are handled as `Neo4jError` types with status codes like "Neo.TransientError.Transaction.Terminated". Do not suggest using `errors.Is(err, neo4j.ErrTransactionTerminated)` for Neo4j Go driver v5.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: When zinic corrects suggestions about Neo4j Go driver v5 transaction rollback error handling, defer to their expertise as they have direct experience with the actual library version being used in the codebase. Don't assume API availability based on general documentation searches.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: Before suggesting changes to transaction rollback patterns in any database driver, verify the actual API documentation for the specific version being used. Don't assume error handling patterns exist without checking the documented API first.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/pg/v2/driver.go:82-85
Timestamp: 2025-06-27T15:24:24.691Z
Learning: The pgx.Rows.Close() method in the jackc/pgx library (including v5) does not return an error - it has the signature Close() with no return value. This is different from the standard database/sql library where Rows.Close() does return an error. Do not suggest changing patterns like "s.rows.Close(); return nil" to "return s.rows.Close()" for pgx.Rows.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/pg/v2/driver.go:82-85
Timestamp: 2025-06-27T15:24:24.691Z
Learning: The pgx.Rows.Close() method in the jackc/pgx/v5 library does not return an error - it has the signature Close() with no return value. Do not suggest changing patterns like "s.rows.Close(); return nil" to "return s.rows.Close()" for pgx.Rows.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: Before suggesting specific API usage or error handling patterns for external libraries, always check the actual version being imported in the code and verify the API availability in that specific version. Don't assume API patterns from other versions or libraries.
drivers/pg/v2/manager.go (6)
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 may not have the same transaction rollback error handling patterns as suggested. Check the specific v5 documentation before recommending `errors.Is(err, neo4j.ErrTransactionTerminated)` or similar patterns.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: When zinic corrects suggestions about Neo4j Go driver v5 transaction rollback error handling, defer to their expertise as they have direct experience with the actual library version being used in the codebase. Don't assume API availability based on general documentation searches.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/pg/v2/driver.go:82-85
Timestamp: 2025-06-27T15:24:24.691Z
Learning: The pgx.Rows.Close() method in the jackc/pgx library (including v5) does not return an error - it has the signature Close() with no return value. This is different from the standard database/sql library where Rows.Close() does return an error. Do not suggest changing patterns like "s.rows.Close(); return nil" to "return s.rows.Close()" for pgx.Rows.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/pg/v2/driver.go:82-85
Timestamp: 2025-06-27T15:24:24.691Z
Learning: The pgx.Rows.Close() method in the jackc/pgx/v5 library does not return an error - it has the signature Close() with no return value. Do not suggest changing patterns like "s.rows.Close(); return nil" to "return s.rows.Close()" for pgx.Rows.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: Before suggesting changes to transaction rollback patterns in any database driver, verify the actual API documentation for the specific version being used. Don't assume error handling patterns exist without checking the documented API first.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 does not export an `ErrTransactionTerminated` constant. Errors are handled as `Neo4jError` types with status codes like "Neo.TransientError.Transaction.Terminated". Do not suggest using `errors.Is(err, neo4j.ErrTransactionTerminated)` for Neo4j Go driver v5.
drivers/pg/v2/types.go (2)
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/pg/v2/query/format.go:168-172
Timestamp: 2025-06-27T15:33:46.673Z
Learning: In the DAWGS codebase, modifying input struct data directly is acceptable when the performance cost of copying outweighs the benefit of avoiding side effects, particularly for graph node structures in the PostgreSQL driver layer.
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 may not have the same transaction rollback error handling patterns as suggested. Check the specific v5 documentation before recommending `errors.Is(err, neo4j.ErrTransactionTerminated)` or similar patterns.
v2/query.go (1)
Learnt from: zinic
PR: SpecterOps/DAWGS#4
File: drivers/neo4j/v2/schema.go:136-140
Timestamp: 2025-06-27T15:32:33.197Z
Learning: The Neo4j Go driver v5 may not have the same transaction rollback error handling patterns as suggested. Check the specific v5 documentation before recommending `errors.Is(err, neo4j.ErrTransactionTerminated)` or similar patterns.
🧬 Code Graph Analysis (1)
drivers/neo4j/v2/driver.go (4)
v2/driver.go (3)
  • Driver (22-27)
  • Result (38-43)
  • NewErrorResult (65-69)
v2/query.go (3)
  • Node (98-102)
  • Query (318-320)
  • Identifiers (41-47)
cypher/models/cypher/model.go (6)
  • Create (640-645)
  • NodePattern (1266-1270)
  • Variable (1136-1138)
  • Properties (1251-1254)
  • NewParameter (808-813)
  • RegularQuery (134-136)
graph/properties.go (1)
  • Properties (227-231)
🪛 golangci-lint (1.64.8)
drivers/neo4j/v2/schema.go

231-231: Error return value of result.Consume is not checked

(errcheck)

🔇 Additional comments (12)
drivers/neo4j/v2/driver.go (4)

36-36: LGTM: Consistent mapper API migration

The change from mapper.TryMap to mapper.Map is consistent with the broader v2 API refactoring mentioned in the summary. The boolean return logic remains the same.

Also applies to: 113-113


156-159: LGTM: Clear no-op implementation

The WithGraph method is clearly documented as a no-op, which aligns with the interface requirements.


161-181: LGTM: Well-structured CreateNode implementation

The method properly constructs a Cypher CREATE query using the v2 query builder, handles errors appropriately, and ensures proper resource cleanup by closing the result and checking for errors.


188-194: LGTM: Clean delegation pattern

The refactored CypherQuery method properly formats the query, uses v2.NewErrorResult for error handling, and delegates execution to the Raw method following a clean separation of concerns.

drivers/neo4j/v2/schema.go (2)

136-142: LGTM: Appropriate transaction rollback handling

Based on my understanding of Neo4j Go driver v5, the current deferred rollback pattern is correct. The driver handles rollback-after-commit scenarios gracefully, and the debug logging approach acknowledges the difficulty of detecting specific error types in this version.


286-335: LGTM: Comprehensive schema assertion logic

The AssertSchema method implements a thorough comparison between required and present schemas, correctly identifying indexes and constraints to add or remove. The logic properly handles type mismatches by removing and re-adding elements, and the order of operations (constraints before indexes) is appropriate for Neo4j.

v2/query.go (6)

8-9: LGTM! Clean import organization.

The import structure is well-organized with the new cypher models import properly placed.


129-154: LGTM! Well-designed interface hierarchy.

The interface definitions create a clean hierarchy with proper separation of concerns:

  • EntityContinuation provides core entity operations
  • Comparable defines comparison operations
  • PropertyContinuation and IdentityContinuation extend functionality appropriately

The fluent interface pattern is well-implemented.


156-206: LGTM! Solid continuation implementation.

The comparisonContinuation and propertyContinuation types provide a clean foundation for the fluent interface pattern:

  • Consistent method signatures across comparison operations
  • Proper delegation to shared asComparison method
  • Clean separation between property operations (Set/Remove) and comparisons

208-272: LGTM! Effective use of Go generics.

The generic entity[T] type provides excellent code reuse while maintaining type safety:

  • Pattern methods properly construct Cypher AST nodes
  • ID() and Property() methods return appropriate continuation types
  • Consistent error handling and validation throughout

299-344: LGTM! Clean query builder interface extension.

The addition of the Create method and PreparedQuery return type enhances the builder pattern:

  • Consistent method signature with other builder methods
  • Proper slice append pattern in implementation
  • Maintains fluent interface chainability

517-534: LGTM! Clean parameter extraction implementation.

The stripASTParameters function effectively uses the visitor pattern to extract and clear parameter values from the AST:

  • Proper duplicate parameter detection
  • Clean separation of concerns with visitor pattern
  • Appropriate error handling with SetErrorf

@zinic zinic merged commit 987df3a into main Jun 27, 2025
1 check passed
@coderabbitai coderabbitai bot mentioned this pull request Aug 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants