J'ai le cas suivant d'utiliser la vue PostgreSQL. Je dois calculer dynamiquement la valeur de la colonne de vue en fonction de la valeur d'une autre colonne de vue calculée dynamiquement. Voici la version simplifiée du code:Éviter la récursion infinie lors du calcul de la valeur de la colonne de vue de base de données en fonction d'une autre colonne de vue
BEGIN;
CREATE TABLE test
(
id serial PRIMARY KEY,
value integer NOT NULL
);
INSERT INTO test VALUES
(1, 13),
(2, 42);
CREATE FUNCTION inc(value integer)
RETURNS integer AS
$BODY$
BEGIN
RETURN value + 1;
END;
$BODY$
LANGUAGE plpgsql;
CREATE FUNCTION double(id integer)
RETURNS integer AS
$BODY$
DECLARE
local_value integer;
BEGIN
SELECT value_1 INTO local_value
FROM test_view WHERE double.id = test_view.id;
RETURN 2 * local_value;
END;
$BODY$
LANGUAGE plpgsql;
CREATE VIEW test_view AS
SELECT *,
inc(test.value) AS value_1,
double(test.id) AS value_2
FROM test;
COMMIT;
Mais ce code tombe dans une récursion infinie en raison de la déclaration suivante dans la deuxième fonction.
SELECT value_1 INTO local_value
FROM test_view WHERE double.id = test_view.id;
L'erreur exacte est la suivante:
ERROR: stack depth limit exceeded
HINT: Increase the configuration parameter "max_stack_depth
(currently 2048kB), after ensuring the platform's stack depth limit is adequate.
CONTEXT: PL/pgSQL function inc(integer) line 3 at RETURN
SQL statement "SELECT value_1 FROM test_view WHERE double.id = test_view.id"
PL/pgSQL function double(integer) line 5 at SQL statement
Le problème peut être facilement résolu en utilisant la deuxième vue. Par exemple:
CREATE FUNCTION double(value integer)
RETURNS integer AS
$BODY$
BEGIN
RETURN 2 * value;
END;
$BODY$
LANGUAGE plpgsql;
CREATE VIEW test_view_1 AS
SELECT *,
inc(test.value) AS value_1
FROM test;
CREATE VIEW test_view_2 AS
SELECT *,
double(test_view_1.value_1) AS value_2
FROM test_view_1;
Mais je n'aime pas cette approche car elle nécessite la création d'une deuxième vue. Il n'échelle pas dans le cas où j'ai n différentes valeurs dépendant chacune de la précédente. Ensuite, je dois avoir n différentes vues.
Est-il possible de résoudre le problème avec une seule vue?