2626import com .hazelcast .map .impl .PartitionContainer ;
2727import com .hazelcast .map .impl .record .Record ;
2828import com .hazelcast .map .impl .recordstore .RecordStore ;
29+ import com .hazelcast .query .impl .InternalIndex ;
30+ import com .hazelcast .query .impl .QueryableEntry ;
2931import com .hazelcast .spi .impl .NodeEngine ;
32+ import com .hazelcast .spi .properties .ClusterProperty ;
3033import com .hazelcast .sql .impl .QueryException ;
3134import com .hazelcast .sql .impl .QueryUtils ;
3235import com .hazelcast .sql .impl .schema .ConstantTableStatistics ;
4548import java .util .Map ;
4649import java .util .Set ;
4750
51+ import static com .hazelcast .spi .properties .ClusterProperty .GLOBAL_HD_INDEX_ENABLED ;
4852import static com .hazelcast .sql .impl .QueryUtils .SCHEMA_NAME_PARTITIONED ;
4953
5054public 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