sqlmariadbmariadb-10.5

function that waits until condition to return


I have barely any experience with proper SQL but I've been trying to write a database function that waits until a condition is met and then releases the thread so I can call that function whenever I want to wait until that condition is met. The condition tells me that a seperate service is not currently working on the data I want to access, but for development I created a useless entry that I just want to manually delete for testing.

Here is my code so far, but I can't get it to work. For development I tried just executing it in a DB manager like I would execute a SELECT statement:

SET @c = 1;
WHILE @c > 0 DO
    SELECT COUNT(*) INTO @c FROM pb_db_operational.application_parameter WHERE `key` = "waitingtest";

    IF @c > 0
        SELECT SLEEP(5);
    END IF;
END WHILE;

SELECT 'asdf' FROM accessory_complete_price_factor LIMIT 1

I also attempted to create a procedure since I wasn't able to use the DECLARE statement when running it outside of a stored procedure:

CREATE FUNCTION `WaitUntilDataReady`()
RETURNS TINYINT
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN

DECLARE v_count INTEGER DEFAULT 1

WHILE v_count > 0 DO
    set v_count = (SELECT COUNT(*) FROM pb_db_operational.application_parameter WHERE `key` = "waitingtest")

    IF v_count > 0
        SELECT SLEEP(5)
    END IF
END WHILE

RETURN 1;

END

I wasn't able to get either of my examples running, so I'm happy about each and any piece of info you can tell me, even if it's just basic syntax.

Thanks in advance :)


Solution

  • you should try a stored procedure, using the following example :

        DROP PROCEDURE IF EXISTS pb_db_operational.WaitUntilDataReady ;
        
        DELIMITER //
        CREATE PROCEDURE pb_db_operational.WaitUntilDataReady(
          IN p_db_name VARCHAR(100),
          IN p_tab_name VARCHAR(100),
          IN p_col_name VARCHAR(100),  
          IN p_key VARCHAR(255),
          INOUT p_return_value INT
        )
        SQL SECURITY DEFINER
        BEGIN
          SET @v_count := 1 ;
          SET @req_sql := CONCAT("SELECT COUNT(*) INTO @v_count FROM ", p_db_name, ".", p_tab_name, " WHERE ", p_col_name, " = '", p_key, "' ; ") ;
          WHILE @v_count > 0 DO
            EXECUTE IMMEDIATE @req_sql ;
            IF @v_count > 0 THEN
              SELECT SLEEP(5) ;
            END IF ;
          END WHILE ;
          SET p_return_value := 1 ;
        END//
        DELIMITER ;
        
        
        SET @a:=0 ;
        CALL pb_db_operational.WaitUntilDataReady('pb_db_operational', 'application_parameter', 'v_key', 'waiting_test', @a) ;
        SELECT @a ;
    

    Stored procedure allows to use dynamic SQL. As you can see above, it allows to call the procedure with parameters, changing the database name, table name and column name as needed.

    The procedure return value, will be stored in @a variable.

    Advice: avoid to use reserved words as object name (variable, database, table, column, etc.), such as "key"

    Hope this will help.