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
impl PostgresProjectionGenerator
Sourcepub fn new() -> PostgresProjectionGenerator
pub fn new() -> PostgresProjectionGenerator
Create new PostgreSQL projection generator with default JSONB column name.
Default JSONB column: “data”
Sourcepub fn with_column(jsonb_column: &str) -> PostgresProjectionGenerator
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
Sourcepub fn generate_projection_sql(
&self,
fields: &[String],
) -> Result<String, FraiseQLError>
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.
Sourcepub fn generate_typed_projection_sql(
&self,
fields: &[ProjectionField],
) -> Result<String, FraiseQLError>
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.
Sourcepub fn generate_merged_projection_sql(
&self,
computed: &[ProjectionField],
) -> Result<String, FraiseQLError>
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.
Sourcepub fn generate_select_clause(
&self,
table_alias: &str,
fields: &[String],
) -> Result<String, FraiseQLError>
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 clausefields- 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.