Browse Source

fixed a crash on order by joined columnar attr; added test

Ilya Kuznetsov 2 years ago
parent
commit
4483186eac

+ 3 - 0
src/columnarsort.cpp

@@ -1115,6 +1115,9 @@ static bool CanCreateColumnarSorter ( const ISphSchema & tSchema, const CSphMatc
 		if ( sphIsDataPtrAttr ( tAttr.m_eAttrType ) )
 			return false;
 
+		if ( tAttr.IsJoined() )
+			return false;
+
 		// all sorter-related columnar attrs should be replaced by expressions at this point
 		assert ( !tAttr.IsColumnar() );
 		if ( tAttr.IsColumnarExpr() )

+ 4 - 4
src/joinsorter.cpp

@@ -387,7 +387,7 @@ void JoinSorter_c::SetupNullMask()
 				continue;
 
 			iDynamic++;
-			if ( tAttr.m_uAttrFlags & CSphColumnInfo::ATTR_JOINED )
+			if ( tAttr.IsJoined() )
 				iNumJoinAttrs = Max ( iNumJoinAttrs, iDynamic );
 		}
 
@@ -400,7 +400,7 @@ void JoinSorter_c::SetupNullMask()
 			if ( !tAttr.m_tLocator.m_bDynamic )
 				continue;
 
-			if ( tAttr.m_uAttrFlags & CSphColumnInfo::ATTR_JOINED )
+			if ( tAttr.IsJoined() )
 				tMask.BitSet(iDynamic);
 
 			iDynamic++;
@@ -421,7 +421,7 @@ void JoinSorter_c::SetupNullMask()
 		if ( !tAttr.m_tLocator.m_bDynamic )
 			continue;
 
-		if ( tAttr.m_uAttrFlags & CSphColumnInfo::ATTR_JOINED )
+		if ( tAttr.IsJoined() )
 			m_uNullMask |= 1ULL << iDynamic;
 
 		iDynamic++;
@@ -684,7 +684,7 @@ void JoinSorter_c::SetupRightFilters()
 		const CSphColumnInfo * pFilterAttr = m_pSorterSchema->GetAttr ( tFilter.m_sAttrName.cstr() );
 		if ( pFilterAttr )
 		{
-			if ( !(pFilterAttr->m_uAttrFlags & CSphColumnInfo::ATTR_JOINED ) )
+			if ( !pFilterAttr->IsJoined() )
 				continue;
 		}
 		else

+ 3 - 2
src/queuecreator.cpp

@@ -873,7 +873,7 @@ void QueueCreator_c::SelectExprEvalStage ( CSphColumnInfo & tExprCol )
 	if ( tExprCol.m_eAttrType==SPH_ATTR_JSON_FIELD )
 		return;
 
-	if ( tExprCol.m_uAttrFlags & CSphColumnInfo::ATTR_JOINED )
+	if ( tExprCol.IsJoined() )
 		return;
 
 	ARRAY_FOREACH ( i, m_tQuery.m_dFilters )
@@ -1500,6 +1500,7 @@ bool QueueCreator_c::AddJoinAttrs()
 			tAttr.m_eAttrType = sphPlainAttrToPtrAttr ( tAttr.m_eAttrType );
 			tAttr.m_tLocator.Reset();
 			tAttr.m_eStage = SPH_EVAL_SORTER;
+			tAttr.m_uAttrFlags &= ~( CSphColumnInfo::ATTR_COLUMNAR | CSphColumnInfo::ATTR_COLUMNAR_HASHES );
 			tAttr.m_uAttrFlags |= CSphColumnInfo::ATTR_JOINED;
 			m_pSorterSchema->AddAttr ( tAttr, true );
 
@@ -1550,7 +1551,7 @@ bool QueueCreator_c::AddNullBitmask()
 			continue;
 
 		iDynamic++;
-		if ( tAttr.m_uAttrFlags & CSphColumnInfo::ATTR_JOINED )
+		if ( tAttr.IsJoined() )
 			iNumJoinAttrs = Max ( iNumJoinAttrs, iDynamic );
 	}
 

+ 7 - 0
src/schema/columninfo.cpp

@@ -71,6 +71,13 @@ bool CSphColumnInfo::IsIndexedKNN() const
 }
 
 
+bool CSphColumnInfo::IsJoined() const
+{
+	return m_uAttrFlags & ATTR_JOINED;
+}
+
+
+
 CSphString sphDumpAttr ( const CSphColumnInfo & tAttr )
 {
 	CSphString sRes;

+ 1 - 0
src/schema/columninfo.h

@@ -89,6 +89,7 @@ struct CSphColumnInfo
 	bool IsColumnarExpr() const;
 	bool IsStoredExpr() const;
 	bool IsIndexedKNN() const;
+	bool IsJoined() const;
 };
 
 

+ 1 - 1
src/sortsetup.cpp

@@ -357,7 +357,7 @@ bool SortStateSetup_c::SetupColumnar ( CSphString & sError )
 		return true;
 
 	const CSphColumnInfo & tAttr = m_tSchema.GetAttr(m_iAttr);
-	if ( !tAttr.IsColumnar() )
+	if ( !tAttr.IsColumnar() || tAttr.IsJoined() )
 		return true;
 
 	ExprParseArgs_t tExprArgs;

+ 3 - 1
src/sphinxexpr.cpp

@@ -9776,7 +9776,9 @@ int	ExprParser_t::AddNodeWithTable ( const char * szTable, uint64_t uOffset )
 
 	YYSTYPE yylval;
 	int iType = ParseAttr ( iAttr, m_pSchema->GetAttr(iAttr).m_sName.cstr(), &yylval );
-	return AddNodeAttr ( iType, yylval.iAttrLocator );
+
+	bool bColumnar = iType==TOK_COLUMNAR_INT || iType==SPH_ATTR_TIMESTAMP || iType==TOK_COLUMNAR_TIMESTAMP || iType==SPH_ATTR_FLOAT || iType==TOK_COLUMNAR_FLOAT || iType==TOK_COLUMNAR_BIGINT || iType==TOK_COLUMNAR_BOOL || iType==TOK_COLUMNAR_STRING || iType==TOK_COLUMNAR_UINT32SET || iType==TOK_COLUMNAR_INT64SET || iType==TOK_COLUMNAR_FLOATVEC;
+	return bColumnar ? AddNodeColumnar ( iType, yylval.iAttrLocator ) : AddNodeAttr ( iType, yylval.iAttrLocator );
 }
 
 

+ 1 - 6
src/sphinxfilter.cpp

@@ -1615,12 +1615,7 @@ static void RemoveJoinFilters ( const CreateFilterContext_t & tCtx, CSphVector<C
 	for ( int i = dModified.GetLength()-1; i>=0; i-- )
 	{
 		const CSphColumnInfo * pAttr = tCtx.m_pSchema->GetAttr ( dModified[i].m_sAttrName.cstr() );
-		bool bRemove = false;
-		if ( pAttr )
-			bRemove = pAttr->m_uAttrFlags & CSphColumnInfo::ATTR_JOINED;
-		else
-			bRemove = dModified[i].m_sAttrName.Begins ( sPrefix.cstr() );
-
+		bool bRemove = pAttr ? pAttr->IsJoined() : dModified[i].m_sAttrName.Begins ( sPrefix.cstr() );
 		if ( bRemove )
 			dModified.Remove(i);		
 	}

+ 1 - 0
test/test_279/model.bin

@@ -0,0 +1 @@
+a:1:{i:0;a:7:{i:0;a:2:{s:8:"sphinxql";s:105:"CREATE TABLE users (id bigint, name text, surname text, email text, reg_date timestamp) engine='columnar'";s:14:"total_affected";i:0;}i:1;a:2:{s:8:"sphinxql";s:184:"CREATE TABLE orders (id bigint, user_id bigint, name text, description text, price float, order_date timestamp, attr json, region_id int, confirm bool, analogs multi) engine='columnar'";s:14:"total_affected";i:0;}i:2;a:2:{s:8:"sphinxql";s:107:"INSERT INTO users (id, name, surname, email, reg_date) VALUES (1, 'Fedor', 'Zaycev', '[email protected]', 1708865549)";s:14:"total_affected";i:1;}i:3;a:2:{s:8:"sphinxql";s:214:"INSERT INTO orders (id, user_id, name, description, price, order_date, attr, region_id, confirm, analogs) VALUES (0, 1, 'iPhone', '14Pro', 1500.50, 1708866233, '{"color":"black","size":14}', 178, 'TRUE', (9,11,15))";s:14:"total_affected";i:1;}i:4;a:3:{s:8:"sphinxql";s:94:"SELECT id, name FROM users INNER JOIN orders ON users.id=orders.user_id ORDER BY orders.id ASC";s:10:"total_rows";i:1;s:4:"rows";a:1:{i:0;a:2:{s:2:"id";s:1:"1";s:4:"name";s:5:"Fedor";}}}i:5;a:2:{s:8:"sphinxql";s:16:"DROP TABLE users";s:14:"total_affected";i:0;}i:6;a:2:{s:8:"sphinxql";s:17:"DROP TABLE orders";s:14:"total_affected";i:0;}}}

+ 36 - 0
test/test_279/test.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<test>
+
+<name>JOIN vs columnar attributes</name>
+
+<requires>
+<force-rt/>
+<columnar/>
+</requires>
+
+<skip_indexer/>
+
+<config>
+searchd
+{
+    <searchd_settings/>
+    data_dir = <data_path/>
+	binlog_path = <data_path/>
+}
+</config>
+
+<queries>
+<sphinxql>
+CREATE TABLE users (id bigint, name text, surname text, email text, reg_date timestamp) engine='columnar';
+CREATE TABLE orders (id bigint, user_id bigint, name text, description text, price float, order_date timestamp, attr json, region_id int, confirm bool, analogs multi) engine='columnar';
+INSERT INTO users (id, name, surname, email, reg_date) VALUES (1, 'Fedor', 'Zaycev', '[email protected]', 1708865549);
+INSERT INTO orders (id, user_id, name, description, price, order_date, attr, region_id, confirm, analogs) VALUES (0, 1, 'iPhone', '14Pro', 1500.50, 1708866233, '{"color":"black","size":14}', 178, 'TRUE', (9,11,15));
+
+SELECT id, name FROM users INNER JOIN orders ON users.id=orders.user_id ORDER BY orders.id ASC;
+
+DROP TABLE users;
+DROP TABLE orders;
+</sphinxql>
+</queries>
+
+</test>