Skip to content

Commit 2b0f390

Browse files
Vladimir Ozerovwebashutosh
authored andcommitted
Do not read HD entries from SQL schema resolver (hazelcast#17414)
1 parent c2c5306 commit 2b0f390

File tree

3 files changed

+154
-85
lines changed

3 files changed

+154
-85
lines changed

hazelcast-sql/src/main/java/com/hazelcast/sql/impl/calcite/opt/physical/visitor/PlanCreateVisitor.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.hazelcast.sql.impl.calcite.opt.physical.visitor;
1818

1919
import com.hazelcast.internal.util.collection.PartitionIdSet;
20-
import com.hazelcast.spi.properties.ClusterProperty;
2120
import com.hazelcast.sql.SqlColumnMetadata;
2221
import com.hazelcast.sql.SqlRowMetadata;
2322
import com.hazelcast.sql.impl.QueryException;
@@ -53,7 +52,6 @@
5352
import com.hazelcast.sql.impl.plan.node.io.RootSendPlanNode;
5453
import com.hazelcast.sql.impl.schema.map.AbstractMapTable;
5554
import com.hazelcast.sql.impl.schema.map.MapTableField;
56-
import com.hazelcast.sql.impl.schema.map.PartitionedMapTable;
5755
import com.hazelcast.sql.impl.type.QueryDataType;
5856
import org.apache.calcite.rex.RexNode;
5957

@@ -222,14 +220,6 @@ private static SqlRowMetadata createRowMetadata(List<String> columnNames, List<Q
222220
public void onMapScan(MapScanPhysicalRel rel) {
223221
AbstractMapTable table = rel.getMap();
224222

225-
if (((PartitionedMapTable) table).isHd()) {
226-
throw QueryException.error("Cannot query the IMap \"" + table.getMapName()
227-
+ "\" with InMemoryFormat.NATIVE because it does not have global indexes "
228-
+ "(please make sure that the IMap has at least one index "
229-
+ "and the property \"" + ClusterProperty.GLOBAL_HD_INDEX_ENABLED.getName()
230-
+ "\" is set to \"true\")");
231-
}
232-
233223
HazelcastTable hazelcastTable = rel.getTableUnwrapped();
234224

235225
PlanNodeSchema schemaBefore = getScanSchemaBeforeProject(table);

hazelcast/src/main/java/com/hazelcast/sql/impl/schema/map/MapTableUtils.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.hazelcast.sql.impl.schema.map;
1818

1919
import com.hazelcast.cluster.memberselector.MemberSelectors;
20-
import com.hazelcast.config.InMemoryFormat;
2120
import com.hazelcast.config.IndexConfig;
2221
import com.hazelcast.core.TypeConverter;
2322
import com.hazelcast.internal.util.collection.PartitionIdSet;
@@ -41,8 +40,6 @@
4140
import java.util.List;
4241
import java.util.Map;
4342

44-
import static com.hazelcast.spi.properties.ClusterProperty.GLOBAL_HD_INDEX_ENABLED;
45-
4643
/**
4744
* Utility methods for schema resolution.
4845
*/
@@ -75,19 +72,7 @@ public static long estimatePartitionedMapRowCount(NodeEngine nodeEngine, MapServ
7572
return entryCount * memberCount;
7673
}
7774

78-
public static List<MapTableIndex> getPartitionedMapIndexes(
79-
NodeEngine nodeEngine,
80-
MapContainer mapContainer,
81-
List<TableField> fields
82-
) {
83-
// Do no return non-concurrent indexes for HD maps.
84-
boolean hd = mapContainer.getMapConfig().getInMemoryFormat() == InMemoryFormat.NATIVE;
85-
boolean globalIndexEnabled = nodeEngine.getProperties().getBoolean(GLOBAL_HD_INDEX_ENABLED);
86-
87-
if (hd && !globalIndexEnabled) {
88-
return Collections.emptyList();
89-
}
90-
75+
public static List<MapTableIndex> getPartitionedMapIndexes(MapContainer mapContainer, List<TableField> fields) {
9176
Map<QueryPath, Integer> pathToOrdinalMap = mapPathsToOrdinals(fields);
9277

9378
InternalIndex[] indexes = mapContainer.getIndexes().getIndexes();

hazelcast/src/main/java/com/hazelcast/sql/impl/schema/map/PartitionedMapTableResolver.java

Lines changed: 153 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
import com.hazelcast.map.impl.PartitionContainer;
2727
import com.hazelcast.map.impl.record.Record;
2828
import com.hazelcast.map.impl.recordstore.RecordStore;
29+
import com.hazelcast.query.impl.InternalIndex;
30+
import com.hazelcast.query.impl.QueryableEntry;
2931
import com.hazelcast.spi.impl.NodeEngine;
32+
import com.hazelcast.spi.properties.ClusterProperty;
3033
import com.hazelcast.sql.impl.QueryException;
3134
import com.hazelcast.sql.impl.QueryUtils;
3235
import com.hazelcast.sql.impl.schema.ConstantTableStatistics;
@@ -45,6 +48,7 @@
4548
import java.util.Map;
4649
import java.util.Set;
4750

51+
import static com.hazelcast.spi.properties.ClusterProperty.GLOBAL_HD_INDEX_ENABLED;
4852
import static com.hazelcast.sql.impl.QueryUtils.SCHEMA_NAME_PARTITIONED;
4953

5054
public class PartitionedMapTableResolver extends AbstractMapTableResolver {
@@ -86,14 +90,13 @@ public List<Table> getTables() {
8690
}
8791

8892
if (knownNames.add(configMapName)) {
89-
res.add(emptyMap(configMapName));
93+
res.add(emptyError(configMapName));
9094
}
9195
}
9296

9397
return res;
9498
}
9599

96-
@SuppressWarnings({"rawtypes", "checkstyle:MethodLength", "checkstyle:CyclomaticComplexity", "checkstyle:NPathComplexity"})
97100
private PartitionedMapTable createTable(
98101
NodeEngine nodeEngine,
99102
MapServiceContext context,
@@ -107,64 +110,46 @@ private PartitionedMapTable createTable(
107110
return null;
108111
}
109112

110-
MapConfig config = mapContainer.getMapConfig();
111-
112-
for (PartitionContainer partitionContainer : context.getPartitionContainers()) {
113-
// Resolve sample.
114-
RecordStore<?> recordStore = partitionContainer.getExistingRecordStore(name);
115-
116-
if (recordStore == null) {
117-
continue;
118-
}
119-
120-
Iterator<Map.Entry<Data, Record>> recordStoreIterator = recordStore.iterator();
121-
122-
if (!recordStoreIterator.hasNext()) {
123-
continue;
124-
}
125-
126-
Map.Entry<Data, Record> entry = recordStoreIterator.next();
127-
128-
InternalSerializationService ss = (InternalSerializationService) nodeEngine.getSerializationService();
129-
130-
MapSampleMetadata keyMetadata = MapSampleMetadataResolver.resolve(
131-
ss,
132-
jetMapMetadataResolver,
133-
entry.getKey(),
134-
true
135-
);
136-
137-
MapSampleMetadata valueMetadata = MapSampleMetadataResolver.resolve(
138-
ss,
139-
jetMapMetadataResolver,
140-
entry.getValue().getValue(),
141-
false
142-
);
143-
144-
List<TableField> fields = mergeMapFields(keyMetadata.getFields(), valueMetadata.getFields());
145-
146-
long estimatedRowCount = MapTableUtils.estimatePartitionedMapRowCount(nodeEngine, context, name);
147-
148-
// Resolve indexes.
149-
List<MapTableIndex> indexes = MapTableUtils.getPartitionedMapIndexes(nodeEngine, mapContainer, fields);
150-
151-
// Done.
152-
return new PartitionedMapTable(
153-
SCHEMA_NAME_PARTITIONED,
154-
name,
155-
name,
156-
fields,
157-
new ConstantTableStatistics(estimatedRowCount),
158-
keyMetadata.getDescriptor(),
159-
valueMetadata.getDescriptor(),
160-
keyMetadata.getJetMetadata(),
161-
valueMetadata.getJetMetadata(),
162-
indexes,
163-
config.getInMemoryFormat() == InMemoryFormat.NATIVE
164-
);
113+
boolean hd = mapContainer.getMapConfig().getInMemoryFormat() == InMemoryFormat.NATIVE;
114+
115+
FieldsMetadata fieldsMetadata;
116+
117+
if (hd) {
118+
fieldsMetadata = getHdMapFields(mapContainer);
119+
} else {
120+
fieldsMetadata = getHeapMapFields(context, name);
121+
}
122+
123+
if (fieldsMetadata.emptyError) {
124+
return emptyError(name);
125+
} else if (fieldsMetadata.hdError) {
126+
return hdError(name);
165127
}
166128

167-
return emptyMap(name);
129+
MapSampleMetadata keyMetadata = fieldsMetadata.keyMetadata;
130+
MapSampleMetadata valueMetadata = fieldsMetadata.valueMetadata;
131+
132+
List<TableField> fields = mergeMapFields(keyMetadata.getFields(), valueMetadata.getFields());
133+
134+
long estimatedRowCount = MapTableUtils.estimatePartitionedMapRowCount(nodeEngine, context, name);
135+
136+
// Resolve indexes.
137+
List<MapTableIndex> indexes = MapTableUtils.getPartitionedMapIndexes(mapContainer, fields);
138+
139+
// Done.
140+
return new PartitionedMapTable(
141+
SCHEMA_NAME_PARTITIONED,
142+
name,
143+
name,
144+
fields,
145+
new ConstantTableStatistics(estimatedRowCount),
146+
keyMetadata.getDescriptor(),
147+
valueMetadata.getDescriptor(),
148+
keyMetadata.getJetMetadata(),
149+
valueMetadata.getJetMetadata(),
150+
indexes,
151+
hd
152+
);
168153
} catch (QueryException e) {
169154
return new PartitionedMapTable(name, e);
170155
} catch (Exception e) {
@@ -174,11 +159,120 @@ private PartitionedMapTable createTable(
174159
}
175160
}
176161

177-
private static PartitionedMapTable emptyMap(String mapName) {
162+
@SuppressWarnings("rawtypes")
163+
private FieldsMetadata getHeapMapFields(MapServiceContext context, String name) {
164+
for (PartitionContainer partitionContainer : context.getPartitionContainers()) {
165+
// Resolve sample.
166+
RecordStore<?> recordStore = partitionContainer.getExistingRecordStore(name);
167+
168+
if (recordStore == null) {
169+
continue;
170+
}
171+
172+
Iterator<Map.Entry<Data, Record>> recordStoreIterator = recordStore.iterator();
173+
174+
if (!recordStoreIterator.hasNext()) {
175+
continue;
176+
}
177+
178+
Map.Entry<Data, Record> entry = recordStoreIterator.next();
179+
180+
return getFieldMetadata(entry.getKey(), entry.getValue().getValue());
181+
}
182+
183+
return FieldsMetadata.EMPTY_ERROR;
184+
}
185+
186+
@SuppressWarnings("rawtypes")
187+
private FieldsMetadata getHdMapFields(MapContainer mapContainer) {
188+
if (!nodeEngine.getProperties().getBoolean(GLOBAL_HD_INDEX_ENABLED)) {
189+
// Cannot resolve fields when concurrent indexes are disabled
190+
return FieldsMetadata.HD_ERROR;
191+
}
192+
193+
InternalIndex[] indexes = mapContainer.getIndexes().getIndexes();
194+
195+
if (indexes == null || indexes.length == 0) {
196+
// Cannot resolve fields when the map doesn't have concurrent indexes
197+
return FieldsMetadata.HD_ERROR;
198+
}
199+
200+
InternalIndex index = indexes[0];
201+
202+
Iterator<QueryableEntry> entryIterator = index.getSqlRecordIterator();
203+
204+
if (!entryIterator.hasNext()) {
205+
return FieldsMetadata.EMPTY_ERROR;
206+
}
207+
208+
QueryableEntry entry = entryIterator.next();
209+
210+
return getFieldMetadata(entry.getKey(), entry.getValue());
211+
}
212+
213+
private static PartitionedMapTable emptyError(String mapName) {
178214
QueryException error = QueryException.error(
179215
"Cannot resolve IMap schema because it doesn't have entries on the local member: " + mapName
180216
);
181217

182218
return new PartitionedMapTable(mapName, error);
183219
}
220+
221+
private static PartitionedMapTable hdError(String mapName) {
222+
QueryException error = QueryException.error("Cannot query the IMap \"" + mapName
223+
+ "\" with InMemoryFormat.NATIVE because it does not have global indexes "
224+
+ "(please make sure that the IMap has at least one index "
225+
+ "and the property \"" + ClusterProperty.GLOBAL_HD_INDEX_ENABLED.getName()
226+
+ "\" is set to \"true\")"
227+
);
228+
229+
return new PartitionedMapTable(mapName, error);
230+
}
231+
232+
private FieldsMetadata getFieldMetadata(Object key, Object value) {
233+
InternalSerializationService ss = (InternalSerializationService) nodeEngine.getSerializationService();
234+
235+
MapSampleMetadata keyMetadata = MapSampleMetadataResolver.resolve(
236+
ss,
237+
jetMapMetadataResolver,
238+
key,
239+
true
240+
);
241+
242+
MapSampleMetadata valueMetadata = MapSampleMetadataResolver.resolve(
243+
ss,
244+
jetMapMetadataResolver,
245+
value,
246+
false
247+
);
248+
249+
return new FieldsMetadata(keyMetadata, valueMetadata);
250+
}
251+
252+
private static final class FieldsMetadata {
253+
254+
private static final FieldsMetadata EMPTY_ERROR = new FieldsMetadata(null, null, true, false);
255+
private static final FieldsMetadata HD_ERROR = new FieldsMetadata(null, null, false, true);
256+
257+
private final MapSampleMetadata keyMetadata;
258+
private final MapSampleMetadata valueMetadata;
259+
private final boolean emptyError;
260+
private final boolean hdError;
261+
262+
private FieldsMetadata(MapSampleMetadata keyMetadata, MapSampleMetadata valueMetadata) {
263+
this(keyMetadata, valueMetadata, false, false);
264+
}
265+
266+
private FieldsMetadata(
267+
MapSampleMetadata keyMetadata,
268+
MapSampleMetadata valueMetadata,
269+
boolean emptyError,
270+
boolean hdError
271+
) {
272+
this.keyMetadata = keyMetadata;
273+
this.valueMetadata = valueMetadata;
274+
this.emptyError = emptyError;
275+
this.hdError = hdError;
276+
}
277+
}
184278
}

0 commit comments

Comments
 (0)