using System;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
using Microsoft.SqlServer.Server;
[Serializable]
[SqlUserDefinedAggregate(
Format.UserDefined, // Binary Serialization because of StringBuilder
IsInvariantToOrder = false, // order changes the result
IsInvariantToNulls = true, // nulls don't change the result
IsInvariantToDuplicates = false, // duplicates change the result
MaxByteSize = -1
)]
public struct StringConcat : IBinarySerialize
{
private StringBuilder _accumulator;
private string _delimiter;
/// <summary>
/// IsNull property
/// </summary>
public Boolean IsNull { get; private set; }
#region IBinarySerialize Members
/// <summary>
/// Deserialize from the reader to recreate the struct
/// </summary>
/// <param name = "r">BinaryReader</param>
void IBinarySerialize.Read(BinaryReader r)
{
_delimiter = r.ReadString();
_accumulator = new StringBuilder(r.ReadString());
if (_accumulator.Length != 0) IsNull = false;
}
/// <summary>
/// Serialize the struct.
/// </summary>
/// <param name = "w">BinaryWriter</param>
void IBinarySerialize.Write(BinaryWriter w)
{
w.Write(_delimiter);
w.Write(_accumulator.ToString());
}
#endregion
public void Init()
{
_accumulator = new StringBuilder();
_delimiter = string.Empty;
IsNull = true;
}
public void Accumulate(SqlString value, SqlString delimiter)
{
if (value.IsNull) return;
if (!delimiter.IsNull && delimiter.Value.Length > 0)
{
if (_delimiter == String.Empty) _delimiter = delimiter.Value;
if (_accumulator.Length > 0) _accumulator.Append(delimiter.Value);
}
_accumulator.Append(value.Value);
IsNull = false;
}
/// <summary>
/// Merge onto the end
/// </summary>
/// <param name = "group"></param>
public void Merge(StringConcat group)
{
// add the delimiter between strings
if (_accumulator.Length > 0 && group._accumulator.Length > 0)
{
if (String.IsNullOrEmpty(_delimiter))
_delimiter = group._delimiter;
_accumulator.Append(_delimiter);
}
_accumulator.Append(group._accumulator.ToString());
}
public SqlString Terminate()
{
var result = _accumulator.ToString();
return String.IsNullOrEmpty(result) ? new SqlString(null) : new SqlString(_accumulator.ToString());
}
}