Skip to content

feat: establish RockQL compiler foundation - #1

Merged
SayanthRock merged 29 commits into
mainfrom
feat/compiler-foundation
Jul 25, 2026
Merged

feat: establish RockQL compiler foundation#1
SayanthRock merged 29 commits into
mainfrom
feat/compiler-foundation

Conversation

@SayanthRock

@SayanthRock SayanthRock commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Creates the first functional RockQL compiler foundation in Rust.

Included

  • Rust workspace with separate AST, parser, SQL generator, and CLI crates.
  • Initial transformations: from, filter, select, derive, sort, and take.
  • Multiline and |-separated pipeline syntax.
  • Line and column diagnostics.
  • Generic SQL, SQLite, and PostgreSQL targets.
  • rockql compile, check, ast, and format commands.
  • Canonical formatter output.
  • Parser and SQL generator tests.
  • README, example query, and contribution guide.
  • Rust formatting, Clippy, tests, release build, and example compilation in CI.
  • Dependency review and CodeQL v4 scanning for Rust.

Example

echo "from users | filter active == true | take 10" \
  | rockql compile --target sqlite
SELECT *
FROM users
WHERE active = TRUE
LIMIT 10;

Scope boundaries

This PR intentionally does not add joins, grouping, aggregation, type resolution, relational IR, WebAssembly, the web playground, Android, desktop, or release packaging. Those should build on this reviewed compiler boundary rather than being added as placeholders.

Validation

  • Rust formatting: passed.
  • Clippy with warnings denied: passed.
  • Workspace tests: passed.
  • Release CLI build: passed.
  • Included example compilation: passed.
  • Security workflow: configured; the latest run is pending repository-level approval/queueing and has not created jobs yet.

The branch uses Rust 1.97.1 because current Clap releases require stable Rust 2024 Cargo support.

Summary by CodeRabbit

  • New Features

    • Added RockQL command-line tools to compile, validate, inspect, and format queries.
    • Added support for filters, selections, derived fields, sorting, row limits, and SQL output for multiple dialects.
    • Added an employee query example.
  • Documentation

    • Expanded usage guidance, syntax reference, roadmap, and contribution guidelines.
  • Quality & Security

    • Added automated formatting, linting, testing, build, dependency, and code security checks.
    • Standardized Rust toolchain and ignored common local build artifacts.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR establishes a Rust workspace for RockQL, adds AST, parser, SQL compiler, and CLI crates, documents syntax and contribution practices, includes an example query, and configures CI and security workflows.

Changes

RockQL compiler foundation

Layer / File(s) Summary
Workspace and project contracts
Cargo.toml, rust-toolchain.toml, .gitignore, CONTRIBUTING.md, README.md, examples/employees.rockql, compiler/rockql-ast/Cargo.toml
The repository defines shared Rust metadata, toolchain settings, project documentation, contribution guidance, ignore rules, and an example query.
AST model and serialization
compiler/rockql-ast/src/lib.rs
The AST crate defines spans, query pipelines, transformations, sort items, serialization, and textual rendering.
Pipeline parsing and formatting
compiler/rockql-parser/Cargo.toml, compiler/rockql-parser/src/lib.rs
The parser handles multiline and pipe-separated transformations, diagnostics, canonical formatting, and parser tests.
SQL compilation and CLI commands
compiler/rockql-sql/*, compiler/rockql-cli/*
The SQL crate supports dialect selection, pipeline compilation, expression normalization, and SQL tests; the CLI exposes compile, check, AST, and format commands.
CI and security validation
.github/workflows/ci.yml, .github/workflows/security.yml
GitHub Actions workflows automate formatting, linting, tests, builds, example compilation, dependency review, and CodeQL analysis.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant rockql_cli
  participant rockql_parser
  participant rockql_sql
  User->>rockql_cli: Submit RockQL source and dialect
  rockql_cli->>rockql_parser: Parse source
  rockql_parser-->>rockql_cli: Return Query or diagnostics
  rockql_cli->>rockql_sql: Compile Query for dialect
  rockql_sql-->>rockql_cli: Return SQL or error
  rockql_cli-->>User: Print result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main change: establishing the initial RockQL compiler foundation.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/compiler-foundation

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

@ai-coding-guardrails

Copy link
Copy Markdown

You've hit your review limit for the week, but don't worry you'll get some more next week!

Contact us at hello@zenable.io if you want this rate limit to go away

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@github-actions

Copy link
Copy Markdown
Contributor

rustfmt changes required

diff --git a/compiler/rockql-parser/src/lib.rs b/compiler/rockql-parser/src/lib.rs
index e441dc9..6b22432 100644
--- a/compiler/rockql-parser/src/lib.rs
+++ b/compiler/rockql-parser/src/lib.rs
@@ -72,7 +72,12 @@ fn split_segments(source: &str) -> Vec<Segment> {
 
         for (byte_index, character) in line.char_indices() {
             if character == '|' {
-                push_segment(&mut segments, &line[start..byte_index], line_index + 1, start);
+                push_segment(
+                    &mut segments,
+                    &line[start..byte_index],
+                    line_index + 1,
+                    start,
+                );
                 start = byte_index + character.len_utf8();
             }
         }
@@ -157,10 +162,7 @@ fn parse_select(rest: &str, span: Span) -> Result<Transform, Diagnostic> {
 
 fn parse_derive(rest: &str, span: Span) -> Result<Transform, Diagnostic> {
     let Some((name, expression)) = rest.split_once('=') else {
-        return Err(Diagnostic::new(
-            "expected `derive name = expression`",
-            span,
-        ));
+        return Err(Diagnostic::new("expected `derive name = expression`", span));
     };
 
     let name = name.trim();
@@ -181,12 +183,7 @@ fn parse_sort(rest: &str, span: Span) -> Result<Transform, Diagnostic> {
     let inner = match (rest.strip_prefix('{'), rest.strip_suffix('}')) {
         (Some(without_open), Some(_)) => &without_open[..without_open.len().saturating_sub(1)],
         (None, None) => rest,
-        _ => {
-            return Err(Diagnostic::new(
-                "sort braces must be balanced",
-                span,
-            ))
-        }
+        _ => return Err(Diagnostic::new("sort braces must be balanced", span)),
     };
 
     let items = inner
@@ -217,9 +214,10 @@ fn parse_sort(rest: &str, span: Span) -> Result<Transform, Diagnostic> {
 fn parse_take(rest: &str, span: Span) -> Result<Transform, Diagnostic> {
     require_value(rest, "expected a row count after `take`", span)?;
 
-    let count = rest.replace('_', "").parse::<u64>().map_err(|_| {
-        Diagnostic::new("`take` requires a non-negative integer row count", span)
-    })?;
+    let count = rest
+        .replace('_', "")
+        .parse::<u64>()
+        .map_err(|_| Diagnostic::new("`take` requires a non-negative integer row count", span))?;
 
     Ok(Transform::Take { count })
 }
@@ -253,8 +251,8 @@ mod tests {
 
     #[test]
     fn parses_pipe_separated_pipeline() {
-        let query = parse("from users | filter active == true | take 10")
-            .expect("query should parse");
+        let query =
+            parse("from users | filter active == true | take 10").expect("query should parse");
 
         assert_eq!(query.transforms.len(), 3);
         assert_eq!(query.transforms[1].span, Span::new(1, 14));
@@ -262,8 +260,8 @@ mod tests {
 
     #[test]
     fn reports_line_and_column() {
-        let diagnostics = parse("from users\n  unknown value")
-            .expect_err("unknown transformation should fail");
+        let diagnostics =
+            parse("from users\n  unknown value").expect_err("unknown transformation should fail");
 
         assert_eq!(diagnostics[0].span, Span::new(2, 3));
         assert!(diagnostics[0].message.contains("unknown transformation"));
@@ -271,12 +269,9 @@ mod tests {
 
     #[test]
     fn formats_to_canonical_multiline_source() {
-        let formatted = format_source("from users | sort {-created_at} | take 5")
-            .expect("query should format");
+        let formatted =
+            format_source("from users | sort {-created_at} | take 5").expect("query should format");
 
-        assert_eq!(
-            formatted,
-            "from users\nsort {-created_at}\ntake 5\n"
-        );
+        assert_eq!(formatted, "from users\nsort {-created_at}\ntake 5\n");
     }
 }
diff --git a/compiler/rockql-sql/src/lib.rs b/compiler/rockql-sql/src/lib.rs
index 8d56f24..ed1f931 100644
--- a/compiler/rockql-sql/src/lib.rs
+++ b/compiler/rockql-sql/src/lib.rs
@@ -39,7 +39,9 @@ impl FromStr for Dialect {
 pub enum SqlError {
     #[error("query must start with a `from` transformation")]
     MissingFrom,
-    #[error("only one `from` transformation is currently supported (line {line}, column {column})")]
+    #[error(
+        "only one `from` transformation is currently supported (line {line}, column {column})"
+    )]
     MultipleFrom { line: usize, column: usize },
 }
 
@@ -245,21 +247,18 @@ mod tests {
 
     #[test]
     fn compiles_boolean_filter_for_sqlite() {
-        let query = parse("from users | filter active == true | take 10")
-            .expect("query should parse");
+        let query =
+            parse("from users | filter active == true | take 10").expect("query should parse");
 
         let sql = compile(&query, Dialect::Sqlite).expect("query should compile");
 
-        assert_eq!(
-            sql,
-            "SELECT *\nFROM users\nWHERE active = TRUE\nLIMIT 10;"
-        );
+        assert_eq!(sql, "SELECT *\nFROM users\nWHERE active = TRUE\nLIMIT 10;");
     }
 
     #[test]
     fn preserves_keywords_inside_strings() {
-        let query = parse("from events | filter label == \"true and false\"")
-            .expect("query should parse");
+        let query =
+            parse("from events | filter label == \"true and false\"").expect("query should parse");
 
         let sql = compile(&query, Dialect::Generic).expect("query should compile");
 

@SayanthRock
SayanthRock marked this pull request as ready for review July 25, 2026 20:31
Copilot AI review requested due to automatic review settings July 25, 2026 20:31
@ai-coding-guardrails

Copy link
Copy Markdown

You've hit your review limit for the week, but don't worry you'll get some more next week!

Contact us at hello@zenable.io if you want this rate limit to go away

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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: 6

🤖 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 @.github/workflows/ci.yml:
- Around line 20-21: Update the actions/checkout@v4 steps in both the CI and
security workflows to disable credential persistence, while leaving the existing
checkout behavior unchanged. Set persist-credentials to false for each checkout
action.

In @.github/workflows/security.yml:
- Around line 35-36: Update the Checkout step in the codeql job to disable
persisted credentials, matching the shared fix applied in ci.yml. Configure the
existing actions/checkout@v4 step with the appropriate persist-credentials
setting.
- Around line 22-23: Update the Checkout step in the dependency-review job of
security.yml to disable persisted credentials, matching the shared fix applied
in the CI workflow. Configure the existing actions/checkout@v4 step with the
appropriate persist-credentials setting while leaving the rest of the job
unchanged.

In `@compiler/rockql-parser/src/lib.rs`:
- Around line 67-102: Update split_segments to track whether scanning is inside
a quoted string, following the quote-handling pattern used by
normalize_keywords, and only treat | as a separator outside string literals.
Preserve push_segment trimming and span calculations, including support for
escaped quote characters as applicable to the existing literal syntax.

In `@compiler/rockql-sql/src/lib.rs`:
- Around line 154-179: Update normalize_expression and the normalization helpers
so numeric-separator removal and !=/== operator replacement occur within the
same quote-aware character walk used by normalize_keywords. Preserve all
characters inside quoted spans—including underscores and operator
sequences—while applying these transformations only outside quotes; remove or
bypass the current raw-string processing in remove_numeric_separators and
normalize_expression.

In `@README.md`:
- Line 141: Update the v0.3 roadmap entry in README.md to remove PostgreSQL if
it refers to already implemented output, or qualify it as expanded PostgreSQL
support; keep only genuinely future features such as MySQL alongside the
existing roadmap items.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 793dd4d3-a058-4c73-8d90-254abbef0a37

📥 Commits

Reviewing files that changed from the base of the PR and between 73cf1aa and 9f110cc.

📒 Files selected for processing (16)
  • .github/workflows/ci.yml
  • .github/workflows/security.yml
  • .gitignore
  • CONTRIBUTING.md
  • Cargo.toml
  • README.md
  • compiler/rockql-ast/Cargo.toml
  • compiler/rockql-ast/src/lib.rs
  • compiler/rockql-cli/Cargo.toml
  • compiler/rockql-cli/src/main.rs
  • compiler/rockql-parser/Cargo.toml
  • compiler/rockql-parser/src/lib.rs
  • compiler/rockql-sql/Cargo.toml
  • compiler/rockql-sql/src/lib.rs
  • examples/employees.rockql
  • rust-toolchain.toml

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/security.yml
Comment thread .github/workflows/security.yml
Comment thread compiler/rockql-parser/src/lib.rs
Comment thread compiler/rockql-sql/src/lib.rs
Comment thread README.md

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f110ccaf7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread compiler/rockql-sql/src/lib.rs
Comment thread compiler/rockql-sql/src/lib.rs
Comment thread compiler/rockql-sql/src/lib.rs
Comment thread compiler/rockql-parser/src/lib.rs
Comment thread compiler/rockql-sql/src/lib.rs
Comment thread compiler/rockql-sql/src/lib.rs
Comment thread compiler/rockql-parser/src/lib.rs
Comment thread compiler/rockql-parser/src/lib.rs
Comment thread compiler/rockql-parser/src/lib.rs
Comment thread compiler/rockql-parser/src/lib.rs
@SayanthRock
SayanthRock merged commit f3f7a2f into main Jul 25, 2026
6 of 9 checks passed
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.

3 participants