Улучшить агрегатную функцию в PL / pgSQL - PullRequest
0 голосов
/ 23 апреля 2019

Я попытался создать агрегатную функцию, которая находит минимальное значение в столбце, затем добавляет шум Лапласа. Я использую язык Postregres PL / pgSQL.

Агрегат работает отлично , но Я хотел бы знать, есть ли способ улучшить код , который я написал.

/*
 * PLpgSQL function which behaves to aggregate the MIN(col) function then adds the laplacian noise.
 * For the sensivity (which is the upper bound of the query), We use the  halfed maximum value of the column called.
 * Passing the array which contains the entire column values, that will be compared, to establish which one is the minimum.
 * Then we compute Laplacian distribution (sensivity/epsilon). This given value is added to the minimum Value that will disturb
 * the final result
 */
CREATE OR REPLACE FUNCTION addLaplacianNoiseMin (real[]) RETURNS real AS $$
DECLARE 
   i real;
   minVal real; --minimum value which is found in the column and then disturbed
   laplaceNoise real; --laplacian distribution which is computed finding the halfed maximum value, divided by an arbitrary epsilon (small value)
   epsilon real := 1.2;
   sensivity real; --our computed upper bound
   maxVal real;
BEGIN
   minVal := $1[1];
   maxVal := $1[1];
   IF ARRAY_LENGTH($1,1) > 0 THEN --Checking whether the array is empty or not
      <<confrontoMinimo>>
      FOREACH i IN ARRAY $1 LOOP --Looping through the entire array, passed as parameter
         IF minVal >= i THEN
            minVal := i;
         ELSE
            maxVal := i;
         END IF;
      END LOOP confrontoMinimo;
   ELSE
      RAISE NOTICE 'Invalid parameter % passed to the aggregate function',$1;
      --Raising exception if the parameter passed as argument points to null.
      RAISE EXCEPTION 'Cannot find MIN value. Parameter % is null', $1
         USING HINT = 'You cannot pass a null array! Check the passed parameter';
   END IF;

   sensivity := maxVal/2;
   laplaceNoise := sensivity/(epsilon);

   RAISE NOTICE 'minVal: %, maxVal: %, sensivity: %, laplaceNoise: %', minVal, maxVal, sensivity,laplaceNoise;

   minVal := laplaceNoise + minVal;
   RETURN minVal;
END;
$$ LANGUAGE plpgsql;

CREATE AGGREGATE searchMinValueArray (real)
(
   sfunc = array_append,
   stype = real[],
   finalfunc = addLaplacianNoiseMin,
   initCond = '{}'
);

1 Ответ

1 голос
/ 23 апреля 2019

Да, вы можете улучшить это, не используя массив в качестве состояния для агрегата, а составной тип, такой как:

CREATE TYPE aggstate AS (minval real, maxval real);

Затем вы можете выполнить операцию из цикла в SFUNC, и вам не нужно будет хранить массив в памяти, который может стать очень большим. FINALFUNC станет очень простым.

...