Skip to main content

PostgresProjectionGenerator

Struct PostgresProjectionGenerator 

Source
pub struct PostgresProjectionGenerator { /* private fields */ }
Expand description

PostgreSQL SQL projection generator using jsonb_build_object.

Generates efficient PostgreSQL SQL that projects only requested JSONB fields, reducing payload size and JSON deserialization time.

Implementations§

Source§

impl PostgresProjectionGenerator

Source

pub fn new() -> PostgresProjectionGenerator

Create new PostgreSQL projection generator with default JSONB column name.

Default JSONB column: “data”

Source

pub fn with_column(jsonb_column: &str) -> PostgresProjectionGenerator

Create projection generator with custom JSONB column name.

§Arguments
  • jsonb_column - Name of the JSONB column in the database table
Source

pub fn generate_projection_sql( &self, fields: &[String], ) -> Result<String, FraiseQLError>

Generate PostgreSQL projection SQL for specified fields.

Generates a jsonb_build_object() call that selects only the requested fields from the JSONB column, drastically reducing payload size.

§Arguments
  • fields - GraphQL field names to project from JSONB
§Returns

SQL fragment that can be used in a SELECT clause, e.g.: jsonb_build_object('id', data->>'id', 'email', data->>'email')

§Example
use fraiseql_db::projection_generator::PostgresProjectionGenerator;
let generator = PostgresProjectionGenerator::new();
let fields = vec!["id".to_string(), "email".to_string()];
let sql = generator.generate_projection_sql(&fields)?;
// Returns:
// jsonb_build_object('id', data->>'id', 'email', data->>'email')
assert!(sql.contains("jsonb_build_object"));
§Errors

Returns FraiseQLError::Validation if any field name contains characters that cannot be safely included in a SQL projection.

Source

pub fn generate_typed_projection_sql( &self, fields: &[ProjectionField], ) -> Result<String, FraiseQLError>

Generate type-aware PostgreSQL projection SQL.

Uses -> (JSONB extraction) for composite fields (objects, lists) and ->> (text extraction) for scalar fields. This avoids the unnecessary text→JSON round-trip that occurs when ->> is used for nested objects.

When a composite field carries sub_fields, the generator recurses and emits a nested jsonb_build_object(...) that selects only the requested sub-fields rather than returning the entire blob, at every depth. sub_fields of Some(vec![]) selects nothing of the object and renders jsonb_build_object(). There is no depth cap: the fields follow a selection, which the caller bounds (max_query_depth), and a cap that fell back to data->'field' served every stored key of the object below it. PostgreSQL 16’s parser refuses a nest of 2 044 jsonb_build_object levels (memory exhausted), two orders of magnitude above any bound a caller sets.

§Arguments
  • fields - Projection fields with type information

An empty field list projects an empty object, not the JSONB column. “Nothing was requested” and “everything was requested” are opposite answers, and returning the whole column for the first is how a node(id:) lookup whose selection resolved to nothing served every column in the view (#827).

§Errors

Returns FraiseQLError::Validation if any field name contains characters that cannot be safely included in a SQL projection.

Source

pub fn generate_merged_projection_sql( &self, computed: &[ProjectionField], ) -> Result<String, FraiseQLError>

Project the whole JSONB column plus a set of computed fields (#959).

"data" || jsonb_build_object('similarity', (…)). Used where the row has to come back whole — a policy-gated field needs the full parent to decide on, and the stream strategy returns the stored blob — but a computed value still has to reach the response. Concatenation, so a computed key that collides with a stored one wins, which is the only reading that matches what the caller asked for.

§Errors

Returns FraiseQLError::Validation if a field name cannot be safely projected.

Source

pub fn generate_select_clause( &self, table_alias: &str, fields: &[String], ) -> Result<String, FraiseQLError>

Generate complete SELECT clause with projection for a table.

§Arguments
  • table_alias - Table alias or name in the FROM clause
  • fields - Fields to project
§Returns

Complete SELECT clause, e.g.: SELECT jsonb_build_object(...) as data

§Example
use fraiseql_db::projection_generator::PostgresProjectionGenerator;

let generator = PostgresProjectionGenerator::new();
let fields = vec!["id".to_string(), "name".to_string()];
let sql = generator.generate_select_clause("t", &fields).unwrap();
assert!(sql.contains("SELECT"));
§Errors

Propagates any error from Self::generate_projection_sql.

Trait Implementations§

Source§

impl Default for PostgresProjectionGenerator

Source§

fn default() -> PostgresProjectionGenerator

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more