Returning multiple result sets from postgres: refcursors, functions or new features?












0















Premise:



An entity has many children and grandchildren (gists, versions and files respectively, in this instance). When it (gist) is requested, we want its children (versions) and grandchildren (files for versions) as well. Here I am really pushing to do as much in SQL as possible, instead of composing several queries together and munging them together in a scripting language. Can it be done? Does the tooling that supports sending queries to a PostgresQL db support the results returned?



Prior art:




  • PostgreSQL function returning multiple result sets

  • http://www.sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure

  • https://www.postgresql.org/docs/10/plpgsql-overview.html


Schema:



Schema (and SQL to insert mock data)



My attempt via stored function (Note, I have simplified to just parent/child return sets, skipping grandchild for now):



CREATE OR REPLACE FUNCTION get_gist_with_children(gist_ref refcursor, 

version_ref refcursor, gist_id_in UUID)
RETURNS SETOF refcursor AS $$
BEGIN
OPEN gist_ref FOR SELECT * from gist where gist_id = gist_id_in;
RETURN NEXT gist_ref;

OPEN version_ref FOR SELECT * from version where gist_id = gist_id_in;
RETURN NEXT version_ref;
END;
$$ LANGUAGE plpgsql;


The query to access that function:



BEGIN;

SELECT get_gist_with_children('gist_ref', 'version_ref', <replace with known UUID of gist record>);

FETCH ALL IN "gist_ref";
FETCH ALL IN "version_ref";
COMMIT;


returns in POSTICO
Postico, a PostgresQL GUI, just returns the refcursor symbol strings in two rows.
screenshot of Postico results



returns in psql
psql returns the first set of results and then... hangs?
screenshot of psql hanging



note: I can successfully query both tables on that gist_id and records returned in separate queries.



Are there new features of Postgres that could achieve this outcome? Is there a better way to use cursors to do so? Is the real problem that the tooling (psql, Postico) does not handle the returning of multiple data sets? Curious about ways forward beyond just falling back on composition via scripting languages.










share|improve this question



























    0















    Premise:



    An entity has many children and grandchildren (gists, versions and files respectively, in this instance). When it (gist) is requested, we want its children (versions) and grandchildren (files for versions) as well. Here I am really pushing to do as much in SQL as possible, instead of composing several queries together and munging them together in a scripting language. Can it be done? Does the tooling that supports sending queries to a PostgresQL db support the results returned?



    Prior art:




    • PostgreSQL function returning multiple result sets

    • http://www.sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure

    • https://www.postgresql.org/docs/10/plpgsql-overview.html


    Schema:



    Schema (and SQL to insert mock data)



    My attempt via stored function (Note, I have simplified to just parent/child return sets, skipping grandchild for now):



    CREATE OR REPLACE FUNCTION get_gist_with_children(gist_ref refcursor, 

    version_ref refcursor, gist_id_in UUID)
    RETURNS SETOF refcursor AS $$
    BEGIN
    OPEN gist_ref FOR SELECT * from gist where gist_id = gist_id_in;
    RETURN NEXT gist_ref;

    OPEN version_ref FOR SELECT * from version where gist_id = gist_id_in;
    RETURN NEXT version_ref;
    END;
    $$ LANGUAGE plpgsql;


    The query to access that function:



    BEGIN;

    SELECT get_gist_with_children('gist_ref', 'version_ref', <replace with known UUID of gist record>);

    FETCH ALL IN "gist_ref";
    FETCH ALL IN "version_ref";
    COMMIT;


    returns in POSTICO
    Postico, a PostgresQL GUI, just returns the refcursor symbol strings in two rows.
    screenshot of Postico results



    returns in psql
    psql returns the first set of results and then... hangs?
    screenshot of psql hanging



    note: I can successfully query both tables on that gist_id and records returned in separate queries.



    Are there new features of Postgres that could achieve this outcome? Is there a better way to use cursors to do so? Is the real problem that the tooling (psql, Postico) does not handle the returning of multiple data sets? Curious about ways forward beyond just falling back on composition via scripting languages.










    share|improve this question

























      0












      0








      0








      Premise:



      An entity has many children and grandchildren (gists, versions and files respectively, in this instance). When it (gist) is requested, we want its children (versions) and grandchildren (files for versions) as well. Here I am really pushing to do as much in SQL as possible, instead of composing several queries together and munging them together in a scripting language. Can it be done? Does the tooling that supports sending queries to a PostgresQL db support the results returned?



      Prior art:




      • PostgreSQL function returning multiple result sets

      • http://www.sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure

      • https://www.postgresql.org/docs/10/plpgsql-overview.html


      Schema:



      Schema (and SQL to insert mock data)



      My attempt via stored function (Note, I have simplified to just parent/child return sets, skipping grandchild for now):



      CREATE OR REPLACE FUNCTION get_gist_with_children(gist_ref refcursor, 

      version_ref refcursor, gist_id_in UUID)
      RETURNS SETOF refcursor AS $$
      BEGIN
      OPEN gist_ref FOR SELECT * from gist where gist_id = gist_id_in;
      RETURN NEXT gist_ref;

      OPEN version_ref FOR SELECT * from version where gist_id = gist_id_in;
      RETURN NEXT version_ref;
      END;
      $$ LANGUAGE plpgsql;


      The query to access that function:



      BEGIN;

      SELECT get_gist_with_children('gist_ref', 'version_ref', <replace with known UUID of gist record>);

      FETCH ALL IN "gist_ref";
      FETCH ALL IN "version_ref";
      COMMIT;


      returns in POSTICO
      Postico, a PostgresQL GUI, just returns the refcursor symbol strings in two rows.
      screenshot of Postico results



      returns in psql
      psql returns the first set of results and then... hangs?
      screenshot of psql hanging



      note: I can successfully query both tables on that gist_id and records returned in separate queries.



      Are there new features of Postgres that could achieve this outcome? Is there a better way to use cursors to do so? Is the real problem that the tooling (psql, Postico) does not handle the returning of multiple data sets? Curious about ways forward beyond just falling back on composition via scripting languages.










      share|improve this question














      Premise:



      An entity has many children and grandchildren (gists, versions and files respectively, in this instance). When it (gist) is requested, we want its children (versions) and grandchildren (files for versions) as well. Here I am really pushing to do as much in SQL as possible, instead of composing several queries together and munging them together in a scripting language. Can it be done? Does the tooling that supports sending queries to a PostgresQL db support the results returned?



      Prior art:




      • PostgreSQL function returning multiple result sets

      • http://www.sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure

      • https://www.postgresql.org/docs/10/plpgsql-overview.html


      Schema:



      Schema (and SQL to insert mock data)



      My attempt via stored function (Note, I have simplified to just parent/child return sets, skipping grandchild for now):



      CREATE OR REPLACE FUNCTION get_gist_with_children(gist_ref refcursor, 

      version_ref refcursor, gist_id_in UUID)
      RETURNS SETOF refcursor AS $$
      BEGIN
      OPEN gist_ref FOR SELECT * from gist where gist_id = gist_id_in;
      RETURN NEXT gist_ref;

      OPEN version_ref FOR SELECT * from version where gist_id = gist_id_in;
      RETURN NEXT version_ref;
      END;
      $$ LANGUAGE plpgsql;


      The query to access that function:



      BEGIN;

      SELECT get_gist_with_children('gist_ref', 'version_ref', <replace with known UUID of gist record>);

      FETCH ALL IN "gist_ref";
      FETCH ALL IN "version_ref";
      COMMIT;


      returns in POSTICO
      Postico, a PostgresQL GUI, just returns the refcursor symbol strings in two rows.
      screenshot of Postico results



      returns in psql
      psql returns the first set of results and then... hangs?
      screenshot of psql hanging



      note: I can successfully query both tables on that gist_id and records returned in separate queries.



      Are there new features of Postgres that could achieve this outcome? Is there a better way to use cursors to do so? Is the real problem that the tooling (psql, Postico) does not handle the returning of multiple data sets? Curious about ways forward beyond just falling back on composition via scripting languages.







      sql postgresql






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 22 '18 at 19:33









      Underwater_developerUnderwater_developer

      186111




      186111
























          1 Answer
          1






          active

          oldest

          votes


















          0














          The PostgreSQL database engine is perfectly capable of handling multiple open result sets per connections, even per call. It can keep multiple cursors that are returned from a single call using multiple "result set"s.



          Don't be afraid of using them. Just try multiple SELECTs inside your procedure and perform a SINGLE call. Then, it's easy to verify you can get read from all the result sets, even in parallel.



          If you asked this same question on MySQL, then answer would categorically a "No". MySQL is far more limited. But with PostgreSQL this is perfectly possible.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437137%2freturning-multiple-result-sets-from-postgres-refcursors-functions-or-new-featu%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            The PostgreSQL database engine is perfectly capable of handling multiple open result sets per connections, even per call. It can keep multiple cursors that are returned from a single call using multiple "result set"s.



            Don't be afraid of using them. Just try multiple SELECTs inside your procedure and perform a SINGLE call. Then, it's easy to verify you can get read from all the result sets, even in parallel.



            If you asked this same question on MySQL, then answer would categorically a "No". MySQL is far more limited. But with PostgreSQL this is perfectly possible.






            share|improve this answer




























              0














              The PostgreSQL database engine is perfectly capable of handling multiple open result sets per connections, even per call. It can keep multiple cursors that are returned from a single call using multiple "result set"s.



              Don't be afraid of using them. Just try multiple SELECTs inside your procedure and perform a SINGLE call. Then, it's easy to verify you can get read from all the result sets, even in parallel.



              If you asked this same question on MySQL, then answer would categorically a "No". MySQL is far more limited. But with PostgreSQL this is perfectly possible.






              share|improve this answer


























                0












                0








                0







                The PostgreSQL database engine is perfectly capable of handling multiple open result sets per connections, even per call. It can keep multiple cursors that are returned from a single call using multiple "result set"s.



                Don't be afraid of using them. Just try multiple SELECTs inside your procedure and perform a SINGLE call. Then, it's easy to verify you can get read from all the result sets, even in parallel.



                If you asked this same question on MySQL, then answer would categorically a "No". MySQL is far more limited. But with PostgreSQL this is perfectly possible.






                share|improve this answer













                The PostgreSQL database engine is perfectly capable of handling multiple open result sets per connections, even per call. It can keep multiple cursors that are returned from a single call using multiple "result set"s.



                Don't be afraid of using them. Just try multiple SELECTs inside your procedure and perform a SINGLE call. Then, it's easy to verify you can get read from all the result sets, even in parallel.



                If you asked this same question on MySQL, then answer would categorically a "No". MySQL is far more limited. But with PostgreSQL this is perfectly possible.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 28 '18 at 0:49









                The ImpalerThe Impaler

                10.5k41341




                10.5k41341
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437137%2freturning-multiple-result-sets-from-postgres-refcursors-functions-or-new-featu%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                    Alcedinidae

                    Origin of the phrase “under your belt”?