Repository: ignite Updated Branches: refs/heads/ignite-2.3 f96a9a4ce -> b7bb79232
IGNITE-6375: SQL: Fixed co-location issue in CREATE TABLE command. This closes #2660. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/b7bb7923 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/b7bb7923 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/b7bb7923 Branch: refs/heads/ignite-2.3 Commit: b7bb7923246198fb424570ed9735f238d4f520e5 Parents: f96a9a4 Author: devozerov <[email protected]> Authored: Thu Sep 28 11:00:46 2017 +0300 Committer: devozerov <[email protected]> Committed: Thu Sep 28 11:00:46 2017 +0300 ---------------------------------------------------------------------- .../query/h2/dml/UpdatePlanBuilder.java | 49 ++---- .../processors/query/h2/sql/DmlAstUtils.java | 16 ++ .../processors/query/h2/sql/GridSqlMerge.java | 5 +- .../query/h2/sql/GridSqlQueryParser.java | 28 ++- ...niteCacheAbstractInsertSqlQuerySelfTest.java | 15 +- .../cache/index/DynamicColumnsAbstractTest.java | 5 +- .../H2DynamicColumnsAbstractBasicSelfTest.java | 5 - .../query/h2/sql/GridQueryParsingTest.java | 171 ++++++------------- 8 files changed, 131 insertions(+), 163 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/b7bb7923/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/UpdatePlanBuilder.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/UpdatePlanBuilder.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/UpdatePlanBuilder.java index 285a0b0..804f7d8 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/UpdatePlanBuilder.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/dml/UpdatePlanBuilder.java @@ -21,7 +21,6 @@ import java.lang.reflect.Constructor; import java.util.HashSet; import java.util.List; import java.util.Set; -import javax.cache.CacheException; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.binary.BinaryObjectBuilder; @@ -60,7 +59,9 @@ import static org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueR * Logic for building update plans performed by {@link DmlStatementsProcessor}. */ public final class UpdatePlanBuilder { - /** */ + /** + * Constructor. + */ private UpdatePlanBuilder() { // No-op. } @@ -111,7 +112,7 @@ public final class UpdatePlanBuilder { GridSqlInsert ins = (GridSqlInsert) stmt; target = ins.into(); - tbl = gridTableForElement(target); + tbl = DmlAstUtils.gridTableForElement(target); desc = tbl.dataTable().rowDescriptor(); cols = ins.columns(); @@ -124,24 +125,18 @@ public final class UpdatePlanBuilder { target = merge.into(); - tbl = gridTableForElement(target); + tbl = DmlAstUtils.gridTableForElement(target); desc = tbl.dataTable().rowDescriptor(); - // This check also protects us from attempts to update key or its fields directly - - // when no key except cache key can be used, it will serve only for uniqueness checks, - // not for updates, and hence will allow putting new pairs only. - // We don't quote _key and _val column names on CREATE TABLE, so they are always uppercase here. - GridSqlColumn[] keys = merge.keys(); - if (keys.length != 1 || !desc.isKeyColumn(tbl.dataTable().getColumn(keys[0].columnName()).getColumnId())) - throw new CacheException("SQL MERGE does not support arbitrary keys"); - cols = merge.columns(); sel = DmlAstUtils.selectForInsertOrMerge(cols, merge.rows(), merge.query()); isTwoStepSubqry = (merge.query() != null); rowsNum = isTwoStepSubqry ? 0 : merge.rows().size(); } - else throw new IgniteSQLException("Unexpected DML operation [cls=" + stmt.getClass().getName() + ']', + else { + throw new IgniteSQLException("Unexpected DML operation [cls=" + stmt.getClass().getName() + ']', IgniteQueryErrorCode.UNEXPECTED_OPERATION); + } // Let's set the flag only for subqueries that have their FROM specified. isTwoStepSubqry = (isTwoStepSubqry && (sel instanceof GridSqlUnion || @@ -212,7 +207,8 @@ public final class UpdatePlanBuilder { * @return Update plan. * @throws IgniteCheckedException if failed. */ - private static UpdatePlan planForUpdate(GridSqlStatement stmt, @Nullable Integer errKeysPos) throws IgniteCheckedException { + private static UpdatePlan planForUpdate(GridSqlStatement stmt, @Nullable Integer errKeysPos) + throws IgniteCheckedException { GridSqlElement target; FastUpdateArguments fastUpdate; @@ -238,7 +234,7 @@ public final class UpdatePlanBuilder { throw new IgniteSQLException("Unexpected DML operation [cls=" + stmt.getClass().getName() + ']', IgniteQueryErrorCode.UNEXPECTED_OPERATION); - GridSqlTable tbl = gridTableForElement(target); + GridSqlTable tbl = DmlAstUtils.gridTableForElement(target); GridH2Table gridTbl = tbl.dataTable(); @@ -267,8 +263,9 @@ public final class UpdatePlanBuilder { colTypes[i] = updatedCols.get(i).resultType().type(); - Column column = updatedCols.get(i).column(); - if (desc.isValueColumn(column.getColumnId())) + Column col = updatedCols.get(i).column(); + + if (desc.isValueColumn(col.getColumnId())) valColIdx = i; } @@ -441,21 +438,6 @@ public final class UpdatePlanBuilder { } /** - * @param target Expression to extract the table from. - * @return Back end table for this element. - */ - private static GridSqlTable gridTableForElement(GridSqlElement target) { - Set<GridSqlTable> tbls = new HashSet<>(); - - DmlAstUtils.collectAllGridTablesInTarget(target, tbls); - - if (tbls.size() != 1) - throw new IgniteSQLException("Failed to determine target table", IgniteQueryErrorCode.TABLE_NOT_FOUND); - - return tbls.iterator().next(); - } - - /** * Check that UPDATE statement affects no key columns. * * @param statement Statement. @@ -473,7 +455,8 @@ public final class UpdatePlanBuilder { DmlAstUtils.collectAllGridTablesInTarget(updTarget, tbls); if (tbls.size() != 1) - throw new IgniteSQLException("Failed to determine target table for UPDATE", IgniteQueryErrorCode.TABLE_NOT_FOUND); + throw new IgniteSQLException("Failed to determine target table for UPDATE", + IgniteQueryErrorCode.TABLE_NOT_FOUND); GridSqlTable tbl = tbls.iterator().next(); http://git-wip-us.apache.org/repos/asf/ignite/blob/b7bb7923/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 edbf56b..4537ffc 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 @@ -23,6 +23,7 @@ import java.util.List; import java.util.Set; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.processors.query.h2.dml.FastUpdateArgument; import org.apache.ignite.internal.processors.query.h2.dml.FastUpdateArguments; @@ -590,6 +591,21 @@ public final class DmlAstUtils { }); } + /** + * @param target Expression to extract the table from. + * @return Back end table for this element. + */ + public static GridSqlTable gridTableForElement(GridSqlElement target) { + Set<GridSqlTable> tbls = new HashSet<>(); + + collectAllGridTablesInTarget(target, tbls); + + if (tbls.size() != 1) + throw new IgniteSQLException("Failed to determine target table", IgniteQueryErrorCode.TABLE_NOT_FOUND); + + return tbls.iterator().next(); + } + /** Simple constant value based operand. */ private final static class ValueArgument implements FastUpdateArgument { /** Value to return. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/b7bb7923/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlMerge.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlMerge.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlMerge.java index 4cdb314..f9b084b 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlMerge.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlMerge.java @@ -55,9 +55,8 @@ public class GridSqlMerge extends GridSqlStatement { buff.append("KEY(\n"); buff.resetCount(); for (GridSqlColumn c : keys) { - buff.appendExceptFirst(", "); - buff.append(c.getSQL()) - .append('\n'); + buff.appendExceptFirst(",\n"); + buff.append(c.getSQL()); } buff.append(")\n"); } http://git-wip-us.apache.org/repos/asf/ignite/blob/b7bb7923/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java index 5cec625..a379a91 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java @@ -36,6 +36,8 @@ import org.apache.ignite.cache.QueryIndexType; import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.processors.query.QueryUtils; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor; +import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table; import org.apache.ignite.internal.util.typedef.F; import org.h2.command.Command; import org.h2.command.CommandContainer; @@ -678,9 +680,24 @@ public class GridSqlQueryParser { Column[] srcKeys = MERGE_KEYS.get(merge); + GridH2Table intoTbl = DmlAstUtils.gridTableForElement(tbl).dataTable(); + + GridH2RowDescriptor rowDesc = intoTbl.rowDescriptor(); + GridSqlColumn[] keys = new GridSqlColumn[srcKeys.length]; - for (int i = 0; i < srcKeys.length; i++) - keys[i] = new GridSqlColumn(srcKeys[i], tbl, null, null, srcKeys[i].getName()); + + for (int i = 0; i < srcKeys.length; i++) { + String colName = srcKeys[i].getName(); + + int colId = intoTbl.getColumn(colName).getColumnId(); + + if (!rowDesc.isKeyColumn(colId) && !F.eq(colName, rowDesc.type().affinityKey())) + throw new IgniteSQLException("Invalid column name in KEYS clause of MERGE - it may include only " + + "key and/or affinity columns: " + colName, IgniteQueryErrorCode.PARSING); + + keys[i] = new GridSqlColumn(srcKeys[i], tbl, null, null, colName); + } + res.keys(keys); List<Expression[]> srcRows = MERGE_ROWS.get(merge); @@ -996,6 +1013,13 @@ public class GridSqlQueryParser { throw new IgniteSQLException("Key and value type names " + "should be different for CREATE TABLE: " + res.valueTypeName(), IgniteQueryErrorCode.PARSING); + if (res.affinityKey() == null) { + LinkedHashSet<String> pkCols0 = res.primaryKeyColumns(); + + if (!F.isEmpty(pkCols0) && pkCols0.size() == 1) + res.affinityKey(pkCols0.iterator().next()); + } + return res; } http://git-wip-us.apache.org/repos/asf/ignite/blob/b7bb7923/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractInsertSqlQuerySelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractInsertSqlQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractInsertSqlQuerySelfTest.java index eab00df..9113e9b 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractInsertSqlQuerySelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractInsertSqlQuerySelfTest.java @@ -26,14 +26,17 @@ import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.binary.BinaryObjectBuilder; import org.apache.ignite.binary.BinaryTypeConfiguration; import org.apache.ignite.cache.CacheAtomicityMode; +import org.apache.ignite.cache.CacheKeyConfiguration; import org.apache.ignite.cache.CacheMode; import org.apache.ignite.cache.QueryEntity; import org.apache.ignite.cache.QueryIndex; +import org.apache.ignite.cache.affinity.AffinityKeyMapped; import org.apache.ignite.cache.query.annotations.QuerySqlField; import org.apache.ignite.configuration.BinaryConfiguration; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.binary.BinaryMarshaller; +import org.apache.ignite.internal.processors.query.QueryUtils; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; @@ -303,13 +306,22 @@ public abstract class IgniteCacheAbstractInsertSqlQuerySelfTest extends GridComm * @return Cache configuration. */ static CacheConfiguration cacheConfig(String name, boolean partitioned, boolean escapeSql, Class<?>... idxTypes) { - return new CacheConfiguration(DEFAULT_CACHE_NAME) + CacheConfiguration res = new CacheConfiguration(DEFAULT_CACHE_NAME) .setName(name) .setCacheMode(partitioned ? CacheMode.PARTITIONED : CacheMode.REPLICATED) .setAtomicityMode(CacheAtomicityMode.ATOMIC) .setBackups(1) .setSqlEscapeAll(escapeSql) .setIndexedTypes(idxTypes); + + for (int i = 0; i < idxTypes.length / 2; i++) { + Class<?> keyType = idxTypes[i]; + + if (!QueryUtils.isSqlType(keyType)) + res.setKeyConfiguration(new CacheKeyConfiguration(keyType)); + } + + return res; } /** @@ -326,6 +338,7 @@ public abstract class IgniteCacheAbstractInsertSqlQuerySelfTest extends GridComm /** */ @QuerySqlField + @AffinityKeyMapped public final int key; /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/b7bb7923/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java index 4831d02..b25359a 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java @@ -302,7 +302,10 @@ public abstract class DynamicColumnsAbstractTest extends GridCommonAbstractTest * @return result. */ protected List<List<?>> run(IgniteCache<?, ?> cache, String sql, Object... args) { - return cache.query(new SqlFieldsQuery(sql).setSchema(QueryUtils.DFLT_SCHEMA).setArgs(args)).getAll(); + SqlFieldsQuery qry = new SqlFieldsQuery(sql).setSchema(QueryUtils.DFLT_SCHEMA).setArgs(args) + .setDistributedJoins(true); + + return cache.query(qry).getAll(); } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/b7bb7923/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java index 7329fa8..5e64959 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java @@ -159,9 +159,7 @@ public abstract class H2DynamicColumnsAbstractBasicSelfTest extends DynamicColum run(cache, "ALTER TABLE Person ADD COLUMN city varchar"); run(cache, "INSERT INTO Person (id, name, city) values (1, 'John Doe', 'New York')"); - run(cache, "INSERT INTO Person (id, name, city) values (2, 'Mike Watts', 'Denver')"); - run(cache, "INSERT INTO Person (id, name, city) values (3, 'Ann Pierce', 'New York')"); run(cache, "CREATE INDEX pidx1 ON Person(name, city desc)"); @@ -205,11 +203,8 @@ public abstract class H2DynamicColumnsAbstractBasicSelfTest extends DynamicColum run(cache, "CREATE INDEX pidx2 on Person(age desc)"); run(cache, "DROP INDEX pidx2"); - run(cache, "DROP INDEX pidx1"); - run(cache, "DROP INDEX cidx2"); - run(cache, "DROP INDEX cidx1"); run(cache, "DELETE FROM Person where age > 10"); http://git-wip-us.apache.org/repos/asf/ignite/blob/b7bb7923/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 61694dd..a1fe04b 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 @@ -31,9 +31,11 @@ import java.util.Map; import java.util.concurrent.Callable; import org.apache.ignite.Ignite; import org.apache.ignite.cache.CacheAtomicityMode; +import org.apache.ignite.cache.CacheKeyConfiguration; import org.apache.ignite.cache.CacheMode; import org.apache.ignite.cache.QueryIndex; import org.apache.ignite.cache.QueryIndexType; +import org.apache.ignite.cache.affinity.AffinityKeyMapped; import org.apache.ignite.cache.query.annotations.QuerySqlField; import org.apache.ignite.cache.query.annotations.QuerySqlFunction; import org.apache.ignite.configuration.CacheConfiguration; @@ -42,19 +44,16 @@ import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.processors.query.GridQueryProcessor; import org.apache.ignite.internal.processors.query.IgniteSQLException; +import org.apache.ignite.internal.processors.query.QueryUtils; import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing; -import org.apache.ignite.internal.util.GridStringBuilder; import org.apache.ignite.internal.util.typedef.F; -import org.apache.ignite.internal.util.typedef.internal.SB; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; 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 org.h2.command.Parser; import org.h2.command.Prepared; -import org.h2.command.ddl.CreateTable; import org.h2.engine.Session; import org.h2.jdbc.JdbcConnection; import org.h2.message.DbException; @@ -88,7 +87,8 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { c.setCacheConfiguration( cacheConfiguration(DEFAULT_CACHE_NAME, "SCH1", String.class, Person.class), - cacheConfiguration("addr", "SCH2", String.class, Address.class)); + cacheConfiguration("addr", "SCH2", String.class, Address.class), + cacheConfiguration("aff", "SCH3", PersonKey.class, Person.class)); return c; } @@ -99,7 +99,9 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { * @param clsV Value class. * @return Cache configuration. */ - private CacheConfiguration cacheConfiguration(@NotNull String name, String sqlSchema, Class<?> clsK, Class<?> clsV) { + @SuppressWarnings("unchecked") + private CacheConfiguration cacheConfiguration(@NotNull String name, String sqlSchema, Class<?> clsK, + Class<?> clsV) { CacheConfiguration cc = defaultCacheConfiguration(); cc.setName(name); @@ -112,6 +114,9 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { cc.setSqlFunctionClasses(GridQueryParsingTest.class); cc.setIndexedTypes(clsK, clsV); + if (!QueryUtils.isSqlType(clsK)) + cc.setKeyConfiguration(new CacheKeyConfiguration(clsK)); + return cc; } @@ -410,13 +415,25 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { checkQuery("merge into Person(old, name) select ASCII(parentName), INSERT(parentName, 4, 4, 'Max') from " + "Person where date='2011-03-12'"); + /* KEY clause. */ + checkQuery("merge into Person(_key, old, name) key(_key) values('a', 5, 'John')"); + checkQuery("merge into SCH3.Person(id, old, name) key(id) values(1, 5, 'John')"); + checkQuery("merge into SCH3.Person(_key, old, name) key(_key) values(?, 5, 'John')"); + checkQuery("merge into SCH3.Person(_key, id, old, name) key(_key, id) values(?, ?, 5, 'John')"); + assertParseThrows("merge into Person(old, name) key(name) values(5, 'John')", IgniteSQLException.class, + "Invalid column name in KEYS clause of MERGE - it may include only key and/or affinity columns: NAME"); + assertParseThrows("merge into SCH3.Person(id, stuff, old, name) key(stuff) values(1, 'x', 5, 'John')", + IgniteSQLException.class, "Invalid column name in KEYS clause of MERGE - it may include only key and/or " + + "affinity columns: STUFF"); + /* Subqueries. */ checkQuery("merge into Person(old, name) select old, parentName from Person"); checkQuery("merge into Person(old, name) select old, parentName from Person where old > 5"); checkQuery("merge into Person(old, name) select 5, 'John'"); checkQuery("merge into Person(old, name) select p1.old, 'Name' from person p1 join person p2 on " + "p2.name = p1.parentName where p2.old > 30"); - checkQuery("merge into Person(old) select 5 from Person UNION select street from sch2.Address limit ? offset ?"); + checkQuery("merge into Person(old) select 5 from Person UNION select street from sch2.Address limit ? " + + "offset ?"); } /** */ @@ -445,8 +462,8 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { checkQuery("insert into Person(date, old, name, parentName, addrId) values " + "(TRUNCATE(TIMESTAMP '2015-12-31 23:59:59'), POWER(3,12), NULL, DEFAULT, DEFAULT)"); checkQuery("insert into Person SET old = 5, name = 'John'"); - checkQuery("insert into Person SET name = CONCAT('Fyodor', null, UPPER(CONCAT(SQRT(?), 'dostoevsky'))), old = " + - "select (5, 6)"); + checkQuery("insert into Person SET name = CONCAT('Fyodor', null, UPPER(CONCAT(SQRT(?), 'dostoevsky'))), " + + "old = select (5, 6)"); checkQuery("insert into Person(old, name) select ASCII(parentName), INSERT(parentName, 4, 4, 'Max') from " + "Person where date='2011-03-12'"); @@ -457,7 +474,8 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { checkQuery("insert into Person(old, name) select 5, 'John'"); checkQuery("insert into Person(old, name) select p1.old, 'Name' from person p1 join person p2 on " + "p2.name = p1.parentName where p2.old > 30"); - checkQuery("insert into Person(old) select 5 from Person UNION select street from sch2.Address limit ? offset ?"); + checkQuery("insert into Person(old) select 5 from Person UNION select street from sch2.Address limit ? " + + "offset ?"); } /** */ @@ -479,8 +497,8 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { checkQuery("update Person p set name='Peter', old = length('zzz') limit 20"); checkQuery("update Person p set name=DEFAULT, old = null limit ?"); checkQuery("update Person p set name=? where old >= ? and old < ? limit ?"); - checkQuery("update Person p set name=(select a.Street from sch2.Address a where a.id=p.addrId), old = (select 42)" + - " where old = sqrt(?)"); + checkQuery("update Person p set name=(select a.Street from sch2.Address a where a.id=p.addrId), old = " + + "(select 42) where old = sqrt(?)"); checkQuery("update Person p set (name, old) = (select 'Peter', 42)"); checkQuery("update Person p set (name, old) = (select street, id from sch2.Address where id > 5 and id <= ?)"); } @@ -655,7 +673,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { IgniteSQLException.class, "ALTER TABLE ADD COLUMN BEFORE/AFTER is not supported"); // No such schema. - assertParseThrows("ALTER TABLE SCH3.\"Person\" ADD (city varchar)", DbException.class, null); + assertParseThrows("ALTER TABLE SCH5.\"Person\" ADD (city varchar)", DbException.class, null); } /** @@ -936,8 +954,8 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { /** * */ - private static GridSqlCreateIndex buildCreateIndex(String name, String tblName, String schemaName, boolean ifNotExists, - QueryIndexType type, Object... flds) { + private static GridSqlCreateIndex buildCreateIndex(String name, String tblName, String schemaName, + boolean ifNotExists, QueryIndexType type, Object... flds) { QueryIndex idx = new QueryIndex(); idx.setName(name); @@ -980,6 +998,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { /** * @param sql Sql. */ + @SuppressWarnings("unchecked") private <T extends Prepared> T parse(String sql) throws Exception { Session ses = (Session)connection().getSession(); @@ -987,12 +1006,12 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { } /** - * @param sql1 Sql 1. - * @param sql2 Sql 2. + * @param exp Sql 1. + * @param actual Sql 2. */ - private void assertSqlEquals(String sql1, String sql2) { - String nsql1 = normalizeSql(sql1); - String nsql2 = normalizeSql(sql2); + private void assertSqlEquals(String exp, String actual) { + String nsql1 = normalizeSql(exp); + String nsql2 = normalizeSql(actual); assertEquals(nsql1, nsql2); } @@ -1011,87 +1030,6 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { } /** - * @param createTbl {@code CREATE TABLE} command. - * @return Corresponding SQL. - */ - private static String createTableToSql(GridSqlCreateTable createTbl) { - GridStringBuilder b = new SB("CREATE TABLE ") - .a(createTbl.ifNotExists() ? "IF NOT EXISTS " : "") - .a("\n") - .a(Parser.quoteIdentifier(createTbl.schemaName())) - .a('.') - .a(Parser.quoteIdentifier(createTbl.tableName())) - .a("\n("); - - boolean singleColPk = false; - - boolean first = true; - - for (GridSqlColumn col : createTbl.columns().values()) { - if (!first) - b.a(",\n"); - else - first = false; - - if (col.column().isPrimaryKey()) { - // Only one column may be marked PRIMARY KEY - multi-col PK is defined separately - assert !singleColPk; - - singleColPk = true; - } - - b.a('\t') - .a(col.getSQL()) - .a(' ') - .a(col.resultType().sql()) - .a(col.column().isPrimaryKey() ? " PRIMARY KEY" : ""); - } - - first = true; - - if (!singleColPk && !F.isEmpty(createTbl.primaryKeyColumns())) { - b.a(",\n") - .a('\t') - .a("PRIMARY KEY (\n"); - - for (String col : createTbl.primaryKeyColumns()) { - GridSqlColumn pkCol = createTbl.columns().get(col); - - assert pkCol != null; - - if (!first) - b.a(",\n"); - else - first = false; - - b.a("\t\t") - .a(pkCol.getSQL()); - } - - b.a("\n\t)"); - } - - b.a("\n)"); - - if (!F.isEmpty(createTbl.params())) { - b.a("\nWITH "); - - first = true; - - for (String p : createTbl.params()) { - if (!first) - b.a(','); - else - first = false; - - b.a(Parser.quoteIdentifier(p)); - } - } - - return b.toString(); - } - - /** * @param qry Query. */ private void checkQuery(String qry) throws Exception { @@ -1106,23 +1044,6 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { assertSqlEquals(U.firstNotNull(prepared.getPlanSQL(), prepared.getSQL()), res); } - /** - * @param qry Query. - */ - private void checkCreateTable(String qry) throws Exception { - Prepared prepared = parse(qry); - - assertTrue(prepared instanceof CreateTable); - - GridSqlStatement gridStmt = new GridSqlQueryParser(false).parse(prepared); - - String res = createTableToSql((GridSqlCreateTable)gridStmt); - - System.out.println(normalizeSql(res)); - - assertSqlEquals(U.firstNotNull(prepared.getPlanSQL(), prepared.getSQL()), res); - } - @QuerySqlFunction public static int cool1() { return 1; @@ -1136,6 +1057,20 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { /** * */ + public static class PersonKey implements Serializable { + /** */ + @QuerySqlField + @AffinityKeyMapped + public int id; + + /** Should not be allowed in KEY clause of MERGE. */ + @QuerySqlField + public String stuff; + } + + /** + * + */ public static class Person implements Serializable { @QuerySqlField(index = true) public Date date = new Date(System.currentTimeMillis());
