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(®::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;