Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Common Procedure Expressions / 17 сообщений из 17, страница 1 из 1
20.10.2016, 13:25
    #39330585
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
EXECUTE STATEMENT (:varchar_variable) - сколько раз препарируется? При каждом исполнении или только при первом ?

Что-то мне захотелось Common Procedure Expressions :-)
Или Generic SQL Programming :-)
Или u name it

Простой пример: есть несколько древовидных справочников.
Типа "лист ссылается на свою ветку-владельца" через FK->PK.
Унаследованных. То есть столбцы называются как хотят.
Хотя бы типы, кажется, везде integer. Но в идеале от них бы отвязаться бы тоже...

Хочется делать join'ы других таблиц с несколькими выбираемыми пользователем "подкустами" справочников

Можно выбирать ID через With Recursive но это как-то не очень красиво.
Лучше подходят, кажется, вложенные диапазоны.

И для любой таблицы в отдельности это просто

Код: 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.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
ALTER TABLE T1
  ADD L Integer;
  
ALTER TABLE T1
  ADD R Integer;  
  
CREATE UNIQUE INDEX T1_L ON T1 (L);
CREATE UNIQUE INDEX T1_R ON T1 (R);


CREATE OR ALTER TRIGGER T1_Tree_Changed FOR T1
ACTIVE AFTER INSERT OR UPDATE 
AS
begin
  if ((NEW.id <> OLD.id) or (NEW.parent is distinct from OLD.Parent)) then
    if ((old.l is not null) or (old.r is not null)) then
    begin
      update T1 set l = null, r = null;
      -- new.l = null;  needed for before-xxx triggers
      -- new.r = null;
    end
end  



CREATE OR ALTER TRIGGER T1_PK FOR T1
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  if (new.ID IS NULL) then
      SELECT NEXT VALUE FOR T1_GEN from rdb$database into new.ID;
end



create or alter procedure UPD_T1_LR_1 (
    R_IN integer = null,
    ITEM_ID integer = null)
returns (
    R_OUT integer)
as
declare variable L_VAR integer;
declare variable LOOP_ID integer;
begin
 R_OUT = 0;
 if (exists( select * from t1 where id = :item_id )) then begin
   L_Var = coalesce(:R_IN, 0) + 1;
   R_OUT = :L_Var;
 end

 for select id from t1
     where parent is not distinct from :item_id
     order by id  -- ordering is not supported in With Recursive
     into loop_id
 do
 begin
   execute procedure UPD_t1_LR_1 (:R_OUT, :loop_id)
                returning_values (:R_OUT);
 end

 R_OUT = :R_OUT + 1;
 update t1 set
   L = :l_var, 
   R = :r_out
 where id = :item_id;
end^



Вторая процедура.... писать её для каждого справочника не хочется.
В конце концов она одна и та же, с точностью до - table name, id column name and type, parent id column name, left-bound and right-bound column names

т.е. можно добавить в неё еще один входящий параметр - текст её тела в виде строки - и пусть она сама себе вызывает рекурсивно через Execute Statement....

но как-то это очень хитровыподвернуто

И вот тут бы какое-нибудь временно-объявленное тело по аналогии с CTE бы хорошо подошло

with statement ..... as TempRecursiveSP do begin
execute procedure TempRecursiveSP
end;

или

with block ..... as TempRecursiveSP do begin
execute procedure TempRecursiveSP
end;
...
Рейтинг: 0 / 0
20.10.2016, 13:46
    #39330611
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
исходный пост и первый комментарий - 19804570
...
Рейтинг: 0 / 0
20.10.2016, 13:46
    #39330614
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
в oracle 12 есть with function выглядит это примерно так:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
WITH
FUNCTION get_domain(url VARCHAR2) RETURN VARCHAR2 IS
   pos BINARY_INTEGER;
   len BINARY_INTEGER;
BEGIN
   pos := INSTR(url, 'www.');
   len := INSTR(SUBSTR(url, pos + 4), '.') - 1;
   RETURN SUBSTR(url, pos + 4, len);
END;
SELECT DISTINCT get_domain(catalog_url)
FROM product_information;



мы бы тоже моли расширить наш DSQL так чтобы можно было писать WITH {PROCEDURE | FUNCTION}

Если есть желание делай тикет в трекере на новую фичу

З.Ы. Насчёт WITH STATMENT в топку
...
Рейтинг: 0 / 0
20.10.2016, 13:51
    #39330621
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
Симонов ДенисЕсли есть желание делай тикет в трекере на новую фичу

Желание-то есть, только сначала обсудить надо, как его делать ,как его не делать, чтобы в трекер было что писать кроме ссылки на форум

Симонов ДенисЕсли есть желание делай тикет в трекере на новую фичу

Желание-то есть, только сначала обсудить надо, как его делать ,как его не делать, чтобы в трекер было что писать кроме ссылки на форум[/quote]
[quote Arioch]Симонов Денисwith function выглядит это примерно так:

в этом пpимере функций то ли не может в рекурсию, то ли не показано


Симонов ДенисWITH STATMENT в топку

не принципиально

with block или with function вполне может состоять из execute statement

тут фишка в создании тела процедуры на лету, то есть в качестве параметров чтобы передавалась таблица и столбцы

и тут либо вводить в PSQL типы "столбец" и "таблица", либо таки создавтаь тело как VARCHAR
...
Рейтинг: 0 / 0
20.10.2016, 13:54
    #39330627
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
ну либо делать, чтобы EXECUTE STATEMENT препарировался только при первом вызове, а не при повторных

но с точки зрения реализации.... делать "унутре неонку", чтобы к каждому varchar переменному подвязывать BLR-кэш.... Бррр....
...
Рейтинг: 0 / 0
20.10.2016, 14:33
    #39330675
afgm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
Ariochну либо делать, чтобы EXECUTE STATEMENT препарировался только при первом вызове, а не при повторных
А разве не так происходит? Трейс говорит что один раз препарится.

По теме, вместо with function приходится делать execute block с suspend-ом и локальной функцией. Отсутствие lateral обходится аналогичным способом.
...
Рейтинг: 0 / 0
20.10.2016, 14:39
    #39330690
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
afgm,

есть надежда на то что lateral появится в Firebird 4.0 CORE-3435
...
Рейтинг: 0 / 0
20.10.2016, 14:42
    #39330695
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
afgmОтсутствие lateral

?

afgmА разве не так происходит? Трейс говорит что один раз препарится.

Там может быть кэш запросов.... а может не быть, хз... Implementation detail, на которую не хочется завязываться. И которую пока никто из гуру не подтвердил.

Плюс к тому надо придумать, что делать с рекурсивностью в данном случае. Может быть и ничего, кэшу пофигу пока текст запроса не менялся. А м.б. и нет....
...
Рейтинг: 0 / 0
20.10.2016, 14:45
    #39330697
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
Симонов Дениснадежда на то что lateral появится в Firebird 4.0 CORE-3435

ага, кажется понял, внесение контекста внутрь derived
...
Рейтинг: 0 / 0
20.10.2016, 15:01
    #39330723
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
AriochТам может быть кэш запросов.... а может не быть, хз...Небольшой кеш есть
AriochImplementation detail, на которую не хочется завязываться.И правильно
AriochИ которую пока никто из гуру не подтвердилПотому что AriochImplementation detail, на которую не хочется завязываться
...
Рейтинг: 0 / 0
20.10.2016, 15:09
    #39330736
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
hvlad,

ну вот это же тоже ответ, что "препарируется столько раз, сколько повезёт" :-)

а чтобы не завязыватсья - надо эту практику лeгализовать

в связи с чем таки в тред призываются разрабы, для обсуждаения желаемого и возможного и от синтаксиса и от реализации

с моей стороны хотелки :
1) рекурсия такого блока, желательно прямая, хотя в крайнем случае и через прокладку из вторичной функции сойдет
2) возможность передать в параметры relation и column напрямую, а не как строковой литерал для сборки execute statement
...
Рейтинг: 0 / 0
24.10.2016, 14:48
    #39332798
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
товарищи гуру, господа птицеводы...

какие-то осмысленные замечания будут?

а то ж я дуриком-то тикет составлю и будем там как дураки по-английски обсуждать, когда можно бы было по-русски
...
Рейтинг: 0 / 0
24.10.2016, 14:53
    #39332807
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
Arioch,

я свои уже высказал. Мне кажется надо делать похоже на Oracle (WITH PROCEDURE, WITH FUNCTION). Только фичу с WITH STATEMENT в топку.
...
Рейтинг: 0 / 0
24.10.2016, 15:14
    #39332843
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
Ariochкакие-то осмысленные замечания будут?А где осмысленное и конкретное предложение ? Без воды и философии
...
Рейтинг: 0 / 0
24.10.2016, 15:33
    #39332866
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
hvlad,

в таком виде пойдёт?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
WITH {<function> | <procedure> | <cte>} [, {<function> | <procedure> | <cte>} ...]
<select statement>

<function> ::= 
  FUNCTION func_name [(<in_impl_params>)]
  RETURNS <type> [COLLATE collation] [DETERMINISTIC]
  AS
    <declarations>
  BEGIN
    <PSQL_statements>]
  END

<procedure> ::= 
  PROCEDURE proc_name [(<in_impl_params>)]
  RETURNS (<out_params>)
  AS
    <declarations>
  BEGIN
    <PSQL_statements>]
  END

пример использования

Код: plsql
1.
2.
3.
4.
5.
6.
7.
WITH 
  FUNCTION sum_args(a int, b int) RETURN int
  AS
  BEGIN
    RETURN a+b;
  END
SELECT sum_args(1, 2) FROM RDB$DATABASE
...
Рейтинг: 0 / 0
24.10.2016, 15:37
    #39332873
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
Симонов Денис,

пойдёт. Только не понятно кто и когда этим сможет заняться
...
Рейтинг: 0 / 0
24.10.2016, 15:38
    #39332876
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Common Procedure Expressions
hvlad,

ну, это же просто предложение. Когда-нибудь в будущем.
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Common Procedure Expressions / 17 сообщений из 17, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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