суббота, 4 июля 2009 г.

Счетчики в SQLite

Недавно ко мне обратился прикладной программист, работающий с моим фрэймворком для AOLServer и SQLite с вопросом, как ему сделать счетчик записей, возвращенных запросом. Разумеется, можно создать временную таблицу или забиндить тиклевскую функцию, но есть и более простой способ - использовать написанный мною модуль key или tempkey (отличаются только тем, что последний использует временную таблицу, таким образом, при хранении временных объектов в ОЗУ не требуется запись на диск). Модуль key создает при инициализации таблицу keys (а модуль tempkey - временную таблицу tempkeys), в которой и будут храниться все ключи; таким образом, можно использовать практически неограниченное количество ключей без ущерба для производительности и не нуждаясь в большом количестве ОЗУ.

Рассмотрим на примере неименованного временного счетчика:

create table colors(name text);
insert into colors values ('Red');
insert into colors values ('Green');
insert into colors values ('Blue');

select tempkey_install();
select tempkey_increment('','',1) as counter, name from colors;
1|Red
2|Green
3|Blue

select tempkey_get('','');
3

--select tempkey_delete('','');
select tempkey_uninstall();


Первым аргументом функции ключей принимают имя группы ключей (unit), а вторым - имя самого ключа. Если нам нужен временный счетчик, можно имя группы и имя ключа вовсе не указывать, работая с неименованным ключом.

По завершению обработки в качестве бонуса мы можем узнать количество строк, обработанных запросом, с помощью функции tempkey_get.

Вызовом tempkey_delete можно удалить указанный ключ, а tempkey_uninstall удалит все ключи (по техническим причинам таблица с ключами не удаляется, чистится только ее содержимое).

Как видите, используя именованные или неименованные ключи, мы получаем возможность работать со счетчиками в запросах и сохранять результаты между запросами.

Для справки приведу свой сценарий для тестирования модуля "key":

select 'ERROR' where key_install() is not null; --Create "keys" table.
select 'ERROR' where key_exists('common','nds%')!=0; --Check is param exists
select 'ERROR' where key_get('common','nds%') is not null; --Get _non-existing_ value _without_ default_value
select 'ERROR' where key_get('common','nds%',18)!='18'; --Get _non-existing_ value _with_ default_value
select 'ERROR' where key_set('common','nds%',10)!='10'; --Set value
select 'ERROR' where key_get('common','nds%')!='10'; --Get _existing_ value
select 'ERROR' where key_add('common','nds%',18) is not null; --Add _existing_ key
select 'ERROR' where key_replace('common','nds%',20)!='20'; --Replace _existing_ key
select 'ERROR' where key_delete('common','nds%')!=1; --Delete existing key
select 'ERROR' where key_delete('common','nds%') is not null; --Delete non-existing key
select 'ERROR' where key_delete('common') is not null; --Delete all keys in unit
select 'ERROR' where key_replace('common','nds%',20) is not null; --Replace _non-existing_ key
select 'ERROR' where key_add('common','nds%',18)!='18'; --Add _non-existing_ key
select 'ERROR' where key_increment('common','num',10)!='10'; --Increment _non-existing_ value
select 'ERROR' where key_increment('common','num',10)!='20'; --Increment _existing_ value
select 'ERROR' where key_prepend('common','string','prepend-')!='prepend-'; --Prepend value
select 'ERROR' where key_append('common','string','-append')!='prepend--append'; --Append value
select 'ERROR' where key_flush('common','string')!=1; --Flush existing key
select 'ERROR' where key_delete('common','string') is not null; --Flush non-existing key
select 'ERROR' where key_uninstall() is not null; -- Drop all keys from "keys" table.


Вышеприведенный набор SQL-запросов демонстрирует все возможности модуля "key".

Upd

См. Ticket 4004: Implement a "counter" SQL function. Разумеется, для подсчета строк в запросе функция counter() намного более эффективна, нежели использование дополнительного модуля. Патч к вышеназванному тикету приложен мной, после добавления функции в мою сборку.

Таким образом, теперь можно использовать модуль key по назначению - передача параметров между разными запросами и/или подключениями.

Комментариев нет:


(C) Alexey Pechnikov aka MBG, mobigroup.ru