Documentation
¶
Overview ¶
Package render turns an endpoint's SQL template into a statement and its arguments, and never writes a caller's value into the statement.
A SUBSET OF JINJA AND NOT JINJA. Text, `{{ name }}`, `{# comment #}` and `{% if %}/{% elif %}/{% else %}/{% endif %}` over names joined by `not`, `and` and `or` -- and a parse error naming whatever else was written. The syntax is Jinja's so an editor highlights it; the semantics are smaller on purpose. The spike that chose this over gonja (88 packages and 6.8 MB for five node kinds) is in the working record, and its other finding is the safety argument: a parser that knows only five things refuses the rest by not parsing them, where an allowlist over a full engine's AST is a list of thirty-seven things to remember to refuse.
`{{ x }}` IS A PLACEHOLDER. It renders as the dialect's `$n` or `@x` and the value travels in the arguments, so what a caller sends is data whatever it contains. The one exception is a value the caller marks Inline -- an enum, because `order by day $1` is not SQL -- and that is written into the text only if it is an identifier, checked here again rather than trusted.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsIdentifier ¶
IsIdentifier reports whether s may be written into the SQL as an Inline value -- the rule Render applies, for a caller to apply at load.
Types ¶
type Template ¶
type Template struct {
// contains filtered or unexported fields
}
Template is a parsed endpoint SQL.
func Parse ¶
Parse reads a template written for one dialect. The dialect is needed because whether `{{ x }}` sits inside a string or a comment is a question about that dialect's SQL: `#` is a comment in BigQuery and an operator in Postgres.
func (*Template) AllText ¶
AllText is every branch's text laid end to end, each `{{ }}` as NULL: what a caller reads to know which relations the template can read -- in any branch, because a model read only when a parameter is sent is still one whose rebuild changes the answer.
func (*Template) IsCondition ¶
IsCondition reports whether a condition tests the name.
func (*Template) Names ¶
Names is every name the template uses, in the order it is first used -- what the config checks a template against.
func (*Template) Render ¶
Render writes the statement for one request.
DETERMINISTIC: the same template, values and dialect give the same bytes and the same arguments, because the cache key is a hash of them. Arguments are numbered in the order their placeholders are written, and a name written twice is bound once.
func (*Template) Unconditional ¶
Unconditional reports whether `{{ name }}` is written outside every condition -- in every statement this template can render, whatever the caller sends. What the API asks of `tenant`: a filter that only exists in some branch is a filter the caller can choose to leave out.
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value is what a name stands for in one render.
func Bind ¶
Bind is a value that travels as an argument. It is one of the types dialect.Arg allows: string, int64, bool or dialect.Date.
func Inline ¶
Inline is a value written into the SQL text. Only an identifier is accepted, at render time, whatever the caller validated before.