-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()}.