DBM_Filter
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- СИНОПСИС
- ОПИСАНИЕ
- Что такое фильтр DBM?
- МЕТОДЫ
- Создание фильтра
- Включенные фильтры
- ПРИМЕЧАНИЯ
- ПРИМЕР
- СМОТРИТЕ ТАКЖЕ
- АВТОР
НАЗВАНИЕ
DBM_Filter — Фильтрация ключей/значений DBM
СИНОПСИС
use DBM_Filter ;
use SDBM_File; # or DB_File, GDBM_File, NDBM_File, or ODBM_File
$db = tie %hash, ...
$db->Filter_Push(Fetch => sub {...},
Store => sub {...});
$db->Filter_Push('my_filter1');
$db->Filter_Push('my_filter2', params...);
$db->Filter_Key_Push(...) ;
$db->Filter_Value_Push(...) ;
$db->Filter_Pop();
$db->Filtered();
package DBM_Filter::my_filter1;
sub Store { ... }
sub Fetch { ... }
1;
package DBM_Filter::my_filter2;
sub Filter
{
my @opts = @_;
...
return (
sub Store { ... },
sub Fetch { ... } );
}
1; ОПИСАНИЕ
Этот модуль предоставляет интерфейс, который позволяет применять фильтры к привязанным хешам, связанным с файлами DBM. Он основан на механизмах фильтрации DBM, которые присутствуют во всех модулях *DB*_File, включенных в стандартное распределение Perl с версии 5.6.1 и выше. Помимо модулей *DB*_File, поставляемых с Perl, модуль BerkeleyDB, доступный на CPAN, поддерживает механизмы фильтрации DBM. См. perldbmfilter для получения дополнительной информации о механизмах фильтрации DBM.
Что такое фильтр DBM?
Фильтр DBM позволяет изменять ключи и/или значения в привязанном хэше с помощью некоторого пользовательского кода непосредственно перед записью в файл DBM и сразу после чтения из файла DBM. Например, этот фрагмент кода
$some_hash{"abc"} = 42; потенциально может активировать два фильтра, один для записи ключа «abc», а другой — для записи значения 42. Аналогично, этот фрагмент
my ($key, $value) = each %some_hash активирует два фильтра, один для чтения ключа и один для чтения значения.
Подобно существующей функциональности фильтрации DBM, этот модуль обеспечивает заполнение переменной $_ ключом или значением, которые будет проверять фильтр. Это обычно означает, что большинство фильтров DBM имеют тенденцию быть очень короткими.
Что нового?
Основные улучшения по сравнению со стандартными механизмами фильтрации DBM:
-
Более чистый интерфейс.
-
Возможность легко применять несколько фильтров к одному файлу DBM.
-
Возможность создания «заготовленных» фильтров. Они позволяют упаковать часто используемые фильтры в самостоятельный модуль.
МЕТОДЫ
Этот модуль обеспечит доступность следующих методов через объект, возвращаемый вызовом tie.
$db->Filter_Push() / $db->Filter_Key_Push() / $db->Filter_Value_Push()
Добавляет фильтр в стек фильтров базы данных, $db. Три формата различаются только тем, к ключу DBM, значению DBM или обоим они применяются.
- Filter_Push
-
Фильтр применяется к обоим ключам и значениям.
- Filter_Key_Push
-
Фильтр применяется только к ключу.
- Filter_Value_Push
-
Фильтр применяется только к значению.
$db->Filter_Pop()
Удаляет последний примененный фильтр к файлу DBM, связанному с $db, если он присутствует.
$db->Filtered()
Возвращает TRUE, если к DBM, связанному с $db, применены какие-либо фильтры. В противном случае возвращает FALSE.
Создание фильтра
Фильтры могут быть созданы двумя основными способами
Немедленные фильтры
Немедленный фильтр позволяет указать код фильтра, который будет использоваться в момент применения фильтра к dbm. В этом режиме методы Filter_*_Push ожидают получения ровно двух параметров.
my $db = tie %hash, 'SDBM_File', ...
$db->Filter_Push( Store => sub { },
Fetch => sub { }); Ссылка на код, связанный с Store, будет вызвана перед записью любого ключа/значения в базу данных, а ссылка на код, связанный с Fetch, будет вызвана после чтения любого ключа/значения из базы данных.
Например, вот пример фильтра, который добавляет заключительный нулевой символ ко всем строкам перед их записью в файл DBM и удаляет заключительный нуль при чтении из файла DBM
my $db = tie %hash, 'SDBM_File', ...
$db->Filter_Push( Store => sub { $_ .= "\x00" ; },
Fetch => sub { s/\x00$// ; }); Примечания:
-
Оба фильтра Store и Fetch обрабатывают
$_.
Заготовленные фильтры
Немедленные фильтры полезны для разовых ситуаций. Для более общих задач полезно упаковать фильтр в свой собственный модуль.
Использование заготовленного фильтра:
$db->Filter_Push("name", params) где
- "name"
-
— имя загружаемого модуля. Если указанная строка не содержит символов разделителя пакетов "::", предполагается, что она относится к полному имени модуля "DBM_Filter::name". Это означает, что полные имена заготовленных фильтров, «null» и «utf8», включенные в этот модуль, равны:
DBM_Filter::null DBM_Filter::utf8 - params
-
— любые необязательные параметры, которые необходимо передать фильтру. Смотрите фильтр кодирования для примера модуля, использующего параметры.
Модуль, реализующий заготовленный фильтр, может иметь одну из двух форм. Вот шаблон для первой
package DBM_Filter::null ;
use strict;
use warnings;
sub Store
{
# store code here
}
sub Fetch
{
# fetch code here
}
1; Примечания:
-
Имя пакета использует префикс
DBM_Filter::. -
Модуль обязательно должен иметь методы Store и Fetch. Если присутствует только один метод, или ни один из них не присутствует, будет выброшено сообщение об ошибке.
Вторая форма позволяет фильтру хранить информацию о состоянии с помощью замыкания, таким образом:
package DBM_Filter::encoding ;
use strict;
use warnings;
sub Filter
{
my @params = @_ ;
...
return {
Store => sub { $_ = $encoding->encode($_) },
Fetch => sub { $_ = $encoding->decode($_) }
} ;
}
1; В этом случае методы «Store» и «Fetch» инкапсулированы в методе «Filter».
Включенные фильтры
В этот модуль включено несколько заготовленных фильтров. Они охватывают ряд основных областей, где фильтры необходимы при взаимодействии с файлами DBM. Они также служат шаблонами для ваших собственных фильтров.
Включенные фильтры:
-
utf8
Этот модуль гарантирует, что все данные, записываемые в DBM, будут закодированы в UTF-8.
Этот модуль требует модуля Encode.
-
encode
Позволяет выбрать кодировку символов, которая будет храниться в файле DBM.
-
compress
Этот фильтр будет сжимать все данные перед записью в базу данных и распаковывать при чтении.
Этот модуль требует Compress::Zlib.
-
int32
Этот модуль используется при взаимодействии с приложением C/C++ использующим C int в качестве ключа и/или значения в файле DBM.
-
null
Этот модуль гарантирует, что все данные, записанные в файл DBM, завершаются нулем. Это полезно, когда у вас есть скрипт Perl, который должен взаимодействовать с файлом DBM, который также использует программа C. Достаточно распространённая проблема заключается в том, что приложение C включает заключительный нуль в строку при записи в файл DBM. Этот фильтр гарантирует, что все данные, записанные в файл DBM, могут быть прочитаны приложением C.
ПРИМЕЧАНИЯ
Поддержание целостности обратного перехода
При написании фильтра DBM очень важно гарантировать, что при наличии фильтра DBM можно получить все данные, которые вы записали. На практике это означает, что любая трансформация, применяемая к данным в методе Store, должна иметь тоже обратное преобразование в методе Fetch.
Если вы не предоставите точное обратное преобразование, вы обнаружите, что код подобный этому не будет вести себя так, как вы ожидаете.
while (my ($k, $v) = each %hash)
{
...
} В зависимости от преобразования вы обнаружите, что произойдёт одно или несколько из следующих действий:
-
Цикл никогда не завершится.
-
Будет получено слишком мало записей.
-
Будет получено слишком много записей.
-
Цикл будет работать правильно некоторое время, но в неожиданный момент завершится с ошибкой.
Не смешивайте отфильтрованные и неотфильтрованные данные в одном файле базы данных.
Это просто повторение предыдущего раздела. Если вы не уверены на 100% в том, что делаете, избегайте смешивания отфильтрованных и неотфильтрованных данных.
ПРИМЕР
Предположим, вам нужно взаимодействовать со старым приложением C, которое хранит ключи как C int, а значения — как null-завершённые UTF-8 строки. Вот как вы это настроите
my $db = tie %hash, 'SDBM_File', ...
$db->Filter_Key_Push('int32') ;
$db->Filter_Value_Push('utf8');
$db->Filter_Value_Push('null'); СМОТРИТЕ ТАКЖЕ
<DB_File>, GDBM_File, NDBM_File, ODBM_File, SDBM_File, perldbmfilter
АВТОР
Paul Marquess <pmqs@cpan.org>
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/DBM_Filter