Thread: Need to understand PL/PGSQL, Foreign Key Deferable, and Transactions...

Need to understand PL/PGSQL, Foreign Key Deferable, and Transactions...

From
"D. Dante Lorenso"
Date:
I just wrote a PL/PGSQL function that is working, but I don't know
why it is...

I have a foreign key constraint defined on:

    transaction.invoice_id --> invoice.invoice_id

But I did NOT state that it was DEFERRABLE.  In this PL/PGSQL
function below, I update the transaction values and set them
to the invoice_id that does not yet exist in the invoice table.

I later add the invoice record, so technically at the end of the
PL/PGSQL function, the constraint is satisfied.  So, what's the
deal?  The foreign key checks are not done until AFTER the
function exits?  If this is true, should I rely on this to exist
into the future as well or do I need to design my function
differently?

//--------------------------------------------------
CREATE FUNCTION "public"."invoicer" (bigint) RETURNS bigint AS'
DECLARE
    in_acct_id ALIAS FOR $1;

    my_invoice_id BIGINT;
BEGIN
    /* Get a new invoice_id for the row we are going to insert */
    my_invoice_id := NEXTVAL(''invoice_invoice_id_seq'');

    /* Attach all active transactions that belong in this invoice */
    UPDATE transaction SET
        invoice_id = my_invoice_id
    WHERE invoice_id IS NULL
    AND trans_effective_ts < NOW();

    /* There are no transactions at this time */
    IF NOT FOUND THEN
        RAISE EXCEPTION ''No Transactions Exist to Invoice for %.'',
in_acct_id;
    END IF;

    /* Create a new Invoice */
    INSERT INTO invoice (invoice_id, acct_id)
    VALUES (my_invoice_id, in_acct_id);

    /* if that didn''t work, BAIL */
    IF NOT FOUND THEN
        RAISE EXCEPTION ''Could not create invoice.'';
    END IF;

    /* yeah, that worked */
    RETURN (my_invoice_id);
END;
'LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
//--------------------------------------------------

-- Dante



Re: Need to understand PL/PGSQL, Foreign Key Deferable,

From
Stephan Szabo
Date:
On Wed, 17 Dec 2003, D. Dante Lorenso wrote:

> I just wrote a PL/PGSQL function that is working, but I don't know
> why it is...
>
> I have a foreign key constraint defined on:
>
>     transaction.invoice_id --> invoice.invoice_id
>
> But I did NOT state that it was DEFERRABLE.  In this PL/PGSQL
> function below, I update the transaction values and set them
> to the invoice_id that does not yet exist in the invoice table.
>
> I later add the invoice record, so technically at the end of the
> PL/PGSQL function, the constraint is satisfied.  So, what's the
> deal?  The foreign key checks are not done until AFTER the
> function exits?  If this is true, should I rely on this to exist
> into the future as well or do I need to design my function
> differently?

Right now, this is true, because the triggers run at "outer" statement end
(ie the statement that called the function).  I wouldn't want to bet on
it possibly not changing in the future (the spec is difficult enough to
read on these issues that we may find out we're doing it wrong).