pgx_pg_sys/submodules/
elog.rs

1/*
2Portions Copyright 2019-2021 ZomboDB, LLC.
3Portions Copyright 2021-2022 Technology Concepts & Design, Inc. <support@tcdi.com>
4
5All rights reserved.
6
7Use of this source code is governed by the MIT license that can be found in the LICENSE file.
8*/
9
10//! Access to Postgres' logging system
11
12/// Postgres' various logging levels
13#[allow(dead_code)]
14#[derive(Clone, Copy, Debug, Ord, PartialOrd, PartialEq, Eq)]
15pub enum PgLogLevel {
16    /// Debugging messages, in categories of decreasing detail
17    DEBUG5 = crate::DEBUG5 as isize,
18
19    /// Debugging messages, in categories of decreasing detail
20    DEBUG4 = crate::DEBUG4 as isize,
21
22    /// Debugging messages, in categories of decreasing detail
23    DEBUG3 = crate::DEBUG3 as isize,
24
25    /// Debugging messages, in categories of decreasing detail
26    DEBUG2 = crate::DEBUG2 as isize,
27
28    /// Debugging messages, in categories of decreasing detail
29    /// NOTE:  used by GUC debug_* variables
30    DEBUG1 = crate::DEBUG1 as isize,
31
32    /// Server operational messages; sent only to server log by default.
33    LOG = crate::LOG as isize,
34
35    /// Same as LOG for server reporting, but never sent to client.
36    #[allow(non_camel_case_types)]
37    LOG_SERVER_ONLY = crate::LOG_SERVER_ONLY as isize,
38
39    /// Messages specifically requested by user (eg VACUUM VERBOSE output); always sent to client
40    /// regardless of client_min_messages, but by default not sent to server log.
41    INFO = crate::INFO as isize,
42
43    /// Helpful messages to users about query operation; sent to client and not to server log by default.
44    NOTICE = crate::NOTICE as isize,
45
46    /// Warnings.  \[NOTICE\] is for expected messages like implicit sequence creation by SERIAL.
47    /// \[WARNING\] is for unexpected messages.
48    WARNING = crate::WARNING as isize,
49
50    /// user error - abort transaction; return to known state
51    ERROR = crate::ERROR as isize,
52
53    /// fatal error - abort process
54    FATAL = crate::FATAL as isize,
55
56    /// take down the other backends with me
57    PANIC = crate::PANIC as isize,
58}
59
60impl From<isize> for PgLogLevel {
61    #[inline]
62    fn from(i: isize) -> Self {
63        if i == PgLogLevel::DEBUG5 as isize {
64            PgLogLevel::DEBUG5
65        } else if i == PgLogLevel::DEBUG4 as isize {
66            PgLogLevel::DEBUG4
67        } else if i == PgLogLevel::DEBUG3 as isize {
68            PgLogLevel::DEBUG3
69        } else if i == PgLogLevel::DEBUG2 as isize {
70            PgLogLevel::DEBUG2
71        } else if i == PgLogLevel::DEBUG1 as isize {
72            PgLogLevel::DEBUG1
73        } else if i == PgLogLevel::INFO as isize {
74            PgLogLevel::INFO
75        } else if i == PgLogLevel::NOTICE as isize {
76            PgLogLevel::NOTICE
77        } else if i == PgLogLevel::WARNING as isize {
78            PgLogLevel::WARNING
79        } else if i == PgLogLevel::ERROR as isize {
80            PgLogLevel::ERROR
81        } else if i == PgLogLevel::FATAL as isize {
82            PgLogLevel::FATAL
83        } else if i == PgLogLevel::PANIC as isize {
84            PgLogLevel::PANIC
85        } else {
86            // ERROR seems like a good default
87            PgLogLevel::ERROR
88        }
89    }
90}
91
92impl From<i32> for PgLogLevel {
93    #[inline]
94    fn from(i: i32) -> Self {
95        (i as isize).into()
96    }
97}
98
99/// Log to Postgres' `debug5` log level.
100///
101/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
102/// See [`fmt`](std::fmt) for information about options.
103///
104/// The output these logs goes to the PostgreSQL log file at `DEBUG5` level, depending on how the
105/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
106#[macro_export]
107macro_rules! debug5 {
108    ($($arg:tt)*) => (
109        {
110            extern crate alloc;
111            $crate::ereport!($crate::elog::PgLogLevel::DEBUG5, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
112        }
113    )
114}
115
116/// Log to Postgres' `debug4` log level.
117///
118/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
119/// See [`fmt`](std::fmt) for information about options.
120///
121/// The output these logs goes to the PostgreSQL log file at `DEBUG4` level, depending on how the
122/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
123#[macro_export]
124macro_rules! debug4 {
125    ($($arg:tt)*) => (
126        {
127            extern crate alloc;
128            $crate::ereport!($crate::elog::PgLogLevel::DEBUG4, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
129        }
130    )
131}
132
133/// Log to Postgres' `debug3` log level.
134///
135/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
136/// See [`fmt`](std::fmt) for information about options.
137///
138/// The output these logs goes to the PostgreSQL log file at `DEBUG3` level, depending on how the
139/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
140#[macro_export]
141macro_rules! debug3 {
142    ($($arg:tt)*) => (
143        {
144            extern crate alloc;
145            $crate::ereport!($crate::elog::PgLogLevel::DEBUG3, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
146        }
147    )
148}
149
150/// Log to Postgres' `debug2` log level.
151///
152/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
153/// See [`fmt`](std::fmt) for information about options.
154///
155/// The output these logs goes to the PostgreSQL log file at `DEBUG2` level, depending on how the
156/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
157#[macro_export]
158macro_rules! debug2 {
159    ($($arg:tt)*) => (
160        {
161            extern crate alloc;
162            $crate::ereport!($crate::elog::PgLogLevel::DEBUG2, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
163        }
164    )
165}
166
167/// Log to Postgres' `debug1` log level.
168///
169/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
170/// See [`fmt`](std::fmt) for information about options.
171///
172/// The output these logs goes to the PostgreSQL log file at `DEBUG1` level, depending on how the
173/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
174#[macro_export]
175macro_rules! debug1 {
176    ($($arg:tt)*) => (
177        {
178            extern crate alloc;
179            $crate::ereport!($crate::elog::PgLogLevel::DEBUG1, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
180        }
181    )
182}
183
184/// Log to Postgres' `log` log level.
185///
186/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
187/// See [`fmt`](std::fmt) for information about options.
188///
189/// The output these logs goes to the PostgreSQL log file at `LOG` level, depending on how the
190/// [PostgreSQL settings](https://www.postgresql.org/docs/current/runtime-config-logging.html) are configured.
191#[macro_export]
192macro_rules! log {
193    ($($arg:tt)*) => (
194        {
195            extern crate alloc;
196            $crate::ereport!($crate::elog::PgLogLevel::LOG, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
197        }
198    )
199}
200
201/// Log to Postgres' `info` log level.
202///
203/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
204/// See [`fmt`](std::fmt) for information about options.
205#[macro_export]
206macro_rules! info {
207    ($($arg:tt)*) => (
208        {
209            extern crate alloc;
210            $crate::ereport!($crate::elog::PgLogLevel::INFO, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
211        }
212    )
213}
214
215/// Log to Postgres' `notice` log level.
216///
217/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
218/// See [`fmt`](std::fmt) for information about options.
219#[macro_export]
220macro_rules! notice {
221    ($($arg:tt)*) => (
222        {
223            extern crate alloc;
224            $crate::ereport!($crate::elog::PgLogLevel::NOTICE, $crate::errcodes::PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, alloc::format!($($arg)*).as_str());
225        }
226    )
227}
228
229/// Log to Postgres' `warning` log level.
230///
231/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
232/// See [`fmt`](std::fmt) for information about options.
233#[macro_export]
234macro_rules! warning {
235    ($($arg:tt)*) => (
236        {
237            extern crate alloc;
238            $crate::ereport!($crate::elog::PgLogLevel::WARNING, $crate::errcodes::PgSqlErrorCode::ERRCODE_WARNING, alloc::format!($($arg)*).as_str());
239        }
240    )
241}
242
243/// Log to Postgres' `error` log level.  This will abort the current Postgres transaction.
244///
245/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
246/// See [`fmt`](std::fmt) for information about options.
247#[macro_export]
248macro_rules! error {
249    ($($arg:tt)*) => (
250        {
251            extern crate alloc;
252            $crate::ereport!($crate::elog::PgLogLevel::ERROR, $crate::errcodes::PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, alloc::format!($($arg)*).as_str());
253            unreachable!()
254        }
255    );
256}
257
258/// Log to Postgres' `fatal` log level.  This will abort the current Postgres backend connection process.
259///
260/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
261/// See [`fmt`](std::fmt) for information about options.
262#[allow(non_snake_case)]
263#[macro_export]
264macro_rules! FATAL {
265    ($($arg:tt)*) => (
266        {
267            extern crate alloc;
268            $crate::ereport!($crate::elog::PgLogLevel::FATAL, $crate::errcodes::PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, alloc::format!($($arg)*).as_str());
269            unreachable!()
270        }
271    )
272}
273
274/// Log to Postgres' `panic` log level.  This will cause the entire Postgres cluster to crash.
275///
276/// This macro accepts arguments like the [`println`](std::println) and [`format`](std::format) macros.
277/// See [`fmt`](std::fmt) for information about options.
278#[allow(non_snake_case)]
279#[macro_export]
280macro_rules! PANIC {
281    ($($arg:tt)*) => (
282        {
283            extern crate alloc;
284            $crate::ereport!($crate::elog::PgLogLevel::PANIC, $crate::errcodes::PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, alloc::format!($($arg)*).as_str());
285            unreachable!()
286        }
287    )
288}
289
290// shamelessly borrowed from https://docs.rs/stdext/0.2.1/src/stdext/macros.rs.html#61-72
291/// This macro returns the name of the enclosing function.
292/// As the internal implementation is based on the [`std::any::type_name`], this macro derives
293/// all the limitations of this function.
294///
295/// [`std::any::type_name`]: https://doc.rust-lang.org/std/any/fn.type_name.html
296#[macro_export]
297macro_rules! function_name {
298    () => {{
299        // Okay, this is ugly, I get it. However, this is the best we can get on a stable rust.
300        fn f() {}
301        fn type_name_of<T>(_: T) -> &'static str {
302            core::any::type_name::<T>()
303        }
304        let name = type_name_of(f);
305        // `3` is the length of the `::f`.
306        &name[..name.len() - 3]
307    }};
308}
309
310/// Sends some kind of message to Postgres, and if it's a [PgLogLevel::ERROR] or greater, Postgres'
311/// error handling takes over and, in the case of [PgLogLevel::ERROR], aborts the current transaction.
312///
313/// This macro is necessary when one needs to supply a specific SQL error code as part of their
314/// error message.
315///
316/// The argument order is:
317/// - `log_level: [PgLogLevel]`
318/// - `error_code: [PgSqlErrorCode]`
319/// - `message: String`
320/// - (optional) `detail: String`
321///
322/// ## Examples
323///
324/// ```rust,no_run
325/// # use pgx_pg_sys::ereport;
326/// # use pgx_pg_sys::elog::PgLogLevel;
327/// # use pgx_pg_sys::errcodes::PgSqlErrorCode;
328/// ereport!(PgLogLevel::ERROR, PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, "oh noes!"); // abort the transaction
329/// ```
330///
331/// ```rust,no_run
332/// # use pgx_pg_sys::ereport;
333/// # use pgx_pg_sys::elog::PgLogLevel;
334/// # use pgx_pg_sys::errcodes::PgSqlErrorCode;
335/// ereport!(PgLogLevel::LOG, PgSqlErrorCode::ERRCODE_SUCCESSFUL_COMPLETION, "this is just a message"); // log output only
336/// ```
337#[macro_export]
338macro_rules! ereport {
339    (ERROR, $errcode:expr, $message:expr) => {
340        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
341            .report($crate::elog::PgLogLevel::ERROR);
342        unreachable!();
343    };
344
345    (PANIC, $errcode:expr, $message:expr) => {
346        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
347            .report($crate::elog::PgLogLevel::PANIC);
348        unreachable!();
349    };
350
351    (FATAL, $errcode:expr, $message:expr) => {
352        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
353            .report($crate::elog::PgLogLevel::FATAL);
354        unreachable!();
355    };
356
357    (WARNING, $errcode:expr, $message:expr) => {
358        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
359            .report($crate::elog::PgLogLevel::WARNING)
360    };
361
362    (NOTICE, $errcode:expr, $message:expr) => {
363        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
364            .report($crate::elog::PgLogLevel::NOTICE)
365    };
366
367    (INFO, $errcode:expr, $message:expr) => {
368        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
369            .report($crate::elog::PgLogLevel::INFO)
370    };
371
372    (LOG, $errcode:expr, $message:expr) => {
373        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
374            .report($crate::elog::PgLogLevel::LOG)
375    };
376
377    (DEBUG5, $errcode:expr, $message:expr) => {
378        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
379            .report($crate::elog::PgLogLevel::DEBUG5)
380    };
381
382    (DEBUG4, $errcode:expr, $message:expr) => {
383        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
384            .report($crate::elog::PgLogLevel::DEBUG4)
385    };
386
387    (DEBUG3, $errcode:expr, $message:expr) => {
388        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
389            .report($crate::elog::PgLogLevel::DEBUG3)
390    };
391
392    (DEBUG2, $errcode:expr, $message:expr) => {
393        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
394            .report($crate::elog::PgLogLevel::DEBUG2)
395    };
396
397    (DEBUG1, $errcode:expr, $message:expr) => {
398        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
399            .report($crate::elog::PgLogLevel::DEBUG1)
400    };
401
402    ($loglevel:expr, $errcode:expr, $message:expr) => {
403        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
404            .report($loglevel);
405    };
406
407    ($loglevel:expr, $errcode:expr, $message:expr, $detail:expr) => {
408        $crate::panic::ErrorReport::new($errcode, $message, $crate::function_name!())
409            .set_detail($detail)
410            .report($loglevel);
411    };
412}
413
414/// Is an interrupt pending?
415#[inline]
416pub fn interrupt_pending() -> bool {
417    #[cfg(any(feature = "pg11"))]
418    unsafe {
419        crate::InterruptPending
420    }
421
422    #[cfg(any(feature = "pg12", feature = "pg13", feature = "pg14", feature = "pg15"))]
423    unsafe {
424        crate::InterruptPending != 0
425    }
426}
427
428/// If an interrupt is pending (perhaps a user-initiated "cancel query" message to this backend),
429/// this will safely abort the current transaction
430#[macro_export]
431macro_rules! check_for_interrupts {
432    () => {
433        #[cfg(any(feature = "pg11"))]
434        #[allow(unused_unsafe)]
435        unsafe {
436            if $crate::InterruptPending {
437                $crate::ProcessInterrupts();
438            }
439        }
440
441        #[cfg(any(feature = "pg12", feature = "pg13", feature = "pg14", feature = "pg15"))]
442        #[allow(unused_unsafe)]
443        unsafe {
444            if $crate::InterruptPending != 0 {
445                $crate::ProcessInterrupts();
446            }
447        }
448    };
449}