pub struct CallSyntax {Show 14 fields
pub named_argument: bool,
pub utc_special_functions: bool,
pub columns_expression: bool,
pub extract_from_syntax: bool,
pub try_cast: bool,
pub restricted_cast_targets: bool,
pub extract_string_field: bool,
pub method_chaining: bool,
pub sqljson_constructors_require_argument: bool,
pub sqljson_expression_functions: bool,
pub xml_expression_functions: bool,
pub variadic_argument: bool,
pub merge_action_function: bool,
pub convert_function: bool,
}Expand description
Dialect-owned function-call syntax accepted by the parser.
The call-tail and special-call-form family, split out of ExpressionSyntax when it
crossed its 16-field line; the aggregate/window call forms and the StringFunc keyword
special forms later split out again into AggregateCallSyntax and StringFuncForms
at their own 16-field lines. Each flag decides whether the parser admits the form at
its call-grammar position, and when off the introducing keyword/arrow is left unconsumed
and surfaces as a clean parse error (named_argument additionally gates the =>/:=
tokenizer lexemes).
Fields§
§named_argument: boolAccept PostgreSQL named function arguments f(name => value) and the
deprecated f(name := value). Also gates the tokenizer for the => / :=
arrow lexemes. Shared := claim: MySQL’s
SessionVariableSyntax::variable_assignment also enables := lexing for
SET @v := …; the two never coexist in a shipped preset, so one
Operator::ColonEquals token stays unambiguous per
dialect (see tokenizer := munch comments).
utc_special_functions: boolAccept MySQL’s UTC_DATE / UTC_TIME / UTC_TIMESTAMP niladic date/time
functions — the UTC-clock analogues of the CURRENT_* special value functions,
sharing the same nullary (plus optional precision on the time forms) grammar
production. A parser-acceptance gate only: the keywords always tokenize (they are
non-reserved outside MySQL), so when off they stay ordinary column/function names.
Expression position only — MySQL has no PostgreSQL-style func_table promotion.
columns_expression: boolRead COLUMNS(<selector>) as DuckDB’s star-expression column selector
(Expr::Columns) rather than an ordinary call to a
function named columns. A grammar-position gate keyed on the (non-reserved)
COLUMNS keyword immediately followed by (: DuckDB has no user function of
that spelling, so the form is unambiguous once the flag is on (the tokenizer is
untouched — the disambiguation is a parser lookahead, mirroring ARRAY[/ROW().
A bare columns with no ( stays an identifier in every dialect. Separate from
SelectSyntax::wildcard_modifiers because
the surfaces sit in different grammar positions — COLUMNS(…) is an expression
(it nests in sum(COLUMNS(*)), COLUMNS(*)::JSON), the * modifiers are a
projection-item tail — and are read by different parser code (expression vs
select-item). When off, COLUMNS(x) parses as a plain function call, matching
every non-DuckDB dialect. On for DuckDB / Lenient, off elsewhere.
extract_from_syntax: boolAccept the EXTRACT(<field> FROM <source>) datetime-field extraction special
form (SQL-92 F052; PostgreSQL). On for ANSI/PostgreSQL/MySQL/DuckDB/Lenient.
SQLite has no EXTRACT (its date functions are strftime/date/…), so it is
off; EXTRACT then reads as an ordinary identifier/function name and the FROM
inside its parentheses surfaces as a clean parse error. Gates only the
FROM-separated form — an ordinary extract(a, b) call is unaffected.
try_cast: boolRead TRY_CAST(<expr> AS <type>) as DuckDB’s null-on-failure cast — the same
Expr::Cast shape as CAST, distinguished by the
canonical try flag (DuckDB’s own serialized tree carries try_cast: true), not
a spelling tag: null-on-failure is different semantics, not a different spelling
of CAST. A grammar-position gate keyed on the (DuckDB-only) TRY_CAST
keyword immediately followed by (; when off, TRY_CAST reads as an ordinary
function name and the AS inside its parentheses surfaces as a clean parse error,
matching every non-DuckDB dialect (verified: PostgreSQL syntax-errors at AS). On
for DuckDb/Lenient.
restricted_cast_targets: boolRestrict the CAST(<expr> AS <target>) target to MySQL’s narrow cast_type
grammar rather than the full column-type vocabulary. Off for
ANSI/PostgreSQL/SQLite/DuckDB/Lenient, whose casts admit any type name. On for
MySQL, whose CAST/CONVERT target is a closed set —
SIGNED/UNSIGNED [INTEGER|INT], CHAR/NCHAR/CHARACTER/NATIONAL CHAR,
BINARY, DATE, DATETIME, TIME, DECIMAL/DEC, DOUBLE/DOUBLE PRECISION,
FLOAT, REAL, JSON, YEAR, and the spatial types (POINT, LINESTRING,
POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION, and
the GEOMCOLLECTION alias) — so the common column types INT/INTEGER/
SMALLINT/BIGINT/TINYINT, VARCHAR/TEXT, TIMESTAMP, NUMERIC, BOOLEAN,
VARBINARY/BLOB/BIT, bare GEOMETRY, and any user-defined name are the syntax
error MySQL reports in cast position (while remaining valid as column types). When on,
the parser parses the target type as usual, then rejects it unless it is one of the
MySQL cast targets (the whole set engine-measured on mysql:8 —
mysql-faithful-cast-type-production).
YEAR and the spatial cast targets parse as user-defined names, so the faithful
production layers a name allowlist over the shape check (the parser’s
is_mysql_cast_target); the inert trailing INTEGER/INT of SIGNED/UNSIGNED is
folded onto the standalone numeric modifier. The one engine-measured residual is the
CHAR charset annotation
(CAST(x AS CHAR CHARACTER SET utf8mb4), and the ASCII/UNICODE/trailing-BINARY
shorthands): MySQL accepts these, but type-name charset/collation is a general MySQL
feature the shared type grammar does not model at all (columns take the same
annotation), so it is over-rejected here — a separate type-grammar feature, not a
cast-target-membership gap, and invisible to every corpus.
extract_string_field: boolAccept a string literal as the EXTRACT('<field>' FROM <source>) field, as DuckDB
admits (extract('year' FROM x)), storing the quoted field as an
Ident with QuoteStyle::Single so
it round-trips. On for Postgres/DuckDb/Lenient. When off the field is a bare
identifier only, so a leading string surfaces as a clean parse error (the standard
EXTRACT field is an identifier). PostgreSQL admits the same quoted field (Sconst
in its extract_arg) — engine-verified against pg_query, including the reject
boundary (a non-string non-identifier field rejects on both) — so the flag ships on
under the Postgres preset too.
method_chaining: boolAccept DuckDB’s dot-method call chaining on a value — a postfix .<method>(<args>)
on a non-name receiver (list(forecast).list_transform(x -> x + 10)) that desugars
to the ordinary function call <method>(<receiver>, <args>). On for DuckDb/Lenient.
A plain name.method(args) is already the schema-qualified call the object-name
grammar reads, so the postfix fires only on a receiver that is not a bare name (a
function-call result, a parenthesized expression, …); there is no ambiguity with a
qualified call. When off, a .method( after a value surfaces as a clean parse error.
sqljson_constructors_require_argument: boolReject an empty argument list on PostgreSQL’s SQL/JSON constructor keywords — the
closed set PG_SQLJSON_EMPTY_REJECTING_CONSTRUCTORS in the parser crate (JSON,
JSON_SCALAR, JSON_SERIALIZE). PostgreSQL parses these through dedicated gram.y
productions that require the context-item / value argument, so JSON() /
JSON_SCALAR() / JSON_SERIALIZE() is a syntax error, whereas we would otherwise
admit them as ordinary niladic calls. Keyed on a single unquoted name, so a quoted
"json"() stays an ordinary call PostgreSQL accepts (rejected only at name
resolution). On for PostgreSQL only. The set is deliberately narrow and extension-
shaped: the JSON_VALUE/JSON_QUERY grammar ([[pg-sqljson-expression-functions]])
carries the same arity floor via sqljson_expression_functions.
sqljson_expression_functions: boolParse the SQL:2016/2023 SQL/JSON expression functions as dedicated special forms:
the JSON_VALUE/JSON_QUERY/JSON_EXISTS query functions with their
PASSING/RETURNING/FORMAT JSON/wrapper/quotes/ON EMPTY/ON ERROR clause
tails, the JSON_OBJECT/JSON_ARRAY constructors and their JSON_OBJECTAGG/
JSON_ARRAYAGG aggregates (with [ABSENT|NULL] ON NULL and [WITH|WITHOUT] UNIQUE [KEYS]), the bare JSON/JSON_SCALAR/JSON_SERIALIZE constructors, and
the IS [NOT] JSON [VALUE|ARRAY|OBJECT|SCALAR] [WITH|WITHOUT UNIQUE [KEYS]]
predicate. On for PostgreSQL/Lenient (engine-verified against pg_query); the
clause grammar is PostgreSQL’s raw-parse surface (per-function legality such as
JSON_VALUE rejecting a wrapper is enforced, while the shared behaviour set that
PostgreSQL only narrows during parse analysis is admitted uniformly). Off for
MySQL/DuckDB/SQLite/ANSI: MySQL has its own JSON functions with a different
grammar, DuckDB/SQLite have no SQL/JSON standard special forms, and those
dialects keep the keywords as ordinary function/column names. When off, the
keyword heads fall through to the ordinary call/name path exactly as before.
Composes with sqljson_constructors_require_argument:
the empty JSON()/JSON_SCALAR()/JSON_SERIALIZE() reject is enforced by these
special forms requiring their argument (PostgreSQL), while a dialect with the
arity floor off (Lenient) falls the empty form back to an ordinary niladic call.
xml_expression_functions: boolParse the SQL:2006 SQL/XML expression functions as dedicated special forms: the
xmlelement/xmlforest/xmlconcat/xmlparse/xmlpi/xmlroot/xmlserialize/
xmlexists constructors — with their keyword-clause grammar inside the parens
(NAME <label>, xmlattributes(…), {DOCUMENT|CONTENT}, {PRESERVE|STRIP} WHITESPACE, VERSION {…|NO VALUE}, STANDALONE {YES|NO|NO VALUE}, AS <type> [[NO] INDENT], PASSING [BY {REF|VALUE}] …) — and the IS [NOT] DOCUMENT
predicate. On for PostgreSQL/Lenient (engine-verified against pg_query); the
clause grammar is PostgreSQL’s raw-parse surface. Off for MySQL/DuckDB/SQLite/ANSI:
none of those dialects have the SQL/XML standard special forms, and they keep the
xml* keywords as ordinary function/column names. When off, the keyword heads fall
through to the ordinary call/name path exactly as before. The xmlagg aggregate is
not gated here — it is an ordinary keyword-free aggregate name that already parses
through the ordinary aggregate call path in every dialect.
variadic_argument: boolAccept the call-site VARIADIC argument marker that spreads an array over a
variadic parameter (f(a, VARIADIC arr), f(VARIADIC name => arr)), riding the
shared FunctionArg’s
variadic flag. On for PostgreSQL/DuckDb/
Lenient (both engines parse-accept it with identical rules — engine-probed on
pg_query PG-17 and DuckDB 1.5.4). A parse-layer gate: the parser admits the
VARIADIC prefix only on the last argument of the list and rejects it alongside
an ALL/DISTINCT quantifier, mirroring both engines’ gram.y productions
(func_application: … ',' VARIADIC func_arg_expr), which carry no quantifier and
place VARIADIC last. When off (ANSI/MySQL/SQLite), the VARIADIC keyword is left
unconsumed and surfaces as a clean parse error. The argument-type check (the spread
value must be an array) is a binding concern neither parser enforces.
merge_action_function: boolAccept PostgreSQL’s merge_action() — the zero-argument special function that
reports which MERGE branch produced a row ('INSERT'/'UPDATE'/'DELETE'),
valid only in a MERGE ... RETURNING list. PostgreSQL gives it a dedicated
func_expr_common_subexpr production (MERGE_ACTION '(' ')'), so at raw parse it
is accepted anywhere an expression is (the MERGE-RETURNING-only restriction is a
parse-analysis check, engine-verified against pg_query: SELECT merge_action()
raw-parse-accepts) but takes strictly empty parens — merge_action(1) and
merge_action() OVER () are both syntax errors (probed). The keyword is reserved
against ordinary calls (POSTGRES_NON_GENERIC_FUNCTION_KEYWORDS), so when off it
stays the “no call form” reject it already was; when on, the strictly niladic form
parses to the canonical Expr::Function shape (name
merge_action, no arguments). On for PostgreSQL/Lenient; off elsewhere (no other
shipped dialect has the form). A bare merge_action with no ( is untouched.
convert_function: boolAccept MySQL’s CONVERT special-form function — both the comma-form cast
CONVERT(<expr>, <type>) and the transcoding CONVERT(<expr> USING <charset>)
form (grammar’s one CONVERT '(' … ')' production, two shapes). Only CONVERT
immediately followed by ( opens it; when off, CONVERT keeps its ordinary
function-name reading (PostgreSQL’s plain convert(bytea, name, name) call is
unaffected — engine-verified against pg_query, which parses CONVERT('x', 'a', 'b')
as an ordinary call and rejects the USING form). The comma form folds onto the
Expr::Cast node as CastSyntax::Convert
and shares restricted_cast_targets’ cast_type
gate (so CONVERT(1, INT) rejects wherever CAST(1 AS INT) does); the USING form
is a StringFunc::ConvertUsing whose charset
operand is a MySQL charset_name (ident_or_text or the BINARY transcoding name).
On for MySQL/Lenient; off elsewhere (no other shipped dialect has the special form).
Implementations§
Source§impl CallSyntax
impl CallSyntax
Source§impl CallSyntax
impl CallSyntax
Source§impl CallSyntax
impl CallSyntax
Source§impl CallSyntax
impl CallSyntax
Source§impl CallSyntax
impl CallSyntax
Source§impl CallSyntax
impl CallSyntax
Trait Implementations§
Source§impl Clone for CallSyntax
impl Clone for CallSyntax
Source§fn clone(&self) -> CallSyntax
fn clone(&self) -> CallSyntax
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more