Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,22 @@ jobs:
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- name: Execute complete SQLite groups and unchanged aggregate behavior
run: cargo test -p graphql-orm --locked --no-default-features --features sqlite --lib --test complete_group_pages --test grouped_aggregates
- name: Execute complete SQLite groups and authorized aggregates
run: cargo test -p graphql-orm --locked --no-default-features --features sqlite --lib --test complete_group_pages --test portable_group_pages --test grouped_aggregates
- name: Execute the dependency-minimal private repository example
run: cargo run --manifest-path crates/graphql-orm/tests/fixtures/repository-aggregate-consumer/Cargo.toml --locked --no-default-features --features sqlite --example complete_events
- name: Verify unsupported profiles before pool I/O
run: |
cargo test -p graphql-orm --locked --no-default-features --features postgres --lib --test complete_group_pages_unsupported
cargo test -p graphql-orm --locked --no-default-features --features postgres --lib
cargo test -p graphql-orm --locked --no-default-features --features mssql --lib --test complete_group_pages_unsupported
- name: Execute existing aggregates on a test-owned PostgreSQL container
run: cargo test -p graphql-orm --locked --no-default-features --features postgres --test grouped_aggregates_postgres -- --ignored --test-threads=1
run: cargo test -p graphql-orm --locked --no-default-features --features postgres --test grouped_aggregates_postgres --test portable_group_pages -- --ignored --test-threads=1
- name: Execute the private PostgreSQL consumer without query SQL
run: cargo test --manifest-path crates/graphql-orm/tests/fixtures/repository-aggregate-consumer/Cargo.toml --locked --no-default-features --features postgres --test portable_groups -- --ignored --test-threads=1
- name: Check explicit backend Clippy and Rustdoc lanes
run: |
for backend in sqlite postgres mssql; do
cargo clippy -p graphql-orm -p graphql-orm-macros --locked --no-default-features --features "$backend" --lib --test complete_group_pages --test complete_group_pages_unsupported -- -D warnings
cargo clippy -p graphql-orm -p graphql-orm-macros --locked --no-default-features --features "$backend" --lib --test complete_group_pages --test portable_group_pages --test complete_group_pages_unsupported -- -D warnings
RUSTDOCFLAGS="-D warnings" cargo doc -p graphql-orm -p graphql-orm-macros --locked --no-default-features --features "$backend" --no-deps
done
cargo clippy --manifest-path crates/graphql-orm/tests/fixtures/repository-aggregate-consumer/Cargo.toml --locked --no-default-features --features sqlite --all-targets -- -D warnings
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,10 @@ jobs:
cargo check -p graphql-orm --no-default-features --features postgres --locked
cargo test -p graphql-orm --no-default-features --features postgres --test federation_entity_keys_postgres --locked
cargo test -p graphql-orm --no-default-features --features postgres --test projection_visibility --test cross_crate_relations_fixture --test repository_counts --locked
cargo test -p graphql-orm --no-default-features --features postgres --test grouped_aggregates_postgres --locked -- --ignored --test-threads=1
cargo test -p graphql-orm --no-default-features --features postgres --test grouped_aggregates_postgres --test portable_group_pages --locked -- --ignored --test-threads=1
cargo run --manifest-path crates/graphql-orm/tests/fixtures/repository-aggregate-consumer/Cargo.toml --locked --no-default-features --features sqlite --example policy_projections
cargo run --manifest-path crates/graphql-orm/tests/fixtures/repository-aggregate-consumer/Cargo.toml --locked --no-default-features --features sqlite --example complete_events
cargo test --manifest-path crates/graphql-orm/tests/fixtures/repository-aggregate-consumer/Cargo.toml --locked --no-default-features --features postgres --test portable_groups -- --ignored --test-threads=1
cargo check -p graphql-orm --no-default-features --features mssql --locked
cargo test -p graphql-orm --no-default-features --features mssql --test federation_entity_keys_mssql --locked
cargo clippy -p graphql-orm --all-targets --locked -- -D warnings
Expand Down
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "Changelog"
kind: reference
status: active
owner: workspace-maintainers
last_reviewed: 2026-10-01
last_reviewed: 2026-10-02
review_by: 2027-02-01
supersedes: []
---
Expand All @@ -14,6 +14,25 @@ This file is the authoritative user-facing release chronology. The former
[release-notes ledger](docs/archive/2026/graphql-orm-release-notes.md) is retained
for historical context.

## 0.38.0 - Unreleased

Companion macros crate: `graphql-orm-macros` **0.38.0**.

- Add PostgreSQL `fetch_group_page` execution for one TEXT/VARCHAR grouping
field, preserving exact original values with explicit bytewise equality and
ASCII-only case-insensitive ordering plus a binary tie-breaker. Preserve
SQLite native group equality, ordering, cursor wire format and page bounds.
- Let ordinary aggregates, including ungrouped COUNT/SUM and GraphQL aggregate
roots, consume current explicit unrestricted or complete SQL read visibility.
Intersect policy and caller predicates before grouping; retain entity/field
authority and reject residual authorization before query execution.
- Add a provided aggregate entity-identity hook, generated by the macro without
requiring changes to existing handwritten aggregate-field implementations.
- Execute over 1,000-group SQLite/PostgreSQL parity, nullable/metric/cursor/policy
regressions and a framework-neutral standalone event-enumeration example.
MSSQL pages remain explicitly unsupported. Separate reads do not constitute a
cross-request snapshot under concurrent writes; see the aggregate reference.

## 0.35.2 - 2026-10-01

- Keep standalone fixture lockfiles aligned with this package set and execute
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ cynic-parser = { version = "=0.11.2", features = ["pretty"] }
futures = "0.3"
getrandom = "0.3"
graphql-composition = "=0.12.2"
graphql-orm = { path = "crates/graphql-orm", version = "0.35.2", default-features = false }
graphql-orm = { path = "crates/graphql-orm", version = "0.38.0", default-features = false }
graphql-orm-ai-tool-profiles = { path = "crates/graphql-orm-ai-tool-profiles", version = "0.15.0" }
graphql-orm-backup = { path = "crates/graphql-orm-backup", version = "0.7.2", default-features = false }
graphql-orm-operation-catalog = { path = "crates/graphql-orm-operation-catalog", version = "0.4.0" }
Expand Down
30 changes: 29 additions & 1 deletion MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "Migration Guide"
kind: reference
status: active
owner: workspace-maintainers
last_reviewed: 2026-10-01
last_reviewed: 2026-10-02
review_by: 2027-02-01
supersedes: []
---
Expand All @@ -13,6 +13,34 @@ supersedes: []
`graphql-orm` is distributed from GitHub only. Use a reviewed full 40-character commit in `rev`;
neither the runtime nor macros crate is published to crates.io.

## Portable group pages and SQL-visible aggregates (0.38.0)

Adopt aligned ORM/macros 0.38.0. No physical schema, data, GraphQL SDL, existing
SQLite cursor wire format or call-site change is required. `fetch_group_page`
remains supported. PostgreSQL now supports single TEXT/VARCHAR group pages:
`Binary` uses bytewise `C` comparison; the retained `SqliteNoCase` variant uses
explicit ASCII A–Z folding then bytewise original-value tie-breaking. PostgreSQL
page grouping uses exact original text equality, independently of source collation;
ordinary aggregates and SQLite page native equality remain unchanged.

An installed row policy no longer automatically blocks ordinary `fetch`: current
`Unrestricted` or `Complete` visibility is required, with policy and caller filters
intersected before aggregation. Residual/callback-only policies still fail closed.
Generated aggregate-field enums supply an entity TypeId through a provided hook;
handwritten enums remain compatible, but must implement `entity_type_id` correctly
to use complete SQL visibility. Unrestricted visibility needs no token.

Keep trusted authorization/public-revision context in page requests, protect
host cursor envelopes as appropriate, and recheck current policy on every call.
Page cursors do not pin a database snapshot. Concurrent insertion/deletion/renaming
can change a multi-page enumeration; refresh from None when refreshing the dropdown.
MSSQL pages and other scalar/multiple grouping keys reject before I/O. Existing
MSSQL ordinary aggregate/provider/schema gates are unchanged.

See [provider, authorization, wire and consistency contract](docs/reference/graphql-orm/typed-aggregates.md)
and its executable standalone example and owned PostgreSQL test. This capability
is independent of runtime contracts A–D and host-managed repository timestamps.

## Policy-aware transaction counts (0.35.2)

Adopt aligned runtime/macros 0.35.2. No schema, stored-data, public API or
Expand Down
2 changes: 1 addition & 1 deletion crates/graphql-orm-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphql-orm-macros"
version = "0.35.2"
version = "0.38.0"
edition = "2024"
authors = ["Toby Martin"]
description = "Procedural macros for async-graphql and ORM-backed entities, relations, and CRUD operations."
Expand Down
8 changes: 5 additions & 3 deletions crates/graphql-orm-macros/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "graphql-orm-macros"
kind: reference
status: active
owner: graphql-orm-macros-maintainers
last_reviewed: 2026-10-01
last_reviewed: 2026-10-02
review_by: 2027-02-01
supersedes: []
---
Expand All @@ -16,13 +16,13 @@ macro/runtime versions aligned:

```toml
[dependencies]
graphql-orm = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.35.2", default-features = false, features = ["sqlite"] }
graphql-orm = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.38.0", default-features = false, features = ["sqlite"] }
```

Direct use is supported for tooling that needs the macro package:

```toml
graphql-orm-macros = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.35.2", default-features = false, features = ["sqlite"] }
graphql-orm-macros = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.38.0", default-features = false, features = ["sqlite"] }
```

The direct dependency still requires a compatible `graphql-orm` runtime in the
Expand Down Expand Up @@ -174,3 +174,5 @@ Version 0.35.1 generates projection identity for complete SQL row visibility and
aligns with the core policy-aware projection fix. Existing generated
aggregate enums/builders and ordinary GraphQL aggregate SDL remain unchanged;
repository-only consumers still need no direct async-graphql dependency.

Complete SQLite/PostgreSQL text-group pages and SQL-visible ordinary aggregates: see [typed aggregates](../../docs/reference/graphql-orm/typed-aggregates.md).

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/graphql-orm-macros/src/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4573,6 +4573,9 @@ fn generate_entity_impl(
impl ::graphql_orm::graphql::orm::TypedAggregateField<#struct_name>
for #aggregate_field_name
{
fn entity_type_id() -> Option<::std::any::TypeId> {
Some(::std::any::TypeId::of::<#struct_name>())
}
fn aggregate_field(self) -> &'static ::graphql_orm::graphql::orm::AggregateFieldRef {
match self {
#(#aggregate_field_match_arms),*
Expand Down
4 changes: 2 additions & 2 deletions crates/graphql-orm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graphql-orm"
version = "0.35.2"
version = "0.38.0"
edition = "2024"
description = "Runtime support crate for graphql-orm-macros"
license = "MIT"
Expand Down Expand Up @@ -68,7 +68,7 @@ futures = "0.3"
geo = { version = "0.33", optional = true, default-features = false }
geo-types = { version = "0.7", optional = true }
geojson = { version = "1", optional = true, default-features = true }
graphql-orm-macros = { path = "../graphql-orm-macros", version = "0.35.2", default-features = false }
graphql-orm-macros = { path = "../graphql-orm-macros", version = "0.38.0", default-features = false }
graphql-orm-operation-catalog = { workspace = true }
rust_decimal = { workspace = true }
serde = { version = "1", features = ["derive"] }
Expand Down
6 changes: 4 additions & 2 deletions crates/graphql-orm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "graphql-orm"
kind: reference
status: active
owner: graphql-orm-maintainers
last_reviewed: 2026-10-01
last_reviewed: 2026-10-02
review_by: 2027-02-01
supersedes: []
---
Expand All @@ -29,7 +29,7 @@ backend:

```toml
[dependencies]
graphql-orm = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.35.2", default-features = false, features = ["sqlite"] }
graphql-orm = { git = "https://github.com/Dastari/graphql-orm.git", rev = "<reviewed-full-40-character-commit-sha>", version = "0.38.0", default-features = false, features = ["sqlite"] }
```

This unpublished package has no docs.rs release. Use this Git README and the
Expand Down Expand Up @@ -192,3 +192,5 @@ Complete bounded SQLite text-group pages reuse generated aggregate enums and the
existing aggregate builder. See [typed aggregates](../../docs/reference/graphql-orm/typed-aggregates.md)
and the SQL-free private consumer example for native distinct identities, current
SQL visibility and typed continuation. Existing aggregate SDL/cursors are unchanged.

Complete SQLite/PostgreSQL text-group pages and SQL-visible ordinary aggregates: see [typed aggregates](../../docs/reference/graphql-orm/typed-aggregates.md).
20 changes: 20 additions & 0 deletions crates/graphql-orm/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,26 @@ impl<B: OrmBackend> Database<B> {
Ok(visibility)
}

pub(crate) async fn aggregate_read_visibility<T, A>(
&self,
ctx: Option<&async_graphql::Context<'_>>,
) -> async_graphql::Result<crate::graphql::orm::ReadVisibility>
where
T: crate::graphql::orm::Entity,
A: crate::graphql::orm::TypedAggregateField<T>,
{
let surface = if ctx.is_some() {
crate::graphql::orm::EntityAccessSurface::GraphqlQuery
} else {
crate::graphql::orm::EntityAccessSurface::Repository
};
let visibility = self
.read_visibility_for(T::metadata(), ctx, surface)
.await?;
visibility.validate_identity(A::entity_type_id(), B::DIALECT)?;
Ok(visibility)
}

async fn read_visibility_for(
&self,
metadata: &'static crate::graphql::orm::EntityMetadata,
Expand Down
Loading
Loading