Фильтр по CustomSQLColumn

Здравствуйте. Такая проблема: не фильтруется датасет по CustomSQLColumn.
Попробовал сделать через OnQuickFilter, как советовали в https://community.terrasoft.ru/blogs/4397 , тоже не работает.
Как заставить его работать? В таблице дублировать данные очень нежелательно.
Спасибо.

Нравится

17 комментариев

Здравствуйте, Ринат!

Если он пустой, значит, он фильтруется. Просто не совпадают значения и содержимое.

Если бы он не фильтровался - тогда бы просто всегда вверху было первое значение.

Рекомендую Вам просто вывести рядом значение, по которому фильтруете, и значение датасета, которое хотите отфильтровать. Вероятнее всего, несовпадение синтаксиса.

Как альтернативный вариант, оберните CustomSQLColumn в subselect. Есть такая небольшая недокументированная фича. :) Т.е. создаете в SelectQuery подзапрос по таблице, у которой по любому есть только одна запись (лучше создать такую и добавить в нее одну запись). Потом в подзапросе добавляете CustomSQLColumn и реализуете в ней все, что хотите. И все. Далее в ядре подзапрос успешно "оборачивается" и при выполнении сортировки, и фильтраций, и при использовании итогов по нему. Можете проверить этот вариант (просто не во всех версиях он работает).

Через subquery не получилось.
SelectQuery формируется правильно, но по-моему параметр не передаётся в запрос

...
WHERE 
("tbl_Houses"."HouseAddress" || "tbl_Incident"."Flat" like '%' || :pFullAddress_U || '%')

В террасофте параметр FullAddress создан, значение ему присваивается.
Вызывается так:

function grdDataOnQuickFilter(DataGrid, DataField, Value, QuickFilterLikeType, DoFilter, DoQuickFilter) {
	debugger;
	if(DataField.Name == 'FullAddress')
	{	
		var Dataset = DataGrid.DatasetLink.Dataset;
		ApplyDatasetFilter(Dataset, 'FullAddress', Value, true);

Для того, чтобы фильтр отработал, необходимо выполнить запрос, то есть, обновить датасет. То есть, закрыть его и открыть заново.

То есть, после

var Dataset = DataGrid.DatasetLink.Dataset;
ApplyDatasetFilter(Dataset, 'FullAddress', Value, true);

добавить

Dataset.Close();
Dataset.Open();

Всё равно пусто.
Копирую сформированный SelectQuery из дебага, подставляю на место :pFullAddress реальный адрес 'Лермонтова', SelectQuery работает.
Может, мне Пользовательский SQL-фильтр переписать? Как-нибудь параметр по-другому передавать?
Сейчас он такой:

UPPER("tbl_Houses"."HouseAddress" || "tbl_Incident"."Flat") like '%' || :pFullAddress_U || '%'

Ринат, рекомендую Вам посмотреть профайлером.

Что касается фильтра, рекомендую Вам попробовать следующую конструкцию:

UPPER("tbl_Houses"."HouseAddress" || "tbl_Incident"."Flat") LIKE '%' + :pFullAddress_U + '%'

У нас Oracle, плюсы не работают :)

А что в итоге идет в базу данных? Пробовали смотреть запросы профайлером?

Что касается объединения строк, Можете попробовать так:

CONCAT(CONCAT('%', :pFullAddress_U)), '%')

Спасибо, но так тоже не работает :(

Не пойму, зачем Вы фильтр накладываете на OnQuickFilter, т.е. после того, как пользователь в гриде уже применил быстрый фильтр. Т.е. датасет уже открылся и уже что-то делать поздно. По моему, мы не туда "копаем". Можете описать задачу детальнее?

Есть такой вот Пользовательский SQL-фильтр в sq_Incidents:

UPPER("tbl_Houses"."HouseAddress" || "tbl_Incident"."Flat") LIKE '%' || :pFullAddress_U || '%'

В датасет он попадает, но датасет по нему не фильтруется, т.к. не всё так просто с этим фильртом, он берёт "адрес дома" из объединённой таблицы и конкатенирует с "квартирой" из основной.
(Сам инцидент привязывается к ID дома, на котором он произошёл, но также важен поиск по полному адресу)
Есть параметр FullAddress (:pFullAddress).

Наверное, всё же придётся дублировать данные в таблице инцидентов...

Просто в сабже Вы писали о CustomSQLColumn и я решил, что Вам нужна возможность фильтрации по такой колонке. Ладно.
1. Согласно Вашего sql-запроса параметр должен называться FullAddress_U, а не FullAddress. Наша engine потом сама добавит при анализе запроса :p и получится :pFullAddress_U.
2. В SQLMonitor-е как запрос целиком отображается (вместе с параметрами и их значениями)?

Вот отрывок трейс-файла оракл, назвал параметр FullAddress_U без :p

*** 2012-01-20 03:58:07.109
CLOSE #139785163541904:c=0,e=13,dep=0,type=3,tim=1327010287108998
PARSE #139785163540784:c=0,e=241,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=376016973,tim=1327010287109350
EXEC #139785163540784:c=1000,e=136,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=376016973,tim=1327010287109521
FETCH #139785163540784:c=2000,e=2200,p=0,cr=144,cu=0,mis=0,r=1,dep=0,og=1,plh=376016973,tim=1327010287111884
FETCH #139785163540784:c=0,e=150,p=0,cr=0,cu=0,mis=0,r=39,dep=0,og=1,plh=376016973,tim=1327010287114409
CLOSE #139785163540784:c=0,e=11,dep=0,type=3,tim=1327010287399713
=====================
PARSING IN CURSOR #139785163649936 len=3226 dep=0 uid=478 oct=3 lid=479 tim=1327010287400513 hv=2088716702 ad='953aafc0' sqlid='d3dkqjty7ykcy'
SELECT
	"ID",
	"IncidentNumber",
	"AccountID",
	"ActualDueDate",
	"ContactID",
	"Date",
	"DueDate",
	"IncidentTypeID",
	"IncidentTypeName",
	"OfferingID",
	"OwnerID",
	"OwnerName",
	"PriorityID",
	"StatusID",
	"StatusName",
	"Synopsis",
	"StatusIsFinish",
	"ResponseLastDate",
	"ResponseDelay",
	"HouseAddressText",
	"Flat",
	"FullAddress",
	"HouseRegion",
	"HouseRegionName"
FROM (
SELECT 
	"tbl_Incident"."ID" "ID",
	"tbl_Incident"."IncidentNumber" "IncidentNumber",
	"tbl_Incident"."AccountID" "AccountID",
	"tbl_Incident"."ActualDueDate" "ActualDueDate",
	"tbl_Incident"."ContactID" "ContactID",
	"tbl_Incident"."Date" "Date",
	"tbl_Incident"."DueDate" "DueDate",
	"tbl_Incident"."IncidentTypeID" "IncidentTypeID",
	"tbl_IncidentType"."Name" "IncidentTypeName",
	"tbl_Incident"."OfferingID" "OfferingID",
	"tbl_Incident"."OwnerID" "OwnerID",
	"Owner"."Name" "OwnerName",
	"tbl_Incident"."PriorityID" "PriorityID",
	"tbl_Incident"."StatusID" "StatusID",
	"tbl_IncidentStatus"."Name" "StatusName",
	"tbl_Incident"."Synopsis" "Synopsis",
	"tbl_IncidentStatus"."IsFinish" "StatusIsFinish",
	"tbl_Incident"."ResponseLastDate" "ResponseLastDate",
	"tbl_Incident"."ResponseDelay" "ResponseDelay",
	"tbl_Houses"."HouseAddress" "HouseAddressText",
	"tbl_Incident"."Flat" "Flat",
	case when "tbl_Houses"."HouseAddress" like '%(%' 
then
	replace(
	replace("tbl_Houses"."HouseAddress", ')', (case when "tbl_Incident"."Flat" is null or "tbl_Incident"."Flat" = 0 then '' else '-' end) || "tbl_Incident"."Flat" || ')'), '(', 
	(case when "tbl_Incident"."Flat" is null or "tbl_Incident"."Flat" = '0'
	then '' else '-' end) || "tbl_Incident"."Flat" || '('
	)
else 
	("tbl_Houses"."HouseAddress" || (case when "tbl_Incident"."Flat" is null or "tbl_Incident"."Flat" = '0' then '' else '-' end) || "tbl_Incident"."Flat")
end
 "FullAddress",
	"tbl_Houses"."HouseRegion" "HouseRegion",
	(SELECT 
"tbl_Regions"."RegionName" "RegionName"
FROM 
"TS"."tbl_Regions" "tbl_Regions"
WHERE ("tbl_Regions"."ID" = "tbl_Houses"."HouseRegion"))  "HouseRegionName"
FROM 
	"TS"."tbl_Incident" "tbl_Incident"
LEFT OUTER JOIN
	"TS"."tbl_Contact" "Owner" ON "Owner"."ID" = "tbl_Incident"."OwnerID"
LEFT OUTER JOIN
	"TS"."tbl_IncidentType" "tbl_IncidentType" ON "tbl_IncidentType"."ID" = "tbl_Incident"."IncidentTypeID"
LEFT OUTER JOIN
	"TS"."tbl_IncidentStatus" "tbl_IncidentStatus" ON "tbl_IncidentStatus"."ID" = "tbl_Incident"."StatusID"
LEFT OUTER JOIN
	"TS"."tbl_Houses" "tbl_Houses" ON "tbl_Houses"."ID" = "tbl_Incident"."HouseID"
LEFT OUTER JOIN
	"TS"."tbl_CableType" "tbl_CableType" ON "tbl_CableType"."ID" = "tbl_Incident"."CableType"
WHERE ((case when "tbl_Houses"."HouseAddress" like '%(%' 
then
	replace(
	replace("tbl_Houses"."HouseAddress", ')', (case when "tbl_Incident"."Flat" is null or "tbl_Incident"."Flat" = 0 then '' else '-' end) || "tbl_Incident"."Flat" || ')'), '(', 
	(case when "tbl_Incident"."Flat" is null or "tbl_Incident"."Flat" = '0'
	then '' else '-' end) || "tbl_Incident"."Flat" || '('
	)
else 
	("tbl_Houses"."HouseAddress" || (case when "tbl_Incident"."Flat" is null or "tbl_Incident"."Flat" = '0' then '' else '-' end) || "tbl_Incident"."Flat")
end
 LIKE '%' || :pFullAddress5_U || '%'))
ORDER BY
	22 ASC
)
 WHERE ROWNUM <= 40
END OF STMT
PARSE #139785163649936:c=0,e=682,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=1327010287400512 

Судя по всему, параметр вообще не присваивается.

Хм. Наконец разобрался, как оно работает.
Terrasoft игнорирует любые мои параметры, фильтры, берёт код CustomSQL Column и подставляет (почему-то без UPPER()) его в WHERE, сравнивая с параметром (для которого не забывает сделать UPPER())
A OnQuickFilter срабатывает уже после того, как датасет отфильтрован.

Сейчас получилось сделать с UPPER адресами. Хотя можно уже в гриде их попробовать уменьшить.
Т.е. в Custom SQL Column дописал UPPER(...) и заработало.

А можно как-нибудь сделать, чтобы CustomSQL Column отображался без UPPER, а в фильтре оно проставлялось?
Или отображалось CustomSQL Column, а фильтровалось по другой колонке?

Здравствуйте, Ринат.

Поведение CustomSQL Column определяется бинарными файлами системы, и необходима доработка ядра для того, чтобы изменить их поведение.

Фильтровать по другой колонке действительно можно, но в таком случае Вам необходимо будет это делать непосредственно из кода, а не в запросе.

Здравствуйте Ринат,
Предлагаю другой вариант, создайте View с ID таблицы tbl_Incident, добавьте логику конкатенации. Добавьте эту View в Terrasoft (создайте сервис таблицы, укажите колонки, как в View на базе данных, на вопрос "Создать ли таблицу в БД" ответьте "Нет", проверьте таблицу создав к ней SelectQuary), добавьте таблицу View в запрос, свяжите ее с основной таблицей, после чего попробуйте использовать параметры

Показать все комментарии