Sql-server – COM error on UnionAggregate

geometryspatialsql serversql-server-2012

Has anyone ever come across a COMException while working with geography data in SQL Server?

I didn't notice the error until I ran .Reduce() on the original zip code data. It may have happened before then had I let queries run long enough, but most queries I tried ran for a very long time (up to 5 hours, in once case) before I terminated them.

I'm not entirely sure how to debug something like this, since it's not giving me any useful error code, and I haven't been able to find anything about this sort of error in the documentation.

The error is as follows:

Msg 6522, Level 16, State 1, Line 1
A .NET Framework error occurred during execution of user-defined routine or aggregate "GeographyUnionAggregate": 
System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.
System.Runtime.InteropServices.COMException: 
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at Microsoft.SqlServer.Types.GLNativeMethods.ThrowExceptionForHr(GL_HResult errorCode)
   at Microsoft.SqlServer.Types.GLNativeMethods.GeodeticCombine(CombineMode combineMode, GeoData g1, GeoData g2, Double eccentricity)
   at Microsoft.SqlServer.Types.GeographyUnionAggregate.Terminate()
.

And I'm able to produce it with the following code:

select
    *
from
    tblGeography
    cross apply
    (
        select
            geography::UnionAggregate(ZC_Geography) as NewGeom
        from
            tblGeographyDetail
            join tblZipCode on ZC_Zip_Code like GD_Zip_Code
        where
            GD_GEO_ID=GEO_ID
    ) a
where
    GEO_ID=2

Best Answer

I've found that this issue seems to be a problem with the number of rows I was attempting to aggregate. I get errors when aggregating over about 5,000 rows, but don't get errors (well, the same error, anyway) when aggregating less than that.

My solution ended up being to segment and aggregate the rows using ROW_NUMBER, then aggregate those groups, as in the following:

select
    geography::UnionAggregate(GroupGeography)
from
    (
        select
            geography::UnionAggregate(ZC_Geography) as GroupGeography
        from
            (
                select
                    *,
                    ROW_NUMBER() OVER(PARTITION BY 'dummy' ORDER BY ZCG_Zip_Code) / 1000 as ZipGroup
                from
                    tblZipCode
            ) a
        group by ZipGroup
    ) groups