tcdi / plrust

A Rust procedural language handler for PostgreSQL
PostgreSQL License
1.12k stars 32 forks source link

Call a function from another function #370

Open dineshsivaji opened 1 year ago

dineshsivaji commented 1 year ago

Hi,

I am just exploring on the feasibility of using multiple functions and calling from one another.

plrust=#     CREATE OR REPLACE FUNCTION plrust.strlen(val TEXT)
plrust-#     RETURNS BIGINT
plrust-#     LANGUAGE plrust STRICT
plrust-# AS $$
plrust$#     Ok(Some(val.len() as i64))
plrust$# $$;

CREATE FUNCTION
plrust=# 
plrust=# SELECT plrust.strlen('This is a random sentence');
 strlen 
--------
     25
(1 row)

plrust=# CREATE OR REPLACE FUNCTION plrust.strlen2(val TEXT)
plrust-#     RETURNS BIGINT
plrust-#     LANGUAGE plrust STRICT
plrust-# AS $$
plrust$#     Ok(Some(plrust.strlen(val)))
plrust$# $$;
ERROR:  
   0: `cargo build` failed

Location:
   /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/convert/mod.rs:727

`cargo build` stderr:
       Updating crates.io index
      Compiling plrust_fn_oid_16384_16428_3272765079552 v0.0.0 (/Users/dsivaji/plrust-scratch/plrust_fn_oid_16384_16428_3272765079552)
   error[E0425]: cannot find value `plrust` in this scope
     --> src/lib.rs:13:17
      |
   13 |         Ok(Some(plrust.strlen(val)))
      |                 ^^^^^^ not found in this scope

   error[E0425]: cannot find value `plrust` in this scope
     --> src/lib.rs:48:17
      |
   48 |         Ok(Some(plrust.strlen(val)))
      |                 ^^^^^^ not found in this scope

   For more information about this error, try `rustc --explain E0425`.
   error: could not compile `plrust_fn_oid_16384_16428_3272765079552` (lib) due to 2 previous errors

Source Code:
   #![deny(unsafe_op_in_unsafe_fn)]
   pub mod opened {
       #[allow(unused_imports)]
       use pgrx::prelude::*;
       #[allow(unused_lifetimes)]
       #[pg_extern]
       fn plrust_fn_oid_16384_16428<'a>(
           val: &'a str,
       ) -> ::std::result::Result<
           Option<i64>,
           Box<dyn std::error::Error + Send + Sync + 'static>,
       > {
           Ok(Some(plrust.strlen(val)))
       }
   }
   #[deny(unknown_lints)]
   mod forbidden {
       #![forbid(deprecated)]
       #![forbid(implied_bounds_entailment)]
       #![forbid(plrust_async)]
       #![forbid(plrust_autotrait_impls)]
       #![forbid(plrust_closure_trait_impl)]
       #![forbid(plrust_env_macros)]
       #![forbid(plrust_extern_blocks)]
       #![forbid(plrust_external_mod)]
       #![forbid(plrust_filesystem_macros)]
       #![forbid(plrust_fn_pointers)]
       #![forbid(plrust_leaky)]
       #![forbid(plrust_lifetime_parameterized_traits)]
       #![forbid(plrust_print_macros)]
       #![forbid(plrust_static_impls)]
       #![forbid(plrust_stdio)]
       #![forbid(plrust_suspicious_trait_object)]
       #![forbid(plrust_tuple_struct_self_pattern)]
       #![forbid(soft_unstable)]
       #![forbid(suspicious_auto_trait_impls)]
       #![forbid(unsafe_code)]
       #![forbid(where_clauses_object_safety)]
       #[allow(unused_imports)]
       use pgrx::prelude::*;
       #[allow(unused_lifetimes)]
       fn plrust_fn_oid_16384_16428<'a>(
           val: &'a str,
       ) -> ::std::result::Result<
           Option<i64>,
           Box<dyn std::error::Error + Send + Sync + 'static>,
       > {
           Ok(Some(plrust.strlen(val)))
       }
   }

Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
plrust=# 

I read that CREATE FUNCTION is compiled to rust function internally in the documentation. In that case, how can we call another function from inside a function ? How to expose functions to one another ?

eeeebbbbrrrr commented 1 year ago

Hi @dineshsivaji! PL/Rust doesn't support this yet. We have some loose plans around what this will look like, and intend to do it eventually. The implementation itself will largely be in pgrx. I'll leave this issue open as you're the first to publicly ask for it.

eeeebbbbrrrr commented 1 year ago

I should add that you can use Spi to call another function. The major downside there is incurring the Spi overhead. Depending on what the other function does, maybe that won't be too terrible.

dineshsivaji commented 1 year ago

Thanks, @eeeebbbbrrrr . I also thought of using SPI as an alternate. Hope this feature added in the near future.

decarbonise commented 1 year ago

Was just about to suggest this and saw that the issue is already open. It would be really useful for us too.

eeeebbbbrrrr commented 1 year ago

It's in-progress. Most of the work has to happen in pgrx, and I've got a proof-of-concept PR up already. Probably a couple more weeks of work.

decarbonise commented 1 year ago

Brilliant, thanks @eeeebbbbrrrr