Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите с функцией / 17 сообщений из 17, страница 1 из 1
04.01.2016, 23:31
    #39142181
Perederiy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
CREATE OR REPLACE FUNCTION get_min_max_rate_for_code_deck(
    character varying,
    integer,
    integer,
    timestamp with time zone)
  RETURNS SETOF record AS
$BODY$
declare
	code_deckslp alias for $1;
	rate_table_idslp alias for $2;
	rate_typeslp alias for $3;
	dateslp alias for $4;
	r record;
begin

for r in
		select codename,minrate,maxrate from (
select  code.name as codename,min(rate.rate) OVER (PARTITION BY code.name) as minrate,max(rate.rate) OVER (PARTITION BY code.name) as maxrate from code
 inner join code_deck
  on code.code_deck_id=code_deck.code_deck_id
  inner join rate_table
   on rate_table.code_deck_id=code_deck.code_deck_id
    inner join rate
      on rate.rate_table_id=rate_table.rate_table_id
  where code_deck.name=code_deckslp and rate_table.rate_type=rate_typeslp and rate_table.rate_table_id=rate_table_idslp and rate.effective_date=dateslp) foo 
  group by codename,minrate,maxrate
  
		loop
			return next r;
		end loop;


end;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION get_min_max_rate_for_code_deck(character varying, integer, integer, timestamp with time zone)
  OWNER TO postgres;



select get_min_max_rate_for_code_deck('A_Z',1619,0,'2014-08-09'::date)


ERROR: set-valued function called in context that cannot accept a set
CONTEXT: PL/pgSQL function get_min_max_rate_for_code_deck(character varying,integer,integer,timestamp with time zone) line 23 at RETURN NEXT
********** Ошибка **********

ERROR: set-valued function called in context that cannot accept a set
SQL-состояние: 0A000
Контекст: PL/pgSQL function get_min_max_rate_for_code_deck(character varying,integer,integer,timestamp with time zone) line 23 at RETURN NEXT
...
Рейтинг: 0 / 0
08.01.2016, 11:52
    #39143285
Perederiy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
ап
...
Рейтинг: 0 / 0
08.01.2016, 12:10
    #39143292
vyegorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
Perederiy,

Как функцию вызываете?
...
Рейтинг: 0 / 0
08.01.2016, 13:50
    #39143345
Lonepsycho
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
Perederiy,

select * FROM get_min_max_rate_for_code_deck('A_Z',1619,0,'2014-08-09'::date)

не вникал. пишу что бросилось в глаза...
...
Рейтинг: 0 / 0
17.02.2016, 17:18
    #39173392
Valentine_vaia
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
По документации, RETURN NEXT r; не заменяет RETURN - выход их функции.
после end loop; можно добавить return;
...
Рейтинг: 0 / 0
17.02.2016, 17:59
    #39173454
big-trot
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
Perederiy,

Кроме отсутствия RETURN в функции, еще и её вызов не правильный.
Для функций, которые возвращают SET необходимо указывать сигнатуру вывода.
...
Рейтинг: 0 / 0
17.02.2016, 19:35
    #39173540
vyegorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
big-trotДля функций, которые возвращают SET необходимо указывать сигнатуру вывода.
Не все SRF, а SETOF record, как в данном случае.
Если функция возвращает таблицу, при этом также являясь SRF, то сигнатура вывода не требуется.
...
Рейтинг: 0 / 0
17.02.2016, 19:38
    #39173541
big-trot
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
vyegorovНе все SRF, а SETOF record, как в данном случае.
Если функция возвращает таблицу, при этом также являясь SRF, то сигнатура вывода не требуется.
Конечно речь идет о рекорд
...
Рейтинг: 0 / 0
17.02.2016, 21:21
    #39173583
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
vyegorovbig-trotДля функций, которые возвращают SET необходимо указывать сигнатуру вывода.
Не все SRF, а SETOF record, как в данном случае.
Если функция возвращает таблицу, при этом также являясь SRF, то сигнатура вывода не требуется.
в принципе, она ещё не требуется при той форме вызова, которую поюзал ТС

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
BEGIN;
CREATE OR REPLACE FUNCTION assa()
  RETURNS SETOF RECORD AS
$BODY$

	SELECT ROW (1,'assa' )
	UNION ALL SELECT  (2,'assa','assa' )
	UNION ALL SELECT  ROW (3,'assa','assa','assa');
$BODY$
  LANGUAGE sql IMMUTABLE
  COST 10
  ROWS 10;

SELECT assa();
------------------------------------
'(1,assa)'
'(2,assa,assa)'
'(3,assa,assa,assa)'



но вот из под plpgsql что--то у меня этот трюк не работает как и у ТС

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
BEGIN;
CREATE OR REPLACE FUNCTION assa2()
  RETURNS SETOF RECORD AS
$BODY$
BEGIN
	/*
	return NEXT (ROW (1,'assa' ));
	return NEXT (ROW (2,'assa','assa' ));
	return NEXT (ROW (3,'assa','assa','assa'));
	*/
	RETURN QUERY 
		SELECT ROW (1,'assa' )
		UNION ALL SELECT  (2,'assa','assa' )
		UNION ALL SELECT  ROW (3,'assa','assa','assa');
	RETURN;
END
$BODY$
  LANGUAGE plpgsql IMMUTABLE
  COST 10
  ROWS 10;

SELECT assa2();
--------------------------------------
ERROR: set-valued function called in context that cannot accept a set
SQL-состояние: 0A000
Контекст: PL/pgSQL function assa2() line 8 at RETURN QUERY




откуда какбе мораль -- то ли я забыл, как это делать именно с plpgsql (что возможно, но маловероятно). либо "что--то пошло не так"

пока всё говорит за то, что д'артаньян тут стоит весь в белом [, красивая вся] с нашей с ТС стороны. думаецца.
...
Рейтинг: 0 / 0
17.02.2016, 21:26
    #39173585
vyegorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
qwwqно вот из под plpgsql что--то у меня этот трюк не работает как и у ТС
Возможно из-за того, что оптимизатор понимает SQL функции (подсматривает, ага), а PL/pgSQL для него — черный ящик.
...
Рейтинг: 0 / 0
17.02.2016, 21:36
    #39173589
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
vyegorovqwwqно вот из под plpgsql что--то у меня этот трюк не работает как и у ТС
Возможно из-за того, что оптимизатор понимает SQL функции (подсматривает, ага), а PL/pgSQL для него — черный ящик.и поэтому разработчику (а не оптимизатору) надо накосячить с реализацией, прикрутив чек, идущий противу обычаев мочь вызывать SRF в SELECT-листе, а не только во FROM-е ?

ну да, ну да, и ещё 200 причин пустить петуха

что-- то я начал сомневаться, все стандартные и половину не очень в select листе вызвать можно. я кажется до существования lateral и свои самописки так вызывал. неужто не натыкался ?
или всё--таки трючок есть, но немного забытый
...
Рейтинг: 0 / 0
17.02.2016, 21:41
    #39173591
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
vyegorovqwwqно вот из под plpgsql что--то у меня этот трюк не работает как и у ТС
Возможно из-за того, что оптимизатор понимает SQL функции (подсматривает, ага), а PL/pgSQL для него — черный ящик.более вероятно, что разраб плпгшной реализации не был знаком с пг--шными традициями возвращать SRF в SELECT листе. ну вот так -- из оракела заскочил ненадолго, и понаписал всякого разного. в свойственной ему манере.
...
Рейтинг: 0 / 0
18.02.2016, 08:34
    #39173736
big-trot
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
vyegorov,


vyegorovВозможно из-за того, что оптимизатор понимает SQL функции (подсматривает, ага), а PL/pgSQL для него — черный ящик.

В данном случае срабатывает инструмент inline вставки тела функции в запрос. inline вставка выполняется не всегда, в только при определенных условий.
Для PL/pgSQL тоже такое возможно, но количество условий и ограничений в этом случае еще больше.
См. здесь
...
Рейтинг: 0 / 0
18.02.2016, 11:06
    #39173881
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
big-trot,

в данном случае задокументированы все особенности (читай багофичи) реализации -- "как есть"

это хороший паттерн -- документировать в стиле "так получилось" [i.e. "не шмогла"].
но это не отвечает на вопрос "как оно должно быть концептуально". (а отвечает на вопрос откуда выросли руки у а. реализаторов и б. "разъяснителей" )

всё это печально. да. инструмент ,долго и довольно честно обещавший быть концептуально более прозрачным , чем оракел, так и не добравшись до навороченности [интеллектуальности] последнего, пустился во все тяжкие в духе "старшего товаристча": "тут играем, тут не играем. а тут рыбу заворачивали"
...
Рейтинг: 0 / 0
18.02.2016, 11:25
    #39173911
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
qwwq, таки плохо лежал, мало думал. наехал на, не по делу на.
приношу извинения вики--писателям.

вот уточнение -- это не имеет никакого отношения к инлайн разворачиванию планером

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
BEGIN;
CREATE OR REPLACE FUNCTION public.assa()
  RETURNS SETOF RECORD AS
$BODY$

	SELECT ROW (1,'assa' )
	UNION ALL SELECT  (2,'assa','assa' )
	UNION ALL SELECT  ROW (3,'assa','assa','assa');
$BODY$
  LANGUAGE sql IMMUTABLE SECURITY DEFINER
  COST 10
  ROWS 10;
  
	GRANT EXECUTE ON FUNCTION  public.assa() TO public;
	GRANT USAGE  ON schema public TO stats_reader;
	SET ROLE stats_reader;
SELECT public.assa();
-- rollback;
--------------------------
'(1,assa)'
'(2,assa,assa)'
'(3,assa,assa,assa)'



-- т.е. мы защитились от возможности развернуть тело в
ан оно всё равно не ругается. (и не должно).
потому что в тексте исподников очевидно для plpgsql что--то другое написано, чем для sql
...
Рейтинг: 0 / 0
18.02.2016, 11:26
    #39173913
vyegorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
Postgres "знает" про функции на языке SQL.

Это не процедурный язык, это всё тот же SQL, к которому добавили плюшек. Поэтому функции на нём предпочтительней, т.к. оптимизатор умеет трансформировать их.
В данном случае — оптимизатор банально может заменить вызов функции на подзапрос, пэтому сигнатура не нужна.

Все остальные языки процедурные — запускается handler и читается то, что он вернёт. И оптимизатор никак не знает, что вернёт функция, потому сигнатуры тут — обязательны.

Язык SQL стоит в стороне от остальных PL и сравнивать функции на нём с функциями на любом другом PL неправильно.
...
Рейтинг: 0 / 0
18.02.2016, 11:35
    #39173926
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с функцией
vyegorov,

не может он security definer развернуть в подзапрос для другого усера. усерится, простите.
это в коде у него записано -- если усер другой -- низзя.

т.е. эти отмазки не канают.

а то, что для других языков "не шмогла" , и наложила куда--то лишнего -- так это просто констатация факта.

вопрос лишь в том, как к оному факту относиться
как к допустимому, или как к возмутительному.

Мне ,как потребиелю концепций, отхождение от стройности -- возмутительно. вам, как продавцу доступа к Провалу -- это мелкая фича, скорее достойная заметания под коврик.
ну так спорить об этом и не имеет смысла.
-- это ваша родина, сынок.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите с функцией / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]