Ignite-950 - Implemented new configuration for indexes.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/6f741823 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/6f741823 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/6f741823 Branch: refs/heads/ignite-950-new Commit: 6f741823c16b0f6b2bc9506fdfe004f17af6f120 Parents: 81b899a Author: Alexey Goncharuk <[email protected]> Authored: Sat Oct 24 15:41:00 2015 +0300 Committer: Alexey Goncharuk <[email protected]> Committed: Sat Oct 24 15:41:00 2015 +0300 ---------------------------------------------------------------------- .../org/apache/ignite/cache/QueryEntity.java | 217 +++++++++++++++++++ .../apache/ignite/cache/QueryEntityIndex.java | 100 +++++++++ .../configuration/CacheConfiguration.java | 140 ++++++------ .../CacheObjectPortableProcessorImpl.java | 3 + .../processors/query/GridQueryProcessor.java | 150 ++++++++++++- .../IgniteCacheAbstractFieldsQuerySelfTest.java | 3 +- 6 files changed, 546 insertions(+), 67 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/6f741823/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java new file mode 100644 index 0000000..2cf8015 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntity.java @@ -0,0 +1,217 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ignite.cache; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.internal.A; + +/** + * Query entity is a description of {@link org.apache.ignite.IgniteCache cache} entry (composed of key and value) + * in a way of how it must be indexed and can be queried. + */ +public class QueryEntity implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Key type. */ + private String keyType; + + /** Value type. */ + private String valType; + + /** Fields available for query. A map from field name to type name. */ + private LinkedHashMap<String, String> fields = new LinkedHashMap<>(); + + /** Aliases. */ + private Map<String, String> aliases = new HashMap<>(); + + /** Collection of query indexes. */ + private Map<String, QueryEntityIndex> idxs = new HashMap<>(); + + /** + * Gets key type for this query pair. + * + * @return Key type. + */ + public String getKeyType() { + return keyType; + } + + /** + * Sets key type for this query pair. + * + * @param keyType Key type. + */ + public void setKeyType(String keyType) { + this.keyType = keyType; + } + + /** + * Gets value type for this query pair. + * + * @return Value type. + */ + public String getValueType() { + return valType; + } + + /** + * Sets value type for this query pair. + * + * @param valType Value type. + */ + public void setValueType(String valType) { + this.valType = valType; + } + + /** + * Gets query fields for this query pair. The order of fields is important as it defines the order + * of columns returned by the 'select *' queries. + * + * @return Field-to-type map. + */ + public LinkedHashMap<String, String> getFields() { + return fields; + } + + /** + * Sets query fields for this query pair. The order if fields is important as it defines the + * order of columns returned by the 'select *' queries. + * + * @param fields Field-to-type map. + */ + public void setFields(LinkedHashMap<String, String> fields) { + this.fields = fields; + } + + /** + * Gets a collection of index entities. + * + * @return Collection of index entities. + */ + public Collection<QueryEntityIndex> getIndexes() { + return idxs.values(); + } + + /** + * Gets aliases map. + * + * @return Aliases. + */ + public Map<String, String> getAliases() { + return aliases; + } + + /** + * Sets mapping from full property name in dot notation to an alias that will be used as SQL column name. + * Example: {"parent.name" -> "parentName"}. + + * @param aliases Aliases map. + */ + public void setAliases(Map<String, String> aliases) { + this.aliases = aliases; + } + + /** + * Sets a collection of index entities. + * + * @param idxs Collection of index entities. + */ + public void setIndexes(Collection<QueryEntityIndex> idxs) { + for (QueryEntityIndex idx : idxs) { + if (!F.isEmpty(idx.getFields())) { + if (idx.getName() == null) + idx.setName(defaultIndexName(idx)); + + if (!this.idxs.containsKey(idx.getName())) + this.idxs.put(idx.getName(), idx); + else + throw new IllegalArgumentException("Duplicate index name: " + idx.getName()); + } + } + } + + /** + * Utility method for building query entities programmatically. + */ + public void addQueryField(String fullName, String type, String alias) { + A.notNull(fullName, "fullName"); + A.notNull(type, "type"); + + fields.put(fullName, type); + + if (alias != null) + aliases.put(alias, fullName); + } + + /** + * Ensures that index with the given name exists. + * + * @param idxName Index name. + * @param idxType Index type. + */ + public void ensureIndex(String idxName, QueryEntityIndex.Type idxType) { + QueryEntityIndex idx = idxs.get(idxName); + + if (idx == null) { + idx = new QueryEntityIndex(); + + idx.setName(idxName); + idx.setType(idxType); + + idxs.put(idxName, idx); + } + else + throw new IllegalArgumentException("An index with the same name and of a different type already exists " + + "[idxName=" + idxName + ", existingIdxType=" + idx.getType() + ", newIdxType=" + idxType + ']'); + } + + /** + * Generates default index name by concatenating all index field names. + * + * @param idx Index to build name for. + * @return Index name. + */ + public static String defaultIndexName(QueryEntityIndex idx) { + StringBuilder idxName = new StringBuilder(); + + for (String field : idx.getFields()) { + idxName.append(field); + + idxName.append('_'); + } + + for (int i = 0; i < idxName.length(); i++) { + char ch = idxName.charAt(i); + + if (Character.isWhitespace(ch)) + idxName.setCharAt(i, '_'); + else + idxName.setCharAt(i, Character.toLowerCase(ch)); + } + + idxName.append("idx"); + + return idxName.toString(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/6f741823/modules/core/src/main/java/org/apache/ignite/cache/QueryEntityIndex.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/cache/QueryEntityIndex.java b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntityIndex.java new file mode 100644 index 0000000..18e7572 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryEntityIndex.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ignite.cache; + +import java.io.Serializable; +import java.util.Collection; + +/** + * Contains list of fields to be indexed. It is possible to provide field name + * suffixed with index specific extension, for example for {@link Type#SORTED sorted} index + * the list can be provided as following {@code (id, name asc, age desc)}. + */ +public class QueryEntityIndex implements Serializable { + /** */ + private static final long serialVersionUID = 0L; + + /** Index name. */ + private String name; + + /** */ + private Collection<String> fields; + + /** */ + private Type type; + + /** + * Index type. + */ + public enum Type { + SORTED, FULLTEXT, GEOSPATIAL + } + + /** + * Gets index name. Will be automatically set if not provided by a user. + * + * @return Index name. + */ + public String getName() { + return name; + } + + /** + * Sets index name. + * + * @param name Index name. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Gets fields included in the index. + * + * @return Collection of index fields. + */ + public Collection<String> getFields() { + return fields; + } + + /** + * Sets fields included in the index. + * + * @param fields Collection of index fields. + */ + public void setFields(Collection<String> fields) { + this.fields = fields; + } + + /** + * Gets index type. + * + * @return Index type. + */ + public Type getType() { + return type; + } + + /** + * Sets index type. + * + * @param type Index type. + */ + public void setType(Type type) { + this.type = type; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/6f741823/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java index 23d5256..ac527f6 100644 --- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java @@ -23,12 +23,14 @@ import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.TreeSet; import javax.cache.Cache; @@ -48,6 +50,8 @@ import org.apache.ignite.cache.CacheMode; import org.apache.ignite.cache.CacheRebalanceMode; import org.apache.ignite.cache.CacheTypeMetadata; import org.apache.ignite.cache.CacheWriteSynchronizationMode; +import org.apache.ignite.cache.QueryEntity; +import org.apache.ignite.cache.QueryEntityIndex; import org.apache.ignite.cache.affinity.AffinityFunction; import org.apache.ignite.cache.affinity.AffinityKeyMapper; import org.apache.ignite.cache.eviction.EvictionFilter; @@ -367,6 +371,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { /** Cache store session listeners. */ private Factory<? extends CacheStoreSessionListener>[] storeSesLsnrs; + /** Query entities. */ + private Collection<QueryEntity> qryEntities; + /** Empty constructor (all values are initialized to their defaults). */ public CacheConfiguration() { /* No-op. */ @@ -429,6 +436,8 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { name = cc.getName(); nearCfg = cc.getNearConfiguration(); nodeFilter = cc.getNodeFilter(); + pluginCfgs = cc.getPluginConfigurations(); + qryEntities = cc.getQueryEntities(); rebalanceMode = cc.getRebalanceMode(); rebalanceBatchSize = cc.getRebalanceBatchSize(); rebalanceDelay = cc.getRebalanceDelay(); @@ -453,7 +462,6 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { writeBehindFlushSize = cc.getWriteBehindFlushSize(); writeBehindFlushThreadCnt = cc.getWriteBehindFlushThreadCount(); writeSync = cc.getWriteSynchronizationMode(); - pluginCfgs = cc.getPluginConfigurations(); } /** @@ -1595,14 +1603,10 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { * * @param typeMeta Collection of type metadata. * @return {@code this} for chaining. + * @deprecated Use {@link #setQueryEntities(java.util.Collection)} instead. */ public CacheConfiguration<K, V> setTypeMetadata(Collection<CacheTypeMetadata> typeMeta) { - if (this.typeMeta == null) - this.typeMeta = new ArrayList<>(typeMeta); - else if (indexedTypes != null) - this.typeMeta.addAll(typeMeta); - else - throw new CacheException("Type metadata can be set only once."); + this.typeMeta = new ArrayList<>(typeMeta); return this; } @@ -1779,8 +1783,8 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { newIndexedTypes[i] = U.box(indexedTypes[i]); } - if (typeMeta == null) - typeMeta = new ArrayList<>(); + if (qryEntities == null) + qryEntities = new ArrayList<>(); for (int i = 0; i < len; i += 2) { Class<?> keyCls = newIndexedTypes[i]; @@ -1788,7 +1792,7 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { TypeDescriptor desc = processKeyAndValueClasses(keyCls, valCls); - typeMeta.add(convert(desc)); + qryEntities.add(convert(desc)); } return this; @@ -1841,6 +1845,32 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { } /** + * Gets a collection of configured query entities. + * + * @return Query entities configurations. + */ + public Collection<QueryEntity> getQueryEntities() { + return qryEntities != null ? qryEntities : Collections.<QueryEntity>emptyList(); + } + + /** + * Sets query entities configuration. + * + * @param qryEntities Query entities. + * @return {@code this} for chaining. + */ + public CacheConfiguration<K, V> setQueryEntities(Collection<QueryEntity> qryEntities) { + if (this.qryEntities == null) + this.qryEntities = new ArrayList<>(qryEntities); + else if (indexedTypes != null) + this.qryEntities.addAll(qryEntities); + else + throw new CacheException("Query entities can be set only once."); + + return this; + } + + /** * Gets topology validator. * <p> * See {@link TopologyValidator} for details. @@ -1911,85 +1941,65 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { * @param desc Type descriptor. * @return Type metadata. */ - private static CacheTypeMetadata convert(TypeDescriptor desc) { - CacheTypeMetadata meta = new CacheTypeMetadata(); + static QueryEntity convert(TypeDescriptor desc) { + QueryEntity entity = new QueryEntity(); // Key and val types. - meta.setKeyType(desc.keyClass()); - meta.setValueType(desc.valueClass()); - - // Query fields. - Map<String, Class<?>> qryFields = new HashMap<>(); + entity.setKeyType(desc.keyClass().getName()); + entity.setValueType(desc.valueClass().getName()); for (ClassProperty prop : desc.props.values()) - qryFields.put(prop.fullName(), mask(prop.type())); + entity.addQueryField(prop.fullName(), prop.type().getName(), prop.alias()); - meta.setQueryFields(qryFields); + QueryEntityIndex txtIdx = null; - // Indexes. - Collection<String> txtFields = new ArrayList<>(); - Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> grps = new HashMap<>(); + Collection<QueryEntityIndex> idxs = new ArrayList<>(); - for (Map.Entry<String,GridQueryIndexDescriptor> idxEntry : desc.indexes().entrySet()) { + for (Map.Entry<String, GridQueryIndexDescriptor> idxEntry : desc.indexes().entrySet()) { GridQueryIndexDescriptor idx = idxEntry.getValue(); if (idx.type() == FULLTEXT) { - assert txtFields.isEmpty(); + assert txtIdx == null; + + txtIdx = new QueryEntityIndex(); - txtFields.addAll(idx.fields()); + txtIdx.setType(QueryEntityIndex.Type.FULLTEXT); + txtIdx.setFields(new ArrayList<>(idx.fields())); } else { - LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>> grp = new LinkedHashMap<>(); - - for (String fieldName : idx.fields()) { - Class<?> cls; - - if (_VAL.equals(fieldName)) - cls = desc.valueClass(); - else { - ClassProperty prop = desc.props.get(fieldName); + Collection<String> grp = new ArrayList<>(); - assert prop != null : fieldName; + for (String fieldName : idx.fields()) + grp.add(idx.descending(fieldName) ? fieldName + " desc" : fieldName); - cls = prop.type(); - } + QueryEntityIndex sortedIdx = new QueryEntityIndex(); - cls = mask(cls); + sortedIdx.setType(QueryEntityIndex.Type.SORTED); + sortedIdx.setFields(grp); - grp.put(fieldName, new IgniteBiTuple<Class<?>, Boolean>(cls, idx.descending(fieldName))); - } - - grps.put(idxEntry.getKey(), grp); + idxs.add(sortedIdx); } } - meta.setGroups(grps); - - if (desc.valueTextIndex()) - txtFields.add(_VAL); - - if (!txtFields.isEmpty()) - meta.setTextFields(txtFields); + if (desc.valueTextIndex()) { + if (txtIdx == null) { + txtIdx = new QueryEntityIndex(); - // Aliases. - Map<String,String> aliases = null; + txtIdx.setType(QueryEntityIndex.Type.FULLTEXT); - for (ClassProperty prop : desc.props.values()) { - while (prop != null) { - if (!F.isEmpty(prop.alias)) { - if (aliases == null) - aliases = new HashMap<>(); - - aliases.put(prop.fullName(), prop.alias); - } - - prop = prop.parent; + txtIdx.setFields(Arrays.asList(_VAL)); } + else + txtIdx.getFields().add(_VAL); } - meta.setAliases(aliases); + if (txtIdx != null) + idxs.add(txtIdx); + + if (!F.isEmpty(idxs)) + entity.setIndexes(idxs); - return meta; + return entity; } /** @@ -2007,7 +2017,7 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { * @param valCls Value class. * @return Type descriptor. */ - private static TypeDescriptor processKeyAndValueClasses( + static TypeDescriptor processKeyAndValueClasses( Class<?> keyCls, Class<?> valCls ) { @@ -2177,7 +2187,7 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> { /** */ @GridToStringExclude - private final Map<String, ClassProperty> props = new HashMap<>(); + private final Map<String, ClassProperty> props = new LinkedHashMap<>(); /** */ @GridToStringInclude http://git-wip-us.apache.org/repos/asf/ignite/blob/6f741823/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java index 1be5aea..6ee6e12 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectPortableProcessorImpl.java @@ -417,6 +417,9 @@ public class CacheObjectPortableProcessorImpl extends IgniteCacheObjectProcessor /** {@inheritDoc} */ @Override public int typeId(String typeName) { + if (portableCtx == null) + return super.typeId(typeName); + return portableCtx.typeId(typeName); } http://git-wip-us.apache.org/repos/asf/ignite/blob/6f741823/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java index 5f7646b..a4a75fd 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java @@ -45,6 +45,8 @@ import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.cache.CacheTypeMetadata; +import org.apache.ignite.cache.QueryEntity; +import org.apache.ignite.cache.QueryEntityIndex; import org.apache.ignite.cache.query.QueryCursor; import org.apache.ignite.cache.query.SqlFieldsQuery; import org.apache.ignite.cache.query.SqlQuery; @@ -167,7 +169,9 @@ public class GridQueryProcessor extends GridProcessorAdapter { * @return {@code true} If query index must be enabled for this cache. */ public static boolean isEnabled(CacheConfiguration<?,?> ccfg) { - return !F.isEmpty(ccfg.getIndexedTypes()) || !F.isEmpty(ccfg.getTypeMetadata()); + return !F.isEmpty(ccfg.getIndexedTypes()) || + !F.isEmpty(ccfg.getTypeMetadata()) || + !F.isEmpty(ccfg.getQueryEntities()); } /** @@ -185,6 +189,56 @@ public class GridQueryProcessor extends GridProcessorAdapter { idx.registerCache(ccfg); try { + if (!F.isEmpty(ccfg.getQueryEntities())) { + for (QueryEntity qryEntity : ccfg.getQueryEntities()) { + if (F.isEmpty(qryEntity.getValueType())) + throw new IgniteCheckedException("Value type is not set: " + qryEntity); + + TypeDescriptor desc = new TypeDescriptor(); + + // Key and value classes still can be available if they are primitive or JDK part. + // We need that to set correct types for _key and _val columns. + Class<?> valCls = U.classForName(qryEntity.getValueType(), null); + + String simpleValType = valCls == null ? qryEntity.getValueType() : typeName(valCls); + + desc.name(simpleValType); + + desc.valueClass(valCls != null ? valCls : Object.class); + desc.keyClass( + qryEntity.getKeyType() == null ? + Object.class : + U.classForName(qryEntity.getKeyType(), Object.class)); + + TypeId typeId; + TypeId altTypeId = null; + + if (valCls == null || ctx.cacheObjects().isPortableEnabled(ccfg)) { + processPortableMeta(qryEntity, desc); + + typeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(qryEntity.getValueType())); + + if (valCls != null) + altTypeId = new TypeId(ccfg.getName(), valCls); + } + else { + processClassMeta(qryEntity, desc); + + typeId = new TypeId(ccfg.getName(), valCls); + altTypeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(qryEntity.getValueType())); + } + + addTypeByName(ccfg, desc); + types.put(typeId, desc); + + if (altTypeId != null) + types.put(altTypeId, desc); + + desc.registered(idx.registerType(ccfg.getName(), desc)); + + } + } + if (!F.isEmpty(ccfg.getTypeMetadata())) { for (CacheTypeMetadata meta : ccfg.getTypeMetadata()) { if (F.isEmpty(meta.getValueType())) @@ -1269,6 +1323,100 @@ public class GridQueryProcessor extends GridProcessorAdapter { } /** + * Processes declarative metadata for portable object. + * + * @param qryEntity Declared metadata. + * @param d Type descriptor. + * @throws IgniteCheckedException If failed. + */ + private void processPortableMeta(QueryEntity qryEntity, TypeDescriptor d) throws IgniteCheckedException { + Map<String,String> aliases = qryEntity.getAliases(); + + if (aliases == null) + aliases = Collections.emptyMap(); + + for (Map.Entry<String, String> entry : qryEntity.getFields().entrySet()) { + PortableProperty prop = buildPortableProperty(entry.getKey(), U.classForName(entry.getValue(), Object.class), aliases); + + d.addProperty(prop, false); + } + + processIndexes(qryEntity, d); + } + + /** + * Processes declarative metadata for portable object. + * + * @param qryEntity Declared metadata. + * @param d Type descriptor. + * @throws IgniteCheckedException If failed. + */ + private void processClassMeta(QueryEntity qryEntity, TypeDescriptor d) throws IgniteCheckedException { + Map<String,String> aliases = qryEntity.getAliases(); + + if (aliases == null) + aliases = Collections.emptyMap(); + + for (Map.Entry<String, String> entry : qryEntity.getFields().entrySet()) { + ClassProperty prop = buildClassProperty( + d.keyClass(), + d.valueClass(), + entry.getKey(), + U.classForName(entry.getValue(), Object.class), + aliases); + + + d.addProperty(prop, false); + } + + processIndexes(qryEntity, d); + } + + /** + * Processes indexes based on query entity. + * + * @param qryEntity Query entity to process. + * @param d Type descriptor to populate. + * @throws IgniteCheckedException If failed to build index information. + */ + private void processIndexes(QueryEntity qryEntity, TypeDescriptor d) throws IgniteCheckedException { + if (!F.isEmpty(qryEntity.getIndexes())) { + for (QueryEntityIndex idx : qryEntity.getIndexes()) { + String idxName = idx.getName(); + + if (idxName == null) + idxName = QueryEntity.defaultIndexName(idx); + + if (idx.getType() == QueryEntityIndex.Type.SORTED || idx.getType() == QueryEntityIndex.Type.GEOSPATIAL) { + d.addIndex(idxName, idx.getType() == QueryEntityIndex.Type.SORTED ? SORTED : GEO_SPATIAL); + + int i = 0; + + for (String field : idx.getFields()) { + boolean desc = false; + + int space = field.indexOf(' '); + + if (space != -1) { + desc = field.toLowerCase().startsWith("desc", space + 1); + + field = field.substring(0, space); + } + + d.addFieldToIndex(idxName, field, i++, desc); + } + } + else { + assert idx.getType() == QueryEntityIndex.Type.FULLTEXT; + + for (String field : idx.getFields()) + d.addFieldToTextIndex(field); + } + } + } + } + + /** * Builds portable object property. * * @param pathStr String representing path to the property. May contains dots '.' to identify http://git-wip-us.apache.org/repos/asf/ignite/blob/6f741823/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractFieldsQuerySelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractFieldsQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractFieldsQuerySelfTest.java index 17f929a..9ccb893 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractFieldsQuerySelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractFieldsQuerySelfTest.java @@ -143,7 +143,8 @@ public abstract class IgniteCacheAbstractFieldsQuerySelfTest extends GridCommonA } } - cache.setIndexedTypes(indexedTypes.toArray(new Class[indexedTypes.size()])); + if (!indexedTypes.isEmpty()) + cache.setIndexedTypes(indexedTypes.toArray(new Class[indexedTypes.size()])); if (cacheMode() == PARTITIONED) cache.setBackups(1);
