Добавить поле в функцию RETURNS TABLE pgplsql - PullRequest
0 голосов
/ 28 февраля 2019

Как добавить поле в RETURNS TABLE функции plpgpsql, значение, которое я хочу добавить, отсутствует в SELECT, выполняемом внутри функции:

У меня есть эта функция, которая выбирает сумму процессораи оперативная память, используемая заданиями каждые «шаги» секунды между start_date и end_date (отметка времени эпохи):

CREATE OR REPLACE FUNCTION resources(start_date INTEGER, end_date INTEGER, step INTEGER) 
RETURNS TABLE (
    cpu bigint
  , ram bigint)  AS $$
DECLARE
   counter INTEGER := 0 ;
BEGIN
  counter := start_date;
  LOOP 
    EXIT WHEN counter > end_date ;
RETURN QUERY EXECUTE
    'SELECT sum(j_ram) as ram, sum(j_cpu) as cpu from jobs where j_start_time <= ' || counter || ' and j_end_time >= ' || counter;
    counter := counter + step ; 
  END LOOP ; 

END;
$$ LANGUAGE plpgsql;    

Полученные результаты выглядят примерно так:

 cpu   |  ram 
-------+------
     0 |      
     6 | 12000
     6 | 11000
     1 | 1000

Как добавить значениепеременная 'counter' в таблице должна иметь что-то вроде:

 cpu   |  ram  | counter 
-------+-------+--------
     0 |       |     100        
     6 | 12000 |     110      
     6 | 11000 |     120       
     1 |  1000 |     130      

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

На самом деле вам не нужно EXECUTE для вашего случая, так как нет динамического параметра, такого как имя таблицы, имя столбца и т. Д. Изменяется только значение, переданное предложению where.Счетчик может быть частью select.

CREATE OR REPLACE FUNCTION resources(start_date INTEGER, end_date INTEGER, 
step INTEGER) 
RETURNS TABLE (
    cpu bigint
  , ram bigint
  , counter int)  AS $$
DECLARE
   counter INTEGER := 0 ;
BEGIN
  counter := start_date;
  LOOP 
    EXIT WHEN counter > end_date ;
RETURN QUERY 
    SELECT sum(j_ram)::bigint as ram, sum(j_cpu)::bigint as cpu,
           counter from jobs 
        where j_start_time <= counter
    and  j_end_time >= counter;
    counter := counter + step ; 
  END LOOP ; 
END;
$$ LANGUAGE plpgsql;    

Я бы порекомендовал вам избегать циклов, достаточно было бы использовать один запрос, использующий generate_series. Тогда эта функция может быть простой функцией SQL если у вас нет ничего другого, кроме как вернуть только результат запроса.

CREATE OR REPLACE FUNCTION resources2(start_date INTEGER, end_date INTEGER, 
step INTEGER) 
RETURNS TABLE (
    cpu bigint
  , ram bigint
  , counter int)  AS $$
   SELECT sum(j_ram) :: BIGINT AS ram, 
         sum(j_cpu) :: BIGINT AS cpu, 
       g.counter 
    FROM   jobs j 
       JOIN (SELECT generate_series(start_date, end_date, step) AS counter) g 
         ON j_start_time <= g.counter 
            AND j_end_time >= g.counter 
   GROUP  BY g.counter 
    ORDER  BY g.counter; 
$$ LANGUAGE sql;   

Демо

0 голосов
/ 28 февраля 2019

Здесь нет необходимости в динамическом SQL.И если вы пропустите это, вы можете просто добавить переменную в select:

CREATE OR REPLACE FUNCTION resources(start_date INTEGER, end_date INTEGER, step INTEGER) 
  RETURNS TABLE (
      cpu bigint
    , ram bigint 
    , counter bigint)  
AS $$

DECLARE
   counter INTEGER := 0;
BEGIN
  counter := start_date;
  LOOP 
    EXIT WHEN counter > end_date;

    RETURN QUERY 
      SELECT sum(j_ram) as ram, sum(j_cpu) as cpu, counter 
      from jobs 
      where j_start_time <= counter 
        and j_end_time >= counter;

    counter := counter + step; 
  END LOOP; 

END;
$$ LANGUAGE plpgsql;   
...