@@ -1806,18 +1806,25 @@ bool SqlParser_c::AddNullFilter ( const SqlNode_t & tCol, bool bEqualsNull )
18061806
18071807void SqlParser_c::AddHaving ()
18081808{
1809- // Move the last parsed filter into HAVING
1810- assert ( m_pQuery->m_dFilters .GetLength () );
1811- m_pQuery->m_tHaving = m_pQuery->m_dFilters .Pop ();
1812-
1813- // FIX(#887): The filter tree (m_dFilterTree) still contains a leaf for the
1814- // just-moved HAVING predicate. If we keep it, CreateFilterTree() for WHERE
1815- // will attempt to build a node for a filter that was popped <E2><86><92> it will look
1816- // like a filter with an empty name and throw "filter with empty name".
1817- //
1818- // Remove the trailing tree op that corresponds to the just-added HAVING item.
1819- if ( m_dFilterTree.GetLength () > 0 )
1820- m_dFilterTree.Pop ();
1809+ assert ( m_pQuery->m_dFilters .GetLength () );
1810+
1811+ // The filter we are about to move to HAVING has index (length-1).
1812+ // After Pop(), GetLength() equals that index.
1813+ const int iExpectHavingIdx = m_pQuery->m_dFilters .GetLength () - 1 ;
1814+ m_pQuery->m_tHaving = m_pQuery->m_dFilters .Pop ();
1815+
1816+ // FIX(#887): The filter tree still contains a leaf for the just-moved HAVING filter.
1817+ // That leaf must be the *last* tree item and must reference the same filter index.
1818+ if ( m_dFilterTree.GetLength () > 0 )
1819+ {
1820+ const int iLastFilterItem = m_dFilterTree.Last ().m_iFilterItem ;
1821+ // Assert the tree's last leaf matches the moved filter.
1822+ assert ( iLastFilterItem == iExpectHavingIdx && " HAVING leaf must be the last filter-tree item" );
1823+
1824+ // Remove that dangling leaf so WHERE's CreateFilterTree() won't see an empty-name filter.
1825+ if ( iLastFilterItem == iExpectHavingIdx )
1826+ m_dFilterTree.Pop ();
1827+ }
18211828}
18221829
18231830
0 commit comments