-
Notifications
You must be signed in to change notification settings - Fork 9
sql_do_upsert
Внесение одной или нескольких записей в заданную таблицу в режиме синхронизации данных: то есть, возможно, поверх существующего содержимого.
Ключ синхронизации на каждую таблицу может быть только один. Он описывается в модели данных в виде условно-уникального индекса.
Процедура реализуется через атомарные UPSERT-операторы SQL (INSERT ... ON CONFLICT, MERGE INTO) без дополнительных блокировок.
Рассмотрим таблицу geo, описанную в модели данных следующим образом:
label => 'Географические координаты',
columns => {
label => 'string', # Адрес
lat => 'decimal[8,6]', # Широта
lon => 'decimal[8,6]', # Долгота
},
keys => {
label => 'label!',
},
Поскольку определение ключа оканчивается на '!', индекс будет уникальным по множеству с fake=0 (в то же время дублей по label с иными значениями fake может быть сколько угодно).
Теперь 2 вызова подряд
my $id_1 = sql_do_upsert (geo => {label => 'Офис', lat => 0, lon => 0, fake => 0});
my $id_2 = sql_do_upsert (geo => {label => 'Офис', lat => 55, lon => 37.392113, fake => 0});
приведут к тому, что в таблице geo будет ровно одна запись с label='Офис' и координатами 55 37.392113, а в переменных $id_1 и $id_2 — одно и то же значение: id этой записи.
Последующий вызов
sql_do_upsert (geo => {label => 'Офис', lat => 55.805393, lon => undef, fake => 0});
уточнит значение поля lat, но не затронет lon: пустые значения игнорируются, даже если переданы явно, но непустые будут записаны в любом случае (в отличие от sql_select_id, где это регулируется префиксом -).
За один вызов можно передать и целый пакет записей:
sql_do_upsert (geo => [
{label => 'Офис', lat => 55.805393, lon => 37.392113, fake => 0},
# ...
{label => 'Магазин', lat => 55.809418, lon => 37.464657, fake => 0},
]);
В этом случае процедура синхронизирует все записи, но не вернёт никакого значения (по аналогии с wish table_data).