Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 CLR UDA SqlUserDefinedAggregateAttribute  [new]
felix_ff
Member

Откуда: Moscow
Сообщений: 1914
Доброго времени суток.

Народ, что то лыжи не едут:

+ UDA

using System;
using System.Data;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;

namespace UDA
{
    [Serializable]
    [SqlUserDefinedAggregate(Microsoft.SqlServer.Server.Format.UserDefined, IsInvariantToNulls=true, IsInvariantToDuplicates=true, MaxByteSize=-1)]
    public class GroupConcatSimple:IBinarySerialize
    {
        SqlString line;
        SqlString accvalues;

        public void Init()
        {
            line = new SqlString("");
            accvalues = new SqlString("");
        }

        public void Accumulate(SqlString value, SqlString delim) {
            if (!value.IsNull)
                line = String.Concat(line.Value, value.Value, delim.IsNull ? "," : delim.Value);

            accvalues = String.Concat(accvalues.Value, value.IsNull ? "NONE" : value.Value, "/");
        }

        public void Merge(GroupConcatSimple instance) {
            if (instance.line != null) String.Concat(line, instance.line);
        }

        public SqlString Terminate() {
            if (line.IsNull) return SqlString.Null;
            return new SqlString(line.Value + "\n" + accvalues.Value);
        }



        public void Read(BinaryReader r)
        {
            line = new SqlString(r.ReadString());
            accvalues = new SqlString(r.ReadString());
        }

        public void Write(BinaryWriter w)
        {
            w.Write(line.Value);
            w.Write(accvalues.Value);
        }
    }
}



if exists (select 1 from sys.objects where name like 'cn') drop aggregate cn
if exists (select 1 from sys.assemblies where name like 'sx') drop assembly sx

create assembly sx from 'C:\temp\UDA\UDA.dll'
go
create aggregate cn (@expr nvarchar(max), @delim nvarchar(255)) returns nvarchar(max)
external name sx.[UDA.GroupConcatSimple]
go


declare @t table (id int identity(1,1), value varchar(255), gr int)
declare @t2 table (rowID int primary key clustered, id int, val varchar(255), gr int)

insert into @t (value, gr) values ('this', 1), (null, 1), ('this', 1), ('is', 1), ('test', 1), ('of', 1), ('groupconcat', 1), ('group:', 1), ('1', 1)
insert into @t (value, gr) values (null, 2), (null, 2), ('this', 2), ('is', 2), ('test', 2), ('of', 2), ('groupconcat', 2), ('group:', 2), ('2', 2), (null, 2)

select * from @t

insert into @t2 
select row_number() over (order by id asc), * from @t

select dbo.cn(val, ' ') from @t2 group by gr


результат:
this this is test of groupconcat group: 1 
this/NONE/this/is/test/of/groupconcat/group:/1/
this is test of groupconcat group: 2 
NONE/NONE/this/is/test/of/groupconcat/group:/2/NONE/


внимание вопрос:
С какого хера при свойстве атрибута IsInvariantToNulls=true эта херня все равно учитывает NULL значения?
Да и дубликаты при IsInvariantToDublicates тоже.

Такое впечатление что серверу вообще по барабану что я там в свойствах указал кроме формата сериализации.

Microsoft SQL Server 2014 - 12.0.2000.8 (X64)
Feb 20 2014 20:04:26
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
19 янв 17, 23:58    [20125131]     Ответить | Цитировать Сообщить модератору
 Re: CLR UDA SqlUserDefinedAggregateAttribute  [new]
felix_ff
Member

Откуда: Moscow
Сообщений: 1914
А главное нигде не могу найти толковое объяснение что же происходит когда параметры данного атрибута IsInvariant... меняются.

В БОЛ ватное описание: блаблабла влияют на поведение квери процессора. Что там он по другому считать начинает хз. Уже все половину буржуйских форумов облазил.
20 янв 17, 00:17    [20125162]     Ответить | Цитировать Сообщить модератору
 Re: CLR UDA SqlUserDefinedAggregateAttribute  [new]
invm
Member

Откуда: Москва
Сообщений: 9913
felix_ff
С какого хера при свойстве атрибута IsInvariantToNulls=true эта херня все равно учитывает NULL значения?
Атрибут означает, что ваша функция не учитывает NULL'ы, а не то, что NULL'ы ей вообще передаваться не будут.
20 янв 17, 00:33    [20125180]     Ответить | Цитировать Сообщить модератору
 Re: CLR UDA SqlUserDefinedAggregateAttribute  [new]
felix_ff
Member

Откуда: Moscow
Сообщений: 1914
invm,

поясните что значит "моя функция не учитывает"?

ну да я дествительно в коде могу явную проверку делать как в случае ксати с первой частью возвращаемых значений по line,
но тогда собственно какой смысл в параметре атрибута?

Ранее я предполагал что в коде более низкого уровня сервера зашита некая проверка, проверяющая значения атрибутов функции и видя что ей присвоено значение игнорировать значения null, она не будет передавать их в методы обработчики.
Однако проверка такого результата не дала. Тогда мне не понятно на что именно влияют значения?

Я мог бы зашить в коде поведение игнорирования значений null жестко и при этом выставить IsInvariantToNulls = false результат бы не изменился.
20 янв 17, 01:23    [20125235]     Ответить | Цитировать Сообщить модератору
 Re: CLR UDA SqlUserDefinedAggregateAttribute  [new]
felix_ff
Member

Откуда: Moscow
Сообщений: 1914
Уточню:
Used by the query processor, this property is true if the aggregate is invariant to nulls. That is, the aggregate of S, {NULL} is the same as aggregate of S. For example, aggregate functions such as MIN and MAX satisfy this property, while COUNT(*) does not.


Вот мне интересно именно в каком плане: Used by the query processor?
20 янв 17, 01:28    [20125237]     Ответить | Цитировать Сообщить модератору
 Re: CLR UDA SqlUserDefinedAggregateAttribute  [new]
felix_ff
Member

Откуда: Moscow
Сообщений: 1914
вот нарыл чтото более менее интересное https://www.google.com/patents/US7376656

включая картинку того как раз как я себе представлял поведение "как оно должно быть"

+ картинка

Картинка с другого сайта.


но практика показала другое, что и вызывает вопросы :(
20 янв 17, 01:59    [20125248]     Ответить | Цитировать Сообщить модератору
 Re: CLR UDA SqlUserDefinedAggregateAttribute  [new]
iljy
Member

Откуда:
Сообщений: 8711
felix_ff
Уточню:
Used by the query processor, this property is true if the aggregate is invariant to nulls. That is, the aggregate of S, {NULL} is the same as aggregate of S. For example, aggregate functions such as MIN and MAX satisfy this property, while COUNT(*) does not.


Вот мне интересно именно в каком плане: Used by the query processor?


В том плане, что оптимизатор может это свойство функции учитывать при построении плана (может передавать NULL, может не передавать), но никаких обязательств на него не накладывает.
20 янв 17, 02:32    [20125268]     Ответить | Цитировать Сообщить модератору
 Re: CLR UDA SqlUserDefinedAggregateAttribute  [new]
iljy
Member

Откуда:
Сообщений: 8711
felix_ff
вот нарыл чтото более менее интересное https://www.google.com/patents/US7376656

включая картинку того как раз как я себе представлял поведение "как оно должно быть"

+ картинка

Картинка с другого сайта.


но практика показала другое, что и вызывает вопросы :(


Данная картинка как раз показывает как вы должны реализовать вашу функцию, чтобы она удовлетворяла декларируемому свойству.
20 янв 17, 02:33    [20125270]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить