Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-33830

Support for cursors on prepared statements

    XMLWordPrintable

Details

    • Q4/2025 Server Development

    Description

      Currently prepared statements can only be executed and only a single row may be fetched. This is a severe limitation, in particular when it comes to stored procedures. This limits the support for Dynamic SQL we have and makes migration from, say, Oracle, real difficult. Oracle has support for cursors on Dynamic SQL.

      Standard SQL syntax

      Let's support the SQL standard syntax for <dynamic declare cursor>.

      The SQL Standard assumes that:

      • A cursor first is declared with the FOR clause, which binds the cursor to a prepared statement
      • Then the prepared statement gets prepared
      • Then the cursor is ready to be opened and fetched using the usual syntax:

        DECLARE cursor_name FOR prepared_statement_name;    -- <dynamic declare cursor>
        PREPARE prepared_statement_name FROM 'SELECT 1,2';  -- Placeholders are also possible
        OPEN cursor_name;                                   -- USING clause is also possible
      

      Example:

      CREATE OR REPLACE TABLE t1 (id INT, c1 VARCHAR(10));
      INSERT INTO t1 VALUES (10,'c10'),(11,'c11'),(12,'c12');
       
      DELIMITER $$
      CREATE OR REPLACE PROCEDURE p1(tab VARCHAR(64), id INTEGER)
      BEGIN
        DECLARE no_data BOOL DEFAULT FALSE;
        DECLARE v_c1 VARCHAR(100);
        DECLARE v_id INT;
        DECLARE c1 CURSOR FOR s1;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_data = TRUE;
       
        PREPARE s1 FROM CONCAT('SELECT id, c1 FROM ', tab, ' WHERE id >= ?');
        OPEN c1 USING id;
        fetch_loop: LOOP
          FETCH c1 INTO v_id, v_c1;
          IF no_data THEN
            LEAVE fetch_loop;
          END IF;
          SELECT v_id, v_c1;
        END LOOP;
        CLOSE c1;
      END;
      $$
      DELIMITER ;
      CALL p1('t1',11);
      

      ROW TYPE OF won't be supported:

      As the cursor structure is needed to be known at sp_rcontext creation time, ROW TYPE declarations won't be supported for dynamic cursors:

      CREATE OR REPLACE TABLE t1 (a INT);
      INSERT INTO t1 VALUES (1),(2),(3);
      DELIMITER $$
      CREATE OR REPLACE PROCEDURE p1()
      BEGIN
        DECLARE v TEXT;
        DECLARE c CURSOR FOR stmt;
        BEGIN
          DECLARE r ROW TYPE OF c; -- This is wrong
        END;
      END;
      $$
      DELIMITER ;
      CALL p1;
      

      Cursor FOR-loops won't be supported:

      CREATE OR REPLACE TABLE t1 (a INT);
      INSERT INTO t1 VALUES (1),(2),(3);
       
      DELIMITER $$
      CREATE OR REPLACE PROCEDURE p1()
      BEGIN
        DECLARE c1 CURSOR FOR stmt;
        PREPARE stmt FROM 'SELECT a FROM t1';
        FOR r IN c1
        DO
          INSERT INTO t2 VALUES(r.a);
        END FOR;
      END;
      $$
      DELIMITER ;
      CALL p1;
      

      SYS_REFCURSORs should be supported:

      CREATE OR REPLACE PROCEDURE p1(dynamic_sql VARCHAR) AS
        v1 INT;
        v2 VARCHAR(256);
        c SYS_REFCURSOR;
      BEGIN
        OPEN c FOR dynamic_sql;
        FETCH c INTO v1, v2;
        DBMS_OUTPUT.PUT_LINE(v1 || ' ' || v2);
        CLOSE c;
      END;
      /
      CALL p1('SELECT 123, ''v123'' FROM DUAL');
      

      123 v123
      

      Attachments

        Issue Links

          Activity

            People

              bar Alexander Barkov
              karlsson Anders Karlsson
              Votes:
              1 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.