Skip to main content

SelectBuilder

Type Alias SelectBuilder 

Source
pub type SelectBuilder<'a, Schema, State, Table = (), Marker = (), Row = (), Grouped = ()> = QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>;
Expand description

Builds a SELECT query specifically for SQLite.

SelectBuilder provides a type-safe, fluent API for constructing SELECT statements with compile-time verification of query structure and table relationships.

§Type Parameters

  • Schema: The database schema type, ensuring only valid tables can be referenced
  • State: The current builder state, enforcing proper query construction order
  • Table: The primary table being queried (when applicable)

§Query Building Flow

  1. Start with QueryBuilder::select() to specify columns
  2. Add from() to specify the source table
  3. Optionally add joins, conditions, grouping, ordering, and limits

§Basic Usage

use drizzle::sqlite::prelude::*;
use drizzle::sqlite::builder::QueryBuilder;

#[SQLiteTable(name = "users")]
struct User {
    #[column(primary)]
    id: i32,
    name: String,
    email: Option<String>,
}

#[derive(SQLiteSchema)]
struct Schema {
    user: User,
}

let builder = QueryBuilder::new::<Schema>();
let Schema { user } = Schema::new();

// Basic SELECT
let query = builder.select(user.name).from(user);
assert_eq!(query.to_sql().sql(), r#"SELECT "users"."name" FROM "users""#);

// SELECT with WHERE clause
use drizzle::core::expr::gt;
let query = builder
    .select((user.id, user.name))
    .from(user)
    .r#where(gt(user.id, 10));
assert_eq!(
    query.to_sql().sql(),
    r#"SELECT "users"."id", "users"."name" FROM "users" WHERE "users"."id" > ?"#
);

§Advanced Queries

let query = builder
    .select((user.name, post.title))
    .from(user)
    .join((post, eq(user.id, post.user_id)));
let query = builder
    .select(user.name)
    .from(user)
    .order_by(asc(user.name))
    .limit(10);

Aliased Type§

pub struct SelectBuilder<'a, Schema, State, Table = (), Marker = (), Row = (), Grouped = ()> {
    pub sql: SQL<'a, SQLiteValue<'a>>,
    /* private fields */
}

Fields§

§sql: SQL<'a, SQLiteValue<'a>>

Implementations§

Source§

impl<'a, S, M> SelectBuilder<'a, S, SelectInitial, (), M>

Source

pub fn from<T>( self, query: T, ) -> SelectBuilder<'a, S, SelectFromSet, T, Scoped<M, Cons<T, Nil>>, <M as ResolveRow<T>>::Row>
where T: ToSQL<'a, SQLiteValue<'a>>, M: ResolveRow<T>,

Specifies the table or subquery to select FROM.

This method transitions the builder from the initial state to the FROM state, enabling subsequent WHERE, JOIN, ORDER BY, and other clauses.

The row type R is resolved from the select marker M and the table T via the ResolveRow trait.

§Examples
// Select from a table
let query = builder.select(user.name).from(user);
assert_eq!(query.to_sql().sql(), r#"SELECT "users"."name" FROM "users""#);
Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: JoinAllowed,

Source

pub fn join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterJoin<R, J::JoinedTable>>::NewRow, G>

Adds an INNER JOIN clause to the query.

Joins another table to the current query using the specified condition. The joined table must be part of the schema and the condition should relate columns from both tables.

let query = builder
    .select((user.name, post.title))
    .from(user)
    .join((post, eq(user.id, post.user_id)));
assert_eq!(
    query.to_sql().sql(),
    r#"SELECT "users"."name", "posts"."title" FROM "users" JOIN "posts" ON "users"."id" = "posts"."user_id""#
);
Source

pub fn natural_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn natural_left_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterLeftJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn left_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterLeftJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn left_outer_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterLeftJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn natural_left_outer_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterLeftJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn natural_right_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterRightJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn right_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterRightJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn right_outer_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterRightJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn natural_right_outer_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterRightJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn natural_full_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterFullJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn full_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterFullJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn full_outer_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterFullJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn natural_full_outer_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterFullJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn inner_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterJoin<R, J::JoinedTable>>::NewRow, G>

Source

pub fn cross_join<J: JoinArg<'a, T>>( self, arg: J, ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as ScopePush<J::JoinedTable>>::Out, <M as AfterJoin<R, J::JoinedTable>>::NewRow, G>

Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: WhereAllowed,

Source

pub fn where<E>( self, condition: E, ) -> SelectBuilder<'a, S, SelectWhereSet, T, M, R, G>
where E: Expr<'a, SQLiteValue<'a>>, E::SQLType: BooleanLike,

Adds a WHERE clause to filter query results.

// Single condition
let query = builder
    .select(user.name)
    .from(user)
    .r#where(gt(user.id, 10));
assert_eq!(
    query.to_sql().sql(),
    r#"SELECT "users"."name" FROM "users" WHERE "users"."id" > ?"#
);

// Multiple conditions
let query = builder
    .select(user.name)
    .from(user)
    .r#where(and(gt(user.id, 10), eq(user.name, "Alice")));
Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: GroupByAllowed,

Source

pub fn group_by<Gr>( self, columns: Gr, ) -> SelectBuilder<'a, S, SelectGroupSet, T, M, R, Gr::Columns>
where Gr: IntoGroupBy<'a, SQLiteValue<'a>>,

Adds a GROUP BY clause to the query.

Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: HavingAllowed,

Source

pub fn having<E>( self, condition: E, ) -> SelectBuilder<'a, S, SelectGroupSet, T, M, R, G>
where E: Expr<'a, SQLiteValue<'a>>, E::SQLType: BooleanLike,

Adds a HAVING clause after GROUP BY.

Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: OrderByAllowed,

Source

pub fn order_by<TOrderBy>( self, expressions: TOrderBy, ) -> SelectBuilder<'a, S, SelectOrderSet, T, M, R, G>
where TOrderBy: ToSQL<'a, SQLiteValue<'a>>,

Sorts the query results.

Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: LimitAllowed,

Source

pub fn limit<P>( self, limit: P, ) -> SelectBuilder<'a, S, SelectLimitSet, T, M, R, G>
where P: PaginationArg<'a, SQLiteValue<'a>>,

Limits the number of rows returned.

§Panics

Panics when a signed numeric argument is negative or a numeric value does not fit in usize.

Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: OffsetAllowed,

Source

pub fn offset<P>( self, offset: P, ) -> SelectBuilder<'a, S, SelectOffsetSet, T, M, R, G>
where P: PaginationArg<'a, SQLiteValue<'a>>,

Sets the offset for the query results.

§Panics

Panics when a signed numeric argument is negative or a numeric value does not fit in usize.

Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: AsCteState, T: SQLTable<'a, SQLiteSchemaType, SQLiteValue<'a>>,

Source

pub fn into_cte<Tag: Tag + 'static>( self, ) -> CTEView<'a, <T as SQLTable<'a, SQLiteSchemaType, SQLiteValue<'a>>>::Aliased<Tag>, Self>

Converts this SELECT query into a typed CTE using alias tag name.

Source§

impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
where State: ExecutableState,

Source

pub fn union( self, other: impl IntoSelect<'a, S, M, R>, ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G>

Combines this query with another using UNION.

Source

pub fn union_all( self, other: impl IntoSelect<'a, S, M, R>, ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G>

Combines this query with another using UNION ALL.

Source

pub fn intersect( self, other: impl IntoSelect<'a, S, M, R>, ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G>

Combines this query with another using INTERSECT.

Source

pub fn intersect_all( self, other: impl IntoSelect<'a, S, M, R>, ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G>

Combines this query with another using INTERSECT ALL.

Source

pub fn except( self, other: impl IntoSelect<'a, S, M, R>, ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G>

Combines this query with another using EXCEPT.

Source

pub fn except_all( self, other: impl IntoSelect<'a, S, M, R>, ) -> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G>

Combines this query with another using EXCEPT ALL.

Trait Implementations§

Source§

impl<'a, S, State, T, M, R, G> Expr<'a, SQLiteValue<'a>> for SelectBuilder<'a, S, State, T, M, R, G>
where State: ExecutableState, M: SubqueryType<'a, SQLiteValue<'a>>,

Source§

type SQLType = <M as SubqueryType<'a, SQLiteValue<'a>>>::SQLType

The SQL data type this expression evaluates to.
Source§

type Nullable = Null

Whether this expression can be NULL.
Source§

type Aggregate = Scalar

Whether this is an aggregate (COUNT, SUM) or scalar expression.
Source§

fn to_expr_sql(&self) -> SQL<'a, V>

Render this value as a scalar expression by reference. Read more
Source§

fn into_expr_sql(self) -> SQL<'a, V>
where Self: Sized,

Render this value as a scalar expression, consuming it when useful.
Source§

impl<'a, S, State: ExecutableState, T, M, R, G> IntoSelect<'a, S, M, R> for SelectBuilder<'a, S, State, T, M, R, G>

Source§

type State = State

Source§

type Table = T

Source§

fn into_select(self) -> SelectBuilder<'a, S, State, T, M, R>