Préparer
Vos formules ressemblent à ceci:
d*b+(l*4+r)+(i/d)+s
Je remplacerais les variables par une $n
notation afin qu'elles puissent être remplacées par des valeurs directement dans plpgsql EXECUTE
(voir ci-dessous):
$1*$5+($3*4+$2)+($6/$1)+$4
Vous pouvez également stocker vos formules originales (pour l'œil humain) ou générer ce formulaire dynamiquement avec une expression comme:
SELECT regexp_replace(regexp_replace(regexp_replace(
regexp_replace(regexp_replace(regexp_replace(
'd*b+(l*4+r)+(i/d)+s'
, '\md\M', '$1', 'g')
, '\mr\M', '$2', 'g')
, '\ml\M', '$3', 'g')
, '\ms\M', '$4', 'g')
, '\mb\M', '$5', 'g')
, '\mi\M', '$6', 'g');
Assurez-vous simplement que votre traduction est bonne. Quelques explications pour les expressions regexp :
\ m .. ne correspond qu'au début d'un mot
\ M .. ne correspond qu'à la fin d'un mot
4ème paramètre 'g'
.. remplacer globalement
Fonction principale
CREATE OR REPLACE FUNCTION f_calc(
d int -- days worked that month
,r int -- new nodes accuired
,l int -- loyalty score
,s numeric -- subagent commission
,b numeric -- base rate
,i numeric -- revenue gained
,formula text
,OUT result numeric
) RETURNS numeric AS
$func$
BEGIN
EXECUTE 'SELECT '|| formula
INTO result
USING $1, $2, $3, $4, $5, $6;
END
$func$ LANGUAGE plpgsql SECURITY DEFINER IMMUTABLE;
Appel:
SELECT f_calc(1, 2, 3, 4.1, 5.2, 6.3, '$1*$5+($3*4+$2)+($6/$1)+$4');
Retour:
29.6000000000000000
Points majeurs
La fonction prend 6 paramètres de valeur et formula text
7e. J'ai mis la formule en dernier, afin que nous puissions utiliser à la $1 .. $6
place de $2 .. $7
. Juste pour des raisons de lisibilité.
J'ai attribué des types de données pour les valeurs comme bon me semblait. Attribuez les types appropriés (pour implémenter les contrôles de base de santé mentale) ou faites-les tous numeric
:
Passez des valeurs pour l'exécution dynamique avec la USING
clause. Cela évite de lancer dans les deux sens et rend tout plus simple, plus sûr et plus rapide.
J'utilise un OUT
paramètre parce qu'il est plus élégant et rend la syntaxe plus claire et plus courte. Une finale RETURN
n'est pas nécessaire, la valeur du ou des paramètres OUT est retournée automatiquement.
Considérez la conférence sur la sécurité par @Chris et le chapitre "Écrire des fonctions de DEFINER DE SECURITE en toute sécurité" dans le manuel. Dans ma conception, le point d'injection unique est la formule elle-même.
Vous pouvez utiliser des valeurs par défaut pour certains paramètres pour simplifier davantage l'appel.