Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save 240596448/44b209fb3b0b5bf7fcda3bc74e960efb to your computer and use it in GitHub Desktop.
Save 240596448/44b209fb3b0b5bf7fcda3bc74e960efb to your computer and use it in GitHub Desktop.
Сравнение объектов БлокировкаДанных
Функция ЕстьКонфликтБлокировок(Блокировка1, Блокировка2) Экспорт
//Преобразуем в пары область - массивы структур
ДанныеБлокировки1 = ПреобразоватьБлокировку(Блокировка1);
ДанныеБлокировки2 = ПреобразоватьБлокировку(Блокировка2);
Для каждого КЗ1 Из ДанныеБлокировки1 Цикл
Область = КЗ1.Ключ;
ДанныеРазделяемые1 = КЗ1.Значение.Разделяемые;
ДанныеИсключительные1 = КЗ1.Значение.Исключительные;
КЗ2_Значение = ДанныеБлокировки2.Получить(Область);
Если КЗ2_Значение = Неопределено Тогда
Продолжить; // нет пересечения по области
КонецЕсли;
ДанныеРазделяемые2 = КЗ2_Значение.Разделяемые;
ДанныеИсключительные2 = КЗ2_Значение.Исключительные;
// не сравниваем разделяемые1 - разделяемые2
Если ЕстьКонфликтМассивовЭлементовБлокировок(ДанныеИсключительные1, ДанныеИсключительные2)
Или ЕстьКонфликтМассивовЭлементовБлокировок(ДанныеИсключительные1, ДанныеРазделяемые2)
Или ЕстьКонфликтМассивовЭлементовБлокировок(ДанныеРазделяемые1, ДанныеИсключительные2) Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Функция ЕстьКонфликтМассивовЭлементовБлокировок(мЭлементыБлокировки1, мЭлементыБлокировки2)
Для каждого сткЭлементБлокировки1 Из мЭлементыБлокировки1 Цикл
Для каждого сткЭлементБлокировки2 Из мЭлементыБлокировки2 Цикл
ЕстьКонфликт = ЕстьКонфликтЭлементовБлокировок(сткЭлементБлокировки1, сткЭлементБлокировки2);
Если ЕстьКонфликт Тогда
СообщитьОКонфликте(сткЭлементБлокировки1, сткЭлементБлокировки2);
Возврат Истина;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат Ложь;
КонецФункции
Функция ЕстьКонфликтЭлементовБлокировок(сткЭлементБлокировки1, сткЭлементБлокировки2)
ВсеПоля = Новый Соответствие;
Для каждого КЗ Из сткЭлементБлокировки1 Цикл
ВсеПоля.Вставить(КЗ.Ключ);
КонецЦикла;
Для каждого КЗ Из сткЭлементБлокировки2 Цикл
ВсеПоля.Вставить(КЗ.Ключ);
КонецЦикла;
Для каждого КЗ Из ВсеПоля Цикл
ИмяПоля = КЗ.Ключ;
Значение1 = Неопределено; //массив значений или диапазонов
Значение2 = Неопределено;
Если НЕ сткЭлементБлокировки1.Свойство(ИмяПоля, Значение1)
Или НЕ сткЭлементБлокировки2.Свойство(ИмяПоля, Значение2) Тогда
Продолжить; // одно из полей блокирует любое значение поля
КонецЕсли;
Если НЕ ЗначенияПересекаются(Значение1, Значение2) Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Функция ЗначенияПересекаются(Значение1, Значение2)
Если ТипЗнч(Значение1) = Тип("Диапазон")
И ТипЗнч(Значение2) = Тип("Диапазон") Тогда
Возврат Значение1.Начало <= Значение2.Конец
И Значение2.Начало <= Значение1.Конец;
ИначеЕсли ТипЗнч(Значение1) = Тип("Диапазон") Тогда
Возврат Значение1.Начало <= Значение2 И Значение2 <= Значение1.Конец;
ИначеЕсли ТипЗнч(Значение2) = Тип("Диапазон") Тогда
Возврат Значение2.Начало <= Значение1 И Значение1 <= Значение2.Конец;
Иначе
Возврат Значение1 = Значение2;
КонецЕсли;
КонецФункции
Функция ПреобразоватьБлокировку(Блокировка)
ДанныеБлокировкиВсеОбласти = Новый Соответствие;
Для каждого ЭлементБлокировки Из Блокировка Цикл
// разделим блокировки по областям и режимам
// в т.ч. разделяем одну область на режимы
Ключ = ЭлементБлокировки.Область;
сткДанныеБлокировки = ДанныеБлокировкиВсеОбласти.Получить(Ключ);
Если сткДанныеБлокировки = Неопределено Тогда
сткДанныеБлокировки = Новый Структура("Исключительные,Разделяемые", Новый Массив, Новый Массив);
ДанныеБлокировкиВсеОбласти.Вставить(Ключ, сткДанныеБлокировки);
КонецЕсли;
Если ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный Тогда
ДанныеБлокировки = сткДанныеБлокировки.Исключительные;
ИначеЕсли ЭлементБлокировки.Режим = РежимБлокировкиДанных.Разделяемый Тогда
ДанныеБлокировки = сткДанныеБлокировки.Разделяемые;
Иначе
ВызватьИсключение "Неизвестный режим блокировки";
КонецЕсли;
Если ЭлементБлокировки.ИсточникДанных = Неопределено Тогда
стк = Новый Структура;
Для каждого Поле Из ЭлементБлокировки.Поля Цикл
стк.Вставить(Поле.Поле, Поле.Значение);
КонецЦикла;
ДанныеБлокировки.Добавить(стк);
Иначе
СоответствиеПолей = Новый Соответствие;
Для каждого Поле Из ЭлементБлокировки.Поля Цикл
СоответствиеПолей.Вставить(Поле.КолонкаИсточникаДанных, Поле.Поле);
КонецЦикла;
Если ТипЗнч(ЭлементБлокировки.ИсточникДанных) = Тип("ТаблицаЗначений") Тогда
ИсточникДанных = ЭлементБлокировки.ИсточникДанных;
ИначеЕсли ТипЗнч(ЭлементБлокировки.ИсточникДанных) = Тип("РезультатЗапроса") Тогда
ИсточникДанных = ЭлементБлокировки.ИсточникДанных.Выгрузить();
ИначеЕсли СтрНайти(ТипЗнч(ЭлементБлокировки.ИсточникДанных), "ДокументТабличнаяЧасть") > 0 Тогда
ИсточникДанных = ЭлементБлокировки.ИсточникДанных.Выгрузить();
Иначе
ВызватьИсключение "Неизвестный тип источника данных блокировки";
КонецЕсли;
Для каждого Стр Из ИсточникДанных Цикл
стк = Новый Структура;
Для каждого КЗ Из СоответствиеПолей Цикл
стк.Вставить(КЗ.Значение, Стр[КЗ.Ключ]);
КонецЦикла;
ДанныеБлокировки.Добавить(стк);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат ДанныеБлокировкиВсеОбласти;
КонецФункции
Процедура СообщитьОКонфликте(сткЭлементБлокировки1, сткЭлементБлокировки2)
Сообщить("Конфликт элементов блокировок:");
Текст = Новый Массив;
Для каждого КЗ Из сткЭлементБлокировки1 Цикл
Если ТипЗнч(КЗ.Значение) = Тип("Диапазон") Тогда
Текст.Добавить(СтрШаблон("%1 = (%2 - %3)", КЗ.Ключ, КЗ.Значение.Начало, КЗ.Значение.Конец));
Иначе
Текст.Добавить(СтрШаблон("%1 = %2", КЗ.Ключ, КЗ.Значение));
КонецЕсли;
КонецЦикла;
Сообщить("1: " + СтрСоединить(Текст, "; "));
Текст = Новый Массив;
Для каждого КЗ Из сткЭлементБлокировки2 Цикл
Если ТипЗнч(КЗ.Значение) = Тип("Диапазон") Тогда
Текст.Добавить(СтрШаблон("%1 = (%2 - %3)", КЗ.Ключ, КЗ.Значение.Начало, КЗ.Значение.Конец));
Иначе
Текст.Добавить(СтрШаблон("%1 = %2", КЗ.Ключ, КЗ.Значение));
КонецЕсли;
КонецЦикла;
Сообщить("2: " + СтрСоединить(Текст, "; "));
КонецПроцедуры
@240596448
Copy link
Author

Программно вычисляет конфликт двух объектов "Новый БлокировкаДанных".

  • Учитывает, что в блокировке могут быть разные области(регионы/регистры/таблицы).
  • Учитывает, что часть блокировок может иметь разделяемый режим.
  • Умеет обрабатывать источник данных
  • Умеет обрабатывать диапазоны значений

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment