Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема Проблема с перехватом через vk_Hook1C.dll при использовании графы отбора (число прочтений - 3674 )
newbas
Junior Member
**
Отсутствует



Сообщений: 32
Местоположение: Краснодар
Зарегистрирован: 29. Августа 2008
Пол: Мужской
Проблема с перехватом через vk_Hook1C.dll при использовании графы отбора
04. Января 2011 :: 23:15
Печать  
Собственное, общий журнал в стандартном ТиС, база на SQL 2005 переделывается на множественный фильтр при помощи перехвата SQL запросов компонентой vk_Hook1C.dll. При установке отбора вызывается

Код
Выбрать все
	УстановитьОтбор("Поступление");
	vk_hook.ВызватьСобытие("vk_hook","Отбор","Журнал");
 



Сама процедура ОбработкаВнешнегоСобытия

Код
Выбрать все
Процедура ОбработкаВнешнегоСобытия(прм_Источник,прм_Событие,прм_Данные)
	Если (прм_Источник="vk_hook") и (прм_Событие="Отбор")  Тогда
		стр	= "";

		Если флУдаленные = 1 Тогда
			стр=стр+"ISMARK='0' and ";
		КонецЕсли;

		// Проверим, отбор чего установлен
		Если ВыбФирма.Выбран() = 1 Тогда
			стр	= стр + МетаПарсер.ОбрМетаСКЛ("$ОбщийРеквизит.Фирма='"+глПолучитьИД(ВыбФирма)+"' and ");
		КонецЕсли;

		Если Форма.ИспользоватьЗакладки() = 1 Тогда
			Если Форма.Закладки.ТекущаяСтрока() > 1  Тогда
				врПодсистема	= Форма.Закладки.ПолучитьЗначение(Форма.Закладки.ТекущаяСтрока());
				стр	= стр + ' and ");
			КонецЕсли;
		КонецЕсли;

		Если ВидОтбора.ТекущаяСтрока()>0 Тогда
			// Есть отбор
			ОтборПо           = ВидОтбора.ПолучитьЗначение(ВидОтбора.ТекущаяСтрока());

			Если ОтборПо = "по виду документов" Тогда
				Если ВидДокументаДляОтбора <> 0 Тогда
					ВидДока	= СписокВидовДокументов.ПолучитьЗначение(ВидДокументаДляОтбора);
					стр	= стр + МетаПарсер.ОбрМетаСКЛ("IDDOCDEF = $ВидДокумента."+ВидДока+" and ");
				КонецЕсли;
			ИначеЕсли ОтборПо = "по автору" Тогда
				Если ПустоеЗначение(АвторДляОтбора) = 0 Тогда
					стр	= стр + МетаПарсер.ОбрМетаСКЛ("$ОбщийРеквизит.Автор='"+глПолучитьИД(АвторДляОтбора)+"' and ");
				КонецЕсли;
			ИначеЕсли ОтборПо = "по проекту" Тогда
				Если ПустоеЗначение(ПроектДляОтбора) = 0 Тогда
					стр	= стр +  and ");
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;

		ОтборПоГрафе = "";

		Если ОтборПо = "по контрагенту" Тогда  
			Если КонтрагентДляОтбора.Выбран() = 1 Тогда
				ОтборПоГрафе = МетаПарсер.ОбрМетаСКЛ(" INNER JOIN _1SCRDOC Отбор1 ON  Отбор1.ChildID = _1SJOURN.IDDoc AND Отбор1.MDID = $ГрафаОтбора.Контрагент AND Отбор1.ParentVal = '"+глПолучитьИД(КонтрагентДляОтбора)+"'");
			КонецЕсли;

		ИначеЕсли ОтборПо = "по складу" Тогда
			Если ПустоеЗначение(СкладДляОтбора) = 0 Тогда
				ОтборПоГрафе = ОтборПоГрафе+МетаПарсер.ОбрМетаСКЛ(" INNER JOIN _1SCRDOC Отбор2 ON  Отбор2.ChildID = _1SJOURN.IDDoc AND Отбор2.MDID = $ГрафаОтбора.Склад AND Отбор2.ParentVal = '"+глПолучитьИД(СкладДляОтбора)+"'");
			КонецЕсли;

		ИначеЕсли ОтборПо = "по менеджеру" Тогда  
			ОтборПоГрафе = ОтборПоГрафе+МетаПарсер.ОбрМетаСКЛ(" INNER JOIN _1SCRDOC Отбор3 ON  Отбор3.ChildID = _1SJOURN.IDDoc AND Отбор3.MDID = $ГрафаОтбора.Менеджер2 AND Отбор3.ParentVal = '"+глПолучитьИД(глПользователь)+"'");
		КонецЕсли;

		глХук.ТекстSQL	= "Select * from _1SJOURN(NOLOCK INDEX=ACDATETIME) where DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC<=? order by DATE_TIME_IDDOC";
		глХук.НовыйSQL	= "Select * from _1SJOURN(NOLOCK INDEX=ACDATETIME) "+ОтборПоГрафе+" where "+стр+" DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC<=? order by DATE_TIME_IDDOC";
		глХук.УстановитьЗаменуSQL();

		глХук.ТекстSQL	= "Select COUNT(*) from _1SJOURN(NOLOCK) where  (DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC<=?) and DATE_TIME_IDDOC<=?";
		глХук.НовыйSQL	= "Select COUNT(*) from _1SJOURN(NOLOCK) "+ОтборПоГрафе+" where "+стр+" (DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC<=?) and DATE_TIME_IDDOC<=?";
		глХук.УстановитьЗаменуSQL();
		УстановитьОтбор("");
	Иначе
		Сообщить(""+прм_Источник+" "+прм_Событие+" "+прм_Данные);
	КонецЕсли;
КонецПроцедуры 



При установке фильтров по общим реквизитам никаких проблем - все работает на ура. А при выборе фильтра по любой из граф отбора "Склад", "Контрагент" или "Менеджер2" происходит следующее:
1). Данные фильтруются
2) Через где-то >0,5 сек таблица становится пустой, т.е. как будто запрос возвращает пустую выборку
В чем ошибка?
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: Проблема с перехватом через vk_Hook1C.dll при использовании графы отбора
Ответ #1 - 05. Января 2011 :: 21:11
Печать  
Прогони текст запроса в квери аналайзере.
Вполне возможно, что оптимизатор решил идти по индексу в _1scrdoc.
И nolock для таблицы ссылок ты не поставил.
Лучше отбор по графам вынести в where:
Код
Выбрать все
"and iddoc in (select childid from _1scrdoc Ref (nolock) where Ref.MDID = $ГрафаОтбора.Контрагент AND Ref.ParentVal = '" + МетаПарсер.ЗначениеВСамуюДлиннуюСтрокуБД(КонтрагентДляОтбора) + "')"
 


Ну и значение для parentval неправильно подставляешь. Там нужна строка 23 символа - представление значения типа "Неопределенный"
  
Наверх
 
IP записан
 
newbas
Junior Member
**
Отсутствует



Сообщений: 32
Местоположение: Краснодар
Зарегистрирован: 29. Августа 2008
Пол: Мужской
Re: Проблема с перехватом через vk_Hook1C.dll при использовании графы отбора
Ответ #2 - 05. Января 2011 :: 21:15
Печать  
Спасибо, все получилось. Еще добавил удаление перехвата. Код обработки внешнего события

Код
Выбрать все
Процедура ОбработкаВнешнегоСобытия(прм_Источник,прм_Событие,прм_Данные)
	Если (прм_Источник="vk_hook") и (прм_Событие="Отбор") И (прм_Данные = "Журнал") Тогда
		стр	= "";

		Если флУдаленные = 1 Тогда
			стр	= стр+"ISMARK='0' and ";
		КонецЕсли;

		Если ВыбФирма.Выбран() = 1 Тогда
			стр	= стр + МетаПарсер.ОбрМетаСКЛ("$ОбщийРеквизит.Фирма='"+глПолучитьИД(ВыбФирма)+"' and ");
		КонецЕсли;

		Если Форма.ИспользоватьЗакладки() = 1 Тогда
			Если Форма.Закладки.ТекущаяСтрока() > 1  Тогда
				врПодсистема	= Форма.Закладки.ПолучитьЗначение(Форма.Закладки.ТекущаяСтрока());
				Если врПодсистема.Код = "11" Тогда
					// Осуществляем отбор по видам документов
					Спр	= СоздатьОбъект("Справочник.ДокументыПодсистем");
					Спр.ИспользоватьВладельца(врПодсистема.ТекущийЭлемент());
					ЕстьЭлементы	= Спр.ВыбратьЭлементы();
					Если ЕстьЭлементы = 1 Тогда
						стр	= стр + "IDDOCDEF IN (";
						Пока Спр.ПолучитьЭлемент() = 1 Цикл
							ВидДока	= СокрЛП(Спр.Наименование);
							стр		= стр + "'"+МетаПарсер.ОбрМетаСКЛ("$ВидДокумента."+ВидДока+"',");
						КонецЦикла;
						Стр	= Лев(Стр, СтрДлина(Стр)-1)+") and ";
					КонецЕсли;
				Иначе
					стр	= стр + ' and ");
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;

		Если ВидОтбора.ТекущаяСтрока()>0 Тогда
			// Есть отбор
			ОтборПо           = ВидОтбора.ПолучитьЗначение(ВидОтбора.ТекущаяСтрока());

			Если ОтборПо = "по виду документов" Тогда
				Если ВидДокументаДляОтбора <> 0 Тогда
					ВидДока	= СписокВидовДокументов.ПолучитьЗначение(ВидДокументаДляОтбора);
					стр	= стр + МетаПарсер.ОбрМетаСКЛ("IDDOCDEF = $ВидДокумента."+ВидДока+" and ");
				КонецЕсли;
			ИначеЕсли ОтборПо = "по автору" Тогда
				Если ПустоеЗначение(АвторДляОтбора) = 0 Тогда
					стр	= стр + МетаПарсер.ОбрМетаСКЛ("$ОбщийРеквизит.Автор='"+глПолучитьИД(АвторДляОтбора)+"' and ");
				КонецЕсли;
			ИначеЕсли ОтборПо = "по проекту" Тогда
				Если ПустоеЗначение(ПроектДляОтбора) = 0 Тогда
					стр	= стр +  and ");
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;

		ОтборПоГрафе = "";

		Если ОтборПо = "по контрагенту" Тогда  
			Если КонтрагентДляОтбора.Выбран() = 1 Тогда
				ОтборПоГрафе = " iddoc in (
						|select childid from _1scrdoc Ref(nolock)
						|where Ref.MDID = '"+МетаПарсер.ОбрМетаСКЛ("$ГрафаОтбора.Контрагент")+"'
						|and  Ref.ParentVal = '" + МетаПарсер.ЗначениеВСамуюДлиннуюСтрокуБД(КонтрагентДляОтбора) + "'
						|) and
						|";
			КонецЕсли;

		ИначеЕсли ОтборПо = "по складу" Тогда
			Если ПустоеЗначение(СкладДляОтбора) = 0 Тогда
				ОтборПоГрафе = " iddoc in (
						|select childid from _1scrdoc Ref1(nolock)
						|where Ref1.MDID = '"+МетаПарсер.ОбрМетаСКЛ("$ГрафаОтбора.Склад")+"'
						|and  Ref1.ParentVal = '" + МетаПарсер.ЗначениеВСамуюДлиннуюСтрокуБД(СкладДляОтбора) + "'
						|) and
						|";
			КонецЕсли;

		ИначеЕсли ОтборПо = "по менеджеру" Тогда  
				ОтборПоГрафе = " iddoc in (
						|select childid from _1scrdoc Ref2(nolock)
						|where Ref2.MDID = '"+МетаПарсер.ОбрМетаСКЛ("$ГрафаОтбора.Менеджер2")+"'
						|and  Ref2.ParentVal = '" + МетаПарсер.ЗначениеВСамуюДлиннуюСтрокуБД(глПользователь) + "'
						|) and
						|";
		КонецЕсли;
//
		Если ПустаяСтрока(СтарыйОтбор) = 0 Тогда
			глХук.ТекстSQL = СтарыйОтбор;
			глХук.УдалитьЗаменуSQL();
		КонецЕсли;

		глХук.ТекстSQL	= "Select * from _1SJOURN(NOLOCK INDEX=ACDATETIME) where DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC<=? order by DATE_TIME_IDDOC";
		глХук.НовыйSQL	= "Select * from _1SJOURN(NOLOCK INDEX=ACDATETIME) where "+ОтборПоГрафе+стр+" DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC<=? order by DATE_TIME_IDDOC";
		СтарыйОтбор		= глХук.ТекстSQL;
		глХук.УстановитьЗаменуSQL();

		Если ПустаяСтрока(СтарыйКолво) = 0 Тогда
			глХук.ТекстSQL = СтарыйКолво;
			глХук.УдалитьЗаменуSQL();
		КонецЕсли;

		глХук.ТекстSQL	= "Select COUNT(*) from _1SJOURN(NOLOCK) where  (DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC<=?) and DATE_TIME_IDDOC<=?";
		СтарыйКолво		= глХук.ТекстSQL;
		глХук.НовыйSQL	= "Select COUNT(*) from _1SJOURN(NOLOCK) where "+ОтборПоГрафе+стр+" (DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC<=?) and DATE_TIME_IDDOC<=?";
		глХук.УстановитьЗаменуSQL();
		УстановитьОтбор("");
	Иначе
		Сообщить(""+прм_Источник+" "+прм_Событие+" "+прм_Данные);
	КонецЕсли;
КонецПроцедуры 

  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: Проблема с перехватом через vk_Hook1C.dll при использовании графы отбора
Ответ #3 - 10. Января 2011 :: 07:00
Печать  
Кстати, условие можно написать еще оптимальнее:
Код
Выбрать все
" exists (
|select * from _1scrdoc Ref(nolock)
|where Ref.MDID = '"+МетаПарсер.ОбрМетаСКЛ("$ГрафаОтбора.Контрагент")+"'
|and  Ref.ParentVal = '" + МетаПарсер.ЗначениеВСамуюДлиннуюСтрокуБД(КонтрагентДляОтбора) + "'
|and Ref.CHILD_DATE_TIME_IDDOC = _1sjourn.date_time_iddoc
|) and
|";
 


Абсолютное попадание в индекс по _1scrdoc.
  
Наверх
 
IP записан
 
newbas
Junior Member
**
Отсутствует



Сообщений: 32
Местоположение: Краснодар
Зарегистрирован: 29. Августа 2008
Пол: Мужской
Re: Проблема с перехватом через vk_Hook1C.dll при использовании графы отбора
Ответ #4 - 10. Января 2011 :: 07:06
Печать  
Цитата:
Кстати, условие можно написать еще оптимальнее:


Действительно так лучше. Спасибо!
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать