77
88import java .util .ArrayList ;
99import java .util .HashMap ;
10- import java .util .HashSet ;
1110import java .util .List ;
1211import java .util .Map ;
13- import java .util .Set ;
1412import java .util .stream .Collectors ;
1513import org .apache .calcite .rel .RelNode ;
1614import org .apache .calcite .rel .type .RelDataType ;
@@ -41,7 +39,7 @@ public static List<RelNode> buildUnifiedSchemaWithConflictResolution(
4139 return nodes ;
4240 }
4341
44- // Step 1: Build the unified schema by processing all nodes
42+ // Step 1: Build the unified schema by processing all nodes (throws on conflict)
4543 List <SchemaField > unifiedSchema = buildUnifiedSchema (nodes );
4644
4745 // Step 2: Create projections for each node to align with unified schema
@@ -55,44 +53,37 @@ public static List<RelNode> buildUnifiedSchemaWithConflictResolution(
5553 projectedNodes .add (projectedNode );
5654 }
5755
58- // Step 3: Check for type conflicts and throw exception if found
59- Set <String > uniqueFieldNames = new HashSet <>();
60- for (String fieldName : fieldNames ) {
61- if (!uniqueFieldNames .add (fieldName )) {
62- throw new IllegalArgumentException (
63- String .format (
64- "Schema unification failed: field '%s' has conflicting types across subsearches" ,
65- fieldName ));
66- }
67- }
68-
6956 return projectedNodes ;
7057 }
7158
7259 /**
73- * Builds a unified schema by merging fields from all nodes. Fields with the same name but
74- * different types are added as separate entries (will cause an exception to be thrown) .
60+ * Builds a unified schema by merging fields from all nodes. Throws an exception if fields with
61+ * the same name have different types .
7562 *
7663 * @param nodes List of RelNodes to merge schemas from
77- * @return List of SchemaField representing the unified schema (may contain duplicate names if
78- * there are type conflicts)
64+ * @return List of SchemaField representing the unified schema
65+ * @throws IllegalArgumentException if type conflicts are detected
7966 */
8067 private static List <SchemaField > buildUnifiedSchema (List <RelNode > nodes ) {
8168 List <SchemaField > schema = new ArrayList <>();
82- Map <String , Set < RelDataType > > seenFields = new HashMap <>();
69+ Map <String , RelDataType > seenFields = new HashMap <>();
8370
8471 for (RelNode node : nodes ) {
8572 for (RelDataTypeField field : node .getRowType ().getFieldList ()) {
8673 String fieldName = field .getName ();
8774 RelDataType fieldType = field .getType ();
8875
89- // Track which (name, type) combinations we've seen
90- Set <RelDataType > typesForName = seenFields .computeIfAbsent (fieldName , k -> new HashSet <>());
91-
92- if (!typesForName .contains (fieldType )) {
93- // New field or same name with different type - add to schema
76+ RelDataType existingType = seenFields .get (fieldName );
77+ if (existingType == null ) {
78+ // New field - add to schema
9479 schema .add (new SchemaField (fieldName , fieldType ));
95- typesForName .add (fieldType );
80+ seenFields .put (fieldName , fieldType );
81+ } else if (!existingType .equals (fieldType )) {
82+ // Same field name but different type - throw exception
83+ throw new IllegalArgumentException (
84+ String .format (
85+ "Schema unification failed: field '%s' has conflicting types across subsearches" ,
86+ fieldName ));
9687 }
9788 // If we've seen this exact (name, type) combination, skip it
9889 }
0 commit comments