web-dev-qa-db-fra.com

Stockez une formule dans une table et utilisez la formule dans une fonction

J'ai une base de données PostgreSQL 9.1 où une partie de celle-ci gère les commissions de l'agent. Chaque agent a sa propre formule de calcul combien de commission qu'ils obtiennent. J'ai une fonction pour générer le montant de la commission que chaque agent devrait obtenir, mais il est impossible d'utiliser comme le nombre d'agents se développer. Je suis obligé de faire des déclarations de cas extrêmement longues et de la répétition de code, qui a rendu ma fonction très grande.

Toutes les formules ont des variables constantes:

[ . Taux de base 
 I .. revenus gagnés [.____]

La formule peut être quelque chose comme:

d*b+(l*4+r)+(i/d)+s

Chaque agent négocie la formule de paiement avec le département HR. Puis-je stocker la formule dans la table des agents, puis une petite fonction qui obtient simplement la formule de la table et le traduit par des valeurs et calcule le montant?

10
indago

Veuillez lire ceci attentivement en ce qui concerne les considérations de sécurité. Essentiellement, vous essayez d'injecter SQL arbitraire dans vos fonctions. En conséquence, vous devez avoir cette exécution sous un utilisateur avec des autorisations hautement restreintes.

  1. Créez un utilisateur et révoquer toutes les autorisations. Ne donnez pas d'autorisations au public dans le même dB que vous le faites.

  2. Créez une fonction pour évaluer l'expression, faites-la security definer et modifier le propriétaire à cet utilisateur restreint.

  3. Préprocéder l'expression puis transmettez-la à la fonction EVAL () que vous avez créée ci-dessus. Vous pouvez le faire dans une autre fonction si vous avez besoin de,

Notez à nouveau, cela a de graves implications de sécurité.

EDIT: Brève code d'échantillon (non testé mais devrait vous y arriver si vous suivez Docs):

CREATE OR REPLACE FUNCTION eval_numeric(text) returns numeric language plpgsql security definer immutable as
$$
declare retval numeric;
begin

execute $e$ SELECT ($1)::numeric$e$ into retval;
return retval;
end;
$$;

ALTER FUNCTION eval_numeric OWNER TO jailed_user;

CREATE OR REPLACE FUNCTION foo(expression text, a numeric, b numeric) returns numeric language sql immutable as $$
select eval(regexp_replace(regexp_replace($1, 'a', $2, 'g'), 'b', '$3', 'g'));
$$; -- can be security invoker, but eval needs to be jailed.
5
Chris Travers