Skip to content

Implement SQL Planner for Logical Plans and Statement Validation - #38

Open
rahulc0dy wants to merge 13 commits into
mainfrom
feat/planner
Open

Implement SQL Planner for Logical Plans and Statement Validation#38
rahulc0dy wants to merge 13 commits into
mainfrom
feat/planner

Conversation

@rahulc0dy

@rahulc0dy rahulc0dy commented Jul 10, 2026

Copy link
Copy Markdown
Member

Issue Reference

Summary by CodeRabbit

  • New Features
    • Added SQL planning for database and table management, data changes, and SELECT queries.
    • Added support for joins, filtering, grouping, aggregates, DISTINCT, sorting, pagination, aliases, ordinals, and wildcard expansion.
    • Improved type checking, name resolution, foreign-key validation, and semantic diagnostics.
  • Bug Fixes
    • Added validation for invalid grouping, duplicate assignments, unsupported comparisons, and incompatible expressions.
  • Tests
    • Added comprehensive planner coverage.
  • Documentation
    • Updated the README coverage badge.

@rahulc0dy
rahulc0dy requested a review from theMr17 July 10, 2026 09:08
@rahulc0dy rahulc0dy self-assigned this Jul 10, 2026
@rahulc0dy rahulc0dy added the feature New feature or request label Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 401b1dda-3d6b-405b-8be2-ad5308f451f5

📥 Commits

Reviewing files that changed from the base of the PR and between a0a677a and 16760f5.

📒 Files selected for processing (4)
  • internal/sql/planner/plan_conditions.go
  • internal/sql/planner/plan_conditions_test.go
  • internal/sql/planner/plan_statements.go
  • internal/sql/planner/plan_statements_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/sql/planner/plan_conditions.go
  • internal/sql/planner/plan_conditions_test.go

Included review availability: Your plan includes up to 1 review per rolling hour; 0 remain after this review.


Walkthrough

The PR adds a SQL planner that resolves catalog identifiers, expressions, conditions, and types, then produces logical plans for SELECT, DDL, INSERT, UPDATE, and DELETE statements with diagnostics and unit tests.

Changes

SQL planner implementation

Layer / File(s) Summary
Planner contracts and plan IR
internal/sql/planner/planner.go, internal/sql/planner/errors.go, internal/sql/planner/statements.go, internal/sql/planner/operators.go, internal/sql/planner/expressions.go, internal/sql/planner/conditions.go
Defines planner entry points, diagnostic codes, resolved AST representations, relational operators, and DDL/DML plan structures.
Identifier, expression, and condition resolution
internal/sql/planner/resolve.go, internal/sql/planner/typecheck.go, internal/sql/planner/plan_expressions.go, internal/sql/planner/plan_conditions.go, internal/sql/planner/*_test.go
Resolves catalog names and typed expressions or predicates, validates scopes and types, supports aggregate functions, and tests diagnostics and resolved nodes.
SELECT relational planning and grouping
internal/sql/planner/aggregate.go, internal/sql/planner/plan_queries.go, internal/sql/planner/plan_queries_test.go
Builds scan, join, filter, projection, aggregation, distinct, sort, and limit trees, including wildcard expansion, aliases, ORDER BY resolution, HAVING, and GROUP BY validation.
DDL and DML planning
internal/sql/planner/plan_statements.go, internal/sql/planner/plan_statements_test.go
Plans database and table operations plus INSERT, UPDATE, and DELETE statements, including schema construction, alterations, defaults, column validation, foreign-key checks, and type validation.
Coverage reporting support
README.md
Updates the coverage badge endpoint.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Planner
  participant Catalog
  participant PlanContext
  participant LogicalPlan
  Client->>Planner: Submit AST statement
  Planner->>PlanContext: Create planning context
  PlanContext->>Catalog: Resolve databases, tables, and columns
  Catalog-->>PlanContext: Return catalog metadata
  PlanContext->>LogicalPlan: Construct resolved plan tree
  LogicalPlan-->>Planner: Return plan and diagnostics
  Planner-->>Client: Return planning result
Loading

Assessment against linked issues

Objective Addressed Explanation
Translate SELECT AST nodes into resolved relational operator trees [#36]
Translate INSERT, UPDATE, and DELETE statements with scope and type validation [#36]
Translate DDL statements into catalog-ready plans and schema metadata [#36]
Provide self-contained plans with semantic diagnostics [#36]

Out-of-scope changes

Code Change Explanation
Coverage badge endpoint update (README.md:13) The linked issue specifies planner implementation and validation, not README coverage reporting.

Merge Risk: ⚪ Minimal · up to 16760

This PR adds SQL planning and statement validation without any identified merge-blocking issue; it is merge-ready after normal checks and review.


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

Comment @coderabbitai help to get the list of available commands.

@rahulc0dy rahulc0dy changed the title Implement SQL name resolution logic @coderabbitai Jul 10, 2026
@Souvik606
Souvik606 self-requested a review July 13, 2026 15:47
@rahulc0dy
rahulc0dy marked this pull request as ready for review July 15, 2026 14:44
@coderabbitai coderabbitai Bot changed the title @coderabbitai Implement SQL Planner for Logical Plans and Statement Validation Jul 15, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/sql/planner/statements.go (1)

167-168: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Run goimports before merging.

The committed file fails the required lint check at Line 167. Apply goimports to remove the formatting discrepancy.

goimports -w internal/sql/planner/statements.go

Sources: Linters/SAST tools, Pipeline failures

🧹 Nitpick comments (1)
internal/sql/planner/plan_statements_test.go (1)

267-306: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing coverage for ADD COLUMN ... UNIQUE / ... PRIMARY KEY rejection.

planAlterSchema's AlterAdd case has dedicated "not supported in v1" diagnostics for Unique and PrimaryKey columns, but no test here exercises either path (only the NOT-NULL-without-default and duplicate-column paths are covered).

func TestPlanAlterTable_AddUniqueColumn_Errors(t *testing.T) {
	pc := newPlanContext(testCatalog(), Session{ActiveDatabase: "shop"}, nil)
	stmt := &ast.AlterTableStmt{
		Table:  ident("users"),
		Action: &ast.AlterAction{Kind: ast.AlterAdd, Column: colDef("email", ast.TypeText, &ast.UniqueConstraint{})},
	}
	_, err := pc.planAlterTable(stmt)
	if err == nil || pc.diag[len(pc.diag)-1].Code != CodeUnsupportedAlter {
		t.Errorf("expected CodeUnsupportedAlter, got err=%v diag=%+v", err, pc.diag)
	}
}

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8dbf5033-632c-4ebb-8109-c14f73ba7f10

📥 Commits

Reviewing files that changed from the base of the PR and between 3f01808 and 5e3ba6c.

📒 Files selected for processing (19)
  • internal/sql/planner/.gitkeep
  • internal/sql/planner/aggregate.go
  • internal/sql/planner/conditions.go
  • internal/sql/planner/errors.go
  • internal/sql/planner/expressions.go
  • internal/sql/planner/operators.go
  • internal/sql/planner/plan_conditions.go
  • internal/sql/planner/plan_conditions_test.go
  • internal/sql/planner/plan_expressions.go
  • internal/sql/planner/plan_expressions_test.go
  • internal/sql/planner/plan_queries.go
  • internal/sql/planner/plan_queries_test.go
  • internal/sql/planner/plan_statements.go
  • internal/sql/planner/plan_statements_test.go
  • internal/sql/planner/planner.go
  • internal/sql/planner/resolve.go
  • internal/sql/planner/resolve_test.go
  • internal/sql/planner/statements.go
  • internal/sql/planner/typecheck.go

Comment thread internal/sql/planner/aggregate.go
Comment thread internal/sql/planner/plan_expressions.go
Comment thread internal/sql/planner/plan_queries.go
Comment thread internal/sql/planner/plan_queries.go Outdated
Comment thread internal/sql/planner/plan_statements.go Outdated
Comment thread internal/sql/planner/plan_statements.go
Comment thread internal/sql/planner/plan_statements.go Outdated
Comment thread internal/sql/planner/plan_statements.go
Comment thread internal/sql/planner/typecheck.go
@rahulc0dy

Copy link
Copy Markdown
Member Author

/coverage

@github-actions

Copy link
Copy Markdown

Coverage report (a0a677a)

Packages changed in this PR:

Package Coverage Statements
internal/sql/planner 81.4% 717/881
TOTAL (PR-affected) 81.4% 717/881
Treemap — by file

coverage treemap by file

Box size = statements per file. Color = coverage heat, red (low) → green (high).

Treemap — by package (with %)

coverage treemap by package

Box size = statements per package. Color = coverage heat, red (low) → green (high).

@rahulc0dy

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d0f230f9-5090-44b1-85dc-1f0848b98004

📥 Commits

Reviewing files that changed from the base of the PR and between d0aaa4c and a0a677a.

📒 Files selected for processing (11)
  • internal/sql/planner/aggregate.go
  • internal/sql/planner/errors.go
  • internal/sql/planner/plan_conditions.go
  • internal/sql/planner/plan_conditions_test.go
  • internal/sql/planner/plan_expressions.go
  • internal/sql/planner/plan_expressions_test.go
  • internal/sql/planner/plan_queries.go
  • internal/sql/planner/plan_queries_test.go
  • internal/sql/planner/plan_statements.go
  • internal/sql/planner/plan_statements_test.go
  • internal/sql/planner/typecheck.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • internal/sql/planner/aggregate.go
  • internal/sql/planner/plan_expressions.go
  • internal/sql/planner/typecheck.go
  • internal/sql/planner/plan_queries.go
  • internal/sql/planner/plan_expressions_test.go

Comment thread internal/sql/planner/plan_conditions.go Outdated
Comment thread internal/sql/planner/plan_statements.go

@Souvik606 Souvik606 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please check following reviews and do the needful.

Comment on lines +70 to +77
// ResolvedNullLiteral is a resolved NULL literal. It is compatible with
// every type and every operator; callers must check for this type (via
// isNullExpr) before consulting ResolvedType, whose return value here is a
// meaningless placeholder.
type ResolvedNullLiteral struct{}

func (*ResolvedNullLiteral) resolvedExprNode() {}
func (*ResolvedNullLiteral) ResolvedType() ast.DataTypeKind { return ast.TypeInt }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If any developer or future helper calls e.ResolvedType() directly without first checking isNullExpr(e), NULL will be silently treated as an INT. This can cause corrupt type coercion, invalid arithmetic promotion, or improper formatting in execution results.

Add a dedicated ast.TypeNull to DataTypeKind instead of returning a misleading TypeInt placeholder.

Comment on lines +82 to +84
type ResolvedColumnRef struct {
Column *ResolvedColumn
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If any pass in the planner or executor mutates a ResolvedColumn in place (e.g. changing Index, Name, or Type), it mutates all references across the plan simultaneously without thread/memory safety.

Store ResolvedColumn by value or mark it immutable or think of some brilliant idea

type ResolvedComparison struct {
ResolvedCondBase
Left ResolvedExpr
Op utils.TokenType

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tightly couples planner structs to raw lexer token constants.Planner should just have idea about its previous stage i.e parser stage.

Define an explicit planner operator enum.

// completes and ResolvedExpr/ResolvedCond trees deliberately carry no
// equivalent — by the time those are built, any problem they'd have
// caused has already been turned into a diagnostic.
Span diagnostic.Span

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Span is only used during planning error checks. Retaining Span on every ProjectItem inflates struct memory footprint during execution across large projection lists.

Strip Span after planning completes, or keep it in a temporary planning wrapper struct.

Comment on lines +119 to +120
Count int
Offset int

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Count and Offset are typed as signed int.Allows negative values (e.g. Count = -5, Offset = -10) to be represented in the struct if validation fails or is bypassed.

Use int64 with non-negative validation or uint64

Comment on lines +136 to +137
Columns []*ResolvedColumn
Rows [][]ResolvedExpr

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

InsertPlan contains both Rows [][]ResolvedExpr (for VALUES) and Source *QueryPlan (for INSERT ... SELECT).
The struct permits invalid states where both Rows and Source are non-nil, or both are nil. The Go type system cannot enforce mutual exclusion.

Write a validator to enforce mutual exclusion like its written at AST level.

type DropDatabasePlan struct {
PlanBase
Name string
Tables []*catalog.TableMeta

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The executor only needs table names to delete keys. Holding full *catalog.TableMeta pointers needlessly pins large catalog schema trees in memory.

Store a slice of table names Tables []string instead of full metadata pointers.

Comment on lines +19 to +21
type Session struct {
ActiveDatabase string
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Session struct contains only ActiveDatabase string.It cannot pass connection context (context.Context), query execution timeouts etc

Expand Session struct:

type Session struct {
ActiveDatabase string
Ctx context.Context
}

Need to check context cancellation stuffs in the concrete planner implementation codes too.Do it comfortably.

@Souvik606
Souvik606 self-requested a review August 15, 2026 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Planner to Translate ASTs into Logical Plan Trees

3 participants