Skip to main content

rudb_functions/
signature.rs

1//! What a function call resolves to.
2//!
3//! This is the smallest thing the binder cannot be written without: given a name and the types of
4//! the arguments, which function is that and what does it return. It is not the function library.
5//! There is no implementation attached to any of these yet, no volatility, no statistics and no
6//! vectorized kernel, and all of that is what this crate grows into.
7//!
8//! The set here is what M0 reaches, which is the operators the transformer emits plus the five
9//! aggregates a first query needs. A name that is not in it produces DuckDB's own error text rather
10//! than a Rust panic or a silent pass through, because a function that binds and then does nothing
11//! is a wrong answer and a function that does not bind is a message.
12//!
13//! Overload resolution here is by shape rather than by an exact signature match. `+` does not have
14//! one entry per pair of numeric types, it has one entry that says both arguments promote and the
15//! result is what they promote to. DuckDB's own table is closer to the former and it needs to be,
16//! because it carries an implementation per pair. Ours does not carry one yet, and inventing 169
17//! rows before there is a kernel behind any of them would be inventing the wrong 169 rows.
18
19use rudb_common::{Error, LogicalType, MAX_DECIMAL_WIDTH, Result};
20
21/// Whether a name is a scalar function, an aggregate or a window.
22///
23/// The binder needs to ask before it knows which slot the call goes in, since an aggregate is only
24/// legal in an aggregate list and the error for one in the wrong place should say so.
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum FunctionKind {
27    /// One row in, one row out.
28    Scalar,
29    /// Many rows in, one row out.
30    Aggregate,
31    /// Many rows in, one row out per row, and the answer comes from where the row sits.
32    ///
33    /// Every aggregate is also usable as a window, so this is not the kind of everything that can
34    /// go inside an `OVER`. It is the kind of the names that can go nowhere else, which is why a
35    /// call to one without an `OVER` is an error rather than a call.
36    Window,
37}
38
39/// A resolved call.
40///
41/// `arguments` is what the arguments have to be cast to and not what they were, so the binder can
42/// insert the casts without redoing the resolution. It is the same length as what was passed in.
43#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct Resolved {
45    /// The function's own name, which is what the plan records.
46    pub name: &'static str,
47    /// Scalar or aggregate.
48    pub kind: FunctionKind,
49    /// What each argument has to be cast to.
50    pub arguments: Vec<LogicalType>,
51    /// What the call produces.
52    pub returns: LogicalType,
53}
54
55/// How the argument types decide the return type.
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57enum Shape {
58    /// Every argument promotes to one type and the result is that type. `*` and `min`.
59    Promoted,
60    /// Two arguments, and a decimal product is as wide as both operands together. `*`.
61    Multiplied,
62    /// Every argument promotes to one type, and a decimal promotion becomes a double instead. `//`.
63    ///
64    /// `//` is integer division only when there are integers on both sides of it. Upstream answers
65    /// `7.5 // 2.5` with the DOUBLE 3.0 and `7.9 // 1.0` with 7.9, so it does not truncate what it
66    /// divides once a side is not an integer, and it is `/` under another spelling there. The one
67    /// thing it does not do is go to a double the way `/` does whatever it was given, since
68    /// `7 // 2` is 3 and an INTEGER on both engines, so it cannot share `/`'s shape. A FLOAT stays
69    /// a FLOAT, which was measured, so this is a rule about decimals rather than about width.
70    Divided,
71    /// Slash promotes integers and decimals to double but preserves two floats as float.
72    Slashed,
73    /// Every argument promotes and a decimal result gains a digit for the carry. `+` and `-`.
74    ///
75    /// Adding two `DECIMAL(18,0)` produces nineteen digits, so a rule that gives the sum eighteen
76    /// of them is a rule that raises an overflow on the largest inputs it accepts. Only a decimal
77    /// moves: an integer result is the promoted type, since promotion already went to a type that
78    /// holds both, and the unary forms of the two operators do not widen because negating a number
79    /// cannot carry.
80    PromotedWithCarry,
81    /// Every argument promotes to one type and the result is fixed. `=` over anything is boolean.
82    PromotedTo(Fixed),
83    /// Every argument is cast to one fixed type and the result is another. `||` over strings.
84    FixedTo(Fixed, Fixed),
85    /// Every argument has to be that type already and the result is fixed. `lower`, `length`,
86    /// `LIKE`, `chr`.
87    ///
88    /// The difference from [`Shape::FixedTo`] is the word already. DuckDB refuses `lower(123)`,
89    /// `length(DATE '2020-01-01')` and `123 LIKE '1%'` with a binder error naming the overloads it
90    /// does have, and it refuses a BLOB as well, so the rule is VARCHAR rather than anything a cast
91    /// can reach. `||` is the one string function that really does take anything, since `1 || 'a'`
92    /// is `1a` upstream, and it keeps [`Shape::FixedTo`] for that reason.
93    ///
94    /// The argument type is part of the shape because the same rule holds away from strings.
95    /// `chr(col0 INTEGER)` is the only overload upstream has and it refuses `chr(65.9)` and
96    /// `chr(65::BIGINT)` rather than narrowing either of them.
97    Exact(Fixed, Fixed),
98    /// Every argument has to reach that type by widening and the result is fixed. `to_days`.
99    ///
100    /// Between [`Shape::Exact`] and [`Shape::FixedTo`], and it is where the interval constructors
101    /// sit. `to_hours(25)` is an INTEGER reaching a BIGINT and upstream answers it, `to_seconds(1.5)`
102    /// is a DECIMAL reaching a DOUBLE and upstream answers that too, and `to_days(1.7)` is a
103    /// DECIMAL that would have to lose its fraction to reach an INTEGER, which upstream refuses with
104    /// a binder error naming both overloads. So the question is whether promotion gets there and not
105    /// whether the type is already right, and not whether a cast exists, since a cast exists for
106    /// every one of the three.
107    Widened(Fixed, Fixed),
108    /// Every argument widens to the one type they all reach, no narrower than a floor, and the
109    /// result is fixed. `age(x, y)`.
110    ///
111    /// The difference from [`Shape::Widened`] is which way the arguments are allowed to pull. There
112    /// the floor is the answer and an argument wider than it is refused, which is right for a name
113    /// whose one overload reads a fixed type. Here the arguments meet each other first, so
114    /// `age(DATE, DATE)` reads two timestamps because the floor says so and `age(now(), now())`
115    /// reads two zoned ones because the arguments say so. Upstream has a row per combination and
116    /// this is the one rule they follow.
117    WidenedTogether(Fixed, Fixed),
118    /// The arguments are whatever they are and the result is fixed. `count(x)` over anything.
119    AnyTo(Fixed),
120    /// The first `n` arguments are cast to one fixed type, the rest are left alone, and the result
121    /// is fixed. `date_part('minute', x)` reads a part of whatever `x` is, and
122    /// `regexp_extract(s, p, 2)` takes two strings and then a number that has to stay one.
123    LeadingFixedTo(usize, Fixed, Fixed),
124    /// The first argument is cast to one fixed type, the rest are left alone, and the result is the
125    /// last argument's own type. `date_trunc('month', x)` gives back whatever kind of date `x` was.
126    LeadingFixedToLast(Fixed),
127    /// Every argument promotes and an integer result widens to the accumulator. `sum`.
128    Accumulated,
129    /// The first argument is a string or a list and the result is one piece of it. `array_extract`.
130    ///
131    /// The index is a BIGINT and nothing is cast to one, which is upstream's rule rather than an
132    /// omission here: `[1, 2, 3][1.5]` is a binder error there listing the four overloads, so a
133    /// decimal index is refused and not rounded. The bounds of a slice are the other way round,
134    /// which is why that is a shape of its own and not this one with a longer arity.
135    Extracted,
136    /// The first argument is a string or a list, the rest are the bounds, and the result is the first
137    /// argument's own type. `array_slice`.
138    Sliced,
139    /// The first `n` arguments have to be strings already, the rest are indexes, and the result is
140    /// fixed. `substring(s, a, b)` and `overlay(s, r, a, b)`.
141    ///
142    /// An index is a BIGINT and nothing is cast to one, which is the same rule
143    /// [`Shape::Extracted`] follows and is upstream's: `substring('abcdef', 2.5, 3)` is a binder
144    /// error there listing the two overloads rather than a substring from the second character.
145    TextThenIndex(usize, Fixed),
146    /// Every argument promotes, and the result is the first argument's own type. `nullif`.
147    ///
148    /// The promotion is for the comparison and not for the answer, which is what makes this its own
149    /// shape: `typeof(nullif(1, 2.5))` is INTEGER upstream and the comparison behind it is still
150    /// `1 = 2.5`, so the two arguments have to meet somewhere and the answer has to come back from
151    /// where it started. Comparing at the first argument's type instead would round the second one
152    /// and answer `nullif(2, 2.5)` with null.
153    PromotedToFirst,
154    /// One string naming a setting, and the result is whatever type that setting holds.
155    ///
156    /// `current_setting` and nothing else. It is a shape rather than a fixed pair because the pin
157    /// declares the return as `ANY` and then works it out from the name that was passed, which is
158    /// why `typeof(current_setting('threads'))` is BIGINT there and
159    /// `typeof(current_setting('memory_limit'))` is VARCHAR. Both come from one overload.
160    ///
161    /// Resolving this is an error and that is the point of it. The binder folds the call to the
162    /// setting's value before it asks this table anything, so the only way a call arrives here is
163    /// the way the fold cannot happen, which is an argument that is not a constant, and that is the
164    /// case the pin refuses in the same words.
165    Setting,
166    /// The first argument is the value and its type is the answer, the second is a row count, and
167    /// the third is another value of the first's type. The five windows that read a row rather than
168    /// aggregate one.
169    ///
170    /// The pin prints the widest of them as `lag(col T, "offset" BIGINT := 1, "default" ANY := NULL)
171    /// -> T`, and `nth_value(col0 ANY, col1 BIGINT) -> ANY` and `first_value(col0 ANY) -> ANY` are
172    /// that rule with the tail cut off, so one shape covers all five. The count is a BIGINT and the
173    /// default is cast to the column's type rather than left alone, which is why `lag(i, 1, 0.5)`
174    /// over an INTEGER column answers 1 and `lag(k, 1, 'z')` over one raises a conversion error at
175    /// run time rather than a binder error at bind time. The cast is legal and it is the value that
176    /// will not go through it.
177    ///
178    /// The spelling is carried because the pin does not use one for all five. `duckdb_functions()`
179    /// there says `[T, BIGINT, ANY] -> T` for `lag` and `lead` and `[ANY] -> ANY` for the other
180    /// three, which is the same rule written two ways, and a table that prints what the pin prints
181    /// has to know which way each row goes.
182    ValueThenCountThenValue(Spelled),
183    /// One argument, nothing is cast, and the result is that argument's own type. `fill`.
184    ///
185    /// The pin prints it as `fill(col0 ANY) -> ANY` and `typeof(fill(x) OVER (ORDER BY k))` there
186    /// gives back whatever `x` was, INTEGER for an INTEGER column and DECIMAL(10,2) for a decimal
187    /// one, so the declaration says nothing and the argument says everything. The rule that the
188    /// argument has to be a type arithmetic can reach is the binder's rather than this table's,
189    /// since it is the sort key and not just the argument that has to satisfy it.
190    AsGiven,
191    /// No arguments at all and a fixed result. `now()` and `current_schema()`.
192    ///
193    /// The session context functions, which are the ones whose answer comes from the connection
194    /// rather than from anything written in the query. The binder folds every one of them into a
195    /// constant before this table is asked, the same way it folds `typeof`, so what these rows are
196    /// for is the two questions the fold does not answer: which names exist, which is what
197    /// `duckdb_functions()` reports, and what `now(1)` says, which is the arity error rather than a
198    /// missing function.
199    Constant(Fixed),
200}
201
202/// How a shape names the argument whose type the call decides, and the result that follows it.
203///
204/// `T` says the two are the same type and `ANY` says the name does not commit to one. They mean the
205/// same thing to the binder, since both resolve from what was passed, and they are different words
206/// in the table `duckdb_functions()` prints.
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208enum Spelled {
209    Same,
210    Any,
211}
212
213impl Spelled {
214    const fn name(self) -> &'static str {
215        match self {
216            Self::Same => SAME,
217            Self::Any => ANY,
218        }
219    }
220}
221
222/// The return types a signature can name outright.
223///
224/// A small enum rather than a `LogicalType` so that the table stays a `const` and there is no
225/// allocation behind a lookup that happens once per expression in every query.
226#[derive(Debug, Clone, Copy, PartialEq, Eq)]
227enum Fixed {
228    Boolean,
229    Integer,
230    BigInt,
231    Double,
232    Varchar,
233    Date,
234    Time,
235    TimeTz,
236    Timestamp,
237    TimestampTz,
238    Interval,
239}
240
241impl Fixed {
242    fn ty(self) -> LogicalType {
243        match self {
244            Self::Boolean => LogicalType::Boolean,
245            Self::Integer => LogicalType::Integer,
246            Self::BigInt => LogicalType::BigInt,
247            Self::Double => LogicalType::Double,
248            Self::Varchar => LogicalType::Varchar,
249            Self::Date => LogicalType::Date,
250            Self::Time => LogicalType::Time,
251            Self::TimeTz => LogicalType::TimeTz,
252            Self::Timestamp => LogicalType::Timestamp,
253            Self::TimestampTz => LogicalType::TimestampTz,
254            Self::Interval => LogicalType::Interval,
255        }
256    }
257}
258
259/// How many arguments a function takes.
260///
261/// A range rather than a count because `-` is both the negation and the subtraction, and one name
262/// with two arities is much less trouble than two names that the transformer would have to tell
263/// apart before the binder ever sees the call.
264///
265/// `OneOf` is the range with a hole in it. `make_date` takes one argument or three and not two, and
266/// a range that accepted two would bind a call DuckDB refuses and then have nothing to compute.
267#[derive(Debug, Clone, Copy, PartialEq, Eq)]
268enum Arity {
269    Exactly(usize),
270    Between(usize, Option<usize>),
271    OneOf(&'static [usize]),
272}
273
274impl Arity {
275    const fn exactly(count: usize) -> Self {
276        Self::Exactly(count)
277    }
278
279    const fn between(least: usize, most: usize) -> Self {
280        Self::Between(least, Some(most))
281    }
282
283    const fn at_least(least: usize) -> Self {
284        Self::Between(least, None)
285    }
286
287    const fn one_of(counts: &'static [usize]) -> Self {
288        Self::OneOf(counts)
289    }
290
291    fn accepts(self, count: usize) -> bool {
292        match self {
293            Self::Exactly(wanted) => count == wanted,
294            Self::Between(least, most) => count >= least && most.is_none_or(|most| count <= most),
295            Self::OneOf(counts) => counts.contains(&count),
296        }
297    }
298
299    /// Every count this accepts, with an open end stopped one past where it starts, for the tests
300    /// that hold each row of the table to its own shape at each count it claims to take.
301    #[cfg(test)]
302    fn counts(self) -> Vec<usize> {
303        match self {
304            Self::Exactly(count) => vec![count],
305            Self::Between(least, most) => (least..=most.unwrap_or(least + 1)).collect(),
306            Self::OneOf(counts) => counts.to_vec(),
307        }
308    }
309
310    #[cfg(test)]
311    fn least(self) -> usize {
312        match self {
313            Self::Exactly(count) | Self::Between(count, _) => count,
314            Self::OneOf(counts) => counts.iter().copied().min().unwrap_or(0),
315        }
316    }
317}
318
319struct Entry {
320    name: &'static str,
321    kind: FunctionKind,
322    arity: Arity,
323    shape: Shape,
324    /// Whether every argument has to be a number, which is the only argument constraint M0 needs.
325    numeric_only: bool,
326}
327
328/// The whole table.
329///
330/// One row per name. There are no overloads by argument type in here yet, because every name below
331/// has exactly one shape, and a second row for a name would need a rule for which one wins that is
332/// worth writing when there is a name that needs it.
333const TABLE: &[Entry] = &[
334    // Arithmetic. The result is what the operands promote to, so `INTEGER + BIGINT` is a `BIGINT`
335    // and the executor never has to widen mid expression. `+` and `-` take one argument as well as
336    // two, because the unary forms are the same function and DuckDB names them the same way, and
337    // they are the two that carry: a sum of two decimals needs a digit the operands do not have.
338    number("+", Arity::between(1, 2), Shape::PromotedWithCarry),
339    number("-", Arity::between(1, 2), Shape::PromotedWithCarry),
340    number("*", Arity::exactly(2), Shape::Multiplied),
341    number("%", Arity::exactly(2), Shape::Promoted),
342    // `/` is the exception and it is DuckDB's exception too: `7 / 2` is 3.5 and not 3, so the
343    // result is a double whatever went in, and `//` is the operator that keeps the integer.
344    number("/", Arity::exactly(2), Shape::Slashed),
345    number("//", Arity::exactly(2), Shape::Divided),
346    number("abs", Arity::exactly(1), Shape::Promoted),
347    // Strings.
348    // `||` is the one that takes anything and turns it into a string, which is why it is a
349    // `FixedTo` and everything under it is a `Text`. `1 || 'a'` is `1a` upstream.
350    Entry {
351        name: "||",
352        kind: FunctionKind::Scalar,
353        arity: Arity::exactly(2),
354        shape: Shape::FixedTo(Fixed::Varchar, Fixed::Varchar),
355        numeric_only: false,
356    },
357    text("lower", Arity::exactly(1), Fixed::Varchar),
358    text("upper", Arity::exactly(1), Fixed::Varchar),
359    text("length", Arity::exactly(1), Fixed::BigInt),
360    // `strlen` is bytes where `length` is characters, and it is a separate row rather than an alias
361    // for that reason. `strlen('héllo')` is 6 upstream and `length('héllo')` is 5. It is here
362    // because DuckDB's own ClickBench entry writes `AVG(STRLEN(URL))` in query 28, so a rudb
363    // that has only `length` cannot run that board at all without the SQL being changed, and the
364    // whole point of the comparison is that it is not changed.
365    text("strlen", Arity::exactly(1), Fixed::BigInt),
366    // The four SQL string functions that have a grammar rule of their own, plus the aliases upstream
367    // answers the same call with. Each alias is a row rather than a pointer at one, because the
368    // column a query gets back is named after the name that was written: `substr('abcdef', 2)` comes
369    // back as `substr('abcdef', 2)` upstream and not as a substring of anything.
370    Entry {
371        name: "substring",
372        kind: FunctionKind::Scalar,
373        arity: Arity::one_of(&[2, 3]),
374        shape: Shape::TextThenIndex(1, Fixed::Varchar),
375        numeric_only: false,
376    },
377    Entry {
378        name: "substr",
379        kind: FunctionKind::Scalar,
380        arity: Arity::one_of(&[2, 3]),
381        shape: Shape::TextThenIndex(1, Fixed::Varchar),
382        numeric_only: false,
383    },
384    Entry {
385        name: "overlay",
386        kind: FunctionKind::Scalar,
387        arity: Arity::one_of(&[3, 4]),
388        shape: Shape::TextThenIndex(2, Fixed::Varchar),
389        numeric_only: false,
390    },
391    // `left` and `right` count characters and clamp, and a negative count is a count from the other
392    // end rather than an error, so `left('abc', -1)` is `ab`. Both are declared
393    // `(VARCHAR, BIGINT)` upstream and neither casts its count, which is what
394    // [`Shape::TextThenIndex`] already says.
395    Entry {
396        name: "left",
397        kind: FunctionKind::Scalar,
398        arity: Arity::exactly(2),
399        shape: Shape::TextThenIndex(1, Fixed::Varchar),
400        numeric_only: false,
401    },
402    Entry {
403        name: "right",
404        kind: FunctionKind::Scalar,
405        arity: Arity::exactly(2),
406        shape: Shape::TextThenIndex(1, Fixed::Varchar),
407        numeric_only: false,
408    },
409    text("replace", Arity::exactly(3), Fixed::Varchar),
410    // `chr` is a code point and not a byte, so `chr(233)` is one character and not two bytes of
411    // something else. Its one overload upstream takes an INTEGER and it narrows nothing to reach
412    // it: `chr(65::BIGINT)` and `chr(65.9)` are both binder errors there.
413    Entry {
414        name: "chr",
415        kind: FunctionKind::Scalar,
416        arity: Arity::exactly(1),
417        shape: Shape::Exact(Fixed::Integer, Fixed::Varchar),
418        numeric_only: false,
419    },
420    // `concat` takes anything, joins it and drops the nulls instead of propagating them, so
421    // `concat('a', 1, NULL)` is `a1`. That last part is what makes it a third exception to the null
422    // in null out rule, next to `coalesce` and `nullif`, and it is the only one of the three that is
423    // an ordinary function rather than sugar for something else.
424    Entry {
425        name: "concat",
426        kind: FunctionKind::Scalar,
427        arity: Arity::at_least(1),
428        shape: Shape::FixedTo(Fixed::Varchar, Fixed::Varchar),
429        numeric_only: false,
430    },
431    text("position", Arity::exactly(2), Fixed::BigInt),
432    text("strpos", Arity::exactly(2), Fixed::BigInt),
433    text("instr", Arity::exactly(2), Fixed::BigInt),
434    text("trim", Arity::between(1, 2), Fixed::Varchar),
435    text("ltrim", Arity::between(1, 2), Fixed::Varchar),
436    text("rtrim", Arity::between(1, 2), Fixed::Varchar),
437    // Pattern matching. The transformer emits the operator spellings, so those are the names, and
438    // `LIKE` is one of them rather than a keyword the binder has to know about separately.
439    text("~~", Arity::exactly(2), Fixed::Boolean),
440    text("!~~", Arity::exactly(2), Fixed::Boolean),
441    text("~~*", Arity::exactly(2), Fixed::Boolean),
442    text("!~~*", Arity::exactly(2), Fixed::Boolean),
443    // Logic. `AND` and `OR` are conjunctions in the plan rather than calls, so only `NOT` is here.
444    Entry {
445        name: "not",
446        kind: FunctionKind::Scalar,
447        arity: Arity::exactly(1),
448        shape: Shape::FixedTo(Fixed::Boolean, Fixed::Boolean),
449        numeric_only: false,
450    },
451    // `coalesce` promotes across every argument, which is exactly what `Shape::Promoted` says, and
452    // it is the one scalar here that takes a variable number of them.
453    Entry {
454        name: "coalesce",
455        kind: FunctionKind::Scalar,
456        arity: Arity::at_least(1),
457        shape: Shape::Promoted,
458        numeric_only: false,
459    },
460    // `nullif(a, b)` is a macro upstream, `CASE WHEN a = b THEN NULL ELSE a END`, and it is a
461    // function here because the column it produces is named after the call rather than after the
462    // expansion. What that costs is the message for the wrong number of arguments: upstream's is a
463    // binder error about a macro listing `"nullif"(a, b)` under `Candidate macros:`, and the one
464    // below is the ordinary sentence about a function. Both refuse, and the reachable spelling of the
465    // mistake is the quoted `"nullif"(1)`, since the grammar has NULLIF with exactly two arguments
466    // and refuses any other count before the binder sees it.
467    Entry {
468        name: "nullif",
469        kind: FunctionKind::Scalar,
470        arity: Arity::exactly(2),
471        shape: Shape::PromotedToFirst,
472        numeric_only: false,
473    },
474    // Dates and times. `EXTRACT(minute FROM x)` is spelled `date_part('minute', x)` by the time it
475    // gets here, because that is what DuckDB's own parser does with it, so there is one entry for
476    // the two spellings. The part is a string and the thing it is a part of is left alone, which is
477    // what the two leading shapes are for: there is nothing to promote a timestamp towards.
478    // The answer is a double here and a bigint by the time the binder is finished with it, for
479    // every part but the two that carry a fraction. See `narrowed_part` in `rudb-bind`, which is
480    // where the value of the first argument gets to decide the type of the call.
481    Entry {
482        name: "date_part",
483        kind: FunctionKind::Scalar,
484        arity: Arity::exactly(2),
485        shape: Shape::LeadingFixedTo(1, Fixed::Varchar, Fixed::Double),
486        numeric_only: false,
487    },
488    Entry {
489        name: "date_trunc",
490        kind: FunctionKind::Scalar,
491        arity: Arity::exactly(2),
492        shape: Shape::LeadingFixedToLast(Fixed::Varchar),
493        numeric_only: false,
494    },
495    // The gap between two moments counted in calendar fields. Upstream has a one argument form as
496    // well, which measures from today, and it is not here because there is no clock in the engine
497    // yet and a function that invents one would be worse than a function that is missing.
498    //
499    // Widening rather than casting is the whole overload: a DATE widens to a TIMESTAMP and upstream
500    // accepts `age(DATE, DATE)`, while a TIME and an INTERVAL do not widen anywhere and upstream
501    // refuses both of those with a binder error rather than reading them as moments.
502    Entry {
503        name: "age",
504        kind: FunctionKind::Scalar,
505        arity: Arity::one_of(&[1, 2]),
506        shape: Shape::WidenedTogether(Fixed::Timestamp, Fixed::Interval),
507        numeric_only: false,
508    },
509    // The two that turn a number into a date and a timestamp, which is how every ClickBench entry
510    // on the board reads that data: the Parquet stores four of its columns as integers and every
511    // query in the set treats them as dates and times. DuckDB's own entry wraps them in exactly
512    // these two calls, so these are what let that entry run here unmodified.
513    //
514    // One argument is days since the epoch and three are a year, a month and a day. Upstream reads
515    // the single one as an INTEGER and the triple as three BIGINTs, and both are INTEGER here,
516    // because the column this is called on is an INTEGER and a widening pass over a hundred million
517    // values to reach a function that immediately narrows again is a pass nobody asked for. The
518    // difference shows on a year that does not fit in an INTEGER, where upstream converts and then
519    // complains about the destination and this complains about the cast.
520    Entry {
521        name: "make_date",
522        kind: FunctionKind::Scalar,
523        arity: Arity::one_of(&[1, 3]),
524        shape: Shape::FixedTo(Fixed::Integer, Fixed::Date),
525        numeric_only: true,
526    },
527    // Milliseconds since the epoch. Upstream also has seven overloads that read a date or a time
528    // and give the milliseconds back, which this table has no way to say yet because it is one row
529    // per name and those pick by argument type. `epoch_ms` of a timestamp is the missing half.
530    Entry {
531        name: "epoch_ms",
532        kind: FunctionKind::Scalar,
533        arity: Arity::exactly(1),
534        shape: Shape::FixedTo(Fixed::BigInt, Fixed::Timestamp),
535        numeric_only: true,
536    },
537    // The thirteen ways to build an interval out of a count of one unit, which is what
538    // `INTERVAL 1 DAY` is once the transformer has rewritten it, and `to_days(1)` written out by
539    // hand is the same call. Eleven of them count whole units and the two that can carry a fraction
540    // take a DOUBLE, so `INTERVAL 2.7 SECOND` is two and seven tenths of a second while
541    // `INTERVAL 1.5 DAY` is one day.
542    //
543    // Upstream declares the eight that land in months or days twice, once over an INTEGER and once
544    // over a BIGINT, and only the first is here, for the reason the head of this table gives: one
545    // row per name, and a second row needs a rule for which one wins. The rewrite always casts to
546    // the width the row below wants, so the literal is unaffected and what is missing is a
547    // handwritten `to_days(3::BIGINT)`, which is refused here and answered there. The three that
548    // land in microseconds have the BIGINT overload and no INTEGER one, so those rows are exact.
549    built("to_years", Fixed::Integer),
550    built("to_months", Fixed::Integer),
551    built("to_quarters", Fixed::Integer),
552    built("to_decades", Fixed::Integer),
553    built("to_centuries", Fixed::Integer),
554    built("to_millennia", Fixed::Integer),
555    built("to_days", Fixed::Integer),
556    built("to_weeks", Fixed::Integer),
557    built("to_hours", Fixed::BigInt),
558    built("to_minutes", Fixed::BigInt),
559    built("to_microseconds", Fixed::BigInt),
560    built("to_seconds", Fixed::Double),
561    built("to_milliseconds", Fixed::Double),
562    // `trunc` is here because the interval rewrite writes it, and it is an ordinary function anybody
563    // can write as well. Upstream has twenty six overloads and every one of them gives back the type
564    // it was handed, which is what `Shape::Promoted` says over one argument. The exception is the
565    // decimal, where upstream drops the scale and gives `DECIMAL(2,0)` for `trunc(1.7)` and this
566    // keeps `DECIMAL(2,1)` holding 1.0, since no shape in this table drops a scale.
567    number("trunc", Arity::exactly(1), Shape::Promoted),
568    // Regular expressions. The pattern is a string like the text is, so three of the four are the
569    // plain string shape. `regexp_extract` is not, because its third argument is the group number
570    // and casting that to a string and reading it back would be a way to accept `'two'`.
571    text("regexp_replace", Arity::between(3, 4), Fixed::Varchar),
572    text("regexp_matches", Arity::between(2, 3), Fixed::Boolean),
573    text("regexp_full_match", Arity::between(2, 3), Fixed::Boolean),
574    Entry {
575        name: "regexp_extract",
576        kind: FunctionKind::Scalar,
577        arity: Arity::between(2, 4),
578        shape: Shape::LeadingFixedTo(2, Fixed::Varchar, Fixed::Varchar),
579        numeric_only: false,
580    },
581    // Subscripting. A bracket is one of these two calls by the time the transformer is done with it,
582    // `x[2]` being `array_extract(x, 2)` and `x[1:2]` being `array_slice(x, 1, 2)`, which is what
583    // DuckDB's own transformer writes as well. Both take a string or a list and give back a piece of
584    // the same thing, so neither one can name its return type here: it is read off the argument.
585    Entry {
586        name: "array_extract",
587        kind: FunctionKind::Scalar,
588        arity: Arity::exactly(2),
589        shape: Shape::Extracted,
590        numeric_only: false,
591    },
592    // Three arguments is a range and four is a range with a step. There is no two argument form,
593    // which is why a slice cannot share the row above: `array_slice([1, 2, 3], 1)` is an arity error
594    // upstream rather than the whole list from the first element on.
595    Entry {
596        name: "array_slice",
597        kind: FunctionKind::Scalar,
598        arity: Arity::between(3, 4),
599        shape: Shape::Sliced,
600        numeric_only: false,
601    },
602    // The type of an expression, as a string. Nothing is cast and nothing runs: the binder folds
603    // this to the name of the type it just decided, so the argument is only ever looked at and the
604    // executor never sees the call.
605    Entry {
606        name: "typeof",
607        kind: FunctionKind::Scalar,
608        arity: Arity::exactly(1),
609        shape: Shape::AnyTo(Fixed::Varchar),
610        numeric_only: false,
611    },
612    // The value of a setting, as a value rather than as a row of `duckdb_settings()`. This is the
613    // second function the binder folds and it folds for the same reason `typeof` does: the answer
614    // is settled once the name is known and nothing about it changes per row. Upstream folds it too
615    // and an `EXPLAIN` of a query that calls it shows the literal, which is what makes an `ANY`
616    // return type resolve to something a plan can carry.
617    Entry {
618        name: "current_setting",
619        kind: FunctionKind::Scalar,
620        arity: Arity::exactly(1),
621        shape: Shape::Setting,
622        numeric_only: false,
623    },
624    // Session context. Fourteen names for eight answers, which is the SQL standard's spellings and
625    // Postgres's spellings and DuckDB's own sitting on top of each other. The binder folds every one
626    // of them, so these rows exist to be listed by `duckdb_settings()`'s neighbour
627    // `duckdb_functions()` and to give `now(1)` the arity error the pin gives it.
628    //
629    // Four of these are macro rows upstream rather than scalar rows, which is `current_user`,
630    // `session_user`, `user` and `current_catalog`, and this table has no macros so they are scalars
631    // here. The difference shows up in the `function_type` column of `duckdb_functions()` and
632    // nowhere else, since the parenthesized call binds on both engines and answers the same.
633    session("now", Fixed::TimestampTz),
634    session("get_current_timestamp", Fixed::TimestampTz),
635    session("transaction_timestamp", Fixed::TimestampTz),
636    session("current_localtimestamp", Fixed::Timestamp),
637    session("get_current_time", Fixed::TimeTz),
638    session("current_localtime", Fixed::Time),
639    session("current_date", Fixed::Date),
640    session("today", Fixed::Date),
641    session("current_schema", Fixed::Varchar),
642    session("current_database", Fixed::Varchar),
643    session("current_catalog", Fixed::Varchar),
644    session("current_user", Fixed::Varchar),
645    session("session_user", Fixed::Varchar),
646    session("user", Fixed::Varchar),
647    // Aggregates.
648    aggregate("count_star", Arity::exactly(0), Shape::AnyTo(Fixed::BigInt), false),
649    aggregate("count", Arity::exactly(1), Shape::AnyTo(Fixed::BigInt), false),
650    aggregate("sum", Arity::exactly(1), Shape::Accumulated, true),
651    aggregate("avg", Arity::exactly(1), Shape::PromotedTo(Fixed::Double), true),
652    aggregate("min", Arity::exactly(1), Shape::Promoted, false),
653    aggregate("max", Arity::exactly(1), Shape::Promoted, false),
654    // The ranking windows, which answer from where the row sits in its partition rather than from
655    // anything in it. Six names and seven rows, since `rank_dense` is an alias upstream reports
656    // with `dense_rank` in its `alias_of`. The three that count rows are BIGINT and the two that
657    // divide one count by another are DOUBLE, which was read off the pin with `typeof` rather than
658    // assumed, and `ntile` takes the one argument the family has and takes it as a BIGINT.
659    ranking("cume_dist", Arity::exactly(0), Shape::AnyTo(Fixed::Double)),
660    ranking("dense_rank", Arity::exactly(0), Shape::AnyTo(Fixed::BigInt)),
661    ranking("ntile", Arity::exactly(1), Shape::FixedTo(Fixed::BigInt, Fixed::BigInt)),
662    ranking("percent_rank", Arity::exactly(0), Shape::AnyTo(Fixed::Double)),
663    ranking("rank", Arity::exactly(0), Shape::AnyTo(Fixed::BigInt)),
664    ranking("row_number", Arity::exactly(0), Shape::AnyTo(Fixed::BigInt)),
665    // The windows that read a row rather than count one. Five names, one shape, and the answer is
666    // the first argument's own type in every case, which was read off the pin with `typeof` the way
667    // the ranking types were. `lag` and `lead` take an optional count and an optional default, and
668    // `nth_value` takes a count it requires.
669    value_window("first_value", Arity::exactly(1), Spelled::Any),
670    value_window("lag", Arity::between(1, 3), Spelled::Same),
671    value_window("last_value", Arity::exactly(1), Spelled::Any),
672    value_window("lead", Arity::between(1, 3), Spelled::Same),
673    value_window("nth_value", Arity::exactly(2), Spelled::Any),
674    // The thirteenth window name, which reads neither a position nor a row. It fills the gaps in a
675    // column by interpolating between the values on either side of each one, so the answer is the
676    // argument's own type and there is nothing else to declare.
677    Entry {
678        name: "fill",
679        kind: FunctionKind::Window,
680        arity: Arity::exactly(1),
681        shape: Shape::AsGiven,
682        numeric_only: false,
683    },
684];
685
686/// A scalar that takes numbers.
687const fn number(name: &'static str, arity: Arity, shape: Shape) -> Entry {
688    Entry { name, kind: FunctionKind::Scalar, arity, shape, numeric_only: true }
689}
690
691/// A scalar that takes strings and returns `returns`.
692const fn text(name: &'static str, arity: Arity, returns: Fixed) -> Entry {
693    Entry {
694        name,
695        kind: FunctionKind::Scalar,
696        arity,
697        shape: Shape::Exact(Fixed::Varchar, returns),
698        numeric_only: false,
699    }
700}
701
702/// An interval constructor, which takes one count of one unit and gives back an interval.
703const fn built(name: &'static str, count: Fixed) -> Entry {
704    Entry {
705        name,
706        kind: FunctionKind::Scalar,
707        arity: Arity::exactly(1),
708        shape: Shape::Widened(count, Fixed::Interval),
709        numeric_only: false,
710    }
711}
712
713/// A session context function, which takes nothing and answers about the connection.
714const fn session(name: &'static str, returns: Fixed) -> Entry {
715    Entry {
716        name,
717        kind: FunctionKind::Scalar,
718        arity: Arity::exactly(0),
719        shape: Shape::Constant(returns),
720        numeric_only: false,
721    }
722}
723
724const fn aggregate(name: &'static str, arity: Arity, shape: Shape, numeric_only: bool) -> Entry {
725    Entry { name, kind: FunctionKind::Aggregate, arity, shape, numeric_only }
726}
727
728/// A window that reads where the row sits rather than what is in it.
729const fn ranking(name: &'static str, arity: Arity, shape: Shape) -> Entry {
730    Entry { name, kind: FunctionKind::Window, arity, shape, numeric_only: false }
731}
732
733/// A window that reads a row of the partition rather than aggregating one.
734const fn value_window(name: &'static str, arity: Arity, spelled: Spelled) -> Entry {
735    Entry {
736        name,
737        kind: FunctionKind::Window,
738        arity,
739        shape: Shape::ValueThenCountThenValue(spelled),
740        numeric_only: false,
741    }
742}
743
744/// Whether a name is a function at all, and which kind.
745///
746/// The binder asks this before it knows what to do with a call, since `count(x)` in a projection
747/// has to become an error naming the aggregate rather than a lookup failure naming the name.
748#[must_use]
749pub fn kind_of(name: &str) -> Option<FunctionKind> {
750    find(name).map(|entry| entry.kind)
751}
752
753/// What `date_part` answers with when the specifier is known at binding time.
754///
755/// `epoch` counts seconds and `julian` counts days, and both of them carry a fraction, so those two
756/// are doubles and every other part is a whole number. A specifier that names no part at all is a
757/// double as well, since the call is going to fail anyway and the sentence about it belongs to the
758/// one place that knows every spelling.
759///
760/// This is the only place a call's type comes from the value of an argument rather than the type of
761/// one, and it is upstream's rule rather than an optimization: the declared overload there is a
762/// double and the binder narrows it, which is why `date_part(p, ts)` over a column of specifiers is
763/// a double even when every row of it says `year`.
764#[must_use]
765pub fn part_type(spelling: &str) -> LogicalType {
766    let fraction = ["epoch", "julian", "jd"];
767    if fraction.iter().any(|name| name.eq_ignore_ascii_case(spelling)) {
768        LogicalType::Double
769    } else {
770        LogicalType::BigInt
771    }
772}
773
774/// Resolves a call.
775///
776/// # Errors
777///
778/// If there is no function of that name, if the argument count is wrong, if an argument is not a
779/// number where the function needs one, or if the arguments have no type in common. The messages
780/// are DuckDB's, since a great deal of code in the wild asserts on them.
781pub fn resolve(name: &str, arguments: &[LogicalType]) -> Result<Resolved> {
782    let entry = find(name).ok_or_else(|| {
783        Error::catalog(format!("Scalar Function with name {name} does not exist!"))
784    })?;
785    if !entry.arity.accepts(arguments.len()) {
786        return Err(no_match(entry.name, arguments));
787    }
788    if let Some((cast_to, returns)) = temporal(entry.name, arguments) {
789        return Ok(Resolved { name: entry.name, kind: entry.kind, arguments: cast_to, returns });
790    }
791    if entry.numeric_only {
792        for ty in arguments {
793            // A null literal has no type yet and every function accepts one, since the alternative
794            // is that `sum(NULL)` fails to bind rather than returning null.
795            if !ty.is_numeric() && *ty != LogicalType::Null {
796                return Err(Error::binder(format!(
797                    "No function matches the given name and argument types '{name}({ty})'. You might need to add explicit type casts."
798                )));
799            }
800        }
801    }
802    let (cast_to, returns) = match entry.shape {
803        Shape::Promoted => {
804            let common = promote_all(name, arguments)?;
805            (vec![common.clone(); arguments.len()], common)
806        }
807        Shape::Multiplied => {
808            let common = promote_all(name, arguments)?;
809            match product(arguments)? {
810                // Each side keeps its own scale and takes the answer's width, so the two runs are
811                // the same physical type and the unscaled values multiply into the answer with no
812                // rescaling anywhere. That is what the decimal loop in rudb-kernels expects.
813                Some(LogicalType::Decimal { width, scale }) => {
814                    let cast_to = arguments
815                        .iter()
816                        .map(|ty| match ty.decimal_shape() {
817                            Some((_, held)) => LogicalType::Decimal { width, scale: held },
818                            None => ty.clone(),
819                        })
820                        .collect();
821                    (cast_to, LogicalType::Decimal { width, scale })
822                }
823                _ => (vec![common.clone(); arguments.len()], common),
824            }
825        }
826        Shape::Divided => {
827            let common = promote_all(name, arguments)?;
828            // The cast goes with the answer rather than being left where promotion put it, because
829            // a decimal run divided as a decimal and then widened to a double is not the same
830            // number as the same pair of values divided as doubles.
831            let returns = match common {
832                LogicalType::Decimal { .. } => LogicalType::Double,
833                other => other,
834            };
835            (vec![returns.clone(); arguments.len()], returns)
836        }
837        Shape::Slashed => {
838            let common = promote_all(name, arguments)?;
839            let returns =
840                if common == LogicalType::Float { LogicalType::Float } else { LogicalType::Double };
841            (vec![returns.clone(); arguments.len()], returns)
842        }
843        Shape::PromotedWithCarry => {
844            let common = promote_all(name, arguments)?;
845            // One argument is a negation or a unary plus, and neither one can carry. Negating the
846            // smallest value of a type is the exception and it is not a signature's to take, since
847            // the type of the answer depends on the value: the constant folder widens that one
848            // value by a step, per #264, and the signature says the same thing here as upstream's
849            // does.
850            let returns = if arguments.len() > 1 { carrying(common) } else { common };
851            (vec![returns.clone(); arguments.len()], returns)
852        }
853        Shape::PromotedTo(fixed) => {
854            let common = promote_all(name, arguments)?;
855            (vec![common; arguments.len()], fixed.ty())
856        }
857        Shape::FixedTo(argument, result) => (vec![argument.ty(); arguments.len()], result.ty()),
858        Shape::Exact(argument, result) => {
859            let wanted = argument.ty();
860            for ty in arguments {
861                // An untyped null is accepted the way it is everywhere else here. DuckDB answers
862                // `length(NULL)` with NULL rather than refusing it, because a null has no type to
863                // pick an overload with and every overload would return null anyway.
864                if *ty != wanted && *ty != LogicalType::Null {
865                    return Err(no_match(entry.name, arguments));
866                }
867            }
868            (vec![wanted; arguments.len()], result.ty())
869        }
870        Shape::Widened(argument, result) => {
871            let wanted = argument.ty();
872            for ty in arguments {
873                // A null is accepted here for the reason it is accepted above, and it is the only
874                // type that does not have to promote anywhere, since it has nothing to promote.
875                if *ty != LogicalType::Null && ty.promote(&wanted).as_ref() != Some(&wanted) {
876                    return Err(no_match(entry.name, arguments));
877                }
878            }
879            (vec![wanted; arguments.len()], result.ty())
880        }
881        Shape::WidenedTogether(floor, result) => {
882            // A null has nothing to pull with, so it is left out of the meeting and then cast to
883            // whatever the rest of them settled on, which is the floor when they were all nulls.
884            let mut wanted = floor.ty();
885            for ty in arguments {
886                if *ty == LogicalType::Null {
887                    continue;
888                }
889                match ty.promote(&wanted) {
890                    Some(met) => wanted = met,
891                    None => return Err(no_match(entry.name, arguments)),
892                }
893            }
894            (vec![wanted.clone(); arguments.len()], result.ty())
895        }
896        Shape::AnyTo(result) => (arguments.to_vec(), result.ty()),
897        Shape::LeadingFixedTo(count, first, result) => {
898            (leading(count, first, arguments), result.ty())
899        }
900        Shape::LeadingFixedToLast(first) => {
901            // A null literal has no type and DuckDB refuses `date_trunc('month', NULL)` outright,
902            // because it cannot tell the date overload from the interval one. Refusing needs a
903            // table with both overloads in it to refuse from, which this is not yet, so the answer
904            // is the widest of the candidates rather than a message about a choice nobody made.
905            let last = match arguments.last() {
906                Some(LogicalType::Null) | None => LogicalType::Timestamp,
907                Some(ty) => ty.clone(),
908            };
909            (leading(1, first, arguments), last)
910        }
911        Shape::Accumulated => {
912            let common = promote_all(name, arguments)?;
913            let returns = accumulator(&common);
914            (vec![common; arguments.len()], returns)
915        }
916        Shape::Extracted => {
917            let target = &arguments[0];
918            let index = &arguments[1];
919            let Some(element) = element_of(target) else {
920                return Err(no_match(entry.name, arguments));
921            };
922            if !index.is_integer() && *index != LogicalType::Null {
923                return Err(no_match(entry.name, arguments));
924            }
925            (vec![target.clone(), LogicalType::BigInt], element)
926        }
927        Shape::Sliced => {
928            let target = &arguments[0];
929            if element_of(target).is_none() {
930                // Upstream's own sentence, shouted, and it is the same sentence whichever of the two
931                // spellings the call was written with.
932                return Err(Error::binder("ARRAY_SLICE can only operate on LISTs and VARCHARs"));
933            }
934            // A step is declared BIGINT and so it is not cast to one either, while the two bounds
935            // are declared ANY and are: `array_slice([1, 2, 3], 1.5, 2)` is `[2]` upstream, rounded,
936            // and `array_slice([1, 2, 3], 1, 2, 1.5)` is a binder error.
937            if let Some(step) = arguments.get(3) {
938                if !step.is_integer() && *step != LogicalType::Null {
939                    return Err(no_match(entry.name, arguments));
940                }
941            }
942            let mut cast_to = vec![LogicalType::BigInt; arguments.len()];
943            cast_to[0] = target.clone();
944            (cast_to, target.clone())
945        }
946        Shape::TextThenIndex(count, result) => {
947            let (text, indexes) = arguments.split_at(count.min(arguments.len()));
948            for ty in text {
949                if *ty != LogicalType::Varchar && *ty != LogicalType::Null {
950                    return Err(no_match(entry.name, arguments));
951                }
952            }
953            for ty in indexes {
954                if !ty.is_integer() && *ty != LogicalType::Null {
955                    return Err(no_match(entry.name, arguments));
956                }
957            }
958            let mut cast_to = vec![LogicalType::BigInt; arguments.len()];
959            for slot in &mut cast_to[..text.len()] {
960                *slot = LogicalType::Varchar;
961            }
962            (cast_to, result.ty())
963        }
964        Shape::ValueThenCountThenValue(_) => {
965            let first = arguments[0].clone();
966            let mut cast_to = vec![first.clone(); arguments.len()];
967            if let Some(count) = cast_to.get_mut(1) {
968                *count = LogicalType::BigInt;
969            }
970            (cast_to, first)
971        }
972        Shape::AsGiven => (vec![arguments[0].clone()], arguments[0].clone()),
973        Shape::PromotedToFirst => {
974            let common = promote_all(name, arguments)?;
975            // An untyped null keeps nothing to hand back, so it takes the promoted type the way
976            // every other shape here does. Upstream says NULL for `typeof(nullif(NULL, NULL))`
977            // because it has a type for a null literal and this engine does not, which is #244.
978            let first = &arguments[0];
979            let returns = if *first == LogicalType::Null { common.clone() } else { first.clone() };
980            (vec![common; arguments.len()], returns)
981        }
982        // Reaching here means the binder could not fold the call, and the only reason it cannot is
983        // an argument that is not a constant. The pin says exactly this and names the parameter.
984        Shape::Setting => {
985            return Err(Error::binder(format!(
986                "The \"setting_name\" argument in function \"{}\" must be a constant expression",
987                entry.name
988            )));
989        }
990        // The arity check above already refused every call but the one with no arguments, so there
991        // is nothing to cast and nothing left to decide.
992        Shape::Constant(fixed) => (Vec::new(), fixed.ty()),
993    };
994    Ok(Resolved { name: entry.name, kind: entry.kind, arguments: cast_to, returns })
995}
996
997/// What the arithmetic operators return when a date, a time, a timestamp or an interval is one of
998/// the arguments.
999///
1000/// The one place in this file where the argument types pick the overload rather than the name
1001/// picking one shape. The table above says a name has exactly one shape and that a second row for
1002/// a name needs a rule for which one wins, and this is the rule: a date, a time, a timestamp or an
1003/// interval next to one of those, or next to a number, is temporal arithmetic, and everything else
1004/// is the numeric row. The answer is the types to cast the arguments to and the type that comes
1005/// back.
1006///
1007/// A date plus an interval is a timestamp and not a date, because the interval carries a time of
1008/// day. A time plus an interval is a time, since the months and the days have nowhere to go and it
1009/// wraps at midnight. Taking a date off an interval is not a thing on either engine, so only the
1010/// commuted addition is here.
1011///
1012/// Two intervals add and subtract field by field, and a number scales one, in either order for the
1013/// multiplication and with the interval on the left for the division.
1014///
1015/// The multiplication has two overloads of its own and the difference between them shows. A whole
1016/// number goes in as a `BIGINT` and multiplies the three fields as they are, and everything else
1017/// goes in as a `DOUBLE` and moves what is left over on a field down to the next one. `HUGEINT` and
1018/// `UBIGINT` take the double as well, since neither of them fits a `BIGINT` to begin with. Dividing
1019/// has only the double, which is why an integer count divided into an interval reports its division
1020/// by zero as `0.0`.
1021///
1022/// A plain number next to a date is a count of days and the answer stays a date, which is the one
1023/// shape here that does not become a timestamp. The count is an `INTEGER` and nothing wider, so a
1024/// `BIGINT` next to a date has no overload to reach at all, and taking a date off a number is not a
1025/// thing. One date taken off another is a count of days as a `BIGINT` and one timestamp taken off
1026/// another is an interval, and a date on either side of that subtraction becomes a timestamp first.
1027/// A date plus a time is the timestamp they name together, in either order, and taking a time off a
1028/// date is refused upstream.
1029///
1030/// An untyped null next to a date is the count of days and next to a timestamp is the interval,
1031/// which is measured rather than picked: `typeof(DATE '2020-01-01' + NULL)` is `DATE` and
1032/// `typeof(TIMESTAMP '2020-01-01' - NULL)` is `TIMESTAMP`. A null next to a time or next to an
1033/// interval is ambiguous upstream and refused, which we refuse too, with the wrong sentence for now
1034/// because the sentence for an ambiguous call is #395.
1035fn temporal(name: &str, arguments: &[LogicalType]) -> Option<(Vec<LogicalType>, LogicalType)> {
1036    use LogicalType::{
1037        BigInt, Date, Double, HugeInt, Integer, Interval, Null, SmallInt, Time, TimeTz, Timestamp,
1038        TimestampTz, TinyInt, UBigInt, UHugeInt, USmallInt, UTinyInt,
1039    };
1040    let kept = |returns| Some((arguments.to_vec(), returns));
1041    // A null literal has no type yet, so it counts as the number and the cast to a double is what
1042    // turns the whole call into a null.
1043    let number = |ty: &LogicalType| ty.is_numeric() || *ty == Null;
1044    let counted = |ty: &LogicalType| ty.is_integer() && !matches!(ty, HugeInt | UHugeInt | UBigInt);
1045    // The days a date moves by are an `INTEGER`, so this is the set of types that widen into one.
1046    let days =
1047        |ty: &LogicalType| matches!(ty, TinyInt | SmallInt | Integer | UTinyInt | USmallInt | Null);
1048    match (name, arguments) {
1049        ("-", [Interval]) => kept(Interval),
1050        ("+" | "-", [Date | Timestamp, Interval]) | ("+", [Interval, Date | Timestamp]) => {
1051            kept(Timestamp)
1052        }
1053        ("+" | "-", [Time, Interval]) | ("+", [Interval, Time]) => kept(Time),
1054        ("+" | "-", [Interval, Interval]) => kept(Interval),
1055        ("-", [Date, Date]) => kept(BigInt),
1056        ("-", [Timestamp, Timestamp]) => kept(Interval),
1057        ("-", [Date, Timestamp] | [Timestamp, Date]) => {
1058            Some((vec![Timestamp, Timestamp], Interval))
1059        }
1060        ("+", [Date, Time] | [Time, Date]) => kept(Timestamp),
1061        // A zoned value keeps its zone through all of this, which is upstream's answer for every one
1062        // of these rather than something read off the unzoned rows above. The mixed subtraction is
1063        // the one that has a cast in it: a plain timestamp or a date next to a zoned one becomes
1064        // zoned first, and then the two of them are two of the same kind.
1065        ("+" | "-", [TimestampTz, Interval]) | ("+", [Interval, TimestampTz]) => kept(TimestampTz),
1066        ("+" | "-", [TimeTz, Interval]) | ("+", [Interval, TimeTz]) => kept(TimeTz),
1067        ("-", [TimestampTz, TimestampTz]) => kept(Interval),
1068        ("-", [TimestampTz, Timestamp | Date] | [Timestamp | Date, TimestampTz]) => {
1069            Some((vec![TimestampTz, TimestampTz], Interval))
1070        }
1071        ("+", [Date, TimeTz] | [TimeTz, Date]) => kept(TimestampTz),
1072        ("+" | "-", [TimestampTz, Null]) | ("+", [Null, TimestampTz]) => kept(TimestampTz),
1073        ("+" | "-", [Date, count]) if days(count) => Some((vec![Date, Integer], Date)),
1074        ("+", [count, Date]) if days(count) => Some((vec![Integer, Date], Date)),
1075        ("+" | "-", [Timestamp, Null]) | ("+", [Null, Timestamp]) => kept(Timestamp),
1076        ("*", [Interval, count]) if counted(count) => Some((vec![Interval, BigInt], Interval)),
1077        ("*", [count, Interval]) if counted(count) => Some((vec![BigInt, Interval], Interval)),
1078        ("*" | "/", [Interval, scale]) if number(scale) => Some((vec![Interval, Double], Interval)),
1079        ("*", [scale, Interval]) if number(scale) => Some((vec![Double, Interval], Interval)),
1080        _ => None,
1081    }
1082}
1083
1084/// The error for a call that names a real function and does not fit any of its overloads.
1085///
1086/// The sentence is DuckDB's, and so is the block under it when there is one. A message that says a
1087/// call does not match without saying what would match is a message that sends somebody to the
1088/// documentation, and the whole argument for copying the reference's errors is that a program
1089/// written against one engine should not have to be debugged differently against the other.
1090///
1091/// The trailing newline is the reference's too. Its message ends after the last candidate with a
1092/// line break, which is visible as the second blank line before the shell prints the offending SQL.
1093fn no_match(name: &str, arguments: &[LogicalType]) -> Error {
1094    let types = arguments.iter().map(ToString::to_string).collect::<Vec<_>>().join(", ");
1095    let mut message = format!(
1096        "No function matches the given name and argument types '{name}({types})'. You might need to add explicit type casts."
1097    );
1098    if let Some((_, overloads)) = CANDIDATES.iter().find(|(entry, _)| *entry == name) {
1099        message.push_str("\n\tCandidate functions:");
1100        for overload in *overloads {
1101            message.push_str("\n\t");
1102            message.push_str(overload);
1103        }
1104        message.push('\n');
1105    }
1106    Error::binder(message)
1107}
1108
1109/// What the reference prints under `Candidate functions:`, per function, byte for byte.
1110///
1111/// Copied off the pinned binary rather than generated from [`TABLE`], because it is not derivable
1112/// from what rudb has. The parameters are called `col0` and `col1` for some functions and `string`,
1113/// `regex` and a quoted `"options"` for others, an operator is quoted where a plain name is not, and
1114/// `length` lists three overloads of which rudb has one. That last one is the argument for copying
1115/// rather than deriving: the list is what DuckDB accepts, rudb is meant to accept the same, and a
1116/// list that shrank to what is built today would have to be edited every time a gap closes.
1117///
1118/// A name missing from here gets the sentence with no block under it, which is what every function
1119/// outside the string family does today.
1120const CANDIDATES: &[(&str, &[&str])] = &[
1121    // The session context functions, which all print the same way because they all take nothing.
1122    // The four spelled as macros upstream are not here on purpose: the pin answers those with
1123    // "Macro current_user() does not support the supplied arguments" and a `Candidate macros:` block
1124    // under it, and rudb has no macros to say that about, so a block naming candidate functions
1125    // would be a second thing wrong rather than the sentence with nothing under it.
1126    ("now", &["now() -> TIMESTAMP WITH TIME ZONE"]),
1127    ("get_current_timestamp", &["get_current_timestamp() -> TIMESTAMP WITH TIME ZONE"]),
1128    ("transaction_timestamp", &["transaction_timestamp() -> TIMESTAMP WITH TIME ZONE"]),
1129    ("current_localtimestamp", &["current_localtimestamp() -> TIMESTAMP"]),
1130    ("get_current_time", &["get_current_time() -> TIME WITH TIME ZONE"]),
1131    ("current_localtime", &["current_localtime() -> TIME"]),
1132    ("current_date", &["current_date() -> DATE"]),
1133    ("today", &["today() -> DATE"]),
1134    ("current_schema", &["current_schema() -> VARCHAR"]),
1135    ("current_database", &["current_database() -> VARCHAR"]),
1136    ("lower", &["lower(col0 VARCHAR) -> VARCHAR"]),
1137    ("upper", &["upper(col0 VARCHAR) -> VARCHAR"]),
1138    (
1139        "length",
1140        &[
1141            "length(col0 VARCHAR) -> BIGINT",
1142            "length(col0 BIT) -> BIGINT",
1143            "length(col0 ANY[]) -> BIGINT",
1144        ],
1145    ),
1146    ("strlen", &["strlen(col0 VARCHAR) -> BIGINT"]),
1147    ("chr", &["chr(col0 INTEGER) -> VARCHAR"]),
1148    ("left", &["\"left\"(col0 VARCHAR, col1 BIGINT) -> VARCHAR"]),
1149    ("right", &["\"right\"(col0 VARCHAR, col1 BIGINT) -> VARCHAR"]),
1150    ("replace", &["\"replace\"(col0 VARCHAR, col1 VARCHAR, col2 VARCHAR) -> VARCHAR"]),
1151    // The one overload upstream prints with a repeated parameter in it, which is how it writes a
1152    // variadic. Reachable with no arguments at all, since the grammar has nothing to say about the
1153    // count of an ordinary call.
1154    ("concat", &["concat(col0 ANY, [ANY...]) -> ANY"]),
1155    (
1156        "substring",
1157        &[
1158            "\"substring\"(col0 VARCHAR, col1 BIGINT, col2 BIGINT) -> VARCHAR",
1159            "\"substring\"(col0 VARCHAR, col1 BIGINT) -> VARCHAR",
1160        ],
1161    ),
1162    (
1163        "substr",
1164        &[
1165            "substr(col0 VARCHAR, col1 BIGINT, col2 BIGINT) -> VARCHAR",
1166            "substr(col0 VARCHAR, col1 BIGINT) -> VARCHAR",
1167        ],
1168    ),
1169    (
1170        "overlay",
1171        &[
1172            "\"overlay\"(col0 VARCHAR, col1 VARCHAR, col2 BIGINT) -> VARCHAR",
1173            "\"overlay\"(col0 VARCHAR, col1 VARCHAR, col2 BIGINT, col3 BIGINT) -> VARCHAR",
1174        ],
1175    ),
1176    ("position", &["\"position\"(col0 VARCHAR, col1 VARCHAR) -> BIGINT"]),
1177    ("strpos", &["strpos(col0 VARCHAR, col1 VARCHAR) -> BIGINT"]),
1178    ("instr", &["instr(col0 VARCHAR, col1 VARCHAR) -> BIGINT"]),
1179    (
1180        "trim",
1181        &["\"trim\"(col0 VARCHAR) -> VARCHAR", "\"trim\"(col0 VARCHAR, col1 VARCHAR) -> VARCHAR"],
1182    ),
1183    ("ltrim", &["ltrim(col0 VARCHAR) -> VARCHAR", "ltrim(col0 VARCHAR, col1 VARCHAR) -> VARCHAR"]),
1184    ("rtrim", &["rtrim(col0 VARCHAR) -> VARCHAR", "rtrim(col0 VARCHAR, col1 VARCHAR) -> VARCHAR"]),
1185    ("~~", &["\"~~\"(col0 VARCHAR, col1 VARCHAR) -> BOOLEAN"]),
1186    ("!~~", &["\"!~~\"(col0 VARCHAR, col1 VARCHAR) -> BOOLEAN"]),
1187    ("~~*", &["\"~~*\"(col0 VARCHAR, col1 VARCHAR) -> BOOLEAN"]),
1188    ("!~~*", &["\"!~~*\"(col0 VARCHAR, col1 VARCHAR) -> BOOLEAN"]),
1189    (
1190        "regexp_replace",
1191        &[
1192            "regexp_replace(string VARCHAR, regex VARCHAR, replacement VARCHAR) -> VARCHAR",
1193            "regexp_replace(string VARCHAR, regex VARCHAR, replacement VARCHAR, \"options\" VARCHAR) -> VARCHAR",
1194        ],
1195    ),
1196    (
1197        "regexp_matches",
1198        &[
1199            "regexp_matches(string VARCHAR, regex VARCHAR) -> BOOLEAN",
1200            "regexp_matches(string VARCHAR, regex VARCHAR, \"options\" VARCHAR) -> BOOLEAN",
1201        ],
1202    ),
1203    (
1204        "regexp_full_match",
1205        &[
1206            "regexp_full_match(string VARCHAR, regex VARCHAR) -> BOOLEAN",
1207            "regexp_full_match(string VARCHAR, regex VARCHAR, \"options\" VARCHAR) -> BOOLEAN",
1208        ],
1209    ),
1210    // Both overloads of each interval constructor, including the BIGINT one this engine does not
1211    // have a row for, because the list is what DuckDB accepts and somebody reading it is being told
1212    // what to write rather than what is built here.
1213    ("to_years", &["to_years(col0 INTEGER) -> INTERVAL", "to_years(col0 BIGINT) -> INTERVAL"]),
1214    ("to_months", &["to_months(col0 INTEGER) -> INTERVAL", "to_months(col0 BIGINT) -> INTERVAL"]),
1215    (
1216        "to_quarters",
1217        &["to_quarters(col0 INTEGER) -> INTERVAL", "to_quarters(col0 BIGINT) -> INTERVAL"],
1218    ),
1219    (
1220        "to_decades",
1221        &["to_decades(col0 INTEGER) -> INTERVAL", "to_decades(col0 BIGINT) -> INTERVAL"],
1222    ),
1223    (
1224        "to_centuries",
1225        &["to_centuries(col0 INTEGER) -> INTERVAL", "to_centuries(col0 BIGINT) -> INTERVAL"],
1226    ),
1227    (
1228        "to_millennia",
1229        &["to_millennia(col0 INTEGER) -> INTERVAL", "to_millennia(col0 BIGINT) -> INTERVAL"],
1230    ),
1231    ("to_days", &["to_days(col0 INTEGER) -> INTERVAL", "to_days(col0 BIGINT) -> INTERVAL"]),
1232    ("to_weeks", &["to_weeks(col0 INTEGER) -> INTERVAL", "to_weeks(col0 BIGINT) -> INTERVAL"]),
1233    // The five that have one overload each, which is why they are not in the pattern above. The
1234    // three that land in microseconds are declared over a BIGINT and never over an INTEGER, since
1235    // an hour of INTEGER hours does not fit the field anyway.
1236    ("to_hours", &["to_hours(col0 BIGINT) -> INTERVAL"]),
1237    ("to_minutes", &["to_minutes(col0 BIGINT) -> INTERVAL"]),
1238    ("to_microseconds", &["to_microseconds(col0 BIGINT) -> INTERVAL"]),
1239    ("to_seconds", &["to_seconds(col0 DOUBLE) -> INTERVAL"]),
1240    ("to_milliseconds", &["to_milliseconds(col0 DOUBLE) -> INTERVAL"]),
1241    // Four overloads of which this engine has two. The STRUCT one is `x.y`, which the transformer
1242    // writes as `struct_extract`, and a TUPLE is the positional half of the same idea.
1243    (
1244        "array_extract",
1245        &[
1246            "array_extract(\"array\" T[], \"index\" BIGINT) -> T",
1247            "array_extract(col0 VARCHAR, col1 BIGINT) -> VARCHAR",
1248            "array_extract(\"struct\" STRUCT, \"key\" VARCHAR) -> ANY",
1249            "array_extract(\"tuple\" TUPLE, \"index\" BIGINT) -> ANY",
1250        ],
1251    ),
1252    (
1253        "array_slice",
1254        &[
1255            "array_slice(col0 ANY, col1 ANY, col2 ANY) -> ANY",
1256            "array_slice(col0 ANY, col1 ANY, col2 ANY, col3 BIGINT) -> ANY",
1257        ],
1258    ),
1259    ("typeof", &["typeof(col0 ANY) -> VARCHAR"]),
1260    ("current_setting", &["current_setting(setting_name VARCHAR) -> ANY"]),
1261];
1262
1263/// What one element of a subscripted value is, or `None` for a value that cannot be subscripted.
1264///
1265/// A string is subscripted by character and a character is a string, so `'abcdef'[2]` is a VARCHAR
1266/// and not a type of its own. An untyped null takes the VARCHAR overload, which was measured:
1267/// `typeof(array_extract(NULL, 1))` is VARCHAR on the pinned binary while
1268/// `typeof(array_slice(NULL, 1, 2))` is NULL, so the null goes here and the slice keeps the type it
1269/// was handed.
1270///
1271/// A STRUCT is subscripted by name rather than by position and is not one of these. `x.y` is
1272/// `struct_extract(x, 'y')` by the time it leaves the transformer, which is a function this table
1273/// does not have yet, so that call fails with the name of the function it is missing.
1274fn element_of(ty: &LogicalType) -> Option<LogicalType> {
1275    match ty {
1276        LogicalType::Varchar | LogicalType::Null => Some(LogicalType::Varchar),
1277        LogicalType::List(element) | LogicalType::Array(element, _) => Some((**element).clone()),
1278        _ => None,
1279    }
1280}
1281
1282/// The cast list for a shape that fixes the leading arguments and leaves the others as they are.
1283fn leading(count: usize, first: Fixed, arguments: &[LogicalType]) -> Vec<LogicalType> {
1284    let mut cast_to = arguments.to_vec();
1285    for head in cast_to.iter_mut().take(count) {
1286        *head = first.ty();
1287    }
1288    cast_to
1289}
1290
1291/// The type of a decimal product, or `None` when no decimal is involved and promotion decides.
1292///
1293/// A product of `DECIMAL(a,b)` and `DECIMAL(c,d)` needs `a + c` digits with `b + d` after the
1294/// point, because the largest pair of inputs multiplies to exactly that, and an integer counts as
1295/// the decimal that holds it. The rest is where upstream stops widening, and both of the places it
1296/// stops were read off `v2.0.0-dev84237` across a grid of seventy two pairs rather than reasoned
1297/// about:
1298///
1299/// A product of two operands that each fit in sixty four bits is kept there when it can be. So
1300/// `DECIMAL(10,0) * DECIMAL(10,0)` is `DECIMAL(18,0)` rather than `DECIMAL(20,0)`, which is a type
1301/// that cannot hold every product of its own inputs and raises an overflow on the ones it cannot,
1302/// and `DECIMAL(18,17) * DECIMAL(10,0)` is `DECIMAL(18,17)`. It is kept there only while a digit is
1303/// left in front of the point, which is why `DECIMAL(10,9) * DECIMAL(10,9)` is `DECIMAL(20,18)` and
1304/// not `DECIMAL(18,18)`: at eighteen decimal places there is no room for the integer part, so the
1305/// answer moves to the wider representation instead.
1306///
1307/// Past that, the width stops at the widest decimal there is and the scale does not, because a
1308/// scale that had to shrink would be an answer with digits missing from the end of it rather than a
1309/// narrower one. A scale of more than thirty eight is refused at bind time with upstream's own
1310/// sentence, since there is no type to put the answer in.
1311fn product(arguments: &[LogicalType]) -> Result<Option<LogicalType>> {
1312    let mut decimals = false;
1313    let (mut width, mut scale, mut widest) = (0u8, 0u8, 0u8);
1314    for ty in arguments {
1315        decimals |= matches!(ty, LogicalType::Decimal { .. });
1316        let Some((one, held)) = ty.decimal_shape() else { return Ok(None) };
1317        width = width.saturating_add(one);
1318        scale = scale.saturating_add(held);
1319        widest = widest.max(one);
1320    }
1321    if !decimals {
1322        return Ok(None);
1323    }
1324    if scale > MAX_DECIMAL_WIDTH {
1325        return Err(Error::out_of_range(format!(
1326            "Needed scale {scale} to accurately represent the multiplication result, but this is out of range of the DECIMAL type. Max scale is {MAX_DECIMAL_WIDTH}; could not perform an accurate multiplication. Either add a cast to DOUBLE, or add an explicit cast to a decimal with a lower scale."
1327        )));
1328    }
1329    if widest <= WIDEST_SIXTY_FOUR_BIT
1330        && width > WIDEST_SIXTY_FOUR_BIT
1331        && scale < WIDEST_SIXTY_FOUR_BIT
1332    {
1333        width = WIDEST_SIXTY_FOUR_BIT;
1334    }
1335    Ok(Some(LogicalType::Decimal { width: width.min(MAX_DECIMAL_WIDTH), scale }))
1336}
1337
1338/// The widest decimal that is still eight bytes a value, which is where a product stops widening.
1339const WIDEST_SIXTY_FOUR_BIT: u8 = 18;
1340
1341/// The type an addition or a subtraction produces from what its operands promote to.
1342///
1343/// A decimal gains the one digit an addition can carry into and everything else is unchanged. At
1344/// the maximum width there is nowhere left to widen into, so the type stays where it is and the
1345/// overflow is raised on the row that overflows rather than on every query that could.
1346///
1347/// Measured on `v2.0.0-dev84237`, which is where each of these numbers comes from:
1348/// `DECIMAL(18,0) + DECIMAL(18,0)` is `DECIMAL(19,0)`, `DECIMAL(38,0) + DECIMAL(38,0)` is
1349/// `DECIMAL(38,0)`, `2.0 + 1::INTEGER` is `DECIMAL(12,1)` and `DECIMAL(18,0) - DECIMAL(4,2)` is
1350/// `DECIMAL(21,2)`. A modulo, a negation and `abs` do not widen and keep [`Shape::Promoted`] for
1351/// that reason, and a product widens by a rule of its own, which is [`product`].
1352fn carrying(common: LogicalType) -> LogicalType {
1353    match common {
1354        LogicalType::Decimal { width, scale } if width < MAX_DECIMAL_WIDTH => {
1355            LogicalType::Decimal { width: width + 1, scale }
1356        }
1357        other => other,
1358    }
1359}
1360
1361/// What a sum of this type accumulates into.
1362///
1363/// Summing a column of `INTEGER` overflows an `INTEGER` after 2^31 of them and there is no useful
1364/// error to raise at that point, so the accumulator is the widest integer there is and the answer
1365/// is right. A float sums into a double for the same reason and a double stays a double, since
1366/// there is nothing wider to go to.
1367fn accumulator(ty: &LogicalType) -> LogicalType {
1368    if ty.is_integer() {
1369        LogicalType::HugeInt
1370    } else if *ty == LogicalType::Float {
1371        LogicalType::Double
1372    } else {
1373        ty.clone()
1374    }
1375}
1376
1377fn promote_all(name: &str, arguments: &[LogicalType]) -> Result<LogicalType> {
1378    // Only reachable for a signature whose arity allows no arguments and whose shape promotes,
1379    // which is a combination the table does not contain and which the test below holds it to.
1380    let mut common = match arguments.first() {
1381        Some(first) => first.clone(),
1382        None => {
1383            return Err(Error::internal(format!("{name} promotes over no arguments")));
1384        }
1385    };
1386    for ty in &arguments[1..] {
1387        common = common.promote(ty).ok_or_else(|| {
1388            Error::binder(format!(
1389                "No function matches the given name and argument types '{name}({})'. You might need to add explicit type casts.",
1390                arguments.iter().map(ToString::to_string).collect::<Vec<_>>().join(", ")
1391            ))
1392        })?;
1393    }
1394    // Every argument was a null literal, which has no type. Untyped null is not a type an executor
1395    // can hold a vector of, so it becomes an integer, which is what DuckDB does with `SELECT NULL`.
1396    if common == LogicalType::Null {
1397        common = LogicalType::Integer;
1398    }
1399    Ok(common)
1400}
1401
1402fn find(name: &str) -> Option<&'static Entry> {
1403    let name = canonical(name);
1404    TABLE.iter().find(|entry| entry.name.eq_ignore_ascii_case(name))
1405}
1406
1407/// One overload of one function, as `duckdb_functions()` reports it.
1408///
1409/// An overload here is a name and an argument count, because that is what an entry in this crate's
1410/// table has one of each. Upstream has an overload per pair of argument types instead and so reports
1411/// 44 rows for `+`, and `types` is where the difference shows up. See [`function_rows`].
1412#[derive(Debug, Clone, PartialEq, Eq)]
1413pub struct FunctionRow {
1414    /// The name as it was written, which is the alias for an alias.
1415    pub name: &'static str,
1416    /// Scalar or aggregate.
1417    pub kind: FunctionKind,
1418    /// The name this one resolves to, and `None` for a name that is its own.
1419    pub alias_of: Option<&'static str>,
1420    /// One per argument, in order.
1421    pub types: Vec<&'static str>,
1422    /// What the call produces.
1423    pub returns: &'static str,
1424    /// The type of the trailing variadic argument, for the names that take one.
1425    pub varargs: Option<&'static str>,
1426}
1427
1428/// Every name in the table and every argument count it takes, for `duckdb_functions()`.
1429///
1430/// The types here are declared types and not resolved ones, which is the whole difference between
1431/// this table and upstream's. The table in this module resolves by shape: `+` is one entry saying
1432/// both arguments promote and the result is what they promote to, where upstream carries an entry
1433/// per pair of numeric types because it carries an implementation per pair. So upstream reports 44
1434/// rows for `+` naming concrete types and this reports two, one per arity, with the type variable.
1435///
1436/// `T` is upstream's own spelling for an argument whose type the call decides, which it uses for
1437/// `list_extract` and `lag` and the rest of the generic functions, and it means the same thing here:
1438/// every argument spelled `T` in one row is the same type as every other. `ANY` is the weaker one
1439/// and means the argument is not constrained and not tied to the others, which is what `count(x)`
1440/// takes. A return of `ANY` means the type is decided by the arguments in a way a name cannot say,
1441/// which is where `sum` is, since it promotes and then widens an integer to the accumulator.
1442///
1443/// Rows come out in the order the table is written in, which is by family. The caller sorts.
1444///
1445/// [`resolve`]: crate::signature::resolve
1446#[must_use]
1447pub fn function_rows() -> Vec<FunctionRow> {
1448    let mut rows = Vec::new();
1449    for entry in TABLE {
1450        for count in entry.arity.every_count() {
1451            let (types, returns) = entry.shape.declared(count);
1452            rows.push(FunctionRow {
1453                name: entry.name,
1454                kind: entry.kind,
1455                alias_of: None,
1456                types,
1457                returns,
1458                varargs: entry.arity.open().then(|| entry.shape.declared(1).0[0]),
1459            });
1460        }
1461    }
1462    // An alias is a row of its own with the same shape, because a client reading this table to find
1463    // out whether `len` works wants a row for `len`. Upstream does the same and fills `alias_of`
1464    // with the name it resolves to, which is how this crate's list was read off in the first place.
1465    for (alias, real) in ALIASES {
1466        let mut aliased: Vec<FunctionRow> = rows
1467            .iter()
1468            .filter(|row| row.name == *real)
1469            .map(|row| FunctionRow { name: alias, alias_of: Some(real), ..row.clone() })
1470            .collect();
1471        rows.append(&mut aliased);
1472    }
1473    rows
1474}
1475
1476impl Arity {
1477    /// Every argument count this accepts, with an open end reported as its shortest form.
1478    ///
1479    /// An open end is `concat` and friends, which take any number, and the row for one says so in
1480    /// `varargs` rather than by having a row per count up to some number nobody picked.
1481    fn every_count(self) -> Vec<usize> {
1482        match self {
1483            Self::Exactly(count) => vec![count],
1484            Self::Between(least, Some(most)) => (least..=most).collect(),
1485            Self::Between(least, None) => vec![least],
1486            Self::OneOf(counts) => counts.to_vec(),
1487        }
1488    }
1489
1490    /// Whether the count has no upper end.
1491    const fn open(self) -> bool {
1492        matches!(self, Self::Between(_, None))
1493    }
1494}
1495
1496impl Fixed {
1497    /// The name this type goes by in a catalog table, which is the name a cast spells.
1498    const fn name(self) -> &'static str {
1499        match self {
1500            Self::Boolean => "BOOLEAN",
1501            Self::Integer => "INTEGER",
1502            Self::BigInt => "BIGINT",
1503            Self::Double => "DOUBLE",
1504            Self::Varchar => "VARCHAR",
1505            Self::Date => "DATE",
1506            Self::Time => "TIME",
1507            Self::TimeTz => "TIME WITH TIME ZONE",
1508            Self::Timestamp => "TIMESTAMP",
1509            Self::TimestampTz => "TIMESTAMP WITH TIME ZONE",
1510            Self::Interval => "INTERVAL",
1511        }
1512    }
1513}
1514
1515/// The type variable, for an argument whose type the call decides and that every other argument
1516/// spelled the same way has to agree with.
1517const SAME: &str = "T";
1518
1519/// An argument that is not constrained and is not tied to the others, or a result that the
1520/// arguments decide in a way no name can say.
1521const ANY: &str = "ANY";
1522
1523impl Shape {
1524    /// What the arguments and the result are declared to be, at this argument count.
1525    ///
1526    /// Not what a call resolves to. A shape that promotes says `T` here and works out the real type
1527    /// in [`resolve`] from what was passed, and a shape that widens a decimal says `ANY` for the
1528    /// result because the width is not in the name.
1529    fn declared(self, count: usize) -> (Vec<&'static str>, &'static str) {
1530        let all = |name: &'static str| vec![name; count];
1531        let leading = |taken: usize, first: &'static str, rest: &'static str| {
1532            (0..count).map(|at| if at < taken { first } else { rest }).collect::<Vec<_>>()
1533        };
1534        match self {
1535            // Promoting says `T` and the result is that same `T`, exactly.
1536            Self::Promoted | Self::PromotedToFirst => (all(SAME), SAME),
1537            // Promoting and then moving: a decimal product is as wide as both operands, a decimal
1538            // quotient is a double, a decimal sum gains a carry digit and an integer sum widens to
1539            // the accumulator. The arguments still meet at one type and the result is no longer it.
1540            Self::Multiplied
1541            | Self::Divided
1542            | Self::Slashed
1543            | Self::PromotedWithCarry
1544            | Self::Accumulated => (all(SAME), ANY),
1545            Self::PromotedTo(fixed) => (all(SAME), fixed.name()),
1546            // The floor is what a shape that widens is declared as, which is the overload upstream
1547            // lists first and the one a call with nothing to say about its arguments lands on.
1548            Self::FixedTo(from, to)
1549            | Self::Exact(from, to)
1550            | Self::Widened(from, to)
1551            | Self::WidenedTogether(from, to) => (all(from.name()), to.name()),
1552            Self::AnyTo(fixed) => (all(ANY), fixed.name()),
1553            Self::LeadingFixedTo(taken, first, to) => {
1554                (leading(taken, first.name(), ANY), to.name())
1555            }
1556            Self::LeadingFixedToLast(first) => (leading(1, first.name(), SAME), SAME),
1557            // A subscript takes a string or a list and a whole number, and the whole number is not
1558            // cast to one, which is why it is spelled out rather than left as `ANY`.
1559            Self::Extracted => (leading(1, SAME, "BIGINT"), ANY),
1560            Self::Sliced => (leading(1, SAME, "BIGINT"), SAME),
1561            Self::TextThenIndex(taken, to) => {
1562                (leading(taken, Fixed::Varchar.name(), "BIGINT"), to.name())
1563            }
1564            // The value, then a row count, then another value of the first one's type. The third
1565            // one is `ANY` and not the spelling of the first, which is the pin's row for `lag` and
1566            // is where the declaration stops being the rule: the binder casts the default to the
1567            // column's type whatever the table says here.
1568            Self::ValueThenCountThenValue(spelled) => {
1569                let names = (0..count)
1570                    .map(|at| match at {
1571                        0 => spelled.name(),
1572                        1 => "BIGINT",
1573                        _ => ANY,
1574                    })
1575                    .collect();
1576                (names, spelled.name())
1577            }
1578            // One `ANY` in and one `ANY` out, which is the pin's row for `fill` and is the whole of
1579            // what it declares.
1580            Self::AsGiven => (all(ANY), ANY),
1581            // One overload with an `ANY` return, which is the pin's row for it. The name decides
1582            // the type and a name is not something a signature can hold.
1583            Self::Setting => (all(Fixed::Varchar.name()), ANY),
1584            // No arguments, so `all` is empty whatever it is handed and only the result is named.
1585            Self::Constant(fixed) => (Vec::new(), fixed.name()),
1586        }
1587    }
1588}
1589
1590/// The name a function is in [`TABLE`] under, which is its own name unless it is an alias.
1591///
1592/// Aliases are resolved here rather than by a second row in the table, so that [`Resolved::name`]
1593/// is always the canonical name and the plan, the executor and every kernel below it see one name
1594/// per function. A kernel that had to know `len` is `length` would be a kernel with a second place
1595/// for the two to drift apart.
1596///
1597/// The list is DuckDB's, read off `duckdb_functions()` where `alias_of` is set, and it is only ever
1598/// as long as the table it points into. There is no point aliasing a name onto a function this
1599/// engine does not have yet, because the error would move from a missing function to a missing
1600/// function under a different name.
1601fn canonical(name: &str) -> &str {
1602    ALIASES
1603        .iter()
1604        .find(|(alias, _)| alias.eq_ignore_ascii_case(name))
1605        .map_or(name, |(_, real)| *real)
1606}
1607
1608/// Every other name DuckDB accepts for a function already in [`TABLE`].
1609///
1610/// `strlen` is deliberately not here. Upstream counts bytes with it and characters with `length`,
1611/// so it is a different function and it has a row of its own.
1612/// The three subscript spellings point the way the transformer writes them rather than the way
1613/// `duckdb_functions()` has them. Upstream is `array_slice` aliased onto `list_slice`, and
1614/// `array_extract` and `list_extract` are two functions there rather than one, differing in the
1615/// overloads they carry for a STRUCT and a TUPLE. Neither of those is here, so they are one function
1616/// here, and the name it is under is the one a bracket produces, which is what keeps the message a
1617/// bracket produces word for word the reference's.
1618///
1619/// What that costs is the same thing every row below costs: the message names the canonical spelling
1620/// and not the written one, so `list_slice(1, 2, 3)` says `array_slice` here where upstream says
1621/// `list_slice`, exactly as `len(1)` says `length`.
1622const ALIASES: &[(&str, &str)] = &[
1623    ("len", "length"),
1624    ("char_length", "length"),
1625    ("character_length", "length"),
1626    ("lcase", "lower"),
1627    ("ucase", "upper"),
1628    ("mean", "avg"),
1629    ("list_extract", "array_extract"),
1630    ("list_element", "array_extract"),
1631    ("list_slice", "array_slice"),
1632    ("rank_dense", "dense_rank"),
1633];
1634
1635#[cfg(test)]
1636mod tests {
1637    use super::*;
1638
1639    #[test]
1640    fn arithmetic_returns_what_its_operands_promote_to() {
1641        let resolved = resolve("+", &[LogicalType::Integer, LogicalType::BigInt])
1642            .expect("an integer and a bigint add");
1643        assert_eq!(resolved.returns, LogicalType::BigInt);
1644        assert_eq!(resolved.arguments, vec![LogicalType::BigInt, LogicalType::BigInt]);
1645    }
1646
1647    /// Every decimal sum in here was read off `v2.0.0-dev84237` with `typeof`, per #243.
1648    ///
1649    /// The last one is the case the rule exists for. Two `DECIMAL(18,0)` hold numbers that add to
1650    /// nineteen digits, and a result type of eighteen means the largest pair of inputs the operator
1651    /// accepts is a pair it cannot answer.
1652    #[test]
1653    fn a_decimal_sum_is_a_digit_wider_than_what_its_operands_promote_to() {
1654        let decimal = |width, scale| LogicalType::Decimal { width, scale };
1655        let sum = |left: LogicalType, right: LogicalType| {
1656            resolve("+", &[left, right]).expect("adds").returns
1657        };
1658        assert_eq!(sum(decimal(18, 0), decimal(18, 0)), decimal(19, 0));
1659        assert_eq!(sum(decimal(2, 1), LogicalType::Integer), decimal(12, 1));
1660        assert_eq!(sum(decimal(18, 0), decimal(4, 2)), decimal(21, 2));
1661        assert_eq!(sum(decimal(4, 2), LogicalType::BigInt), decimal(22, 2));
1662        assert_eq!(sum(decimal(4, 2), LogicalType::UBigInt), decimal(23, 2));
1663        assert_eq!(sum(decimal(4, 2), LogicalType::HugeInt), decimal(38, 2));
1664        // Both sides are cast to the answer's type, because the kernel underneath adds two runs of
1665        // the same width and the carry digit can move the answer into a wider one.
1666        let resolved = resolve("-", &[decimal(18, 0), decimal(18, 0)]).expect("subtracts");
1667        assert_eq!(resolved.arguments, vec![decimal(19, 0), decimal(19, 0)]);
1668    }
1669
1670    /// At the maximum width there is nowhere to carry into, so the type stops and the row raises.
1671    #[test]
1672    fn a_decimal_sum_at_the_widest_decimal_stays_there() {
1673        let widest = LogicalType::Decimal { width: MAX_DECIMAL_WIDTH, scale: 0 };
1674        let resolved = resolve("+", &[widest.clone(), widest.clone()]).expect("adds");
1675        assert_eq!(resolved.returns, widest);
1676    }
1677
1678    /// Negation cannot carry, and neither can anything that is not an addition.
1679    ///
1680    /// `-1.50` is a `DECIMAL(4,2)` upstream and so is `abs(-1.50)`, and `5.50 % 3` is a
1681    /// `DECIMAL(12,2)`, which is the promotion with no digit added to it.
1682    #[test]
1683    fn nothing_but_a_two_sided_addition_gains_a_digit() {
1684        let decimal = |width, scale| LogicalType::Decimal { width, scale };
1685        assert_eq!(resolve("-", &[decimal(4, 2)]).expect("negates").returns, decimal(4, 2));
1686        assert_eq!(resolve("+", &[decimal(4, 2)]).expect("is unary plus").returns, decimal(4, 2));
1687        assert_eq!(resolve("abs", &[decimal(4, 2)]).expect("has a size").returns, decimal(4, 2));
1688        assert_eq!(
1689            resolve("%", &[decimal(4, 2), LogicalType::Integer]).expect("divides").returns,
1690            decimal(12, 2)
1691        );
1692    }
1693
1694    /// Every product in here was read off `v2.0.0-dev84237` with `typeof`, per #243.
1695    ///
1696    /// The first three are the plain rule, the next two are the pair that stays in sixty four bits
1697    /// and the pair that does not because it has no digit left in front of the point, and the last
1698    /// is the width running into the widest decimal there is while the scale does not move.
1699    #[test]
1700    fn a_decimal_product_is_as_wide_as_both_of_its_operands_together() {
1701        let decimal = |width, scale| LogicalType::Decimal { width, scale };
1702        let times = |left: LogicalType, right: LogicalType| {
1703            resolve("*", &[left, right]).expect("multiplies").returns
1704        };
1705        assert_eq!(times(decimal(4, 2), decimal(4, 2)), decimal(8, 4));
1706        assert_eq!(times(decimal(4, 2), LogicalType::BigInt), decimal(23, 2));
1707        assert_eq!(times(decimal(18, 3), LogicalType::Integer), decimal(18, 3));
1708        assert_eq!(times(decimal(12, 6), decimal(12, 6)), decimal(18, 12));
1709        assert_eq!(times(decimal(10, 9), decimal(10, 9)), decimal(20, 18));
1710        assert_eq!(times(decimal(18, 17), decimal(18, 17)), decimal(36, 34));
1711        assert_eq!(times(decimal(20, 10), decimal(20, 10)), decimal(38, 20));
1712        // Nothing that is not a decimal goes near any of this.
1713        assert_eq!(times(LogicalType::Integer, LogicalType::Integer), LogicalType::Integer);
1714    }
1715
1716    /// Each side takes the answer's width and keeps its own scale, which is what the kernel needs.
1717    ///
1718    /// The unscaled values then multiply into the answer with nothing rescaled on either side of
1719    /// the operator, which a cast of both sides to the answer's scale would not give.
1720    #[test]
1721    fn a_decimal_product_casts_its_operands_to_the_width_of_the_answer() {
1722        let decimal = |width, scale| LogicalType::Decimal { width, scale };
1723        let resolved = resolve("*", &[decimal(4, 2), LogicalType::BigInt]).expect("multiplies");
1724        assert_eq!(resolved.arguments, vec![decimal(23, 2), decimal(23, 0)]);
1725    }
1726
1727    /// There is no type to put the answer in, so it is refused at bind time rather than truncated.
1728    #[test]
1729    fn a_product_that_needs_more_than_thirty_eight_decimal_places_is_refused() {
1730        let wide = LogicalType::Decimal { width: 30, scale: 30 };
1731        let error = resolve("*", &[wide.clone(), wide]).expect_err("has nowhere to put the scale");
1732        assert!(error.to_string().contains("Max scale is 38"), "{error}");
1733    }
1734
1735    /// The one arithmetic result that is not the promotion, and it is DuckDB's rule rather than an
1736    /// invention: `7 / 2` is 3.5 and `7 // 2` is 3.
1737    #[test]
1738    fn division_gives_a_double_and_integer_division_does_not() {
1739        let divide = resolve("/", &[LogicalType::Integer, LogicalType::Integer]).expect("divides");
1740        assert_eq!(divide.returns, LogicalType::Double);
1741        let integer =
1742            resolve("//", &[LogicalType::Integer, LogicalType::Integer]).expect("divides");
1743        assert_eq!(integer.returns, LogicalType::Integer);
1744    }
1745
1746    /// `//` is integer division only when there are integers on both sides of it, which was
1747    /// measured: `7.5 // 2.5` is the DOUBLE 3.0 upstream and `7.5 // 2` is 3.75, so it neither
1748    /// stays a decimal nor truncates what it divided.
1749    #[test]
1750    fn integer_division_of_anything_but_integers_is_ordinary_division() {
1751        let decimal = LogicalType::Decimal { width: 4, scale: 2 };
1752        let divides = |left: LogicalType, right: LogicalType| {
1753            let resolved = resolve("//", &[left, right]).expect("divides");
1754            (resolved.arguments, resolved.returns)
1755        };
1756        let double = || (vec![LogicalType::Double; 2], LogicalType::Double);
1757        assert_eq!(divides(decimal.clone(), decimal.clone()), double());
1758        assert_eq!(divides(decimal.clone(), LogicalType::Integer), double());
1759        assert_eq!(divides(LogicalType::Integer, decimal), double());
1760        assert_eq!(divides(LogicalType::Double, LogicalType::Double), double());
1761        // A float stays a float, so this is a rule about decimals rather than about width.
1762        assert_eq!(
1763            divides(LogicalType::Float, LogicalType::Float),
1764            (vec![LogicalType::Float; 2], LogicalType::Float)
1765        );
1766        assert_eq!(
1767            divides(LogicalType::Integer, LogicalType::BigInt),
1768            (vec![LogicalType::BigInt; 2], LogicalType::BigInt)
1769        );
1770        assert_eq!(
1771            divides(LogicalType::HugeInt, LogicalType::HugeInt),
1772            (vec![LogicalType::HugeInt; 2], LogicalType::HugeInt)
1773        );
1774    }
1775
1776    /// An alias has to come back under the real name, because the name on [`Resolved`] is what the
1777    /// plan interns and what every kernel below it matches on. SQL is case insensitive here, so the
1778    /// shouted spelling has to land in the same place.
1779    #[test]
1780    fn an_alias_resolves_to_the_function_it_is_an_alias_of() {
1781        for (alias, real) in ALIASES {
1782            assert_eq!(canonical(alias), *real);
1783            assert_eq!(canonical(&alias.to_uppercase()), *real);
1784        }
1785        let resolved = resolve("LEN", &[LogicalType::Varchar]).expect("len resolves");
1786        assert_eq!(resolved.name, "length");
1787        assert_eq!(resolved.returns, LogicalType::BigInt);
1788    }
1789
1790    /// Every alias has to point at a row that exists, or the error a caller gets moves from a
1791    /// missing function to a missing function under another name, which is worse.
1792    #[test]
1793    fn every_alias_points_at_a_real_function() {
1794        for (alias, real) in ALIASES {
1795            assert!(
1796                TABLE.iter().any(|entry| entry.name == *real),
1797                "{alias} points at {real}, which is not in the table"
1798            );
1799        }
1800    }
1801
1802    /// DuckDB refuses a string function anything that is not already a string, and the whole point
1803    /// of refusing is the message, so the message is what this checks.
1804    #[test]
1805    fn a_string_function_refuses_a_type_that_is_not_a_string() {
1806        let error = resolve("lower", &[LogicalType::Date]).expect_err("lower takes strings");
1807        assert_eq!(
1808            error.to_string(),
1809            "Binder Error: No function matches the given name and argument types 'lower(DATE)'. \
1810             You might need to add explicit type casts.\n\tCandidate functions:\n\tlower(col0 \
1811             VARCHAR) -> VARCHAR\n"
1812        );
1813        for name in ["upper", "length", "strlen"] {
1814            assert!(resolve(name, &[LogicalType::Integer]).is_err(), "{name} took an integer");
1815        }
1816        for name in ["~~", "!~~", "~~*", "!~~*"] {
1817            let types = [LogicalType::Integer, LogicalType::Varchar];
1818            assert!(resolve(name, &types).is_err(), "{name} took an integer");
1819        }
1820    }
1821
1822    /// The wrong answer this shape was added for. `length([1,2,3])` used to cast the list to a
1823    /// string and count the nine characters of `[1, 2, 3]`, where DuckDB counts three elements.
1824    /// rudb has no list type in the executor yet, so refusing is the honest end of it for now.
1825    #[test]
1826    fn length_of_something_that_is_not_a_string_is_refused_rather_than_stringified() {
1827        let error = resolve("length", &[LogicalType::Blob]).expect_err("length takes strings");
1828        assert!(error.to_string().contains("length(col0 ANY[]) -> BIGINT"), "{error}");
1829    }
1830
1831    /// `||` is the exception and it has to stay one. `1 || 'a'` is `1a` upstream.
1832    #[test]
1833    fn concatenation_still_takes_anything_and_makes_a_string_of_it() {
1834        let resolved = resolve("||", &[LogicalType::Integer, LogicalType::Varchar])
1835            .expect("concatenation takes anything");
1836        assert_eq!(resolved.returns, LogicalType::Varchar);
1837        assert_eq!(resolved.arguments, vec![LogicalType::Varchar, LogicalType::Varchar]);
1838    }
1839
1840    /// A null literal has no type to pick an overload with, and DuckDB answers `length(NULL)` with
1841    /// NULL rather than refusing it.
1842    #[test]
1843    fn a_string_function_takes_an_untyped_null() {
1844        let resolved = resolve("length", &[LogicalType::Null]).expect("length of a null");
1845        assert_eq!(resolved.returns, LogicalType::BigInt);
1846        assert_eq!(resolved.arguments, vec![LogicalType::Varchar]);
1847    }
1848
1849    /// A candidate block for a name nothing resolves to would be a message about a function that
1850    /// does not exist, which is worse than no block at all.
1851    #[test]
1852    fn every_name_with_candidates_is_a_function_this_engine_has() {
1853        for (name, overloads) in CANDIDATES {
1854            assert!(TABLE.iter().any(|entry| entry.name == *name), "{name} has no entry");
1855            assert!(!overloads.is_empty(), "{name} has an empty candidate list");
1856        }
1857    }
1858
1859    /// `strlen` counts bytes and `length` counts characters, so it is a function and not an alias.
1860    /// This is the test that stops someone folding it into [`ALIASES`] to save a row.
1861    #[test]
1862    fn strlen_is_its_own_function_and_not_an_alias_of_length() {
1863        assert!(!ALIASES.iter().any(|(alias, _)| *alias == "strlen"));
1864        let resolved = resolve("strlen", &[LogicalType::Varchar]).expect("strlen resolves");
1865        assert_eq!(resolved.name, "strlen");
1866        assert_eq!(resolved.returns, LogicalType::BigInt);
1867    }
1868
1869    #[test]
1870    fn a_sum_accumulates_wider_than_it_reads() {
1871        assert_eq!(
1872            resolve("sum", &[LogicalType::Integer]).expect("sums").returns,
1873            LogicalType::HugeInt
1874        );
1875        assert_eq!(
1876            resolve("sum", &[LogicalType::Double]).expect("sums").returns,
1877            LogicalType::Double
1878        );
1879        assert_eq!(
1880            resolve("sum", &[LogicalType::Float]).expect("sums").returns,
1881            LogicalType::Double
1882        );
1883    }
1884
1885    #[test]
1886    fn count_takes_anything_and_returns_a_bigint() {
1887        let counted = resolve("count", &[LogicalType::Varchar]).expect("counts strings");
1888        assert_eq!(counted.returns, LogicalType::BigInt);
1889        assert_eq!(counted.arguments, vec![LogicalType::Varchar], "count does not cast its input");
1890        assert_eq!(resolve("count_star", &[]).expect("counts rows").returns, LogicalType::BigInt);
1891    }
1892
1893    /// `date_part` says double whatever it reads and `date_trunc` hands back the type it was given,
1894    /// which is two answers that one shape cannot give and is why there are two new ones. A double
1895    /// rather than a bigint because that is upstream's declared overload, and the narrowing to a
1896    /// bigint happens in the binder, where the specifier can be looked at.
1897    #[test]
1898    fn a_date_function_fixes_the_part_and_leaves_the_date_alone() {
1899        let part = resolve("date_part", &[LogicalType::Varchar, LogicalType::Timestamp])
1900            .expect("a part of a timestamp");
1901        assert_eq!(part.returns, LogicalType::Double);
1902        assert_eq!(part.arguments, vec![LogicalType::Varchar, LogicalType::Timestamp]);
1903        let truncated = resolve("date_trunc", &[LogicalType::Varchar, LogicalType::Date])
1904            .expect("a truncated date");
1905        assert_eq!(truncated.returns, LogicalType::Date);
1906        assert_eq!(truncated.arguments, vec![LogicalType::Varchar, LogicalType::Date]);
1907    }
1908
1909    /// The two constructors, and the arity with a hole in it. Two arguments is not a `make_date`
1910    /// upstream has and it is not one here either.
1911    #[test]
1912    fn a_date_is_made_from_one_number_or_from_three_and_never_from_two() {
1913        let day = resolve("make_date", &[LogicalType::Integer]).expect("days since the epoch");
1914        assert_eq!(day.returns, LogicalType::Date);
1915        assert_eq!(day.arguments, vec![LogicalType::Integer]);
1916        let civil =
1917            resolve("make_date", &vec![LogicalType::BigInt; 3]).expect("a year, a month and a day");
1918        assert_eq!(civil.returns, LogicalType::Date);
1919        assert_eq!(civil.arguments, vec![LogicalType::Integer; 3]);
1920        let error = resolve("make_date", &vec![LogicalType::Integer; 2]).unwrap_err();
1921        assert_eq!(
1922            error.message(),
1923            "No function matches the given name and argument types 'make_date(INTEGER, INTEGER)'. You might need to add explicit type casts."
1924        );
1925    }
1926
1927    #[test]
1928    fn milliseconds_since_the_epoch_are_a_timestamp() {
1929        let stamp = resolve("epoch_ms", &[LogicalType::Integer]).expect("a timestamp");
1930        assert_eq!(stamp.returns, LogicalType::Timestamp);
1931        assert_eq!(stamp.arguments, vec![LogicalType::BigInt], "the argument widens to read it");
1932        let error = resolve("epoch_ms", &[LogicalType::Varchar]).unwrap_err();
1933        assert!(error.message().contains("'epoch_ms(VARCHAR)'"), "{error}");
1934    }
1935
1936    /// The part is cast rather than checked, so a part that arrives as something other than a
1937    /// string is a string by the time the kernel sees it.
1938    #[test]
1939    fn the_part_of_a_date_function_is_cast_to_a_string() {
1940        let resolved = resolve("date_part", &[LogicalType::Integer, LogicalType::Date])
1941            .expect("the part is cast rather than refused");
1942        assert_eq!(resolved.arguments, vec![LogicalType::Varchar, LogicalType::Date]);
1943    }
1944
1945    /// The group number of an extraction has to arrive as a number, since the kernel tells the
1946    /// option string from the group by the type rather than by the position.
1947    #[test]
1948    fn an_extraction_casts_the_text_and_the_pattern_and_leaves_the_group_alone() {
1949        let resolved = resolve(
1950            "regexp_extract",
1951            &[LogicalType::Varchar, LogicalType::Varchar, LogicalType::Integer],
1952        )
1953        .expect("an extraction");
1954        assert_eq!(resolved.returns, LogicalType::Varchar);
1955        assert_eq!(
1956            resolved.arguments,
1957            vec![LogicalType::Varchar, LogicalType::Varchar, LogicalType::Integer]
1958        );
1959        let matched = resolve("regexp_matches", &[LogicalType::Varchar, LogicalType::Varchar])
1960            .expect("a match");
1961        assert_eq!(matched.returns, LogicalType::Boolean);
1962    }
1963
1964    #[test]
1965    fn a_name_that_is_not_a_function_says_so_the_way_duckdb_does() {
1966        let error = resolve("nope", &[]).expect_err("there is no function called nope");
1967        assert_eq!(
1968            error.to_string(),
1969            "Catalog Error: Scalar Function with name nope does not exist!"
1970        );
1971    }
1972
1973    #[test]
1974    fn the_wrong_number_of_arguments_is_caught() {
1975        let error = resolve("abs", &[LogicalType::Integer, LogicalType::Integer])
1976            .expect_err("abs takes one");
1977        assert!(error.message().contains("No function matches"), "{error}");
1978    }
1979
1980    #[test]
1981    fn arithmetic_on_a_string_is_refused() {
1982        let error =
1983            resolve("*", &[LogicalType::Varchar, LogicalType::Integer]).expect_err("no multiply");
1984        assert!(error.message().contains("No function matches"), "{error}");
1985    }
1986
1987    #[test]
1988    fn a_call_over_nothing_but_nulls_lands_on_a_type_an_executor_can_hold() {
1989        let resolved =
1990            resolve("+", &[LogicalType::Null, LogicalType::Null]).expect("null plus null");
1991        assert_eq!(resolved.returns, LogicalType::Integer);
1992    }
1993
1994    /// `nullif` compares at one type and answers at another, both read off the pinned binary with
1995    /// `typeof`. Per #306.
1996    #[test]
1997    fn nullif_answers_the_first_argument_and_compares_at_the_promotion() {
1998        let resolved =
1999            resolve("nullif", &[LogicalType::Integer, LogicalType::Decimal { width: 2, scale: 1 }])
2000                .expect("an integer and a decimal compare");
2001        assert_eq!(resolved.returns, LogicalType::Integer);
2002        let wide = LogicalType::Decimal { width: 11, scale: 1 };
2003        assert_eq!(resolved.arguments, vec![wide.clone(), wide]);
2004        let resolved = resolve("nullif", &[LogicalType::BigInt, LogicalType::SmallInt])
2005            .expect("two integers compare");
2006        assert_eq!(resolved.returns, LogicalType::BigInt);
2007        let resolved =
2008            resolve("nullif", &[LogicalType::Null, LogicalType::Null]).expect("two nulls compare");
2009        assert_eq!(resolved.returns, LogicalType::Integer, "there is nothing else to hand back");
2010        let error = resolve("nullif", &[LogicalType::Varchar, LogicalType::Integer])
2011            .expect_err("a string and a number have nothing in common here");
2012        assert!(error.message().contains("No function matches"), "{error}");
2013    }
2014
2015    #[test]
2016    fn an_aggregate_is_known_to_be_one() {
2017        assert_eq!(kind_of("sum"), Some(FunctionKind::Aggregate));
2018        assert_eq!(kind_of("SUM"), Some(FunctionKind::Aggregate), "names are case insensitive");
2019        assert_eq!(kind_of("abs"), Some(FunctionKind::Scalar));
2020        assert_eq!(kind_of("nope"), None);
2021    }
2022
2023    /// Two rows for one name would need a rule for which one wins, and there is no such rule yet,
2024    /// so the table having none is worth asserting rather than remembering.
2025    #[test]
2026    fn no_name_appears_twice() {
2027        let mut names: Vec<&str> = TABLE.iter().map(|entry| entry.name).collect();
2028        let count = names.len();
2029        names.sort_unstable();
2030        names.dedup();
2031        assert_eq!(names.len(), count, "a name is in the table twice");
2032    }
2033
2034    #[test]
2035    fn every_entry_resolves_at_every_count_it_accepts() {
2036        for entry in TABLE {
2037            // The one row that is meant not to resolve, because the binder answers the call before
2038            // it gets here and the only way here is the case upstream refuses. It has a test of its
2039            // own below rather than an exception with nothing behind it.
2040            if entry.shape == Shape::Setting {
2041                continue;
2042            }
2043            for count in entry.arity.counts() {
2044                // A shape that names the type it wants is asked for it, since `chr` wants an
2045                // INTEGER and refuses a string the way upstream does.
2046                let ty = match (entry.numeric_only, entry.shape) {
2047                    (
2048                        _,
2049                        Shape::Exact(argument, _)
2050                        | Shape::Widened(argument, _)
2051                        | Shape::WidenedTogether(argument, _),
2052                    ) => argument.ty(),
2053                    (true, _) => LogicalType::Integer,
2054                    (false, _) => LogicalType::Varchar,
2055                };
2056                let mut arguments = vec![ty; count];
2057                // A subscript and a substring are the shapes whose arguments are not all alike. The
2058                // leading ones are the string or the list and everything after them is a whole
2059                // number, so a row of strings is not a call either one accepts and not a call worth
2060                // asserting it accepts.
2061                let leading = match entry.shape {
2062                    Shape::Extracted | Shape::Sliced => 1,
2063                    Shape::TextThenIndex(leading, _) => leading,
2064                    _ => count,
2065                };
2066                for bound in arguments.iter_mut().skip(leading) {
2067                    *bound = LogicalType::BigInt;
2068                }
2069                resolve(entry.name, &arguments).unwrap_or_else(|error| {
2070                    panic!("{} does not resolve at {count} arguments: {error}", entry.name)
2071                });
2072            }
2073        }
2074    }
2075
2076    /// The three answers the pin gives a call to `current_setting`, read off `v2.0.0-dev84237`.
2077    ///
2078    /// The right number of arguments and a name the binder could not fold is the constant
2079    /// expression sentence, and a wrong number is the ordinary arity error with the one overload
2080    /// listed under it. The folded case is not here because it never reaches this table.
2081    #[test]
2082    fn a_setting_read_from_a_column_is_refused_in_the_pins_words() {
2083        let error = resolve("current_setting", &[LogicalType::Varchar]).expect_err("is refused");
2084        assert_eq!(
2085            error.to_string(),
2086            "Binder Error: The \"setting_name\" argument in function \"current_setting\" must be a constant expression"
2087        );
2088        let none = resolve("current_setting", &[]).expect_err("takes one argument");
2089        assert_eq!(
2090            none.to_string(),
2091            "Binder Error: No function matches the given name and argument types 'current_setting()'. \
2092             You might need to add explicit type casts.\n\tCandidate functions:\n\tcurrent_setting(setting_name VARCHAR) -> ANY\n"
2093        );
2094    }
2095
2096    /// One row with an `ANY` return, which is what the pin's `duckdb_functions()` says about it.
2097    #[test]
2098    fn a_setting_is_declared_over_a_string_and_returns_anything() {
2099        let row = function_rows()
2100            .into_iter()
2101            .find(|row| row.name == "current_setting")
2102            .expect("a row for it");
2103        assert_eq!(row.types, ["VARCHAR"]);
2104        assert_eq!(row.returns, "ANY");
2105        assert_eq!(row.varargs, None);
2106    }
2107
2108    /// A signature that promotes over its arguments and accepts none of them would reach the
2109    /// internal error in `promote_all`, which is a message no user should ever see.
2110    #[test]
2111    fn nothing_that_promotes_accepts_no_arguments() {
2112        for entry in TABLE {
2113            let promotes =
2114                matches!(entry.shape, Shape::Promoted | Shape::PromotedTo(_) | Shape::Accumulated);
2115            assert!(
2116                !(promotes && entry.arity.least() == 0),
2117                "{} promotes over its arguments and takes none",
2118                entry.name
2119            );
2120        }
2121    }
2122
2123    /// `-` is the negation and the subtraction under one name, which is the reason arity is a
2124    /// range, so it is worth holding to.
2125    #[test]
2126    fn minus_is_both_the_negation_and_the_subtraction() {
2127        assert_eq!(
2128            resolve("-", &[LogicalType::Integer]).expect("negates").returns,
2129            LogicalType::Integer
2130        );
2131        assert_eq!(
2132            resolve("-", &[LogicalType::Integer, LogicalType::BigInt]).expect("subtracts").returns,
2133            LogicalType::BigInt
2134        );
2135        assert!(
2136            resolve("-", &vec![LogicalType::Integer; 3]).is_err(),
2137            "three is not an arity minus has"
2138        );
2139    }
2140}