Search code examples
sqlpostgresqlhasura

Return boolean from Hasura PostgreSQL function


I have a subscription table and I want to add a field called is_subscription_active as a computed field on that table. I wrote a function to return a boolean from the PostgreSQL function after looking at some examples, but I can't seem to figure out the issue here.

CREATE OR REPLACE FUNCTION public.is_subscription_active(sub subscriptions)
 RETURNS BOOLEAN
 LANGUAGE sql
 STABLE
AS $function$
    IF (sub.subscription_status = 'active') THEN
        RETURN true;
    ELSE
        IF (sub.subscription_status != 'cancelled') THEN
            RETURN false;
        ELSE
            IF sub.ending_date > now() THEN
                RETURN true;
            ELSE
                RETURN false;
            END IF;
        END IF;
    END IF;
$function$

My logic here is that, I get sub (which will be a row of subscriptions table), and I just check if status is active then return true, else if it's cancelled, then check if the ending date is greater than now, and if it is return true, else false.

I get this error from Hasura.

{
    "statement": "CREATE OR REPLACE FUNCTION public.is_subscription_active(sub subscriptions)\n RETURNS BOOLEAN\n LANGUAGE sql\n STABLE\nAS $function$\n    IF (sub.subscription_status = 'active') THEN\n        RETURN true;\n    ELSE\n        IF (sub.subscription_status != 'canceled') THEN\n            RETURN false;\n        ELSE\n            IF sub.ending_date > now() THEN\n                RETURN true;\n            ELSE\n                RETURN false;\n            END IF;\n        END IF;\n    END IF;\n$function$;",
    "prepared": false,
    "error": {
        "exec_status": "FatalError",
        "hint": null,
        "message": "syntax error at or near \"IF\"",
        "status_code": "42601",
        "description": null
    },
    "arguments": []
}

I've also tried wrapping the function body in a BEGIN ... END block, but I still get the same error.

Clearly, I'm missing something fundamental here, but I can't figure out what


Solution

  • The main issue here is that you're specifying the function language is sql instead of plpgsql. plpgsql is a procedural language specific to postgres that actually allows you to work with procedural coding patterns like conditional statements and loops. These are not supported by regular sql.

    The following should work for you:

    CREATE OR REPLACE FUNCTION public.is_subscription_active(sub subscriptions)
     RETURNS BOOLEAN
     LANGUAGE plpgsql
     STABLE
    AS $function$
        BEGIN
            IF (sub.subscription_status = 'active') THEN
                RETURN true;
            ELSE
                IF (sub.subscription_status != 'cancelled') THEN
                    RETURN false;
                ELSE
                    IF sub.ending_date > now() THEN
                        RETURN true;
                    ELSE
                        RETURN false;
                    END IF;
                END IF;
            END IF;
        END;
    $function$