Skip to content

Commit d347ab2

Browse files
committed
fix: sorting by string with OPTION scroll
Related issue #3928
1 parent b01af24 commit d347ab2

File tree

4 files changed

+193
-31
lines changed

4 files changed

+193
-31
lines changed

src/sorterscroll.cpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class ScrollSorter_T : public ISphMatchSorter
6464
CSphVector<CSphRowitem> m_dStatic;
6565
CSphMatchComparatorState m_tState;
6666
ScrollSettings_t m_tScroll;
67+
CSphVector<const CSphColumnInfo*> m_dAllocatedPtrAttrs; // Track which attributes we allocated pointers for
6768

6869
FORCE_INLINE bool PushMatch ( const CSphMatch & tEntry );
6970
void SetupRefMatch();
@@ -122,8 +123,10 @@ void ScrollSorter_T<COMP>::SetupRefMatch()
122123
const ISphSchema * pSchema = m_pSorter->GetSchema();
123124
assert(pSchema);
124125

126+
// Free old data pointer attributes before resetting
125127
FreeDataPtrAttrs();
126-
m_tRefMatch.Reset ( pSchema->GetRowSize() );
128+
129+
m_tRefMatch.Reset ( pSchema->GetDynamicSize() );
127130
m_dStatic.Resize ( pSchema->GetStaticSize() );
128131
m_tRefMatch.m_pStatic = m_dStatic.Begin();
129132

@@ -137,11 +140,31 @@ void ScrollSorter_T<COMP>::SetupRefMatch()
137140
}
138141

139142
auto pAttr = pSchema->GetAttr ( i.m_sSortAttr.cstr() );
143+
if ( !pAttr )
144+
continue;
145+
146+
// If the scroll token has a string type and the schema attribute is SPH_ATTR_STRING,
147+
// use the remapped STRINGPTR version (used for sorting)
148+
if ( i.m_eType==SPH_ATTR_STRINGPTR && pAttr->m_eAttrType==SPH_ATTR_STRING )
149+
{
150+
CSphString sRemappedName;
151+
sRemappedName.SetSprintf ( "@int_attr_%s", i.m_sSortAttr.cstr() );
152+
auto pRemapped = pSchema->GetAttr ( sRemappedName.cstr() );
153+
if ( pRemapped && pRemapped->m_eAttrType==SPH_ATTR_STRINGPTR )
154+
pAttr = pRemapped;
155+
}
156+
140157
auto pRowData = pAttr->m_tLocator.m_bDynamic ? m_tRefMatch.m_pDynamic : m_dStatic.Begin();
141158
switch ( i.m_eType )
142159
{
143160
case SPH_ATTR_STRINGPTR:
144-
sphSetRowAttr ( pRowData, pAttr->m_tLocator, (SphAttr_t)sphPackPtrAttr ( { (const BYTE*)i.m_sValue.cstr(), i.m_sValue.Length() } ) );
161+
// After remapping, pAttr should be SPH_ATTR_STRINGPTR, but check to be safe
162+
if ( pAttr->m_eAttrType==SPH_ATTR_STRINGPTR )
163+
{
164+
sphSetRowAttr ( pRowData, pAttr->m_tLocator, (SphAttr_t)sphPackPtrAttr ( { (const BYTE*)i.m_sValue.cstr(), i.m_sValue.Length() } ) );
165+
// Track that we allocated a pointer for this attribute
166+
m_dAllocatedPtrAttrs.Add(pAttr);
167+
}
145168
break;
146169

147170
case SPH_ATTR_FLOAT:
@@ -158,25 +181,26 @@ void ScrollSorter_T<COMP>::SetupRefMatch()
158181
template <typename COMP>
159182
void ScrollSorter_T<COMP>::FreeDataPtrAttrs()
160183
{
161-
if ( !m_tRefMatch.m_pDynamic )
184+
if ( !m_tRefMatch.m_pDynamic && !m_tRefMatch.m_pStatic )
162185
return;
163186

164-
const ISphSchema * pSchema = m_pSorter->GetSchema();
165-
assert(pSchema);
166-
167-
for ( auto & i : m_tScroll.m_dAttrs )
187+
// Only free pointers for attributes that we actually allocated
188+
for ( auto pAttr : m_dAllocatedPtrAttrs )
168189
{
169-
if ( i.m_sSortAttr=="weight()" )
190+
if ( !pAttr )
170191
continue;
171192

172-
const CSphColumnInfo * pAttr = pSchema->GetAttr ( i.m_sSortAttr.cstr() );
173-
assert(pAttr);
174-
if ( sphIsDataPtrAttr ( pAttr->m_eAttrType ) )
175-
{
176-
auto pData = (BYTE *)m_tRefMatch.GetAttr ( pAttr->m_tLocator );
193+
if ( pAttr->m_tLocator.m_bDynamic && !m_tRefMatch.m_pDynamic )
194+
continue;
195+
if ( !pAttr->m_tLocator.m_bDynamic && !m_tRefMatch.m_pStatic )
196+
continue;
197+
198+
auto pData = (BYTE *)m_tRefMatch.GetAttr ( pAttr->m_tLocator );
199+
if ( pData )
177200
sphDeallocatePacked(pData);
178-
}
179201
}
202+
203+
m_dAllocatedPtrAttrs.Resize(0);
180204
}
181205

182206
/////////////////////////////////////////////////////////////////////
@@ -218,9 +242,22 @@ static bool CanCreateScrollSorter ( bool bMulti, const ISphSchema & tSchema, con
218242
if ( !pAttr )
219243
return false;
220244

245+
ESphAttr eCheckType = pAttr->m_eAttrType;
246+
247+
// If the scroll token has a string type and the schema attribute is SPH_ATTR_STRING,
248+
// check if there's a remapped STRINGPTR version (used for sorting)
249+
if ( i.m_eType==SPH_ATTR_STRINGPTR && eCheckType==SPH_ATTR_STRING )
250+
{
251+
CSphString sRemappedName;
252+
sRemappedName.SetSprintf ( "@int_attr_%s", i.m_sSortAttr.cstr() );
253+
auto pRemapped = tSchema.GetAttr ( sRemappedName.cstr() );
254+
if ( pRemapped && pRemapped->m_eAttrType==SPH_ATTR_STRINGPTR )
255+
eCheckType = SPH_ATTR_STRINGPTR;
256+
}
257+
221258
bool bSupported = false;
222259
for ( auto eType : dSupportedTypes )
223-
if ( pAttr->m_eAttrType==eType )
260+
if ( eCheckType==eType )
224261
{
225262
bSupported = true;
226263
break;

0 commit comments

Comments
 (0)