Фон
Для проекта ввода данных пользователь может вводить переменные, используя сокращенную запись:
"Pour i1 into a flask."
"Warm the flask to 25 degrees C."
"Add 1 drop of i2 to the flask."
"Immediately seek cover."
В этом случае i1
и i2
являются ссылочными переменнымигде число относится к ингредиенту.Текстовые строки находятся в таблице INSTRUCTION
, ингредиенты - в таблице INGREDIENT
.
Каждый ингредиент имеет порядковый номер для сортировки.
Задача
Пользователи могутизменить порядок ингредиентов, что неблагоприятно меняет инструкции.Например, порядок ингредиентов вначале может выглядеть следующим образом:
seq | label
1 | water
2 | sodium
Пользователь добавляет еще один ингредиент:
seq | label
1 | water
2 | sodium
3 | francium
Пользователь переупорядочивает список:
seq | label
1 | water
2 | francium
3 | sodium
На этом этапе следующая строка теперь неверна:
"Add 1 drop of i2 to the flask."
Необходимо изменить нумерацию i2
(поскольку ингредиент # 2 был перемещен в позицию # 3), чтобы указывать на исходную ссылочную переменную:
"Add 1 drop of i3 to the flask."
Обновленные сведения
Это упрощенная версия проблемы.Полная проблема может иметь строки, такие как:
"Add 1 drop of i2 to the o3 of i1."
, где o3
- объект (колба), а i1
и i2
- вода и натрий соответственно.
Структура таблицы
Таблица ингредиентов имеет следующую структуру:
id | seq | label
Таблица инструкций имеет следующую структуру:
step
Алгоритм
Алгоритм, который я имею в виду:
- Повторите для всех
step
с, которые соответствуют выражению '\mi([0-9]+)'
: - Разбейте шаг на жетоны слова.
- Длякаждый токен:
- Если числовая часть токена соответствует старому порядковому номеру, замените его новым порядковым номером.
- Перекомбинируйте токены и обновите инструкцию.
- Обновите номер ингредиента.
Обновление
Алгоритм может быть неверным, как написано.Могут быть две ссылочные переменные, которые должны измениться.Рассмотрим до:
seq | label
1 | water
2 | sodium
3 | caesium
4 | francium
И после (замена натрия и цезия):
seq | label
1 | water
2 | caesium
3 | sodium
4 | francium
Каждый i2
на каждом шаге должен стать i3
;аналогично i3
должно стать i2
.Итак
"Add 1 drop of i2 to the flask, but absolutely do not add i3."
Становится:
"Add 1 drop of i3 to the flask, but absolutely do not add i2."
Код
Код для выполнения первых двух частей алгоритма напоминает:
CREATE OR REPLACE FUNCTION
renumber_steps(
p_ingredient_id integer,
p_old_sequence integer,
p_new_sequence integer )
RETURNS void AS
$BODY$
DECLARE
v_tokens text[];
BEGIN
FOR v_tokens IN
SELECT
t.tokens
FROM (
SELECT
regexp_split_to_array( step, '\W' ) tokens,
regexp_matches( step, '\mi([0-9]+)' ) matches
FROM
instruction
) t
LOOP
RAISE NOTICE '%', v_tokens;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Вопрос
Какой более эффективный способ решения этой проблемы (т. Е. Как бы вы исключили циклические конструкции), возможно, с использованием возможностей, специфичных для PostgreSQL, без серьезного пересмотра модели данных?
Спасибо!
Сведения о системе
PostgreSQL 9.1.2.