class Rotor::Translator
Translates the tree of a query's block (Meta::Expr, Quarz's docs/14
§6) to SQL, with the values its captures had when the query was built.
The block's row is its receiver (where { age > 18 }) or its
parameter (where { |u| u.age > 18 }), one per table in a join
(where { |u, p| p.user_id == u.id }); a call of a column's getter on
a row is the column, and on a model the block captured, its value.
/home/runner/work/rotor/rotor/src/translate.qz:56
Constants
OR: Int
Precedences, loosest first (PostgreSQL's order).
AND: Int
NOT: Int
IS: Int
CMP: Int
LIKE: Int
OTHER: Int
ADD: Int
MUL: Int
ATOM: Int
COMPARISONS: Hash[Symbol, String]
ARITHMETIC: Hash[Symbol, String]
INT_DIV: Meta::MethodRef
The overloads whose SQL differs from the operator's: Int#/(Int)
floors and Int#%(Int) takes the divisor's sign; Int#/(Float) is
a plain /.
INT_MOD: Meta::MethodRef
INT_BY_FLOAT: Meta::MethodRef
NONE: Int
What row_in gives for what is not a row, and for a self that may
be any receiver's.
ANY: Int
Class methods
def self.called[A, B, R](&q: Quoted[(A, B) -> R]) -> Meta::MethodRef
The method q's body calls.
def self.new(sources: Array[Rotor::Source], captures: Array[Object], file: String, scopes: Array[Rotor::Scope], guards: Rotor::Guards = …, non_null: Array[[Int, Symbol]] = …) -> Rotor::Translator
def self.of(sources: Array[Rotor::Source], expr: Meta::Expr, captures: Array[Object], file: String) -> [Rotor::Translator, Meta::Expr]
The translator of a quoted block over the rows of sources, and the
block's one expression.
def self.body(expr: Meta::Expr, file: String) -> [Array[Symbol], Meta::Expr]
A block's parameters and its one expression.
def self.scope(params: Array[Symbol], tables: Array[Int]) -> Rotor::Scope
The scope of a block over the rows of tables (indexes among the
query's): its receiver when it has no parameters (the row of a
single table), else its parameters, one per table (the first
parameter for a single table).
def self.line_of(e: Meta::Expr) -> Int
The line of e.
def self.meet?(ls: Array[Type[Object]], rs: Array[Type[Object]]) -> Bool
Whether values of the classes ls and of rs (nil aside) can be
equal: a class in both, Int and Float, nil only or a class the
translator does not know (Object) on either side.
def self.never_equal(ls: Array[Type[Object]], rs: Array[Type[Object]]) -> String
def self.a(k: Type[Object]) -> String
def self.test_error(e: Meta::Expr, what: String, file: String) -> String
The error for e, where what (an && or || of an operand other
than a Bool) is a value.
def self.value_error(e: Meta::Expr, what: String, file: String) -> String
The error for e, which is NULL where what is, used as a value.
def self.nil_advice(what: String) -> String
What to do when what can be NULL is not a column, which nil?
tells nothing of in SQL: a nil captured or written.
def self.column_named?(e: Meta::Expr, what: String) -> Bool
Whether what is shown in e as a call of a getter on a row or
self: a column (not a capture, nor a captured model's value).
def self.show(e: Meta::Expr) -> String
e as Quarz source, for messages (a row's receiver left implicit).
def self.shown_operand(e: Meta::Expr) -> String
show(e), parenthesized when it is an operator's.
def self.label(m: Meta::MethodRef) -> String
m for messages: `Int#>`, `Rotor::SQL.lower`.
def self.null?(s: Rotor::Sql) -> Bool
Whether s is nil: a known nil, or an if nil either way.
def self.order_key(s: Rotor::Sql) -> Rotor::Sql
s as an order key: an if nil either way (NULL, a constant
PostgreSQL refuses there) typed.
def self.union(xs: Array[Type[Object]], ys: Array[Type[Object]]) -> Array[Type[Object]]
xs and the classes of ys not in it.
Methods
def guards -> Array[Rotor::Guard]
The kinds of captured values the translation so far holds for: the
same tree with captures of these kinds translates the same, up to
the values of its Rotor::Piece::Bound pieces.
def inner(sources: Array[Rotor::Source], scope: Rotor::Scope) -> Rotor::Translator
This translator for a block inside the one it translates, whose
scope is scope, over sources (the tables a for has joined so
far).
def row_of(e: Meta::Expr) -> Int
The table whose row e is (an index among the query's), NONE
for none.
def file -> String
The file the block is written in.
def sql(e: Meta::Expr) -> Rotor::Sql
e as SQL (made once for each mode and facts: @sqls).
def operand(e: Meta::Expr, typed: Bool = …) -> Rotor::Sql
e as SQL where it is a value, not a condition: an update's value,
an order's key, an operand. A comparison that can be NULL
(Sql#tri) is refused: NULL is not false there.
def one_type(e: Meta::Expr) -> Void
Refuses e as a value when its classes are more than one SQL type
holds (a Bool and another value, a String and an Int): a
SQL CASE or COALESCE of them is an error in PostgreSQL. Ints and
Floats meet in double precision; nil and what the translator does
not know the class of (Object) meet anything.
def valued_check(e: Meta::Expr) -> Void
one_type of e as a value (an order key).
def value(e: Meta::Expr) -> Rotor::Sql
e translated as a value (@value), its refusals left to the
caller (operand).
def column_of(e: Meta::Expr) -> [Int, Rotor::Column]?
The table and column e is (a column's getter called on a row), or
nil.
def reads(e: Meta::Expr) -> Array[Array[Rotor::Column]?]
The columns e reads of each table's row, in the table's order, nil
for one whose row it may read more of: it calls another method of the
row or passes the row on (its value is computed in Quarz,
Rotor::Query#select). An association's getter reads the key it
needs.
def untranslatable(what: String, line: Int) -> Nothing
Raises the error for what at line.
def classes(e: Meta::Expr) -> Array[Type[Object]]
The classes e may have in Quarz, as translated: a column's class,
a known value's (Nil for nil: a literal, a capture, a captured
model's column, an if without else), a comparison's Bool,
arithmetic's by its operands' (Int only from two Ints). An if
gives its branches' (only the one a known condition takes, as sql
does). A column that can be NULL (past the nil? facts) gives Nil
as well, so an update refuses it into a non-null column. For an update
to check its value against the column, and a condition to be tested
for its truthiness: PostgreSQL would convert another class on
assignment (round a double precision into a bigint, write a number
as text) and refuses one as a condition. (Read as a translation
does, guarded.)
l && r and l || r are Quarz's: the classes of what makes the
left operand the value (its falsy ones for &&, its truthy ones for
||) and the right operand's.