Current section

Files

Jump to
sqlode src sqlode@query_ir.erl
Raw

src/sqlode@query_ir.erl

-module(sqlode@query_ir).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/sqlode/query_ir.gleam").
-export_type([tokenized_query/0, sql_statement/0, select_item/0, from_item/0, join_clause/0, structured_query/0, stmt/0, select_core/0, set_op/0, set_op_kind/0, order_key/0, nulls_order/0, cte_def/0, select_item_ex/0, from_item_ex/0, join_kind/0, join_on/0, assignment/0, insert_source/0, expr/0, func_arg/0, case_branch/0, quantifier/0, is_predicate/0, like_op/0, in_source/0, window_spec/0, rich_query/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Intermediate representation shared between the query parser and the\n"
" query analyzer.\n"
"\n"
" This module defines two layers:\n"
"\n"
" - The legacy **structured IR** (`SqlStatement`, `SelectItem`,\n"
" `FromItem`, `JoinClause`) that identifies top-level clauses but\n"
" stores complex sub-expressions as raw `List(lexer.Token)`.\n"
" - The **expression-aware IR** (`Stmt`, `Expr`, `CteDef`, …) that\n"
" explicitly models the SQL subset sqlode actually needs: CTEs\n"
" (including nested references), select items, table refs / aliases\n"
" / derived tables / lateral subqueries, predicate expressions,\n"
" arithmetic and `CASE`, function calls and casts, `IN`, `EXISTS`,\n"
" `ANY`, `ALL`, `GROUP BY`, `HAVING`, window expressions, and\n"
" `RETURNING`.\n"
"\n"
" The expression-aware IR is intended to become the single semantic\n"
" input for type inference; `RawExpr` / `UnstructuredStmt` remain only\n"
" as explicit diagnostic hooks for concrete IR gaps.\n"
).
-type tokenized_query() :: {tokenized_query,
sqlode@model:parsed_query(),
list(sqlode@lexer:token())}.
-type sql_statement() :: {select_statement,
list(select_item()),
list(from_item()),
list(join_clause()),
gleam@option:option(list(sqlode@lexer:token())),
gleam@option:option(list(sqlode@lexer:token())),
gleam@option:option(list(sqlode@lexer:token())),
gleam@option:option(list(sqlode@lexer:token())),
gleam@option:option(list(sqlode@lexer:token()))} |
{insert_statement,
binary(),
list(binary()),
list(list(sqlode@lexer:token())),
gleam@option:option(list(sqlode@lexer:token()))} |
{update_statement,
binary(),
list(sqlode@lexer:token()),
gleam@option:option(list(sqlode@lexer:token())),
gleam@option:option(list(sqlode@lexer:token()))} |
{delete_statement,
binary(),
gleam@option:option(list(sqlode@lexer:token())),
gleam@option:option(list(sqlode@lexer:token()))} |
{unstructured_statement, list(sqlode@lexer:token())}.
-type select_item() :: {star_item, gleam@option:option(binary())} |
{expression_item, list(sqlode@lexer:token()), gleam@option:option(binary())}.
-type from_item() :: {table_ref, binary(), gleam@option:option(binary())} |
{subquery_ref, list(sqlode@lexer:token()), gleam@option:option(binary())}.
-type join_clause() :: {join_clause,
binary(),
gleam@option:option(binary()),
gleam@option:option(list(sqlode@lexer:token()))}.
-type structured_query() :: {structured_query,
sqlode@model:parsed_query(),
list(sqlode@lexer:token()),
sql_statement()}.
-type stmt() :: {select_stmt, list(cte_def()), select_core()} |
{insert_stmt,
list(cte_def()),
binary(),
list(binary()),
insert_source(),
list(select_item_ex())} |
{update_stmt,
list(cte_def()),
binary(),
gleam@option:option(binary()),
list(assignment()),
list(from_item_ex()),
gleam@option:option(expr()),
list(select_item_ex())} |
{delete_stmt,
list(cte_def()),
binary(),
gleam@option:option(binary()),
list(from_item_ex()),
gleam@option:option(expr()),
list(select_item_ex())} |
{unstructured_stmt, binary(), list(sqlode@lexer:token())}.
-type select_core() :: {select_core,
boolean(),
list(select_item_ex()),
list(from_item_ex()),
gleam@option:option(expr()),
list(expr()),
gleam@option:option(expr()),
list(order_key()),
gleam@option:option(expr()),
gleam@option:option(expr()),
gleam@option:option(set_op())}.
-type set_op() :: {set_op, set_op_kind(), boolean(), select_core()}.
-type set_op_kind() :: union | intersect | except.
-type order_key() :: {order_key,
expr(),
boolean(),
gleam@option:option(nulls_order())}.
-type nulls_order() :: nulls_first | nulls_last.
-type cte_def() :: {cte_def, binary(), list(binary()), stmt(), boolean()}.
-type select_item_ex() :: {star_ex, gleam@option:option(binary())} |
{expr_item, expr(), gleam@option:option(binary())}.
-type from_item_ex() :: {from_table, binary(), gleam@option:option(binary())} |
{from_subquery, select_core(), binary(), list(binary())} |
{from_values, list(list(expr())), binary(), list(binary())} |
{from_join,
from_item_ex(),
from_item_ex(),
join_kind(),
join_on(),
boolean()}.
-type join_kind() :: inner_join |
left_join |
right_join |
full_join |
cross_join.
-type join_on() :: {join_on_expr, expr()} |
{join_using, list(binary())} |
join_no_condition.
-type assignment() :: {assignment, binary(), expr()}.
-type insert_source() :: {insert_values, list(list(expr()))} |
{insert_select, select_core()} |
insert_default_values.
-type expr() :: null_lit |
{bool_lit, boolean()} |
{string_lit, binary()} |
{number_lit, binary()} |
{param, integer(), binary()} |
{column_ref, gleam@option:option(binary()), binary()} |
{star_ref, gleam@option:option(binary())} |
{unary, binary(), expr()} |
{binary, binary(), expr(), expr()} |
{func,
binary(),
list(func_arg()),
boolean(),
gleam@option:option(expr()),
gleam@option:option(window_spec())} |
{cast, expr(), binary()} |
{'case',
gleam@option:option(expr()),
list(case_branch()),
gleam@option:option(expr())} |
{in_expr, expr(), in_source(), boolean()} |
{exists, select_core(), boolean()} |
{scalar_subquery, select_core()} |
{quantified, binary(), expr(), quantifier(), expr()} |
{between, expr(), expr(), expr(), boolean()} |
{is_check, expr(), is_predicate(), boolean()} |
{like_expr,
expr(),
like_op(),
expr(),
gleam@option:option(expr()),
boolean()} |
{array_lit, list(expr())} |
{tuple, list(expr())} |
{macro, binary(), list(sqlode@lexer:token())} |
{raw_expr, binary(), list(sqlode@lexer:token())}.
-type func_arg() :: {func_arg, expr()}.
-type case_branch() :: {case_branch, expr(), expr()}.
-type quantifier() :: q_any | q_all | q_some.
-type is_predicate() :: is_null |
is_true |
is_false |
is_unknown |
{is_distinct_from, expr()}.
-type like_op() :: like | ilike | similar_to.
-type in_source() :: {in_list, list(expr())} |
{in_subquery, select_core()} |
{in_slice_macro, binary()}.
-type window_spec() :: {window_spec,
list(expr()),
list(order_key()),
gleam@option:option(list(sqlode@lexer:token()))}.
-type rich_query() :: {rich_query,
sqlode@model:parsed_query(),
list(sqlode@lexer:token()),
stmt()}.