GithubHelp home page GithubHelp logo

Comments (6)

anth0nyleung avatar anth0nyleung commented on August 22, 2024

Not sure if PGX has api to access TopTransactionId. But one way that i can think of to address this is to track the mtime of the source code / .so file in the in-memory map. On function execution, compare the in memory mtime of the function with the actual mtime of the source code / .so file. If the user function has been modified, the it should reload the function from the .so file.

from plrust.

workingjubilee avatar workingjubilee commented on August 22, 2024

PGX can add the relevant header if necessary.

from plrust.

workingjubilee avatar workingjubilee commented on August 22, 2024

I feel apprehensive about CREATE OR REPLACE FUNCTION in general, honestly. In the concurrent function creation case, with two sessions connected to Postgres, isn't this always a form of race condition?

We can create a coherent model for when to build, load, rebuild, and discard symbols, and use various tricks like symbol generations to make sure we're always using the correct symbol... but I don't think "two sessions open a transaction and try to commit creating the same function, and the second one will clobber the first, because even though they both think they are creating the same function, one will actually be OR REPLACE" is a situation where working around that with more and more epicycles is going to get us anywhere useful, as we then have to account for ROLLBACK as well. Postgres avoids trying to unload symbols because dlclose is somewhat incoherent to begin with, and probably is for Rust's std as well, and security advisories have been issued against CREATE OR REPLACE FUNCTION.

PGX allows it in user code, but that's with the admonishment that CREATE OR REPLACE FUNCTION is a dubious choice... but it's different when you're loading an entire extension, instead of building up the user code in the language, function by function.

from plrust.

anth0nyleung avatar anth0nyleung commented on August 22, 2024

I think the issue does not necessary applies to two racing CREATE OR REPLACE. It could be some situation where one session performs a CREATE OR REPLACE and the function is up-to-date on this session. But on the other sessions the function is now stale.

# On Session1
postgres=> SELECT foo(1);
 foo
-----
   1
(1 row)

# On Session2
postgres=> SELECT foo(1);
 foo
-----
   1
(1 row)

# Update the function on Session1, the function is up-to-date
postgres=> CREATE OR REPLACE FUNCTION foo(i int) RETURNS INT AS
postgres-> $$
postgres$> Some(i.unwrap() + 1)
postgres$> $$ LANGUAGE plrust;
NOTICE:  INFO plrust::plrust: unloaded function
    at src/plrust.rs:40

CREATE FUNCTION
postgres=> SELECT foo (1);
 foo
-----
   2
(1 row)

# However in Session2, the function is stale
postgres=> SELECT foo(1);
 foo
-----
   1
(1 row)

For plpgsql, this is handled properly

# Session1
postgres=# SELECT test_plpgsql(1);
 test_plpgsql
--------------
            1
(1 row)

# Session2
postgres=# SELECT test_plpgsql(1);
 test_plpgsql
--------------
            1
(1 row)

# Update the function on Session1
postgres=# CREATE OR REPLACE FUNCTION test_plpgsql(i int)
  RETURNS int AS
$$
BEGIN
  RETURN i + 1;
END
$$ LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# SELECT test_plpgsql(1);
 test_plpgsql
--------------
            2
(1 row)

# On Session2
postgres=# SELECT test_plpgsql(1);
 test_plpgsql
--------------
            2
(1 row)

from plrust.

workingjubilee avatar workingjubilee commented on August 22, 2024

I know that part, I'm just annoyed because of the other implications.

e.g. whatever we use to approach this has to do something to avoid rebuilding and replacing the function and opening new sharedlibs with new symbols constantly or else it becomes distressingly plausible to just repeatedly issue CREATE OR REPLACE FUNCTION until the machine runs out of hard drive space and memory. But this becomes comparatively easier if we always know whether we're creating instance "generation 0" for a function or advancing the generation by 1.

from plrust.

eeeebbbbrrrr avatar eeeebbbbrrrr commented on August 22, 2024

This has been fixed. We now track the xmin of the row from pg_catalog.pg_proc. And if that's different than what we previously loaded we then (attempt to) unload the function and reload the new version.

from plrust.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.