| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- //
- // Copyright (c) 2017-2026, Manticore Software LTD (https://manticoresearch.com)
- // Copyright (c) 2001-2016, Andrew Aksyonoff
- // Copyright (c) 2008-2016, Sphinx Technologies Inc
- // All rights reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License. You should have
- // received a copy of the GPL license along with this program; if you
- // did not, you can find it at http://www.gnu.org/
- //
- #include "sorterprecalc.h"
- #include "sortertraits.h"
- static const char * GetPrecalcSorterName() { return "Precalc"; }
- class FastBaseSorter_c : public MatchSorter_c, ISphNoncopyable, protected BaseGroupSorter_c
- {
- public:
- FastBaseSorter_c ( const CSphGroupSorterSettings & tSettings ) : BaseGroupSorter_c ( tSettings ) {}
- bool IsGroupby () const final { return true; }
- bool CanBeCloned() const final { return false; }
- void SetMerge ( bool bMerge ) final {}
- void Finalize ( MatchProcessor_i & tProcessor, bool, bool bFinalizeMatches ) final { if ( GetLength() ) tProcessor.Process ( &m_tData ); }
- int GetLength() final { return m_bDataInitialized ? 1 : 0; }
- ISphMatchSorter * Clone() const final { return nullptr; }
- void MoveTo ( ISphMatchSorter * pRhs, bool bCopyMeta ) final { assert ( 0 && "Not supported"); }
- bool IsPrecalc() const final { return true; }
- int Flatten ( CSphMatch * pTo ) final;
- protected:
- CSphMatch m_tData;
- bool m_bDataInitialized = false;
- };
- int FastBaseSorter_c::Flatten ( CSphMatch * pTo )
- {
- assert ( m_bDataInitialized );
- Swap ( *pTo, m_tData );
- m_iTotal = 0;
- m_bDataInitialized = false;
- return 1;
- }
- // fast count distinct sorter
- // works by using precalculated count distinct taken from secondary indexes
- class FastCountDistinctSorter_c final : public FastBaseSorter_c
- {
- public:
- FastCountDistinctSorter_c ( int64_t iCountDistinct, const CSphString & sAttr, const CSphGroupSorterSettings & tSettings );
- bool Push ( const CSphMatch & tEntry ) final { return PushEx(tEntry); }
- void Push ( const VecTraits_T<const CSphMatch> & dMatches ) final { assert ( 0 && "Not supported in grouping"); }
- bool PushGrouped ( const CSphMatch & tEntry, bool ) final { return PushEx(tEntry); }
- void AddDesc ( CSphVector<IteratorDesc_t> & dDesc ) const final { dDesc.Add ( { m_sAttr, GetPrecalcSorterName() } ); }
- private:
- int64_t m_iCountDistinct = 0;
- CSphString m_sAttr;
- bool PushEx ( const CSphMatch & tEntry );
- };
- FastCountDistinctSorter_c::FastCountDistinctSorter_c ( int64_t iCountDistinct, const CSphString & sAttr, const CSphGroupSorterSettings & tSettings )
- : FastBaseSorter_c ( tSettings )
- , m_iCountDistinct ( iCountDistinct )
- , m_sAttr ( sAttr )
- {}
- FORCE_INLINE bool FastCountDistinctSorter_c::PushEx ( const CSphMatch & tEntry )
- {
- if ( m_bDataInitialized )
- return true; // always return true, otherwise in RT indexes we won't be able to hit cutoff in disk chunks after the first one
- m_pSchema->CloneMatch ( m_tData, tEntry );
- m_tData.SetAttr ( m_tLocGroupby, 1 ); // fake group number
- m_tData.SetAttr ( m_tLocCount, 1 );
- m_tData.SetAttr ( m_tLocDistinct, m_iCountDistinct );
- m_bDataInitialized = true;
- ++m_iTotal;
- return true;
- }
- // fast count sorter
- // works by using precalculated count taken from secondary indexes
- class FastCountFilterSorter_c final : public FastBaseSorter_c
- {
- public:
- FastCountFilterSorter_c ( int64_t iCount, const CSphString & sAttr, const CSphGroupSorterSettings & tSettings );
- bool Push ( const CSphMatch & tEntry ) final { return PushEx(tEntry); }
- void Push ( const VecTraits_T<const CSphMatch> & dMatches ) final { assert ( 0 && "Not supported in grouping"); }
- bool PushGrouped ( const CSphMatch & tEntry, bool ) final { return PushEx(tEntry); }
- void AddDesc ( CSphVector<IteratorDesc_t> & dDesc ) const final { dDesc.Add ( { m_sAttr, GetPrecalcSorterName() } ); }
- private:
- int64_t m_iCount;
- CSphString m_sAttr;
- bool PushEx ( const CSphMatch & tEntry );
- };
- FastCountFilterSorter_c::FastCountFilterSorter_c ( int64_t iCount, const CSphString & sAttr, const CSphGroupSorterSettings & tSettings )
- : FastBaseSorter_c ( tSettings )
- , m_iCount ( iCount )
- , m_sAttr ( sAttr )
- {}
- FORCE_INLINE bool FastCountFilterSorter_c::PushEx ( const CSphMatch & tEntry )
- {
- if ( m_bDataInitialized )
- return true; // always return true, otherwise in RT indexes we won't be able to hit cutoff in disk chunks after the first one
- m_pSchema->CloneMatch ( m_tData, tEntry );
- m_tData.SetAttr ( m_tLocGroupby, 1 ); // fake group number
- m_tData.SetAttr ( m_tLocCount, m_iCount );
- m_bDataInitialized = true;
- m_iTotal++;
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- ISphMatchSorter * CreatePrecalcSorter ( const PrecalculatedSorterResults_t & tPrecalc, const CSphGroupSorterSettings & tSettings )
- {
- if ( tPrecalc.m_iCountDistinct!=-1 )
- return new FastCountDistinctSorter_c ( tPrecalc.m_iCountDistinct, tPrecalc.m_sAttr, tSettings );
- if ( tPrecalc.m_iCountFilter!=-1 )
- return new FastCountFilterSorter_c ( tPrecalc.m_iCountFilter, tPrecalc.m_sAttr, tSettings );
- if ( tPrecalc.m_iCount!=-1 )
- return new FastCountFilterSorter_c ( tPrecalc.m_iCount, "count(*)", tSettings );
- return nullptr;
- }
|