Wish table data
Желание типа table_data естественным образом возникает при необходимости записать в одну из таблиц БД пакет согласованных данных, в особенности если простой INSERT может вызвать коллизии с ранее записанным содержимым.
Данные с общей частью
Рассмотрим редактирование многозначных данных, таких, как установление связей многие-ко-многим, визуализируемых при помощи checkboxes, или показателей, вводимых в статистические формы.
В этой ситуации, как правило, имеется таблица (table) с минимум 2 ссылками: на текущую форму (id_form) и на некоторый справочник (id_voc). Типичная задача: добиться того, чтобы для текущей формы с id_form = $_REQUEST {id} (это — общая часть данных всех записей на отображаемой форме) и каждого непустого $_REQUEST {_id_voc_$id_voc} в ней имелось по 1 записи с fake = 0. Задача эта решается вызовом
wish (table_data => [map {{ fake => 0, id_voc => $_ }} get_ids ('id_voc')], { table => 'table', root => {id_form => $_REQUEST {id}}, key => 'id_voc', delayed => 1, # можно в MySQL } );
В рассмотрение принимаются только записи, удовлетворяющие условиям, прописанным в опции root. Те записи, которы существовали в таблице до вызова, но не упомянуты в желаниях, удаляются. Комбинация из всех ключей root и всех компонент key (их можно указывать через запятую) играет роль ключа синхронизации. Уникальность такого набора полей на совести программиста.
Приведённый пример является распространённым, но несколько вырожденным: здесь строка 'id_voc' одновременно является значением 3 независимых параметров, а значение опции root, скорее всего, однозначно угадывается по контексту вызова. Поэтому для checkboxes и tree разработана упрощённая процедура-обёртка: sql_store_ids.
В более сложных случаях (когда надо учитывать не только факт непустоты, но и значение параметра) комбинацию map / get_ids необходимо заменить на формирование целевого списка вручную.
Данные с явными id
Если опция root не задана, множество записей, с которыми происходит сопоставление, расширяется до всей таблицы. При этом порядок исполнения желаний имеет специфику:
- id должны быть явно указаны в описании данных;
- сборка мусора не производится.
Такой режим работы соотвествует расширяемому справочнику, в котором есть несколько строк с заранее известными номерами. Именно так обрабатывается раздел data в описании схемы данных.
Дополнительные сведения
Данные здесь меняются минимально: при записи формы с неизменённым набором checkboxes никаких DML-инструкций не выполняется вовсе.
Если же изменения требуются, то они выполняются оптимальным образом:
- для MySQL при задании опции delayed создание и модификация осуществляются пакетными INSERT DELAYED и REPLACE DELAYED (это можно использовать, если не было LOCK на таблицу и вносимые данные гарантированно не понадобятся в рамках того же процесса), а удаление — всегда DELETE с выражением IN (...);
- для Oracle производится не более 1 вызова на каждую из операций INSERT, UPDATE, DELETE: используется execute_array;
- для всех прочих СУБД также используется execute_array. На уровне API это приводит к серии отдельных вызовов, однако по крайней мере используется одноразовый prepare на стороне сервера (разумеется, если данная возможность доступна).
Описанные оптимизационные приёмы могут с успехом применяться при количестве записей в пакете порядка нескольких тысяч. Хотя при неограниченном возрастании объёма данных есть риск натолкнуться на ограничения API.
Исполнение желания типа table_data весьма близко к побочному эффекту процедуры sql_select_id (также гарантируется наличие требуемых данных), однако эти механизмы никогда не будут совмещены: основной смысл table_data в том, чтобы как можно быстрее модифицировать данные, а sql_select_id — определить номер записи и выдать его в качестве результата.