Repository: ignite Updated Branches: refs/heads/ignite-2.0 760cf952d -> efb7abce8
http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java index b9394ec..a00ea90 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java @@ -19,7 +19,7 @@ package org.apache.ignite.internal.processors.query.h2.opt; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; @@ -34,6 +34,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.KeyCacheObject; import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; import org.apache.ignite.internal.processors.query.h2.database.H2RowFactory; +import org.apache.ignite.internal.processors.query.h2.database.H2TreeIndex; import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemory; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.lang.IgniteBiTuple; @@ -41,6 +42,7 @@ import org.h2.command.ddl.CreateTableData; import org.h2.engine.Session; import org.h2.index.Index; import org.h2.index.IndexType; +import org.h2.index.SpatialIndex; import org.h2.message.DbException; import org.h2.result.Row; import org.h2.result.SearchRow; @@ -152,6 +154,14 @@ public class GridH2Table extends TableBase { assert idxs != null; + List<Index> clones = new ArrayList<>(idxs.size()); + for (Index index: idxs) { + Index clone = createDuplicateIndexIfNeeded(index); + if (clone != null) + clones.add(clone); + } + idxs.addAll(clones); + // Add scan index at 0 which is required by H2. if (idxs.size() >= 2 && index(0).getIndexType().isHash()) idxs.add(0, new GridH2PrimaryScanIndex(this, index(1), index(0))); @@ -365,6 +375,9 @@ public class GridH2Table extends TableBase { boolean reuseExisting = s != null; + if (!(idxs.get(i) instanceof GridH2IndexBase)) + continue; + s = index(i).takeSnapshot(s, qctx); if (reuseExisting && s == null) { // Existing snapshot was invalidated before we were able to reserve it. @@ -373,7 +386,8 @@ public class GridH2Table extends TableBase { qctx.clearSnapshots(); for (int j = 2; j < i; j++) - index(j).releaseSnapshot(); + if ((idxs.get(j) instanceof GridH2IndexBase)) + index(j).releaseSnapshot(); // Drop invalidated snapshot. actualSnapshot.compareAndSet(snapshots, null); @@ -406,7 +420,8 @@ public class GridH2Table extends TableBase { destroyed = true; for (int i = 1, len = idxs.size(); i < len; i++) - index(i).destroy(); + if (idxs.get(i) instanceof GridH2IndexBase) + index(i).destroy(); } finally { unlock(true); @@ -561,6 +576,8 @@ public class GridH2Table extends TableBase { // Put row if absent to all indexes sequentially. // Start from 3 because 0 - Scan (don't need to update), 1 - PK hash (already updated), 2 - PK (already updated). while (++i < len) { + if (!(idxs.get(i) instanceof GridH2IndexBase)) + continue; GridH2IndexBase idx = index(i); addToIndex(idx, pk, row, old, false); @@ -577,6 +594,8 @@ public class GridH2Table extends TableBase { // Remove row from all indexes. // Start from 3 because 0 - Scan (don't need to update), 1 - PK hash (already updated), 2 - PK (already updated). for (int i = 3, len = idxs.size(); i < len; i++) { + if (!(idxs.get(i) instanceof GridH2IndexBase)) + continue; Row res = index(i).remove(old); assert eq(pk, res, old) : "\n" + old + "\n" + res + "\n" + i + " -> " + index(i).getName(); @@ -650,7 +669,8 @@ public class GridH2Table extends TableBase { ArrayList<GridH2IndexBase> res = new ArrayList<>(idxs.size() - 2); for (int i = 2, len = idxs.size(); i < len; i++) - res.add(index(i)); + if (idxs.get(i) instanceof GridH2IndexBase) + res.add(index(i)); return res; } @@ -721,16 +741,24 @@ public class GridH2Table extends TableBase { assert idx != null; - ArrayList<Index> newIdxs = new ArrayList<>(idxs.size() + 1); + Index cloneIdx = createDuplicateIndexIfNeeded(idx); + + ArrayList<Index> newIdxs = new ArrayList<>( + idxs.size() + ((cloneIdx == null) ? 1 : 2)); newIdxs.addAll(idxs); newIdxs.add(idx); + if (cloneIdx != null) + newIdxs.add(cloneIdx); idxs = newIdxs; database.addSchemaObject(ses, idx); + if (cloneIdx != null) + database.addSchemaObject(ses, cloneIdx); + setModified(); return idx; @@ -762,23 +790,42 @@ public class GridH2Table extends TableBase { /** {@inheritDoc} */ @Override public void removeIndex(Index h2Idx) { + throw DbException.getUnsupportedException("must use removeIndex(session, idx)"); + } + + /** + * Remove the given index from the list. + * + * @param h2Idx the index to remove + */ + public void removeIndex(Session session, Index h2Idx) { lock(true); try { ArrayList<Index> idxs = new ArrayList<>(this.idxs); - for (int i = 2; i < idxs.size(); i++) { - GridH2IndexBase idx = (GridH2IndexBase)idxs.get(i); + Index targetIdx = (h2Idx instanceof GridH2ProxyIndex)? + ((GridH2ProxyIndex)h2Idx).underlyingIndex(): h2Idx; - if (idx != h2Idx) - continue; + for (int i = 2; i < idxs.size(); ) { + Index idx = idxs.get(i); - idxs.remove(i); + if (idx == targetIdx || (idx instanceof GridH2ProxyIndex && + ((GridH2ProxyIndex)idx).underlyingIndex() == targetIdx)) { - this.idxs = idxs; + idxs.remove(i); - return; + if (idx instanceof GridH2ProxyIndex && + idx.getSchema().findIndex(session, idx.getName()) != null) + database.removeSchemaObject(session, idx); + + continue; + } + + i++; } + + this.idxs = idxs; } finally { unlock(true); @@ -912,4 +959,47 @@ public class GridH2Table extends TableBase { return rowFactory; } + /** + * Creates proxy index for given target index. + * Proxy index refers to alternative key and val columns. + * + * @param target Index to clone. + * @return Proxy index. + */ + public Index createDuplicateIndexIfNeeded(Index target) { + if (!(target instanceof H2TreeIndex) && + !(target instanceof SpatialIndex)) + return null; + + IndexColumn[] cols = target.getIndexColumns(); + List<IndexColumn> proxyCols = new ArrayList<>(cols.length); + boolean modified = false; + for (int i = 0; i < cols.length; i++) { + IndexColumn col = cols[i]; + IndexColumn proxyCol = new IndexColumn(); + proxyCol.columnName = col.columnName; + proxyCol.column = col.column; + proxyCol.sortType = col.sortType; + + int altColId = desc.getAlternativeColumnId(proxyCol.column.getColumnId()); + if (altColId != proxyCol.column.getColumnId()) { + proxyCol.column = getColumn(altColId); + proxyCol.columnName = proxyCol.column.getName(); + modified = true; + } + + proxyCols.add(proxyCol); + } + + if (modified) { + String proxyName = target.getName() + "_proxy"; + + if (target.getIndexType().isSpatial()) + return new GridH2ProxySpatialIndex(this, proxyName, proxyCols, target); + + return new GridH2ProxyIndex(this, proxyName, proxyCols, target); + } + + return null; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java index 4395024..6671dc6 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java @@ -54,8 +54,8 @@ import org.apache.lucene.util.Version; import org.h2.util.JdbcUtils; import org.jetbrains.annotations.Nullable; -import static org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.KEY_FIELD_NAME; -import static org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.VAL_FIELD_NAME; +import static org.apache.ignite.internal.processors.query.QueryUtils.KEY_FIELD_NAME; +import static org.apache.ignite.internal.processors.query.QueryUtils.VAL_FIELD_NAME; /** * Lucene fulltext index. http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/DmlAstUtils.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/DmlAstUtils.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/DmlAstUtils.java index 91694ae..5a1d412 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/DmlAstUtils.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/DmlAstUtils.java @@ -24,7 +24,6 @@ import java.util.Set; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.internal.processors.query.IgniteSQLException; -import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing; import org.apache.ignite.internal.processors.query.h2.dml.FastUpdateArgument; import org.apache.ignite.internal.processors.query.h2.dml.FastUpdateArguments; import org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow; @@ -175,8 +174,15 @@ public final class DmlAstUtils { if (filter == null) return null; - if (update.cols().size() != 1 || - !IgniteH2Indexing.VAL_FIELD_NAME.equalsIgnoreCase(update.cols().get(0).columnName())) + if (update.cols().size() != 1) + return null; + + Table tbl = update.cols().get(0).column().getTable(); + if (!(tbl instanceof GridH2Table)) + return null; + + GridH2RowDescriptor desc = ((GridH2Table)tbl).rowDescriptor(); + if (!desc.isValueColumn(update.cols().get(0).column().getColumnId())) return null; GridSqlElement set = update.set().get(update.cols().get(0).columnName()); @@ -268,19 +274,29 @@ public final class DmlAstUtils { /** * @param op Operation. - * @param colName Column name to check. + * @param key true - check for key equality condition, + * otherwise check for value equality condition * @return Whether this condition is of form {@code colName} = ? */ - private static boolean isEqualityCondition(GridSqlOperation op, String colName) { + private static boolean isEqualityCondition(GridSqlOperation op, boolean key) { if (op.operationType() != GridSqlOperationType.EQUAL) return false; GridSqlElement left = op.child(0); GridSqlElement right = op.child(1); - return left instanceof GridSqlColumn && - colName.equals(((GridSqlColumn) left).columnName()) && - (right instanceof GridSqlConst || right instanceof GridSqlParameter); + if (!(left instanceof GridSqlColumn)) + return false; + + GridSqlColumn column = (GridSqlColumn)left; + if (!(column.column().getTable() instanceof GridH2Table)) + return false; + + GridH2RowDescriptor desc =((GridH2Table) column.column().getTable()).rowDescriptor(); + + return (key ? desc.isKeyColumn(column.column().getColumnId()) : + desc.isValueColumn(column.column().getColumnId())) && + (right instanceof GridSqlConst || right instanceof GridSqlParameter); } /** @@ -288,7 +304,7 @@ public final class DmlAstUtils { * @return Whether this condition is of form _key = ? */ private static boolean isKeyEqualityCondition(GridSqlOperation op) { - return isEqualityCondition(op, IgniteH2Indexing.KEY_FIELD_NAME); + return isEqualityCondition(op, true); } /** @@ -296,7 +312,7 @@ public final class DmlAstUtils { * @return Whether this condition is of form _val = ? */ private static boolean isValueEqualityCondition(GridSqlOperation op) { - return isEqualityCondition(op, IgniteH2Indexing.VAL_FIELD_NAME); + return isEqualityCondition(op, false); } http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectQueryArgumentsTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectQueryArgumentsTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectQueryArgumentsTest.java index 9d18b62..c845496 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectQueryArgumentsTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteBinaryObjectQueryArgumentsTest.java @@ -292,7 +292,7 @@ public class IgniteBinaryObjectQueryArgumentsTest extends GridCommonAbstractTest final SqlQuery<T, Person> qry = new SqlQuery<>(Person.class, "where _key=?"); - final SqlFieldsQuery fieldsQry = new SqlFieldsQuery("select * from Person where _key=?"); + final SqlFieldsQuery fieldsQry = new SqlFieldsQuery("select _key, _val, * from Person where _key=?"); qry.setLocal(isLocal()); fieldsQry.setLocal(isLocal()); @@ -335,7 +335,7 @@ public class IgniteBinaryObjectQueryArgumentsTest extends GridCommonAbstractTest final SqlQuery<Person, T> qry = new SqlQuery<>(valType, "where _val=?"); - final SqlFieldsQuery fieldsQry = new SqlFieldsQuery("select * from " + valType.getSimpleName() + " where _val=?"); + final SqlFieldsQuery fieldsQry = new SqlFieldsQuery("select _key, _val, * from " + valType.getSimpleName() + " where _val=?"); qry.setLocal(isLocal()); fieldsQry.setLocal(isLocal()); http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/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 fedeef6..fed8980 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 @@ -249,17 +249,13 @@ public abstract class IgniteCacheAbstractFieldsQuerySelfTest extends GridCommonA Map<String, String> fields = meta.fields("Person"); assert fields != null; - assert fields.size() == 5; + assert fields.size() == 3; if (binaryMarshaller) { - assert Object.class.getName().equals(fields.get("_KEY")); - assert Object.class.getName().equals(fields.get("_VAL")); assert Integer.class.getName().equals(fields.get("AGE")); assert Integer.class.getName().equals(fields.get("ORGID")); } else { - assert AffinityKey.class.getName().equals(fields.get("_KEY")); - assert Person.class.getName().equals(fields.get("_VAL")); assert int.class.getName().equals(fields.get("AGE")); assert int.class.getName().equals(fields.get("ORGID")); } @@ -310,18 +306,15 @@ public abstract class IgniteCacheAbstractFieldsQuerySelfTest extends GridCommonA Map<String, String> fields = meta.fields("Organization"); assert fields != null; - assertEquals("Fields: " + fields, 4, fields.size()); + assertEquals("Fields: " + fields, 2, fields.size()); if (binaryMarshaller) { - assert Object.class.getName().equals(fields.get("_VAL")); assert Integer.class.getName().equals(fields.get("ID")); } else { - assert Organization.class.getName().equals(fields.get("_VAL")); assert int.class.getName().equals(fields.get("ID")); } - assert String.class.getName().equals(fields.get("_KEY")); assert String.class.getName().equals(fields.get("NAME")); } else if (intCache.getName().equals(meta.cacheName())) { @@ -587,7 +580,7 @@ public abstract class IgniteCacheAbstractFieldsQuerySelfTest extends GridCommonA public void testSelectAllJoined() throws Exception { QueryCursor<List<?>> qry = personCache.query(sqlFieldsQuery( - String.format("select * from \"%s\".Person p, \"%s\".Organization o where p.orgId = o.id", + String.format("select p._key, p._val, p.*, o._key, o._val, o.* from \"%s\".Person p, \"%s\".Organization o where p.orgId = o.id", personCache.getName(), orgCache.getName()))); List<List<?>> res = new ArrayList<>(qry.getAll()); @@ -768,7 +761,7 @@ public abstract class IgniteCacheAbstractFieldsQuerySelfTest extends GridCommonA cache.put(key, val); - Collection<List<?>> res = cache.query(sqlFieldsQuery("select * from Person")).getAll(); + Collection<List<?>> res = cache.query(sqlFieldsQuery("select _key, _val, * from Person")).getAll(); assertEquals(1, res.size()); http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDeleteSqlQuerySelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDeleteSqlQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDeleteSqlQuerySelfTest.java index 12662db..92c40b8 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDeleteSqlQuerySelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDeleteSqlQuerySelfTest.java @@ -39,7 +39,7 @@ public class IgniteCacheDeleteSqlQuerySelfTest extends IgniteCacheAbstractSqlDml c.iterator(); - c = p.query(new SqlFieldsQuery("select * from Person order by id")); + c = p.query(new SqlFieldsQuery("select _key, _val, * from Person order by id")); List<List<?>> leftovers = c.getAll(); @@ -63,7 +63,7 @@ public class IgniteCacheDeleteSqlQuerySelfTest extends IgniteCacheAbstractSqlDml c.iterator(); - c = p.query(new SqlFieldsQuery("select * from Person order by id, _key")); + c = p.query(new SqlFieldsQuery("select _key, _val, * from Person order by id, _key")); List<List<?>> leftovers = c.getAll(); @@ -91,7 +91,7 @@ public class IgniteCacheDeleteSqlQuerySelfTest extends IgniteCacheAbstractSqlDml c.iterator(); - c = p.query(new SqlFieldsQuery("select * from Person order by id")); + c = p.query(new SqlFieldsQuery("select _key, _val, * from Person order by id")); List<List<?>> leftovers = c.getAll(); http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheUpdateSqlQuerySelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheUpdateSqlQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheUpdateSqlQuerySelfTest.java index 3626341..20cbe3a 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheUpdateSqlQuerySelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheUpdateSqlQuerySelfTest.java @@ -73,7 +73,7 @@ public class IgniteCacheUpdateSqlQuerySelfTest extends IgniteCacheAbstractSqlDml c.iterator(); - c = p.query(new SqlFieldsQuery("select * from Person order by _key, id")); + c = p.query(new SqlFieldsQuery("select _key, _val, * from Person order by _key, id")); List<List<?>> leftovers = c.getAll(); @@ -103,7 +103,7 @@ public class IgniteCacheUpdateSqlQuerySelfTest extends IgniteCacheAbstractSqlDml c.iterator(); - c = p.query(new SqlFieldsQuery("select * from Person order by id, _key")); + c = p.query(new SqlFieldsQuery("select _key, _val, * from Person order by id, _key")); List<List<?>> leftovers = c.getAll(); @@ -133,7 +133,7 @@ public class IgniteCacheUpdateSqlQuerySelfTest extends IgniteCacheAbstractSqlDml c.iterator(); - c = p.query(new SqlFieldsQuery("select * from Person order by _key, id")); + c = p.query(new SqlFieldsQuery("select _key, _val, * from Person order by _key, id")); List<List<?>> leftovers = c.getAll(); @@ -163,7 +163,7 @@ public class IgniteCacheUpdateSqlQuerySelfTest extends IgniteCacheAbstractSqlDml c.iterator(); - c = p.query(new SqlFieldsQuery("select * from Person order by _key, id")); + c = p.query(new SqlFieldsQuery("select _key, _val, * from Person order by _key, id")); List<List<?>> leftovers = c.getAll(); http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java index 19d6f54..1f50244 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java @@ -82,6 +82,9 @@ public class AbstractSchemaSelfTest extends GridCommonAbstractTest { /** Field 3. */ protected static final String FIELD_NAME_3 = "field3"; + /** Key alias */ + protected static final String FIELD_KEY_ALIAS = "key"; + /** * Get type on the given node for the given cache and table name. Type must exist. * http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java index 1ed7426..3db3050 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java @@ -157,6 +157,9 @@ public abstract class DynamicIndexAbstractSelfTest extends AbstractSchemaSelfTes entity.setKeyType(KeyClass.class.getName()); entity.setValueType(ValueClass.class.getName()); + entity.setKeyFieldName(FIELD_KEY_ALIAS); + entity.addQueryField(FIELD_KEY_ALIAS, entity.getKeyType(), null); + entity.addQueryField(FIELD_KEY, Long.class.getName(), null); entity.addQueryField(FIELD_NAME_1, Long.class.getName(), null); entity.addQueryField(FIELD_NAME_2, Long.class.getName(), null); http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlKeyValueFieldsTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlKeyValueFieldsTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlKeyValueFieldsTest.java new file mode 100644 index 0000000..d63be7c --- /dev/null +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlKeyValueFieldsTest.java @@ -0,0 +1,392 @@ +/* + * 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.internal.processors.query; + +import org.apache.ignite.IgniteCache; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cache.QueryEntity; +import org.apache.ignite.cache.QueryIndex; +import org.apache.ignite.cache.query.QueryCursor; +import org.apache.ignite.cache.query.SqlFieldsQuery; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.internal.binary.BinaryMarshaller; +import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; +import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.concurrent.Callable; + +/** + * Test hidden _key, _val, _ver columns + */ +public class IgniteSqlKeyValueFieldsTest extends GridCommonAbstractTest { + + /** IP finder. */ + private static final TcpDiscoveryVmIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); + + /** */ + private static String NODE_BAD_CONF_MISS_KEY_FIELD = "badConf1"; + /** */ + private static String NODE_BAD_CONF_MISS_VAL_FIELD = "badConf2"; + /** */ + private static String NODE_CLIENT = "client"; + + /** */ + private static String CACHE_PERSON_NO_KV = "PersonNoKV"; + /** */ + private static String CACHE_INT_NO_KV_TYPE = "IntNoKVType"; + /** */ + private static String CACHE_PERSON = "Person"; + /** */ + private static String CACHE_JOB = "Job"; + + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration c = super.getConfiguration(gridName); + + TcpDiscoverySpi disco = new TcpDiscoverySpi(); + + disco.setIpFinder(IP_FINDER); + + c.setDiscoverySpi(disco); + + c.setMarshaller(new BinaryMarshaller()); + + List<CacheConfiguration> ccfgs = new ArrayList<>(); + CacheConfiguration ccfg = buildCacheConfiguration(gridName); + if (ccfg != null) + ccfgs.add(ccfg); + + ccfgs.add(buildCacheConfiguration(CACHE_PERSON_NO_KV)); + ccfgs.add(buildCacheConfiguration(CACHE_INT_NO_KV_TYPE)); + ccfgs.add(buildCacheConfiguration(CACHE_PERSON)); + ccfgs.add(buildCacheConfiguration(CACHE_JOB)); + + c.setCacheConfiguration(ccfgs.toArray(new CacheConfiguration[ccfgs.size()])); + if (gridName.equals(NODE_CLIENT)) + c.setClientMode(true); + + return c; + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + super.beforeTest(); + + startGrid(0); + startGrid(NODE_CLIENT); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + super.afterTest(); + + stopAllGrids(); + } + + private CacheConfiguration buildCacheConfiguration(String name) { + if (name.equals(NODE_BAD_CONF_MISS_KEY_FIELD)) { + CacheConfiguration ccfg = new CacheConfiguration(NODE_BAD_CONF_MISS_KEY_FIELD); + QueryEntity qe = new QueryEntity(Object.class.getName(), Object.class.getName()); + qe.setKeyFieldName("k"); + qe.addQueryField("a", Integer.class.getName(), null); + ccfg.setQueryEntities(F.asList(qe)); + return ccfg; + } + else if (name.equals(NODE_BAD_CONF_MISS_VAL_FIELD)) { + CacheConfiguration ccfg = new CacheConfiguration(NODE_BAD_CONF_MISS_VAL_FIELD); + QueryEntity qe = new QueryEntity(Object.class.getName(), Object.class.getName()); + qe.setValueFieldName("v"); + qe.addQueryField("a", Integer.class.getName(), null); + ccfg.setQueryEntities(F.asList(qe)); + return ccfg; + } + else if (name.equals(CACHE_PERSON_NO_KV)) { + CacheConfiguration ccfg = new CacheConfiguration(CACHE_PERSON_NO_KV); + + QueryEntity entity = new QueryEntity(); + + entity.setKeyType(Integer.class.getName()); + entity.setValueType(Person.class.getName()); + + LinkedHashMap<String, String> fields = new LinkedHashMap<>(); + fields.put("name", String.class.getName()); + fields.put("age", Integer.class.getName()); + + entity.setFields(fields); + + ccfg.setQueryEntities(Arrays.asList(entity)); + return ccfg; + } + else if (name.equals(CACHE_INT_NO_KV_TYPE)) { + CacheConfiguration ccfg = new CacheConfiguration(CACHE_INT_NO_KV_TYPE); + QueryEntity entity = new QueryEntity(); + + entity.setKeyType(null); + entity.setValueType(null); + + entity.setKeyFieldName("id"); + entity.setValueFieldName("v"); + + LinkedHashMap<String, String> fields = new LinkedHashMap<>(); + fields.put("id", Integer.class.getName()); + fields.put("v", Integer.class.getName()); + + entity.setFields(fields); + + ccfg.setQueryEntities(Arrays.asList(entity)); + return ccfg; + } + else if (name.equals(CACHE_PERSON)) { + CacheConfiguration ccfg = new CacheConfiguration(CACHE_PERSON); + + QueryEntity entity = new QueryEntity(); + + entity.setKeyType(Integer.class.getName()); + entity.setValueType(Person.class.getName()); + + entity.setKeyFieldName("id"); + entity.setValueFieldName("v"); + + LinkedHashMap<String, String> fields = new LinkedHashMap<>(); + fields.put("name", String.class.getName()); + fields.put("age", Integer.class.getName()); + + fields.put(entity.getKeyFieldName(), entity.getKeyType()); + fields.put(entity.getValueFieldName(), entity.getValueType()); + + entity.setFields(fields); + + ccfg.setQueryEntities(Arrays.asList(entity)); + return ccfg; + } + else if (name.equals(CACHE_JOB)) { + CacheConfiguration ccfg = new CacheConfiguration(CACHE_JOB); + ccfg.setIndexedTypes(Integer.class, Integer.class); + return ccfg; + } + return null; + } + + /** Test for setIndexedTypes() primitive types */ + public void testSetIndexTypesPrimitive() throws Exception { + IgniteCache<Integer, Integer> cache = grid(NODE_CLIENT).cache(CACHE_JOB); + + checkInsert(cache, "insert into Integer (_key, _val) values (?,?)", 1, 100); + + checkSelect(cache, "select * from Integer", 1, 100); + checkSelect(cache, "select _key, _val from Integer", 1, 100); + } + + /** Test configuration error : keyFieldName is missing from fields */ + public void testErrorKeyFieldMissingFromFields() throws Exception { + checkCacheStartupError(NODE_BAD_CONF_MISS_KEY_FIELD); + } + + /** Test configuration error : valueFieldName is missing from fields */ + public void testErrorValueFieldMissingFromFields() throws Exception { + checkCacheStartupError(NODE_BAD_CONF_MISS_VAL_FIELD); + } + + /** */ + private void checkCacheStartupError(final String name) { + GridTestUtils.assertThrows(log, new Callable<Void>() { + @Override public Void call() throws Exception { + startGrid(name); + + return null; + } + }, IgniteCheckedException.class, null); + } + + /** + * Check that it is allowed to leave QE.keyType and QE.valueType unset + * in case keyFieldName and valueFieldName are set and present in fields + */ + public void testQueryEntityAutoKeyValTypes() throws Exception { + IgniteCache<Integer, Integer> cache = grid(NODE_CLIENT).cache(CACHE_INT_NO_KV_TYPE); + + checkInsert(cache, "insert into Integer (_key, _val) values (?,?)", 1, 100); + + checkSelect(cache, "select * from Integer where id = 1", 1, 100); + + checkSelect(cache, "select * from Integer", 1, 100); + checkSelect(cache, "select _key, _val from Integer", 1, 100); + checkSelect(cache, "select id, v from Integer", 1, 100); + } + + /** Check that it is possible to not have keyFieldName and valueFieldName */ + public void testNoKeyValueAliases() throws Exception { + IgniteCache<Integer, Person> cache = grid(NODE_CLIENT).cache(CACHE_PERSON_NO_KV); + + Person alice = new Person("Alice", 1); + checkInsert(cache, "insert into Person (_key, _val) values (?,?)", 1, alice); + + checkSelect(cache, "select * from Person", alice.name, alice.age); + checkSelect(cache, "select _key, _val from Person", 1, alice); + } + + /** Check keyFieldName and valueFieldName columns access */ + public void testKeyValueAlias() throws Exception { + //_key, _val, _ver | name, age, id, v + Person alice = new Person("Alice", 1); + Person bob = new Person("Bob", 2); + + IgniteCache<Integer, Person> cache = grid(NODE_CLIENT).cache(CACHE_PERSON); + + checkInsert(cache, "insert into Person (_key, _val) values (?,?)", 1, alice); + checkInsert(cache, "insert into Person (id, v) values (?,?)", 2, bob); + + checkSelect(cache, "select * from Person where _key=1", alice.name, alice.age, 1, alice); + checkSelect(cache, "select _key, _val from Person where id=1", 1, alice); + + checkSelect(cache, "select * from Person where _key=2", bob.name, bob.age, 2, bob); + checkSelect(cache, "select _key, _val from Person where id=2", 2, bob); + + checkInsert(cache, "update Person set age = ? where id = ?", 3, 1); + checkSelect(cache, "select _key, age from Person where id=1", 1, 3); + + checkInsert(cache, "update Person set v = ? where id = ?", alice, 1); + checkSelect(cache, "select _key, _val from Person where id=1", 1, alice); + } + + /** Check _ver version field is accessible */ + public void testVersionField() throws Exception { + Person alice = new Person("Alice", 1); + Person bob = new Person("Bob", 2); + + IgniteCache<Integer, Person> cache = grid(NODE_CLIENT).cache(CACHE_PERSON); + + checkInsert(cache, "insert into Person (id, v) values (?,?)", 1, alice); + assertNotNull(getVersion(cache, 1)); + + checkInsert(cache, "insert into Person (id, v) values (?,?)", 2, bob); + assertNotNull(getVersion(cache, 2)); + + GridCacheVersion v1 = getVersion(cache, 1); + + checkInsert(cache, "update Person set age = ? where id = ?", 3, 1); + + GridCacheVersion v2 = getVersion(cache, 1); + + assertFalse( v1.equals(v2) ); + } + + /** Check that joins are working on keyFieldName, valueFieldName columns */ + public void testJoinKeyValFields() throws Exception { + IgniteEx client = grid(NODE_CLIENT); + IgniteCache<Integer, Person> cache = client.cache(CACHE_PERSON); + IgniteCache<Integer, Integer> cache2 = client.cache(CACHE_JOB); + + checkInsert(cache, "insert into Person (id, v) values (?, ?)", 1, new Person("Bob", 30)); + checkInsert(cache, "insert into Person (id, v) values (?, ?)", 2, new Person("David", 35)); + checkInsert(cache2, "insert into Integer (_key, _val) values (?, ?)", 100, 1); + checkInsert(cache2, "insert into Integer (_key, _val) values (?, ?)", 200, 2); + + QueryCursor<List<?>> cursor = cache.query(new SqlFieldsQuery("select p.id, j._key from Person p, \""+ CACHE_JOB +"\".Integer j where p.id = j._val")); + List<List<?>> results = cursor.getAll(); + assertEquals(2, results.size()); + assertEquals(1, results.get(0).get(0)); + assertEquals(100, results.get(0).get(1)); + assertEquals(2, results.get(1).get(0)); + assertEquals(200, results.get(1).get(1)); + } + + /** Check automatic addition of index for keyFieldName column */ + public void testAutoKeyFieldIndex() throws Exception { + IgniteEx client = grid(NODE_CLIENT); + IgniteCache<Integer, Person> cache = client.cache(CACHE_PERSON); + + QueryCursor<List<?>> cursor = cache.query(new SqlFieldsQuery("explain select * from Person where id = 1")); + List<List<?>> results = cursor.getAll(); + assertEquals(2, results.size()); + assertTrue(((String)results.get(0).get(0)).contains("\"_key_PK_proxy\"")); + + cursor = cache.query(new SqlFieldsQuery("explain select * from Person where _key = 1")); + results = cursor.getAll(); + assertEquals(2, results.size()); + assertTrue(((String)results.get(0).get(0)).contains("\"_key_PK\"")); + } + + /** */ + private GridCacheVersion getVersion(IgniteCache<?, ?> cache, int key) { + QueryCursor<List<?>> cursor = cache.query(new SqlFieldsQuery("select _ver from Person where id = ?").setArgs(key)); + List<List<?>> results = cursor.getAll(); + assertEquals(1, results.size()); + return ((GridCacheVersion) results.get(0).get(0)); + } + + /** */ + private void checkInsert(IgniteCache<?, ?> cache, String qry, Object ... args) throws Exception { + QueryCursor<List<?>> cursor = cache.query(new SqlFieldsQuery(qry).setArgs(args)); + assertEquals(1, ((Number) cursor.getAll().get(0).get(0)).intValue()); + } + + /** */ + private void checkSelect(IgniteCache<?, ?> cache, String selectQry, Object ... expected) { + QueryCursor<List<?>> cursor = cache.query(new SqlFieldsQuery(selectQry)); + + List<List<?>> results = cursor.getAll(); + + assertEquals(1, results.size()); + + List<?> row0 = results.get(0); + for(int col = 0; col < expected.length; ++col) + assertEquals(expected[col], row0.get(col)); + } + + /** */ + private static class Person { + /** */ + private String name; + + /** */ + private int age; + + /** */ + public Person(String name, int age) { + this.name = name; + this.age = age; + } + + /** */ + @Override public int hashCode() { + return name.hashCode() ^ age; + } + + /** */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof Person)) + return false; + Person other = (Person)o; + return name.equals(other.name) && age == other.age; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java index fa4eded..6110faa 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java @@ -799,14 +799,14 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest { false, 0, "select p._key k1, o._key k2 " + - "from \"persPart\".Person2 p, (select * from \"orgRepl\".Organization) o " + + "from \"persPart\".Person2 p, (select _key, _val, * from \"orgRepl\".Organization) o " + "where p.orgId = o._key"); checkQueryPlan(persPart, false, 0, "select p._key k1, o._key k2 " + - "from (select * from \"orgRepl\".Organization) o, \"persPart\".Person2 p " + + "from (select _key, _val, * from \"orgRepl\".Organization) o, \"persPart\".Person2 p " + "where p.orgId = o._key"); checkQueryPlan(persPart, @@ -1019,7 +1019,7 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest { sql); sql = "select p1._key k1, p2._key k2, o._key k3 " + - "from (select * from \"orgRepl\".Organization) o, \"persPartAff\".Person2 p1, \"persPart\".Person2 p2 " + + "from (select _key, _val, * from \"orgRepl\".Organization) o, \"persPartAff\".Person2 p1, \"persPart\".Person2 p2 " + "where p1._key=p2.name and p2.orgId = o._key"; checkQueryPlan(persPart, @@ -1029,7 +1029,7 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest { "batched:unicast"); sql = "select p1._key k1, p2._key k2, o._key k3 " + - "from (select * from \"orgRepl\".Organization) o, \"persPartAff\".Person2 p1, \"persPart\".Person2 p2 " + + "from (select _key, _val, * from \"orgRepl\".Organization) o, \"persPartAff\".Person2 p1, \"persPart\".Person2 p2 " + "where p1._key=p2._key and p2.orgId = o._key"; checkQueryPlan(persPart, http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java index e62199a..7e2026b 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java @@ -682,6 +682,16 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract @Override public int typeId() { return 0; } + + /** {@inheritDoc} */ + @Override public String keyFieldName() { + return null; + } + + /** {@inheritDoc} */ + @Override public String valueFieldName() { + return null; + } } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java index 9782f28..7423c9b 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java @@ -506,7 +506,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { // Schemas for index and table must match assertParseThrows("create index if not exists sch2.idx on sch1.Person (name)", - DbException.class, "Schema name must match [90080-195]"); + DbException.class, "Schema name must match"); assertParseThrows("create hash index if not exists idx on Person (name)", IgniteSQLException.class, "Only SPATIAL modifier is supported for CREATE INDEX"); http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java index 032e544..6370cd0 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java +++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java @@ -108,6 +108,7 @@ import org.apache.ignite.internal.processors.cache.query.IndexingSpiQuerySelfTes import org.apache.ignite.internal.processors.cache.query.IndexingSpiQueryTxSelfTest; import org.apache.ignite.internal.processors.query.IgniteQueryDedicatedPoolTest; import org.apache.ignite.internal.processors.query.IgniteSqlEntryCacheModeAgnosticTest; +import org.apache.ignite.internal.processors.query.IgniteSqlKeyValueFieldsTest; import org.apache.ignite.internal.processors.query.IgniteSqlSchemaIndexingTest; import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexMultiNodeSelfTest; import org.apache.ignite.internal.processors.query.IgniteSqlSegmentedIndexSelfTest; @@ -283,6 +284,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite { suite.addTestSuite(IgniteCacheDistributedPartitionQuerySelfTest.class); suite.addTestSuite(IgniteCacheDistributedPartitionQueryNodeRestartsSelfTest.class); suite.addTestSuite(IgniteCacheDistributedPartitionQueryConfigurationSelfTest.class); + suite.addTestSuite(IgniteSqlKeyValueFieldsTest.class); return suite; } http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/cpp/core-test/config/cache-query-default.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/config/cache-query-default.xml b/modules/platforms/cpp/core-test/config/cache-query-default.xml index 366435c..1c1e5f3 100644 --- a/modules/platforms/cpp/core-test/config/cache-query-default.xml +++ b/modules/platforms/cpp/core-test/config/cache-query-default.xml @@ -50,8 +50,14 @@ <list> <bean class="org.apache.ignite.cache.QueryEntity"> <property name="valueType" value="QueryPerson"/> + + <property name="keyFieldName" value="k"/> + <property name="valueFieldName" value="v"/> + <property name="fields"> <map> + <entry key="k" value="java.lang.Integer"/> + <entry key="v" value="QueryPerson"/> <entry key="name" value="java.lang.String"/> <entry key="age" value="java.lang.Integer"/> <entry key="birthday" value="java.util.Date"/> http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/cpp/core-test/src/cache_query_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/cache_query_test.cpp b/modules/platforms/cpp/core-test/src/cache_query_test.cpp index 259a9a1..e9c4610 100644 --- a/modules/platforms/cpp/core-test/src/cache_query_test.cpp +++ b/modules/platforms/cpp/core-test/src/cache_query_test.cpp @@ -163,6 +163,29 @@ public: return recordCreated; } + /** + * @return true if objects are equal. + */ + friend bool operator==(QueryPerson const& lhs, QueryPerson const& rhs) + { + return lhs.GetName() == rhs.GetName() && lhs.GetAge() == rhs.GetAge() && + lhs.GetBirthday() == rhs.GetBirthday() && lhs.GetCreationTime() == rhs.GetCreationTime(); + } + + /** + * Outputs the object to stream. + * + * @return Stream. + */ + friend std::ostream& operator<<(std::ostream& str, QueryPerson const& obj) + { + str << "QueryPerson::name: " << obj.GetName() + << "QueryPerson::age: " << obj.GetAge() + << "QueryPerson::birthday: " << obj.GetBirthday().GetMilliseconds() + << "QueryPerson::recordCreated: " << obj.GetCreationTime().GetSeconds() << "." << obj.GetCreationTime().GetSecondFraction(); + return str; + } + private: /** Name. */ char* name; @@ -1811,4 +1834,63 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryPageZero) BOOST_CHECK_THROW(CheckFieldsQueryPages(0, 100, 0), IgniteError); } +/** + * Test query for key and value fields. + */ +BOOST_AUTO_TEST_CASE(TestKeyValFields) +{ + Cache<int, QueryPerson> cache = GetPersonCache(); + + QueryPerson person("John", 30, MakeDateGmt(1987), MakeTimestampGmt(2017, 1, 1, 1, 1)); + + cache.Put(1, person); + + for (int i = 0; i < 2; i++) + { + SqlFieldsQuery qry(i == 0 ? + "select _key, _val, k, v, name, age, birthday, recordCreated from QueryPerson" : + "select _key, _val, * from QueryPerson"); + + QueryFieldsCursor cursor = cache.Query(qry); + + BOOST_REQUIRE(cursor.HasNext()); + + QueryFieldsRow row = cursor.GetNext(); + + BOOST_REQUIRE(row.HasNext()); + int id = row.GetNext<int>(); + BOOST_CHECK_EQUAL(1, id); + + BOOST_REQUIRE(row.HasNext()); + QueryPerson p = row.GetNext<QueryPerson>(); + BOOST_CHECK_EQUAL(p, person); + + BOOST_REQUIRE(row.HasNext()); + id = row.GetNext<int>(); + BOOST_CHECK_EQUAL(1, id); + + BOOST_REQUIRE(row.HasNext()); + p = row.GetNext<QueryPerson>(); + BOOST_CHECK_EQUAL(p, person); + + BOOST_REQUIRE(row.HasNext()); + std::string name = row.GetNext<std::string>(); + BOOST_CHECK_EQUAL(name, person.GetName()); + + BOOST_REQUIRE(row.HasNext()); + int age = row.GetNext<int>(); + BOOST_CHECK_EQUAL(age, person.GetAge()); + + BOOST_REQUIRE(row.HasNext()); + Date birthday = row.GetNext<Date>(); + BOOST_CHECK(birthday == person.GetBirthday()); + + BOOST_REQUIRE(row.HasNext()); + Timestamp recordCreated = row.GetNext<Timestamp>(); + BOOST_CHECK(recordCreated == person.GetCreationTime()); + + BOOST_CHECK(!row.HasNext()); + } +} + BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/cpp/odbc-test/config/queries-default.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/config/queries-default.xml b/modules/platforms/cpp/odbc-test/config/queries-default.xml index c1eaea8..56040f1 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-default.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-default.xml @@ -95,8 +95,13 @@ <property name="keyType" value="java.lang.Long"/> <property name="valueType" value="ComplexType"/> + <property name="keyFieldName" value="k"/> + <property name="valueFieldName" value="v"/> + <property name="fields"> <map> + <entry key="k" value="java.lang.Long"/> + <entry key="v" value="ComplexType"/> <entry key="i32Field" value="java.lang.Integer"/> <entry key="objField" value="TestObject"/> <entry key="strField" value="java.lang.String"/> http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/cpp/odbc-test/include/complex_type.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/include/complex_type.h b/modules/platforms/cpp/odbc-test/include/complex_type.h index d844cd5..8a1bd59 100644 --- a/modules/platforms/cpp/odbc-test/include/complex_type.h +++ b/modules/platforms/cpp/odbc-test/include/complex_type.h @@ -50,6 +50,31 @@ namespace ignite TestObject objField; std::string strField; }; + + bool operator==(TestObject const& lhs, TestObject const& rhs) + { + return lhs.f1 == rhs.f1 && lhs.f2 == rhs.f2; + } + + bool operator==(ComplexType const& lhs, ComplexType const& rhs) + { + return lhs.i32Field == rhs.i32Field && lhs.objField == rhs.objField && lhs.strField == rhs.strField; + } + + std::ostream& operator<<(std::ostream& str, TestObject const& obj) + { + str << "TestObject::f1: " << obj.f1 + << "TestObject::f2: " << obj.f2; + return str; + } + + std::ostream& operator<<(std::ostream& str, ComplexType const& obj) + { + str << "ComplexType::i32Field: " << obj.i32Field + << "ComplexType::objField: " << obj.objField + << "ComplexType::strField: " << obj.strField; + return str; + } } namespace ignite http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/cpp/odbc-test/src/queries_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp index eb0904f..fdf3503 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp @@ -35,6 +35,7 @@ #include "ignite/ignite.h" #include "ignite/ignition.h" #include "ignite/impl/binary/binary_utils.h" +#include "ignite/binary/binary_object.h" #include "test_type.h" #include "complex_type.h" @@ -45,6 +46,9 @@ using namespace ignite::cache; using namespace ignite::cache::query; using namespace ignite::common; using namespace ignite_test; +using namespace ignite::binary; +using namespace ignite::impl::binary; +using namespace ignite::impl::interop; using namespace boost::unit_test; @@ -1414,4 +1418,148 @@ BOOST_AUTO_TEST_CASE(TestTablesMeta) BOOST_CHECK(ret == SQL_NO_DATA); } +template<typename T> +void CheckObjectData(int8_t* data, int32_t len, T const& value) +{ + InteropUnpooledMemory mem(len); + mem.Length(len); + memcpy(mem.Data(), data, len); + + BinaryObject obj(BinaryObjectImpl::FromMemory(mem, 0, 0)); + + T actual = obj.Deserialize<T>(); + + BOOST_CHECK_EQUAL(value, actual); +} + +BOOST_AUTO_TEST_CASE(TestKeyVal) +{ + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache2"); + + SQLRETURN ret; + + ComplexType obj; + + obj.i32Field = 123; + obj.strField = "Some string"; + + obj.objField.f1 = 54321; + obj.objField.f2 = "Hello Ignite"; + + cache2.Put(1, obj); + + //_key + int64_t column1 = 0; + //_val + int8_t column2[ODBC_BUFFER_SIZE] = { 0 }; + //k + int64_t column3 = 0; + //v + int8_t column4[ODBC_BUFFER_SIZE] = { 0 }; + //i32Field + int64_t column5 = 0; + //objField + int8_t column6[ODBC_BUFFER_SIZE] = { 0 }; + //strField + char column7[ODBC_BUFFER_SIZE] = { 0 }; + + SQLLEN column1Len = sizeof(column1); + SQLLEN column2Len = sizeof(column2); + SQLLEN column3Len = sizeof(column3); + SQLLEN column4Len = sizeof(column4); + SQLLEN column5Len = sizeof(column5); + SQLLEN column6Len = sizeof(column6); + SQLLEN column7Len = sizeof(column7); + + // Binding columns. + ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &column1, column1Len, &column1Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindCol(stmt, 2, SQL_C_BINARY, &column2, column2Len, &column2Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindCol(stmt, 3, SQL_C_SLONG, &column3, column3Len, &column3Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindCol(stmt, 4, SQL_C_BINARY, &column4, column4Len, &column4Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindCol(stmt, 5, SQL_C_SLONG, &column5, column5Len, &column5Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindCol(stmt, 6, SQL_C_BINARY, &column6, column6Len, &column6Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindCol(stmt, 7, SQL_C_CHAR, &column7, column7Len, &column7Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + SQLCHAR request[] = "SELECT _key, _val, k, v, i32Field, objField, strField FROM ComplexType"; + + ret = SQLExecDirect(stmt, request, SQL_NTS); + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLFetch(stmt); + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECK_EQUAL(column1, 1); + + CheckObjectData(column2, static_cast<int32_t>(column2Len), obj); + + BOOST_CHECK_EQUAL(column3, 1); + + CheckObjectData(column4, static_cast<int32_t>(column4Len), obj); + + BOOST_CHECK_EQUAL(column5, obj.i32Field); + + CheckObjectData(column6, static_cast<int32_t>(column6Len), obj.objField); + + BOOST_CHECK_EQUAL(column7, obj.strField); + + ret = SQLFetch(stmt); + BOOST_CHECK(ret == SQL_NO_DATA); + + SQLCHAR requestStar[] = "SELECT _key, _val, * FROM ComplexType"; + + ret = SQLExecDirect(stmt, requestStar, SQL_NTS); + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLFetch(stmt); + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECK_EQUAL(column1, 1); + + CheckObjectData(column2, static_cast<int32_t>(column2Len), obj); + + BOOST_CHECK_EQUAL(column3, 1); + + CheckObjectData(column4, static_cast<int32_t>(column4Len), obj); + + BOOST_CHECK_EQUAL(column5, obj.i32Field); + + CheckObjectData(column6, static_cast<int32_t>(column6Len), obj.objField); + + BOOST_CHECK_EQUAL(column7, obj.strField); + + ret = SQLFetch(stmt); + BOOST_CHECK(ret == SQL_NO_DATA); +} + BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs index b2213d8..c638449 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs @@ -1423,6 +1423,13 @@ namespace Apache.Ignite.Core.Tests.Cache.Query { new QueryAlias("AliasTest", "Person_AliasTest"), new QueryAlias("Address.AliasTest", "Addr_AliasTest") + }, + KeyFieldName = "MyKey", + ValueFieldName = "MyValue", + Fields = + { + new QueryField("MyKey", typeof(int)), + new QueryField("MyValue", typeof(T)), } }, new QueryEntity(typeof (int), typeof (Organization))) {CacheMode = CacheMode.Replicated}); http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs index 0b13bf9..1fa993b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs @@ -622,6 +622,58 @@ namespace Apache.Ignite.Core.Tests.Cache.Query } /// <summary> + /// Tests custom key and value field names. + /// </summary> + [Test] + public void TestCustomKeyValueFieldNames() + { + // Check select * with default config - does not include _key, _val. + var cache = Cache(); + + cache[1] = new QueryPerson("Joe", 48); + + var row = cache.QueryFields(new SqlFieldsQuery("select * from QueryPerson")).GetAll()[0]; + Assert.AreEqual(2, row.Count); + Assert.AreEqual(48, row[0]); + Assert.AreEqual("Joe", row[1]); + + // Check select * with custom names - fields are included. + cache = GetIgnite().GetOrCreateCache<int, QueryPerson>( + new CacheConfiguration("customKeyVal") + { + QueryEntities = new[] + { + new QueryEntity(typeof(int), typeof(QueryPerson)) + { + Fields = new[] + { + new QueryField("age", "int"), + new QueryField("FullKey", "int"), + new QueryField("FullVal", "QueryPerson") + }, + KeyFieldName = "FullKey", + ValueFieldName = "FullVal" + } + } + }); + + cache[1] = new QueryPerson("John", 33); + + row = cache.QueryFields(new SqlFieldsQuery("select * from QueryPerson")).GetAll()[0]; + + Assert.AreEqual(3, row.Count); + Assert.AreEqual(33, row[0]); + Assert.AreEqual(1, row[1]); + + var person = (QueryPerson) row[2]; + Assert.AreEqual("John", person.Name); + + // Check explicit select. + row = cache.QueryFields(new SqlFieldsQuery("select FullKey from QueryPerson")).GetAll()[0]; + Assert.AreEqual(1, row[0]); + } + + /// <summary> /// Validates the query results. /// </summary> /// <param name="cache">Cache.</param> http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs index 0524c05..2600028 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs @@ -661,7 +661,9 @@ namespace Apache.Ignite.Core.Tests }, KeyType = typeof (string), ValueType = typeof (long), - TableName = "table-1" + TableName = "table-1", + KeyFieldName = "k", + ValueFieldName = "v" }, }, ReadFromBackup = false, http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs index 8aadf0e..b6163ee 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs @@ -148,6 +148,20 @@ namespace Apache.Ignite.Core.Cache.Configuration } /// <summary> + /// Gets or sets the name of the field that is used to denote the entire key. + /// <para /> + /// By default, entite key can be accessed with a special "_key" field name. + /// </summary> + public string KeyFieldName { get; set; } + + /// <summary> + /// Gets or sets the name of the field that is used to denote the entire value. + /// <para /> + /// By default, entite value can be accessed with a special "_val" field name. + /// </summary> + public string ValueFieldName { get; set; } + + /// <summary> /// Gets or sets the name of the SQL table. /// When not set, value type name is used. /// </summary> @@ -197,6 +211,9 @@ namespace Apache.Ignite.Core.Cache.Configuration count = reader.ReadInt(); Indexes = count == 0 ? null : Enumerable.Range(0, count).Select(x => new QueryIndex(reader)).ToList(); + + KeyFieldName = reader.ReadString(); + ValueFieldName = reader.ReadString(); } /// <summary> @@ -250,6 +267,9 @@ namespace Apache.Ignite.Core.Cache.Configuration } else writer.WriteInt(0); + + writer.WriteString(KeyFieldName); + writer.WriteString(ValueFieldName); } /// <summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd index 728e62b..76c2068 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd @@ -417,6 +417,20 @@ </xs:documentation> </xs:annotation> </xs:attribute> + <xs:attribute name="keyFieldName" type="xs:string"> + <xs:annotation> + <xs:documentation> + Name of the field that denotes the key. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="valueFieldName" type="xs:string"> + <xs:annotation> + <xs:documentation> + Name of the field that denotes the value. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:element> </xs:sequence> http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs index 3659158..2d14ec4 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs @@ -51,18 +51,24 @@ namespace Apache.Ignite.Linq.Impl private static readonly CopyOnWriteConcurrentDictionary<MemberInfo, string> FieldNameMap = new CopyOnWriteConcurrentDictionary<MemberInfo, string>(); + /** */ + private readonly bool _includeAllFields; + /// <summary> /// Initializes a new instance of the <see cref="CacheQueryExpressionVisitor" /> class. /// </summary> /// <param name="modelVisitor">The _model visitor.</param> /// <param name="useStar">Flag indicating that star '*' qualifier should be used /// for the whole-table select instead of _key, _val.</param> - public CacheQueryExpressionVisitor(CacheQueryModelVisitor modelVisitor, bool useStar) + /// <param name="includeAllFields">Flag indicating that star '*' qualifier should be used + /// for the whole-table select as well as _key, _val.</param> + public CacheQueryExpressionVisitor(CacheQueryModelVisitor modelVisitor, bool useStar, bool includeAllFields) { Debug.Assert(modelVisitor != null); _modelVisitor = modelVisitor; _useStar = useStar; + _includeAllFields = includeAllFields; } /// <summary> @@ -271,7 +277,11 @@ namespace Apache.Ignite.Linq.Impl { // Count, sum, max, min expect a single field or * // In other cases we need both parts of cache entry - var format = _useStar ? "{0}.*" : "{0}._key, {0}._val"; + var format = _includeAllFields + ? "{0}.*, {0}._key, {0}._val" + : _useStar + ? "{0}.*" + : "{0}._key, {0}._val"; var tableName = Aliases.GetTableAlias(expression); http://git-wip-us.apache.org/repos/asf/ignite/blob/efb7abce/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs index 2cf4420..f74ccc7 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs @@ -107,7 +107,7 @@ namespace Apache.Ignite.Linq.Impl /// <summary> /// Visits the query model. /// </summary> - private void VisitQueryModel(QueryModel queryModel, bool forceStar) + private void VisitQueryModel(QueryModel queryModel, bool includeAllFields) { _aliases.Push(); @@ -115,7 +115,7 @@ namespace Apache.Ignite.Linq.Impl _builder.Append("select "); // TOP 1 FLD1, FLD2 - VisitSelectors(queryModel, forceStar); + VisitSelectors(queryModel, includeAllFields); // FROM ... WHERE ... JOIN ... base.VisitQueryModel(queryModel); @@ -129,14 +129,14 @@ namespace Apache.Ignite.Linq.Impl /// <summary> /// Visits the selectors. /// </summary> - public void VisitSelectors(QueryModel queryModel, bool forceStar) + public void VisitSelectors(QueryModel queryModel, bool includeAllFields) { var parenCount = ProcessResultOperatorsBegin(queryModel); if (parenCount >= 0) { // FIELD1, FIELD2 - BuildSqlExpression(queryModel.SelectClause.Selector, forceStar || parenCount > 0); + BuildSqlExpression(queryModel.SelectClause.Selector, parenCount > 0, includeAllFields); _builder.Append(')', parenCount).Append(" "); } } @@ -512,9 +512,9 @@ namespace Apache.Ignite.Linq.Impl /// <summary> /// Builds the SQL expression. /// </summary> - private void BuildSqlExpression(Expression expression, bool useStar = false) + private void BuildSqlExpression(Expression expression, bool useStar = false, bool includeAllFields = false) { - new CacheQueryExpressionVisitor(this, useStar).Visit(expression); + new CacheQueryExpressionVisitor(this, useStar, includeAllFields).Visit(expression); } } }