Liking cljdoc? Tell your friends :D

datahike.pg.plpgsql.exec

Run a parsed plpgsql body.

The evaluator has two primitives and everything else is control flow:

  • evaluate an expression -- run SELECT <expr> and take one value
  • run a statement -- hand the source to the query handler

Both go through the handler this function was called from, which is what SPI is for PostgreSQL: the nested statement sees the same transaction, the same temporary tables and the same session. That is also why pl_exec.c is 9,226 lines and this is not -- most of it is memory contexts, plan caching and TupleDesc conversion, none of which we have to reproduce.

A variable reaches an embedded statement as a PARAMETER: the statement's references to it are rewritten to $n and the values are bound per call. That is how PostgreSQL does it, and it is what makes the plan cacheable -- resolving a variable to its VALUE during translation made the plan specific to that value, so every execution re-translated and a body reading one variable cost 11ms a call against 0.3ms for one reading none.

Run a parsed plpgsql body.

The evaluator has two primitives and everything else is control flow:

  - evaluate an expression  -- run `SELECT <expr>` and take one value
  - run a statement         -- hand the source to the query handler

Both go through the handler this function was called from, which is
what SPI is for PostgreSQL: the nested statement sees the same
transaction, the same temporary tables and the same session. That is
also why `pl_exec.c` is 9,226 lines and this is not -- most of it is
memory contexts, plan caching and TupleDesc conversion, none of which
we have to reproduce.

A variable reaches an embedded statement as a PARAMETER: the
statement's references to it are rewritten to `$n` and the values are
bound per call. That is how PostgreSQL does it, and it is what makes
the plan cacheable -- resolving a variable to its VALUE during
translation made the plan specific to that value, so every execution
re-translated and a body reading one variable cost 11ms a call
against 0.3ms for one reading none.
raw docstring

datahike.pg.plpgsql.parse

Parse a plpgsql function body into an AST.

pl_gram.y is the specification. What that grammar actually does -- and what this does -- is parse the statement structure and hand every embedded expression and query to the SQL parser untouched. plpgsql has no expression grammar of its own: IF a > b THEN finds the THEN and gives a > b to the SQL layer as SELECT a > b. So the job here is to find where each embedded fragment ends, and to keep its SOURCE, which the executor later runs through the ordinary statement path.

Everything pl_gram.y accepts is parsed, including the constructs the executor does not implement. That is deliberate: CREATE FUNCTION walks the AST and refuses a body that uses one, naming it, so an unimplemented construct is a clean 0A000 at definition time rather than a wrong answer at call time.

The tokenizer is the SQL classifier's, so a keyword inside a string, a comment, a dollar-quoted body or a quoted identifier is not a keyword.

Parse a plpgsql function body into an AST.

`pl_gram.y` is the specification. What that grammar actually does --
and what this does -- is parse the *statement structure* and hand
every embedded expression and query to the SQL parser untouched.
plpgsql has no expression grammar of its own: `IF a > b THEN` finds
the `THEN` and gives `a > b` to the SQL layer as `SELECT a > b`. So
the job here is to find where each embedded fragment ends, and to
keep its SOURCE, which the executor later runs through the ordinary
statement path.

Everything `pl_gram.y` accepts is parsed, including the constructs
the executor does not implement. That is deliberate: `CREATE
FUNCTION` walks the AST and refuses a body that uses one, naming it,
so an unimplemented construct is a clean 0A000 at definition time
rather than a wrong answer at call time.

The tokenizer is the SQL classifier's, so a keyword inside a string,
a comment, a dollar-quoted body or a quoted identifier is not a
keyword.
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close