Skip to main content

rupg_func/
lib.rs

1//! The built-in functions: the input and output functions of the types, and the kernels of the functions, the operators and the casts of `pg_proc`.
2//!
3//! A kernel is found by the `prosrc` of the function, as the `fmgr` of PostgreSQL finds the C function of an internal function. Many functions of the same kind, such as the comparisons and the arithmetic of the number types, share one kernel that reads the types of the call. A function that has no kernel here is an error `0A000` when the executor compiles the query, so a query never gives a wrong answer for a function that the engine does not have.
4
5#![forbid(unsafe_code)]
6
7mod absent;
8mod acl;
9mod activity;
10mod advisory;
11mod agg;
12mod amutils;
13mod array;
14mod autovacuum;
15mod binary;
16mod bit;
17mod bytea;
18mod calendar;
19mod cash;
20mod cast;
21mod catinfo;
22mod compare;
23mod datetime;
24mod dbsize;
25mod deparse;
26mod describe;
27mod encoding;
28mod enums;
29mod extract;
30mod formatting;
31mod generated;
32mod geo;
33mod hash;
34mod identify;
35mod inrange;
36mod io;
37mod json;
38mod jsonbuild;
39mod jsonedit;
40mod jsonpath;
41mod lsn;
42mod mac;
43mod math;
44mod misc;
45mod multirange;
46mod network;
47mod numformat;
48mod random;
49mod range;
50mod reg;
51mod regex;
52mod regress;
53mod replication;
54mod sequence;
55mod shared;
56mod snapshot;
57mod special;
58mod srf;
59mod stat;
60mod text;
61mod timezone;
62mod trig;
63mod tsearch;
64mod tsheadline;
65mod tsm;
66mod tsmatch;
67mod tsparser;
68mod tsquery;
69mod tsrank;
70mod tsrewrite;
71mod tsstat;
72mod tsvector;
73mod unicode;
74mod updatable;
75mod xml;
76mod zones;
77
78use std::borrow::Cow;
79use std::collections::BTreeMap;
80use std::rc::Rc;
81use std::sync::{Arc, OnceLock};
82
83use rupg_common::{Error, Object, Result, SqlState};
84use rupg_pgcatalog::builtin;
85use rupg_types::{ByteaOutput, DateFormat, IntervalStyle, TimeZone, TypeError, Value};
86
87pub use acl::{check_execute, check_permissions, insert_allowed, lock_table_allowed};
88pub use activity::{Backend, BackendState, Client, Ssl};
89pub use agg::check_percentile;
90pub use cast::local_time;
91pub use compare::{compare, equal};
92pub use datetime::{IntervalSum, interval_lerp};
93pub use deparse::{
94    deparse_constant, deparse_expression, deparse_relation_expression, explain, index_key_columns,
95    partition_key_columns, view_statement,
96};
97pub use describe::describe;
98pub use encoding::{char_to_encoding, encoding, encoding_to_char};
99pub use hash::{HASH_PARTITION_SEED, extended_hash, hash_combine64, partition_hash};
100pub use io::{
101    base_type, input, input_soft, input_supported, is_row_type, output, output_supported, receive,
102    send, to_text,
103};
104pub use jsonbuild::{
105    is_json, json_ctor_array, json_ctor_object, json_ctor_parse, json_ctor_scalar, json_structured,
106    json_value,
107};
108pub use jsonpath::{PathVar, SqlJsonItem, sql_json_path};
109pub use multirange::range_agg;
110pub use random::Randomness;
111pub use reg::ts_config_setting;
112pub use regex::{AuthMatch, auth_compile, auth_search};
113pub use sequence::Sequences;
114pub use snapshot::XactState;
115pub use srf::{SetKernel, set_kernel};
116pub use stat::{RelationCounts, Writes};
117pub use text::quote_identifier;
118pub use tsm::sample_rows;
119pub use xml::{xml_expr, xml_value};
120
121/// `format_type_be`: the name of a type for a message, with its schema when the search path does not find it.
122pub fn type_message_name(ty: u32, session: &dyn Session) -> String {
123    reg::type_text(ty, None, session).unwrap_or_else(|_| "???".to_string())
124}
125
126/// `errtable`: the error with the schema and the name of the relation `rel` as the names of its object. An error for a relation that is not in the catalog does not change.
127pub fn with_table(error: Error, rel: u32, session: &dyn Session) -> Error {
128    let Some((name, namespace)) = reg::class_name(rel, session) else { return error };
129    let error = error.with_object(Object::Table, name);
130    match reg::namespace_name(namespace, session) {
131        Some(schema) => error.with_object(Object::Schema, schema),
132        None => error,
133    }
134}
135
136/// `errtablecol`: [`with_table`] and the name of the column.
137pub fn with_table_column(error: Error, rel: u32, column: &str, session: &dyn Session) -> Error {
138    with_table(error, rel, session).with_object(Object::Column, column)
139}
140
141/// `errtableconstraint`: [`with_table`] and the name of the constraint.
142pub fn with_table_constraint(
143    error: Error,
144    rel: u32,
145    constraint: &str,
146    session: &dyn Session,
147) -> Error {
148    with_table(error, rel, session).with_object(Object::Constraint, constraint)
149}
150
151/// `errdatatype`: the error with the schema and the name of the type `ty` as the names of its object.
152pub fn with_datatype(error: Error, ty: u32, session: &dyn Session) -> Error {
153    let Some((name, namespace)) = reg::type_name(ty, session) else { return error };
154    let error = error.with_object(Object::Datatype, name);
155    match reg::namespace_name(namespace, session) {
156        Some(schema) => error.with_object(Object::Schema, schema),
157        None => error,
158    }
159}
160
161/// `errdomainconstraint`: [`with_datatype`] for the domain and the name of the constraint.
162pub fn with_domain_constraint(
163    error: Error,
164    domain: u32,
165    constraint: &str,
166    session: &dyn Session,
167) -> Error {
168    with_datatype(error, domain, session).with_object(Object::Constraint, constraint)
169}
170
171/// The OID of `internal`, the language of the functions in C.
172const INTERNAL_LANGUAGE: u32 = 12;
173/// The OID of the language `c`, the language of the functions of a library.
174const C_LANGUAGE: u32 = 13;
175
176/// The key of an advisory lock, the fields 2 to 4 of its tag: the two halves of a `bigint` key with `kind` 1, or two `integer` keys with `kind` 2. The database of the session is the field 1.
177#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
178pub struct AdvisoryKey {
179    pub high: u32,
180    pub low: u32,
181    pub kind: u16,
182}
183
184/// A request for an advisory lock: the key, the mode, which is `ShareLock` when `share` is true and `ExclusiveLock` when it is false, and the level, which is the session when `session` is true and the transaction when it is false.
185#[derive(Clone, Copy, Debug, PartialEq, Eq)]
186pub struct AdvisoryLock {
187    pub key: AdvisoryKey,
188    pub share: bool,
189    pub session: bool,
190}
191
192/// The state of the session that the functions read.
193pub trait Session {
194    /// The `DateStyle` setting.
195    fn date_format(&self) -> DateFormat;
196    /// The `IntervalStyle` setting.
197    fn interval_style(&self) -> IntervalStyle;
198    /// The `TimeZone` setting.
199    ///
200    /// # Errors
201    ///
202    /// `22023` when the value of `TimeZone` is not a zone.
203    fn zone(&self) -> Result<Rc<dyn TimeZone>>;
204    /// The `extra_float_digits` setting.
205    fn extra_float_digits(&self) -> i32;
206    /// The `bytea_output` setting.
207    fn bytea_output(&self) -> ByteaOutput;
208    /// The `array_nulls` setting.
209    fn array_nulls(&self) -> bool;
210    /// The start of the transaction in microseconds since 2000-01-01 UTC.
211    fn transaction_start(&self) -> i64;
212    /// The start of the statement in microseconds since 2000-01-01 UTC.
213    fn statement_start(&self) -> i64;
214    /// The time now in microseconds since 2000-01-01 UTC.
215    fn clock(&self) -> i64;
216    /// The current user, which is the owner during a call of a `SECURITY DEFINER` function.
217    fn user(&self) -> Cow<'_, str>;
218    /// The session user.
219    fn session_user(&self) -> &str;
220    /// `SYSTEM_USER`: the method of the authentication and the identity that it checked, as `auth_method:authn_id`, or `None` when the method checked no identity, as for `trust`.
221    fn system_user(&self) -> Option<String> {
222        None
223    }
224    /// `debug_query_string`: the text of the message of the client that runs the statement, which `current_query` gives.
225    fn query(&self) -> Option<String> {
226        None
227    }
228    /// The current database.
229    fn database(&self) -> &str;
230    /// The schemas of `search_path` that exist, in order, without the implicit schemas.
231    fn schemas(&self) -> Vec<String>;
232    /// The number of the session in the table of the sessions, which names its temporary schema `pg_temp_N`, or `None` for a session that cannot have temporary objects.
233    fn temp_number(&self) -> Option<i32> {
234        None
235    }
236    /// The process ID of the session.
237    fn backend_pid(&self) -> i32;
238    /// `MyTriggerDepth`: the number of the trigger functions that run, one in the other. It is 0 outside of a trigger.
239    fn trigger_depth(&self) -> i32 {
240        0
241    }
242    /// The ID of the transaction: `GetTopFullTransactionId` when `assign` is true, which gives an ID to a transaction that has none, and `GetTopFullTransactionIdIfAny` when it is false. `None` when the transaction has no ID or the session has no server.
243    fn transaction_id(&self, assign: bool) -> Option<u64> {
244        let _ = assign;
245        None
246    }
247    /// `ReadNextFullTransactionId`: the ID that the next transaction gets.
248    fn next_transaction_id(&self) -> u64 {
249        3
250    }
251    /// `GetStableLatestTransactionId`: the ID of the transaction, or the ID that the next transaction gets when it has none, the same for the whole transaction.
252    fn stable_transaction_id(&self) -> u32 {
253        3
254    }
255    /// The state of the transaction `xid`, which is before [`Session::next_transaction_id`], or `None` when the session does not know it.
256    fn transaction_state(&self, xid: u32) -> Option<XactState> {
257        let _ = xid;
258        None
259    }
260    /// `GetActiveSnapshot`: the snapshot of the statement as a `pg_snapshot`, or `None` when the statement has no snapshot.
261    fn current_snapshot(&self) -> Option<rupg_types::Snapshot> {
262        None
263    }
264    /// The text of `version()`.
265    fn version(&self) -> String;
266    /// The value of a setting as `SHOW` gives it, or `None` for a name that is not a setting.
267    fn setting(&self, name: &str) -> Option<String>;
268    /// `set_config_option` for `set_config`: sets a parameter for the session, or for the transaction when `local` is true, and gives the new value as `SHOW` gives it. `value` is `None` for a reset.
269    ///
270    /// # Errors
271    ///
272    /// The errors of `SET` for the name and the value.
273    fn set_setting(&self, name: &str, value: Option<&str>, local: bool) -> Result<String>;
274    /// `GetConfigOptionFlags` with `GUC_LIST_QUOTE` and `SplitGUCList`: the elements of the value `text` of the parameter `name` when the parameter quotes the elements of its list, or `None` for another parameter and for a name that is not a parameter.
275    fn setting_list(&self, name: &str, text: &str) -> Option<Vec<String>> {
276        let _ = (name, text);
277        None
278    }
279    /// `fmgr_security_definer` for a function with settings or with `SECURITY DEFINER`: `definer`, the owner of a `SECURITY DEFINER` function, is the current user, and `ProcessGUCArray` with `GUC_ACTION_SAVE` gives the settings of `proconfig`, each one as `name=value`, until [`Session::end_function_call`]. A session with no settings does nothing.
280    ///
281    /// # Errors
282    ///
283    /// The errors of the names and of the values.
284    fn start_function_call(&self, config: &[String], definer: Option<u32>) -> Result<()> {
285        let _ = (config, definer);
286        Ok(())
287    }
288    /// The end of the call of [`Session::start_function_call`]: the current user from before the call comes back, and `AtEOXact_GUC` gives the settings their values from before the call, other than the ones that a `SET` in the call changed.
289    fn end_function_call(&self) {}
290    /// `CHECK_FOR_INTERRUPTS`: the check for a cancel of the statement, which a long loop of the executor, such as the loop of a recursive query, does at each step. A session with no server has no cancel.
291    ///
292    /// # Errors
293    ///
294    /// `57014` when a client canceled the statement.
295    fn interrupted(&self) -> Result<()> {
296        Ok(())
297    }
298    /// `WaitLatch` with the wait event `PgSleep`: the session waits for at most `micros` microseconds. A cancel ends the wait early, and the next call of [`Session::interrupted`] gives its error.
299    ///
300    /// # Errors
301    ///
302    /// `0A000` for a session with no server, which cannot wait.
303    fn sleep(&self, micros: i64) -> Result<()> {
304        let _ = micros;
305        Err(not_yet("a wait in a session with no server"))
306    }
307    /// `LockAcquire` of an advisory lock in the database of the session. With `wait`, the session waits while another session holds or waits for a lock that conflicts, and then gives true. Without `wait`, it gives false at once.
308    ///
309    /// # Errors
310    ///
311    /// `57014` for a cancel, `40P01` for a deadlock, `55P03` for the end of `lock_timeout`, and `0A000` for a session with no server.
312    fn advisory_lock(&self, lock: AdvisoryLock, wait: bool) -> Result<bool> {
313        let _ = (lock, wait);
314        Err(not_yet("an advisory lock in a session with no server"))
315    }
316    /// `LockRelease` of an advisory lock of the session level. It gives false when the session does not hold the lock in this mode at the session level.
317    ///
318    /// # Errors
319    ///
320    /// `0A000` for a session with no server.
321    fn advisory_unlock(&self, lock: AdvisoryLock) -> Result<bool> {
322        let _ = lock;
323        Err(not_yet("an advisory lock in a session with no server"))
324    }
325    /// `LockReleaseSession`: releases all the advisory locks of the session level.
326    ///
327    /// # Errors
328    ///
329    /// `0A000` for a session with no server.
330    fn advisory_unlock_all(&self) -> Result<()> {
331        Err(not_yet("an advisory lock in a session with no server"))
332    }
333    /// The rows of `pg_show_all_settings`, one for each parameter that `SHOW ALL` lists, in the 17 columns of the function.
334    fn all_settings(&self) -> Vec<Vec<Value>> {
335        Vec::new()
336    }
337    /// The rows of `pg_prepared_statement`, one for each named prepared statement of the session, in the 8 columns of the function. The order is not defined.
338    fn prepared_statements(&self) -> Vec<Vec<Value>> {
339        Vec::new()
340    }
341    /// The rows of `pg_cursor`, one for each cursor of `DECLARE` that is open in the session, in the 6 columns of the function. The order is not defined.
342    fn cursors(&self) -> Vec<Vec<Value>> {
343        Vec::new()
344    }
345    /// The rows of `pg_hba_file_rules`, one for each line of the host rules, in the 11 columns of the function. A session with no server has no rules and no rows.
346    ///
347    /// # Errors
348    ///
349    /// The error of a file of the rules that does not open.
350    fn hba_rules(&self) -> Result<Vec<Vec<Value>>> {
351        Ok(Vec::new())
352    }
353    /// The rows of `pg_ident_file_mappings`, one for each line of the user maps, in the 7 columns of the function. A session with no server has no maps and no rows.
354    ///
355    /// # Errors
356    ///
357    /// The error of a file of the maps that does not open.
358    fn ident_mappings(&self) -> Result<Vec<Vec<Value>>> {
359        Ok(Vec::new())
360    }
361    /// The rows of `pg_show_all_file_settings`, one for each line of the configuration files and each error in them, in the 7 columns of the function. A session with no server has no rows.
362    fn file_settings(&self) -> Vec<Vec<Value>> {
363        Vec::new()
364    }
365    /// The stored secret of the password of a role, which `pg_authid.rolpassword` shows, or `None` for a role with no password.
366    fn role_password(&self, role: u32) -> Option<String> {
367        let _ = role;
368        None
369    }
370    /// The row of the file of a sequence as the sessions changed it, or `None` when no session changed it, so that the row is the one of the file when it was made.
371    fn sequence_row(&self, file: u32) -> Option<rupg_catalog::SequenceData> {
372        let _ = file;
373        None
374    }
375    /// The change of the row of the file of a sequence, outside of the transaction, so that a rollback does not undo it. `initial` is the row when no session changed it yet. The change stays only when `change` gives no error, and no other session changes the row at the same time.
376    ///
377    /// # Errors
378    ///
379    /// The error of `change`, and `0A000` for a session with no server.
380    fn change_sequence(
381        &self,
382        file: u32,
383        initial: rupg_catalog::SequenceData,
384        change: &mut dyn FnMut(&mut rupg_catalog::SequenceData) -> Result<()>,
385    ) -> Result<()> {
386        let _ = (file, initial, change);
387        Err(not_yet("a sequence in a session with no server"))
388    }
389    /// The cache of the sequences of the session, or `None` for a session with no server.
390    fn local_sequences(&self) -> Option<&std::cell::RefCell<Sequences>> {
391        None
392    }
393    /// The state of `random` and `uuidv7` of the session, or `None` for a session with no server, which uses a state of its thread.
394    fn randomness(&self) -> Option<&std::cell::RefCell<Randomness>> {
395        None
396    }
397    /// `pg_strong_random`: fills `buf` with random bytes. A session with no server takes them from a generator with a seed from the clock.
398    fn strong_random(&self, buf: &mut [u8]) {
399        random::clock_random(self.clock(), buf);
400    }
401    /// The catalog of the user objects that the statement sees, or `None` when the session has no catalog.
402    fn catalog(&self) -> Option<&rupg_catalog::Catalog> {
403        None
404    }
405    /// The rows of the transition table `name` of the trigger that runs, which a scan of a `NamedTuplestoreScan` reads, or `None` when the trigger has no such table.
406    fn transition_rows(&self, name: &str) -> Option<Rc<Vec<Vec<Value>>>> {
407        let _ = name;
408        None
409    }
410    /// The rows of `pg_database` of the databases that `CREATE DATABASE` made, in the order of their OIDs. The rows of `initdb` are static rows. A session with no server has no other databases.
411    fn databases(&self) -> Arc<[rupg_catalog::Database]> {
412        Arc::from(Vec::new())
413    }
414    /// The rows of `pg_tablespace` of the tablespaces that `CREATE TABLESPACE` made, in the order of their OIDs. The rows of `pg_default` and `pg_global` are static rows. A session with no server has no other tablespaces.
415    fn tablespaces(&self) -> Arc<[rupg_catalog::Tablespace]> {
416        Arc::from(Vec::new())
417    }
418    /// The rows of `pg_db_role_setting`: the OID of the database, the OID of the role, and the settings, each as `name=value`. A session with no server has no rows.
419    fn db_role_settings(&self) -> Vec<(u32, u32, Vec<String>)> {
420        Vec::new()
421    }
422    /// The rows of the table of the sessions in the order of their numbers, from the snapshot of the transaction. The first call of a transaction takes the snapshot.
423    fn backends(&self) -> Arc<[Backend]> {
424        Arc::from(Vec::new())
425    }
426    /// `BackendPidGetProc` and `GetBlockerStatusData`: the process IDs of the sessions that hold or wait for a lock that the session `pid` waits for, or for whose transaction it waits. A session with no server has no waits.
427    fn blocking_pids(&self, pid: i32) -> Vec<i32> {
428        let _ = pid;
429        Vec::new()
430    }
431    /// `pgstat_clear_snapshot`: drops the snapshot of the table of the sessions and of the statistics.
432    fn clear_backends(&self) {}
433    /// `pgstat_count_heap_scan`: counts a sequential scan of a relation in the counts of the transaction. A session with no server keeps no counts.
434    fn count_scan(&self, relation: u32) {
435        let _ = relation;
436    }
437    /// The rows of a table of the user that the snapshot of the statement sees, each with a value for each column of the table when the row was written. A session with no server has no rows.
438    ///
439    /// # Errors
440    ///
441    /// An error of the store of the rows.
442    fn table_rows(&self, relation: u32) -> Result<Vec<Vec<Value>>> {
443        let _ = relation;
444        Ok(Vec::new())
445    }
446    /// The rows of [`Session::table_rows`], each with the system columns `xmin` and `xmax` of its version before the ID of the version.
447    ///
448    /// # Errors
449    ///
450    /// An error of the store of the rows.
451    fn table_rows_with_xids(&self, relation: u32) -> Result<Vec<Vec<Value>>> {
452        let _ = relation;
453        Ok(Vec::new())
454    }
455    /// `pgstat_fetch_stat_tabentry`: the counters of a relation of the database of the session, from the snapshot of the transaction, or `None` for a relation with no entry. The first call of a transaction takes the snapshot.
456    fn relation_counts(&self, relation: u32) -> Option<RelationCounts> {
457        let _ = relation;
458        None
459    }
460    /// `find_tabstat_entry`: the sequential scans of a relation that the transaction counted and did not report yet.
461    fn pending_scans(&self, relation: u32) -> i64 {
462        let _ = relation;
463        0
464    }
465    /// `find_tabstat_entry`: the rows that the transaction wrote in a relation and did not report yet, with the rows of the subtransactions that rolled back.
466    fn pending_writes(&self, relation: u32) -> Writes {
467        let _ = relation;
468        Writes::default()
469    }
470    /// The time of the last reset of the statistics of the whole server in microseconds since 2000-01-01 UTC, or 0 when the session has no server.
471    fn stats_reset(&self) -> i64 {
472        0
473    }
474    /// The two ends of the connection of the session: the client, then the server.
475    fn addresses(&self) -> (Client, Client) {
476        (Client::Unknown, Client::Unknown)
477    }
478    /// `domain_check_safe` for a value of a domain or for each element of an array of a domain: the error of the first check constraint that rejects the value, or `None` when the value passes. The engine evaluates the checks, so a session without an engine cannot do this.
479    ///
480    /// # Errors
481    ///
482    /// The error of a check expression.
483    fn input_checks(&self, ty: u32, value: &Value) -> Result<Option<Error>> {
484        let _ = (ty, value);
485        Err(not_yet("the check constraints of a domain"))
486    }
487    /// `ereport(WARNING)` or `ereport(NOTICE)` in a function: a message for the client, such as the warning of the input of an `aclitem` value with no grantor. A message with a SQLSTATE of class `00` or with the mark of `Error::as_notice` is a `NOTICE`, and any other message is a `WARNING`. A session with no client drops it.
488    fn warn(&self, warning: Error) {
489        let _ = warning;
490    }
491    /// `SPI_cursor_open` of a read-only plan for `text` and the fetch of all its rows, for a function that runs a query, such as `ts_stat`. It gives the type of each column and the rows.
492    ///
493    /// # Errors
494    ///
495    /// `42P11` when the text is not one statement that gives rows, the errors of the query, and `0A000` for a session that cannot run a query.
496    fn run_query(&self, text: &str) -> Result<(Vec<u32>, Vec<Vec<Value>>)> {
497        let _ = text;
498        Err(not_yet("a query in a function"))
499    }
500    /// `execCurrentOf`: the `tableoid` and the `ctid` of the row of the table `table` that the cursor `cursor` is on.
501    ///
502    /// # Errors
503    ///
504    /// `34000` when there is no such cursor, and `24000` when the cursor is not on a row of the table.
505    fn current_of(&self, cursor: &str, table: u32) -> Result<(Value, Value)> {
506        let _ = table;
507        Err(Error::new(SqlState::UNDEFINED_CURSOR, format!("cursor \"{cursor}\" does not exist")))
508    }
509    /// `fmgr_sql` for a function in SQL whose body is [`rupg_analyze::Body::Statements`]: a call of the function `func` with the values `args` of the types `types`. The statements run one after the other, and the call gives the types of the columns of the last statement and its rows.
510    ///
511    /// # Errors
512    ///
513    /// The errors of the statements, and `0A000` for a session that cannot run them.
514    fn call_sql_function(
515        &self,
516        func: u32,
517        types: &[u32],
518        args: &[Value],
519    ) -> Result<(Vec<u32>, Vec<Vec<Value>>)> {
520        let _ = (func, types, args);
521        Err(not_yet("a function in SQL with more than one statement"))
522    }
523    /// `plpgsql_call_handler`: a call of the function `func` in PL/pgSQL with the values `args` of the types `types`, for the result type `ret`. It gives the value of the function, or a value for each row of a function that returns a set. A row is a `Record`.
524    ///
525    /// # Errors
526    ///
527    /// The errors of the function, and `0A000` for a session that cannot run a function in PL/pgSQL.
528    fn call_function(
529        &self,
530        func: u32,
531        types: &[u32],
532        ret: u32,
533        args: &[Value],
534    ) -> Result<Vec<Value>> {
535        let _ = (func, types, ret, args);
536        Err(not_yet("a function in PL/pgSQL"))
537    }
538}
539
540/// A call of a function.
541pub struct Call<'a> {
542    pub session: &'a dyn Session,
543    /// The types of the arguments as the query gives them.
544    pub args: &'a [u32],
545    /// The type of the result.
546    pub ret: u32,
547    /// True when the last argument is the array of a `VARIADIC` call.
548    pub variadic: bool,
549    /// The number of rows that the caller reads from a set kernel, or `None` for all the rows. A function of the target list stops after them, as a function in the value-per-call mode of PostgreSQL gives no more rows when the node above it stops.
550    pub want: Option<usize>,
551}
552
553impl std::fmt::Debug for Call<'_> {
554    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
555        f.debug_struct("Call")
556            .field("args", &self.args)
557            .field("ret", &self.ret)
558            .field("variadic", &self.variadic)
559            .field("want", &self.want)
560            .finish_non_exhaustive()
561    }
562}
563
564/// The code of a function. It gets the values of the arguments. A strict function does not get a null value, because the executor gives null without the call.
565pub type Kernel = fn(&Call<'_>, &[Value]) -> Result<Value>;
566
567/// The error of a type function as the session sends it.
568pub fn type_error(error: TypeError) -> Error {
569    let mut out = Error::new(error.sqlstate, error.message);
570    if let Some(detail) = error.detail {
571        out = out.with_detail(detail);
572    }
573    if let Some(hint) = error.hint {
574        out = out.with_hint(hint);
575    }
576    if let Some(context) = error.context {
577        out = out.with_context(context);
578    }
579    out
580}
581
582/// The error of a feature that the engine does not have yet.
583pub(crate) fn not_yet(what: impl std::fmt::Display) -> Error {
584    Error::new(SqlState::FEATURE_NOT_SUPPORTED, format!("{what} is not supported yet"))
585}
586
587/// The error of a value of a different kind than the type of the call gives, which is a bug of the engine.
588pub(crate) fn bad_value() -> Error {
589    Error::internal("a function got a value of the wrong kind")
590}
591
592/// The body of a function in SQL of the catalog of the session, as the analyzer reads it for a call with arguments of the types `inputs`, with `$1` as the first argument. `None` for a function that is not in the catalog of the session.
593///
594/// # Errors
595///
596/// The errors of the analysis of the body.
597pub fn function_body(
598    func: u32,
599    inputs: &[u32],
600    session: &dyn Session,
601) -> Result<Option<rupg_analyze::Body>> {
602    rupg_analyze::function_body(&reg::SessionEnv(session), func, inputs)
603}
604
605/// The kernel of the function with this `pg_proc` OID, or `None` if the engine does not have it.
606pub fn kernel(func: u32) -> Option<Kernel> {
607    let proc = builtin::proc_by_oid(func)?;
608    let user = proc.oid >= rupg_catalog::FIRST_NORMAL_OID;
609    if proc.lang == C_LANGUAGE && user {
610        return regress::by_symbol(proc.src);
611    }
612    if proc.lang != INTERNAL_LANGUAGE {
613        return misc::sql_function(func);
614    }
615    // A function in `internal` that a user makes runs the built-in function with the same `prosrc`.
616    if user {
617        let found =
618            builtin::procs().iter().find(|p| p.lang == INTERNAL_LANGUAGE && p.src == proc.src)?;
619        return kernel(found.oid);
620    }
621    if let Some(kernel) = by_src(proc.src).or_else(|| compare::by_src(proc.src, proc)) {
622        return Some(kernel);
623    }
624    // The functions of the types for input and output. An input function with a pseudo-type as its result, such as `array_in`, needs the type of the value from its arguments, which the engine does not have yet.
625    let pseudo = builtin::type_by_oid(proc.rettype).is_none_or(|row| row.kind == b'p');
626    for row in builtin::types() {
627        if row.send == func {
628            return Some(io::send_kernel);
629        }
630        if row.output == func {
631            return Some(io::output_kernel);
632        }
633        if row.input == func && !pseudo {
634            return Some(io::input_kernel);
635        }
636    }
637    let operator = operator_of(func)?;
638    let left = proc.argtypes.first().copied().unwrap_or(0);
639    let right = proc.argtypes.get(1).copied().unwrap_or(0);
640    if proc.argtypes.len() == 2 {
641        compare::by_operator(operator, left, right)
642            .or_else(|| math::by_operator(operator, left, right, proc.rettype))
643    } else {
644        math::by_prefix_operator(operator, left, proc.rettype)
645    }
646}
647
648/// The kernel of an internal function by its `prosrc`.
649fn by_src(src: &str) -> Option<Kernel> {
650    cast::by_src(src)
651        .or_else(|| agg::by_src(src))
652        .or_else(|| math::by_src(src))
653        .or_else(|| datetime::by_src(src))
654        .or_else(|| extract::by_src(src))
655        .or_else(|| formatting::by_src(src))
656        .or_else(|| numformat::by_src(src))
657        .or_else(|| dbsize::by_src(src))
658        .or_else(|| hash::by_src(src))
659        .or_else(|| inrange::by_src(src))
660        .or_else(|| timezone::by_src(src))
661        .or_else(|| calendar::by_src(src))
662        .or_else(|| random::by_src(src))
663        .or_else(|| trig::by_src(src))
664        .or_else(|| bytea::by_src(src))
665        .or_else(|| json::by_src(src))
666        .or_else(|| jsonedit::by_src(src))
667        .or_else(|| jsonbuild::by_src(src))
668        .or_else(|| jsonpath::by_src(src))
669        .or_else(|| text::by_src(src))
670        .or_else(|| unicode::by_src(src))
671        .or_else(|| misc::by_src(src))
672        .or_else(|| encoding::by_src(src))
673        .or_else(|| cash::by_src(src))
674        .or_else(|| mac::by_src(src))
675        .or_else(|| bit::by_src(src))
676        .or_else(|| binary::by_src(src))
677        .or_else(|| geo::by_src(src))
678        .or_else(|| lsn::by_src(src))
679        .or_else(|| snapshot::by_src(src))
680        .or_else(|| reg::by_src(src))
681        .or_else(|| catinfo::by_src(src))
682        .or_else(|| describe::by_src(src))
683        .or_else(|| identify::by_src(src))
684        .or_else(|| acl::by_src(src))
685        .or_else(|| updatable::by_src(src))
686        .or_else(|| amutils::by_src(src))
687        .or_else(|| deparse::by_src(src))
688        .or_else(|| stat::by_src(src))
689        .or_else(|| array::by_src(src))
690        .or_else(|| regex::by_src(src))
691        .or_else(|| network::by_src(src))
692        .or_else(|| range::by_src(src))
693        .or_else(|| multirange::by_src(src))
694        .or_else(|| tsvector::by_src(src))
695        .or_else(|| tsquery::by_src(src))
696        .or_else(|| tsearch::by_src(src))
697        .or_else(|| tsmatch::by_src(src))
698        .or_else(|| tsrank::by_src(src))
699        .or_else(|| tsrewrite::by_src(src))
700        .or_else(|| tsheadline::by_src(src))
701        .or_else(|| activity::by_src(src))
702        .or_else(|| replication::by_src(src))
703        .or_else(|| shared::by_src(src))
704        .or_else(|| advisory::by_src(src))
705        .or_else(|| sequence::by_src(src))
706        .or_else(|| enums::by_src(src))
707        .or_else(|| xml::by_src(src))
708}
709
710/// The name of the operator that the function implements, if it implements one.
711fn operator_of(func: u32) -> Option<&'static str> {
712    static OPERATORS: OnceLock<BTreeMap<u32, &'static str>> = OnceLock::new();
713    let map = OPERATORS
714        .get_or_init(|| builtin::operators().iter().map(|op| (op.code, op.name)).collect());
715    map.get(&func).copied()
716}
717
718#[cfg(test)]
719mod tests;