Skip to main content

Qail

Struct Qail 

Source
pub struct Qail {
Show 40 fields pub action: Action, pub table: String, pub columns: Vec<Expr>, pub joins: Vec<Join>, pub cages: Vec<Cage>, pub distinct: bool, pub index_def: Option<IndexDef>, pub table_constraints: Vec<TableConstraint>, pub set_ops: Vec<(SetOp, Box<Qail>)>, pub having: Vec<Condition>, pub group_by_mode: GroupByMode, pub ctes: Vec<CTEDef>, pub distinct_on: Vec<Expr>, pub returning: Option<Vec<Expr>>, pub on_conflict: Option<OnConflict>, pub merge: Option<Merge>, pub source_query: Option<Box<Qail>>, pub channel: Option<String>, pub payload: Option<String>, pub savepoint_name: Option<String>, pub from_tables: Vec<String>, pub using_tables: Vec<String>, pub lock_mode: Option<LockMode>, pub skip_locked: bool, pub fetch: Option<(u64, bool)>, pub default_values: bool, pub overriding: Option<OverridingKind>, pub sample: Option<(SampleMethod, f64, Option<u64>)>, pub only_table: bool, pub vector: Option<Vec<f32>>, pub score_threshold: Option<f32>, pub vector_name: Option<String>, pub with_vector: bool, pub vector_size: Option<u64>, pub distance: Option<Distance>, pub on_disk: Option<bool>, pub function_def: Option<FunctionDef>, pub trigger_def: Option<TriggerDef>, pub policy_def: Option<RlsPolicy>, pub view_security_invoker: bool,
}
Expand description

The core Qail AST node representing a single database operation.

Fields§

§action: Action

SQL action to perform.

§table: String

Target table name.

§columns: Vec<Expr>

Selected / inserted / modified columns.

§joins: Vec<Join>

Join clauses.

§cages: Vec<Cage>

Filter / sort / group / limit cages.

§distinct: bool

SELECT DISTINCT.

§index_def: Option<IndexDef>

Index definition for CREATE INDEX.

§table_constraints: Vec<TableConstraint>

Table-level constraints (composite UNIQUE / PK).

§set_ops: Vec<(SetOp, Box<Qail>)>

UNION / INTERSECT / EXCEPT operations.

§having: Vec<Condition>

HAVING clause conditions.

§group_by_mode: GroupByMode

GROUP BY mode (simple, rollup, cube, grouping sets).

§ctes: Vec<CTEDef>

Common table expressions (WITH).

§distinct_on: Vec<Expr>

DISTINCT ON columns.

§returning: Option<Vec<Expr>>

RETURNING clause.

§on_conflict: Option<OnConflict>

ON CONFLICT clause for upsert.

§merge: Option<Merge>

PostgreSQL MERGE specification.

§source_query: Option<Box<Qail>>

INSERT … SELECT source query.

§channel: Option<String>

LISTEN/NOTIFY channel.

§payload: Option<String>

NOTIFY payload.

§savepoint_name: Option<String>

SAVEPOINT name.

§from_tables: Vec<String>

UPDATE … FROM additional tables.

§using_tables: Vec<String>

DELETE … USING additional tables.

§lock_mode: Option<LockMode>

Row locking (FOR UPDATE / FOR SHARE).

§skip_locked: bool

SKIP LOCKED modifier for row locking (FOR UPDATE SKIP LOCKED).

§fetch: Option<(u64, bool)>

FETCH FIRST n ROWS [ONLY|WITH TIES].

§default_values: bool

INSERT with DEFAULT VALUES.

§overriding: Option<OverridingKind>

OVERRIDING clause for generated columns.

§sample: Option<(SampleMethod, f64, Option<u64>)>

TABLESAMPLE method, percentage, and optional seed.

§only_table: bool

SELECT FROM ONLY (exclude inheritance).

§vector: Option<Vec<f32>>

Search vector for similarity queries.

§score_threshold: Option<f32>

Minimum score threshold.

§vector_name: Option<String>

Named vector in multi-vector collections.

§with_vector: bool

Include vector data in results.

§vector_size: Option<u64>

Vector dimensionality.

§distance: Option<Distance>

Distance metric.

§on_disk: Option<bool>

Store vectors on disk.

§function_def: Option<FunctionDef>

Function definition.

§trigger_def: Option<TriggerDef>

Trigger definition.

§policy_def: Option<RlsPolicy>

RLS policy definition.

§view_security_invoker: bool

CREATE VIEW … WITH (security_invoker = true).

Postgres evaluates a plain view against its base tables with the VIEW OWNER’s privileges, so row-level security on those tables is checked as the owner rather than the caller — a view over an RLS-protected table is an RLS bypass unless this is set. Only meaningful for Action::CreateView.

Implementations§

Source§

impl Qail

Source

pub fn typed_eq<T, V>(self, col: TypedColumn<T>, value: V) -> Self
where V: Into<Value> + ColumnValue<T>,

Type-safe equality condition.

Enforces at compile time that the value type matches the column type.

§Arguments
  • col — Typed column descriptor.
  • value — Value whose type must match the column’s type marker.
Source

pub fn typed_ne<T, V>(self, col: TypedColumn<T>, value: V) -> Self
where V: Into<Value> + ColumnValue<T>,

Type-safe not-equal condition.

§Arguments
  • col — Typed column descriptor.
  • value — Value whose type must match the column’s type marker.
Source

pub fn typed_gt<T, V>(self, col: TypedColumn<T>, value: V) -> Self
where V: Into<Value> + ColumnValue<T>,

Type-safe greater-than condition.

§Arguments
  • col — Typed column descriptor.
  • value — Value whose type must match the column’s type marker.
Source

pub fn typed_lt<T, V>(self, col: TypedColumn<T>, value: V) -> Self
where V: Into<Value> + ColumnValue<T>,

Type-safe less-than condition.

§Arguments
  • col — Typed column descriptor.
  • value — Value whose type must match the column’s type marker.
Source

pub fn typed_gte<T, V>(self, col: TypedColumn<T>, value: V) -> Self
where V: Into<Value> + ColumnValue<T>,

Type-safe greater-than-or-equal condition.

§Arguments
  • col — Typed column descriptor.
  • value — Value whose type must match the column’s type marker.
Source

pub fn typed_lte<T, V>(self, col: TypedColumn<T>, value: V) -> Self
where V: Into<Value> + ColumnValue<T>,

Type-safe less-than-or-equal condition.

§Arguments
  • col — Typed column descriptor.
  • value — Value whose type must match the column’s type marker.
Source

pub fn typed_column<T>(self, col: TypedColumn<T>) -> Self

Type-safe column selection.

Source

pub fn typed_filter<T, V>( self, col: TypedColumn<T>, op: Operator, value: V, ) -> Self
where V: Into<Value> + ColumnValue<T>,

Type-safe filter with custom operator.

§Arguments
  • col — Typed column descriptor.
  • op — Comparison operator.
  • value — Value whose type must match the column’s type marker.
Source§

impl Qail

Source

pub fn column_expr(self, expr: Expr) -> Self

Add a column expression.

Source

pub fn columns_expr<I>(self, exprs: I) -> Self
where I: IntoIterator<Item = Expr>,

Add multiple column expressions.

Source

pub fn distinct_on<I, S>(self, cols: I) -> Self
where I: IntoIterator<Item = S>, S: AsRef<str>,

DISTINCT ON named columns.

Source

pub fn distinct_on_expr<I>(self, exprs: I) -> Self
where I: IntoIterator<Item = Expr>,

DISTINCT ON expressions.

Source

pub fn filter_cond(self, condition: Condition) -> Self

Add a raw Condition to the WHERE clause.

Source

pub fn having_cond(self, condition: Condition) -> Self

Add a HAVING condition.

Source

pub fn having_conds( self, conditions: impl IntoIterator<Item = Condition>, ) -> Self

Add multiple HAVING conditions.

Source

pub fn with_ctes(self, ctes: Vec<CTEDef>) -> Self

Set CTEs (WITH clause).

Source

pub fn update_from<I, S>(self, tables: I) -> Self
where I: IntoIterator<Item = S>, S: AsRef<str>,

UPDATE … FROM additional tables.

Source

pub fn delete_using<I, S>(self, tables: I) -> Self
where I: IntoIterator<Item = S>, S: AsRef<str>,

DELETE … USING additional tables.

Source

pub fn for_update(self) -> Self

FOR UPDATE row lock.

Source

pub fn for_update_skip_locked(self) -> Self

FOR UPDATE SKIP LOCKED row lock. Used for concurrent job claiming (e.g. outbox dispatch).

Source

pub fn for_no_key_update(self) -> Self

FOR NO KEY UPDATE row lock.

Source

pub fn for_share(self) -> Self

FOR SHARE row lock.

Source

pub fn for_key_share(self) -> Self

FOR KEY SHARE row lock.

Source

pub fn fetch_first(self, count: u64) -> Self

FETCH FIRST n ROWS ONLY.

Source

pub fn fetch_with_ties(self, count: u64) -> Self

FETCH FIRST n ROWS WITH TIES.

Source

pub fn default_values(self) -> Self

INSERT with DEFAULT VALUES.

Source

pub fn overriding_system_value(self) -> Self

OVERRIDING SYSTEM VALUE.

Source

pub fn overriding_user_value(self) -> Self

OVERRIDING USER VALUE.

Source

pub fn tablesample_bernoulli(self, percent: f64) -> Self

TABLESAMPLE BERNOULLI(percent).

Source

pub fn tablesample_system(self, percent: f64) -> Self

TABLESAMPLE SYSTEM(percent).

Source

pub fn repeatable(self, seed: u64) -> Self

REPEATABLE(seed) for TABLESAMPLE.

Source

pub fn only(self) -> Self

SELECT FROM ONLY (exclude child tables).

Source

pub fn left_join_as( self, table: impl AsRef<str>, alias: impl AsRef<str>, left_col: impl AsRef<str>, right_col: impl AsRef<str>, ) -> Self

LEFT JOIN with alias.

Source

pub fn inner_join_as( self, table: impl AsRef<str>, alias: impl AsRef<str>, left_col: impl AsRef<str>, right_col: impl AsRef<str>, ) -> Self

INNER JOIN with alias.

Source

pub fn join_conds( self, kind: JoinKind, table: impl AsRef<str>, conditions: Vec<Condition>, ) -> Self

JOIN with multiple ON conditions.

The table string may include an alias (e.g. "inventory inv").

§Example
use qail_core::ast::builders::{eq, col};
use qail_core::ast::{Condition, Operator, Expr, Value};

// LEFT JOIN odyssey_leg_inventory inv
//   ON inv.leg_id = ol.id AND inv.service_date = '2024-01-15'
.left_join_conds("odyssey_leg_inventory inv", vec![
    Condition { left: Expr::Named("inv.leg_id".into()), op: Operator::Eq,
                value: Value::Column("ol.id".into()), is_array_unnest: false },
    Condition { left: Expr::Named("inv.service_date".into()), op: Operator::Eq,
                value: Value::String("2024-01-15".into()), is_array_unnest: false },
])
Source

pub fn left_join_conds( self, table: impl AsRef<str>, conditions: Vec<Condition>, ) -> Self

LEFT JOIN with multiple ON conditions.

Source

pub fn inner_join_conds( self, table: impl AsRef<str>, conditions: Vec<Condition>, ) -> Self

INNER JOIN with multiple ON conditions.

Source

pub fn table_alias(self, alias: impl AsRef<str>) -> Self

Set an alias for the FROM table.

Source

pub fn order_by_expr(self, expr: Expr, order: SortOrder) -> Self

ORDER BY an expression.

Source

pub fn group_by_expr<I>(self, exprs: I) -> Self
where I: IntoIterator<Item = Expr>,

GROUP BY expressions.

Source§

impl Qail

Source

pub fn get(table: impl Into<String>) -> Self

SELECT — query rows.

Source

pub fn set(table: impl Into<String>) -> Self

UPDATE — modify rows.

Source

pub fn del(table: impl Into<String>) -> Self

DELETE — remove rows.

Source

pub fn add(table: impl Into<String>) -> Self

INSERT — add rows.

Source

pub fn put(table: impl Into<String>) -> Self

UPSERT — insert or update.

Source

pub fn merge_into(table: impl Into<String>) -> Self

MERGE — conditionally insert, update, delete, or do nothing.

Source

pub fn export(table: impl Into<String>) -> Self

COPY … TO — export data.

Source

pub fn make(table: impl Into<String>) -> Self

CREATE TABLE.

Source

pub fn truncate(table: impl Into<String>) -> Self

TRUNCATE — empty a table.

Source

pub fn explain(table: impl Into<String>) -> Self

EXPLAIN — show query plan.

Source

pub fn explain_analyze(table: impl Into<String>) -> Self

EXPLAIN ANALYZE — show query plan with execution stats.

Source

pub fn lock(table: impl Into<String>) -> Self

LOCK TABLE.

Source

pub fn create_materialized_view(name: impl Into<String>, query: Qail) -> Self

CREATE MATERIALIZED VIEW.

Source

pub fn refresh_materialized_view(name: impl Into<String>) -> Self

REFRESH MATERIALIZED VIEW.

Source

pub fn drop_materialized_view(name: impl Into<String>) -> Self

DROP MATERIALIZED VIEW.

Source

pub fn listen(channel: impl Into<String>) -> Self

Create a LISTEN command to subscribe to a channel.

§Example
let cmd = Qail::listen("orders");
// Generates: LISTEN orders
Source

pub fn unlisten(channel: impl Into<String>) -> Self

Create an UNLISTEN command to unsubscribe from a channel.

§Example
let cmd = Qail::unlisten("orders");
// Generates: UNLISTEN orders
Source

pub fn notify(channel: impl Into<String>, payload: impl Into<String>) -> Self

Create a NOTIFY command to send a message to a channel.

§Example
let cmd = Qail::notify("orders", "new_order:123");
// Generates: NOTIFY orders, 'new_order:123'
Source

pub fn notify_scoped( ctx: &RlsContext, fragment: &str, payload: impl Into<String>, ) -> Result<Self, String>

Create a NOTIFY on the channel a gateway subscribe(fragment) under ctx actually listens on.

The gateway derives its real PostgreSQL channel from (scope, fragment) via crate::rls::channel::scoped_channel_for; this is the producer-side half of that contract, so application code never re-implements the naming convention.

§Example
let ctx = RlsContext::tenant("acme");
let cmd = Qail::notify_scoped(&ctx, "chat_42", r#"{"id":7}"#)?;
// Generates: NOTIFY "t_4_acme_chat_42", '{"id":7}'
Source

pub fn call(procedure: impl Into<String>) -> Self

Create a CALL command to invoke a stored procedure.

§Example
let cmd = Qail::call("refresh_materialized_views()");
// Generates: CALL refresh_materialized_views()
Source

pub fn do_block(body: impl Into<String>, language: impl Into<String>) -> Self

Create a DO command to execute an anonymous code block.

§Example
let cmd = Qail::do_block("BEGIN RAISE NOTICE 'hello'; END;", "plpgsql");
// Generates: DO $$ BEGIN RAISE NOTICE 'hello'; END; $$ LANGUAGE plpgsql
Source

pub fn session_set(key: impl Into<String>, value: impl Into<String>) -> Self

Create a SET command for session variables.

§Example
let cmd = Qail::session_set("statement_timeout", "5000");
// Generates: SET statement_timeout = '5000'
Source

pub fn session_show(key: impl Into<String>) -> Self

Create a SHOW command to inspect a session variable.

§Example
let cmd = Qail::session_show("statement_timeout");
// Generates: SHOW statement_timeout
Source

pub fn session_reset(key: impl Into<String>) -> Self

Create a RESET command to restore a session variable to default.

§Example
let cmd = Qail::session_reset("statement_timeout");
// Generates: RESET statement_timeout
Source

pub fn create_database(name: impl Into<String>) -> Self

Create a CREATE DATABASE command.

Source

pub fn drop_database(name: impl Into<String>) -> Self

Create a DROP DATABASE command.

Source§

impl Qail

Source

pub fn to_cte(self, name: impl Into<String>) -> CTEDef

Convert this query into a reusable CTE definition.

Source

pub fn with(self, name: impl Into<String>, query: Qail) -> Self

Add an inline CTE from another query.

Source

pub fn recursive(self, recursive_part: Qail) -> Self

Mark the last CTE as recursive and attach the recursive query.

Source

pub fn from_cte(self, cte_name: impl Into<String>) -> Self

Set the source table of the last CTE.

Source

pub fn select_from_cte(self, columns: &[&str]) -> Self

Replace the column list with named columns (for selecting from a CTE).

Source

pub fn with_cte(self, cte: CTEDef) -> Self

Append a pre-built CTE definition.

Source§

impl Qail

Source

pub fn target_alias(self, alias: impl Into<String>) -> Self

Set a target alias for MERGE INTO.

Source

pub fn using_table(self, table: impl Into<String>) -> Self

Set a table source for MERGE USING.

Source

pub fn using_table_as( self, table: impl Into<String>, alias: impl Into<String>, ) -> Self

Set an aliased table source for MERGE USING.

Source

pub fn using_query_as(self, query: Qail, alias: impl Into<String>) -> Self

Set an aliased query source for MERGE USING.

Source

pub fn merge_on_column( self, left: impl Into<String>, op: Operator, right: impl Into<String>, ) -> Self

Add an ON condition comparing the target side to a source column.

Source

pub fn merge_on_condition(self, condition: Condition) -> Self

Add an arbitrary ON condition.

Source

pub fn when_matched_update<S>(self, assignments: &[(S, Expr)]) -> Self
where S: AsRef<str>,

Add WHEN MATCHED THEN UPDATE SET ....

Source

pub fn when_matched_update_if<S>( self, condition: Vec<Condition>, assignments: &[(S, Expr)], ) -> Self
where S: AsRef<str>,

Add WHEN MATCHED AND ... THEN UPDATE SET ....

Source

pub fn when_matched_delete(self) -> Self

Add WHEN MATCHED THEN DELETE.

Source

pub fn when_matched_do_nothing(self) -> Self

Add WHEN MATCHED THEN DO NOTHING.

Source

pub fn when_not_matched_insert<S>(self, columns: &[S], values: &[Expr]) -> Self
where S: AsRef<str>,

Add WHEN NOT MATCHED [BY TARGET] THEN INSERT (...) VALUES (...).

Source

pub fn when_not_matched_insert_if<S>( self, condition: Vec<Condition>, columns: &[S], values: &[Expr], ) -> Self
where S: AsRef<str>,

Add WHEN NOT MATCHED [BY TARGET] AND ... THEN INSERT (...) VALUES (...).

Source

pub fn when_not_matched_do_nothing(self) -> Self

Add WHEN NOT MATCHED [BY TARGET] THEN DO NOTHING.

Source

pub fn when_not_matched_by_source_delete(self) -> Self

Add WHEN NOT MATCHED BY SOURCE THEN DELETE.

Source

pub fn when_not_matched_by_source_update<S>( self, assignments: &[(S, Expr)], ) -> Self
where S: AsRef<str>,

Add WHEN NOT MATCHED BY SOURCE THEN UPDATE SET ....

Source

pub fn when_not_matched_by_source_do_nothing(self) -> Self

Add WHEN NOT MATCHED BY SOURCE THEN DO NOTHING.

Source§

impl Qail

Source

pub fn limit(self, n: i64) -> Self

Set LIMIT.

Source

pub fn select_all(self) -> Self

SELECT * (all columns).

Source

pub fn columns<I, S>(self, cols: I) -> Self
where I: IntoIterator<Item = S>, S: AsRef<str>,

Add columns by name.

Source

pub fn column(self, col: impl AsRef<str>) -> Self

Add a single column by name.

Source

pub fn select_expr(self, expr: impl Into<Expr>) -> Self

Add a computed expression as a SELECT column.

Use this for subqueries, aggregates, CASE WHEN, COALESCE, etc.

§Example
use qail_core::ast::builders::{subquery, coalesce, col, text};
use qail_core::ast::builders::ExprExt;

Qail::get("orders")
    .columns(&["id", "status"])
    .select_expr(
        subquery(Qail::get("order_items")
            .column("sum(amount)")
            .eq("order_id", col("orders.id")))
        .with_alias("total_amount")
    )
    .select_expr(
        coalesce([col("nickname"), col("first_name"), text("Guest")])
            .alias("display_name")
    )
Source

pub fn select_exprs<I, E>(self, exprs: I) -> Self
where I: IntoIterator<Item = E>, E: Into<Expr>,

Add multiple computed expressions as SELECT columns.

§Example
.select_exprs([
    count().alias("total"),
    sum("amount").alias("grand_total"),
])
Source

pub fn filter( self, column: impl AsRef<str>, op: Operator, value: impl Into<Value>, ) -> Self

Add a WHERE filter with an operator and value.

Source

pub fn or_filter( self, column: impl AsRef<str>, op: Operator, value: impl Into<Value>, ) -> Self

Add an OR filter condition.

Source

pub fn where_eq(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self

Filter: column = value.

Source

pub fn eq(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self

Filter: column = value (alias for where_eq).

Source

pub fn ne(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self

Filter: column != value.

Source

pub fn gt(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self

Filter: column > value.

Source

pub fn gte(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self

Filter: column >= value.

Source

pub fn lt(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self

Filter: column < value

Source

pub fn lte(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self

Filter: column <= value.

Source

pub fn is_null(self, column: impl AsRef<str>) -> Self

Filter: column IS NULL.

Source

pub fn is_not_null(self, column: impl AsRef<str>) -> Self

Filter: column IS NOT NULL.

Source

pub fn like(self, column: impl AsRef<str>, pattern: impl Into<Value>) -> Self

Filter: column LIKE pattern.

Source

pub fn ilike(self, column: impl AsRef<str>, pattern: impl Into<Value>) -> Self

Filter: column ILIKE pattern.

Source

pub fn array_elem_contained_in_text( self, array_column: impl AsRef<str>, text: impl Into<Value>, ) -> Self

Filter: does text contain any element from array_column?

Generates an EXISTS (SELECT 1 FROM unnest(array_column) _el WHERE ...) predicate with case-insensitive matching.

Source

pub fn in_vals<I, V>(self, column: impl AsRef<str>, values: I) -> Self
where I: IntoIterator<Item = V>, V: Into<Value>,

Filter: column IN (values).

§Arguments
  • column — Column name to filter on.
  • values — Iterable of values for the IN list.
Source

pub fn order_by(self, column: impl AsRef<str>, order: SortOrder) -> Self

Add ORDER BY clause.

Source

pub fn order_desc(self, column: impl AsRef<str>) -> Self

ORDER BY column DESC.

Source

pub fn order_asc(self, column: impl AsRef<str>) -> Self

ORDER BY column ASC.

Source

pub fn offset(self, n: i64) -> Self

Set OFFSET.

Source

pub fn group_by<I, S>(self, cols: I) -> Self
where I: IntoIterator<Item = S>, S: AsRef<str>,

GROUP BY columns.

Source

pub fn distinct_on_all(self) -> Self

SELECT DISTINCT (all columns).

Source

pub fn join( self, kind: JoinKind, table: impl AsRef<str>, left_col: impl AsRef<str>, right_col: impl AsRef<str>, ) -> Self

Add a JOIN clause.

Source

pub fn left_join( self, table: impl AsRef<str>, left_col: impl AsRef<str>, right_col: impl AsRef<str>, ) -> Self

LEFT JOIN.

Source

pub fn inner_join( self, table: impl AsRef<str>, left_col: impl AsRef<str>, right_col: impl AsRef<str>, ) -> Self

INNER JOIN.

Source

pub fn join_on(self, related_table: impl AsRef<str>) -> QailBuildResult<Self>

Join a related table using schema-defined foreign key relationship.

This is the “First-Class Relations” API - it automatically infers the join condition from the schema’s ref: definitions.

§Example
// Schema: posts.user_id UUID ref:users.id

// Instead of:
Qail::get("users").left_join("posts", "users.id", "posts.user_id")

// Simply:
Qail::get("users").join_on("posts")?

Returns an error when no relation is found or relation metadata is ambiguous. Use Qail::join_on_optional for a no-op fallback.

Source

pub fn join_on_optional(self, related_table: impl AsRef<str>) -> Self

Join a related table if relation exists, otherwise no-op.

This is the panic-free variant of join_on(). On ambiguous relation metadata it logs and returns self unchanged.

Source

pub fn returning<I, S>(self, cols: I) -> Self
where I: IntoIterator<Item = S>, S: AsRef<str>,

Add RETURNING clause with column names.

Source

pub fn returning_all(self) -> Self

RETURNING * (all columns).

Source

pub fn values<I, V>(self, vals: I) -> Self
where I: IntoIterator<Item = V>, V: Into<Value>,

Add payload values (INSERT positional).

Source

pub fn set_value(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self

Set a column = value pair for UPDATE or INSERT.

Source

pub fn set_opt<T>(self, column: impl AsRef<str>, value: Option<T>) -> Self
where T: Into<Value>,

Set value only if Some, skip entirely if None This is ergonomic for optional fields - the column is not included in the INSERT at all if None

Source

pub fn set_coalesce( self, column: impl AsRef<str>, value: impl Into<Value>, ) -> Self

Set column to COALESCE(new_value, existing_column) for partial updates.

This is useful for UPDATE operations where you want to keep the existing value if the new value is NULL.

§Example
Qail::set("users")
    .set_coalesce("name", "Alice")  // name = COALESCE('Alice', name)
    .eq("id", 1)
Source

pub fn set_coalesce_opt<T>( self, column: impl AsRef<str>, value: Option<T>, ) -> Self
where T: Into<Value>,

Set column to COALESCE(new_value, existing_column) only if value is Some.

Combines set_coalesce() with optional handling - if None, still adds the COALESCE with NULL as the first argument (so existing value is kept).

Source

pub fn on_conflict_update<S>( self, conflict_cols: &[S], updates: &[(S, Expr)], ) -> Self
where S: AsRef<str>,

Add ON CONFLICT DO UPDATE clause for UPSERT operations.

§Example
Qail::add("users")
    .set_value("id", 1)
    .set_value("name", "Alice")
    .on_conflict_update(&["id"], &[("name", Expr::Named("EXCLUDED.name".into()))])
Source

pub fn on_conflict_nothing<S>(self, conflict_cols: &[S]) -> Self
where S: AsRef<str>,

Add ON CONFLICT DO NOTHING clause (ignore duplicates).

§Example
Qail::add("users")
    .set_value("id", 1)
    .on_conflict_nothing(&["id"])
Source§

impl Qail

Source

pub fn with_rls(self, ctx: &RlsContext) -> QailBuildResult<Self>

Apply tenant-scope isolation based on the query action.

  • GET/SET/DEL → injects WHERE tenant_col = $value
  • ADD/Upsert → auto-sets tenant_col in payload
  • Global context → injects tenant_col IS NULL (or payload tenant_col = NULL)
  • Super admins → no-op (bypasses isolation)
  • Unregistered tables → no-op (not a tenant table)
  • DDL/etc → no-op
§⚠️ Unregistered relations FAIL OPEN

The unregistered case returns the query unscoped, which makes this call site look protected while emitting SQL that is not. The registry is populated by scanning schema.qail for table blocks carrying a literal tenant_id, so a renamed table, a differently-named tenant column, or any view falls through silently.

Views are the sharp edge: they cannot carry RLS of their own, and unless declared security_invoker Postgres evaluates their base tables with the view OWNER’s rights — bypassing those tables’ policies as well. A view read under with_rls has neither layer.

Assert it where scoping is load-bearing, with crate::rls::tenant::scoping_applies.

§Example
let ctx = RlsContext::tenant("tenant-uuid");
let query = Qail::get("orders").with_rls(&ctx)?;
Source

pub fn with_rls_policy(self, _ctx: &RlsContext) -> Self

Declare that this query’s tenant isolation is DELIBERATELY delegated to the database’s row-level-security policies (Phase 2 session variable + Phase 3 CREATE POLICY) instead of AST injection.

Use this for queries that are intentionally cross-tenant by policy — e.g. a reseller storefront reading an operator’s rows through a contract-scope policy (... OR tenant_id IN (SELECT principal_tenant_id FROM tenant_contracts ...)), or an insert whose payload tenant_id must NOT be overwritten with the session tenant (settlement/payout attribution). Calling Qail::with_rls on such a query would inject WHERE tenant_col = ctx.tenant (hiding the policy-granted rows) or overwrite the payload tenant; leaving the query bare trips the build-time RLS audit. This marker is the explicit, auditable middle ground: the AST is left untouched and the audit treats the query as consciously scoped.

The RlsContext argument is not applied to the AST — it documents (and type-checks) which session context the caller runs the query under. Policy delegation only isolates when the connection was acquired with an RLS context (acquire_with_rls) so app.current_tenant_id is set for the policies to read; it is NOT a bypass.

§Example
// Reseller storefront reads the operator's package via the
// charter contract-scope DB policy — do NOT inject
// WHERE tenant_id = <reseller>.
let ctx = tenant.to_rls_context();
let query = Qail::get("charter_packages")
    .eq("slug", slug)
    .with_rls_policy(&ctx);
Source§

impl Qail

Source

pub fn search(collection: &str) -> Self

Create a vector similarity search command.

§Example
use qail_core::prelude::*;

let cmd = Qail::search("products")
    .vector(vec![0.1, 0.2, 0.3])
    .limit(10);
Source

pub fn upsert(collection: &str) -> Self

Create a vector upsert command (insert or update points).

§Example
let cmd = Qail::upsert("products");
Source

pub fn scroll(collection: &str) -> Self

Create a scroll command for paginated iteration.

§Example
let cmd = Qail::scroll("products").limit(100);
Source

pub fn vector(self, embedding: Vec<f32>) -> Self

Set the query vector for similarity search.

§Example
use qail_core::prelude::*;

let embedding = vec![0.1, 0.2, 0.3, 0.4];
let cmd = Qail::search("products").vector(embedding);
assert!(cmd.vector.is_some());
Source

pub fn score_threshold(self, threshold: f32) -> Self

Set minimum similarity score threshold.

Points with similarity below this threshold will be filtered out.

§Example
use qail_core::prelude::*;

let cmd = Qail::search("products")
    .vector(vec![0.1, 0.2])
    .score_threshold(0.8);
assert_eq!(cmd.score_threshold, Some(0.8));
Source

pub fn vector_name(self, name: &str) -> Self

Specify which named vector to search (for multi-vector collections).

§Example
use qail_core::prelude::*;

// Collection with separate "title" and "content" vectors
let title_embedding = vec![0.1, 0.2, 0.3];
let cmd = Qail::search("articles")
    .vector_name("title")
    .vector(title_embedding);
Source

pub fn with_vectors(self) -> Self

Include vectors in search results.

§Example
use qail_core::prelude::*;

let embedding = vec![0.1, 0.2, 0.3];
let cmd = Qail::search("products")
    .vector(embedding)
    .with_vectors();
assert!(cmd.with_vector);
Source§

impl Qail

Source

pub fn typed<T: Table + Into<String>>(table: T) -> TypedQail<T>

Create a typed query builder that carries the table type.

This enables join_related() with compile-time relationship checking.

Qail::typed(users::table)
    .join_related(posts::table)     // Compiles ✓
    .typed_eq(users::age(), 25)
    .build()

Trait Implementations§

Source§

impl Clone for Qail

Source§

fn clone(&self) -> Qail

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Qail

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Qail

Source§

fn default() -> Self

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

impl<'de> Deserialize<'de> for Qail

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for Qail

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Qail

Source§

fn eq(&self, other: &Qail) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for Qail

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Qail

Source§

impl ToQdrant for Qail

Convert a QAIL query into a Qdrant search/upsert/delete JSON body.
Source§

impl ToSql for Qail

Source§

fn to_sql_with_dialect(&self, dialect: Dialect) -> String

Convert this node to a SQL string with specific dialect.
Source§

fn to_sql(&self) -> String

Convert this node to a SQL string using default dialect.
Source§

impl ToSqlParameterized for Qail

Source§

fn to_sql_parameterized_with_dialect(&self, dialect: Dialect) -> TranspileResult

Convert to SQL with extracted parameters for specific dialect.
Source§

fn to_sql_parameterized(&self) -> TranspileResult

Convert to SQL with extracted parameters (default dialect).
Source§

impl TryFrom<&Qail> for NormalizedMutation

Source§

type Error = NormalizeMutationError

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

fn try_from(qail: &Qail) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<&Qail> for NormalizedSelect

Source§

type Error = NormalizeError

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

fn try_from(qail: &Qail) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl WithCap for Qail

Source§

fn with_cap<C: Capability>(self, _cap: &C) -> CapQuery<C>

Start building a capability-aware query.

Auto Trait Implementations§

§

impl Freeze for Qail

§

impl RefUnwindSafe for Qail

§

impl Send for Qail

§

impl Sync for Qail

§

impl Unpin for Qail

§

impl UnsafeUnpin for Qail

§

impl UnwindSafe for Qail

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> ColumnValue<Value> for T

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
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.