Функции для работы с Dictionary (Map)

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Функции для работы с Dictionary (Map)

Andrei K

Нововведения в ФБ 3.0 (процедурные функции и локальные процедуры)
позволят еще больше логики из приложения вынести в БД
и выполнять на сервере.

Для сложных обработок будет крайне нехватать объектов
типа Dictionary (его же можно использовать как массив). Конечно,
можно обойтись временными таблицами, но работа с ними
будет гораздо более громоздкой и их надо создавать заранее.

Функции, которые можно было бы добавить:

// добавляет или присваивает значение по ключу
RDB$DICTIONARY_ADD(context, dictionary_name, key, value)

// проверяет наличие ключа
RDB$DICTIONARY_HAS(context, dictionary_name, key)

// возвращает количество элементов
RDB$DICTIONARY_COUNT(context, dictionary_name)

// удаляет элемент
RDB$DICTIONARY_REMOVE(context, dictionary_name, key)

//очищает словарь
RDB$DICTIONARY_CLEAR(context, dictionary_name)

context здесь это 'USER_SESSION' или 'USER_TRANSACTION'

--

---
Вы получили это сообщение, поскольку подписаны на группу "gmane.comp.db.firebird.russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес [hidden email].
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Функции для работы с Dictionary (Map)

Roman Simakov-2
10 апреля 2014 г., 12:32 пользователь Andrei K. <[hidden email]> написал:
> Конечно,
> можно обойтись временными таблицами, но работа с ними
> будет гораздо более громоздкой и их надо создавать заранее.

Не понимаю в чем громоздкость. Пользователь не видит запросов, зато
все SQL плюшки сразу есть у временных таблиц и в движке все готово.
По-моему не надо выдумывать, если есть четкий механизм SQL.

--
Roman Simakov

--

---
Вы получили это сообщение, поскольку подписаны на группу gmane.comp.db.firebird.russian.

Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес [hidden email].
Настройки подписки и доставки писем: https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Функции для работы с Dictionary (Map)

Simonov Denis
In reply to this post by Andrei K
Andrei K. <[hidden email]> писал(а) в  
своём письме Thu, 10 Apr 2014 12:32:31 +0400:

>
> Нововведения в ФБ 3.0 (процедурные функции и локальные процедуры)
> позволят еще больше логики из приложения вынести в БД
> и выполнять на сервере.
>
> Для сложных обработок будет крайне нехватать объектов
> типа Dictionary (его же можно использовать как массив). Конечно,
> можно обойтись временными таблицами, но работа с ними
> будет гораздо более громоздкой и их надо создавать заранее.
>
> Функции, которые можно было бы добавить:
>
> // добавляет или присваивает значение по ключу
> RDB$DICTIONARY_ADD(context, dictionary_name, key, value)
>
> // проверяет наличие ключа
> RDB$DICTIONARY_HAS(context, dictionary_name, key)
>
> // возвращает количество элементов
> RDB$DICTIONARY_COUNT(context, dictionary_name)
>
> // удаляет элемент
> RDB$DICTIONARY_REMOVE(context, dictionary_name, key)
>
> //очищает словарь
> RDB$DICTIONARY_CLEAR(context, dictionary_name)
>
> context здесь это 'USER_SESSION' или 'USER_TRANSACTION'
>

Можно сделать свой Package и разместить туда все свои функции для работы  
со словарём, а внутри они будут обращаться всё к той же GTT


--
Написано с помощью почтового клиента Opera: http://www.opera.com/mail/

--

---
Вы получили это сообщение, поскольку подписаны на группу gmane.comp.db.firebird.russian.

Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес [hidden email].
Настройки подписки и доставки писем: https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Функции для работы с Dictionary (Map)

Simonov Denis
In reply to this post by Andrei K
Andrei K. <[hidden email]> писал(а) в  
своём письме Thu, 10 Apr 2014 12:32:31 +0400:


>
> Для сложных обработок будет крайне нехватать объектов
> типа Dictionary (его же можно использовать как массив). Конечно,
> можно обойтись временными таблицами, но работа с ними
> будет гораздо более громоздкой и их надо создавать заранее.
>
> Функции, которые можно было бы добавить:
>
> // добавляет или присваивает значение по ключу
> RDB$DICTIONARY_ADD(context, dictionary_name, key, value)
>
> // проверяет наличие ключа
> RDB$DICTIONARY_HAS(context, dictionary_name, key)
>
> // возвращает количество элементов
> RDB$DICTIONARY_COUNT(context, dictionary_name)
>
> // удаляет элемент
> RDB$DICTIONARY_REMOVE(context, dictionary_name, key)
>
> //очищает словарь
> RDB$DICTIONARY_CLEAR(context, dictionary_name)
>
> context здесь это 'USER_SESSION' или 'USER_TRANSACTION'
>

написал модуль реализующий это. Я думаю при желании его можно заточить под  
твои нужды

CREATE GLOBAL TEMPORARY TABLE SESSION_DICTIONARY (
     NAME       VARCHAR(31) NOT NULL,
     KEY_NAME   VARCHAR(31) NOT NULL,
     DIC_VALUE  VARCHAR(255)
) ON COMMIT PRESERVE ROWS;

ALTER TABLE SESSION_DICTIONARY ADD CONSTRAINT PK_SESSION_DICTIONARY  
PRIMARY KEY (NAME, KEY_NAME);

CREATE GLOBAL TEMPORARY TABLE TRANSACTION_DICTIONARY (
     NAME       VARCHAR(31) NOT NULL,
     KEY_NAME   VARCHAR(31) NOT NULL,
     DIC_VALUE  VARCHAR(255)
) ON COMMIT DELETE ROWS;

ALTER TABLE TRANSACTION_DICTIONARY ADD CONSTRAINT  
PK_TRANSACTION_DICTIONARY PRIMARY KEY (NAME, KEY_NAME);

CREATE EXCEPTION E_INCORRECT_DICTIONARY_CONTEXT 'Не корректный контекст  
для словаря';

SET TERM ^;

CREATE OR ALTER PACKAGE DICTIONARY
AS
begin
   -- добавляет или присваивает значение по ключу
   function ADD_ITEM(context varchar(31),
                     dictionary_name varchar(31),
                     key_name varchar(31),
                     dic_value varchar(255)) returns varchar(255);

   -- проверяет наличие ключа
   function HAS_ITEM(context varchar(31),
                     dictionary_name varchar(31),
                     key_name varchar(31)) returns boolean;

   -- возвращает количество элементов
   function COUNT_ITEM(context varchar(31),
                       dictionary_name varchar(31)) returns int;

   -- удаляет элемент
   function REMOVE_ITEM(context varchar(31),
                        dictionary_name varchar(31),
                        key_name varchar(31)) returns varchar(255);

   --очищает словарь
   function CLEAR(context varchar(31),
                  dictionary_name varchar(31)) returns int;

   -- возвращает элемент
   function GET_ITEM(context varchar(31),
                     dictionary_name varchar(31),
                     key_name varchar(31)) returns varchar(255);
end^

RECREATE PACKAGE BODY DICTIONARY
AS
begin

/*************************************/
-- Реализация приватных функций
/*************************************/

   -- проверяет правильность контекста
   procedure CHECK_CONTEXT(context varchar(31))
   as
   begin
     if (UPPER(context) not in ('USER_SESSION', 'USER_TRANSACTION')) then
        exception E_INCORRECT_DICTIONARY_CONTEXT;
   end

/*************************************/
-- Реализация публичных функций
/*************************************/

   -- добавляет или присваивает значение по ключу
   function ADD_ITEM(context varchar(31),
                     dictionary_name varchar(31),
                     key_name varchar(31),
                     dic_value varchar(255)) returns varchar(255)
   as
   begin
     execute procedure CHECK_CONTEXT(:context);
     if (UPPER(context) = 'USER_SESSION') then
     begin
       insert into SESSION_DICTIONARY(name, key_name, dic_value)
       values (:dictionary_name, :key_name, :dic_value);
       return dic_value;
     end
     if (UPPER(context) = 'USER_TRANSACTION') then
     begin
       insert into TRANSACTION_DICTIONARY(name, key_name, dic_value)
       values (:dictionary_name, :key_name, :dic_value);
       return dic_value;
     end
   end

   -- проверяет наличие ключа
   function HAS_ITEM(context varchar(31),
                     dictionary_name varchar(31),
                     key_name varchar(31)) returns boolean
   as
   begin
     execute procedure CHECK_CONTEXT(:context);
     if (UPPER(context) = 'USER_SESSION') then
     begin
       return EXISTS(select *
                     from SESSION_DICTIONARY
                     where name = :dictionary_name and
                           key_name = :key_name);
     end
     if (UPPER(context) = 'USER_TRANSACTION') then
     begin
       return EXISTS(select *
                     from TRANSACTION_DICTIONARY
                     where name = :dictionary_name and
                           key_name = :key_name);
     end
   end

   -- возвращает количество элементов
   function COUNT_ITEM(context varchar(31),
                       dictionary_name varchar(31)) returns int
   as
   begin
     execute procedure CHECK_CONTEXT(:context);
     if (UPPER(context) = 'USER_SESSION') then
     begin
       return (select count(*)
               from SESSION_DICTIONARY
               where name = :dictionary_name);
     end
     if (UPPER(context) = 'USER_TRANSACTION') then
     begin
       return (select count(*)
               from TRANSACTION_DICTIONARY
               where name = :dictionary_name);
     end
   end

   -- удаляет элемент
   function REMOVE_ITEM(context varchar(31),
                        dictionary_name varchar(31),
                        key_name varchar(31)) returns varchar(255)
   as
   declare variable xValue varchar(255);
   begin
     execute procedure CHECK_CONTEXT(:context);
     if (UPPER(context) = 'USER_SESSION') then
     begin
       delete from SESSION_DICTIONARY
       where name = :dictionary_name and
             key_name = :key_name
       returning dic_value
       into xValue;
     end
     if (UPPER(context) = 'USER_TRANSACTION') then
     begin
       delete from TRANSACTION_DICTIONARY
       where name = :dictionary_name and
             key_name = :key_name
       returning dic_value
       into xValue;
     end
     return xValue;
   end

   --очищает словарь
   function CLEAR(context varchar(31),
                  dictionary_name varchar(31)) returns int
   as
   begin
     execute procedure CHECK_CONTEXT(:context);
     if (UPPER(context) = 'USER_SESSION') then
     begin
       delete from SESSION_DICTIONARY
       where name = :dictionary_name;
       return ROW_COUNT;
     end
     if (UPPER(context) = 'USER_TRANSACTION') then
     begin
       delete from TRANSACTION_DICTIONARY
       where name = :dictionary_name;
       return ROW_COUNT;
     end
   end

   -- возвращает элемент
   function GET_ITEM(context varchar(31),
                     dictionary_name varchar(31),
                     key_name varchar(31)) returns varchar(255)
   as
   declare variable xValue varchar(255);
   begin
     execute procedure CHECK_CONTEXT(:context);
     if (UPPER(context) = 'USER_SESSION') then
     begin
       select dic_value
       from SESSION_DICTIONARY
       where name = :dictionary_name and
             key_name = :key_name
       into xValue;
     end
     if (UPPER(context) = 'USER_TRANSACTION') then
     begin
       select dic_value
       from TRANSACTION_DICTIONARY
       where name = :dictionary_name and
             key_name = :key_name
       into xValue;
     end
     return xValue;
   end
end^

SET TERM ;^

--

---
Вы получили это сообщение, поскольку подписаны на группу gmane.comp.db.firebird.russian.

Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес [hidden email].
Настройки подписки и доставки писем: https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Функции для работы с Dictionary (Map)

Roman Simakov-2
Нет, не хочу быть занудой, но пардон это все для чего? Чтобы вместо

> insert into SESSION_DICTIONARY(name, key_name, dic_value) values (:dictionary_name, :key_name, :dic_value);
писать
ADD_ITEM(context, dictionary_name, key_name)

Таких вызовов-то будет два-три обвернутых в прикладные функции в
программе. Да еще эти лишние проверки сессий, разных таблиц. Вот не
понимаю я зачем эти обвертки придумывать.


--
Roman Simakov

--

---
Вы получили это сообщение, поскольку подписаны на группу gmane.comp.db.firebird.russian.

Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес [hidden email].
Настройки подписки и доставки писем: https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Функции для работы с Dictionary (Map)

Simonov Denis
Roman Simakov <[hidden email]>  
писал(а) в своём письме Thu, 10 Apr 2014 15:05:56 +0400:

> Нет, не хочу быть занудой, но пардон это все для чего? Чтобы вместо
>
>> insert into SESSION_DICTIONARY(name, key_name, dic_value) values  
>> (:dictionary_name, :key_name, :dic_value);
> писать
> ADD_ITEM(context, dictionary_name, key_name)
>
> Таких вызовов-то будет два-три обвернутых в прикладные функции в
> программе. Да еще эти лишние проверки сессий, разных таблиц. Вот не
> понимаю я зачем эти обвертки придумывать.
>
>
ну мне они не нужны. Я просто показал вопрашающему что это не сложно  
реализовать.
Да и потестировал заодно пакеты.

--
Написано с помощью почтового клиента Opera: http://www.opera.com/mail/

--

---
Вы получили это сообщение, поскольку подписаны на группу gmane.comp.db.firebird.russian.

Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес [hidden email].
Настройки подписки и доставки писем: https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Функции для работы с Dictionary (Map)

Andrei K

Можно и так. Единственный минус -- временные таблицы это те же таблицы, где на каждую запись
накладывается значительный оверхед. При работе с большим количеством пар ключ - значение
это может быть проблемой. Хотелось бы иметь легковесный механизм словаря.




On Thursday, April 10, 2014 2:50:15 PM UTC+3, Simonov Denis wrote:
Roman Simakov <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="yO5yKkZ1a-MJ" onmousedown="this.href='javascript:';return true;" onclick="this.href='javascript:';return true;">roman.simakov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>  
писал(а) в своём письме Thu, 10 Apr 2014 15:05:56 +0400:

> Нет, не хочу быть занудой, но пардон это все для чего? Чтобы вместо
>
>> insert into SESSION_DICTIONARY(name, key_name, dic_value) values  
>> (:dictionary_name, :key_name, :dic_value);
> писать
> ADD_ITEM(context, dictionary_name, key_name)
>
> Таких вызовов-то будет два-три обвернутых в прикладные функции в
> программе. Да еще эти лишние проверки сессий, разных таблиц. Вот не
> понимаю я зачем эти обвертки придумывать.
>
>
ну мне они не нужны. Я просто показал вопрашающему что это не сложно  
реализовать.
Да и потестировал заодно пакеты.

--
Написано с помощью почтового клиента Opera: <a href="http://www.opera.com/mail/" target="_blank" onmousedown="this.href='http://www.google.com/url?q\75http%3A%2F%2Fwww.opera.com%2Fmail%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNEwdZtf3630O-tfNgwVt6xFb0QJNg';return true;" onclick="this.href='http://www.google.com/url?q\75http%3A%2F%2Fwww.opera.com%2Fmail%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNEwdZtf3630O-tfNgwVt6xFb0QJNg';return true;">http://www.opera.com/mail/

--

---
Вы получили это сообщение, поскольку подписаны на группу "gmane.comp.db.firebird.russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес [hidden email].
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.