diff --git a/src/Microsoft.SqlServer.Types.Tests/Microsoft.SqlServer.Types.Tests.csproj b/src/Microsoft.SqlServer.Types.Tests/Microsoft.SqlServer.Types.Tests.csproj
index b038d5b..2ce1b9c 100644
--- a/src/Microsoft.SqlServer.Types.Tests/Microsoft.SqlServer.Types.Tests.csproj
+++ b/src/Microsoft.SqlServer.Types.Tests/Microsoft.SqlServer.Types.Tests.csproj
@@ -1,7 +1,7 @@
- net6.0;net461
+ net7.0;net6.0;net461
false
enable
10.0
diff --git a/src/Microsoft.SqlServer.Types/ISqlSpatialGridIndexable.cs b/src/Microsoft.SqlServer.Types/ISqlSpatialGridIndexable.cs
index 2718354..4c28cb5 100644
--- a/src/Microsoft.SqlServer.Types/ISqlSpatialGridIndexable.cs
+++ b/src/Microsoft.SqlServer.Types/ISqlSpatialGridIndexable.cs
@@ -1,4 +1,6 @@
-namespace Microsoft.SqlServer.Types
+using Microsoft.SqlServer.Server;
+
+namespace Microsoft.SqlServer.Types
{
///
/// This API supports the product infrastructure and is not intended to be used directly from your code.
diff --git a/src/Microsoft.SqlServer.Types/Microsoft.SqlServer.Types.csproj b/src/Microsoft.SqlServer.Types/Microsoft.SqlServer.Types.csproj
index 1fc0e6f..83de11d 100644
--- a/src/Microsoft.SqlServer.Types/Microsoft.SqlServer.Types.csproj
+++ b/src/Microsoft.SqlServer.Types/Microsoft.SqlServer.Types.csproj
@@ -9,7 +9,7 @@
true
Debug;Release;Debug_Legacy;Release_Legacy
true
- 5.0
+ 6.0
2.$(MinorVersion)
1.$(MinorVersion)
@@ -47,7 +47,7 @@
- 4.0.0
+ 5.0.1
@@ -56,9 +56,9 @@
-
-
-
+
+
+
@@ -77,10 +77,8 @@
-
-
+
+
diff --git a/src/Microsoft.SqlServer.Types/SqlGeography.cs b/src/Microsoft.SqlServer.Types/SqlGeography.cs
index 06dd5be..aed5553 100644
--- a/src/Microsoft.SqlServer.Types/SqlGeography.cs
+++ b/src/Microsoft.SqlServer.Types/SqlGeography.cs
@@ -1,3 +1,5 @@
+using Microsoft.SqlServer.Server;
+
namespace Microsoft.SqlServer.Types
{
///
@@ -11,10 +13,10 @@ public class SqlGeography : INullable, IBinarySerialize
internal SqlGeography(bool isNull) { IsNull = isNull; }
- internal SqlGeography(ShapeData g, int srid)
- {
- this.srid = srid;
- this._geometry = g;
+ internal SqlGeography(ShapeData g, int srid)
+ {
+ this.srid = srid;
+ this._geometry = g;
}
///
@@ -170,14 +172,14 @@ public static SqlGeography Null {
/// This method will return NULL if this is not a Polygon instance and will return 0 if the instance is empty.
///
/// In the SQL Server geography type, external and internal rings are not distinguished, as any ring can be taken to be the external ring.
- [SqlMethod(IsDeterministic = true, IsPrecise = true)]
- public SqlInt32 NumRings()
+ [SqlMethod(IsDeterministic = true, IsPrecise = true)]
+ public SqlInt32 NumRings()
{
if (IsNull || (_geometry.Type != OGCGeometryType.Polygon && _geometry.Type != OGCGeometryType.CurvePolygon))
- {
- return SqlInt32.Null;
- }
- return this._geometry.NumRings;
+ {
+ return SqlInt32.Null;
+ }
+ return this._geometry.NumRings;
}
///
@@ -225,19 +227,19 @@ public SqlInt32 STNumCurves()
{
if (IsNull || _geometry.IsEmpty) return SqlInt32.Null;
- if (_geometry.Type == OGCGeometryType.LineString)
- return _geometry.IsEmpty ? 0 : _geometry.NumPoints - 1;
+ if (_geometry.Type == OGCGeometryType.LineString)
+ return _geometry.IsEmpty ? 0 : _geometry.NumPoints - 1;
- if (_geometry.Type == OGCGeometryType.CircularString)
+ if (_geometry.Type == OGCGeometryType.CircularString)
{
if (_geometry.IsEmpty) return 0;
return (_geometry.NumPoints - 1) / 2;
}
if(_geometry.Type == OGCGeometryType.Polygon)
- return _geometry.NumRings;
+ return _geometry.NumRings;
if (_geometry.Type != OGCGeometryType.CompoundCurve)
return SqlInt32.Null;
- return _geometry.NumRings;
+ return _geometry.NumRings;
}
///
@@ -252,7 +254,7 @@ public SqlInt32 STNumCurves()
[SqlMethod(IsDeterministic = true, IsPrecise = true)]
public SqlGeography STGeometryN(int n)
{
- if (n < 1)
+ if (n < 1)
throw new ArgumentOutOfRangeException(nameof(n));
if (IsNull || n > STNumGeometries())
@@ -291,24 +293,24 @@ public SqlGeography STCurveN(int n)
///
public SqlGeography STPointN(int n)
{
- if (n < 1)
- throw new ArgumentOutOfRangeException(nameof(n));
- if (IsNull)
- return SqlGeography.Null;
-
- if (n > this._geometry.NumPoints)
- return SqlGeography.Null;
-
- var p = _geometry.GetPointN(n);
+ if (n < 1)
+ throw new ArgumentOutOfRangeException(nameof(n));
+ if (IsNull)
+ return SqlGeography.Null;
+
+ if (n > this._geometry.NumPoints)
+ return SqlGeography.Null;
+
+ var p = _geometry.GetPointN(n);
return new SqlGeography(new ShapeData(p.X, p.Y, HasZ ? (double?)p.Z : null, HasM ? (double?)p.M : null), srid);
}
-
+
///
/// Returns the start point of a SqlGeography instance.
///
- /// A SqlGeography value that represents the start point of the calling SqlGeography.
- /// STStartPoint is the equivalent of STPointN(1).
- [SqlMethod(IsDeterministic = true, IsPrecise = true)]
+ /// A SqlGeography value that represents the start point of the calling SqlGeography.
+ /// STStartPoint is the equivalent of STPointN(1).
+ [SqlMethod(IsDeterministic = true, IsPrecise = true)]
public SqlGeography STStartPoint() => this.STPointN(1);
// public SqlGeography STUnion(SqlGeography sqlGeography)
@@ -324,8 +326,8 @@ public SqlGeography STPointN(int n)
/// STEndPoint is the equivalent of SqlGeography.STPointN(x.STNumPoints()).
/// This method returns null if called on an empty geography instance.
///
- [SqlMethod(IsDeterministic = true, IsPrecise = true)]
- public SqlGeography STEndPoint() => STPointN(Math.Max(1, _geometry.NumPoints));
+ [SqlMethod(IsDeterministic = true, IsPrecise = true)]
+ public SqlGeography STEndPoint() => STPointN(Math.Max(1, _geometry.NumPoints));
///
/// Returns the specified ring of the SqlGeography instance: 1 ≤ n ≤ NumRings().
@@ -338,14 +340,14 @@ public SqlGeography STPointN(int n)
[SqlMethodAttribute(IsDeterministic = true, IsPrecise = true)]
public SqlGeography RingN(int n)
{
- if (n < 1)
+ if (n < 1)
throw new ArgumentOutOfRangeException(nameof(n));
- if (IsNull || (_geometry.Type != OGCGeometryType.Polygon && _geometry.Type != OGCGeometryType.CurvePolygon) || n > this._geometry.NumRings)
- {
- return SqlGeography.Null;
- }
- ShapeData ring = _geometry.GetRing(n - 1);
- ring.SetIsValid(false);
+ if (IsNull || (_geometry.Type != OGCGeometryType.Polygon && _geometry.Type != OGCGeometryType.CurvePolygon) || n > this._geometry.NumRings)
+ {
+ return SqlGeography.Null;
+ }
+ ShapeData ring = _geometry.GetRing(n - 1);
+ ring.SetIsValid(false);
return new SqlGeography(ring, this.srid);
}
@@ -356,8 +358,8 @@ public SqlGeography RingN(int n)
[SqlMethodAttribute(IsDeterministic = true, IsPrecise = true)]
public SqlBoolean STIsEmpty()
{
- if (this.IsNull)
- return SqlBoolean.Null;
+ if (this.IsNull)
+ return SqlBoolean.Null;
return _geometry.IsEmpty;
}
diff --git a/src/Microsoft.SqlServer.Types/SqlGeometry.cs b/src/Microsoft.SqlServer.Types/SqlGeometry.cs
index 71a508c..01b9d1e 100644
--- a/src/Microsoft.SqlServer.Types/SqlGeometry.cs
+++ b/src/Microsoft.SqlServer.Types/SqlGeometry.cs
@@ -1,3 +1,5 @@
+using Microsoft.SqlServer.Server;
+
namespace Microsoft.SqlServer.Types
{
///
@@ -199,10 +201,10 @@ public SqlInt32 STNumCurves()
{
if (IsNull || _geometry.IsEmpty) return SqlInt32.Null;
- if (_geometry.Type == OGCGeometryType.LineString)
- return _geometry.IsEmpty ? 0 : _geometry.NumPoints - 1;
+ if (_geometry.Type == OGCGeometryType.LineString)
+ return _geometry.IsEmpty ? 0 : _geometry.NumPoints - 1;
- if (_geometry.Type == OGCGeometryType.CircularString)
+ if (_geometry.Type == OGCGeometryType.CircularString)
{
if (_geometry.IsEmpty) return 0;
return (_geometry.NumPoints - 1) / 2;
@@ -211,7 +213,7 @@ public SqlInt32 STNumCurves()
return _geometry.NumRings;
if (_geometry.Type != OGCGeometryType.CompoundCurve)
return SqlInt32.Null;
- return _geometry.NumSegments;
+ return _geometry.NumSegments;
}
///
diff --git a/src/Microsoft.SqlServer.Types/SqlHierarchyId.cs b/src/Microsoft.SqlServer.Types/SqlHierarchyId.cs
index c635782..d27f260 100644
--- a/src/Microsoft.SqlServer.Types/SqlHierarchyId.cs
+++ b/src/Microsoft.SqlServer.Types/SqlHierarchyId.cs
@@ -1,263 +1,264 @@
-using Microsoft.SqlServer.Types.SqlHierarchy;
-using System.Linq;
-
-namespace Microsoft.SqlServer.Types
-{
- ///
- /// The SqlHierarchyId type represents a position in a hierarchical structure, specifying depth and breadth.
- ///
- [SqlUserDefinedType(Format.UserDefined, IsByteOrdered = true, MaxByteSize = 892, Name = "SqlHierarchyId")]
- public struct SqlHierarchyId : IBinarySerialize, INullable, IComparable
- {
- private HierarchyId _imp;
- private bool _isNotNull;
-
- ///
- /// Gets a value indicating whether the is null.
- ///
- /// Boolean representing true (1) if the node is null; otherwise, false (0).
- public bool IsNull => !_isNotNull; // This is a bit backwards, but is done so default(SqlHierarchyId) will return a null id
-
- ///
- /// Gets a with a hierarchy identification of null.
- ///
- public static SqlHierarchyId Null
- {
- [SqlMethodAttribute(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None,
- IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- get;
- } = new SqlHierarchyId(new HierarchyId(), true);
-
- private SqlHierarchyId(HierarchyId imp, bool isNull = false)
- {
- _isNotNull = !isNull;
- _imp = imp;
- }
-
- ///
- /// Gets a value representing the root node of the hierarchy.
- ///
- /// A representing the root node of the hierarchical tree. Root value is typically 0x.
- [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- public static SqlHierarchyId GetRoot() => new SqlHierarchyId(HierarchyId.GetRoot());
-
- ///
- /// Converts the canonical string representation of a node to a value.
- ///
- /// String representation of node.
- /// representing the node described canonically.
- [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- public static SqlHierarchyId Parse(SqlString input) => new SqlHierarchyId(HierarchyId.Parse((string)input));
-
- ///
- /// Returns a value indicating the results of a comparison between a SqlHierarchyId and an object.
- ///
- /// An object to be compared to this.
- /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings:
- ///
- ///
- /// Value
- /// Meaning
- ///
- /// - Less than zerothis is less than .
- /// - Zerothis is equal to .
- /// - Greater than zerothis is greater than .
- ///
- ///
- ///
- /// Throws an exception if is not a node.
- /// This member is sealed.
- ///
- public int CompareTo(object obj) => this.CompareTo((SqlHierarchyId)obj);
-
- ///
- /// Returns a value indicating the results of a comparison between two nodes.
- ///
- /// A node to compare to this.
- /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings:
- ///
- ///
- /// Value
- /// Meaning
- ///
- /// - Less than zerothis is less than .
- /// - Zerothis is equal to .
- /// - Greater than zerothis is greater than .
- ///
- ///
- ///
- /// If both nodes are null, returns 0.
- /// If one node is null, it is considered to be less than the non-null node.
- ///
- public int CompareTo(SqlHierarchyId hid)
- {
- if(IsNull)
- {
- if (!hid.IsNull)
- return -1;
- return 0;
- }
- if (hid.IsNull)
- return 1;
- if (this < hid)
- return -1;
- if (this > hid)
- return 1;
- return 0;
- }
-
- ///
- /// Evaluates whether and obj are equal.
- ///
- /// The object against which to compare this.
- /// Boolean. true (1) if this and obj are equal; otherwise, false (0).
- ///
- /// Returns false (0) if obj is not a SqlHierarchyId node.
- /// Returns true (1) if both this and obj are null.
- ///
- public override bool Equals(object obj) => obj is SqlHierarchyId && Equals((SqlHierarchyId)obj);
-
- private bool Equals(SqlHierarchyId other) => (IsNull && other.IsNull) || (this == other).IsTrue;
-
- ///
- /// Retrieves the node n levels up the hierarchical tree.
- ///
- /// An integer representing the number of levels to ascend in the hierarchy.
- ///
- /// representing the nth ancestor of this.
- /// If a number greater than is passed, null is returned.
- /// If a negative number is passed, an exception is raised indicating that the argument is out of range.
- ///
- [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- public SqlHierarchyId GetAncestor(int n)
- {
- if (IsNull || _imp.GetLevel() < n)
- {
- return Null;
- }
- if (n < 0)
- {
- throw new ArgumentOutOfRangeException("24011: SqlHierarchyId.GetAncestor failed because 'n' was negative.");
- }
- return new SqlHierarchyId(_imp.GetAncestor(n));
- }
- ///
- /// Gets the value of a descendant node that is greater than and less than .
- ///
- /// The lower bound.
- /// The upper bound.
- /// A SqlHierarchyId with a value greater than the lower bound and less than the upper bound.
- ///
- ///
- /// - If parent is null, returns null.
- /// - If parent is not null, and both and are null, returns a descendant of parent.
- /// - If parent and are not null, and is null, returns a descendant of parent greater than .
- /// - If parent and are not null and is null, returns a descendant of parent less than .
- /// - If parent, , and child2 are not null, returns a descendant of parent greater than and less than .
- /// - An exception is raised if or are not null and are not a descendant of parent.
- /// - If >= , an exception is raised.
- ///
- ///
- [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = true, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- public SqlHierarchyId GetDescendant(SqlHierarchyId child1, SqlHierarchyId child2) => new SqlHierarchyId(_imp.GetDescendant(
- child1.IsNull ? default(HierarchyId?) : child1._imp,
- child2.IsNull ? default(HierarchyId?) : child2._imp));
-
- ///
- /// Gets a hash of the path from the root node of the hierarchy tree to the node.
- ///
- /// A 32-bit signed integer representing the hash code for this instance.
- public override int GetHashCode() => _imp.GetHashCode();
-
- ///
- /// Gets a value indicating the level of the node in the hierarchical tree.
- ///
- /// A 16-bit integer indicating the depth of the node in the hierarchical tree.
- /// The root of the hierarchy is level 0.
- [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- public SqlInt16 GetLevel() => _imp.GetLevel();
-
- ///
- /// Gets a value representing the location of a new node that has a path from newRoot equal to the path from oldRoot to this, effectively moving this to the new location.
- ///
- /// An ancestor of the node specifying the endpoint of the path segment that is to be moved.
- /// The node that represents the new ancestor of this.
- /// A node representing the new hierarchical location of this. Will return null if , , or this are null.
- ///
- /// Returns a node whose path from the root is the path to , followed by the path from to this.
- /// The data type represents but does not enforce the hierarchical structure. Users must ensure that the node is appropriately structured for the new location.
- ///
- [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- public SqlHierarchyId GetReparentedValue(SqlHierarchyId oldRoot, SqlHierarchyId newRoot)
- {
- if (!IsNull && !oldRoot.IsNull && !newRoot.IsNull)
- {
- if (!IsDescendantOf(oldRoot))
- {
- throw new HierarchyIdException("Instance is not a descendant of 'oldRoot'");
- }
- return new SqlHierarchyId(_imp.GetReparentedValue(oldRoot._imp, newRoot._imp));
- }
- return Null;
- }
- ///
- /// Gets a value indicating whether the node is the descendant of the parent.
- ///
- /// The specified node for which the IsDescendantOf test is performed.
- /// Boolean, true (1) for all the nodes in the sub-tree rooted at parent; false (0) for all other nodes.
- /// parent is considered its own descendant.
- [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- public SqlBoolean IsDescendantOf(SqlHierarchyId parent) => _imp.IsDescendantOf(parent._imp);
-
- ///
- /// Returns the canonical string representation of a node from a value.
- ///
- ///
- ///
- /// Called implicitly when a conversion from a data type to a string type occurs.
- /// Acts as the opposite of .
- ///
- ///
- /// DECLARE @StringValue AS nvarchar(4000), @hierarchyidValue AS hierarchyid
- /// SET @StringValue = '/1/1/3/'
- /// SET @hierarchyidValue = 0x5ADE
- /// SELECT hierarchyid::Parse(@StringValue) AS hierarchyidRepresentation,
- /// @hierarchyidValue.ToString() AS StringRepresentation;
- /// GO
- ///
- [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
- public override string ToString() => _imp.ToString();
-
- ///
- /// Writes a to a specified binary writer.
- ///
- /// The specified binary writer.
- ///
- /// Throws an exception if w is null.
- /// Throws an exception if the is null.
- /// This member is sealed.
- ///
- [SqlMethod(IsDeterministic = true, IsPrecise = true)]
- public void Write(BinaryWriter w)
- {
- if (w is null)
- throw new ArgumentNullException(nameof(w));
- if (IsNull)
- throw new HierarchyIdException("24002: SqlHierarchyId.Write failed because 'this' was a NULL instance.");
- BitWriter bw = new BitWriter(w);
-
- var nodes = this._imp.GetNodes();
-
- for (int i = 0; i < nodes.Length; i++)
- {
- var subNodes = nodes[i];
- for (int j = 0; j < subNodes.Length; j++)
- {
- bool isLast = j == (subNodes.Length - 1);
-
-
- long val = subNodes[j];
-
+using Microsoft.SqlServer.Server;
+using Microsoft.SqlServer.Types.SqlHierarchy;
+using System.Linq;
+
+namespace Microsoft.SqlServer.Types
+{
+ ///
+ /// The SqlHierarchyId type represents a position in a hierarchical structure, specifying depth and breadth.
+ ///
+ [SqlUserDefinedType(Format.UserDefined, IsByteOrdered = true, MaxByteSize = 892, Name = "SqlHierarchyId")]
+ public struct SqlHierarchyId : IBinarySerialize, INullable, IComparable
+ {
+ private HierarchyId _imp;
+ private bool _isNotNull;
+
+ ///
+ /// Gets a value indicating whether the is null.
+ ///
+ /// Boolean representing true (1) if the node is null; otherwise, false (0).
+ public bool IsNull => !_isNotNull; // This is a bit backwards, but is done so default(SqlHierarchyId) will return a null id
+
+ ///
+ /// Gets a with a hierarchy identification of null.
+ ///
+ public static SqlHierarchyId Null
+ {
+ [SqlMethodAttribute(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None,
+ IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ get;
+ } = new SqlHierarchyId(new HierarchyId(), true);
+
+ private SqlHierarchyId(HierarchyId imp, bool isNull = false)
+ {
+ _isNotNull = !isNull;
+ _imp = imp;
+ }
+
+ ///
+ /// Gets a value representing the root node of the hierarchy.
+ ///
+ /// A representing the root node of the hierarchical tree. Root value is typically 0x.
+ [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ public static SqlHierarchyId GetRoot() => new SqlHierarchyId(HierarchyId.GetRoot());
+
+ ///
+ /// Converts the canonical string representation of a node to a value.
+ ///
+ /// String representation of node.
+ /// representing the node described canonically.
+ [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ public static SqlHierarchyId Parse(SqlString input) => new SqlHierarchyId(HierarchyId.Parse((string)input));
+
+ ///
+ /// Returns a value indicating the results of a comparison between a SqlHierarchyId and an object.
+ ///
+ /// An object to be compared to this.
+ /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings:
+ ///
+ ///
+ /// Value
+ /// Meaning
+ ///
+ /// - Less than zerothis is less than .
+ /// - Zerothis is equal to .
+ /// - Greater than zerothis is greater than .
+ ///
+ ///
+ ///
+ /// Throws an exception if is not a node.
+ /// This member is sealed.
+ ///
+ public int CompareTo(object obj) => this.CompareTo((SqlHierarchyId)obj);
+
+ ///
+ /// Returns a value indicating the results of a comparison between two nodes.
+ ///
+ /// A node to compare to this.
+ /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings:
+ ///
+ ///
+ /// Value
+ /// Meaning
+ ///
+ /// - Less than zerothis is less than .
+ /// - Zerothis is equal to .
+ /// - Greater than zerothis is greater than .
+ ///
+ ///
+ ///
+ /// If both nodes are null, returns 0.
+ /// If one node is null, it is considered to be less than the non-null node.
+ ///
+ public int CompareTo(SqlHierarchyId hid)
+ {
+ if(IsNull)
+ {
+ if (!hid.IsNull)
+ return -1;
+ return 0;
+ }
+ if (hid.IsNull)
+ return 1;
+ if (this < hid)
+ return -1;
+ if (this > hid)
+ return 1;
+ return 0;
+ }
+
+ ///
+ /// Evaluates whether and obj are equal.
+ ///
+ /// The object against which to compare this.
+ /// Boolean. true (1) if this and obj are equal; otherwise, false (0).
+ ///
+ /// Returns false (0) if obj is not a SqlHierarchyId node.
+ /// Returns true (1) if both this and obj are null.
+ ///
+ public override bool Equals(object obj) => obj is SqlHierarchyId && Equals((SqlHierarchyId)obj);
+
+ private bool Equals(SqlHierarchyId other) => (IsNull && other.IsNull) || (this == other).IsTrue;
+
+ ///
+ /// Retrieves the node n levels up the hierarchical tree.
+ ///
+ /// An integer representing the number of levels to ascend in the hierarchy.
+ ///
+ /// representing the nth ancestor of this.
+ /// If a number greater than is passed, null is returned.
+ /// If a negative number is passed, an exception is raised indicating that the argument is out of range.
+ ///
+ [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ public SqlHierarchyId GetAncestor(int n)
+ {
+ if (IsNull || _imp.GetLevel() < n)
+ {
+ return Null;
+ }
+ if (n < 0)
+ {
+ throw new ArgumentOutOfRangeException("24011: SqlHierarchyId.GetAncestor failed because 'n' was negative.");
+ }
+ return new SqlHierarchyId(_imp.GetAncestor(n));
+ }
+ ///
+ /// Gets the value of a descendant node that is greater than and less than .
+ ///
+ /// The lower bound.
+ /// The upper bound.
+ /// A SqlHierarchyId with a value greater than the lower bound and less than the upper bound.
+ ///
+ ///
+ /// - If parent is null, returns null.
+ /// - If parent is not null, and both and are null, returns a descendant of parent.
+ /// - If parent and are not null, and is null, returns a descendant of parent greater than .
+ /// - If parent and are not null and is null, returns a descendant of parent less than .
+ /// - If parent, , and child2 are not null, returns a descendant of parent greater than and less than .
+ /// - An exception is raised if or are not null and are not a descendant of parent.
+ /// - If >= , an exception is raised.
+ ///
+ ///
+ [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = true, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ public SqlHierarchyId GetDescendant(SqlHierarchyId child1, SqlHierarchyId child2) => new SqlHierarchyId(_imp.GetDescendant(
+ child1.IsNull ? default(HierarchyId?) : child1._imp,
+ child2.IsNull ? default(HierarchyId?) : child2._imp));
+
+ ///
+ /// Gets a hash of the path from the root node of the hierarchy tree to the node.
+ ///
+ /// A 32-bit signed integer representing the hash code for this instance.
+ public override int GetHashCode() => _imp.GetHashCode();
+
+ ///
+ /// Gets a value indicating the level of the node in the hierarchical tree.
+ ///
+ /// A 16-bit integer indicating the depth of the node in the hierarchical tree.
+ /// The root of the hierarchy is level 0.
+ [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ public SqlInt16 GetLevel() => _imp.GetLevel();
+
+ ///
+ /// Gets a value representing the location of a new node that has a path from newRoot equal to the path from oldRoot to this, effectively moving this to the new location.
+ ///
+ /// An ancestor of the node specifying the endpoint of the path segment that is to be moved.
+ /// The node that represents the new ancestor of this.
+ /// A node representing the new hierarchical location of this. Will return null if , , or this are null.
+ ///
+ /// Returns a node whose path from the root is the path to , followed by the path from to this.
+ /// The data type represents but does not enforce the hierarchical structure. Users must ensure that the node is appropriately structured for the new location.
+ ///
+ [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ public SqlHierarchyId GetReparentedValue(SqlHierarchyId oldRoot, SqlHierarchyId newRoot)
+ {
+ if (!IsNull && !oldRoot.IsNull && !newRoot.IsNull)
+ {
+ if (!IsDescendantOf(oldRoot))
+ {
+ throw new HierarchyIdException("Instance is not a descendant of 'oldRoot'");
+ }
+ return new SqlHierarchyId(_imp.GetReparentedValue(oldRoot._imp, newRoot._imp));
+ }
+ return Null;
+ }
+ ///
+ /// Gets a value indicating whether the node is the descendant of the parent.
+ ///
+ /// The specified node for which the IsDescendantOf test is performed.
+ /// Boolean, true (1) for all the nodes in the sub-tree rooted at parent; false (0) for all other nodes.
+ /// parent is considered its own descendant.
+ [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ public SqlBoolean IsDescendantOf(SqlHierarchyId parent) => _imp.IsDescendantOf(parent._imp);
+
+ ///
+ /// Returns the canonical string representation of a node from a value.
+ ///
+ ///
+ ///
+ /// Called implicitly when a conversion from a data type to a string type occurs.
+ /// Acts as the opposite of .
+ ///
+ ///
+ /// DECLARE @StringValue AS nvarchar(4000), @hierarchyidValue AS hierarchyid
+ /// SET @StringValue = '/1/1/3/'
+ /// SET @hierarchyidValue = 0x5ADE
+ /// SELECT hierarchyid::Parse(@StringValue) AS hierarchyidRepresentation,
+ /// @hierarchyidValue.ToString() AS StringRepresentation;
+ /// GO
+ ///
+ [SqlMethod(DataAccess = DataAccessKind.None, SystemDataAccess = SystemDataAccessKind.None, InvokeIfReceiverIsNull = false, OnNullCall = false, IsDeterministic = true, IsPrecise = true, IsMutator = false)]
+ public override string ToString() => _imp.ToString();
+
+ ///
+ /// Writes a to a specified binary writer.
+ ///
+ /// The specified binary writer.
+ ///
+ /// Throws an exception if w is null.
+ /// Throws an exception if the is null.
+ /// This member is sealed.
+ ///
+ [SqlMethod(IsDeterministic = true, IsPrecise = true)]
+ public void Write(BinaryWriter w)
+ {
+ if (w is null)
+ throw new ArgumentNullException(nameof(w));
+ if (IsNull)
+ throw new HierarchyIdException("24002: SqlHierarchyId.Write failed because 'this' was a NULL instance.");
+ BitWriter bw = new BitWriter(w);
+
+ var nodes = this._imp.GetNodes();
+
+ for (int i = 0; i < nodes.Length; i++)
+ {
+ var subNodes = nodes[i];
+ for (int j = 0; j < subNodes.Length; j++)
+ {
+ bool isLast = j == (subNodes.Length - 1);
+
+
+ long val = subNodes[j];
+
if (isLast)
{
BitPattern p = KnownPatterns.GetPatternByValue(val);
@@ -269,131 +270,131 @@ public void Write(BinaryWriter w)
BitPattern p = KnownPatterns.GetPatternByValue(val + 1);
ulong value = p.EncodeValue(val + 1) - 1;
bw.Write(value, p.BitLength);
- }
- }
- }
-
- bw.Finish();
- }
-
- ///
- /// Reads from a specified binary reader into a .
- ///
- /// The specified binary reader.
- ///
- /// Throws an exception if r is null.
- /// Throws an exception if the SqlHierarchyId is not null.
- /// This member is sealed.
- ///
- [SqlMethod(IsDeterministic = true, IsPrecise = true)]
- public void Read(BinaryReader r)
- {
- if (r is null)
- throw new ArgumentNullException(nameof(r));
- var bitR = new BitReader(r);
- List> result = new List>();
-
- while (true)
- {
- List step = new List();
-
- while (true)
- {
- var p = KnownPatterns.GetPatternByPrefix(bitR);
-
- if (p == null)
- goto finish;
-
- ulong encodedValue = bitR.Read(p.BitLength);
-
- long value = p.Decode(encodedValue, out bool isLast);
-
- step.Add(value);
-
- if (isLast)
- break;
- }
-
- result.Add(step);
- }
-
- finish:
-
- this._imp = new HierarchyId(result.Select(a => a.ToArray()).ToArray());
- this._isNotNull = !_imp.IsNull;
- }
-
- ///
- /// Evaluates whether two nodes are equal.
- ///
- /// First node to compare.
- /// Second node to compare.
- /// Boolean. true (1) if and are equal; otherwise, false (0).
- /// Returns null if either or are null.
- public static SqlBoolean operator ==(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp == hid2._imp;
-
- ///
- /// Evaluates whether two nodes are unequal.
- ///
- /// First node to compare.
- /// Second node to compare.
- ///
- /// Returns null if either or are null.
- public static SqlBoolean operator !=(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp != hid2._imp;
-
- ///
- /// Evaluates whether one specified node is less than another.
- ///
- /// First node to compare.
- /// Second node to compare.
- ///
- /// Returns null if either or are null.
- public static SqlBoolean operator <(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp < hid2._imp;
-
- ///
- /// Evaluates whether one specified node is greater than another.
- ///
- /// First node to compare.
- /// Second node to compare.
- ///
- /// Returns null if either or are null.
- public static SqlBoolean operator >(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp > hid2._imp;
-
- ///
- /// Evaluates whether one specified node is less than or equal to another.
- ///
- /// First node to compare.
- /// Second node to compare.
- ///
- /// Returns null if either or are null.
- public static SqlBoolean operator <=(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp <= hid2._imp;
-
- ///
- /// Evaluates whether one specified node is greater than or equal to another.
- ///
- /// First node to compare.
- /// Second node to compare.
- ///
- /// Returns null if either or are null.
- public static SqlBoolean operator >=(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp >= hid2._imp;
-
- //public static SqlHierarchyId Deserialize(SqlBytes bytes)
- //{
- // using (var r = new BinaryReader(bytes.Stream))
- // {
- // var hid = new SqlHierarchyId(new HierarchyId());
- // hid.Read(r);
- // return hid;
- // }
- //}
-
- //public SqlBytes Serialize()
- //{
- // using (var ms = new MemoryStream())
- // {
- // Write(new BinaryWriter(ms));
- // return new SqlBytes(ms.ToArray());
- // }
- //}
- }
-}
+ }
+ }
+ }
+
+ bw.Finish();
+ }
+
+ ///
+ /// Reads from a specified binary reader into a .
+ ///
+ /// The specified binary reader.
+ ///
+ /// Throws an exception if r is null.
+ /// Throws an exception if the SqlHierarchyId is not null.
+ /// This member is sealed.
+ ///
+ [SqlMethod(IsDeterministic = true, IsPrecise = true)]
+ public void Read(BinaryReader r)
+ {
+ if (r is null)
+ throw new ArgumentNullException(nameof(r));
+ var bitR = new BitReader(r);
+ List> result = new List>();
+
+ while (true)
+ {
+ List step = new List();
+
+ while (true)
+ {
+ var p = KnownPatterns.GetPatternByPrefix(bitR);
+
+ if (p == null)
+ goto finish;
+
+ ulong encodedValue = bitR.Read(p.BitLength);
+
+ long value = p.Decode(encodedValue, out bool isLast);
+
+ step.Add(value);
+
+ if (isLast)
+ break;
+ }
+
+ result.Add(step);
+ }
+
+ finish:
+
+ this._imp = new HierarchyId(result.Select(a => a.ToArray()).ToArray());
+ this._isNotNull = !_imp.IsNull;
+ }
+
+ ///
+ /// Evaluates whether two nodes are equal.
+ ///
+ /// First node to compare.
+ /// Second node to compare.
+ /// Boolean. true (1) if and are equal; otherwise, false (0).
+ /// Returns null if either or are null.
+ public static SqlBoolean operator ==(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp == hid2._imp;
+
+ ///
+ /// Evaluates whether two nodes are unequal.
+ ///
+ /// First node to compare.
+ /// Second node to compare.
+ ///
+ /// Returns null if either or are null.
+ public static SqlBoolean operator !=(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp != hid2._imp;
+
+ ///
+ /// Evaluates whether one specified node is less than another.
+ ///
+ /// First node to compare.
+ /// Second node to compare.
+ ///
+ /// Returns null if either or are null.
+ public static SqlBoolean operator <(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp < hid2._imp;
+
+ ///
+ /// Evaluates whether one specified node is greater than another.
+ ///
+ /// First node to compare.
+ /// Second node to compare.
+ ///
+ /// Returns null if either or are null.
+ public static SqlBoolean operator >(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp > hid2._imp;
+
+ ///
+ /// Evaluates whether one specified node is less than or equal to another.
+ ///
+ /// First node to compare.
+ /// Second node to compare.
+ ///
+ /// Returns null if either or are null.
+ public static SqlBoolean operator <=(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp <= hid2._imp;
+
+ ///
+ /// Evaluates whether one specified node is greater than or equal to another.
+ ///
+ /// First node to compare.
+ /// Second node to compare.
+ ///
+ /// Returns null if either or are null.
+ public static SqlBoolean operator >=(SqlHierarchyId hid1, SqlHierarchyId hid2) => hid1.IsNull || hid2.IsNull ? SqlBoolean.Null : hid1._imp >= hid2._imp;
+
+ //public static SqlHierarchyId Deserialize(SqlBytes bytes)
+ //{
+ // using (var r = new BinaryReader(bytes.Stream))
+ // {
+ // var hid = new SqlHierarchyId(new HierarchyId());
+ // hid.Read(r);
+ // return hid;
+ // }
+ //}
+
+ //public SqlBytes Serialize()
+ //{
+ // using (var ms = new MemoryStream())
+ // {
+ // Write(new BinaryWriter(ms));
+ // return new SqlBytes(ms.ToArray());
+ // }
+ //}
+ }
+}