Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 8CE26200B54 for ; Thu, 28 Jul 2016 18:05:41 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 8BA18160A94; Thu, 28 Jul 2016 16:05:41 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id D96D8160A56 for ; Thu, 28 Jul 2016 18:05:39 +0200 (CEST) Received: (qmail 95275 invoked by uid 500); 28 Jul 2016 16:05:39 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 95260 invoked by uid 99); 28 Jul 2016 16:05:39 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 28 Jul 2016 16:05:39 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id D58DAE0B40; Thu, 28 Jul 2016 16:05:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ptupitsyn@apache.org To: commits@ignite.apache.org Date: Thu, 28 Jul 2016 16:05:38 -0000 Message-Id: <2f715c59d8aa404d8aaf564b3ce6a4b4@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/8] ignite git commit: IGNITE-3578: CPP: Added properties to support distributed joins in CPP. This closes #894. archived-at: Thu, 28 Jul 2016 16:05:41 -0000 Repository: ignite Updated Branches: refs/heads/master 4318be6d5 -> 506060514 IGNITE-3578: CPP: Added properties to support distributed joins in CPP. This closes #894. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/33d35b3e Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/33d35b3e Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/33d35b3e Branch: refs/heads/master Commit: 33d35b3ed87f986918f87838d4c9f12d23ec8dda Parents: a7cf124 Author: isapego Authored: Thu Jul 28 08:59:26 2016 +0300 Committer: vozerov-gridgain Committed: Thu Jul 28 08:59:26 2016 +0300 ---------------------------------------------------------------------- .../cpp/core-test/config/cache-query.xml | 39 +- .../cpp/core-test/src/cache_query_test.cpp | 443 ++++++++++++++++--- .../core/include/ignite/cache/query/query_sql.h | 61 ++- .../ignite/cache/query/query_sql_fields.h | 112 ++++- 4 files changed, 569 insertions(+), 86 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/33d35b3e/modules/platforms/cpp/core-test/config/cache-query.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/config/cache-query.xml b/modules/platforms/cpp/core-test/config/cache-query.xml index 232b6da..06bc7f5 100644 --- a/modules/platforms/cpp/core-test/config/cache-query.xml +++ b/modules/platforms/cpp/core-test/config/cache-query.xml @@ -35,7 +35,7 @@ - + @@ -69,6 +69,43 @@ + + + + + + + + + + + + + + + + + + + + + http://git-wip-us.apache.org/repos/asf/ignite/blob/33d35b3e/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 168f3f9..e3fba02 100644 --- a/modules/platforms/cpp/core-test/src/cache_query_test.cpp +++ b/modules/platforms/cpp/core-test/src/cache_query_test.cpp @@ -175,12 +175,71 @@ private: Timestamp recordCreated; }; +/** + * Relation class for query tests. + */ +class IGNITE_IMPORT_EXPORT QueryRelation +{ +public: + /** + * Constructor. + */ + QueryRelation() : + personId(), + someVal() + { + // No-op. + } + + /** + * Constructor. + * + * @param name Name. + * @param age Age. + */ + QueryRelation(int32_t personId, int32_t someVal) : + personId(personId), + someVal(someVal) + { + // No-op. + } + + /** + * Get person ID. + * + * @return Person ID. + */ + int32_t GetPersonId() const + { + return personId; + } + + /** + * Get hobby ID. + * + * @return Some test value. + */ + int32_t GetHobbyId() const + { + return someVal; + } + +private: + /** Person ID. */ + int32_t personId; + + /** Some test value. */ + int32_t someVal; +}; + + + namespace ignite { namespace binary { /** - * Binary type definition. + * Binary type definition for QueryPerson. */ IGNITE_BINARY_TYPE_START(QueryPerson) IGNITE_BINARY_GET_TYPE_ID_AS_HASH(QueryPerson) @@ -207,31 +266,45 @@ namespace ignite return QueryPerson(name, age, birthday, recordCreated); } - IGNITE_BINARY_TYPE_END - } -} -/** Node started during the test. */ -Ignite grid = Ignite(); + /** + * Binary type definition for QueryRelation. + */ + IGNITE_BINARY_TYPE_START(QueryRelation) + IGNITE_BINARY_GET_TYPE_ID_AS_HASH(QueryRelation) + IGNITE_BINARY_GET_TYPE_NAME_AS_IS(QueryRelation) + IGNITE_BINARY_GET_FIELD_ID_AS_HASH + IGNITE_BINARY_GET_HASH_CODE_ZERO(QueryRelation) + IGNITE_BINARY_IS_NULL_FALSE(QueryRelation) + IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(QueryRelation) -/** Cache accessor. */ -Cache GetCache() -{ - return grid.GetCache("cache"); + void Write(BinaryWriter& writer, QueryRelation obj) + { + writer.WriteInt32("personId", obj.GetPersonId()); + writer.WriteInt32("someVal", obj.GetHobbyId()); + } + + QueryRelation Read(BinaryReader& reader) + { + int32_t personId = reader.ReadInt32("personId"); + int32_t someVal = reader.ReadInt32("someVal"); + + return QueryRelation(personId, someVal); + } + IGNITE_BINARY_TYPE_END + } } /** * Test setup fixture. */ -struct CacheQueryTestSuiteFixture { - /** - * Constructor. - */ - CacheQueryTestSuiteFixture() +struct CacheQueryTestSuiteFixture +{ + Ignite StartNode(const char* name) { IgniteConfiguration cfg; - + cfg.jvmOpts.push_back("-Xdebug"); cfg.jvmOpts.push_back("-Xnoagent"); cfg.jvmOpts.push_back("-Djava.compiler=NONE"); @@ -246,18 +319,26 @@ struct CacheQueryTestSuiteFixture { cfg.jvmMaxMem = 4096; #endif - char* cfgPath = getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH"); - - cfg.springCfgPath = std::string(cfgPath).append("/").append("cache-query.xml"); + cfg.springCfgPath.assign(getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH")).append("/cache-query.xml"); IgniteError err; - Ignite grid0 = Ignition::Start(cfg, &err); + Ignite grid0 = Ignition::Start(cfg, name, &err); if (err.GetCode() != IgniteError::IGNITE_SUCCESS) BOOST_ERROR(err.GetText()); - grid = grid0; + return grid0; + } + + + /** + * Constructor. + */ + CacheQueryTestSuiteFixture() : + grid(StartNode("Node1")) + { + // No-op. } /** @@ -265,11 +346,44 @@ struct CacheQueryTestSuiteFixture { */ ~CacheQueryTestSuiteFixture() { - Ignition::Stop(grid.GetName(), true); + Ignition::StopAll(true); } + + /** Person cache accessor. */ + Cache GetPersonCache() + { + return grid.GetCache("QueryPerson"); + } + + /** Relation cache accessor. */ + Cache GetRelationCache() + { + return grid.GetCache("QueryRelation"); + } + + /** Node started during the test. */ + Ignite grid; }; /** + * Count number of records returned by cursor. + * + * @param cur Cursor. + */ +template +int CountRecords(Cursor& cur) +{ + int number = 0; + while (cur.HasNext()) + { + ++number; + cur.GetNext(); + } + + return number; +} + +/** * Ensure that HasNext() fails. * * @param cur Cursor. @@ -314,8 +428,7 @@ void CheckGetNextFail(Cursor& cur) * * @param cur Cursor. */ -template -void CheckGetAllFail(Cursor& cur) +void CheckGetAllFail(QueryCursor& cur) { try { @@ -361,8 +474,7 @@ void CheckEmpty(QueryFieldsCursor& cur) * * @param cur Cursor. */ -template -void CheckEmptyGetAll(Cursor& cur) +void CheckEmptyGetAll(QueryCursor& cur) { std::vector> res; @@ -382,8 +494,7 @@ void CheckEmptyGetAll(Cursor& cur) * @param name1 Name. * @param age1 Age. */ -template -void CheckSingle(Cursor& cur, int key, const std::string& name, int age) +void CheckSingle(QueryCursor& cur, int key, const std::string& name, int age) { BOOST_REQUIRE(cur.HasNext()); @@ -404,6 +515,30 @@ void CheckSingle(Cursor& cur, int key, const std::string& name, int age) } /** + * Check single result through iteration. + * + * @param cur Cursor. + * @param key Key. + * @param name Name. + * @param age Age. + */ +void CheckSingle(QueryFieldsCursor& cur, int key, const std::string& name, int age) +{ + BOOST_REQUIRE(cur.HasNext()); + + QueryFieldsRow row = cur.GetNext(); + + BOOST_REQUIRE_EQUAL(row.GetNext(), key); + BOOST_REQUIRE_EQUAL(row.GetNext(), name); + BOOST_REQUIRE_EQUAL(row.GetNext(), age); + + BOOST_REQUIRE(!row.HasNext()); + BOOST_REQUIRE(!cur.HasNext()); + + CheckGetNextFail(cur); +} + +/** * Check single result through GetAll(). * * @param cur Cursor. @@ -411,8 +546,7 @@ void CheckSingle(Cursor& cur, int key, const std::string& name, int age) * @param name1 Name. * @param age1 Age. */ -template -void CheckSingleGetAll(Cursor& cur, int key, const std::string& name, int age) +void CheckSingleGetAll(QueryCursor& cur, int key, const std::string& name, int age) { std::vector> res; @@ -444,8 +578,7 @@ void CheckSingleGetAll(Cursor& cur, int key, const std::string& name, int age) * @param name2 Name 2. * @param age2 Age 2. */ -template -void CheckMultiple(Cursor& cur, int key1, const std::string& name1, +void CheckMultiple(QueryCursor& cur, int key1, const std::string& name1, int age1, int key2, const std::string& name2, int age2) { for (int i = 0; i < 2; i++) @@ -489,8 +622,7 @@ void CheckMultiple(Cursor& cur, int key1, const std::string& name1, * @param name2 Name 2. * @param age2 Age 2. */ -template -void CheckMultipleGetAll(Cursor& cur, int key1, const std::string& name1, +void CheckMultipleGetAll(QueryCursor& cur, int key1, const std::string& name1, int age1, int key2, const std::string& name2, int age2) { std::vector> res; @@ -529,7 +661,7 @@ BOOST_FIXTURE_TEST_SUITE(CacheQueryTestSuite, CacheQueryTestSuiteFixture) */ BOOST_AUTO_TEST_CASE(TestSqlQuery) { - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with no results. SqlQuery qry("QueryPerson", "age < 20"); @@ -541,8 +673,11 @@ BOOST_AUTO_TEST_CASE(TestSqlQuery) CheckEmptyGetAll(cursor); // Test simple query. - cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); - cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); + cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); + + cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); cursor = cache.Query(qry); CheckSingle(cursor, 1, "A1", 10); @@ -550,8 +685,23 @@ BOOST_AUTO_TEST_CASE(TestSqlQuery) cursor = cache.Query(qry); CheckSingleGetAll(cursor, 1, "A1", 10); + // Test simple distributed joins query. + BOOST_CHECK(!qry.IsDistributedJoins()); + qry.SetDistributedJoins(true); + BOOST_CHECK(qry.IsDistributedJoins()); + + cursor = cache.Query(qry); + CheckSingle(cursor, 1, "A1", 10); + + cursor = cache.Query(qry); + CheckSingleGetAll(cursor, 1, "A1", 10); + + qry.SetDistributedJoins(false); + // Test simple local query. + BOOST_CHECK(!qry.IsLocal()); qry.SetLocal(true); + BOOST_CHECK(qry.IsLocal()); cursor = cache.Query(qry); CheckSingle(cursor, 1, "A1", 10); @@ -581,11 +731,60 @@ BOOST_AUTO_TEST_CASE(TestSqlQuery) } /** + * Test SQL query distributed joins. + */ +BOOST_AUTO_TEST_CASE(TestSqlQueryDistributedJoins) +{ + Cache cache1 = GetPersonCache(); + Cache cache2 = GetRelationCache(); + + // Starting second node. + Ignite node2 = StartNode("Node2"); + + int entryCnt = 1000; + + // Filling caches + for (int i = 0; i < entryCnt; i++) + { + std::stringstream stream; + + stream << "A" << i; + + cache1.Put(i, QueryPerson(stream.str(), i * 10, BinaryUtils::MakeDateLocal(1970 + i), + BinaryUtils::MakeTimestampLocal(2016, 1, 1, i / 60, i % 60))); + + cache2.Put(i + 1, QueryRelation(i, i * 10)); + } + + // Test query with no results. + SqlQuery qry("QueryPerson", + "from \"QueryPerson\".QueryPerson, \"QueryRelation\".QueryRelation " + "where \"QueryPerson\".QueryPerson.age = \"QueryRelation\".QueryRelation.someVal"); + + QueryCursor cursor = cache1.Query(qry); + + // Ensure that data is not collocated, so not full result set is returned. + int recordsNum = CountRecords(cursor); + + BOOST_CHECK_GT(recordsNum, 0); + BOOST_CHECK_LT(recordsNum, entryCnt); + + qry.SetDistributedJoins(true); + + cursor = cache1.Query(qry); + + // Check that full result set is returned. + recordsNum = CountRecords(cursor); + + BOOST_CHECK_EQUAL(recordsNum, entryCnt); +} + +/** * Test text query. */ BOOST_AUTO_TEST_CASE(TestTextQuery) { - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with no results. TextQuery qry("QueryPerson", "A1"); @@ -597,8 +796,11 @@ BOOST_AUTO_TEST_CASE(TestTextQuery) CheckEmptyGetAll(cursor); // Test simple query. - cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); - cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); + cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); + + cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); cursor = cache.Query(qry); CheckSingle(cursor, 1, "A1", 10); @@ -631,7 +833,7 @@ BOOST_AUTO_TEST_CASE(TestTextQuery) BOOST_AUTO_TEST_CASE(TestScanQuery) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with no results. ScanQuery qry; @@ -643,7 +845,8 @@ BOOST_AUTO_TEST_CASE(TestScanQuery) CheckEmptyGetAll(cursor); // Test simple query. - cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); + cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); cursor = cache.Query(qry); CheckSingle(cursor, 1, "A1", 10); @@ -652,7 +855,8 @@ BOOST_AUTO_TEST_CASE(TestScanQuery) CheckSingleGetAll(cursor, 1, "A1", 10); // Test query returning multiple entries. - cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); + cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); cursor = cache.Query(qry); CheckMultiple(cursor, 1, "A1", 10, 2, "A2", 20); @@ -667,9 +871,9 @@ BOOST_AUTO_TEST_CASE(TestScanQuery) BOOST_AUTO_TEST_CASE(TestScanQueryPartitioned) { // Populate cache with data. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); - int32_t partCnt = 256; // Defined in configuration explicitly. + int32_t partCnt = 256; // Defined in configuration explicitly. int32_t entryCnt = 1000; // Should be greater than partCnt. for (int i = 0; i < entryCnt; i++) @@ -678,7 +882,8 @@ BOOST_AUTO_TEST_CASE(TestScanQueryPartitioned) stream << "A" << i; - cache.Put(i, QueryPerson(stream.str(), i * 10, BinaryUtils::MakeDateLocal(1970 + i), BinaryUtils::MakeTimestampLocal(2016, 1, 1, i / 60, i % 60))); + cache.Put(i, QueryPerson(stream.str(), i * 10, BinaryUtils::MakeDateLocal(1970 + i), + BinaryUtils::MakeTimestampLocal(2016, 1, 1, i / 60, i % 60))); } // Iterate over all partitions and collect data. @@ -711,12 +916,125 @@ BOOST_AUTO_TEST_CASE(TestScanQueryPartitioned) } /** + * Basic test for SQL fields query. + */ +BOOST_AUTO_TEST_CASE(TestSqlFieldsQueryBasic) +{ + Cache cache = GetPersonCache(); + + // Test query with no results. + SqlFieldsQuery qry("select _key, name, age from QueryPerson where age < 20"); + + QueryFieldsCursor cursor = cache.Query(qry); + CheckEmpty(cursor); + + // Test simple query. + cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); + + cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); + + cursor = cache.Query(qry); + CheckSingle(cursor, 1, "A1", 10); + + // Test simple distributed joins query. + BOOST_CHECK(!qry.IsDistributedJoins()); + BOOST_CHECK(!qry.IsEnforceJoinOrder()); + + qry.SetDistributedJoins(true); + + BOOST_CHECK(qry.IsDistributedJoins()); + BOOST_CHECK(!qry.IsEnforceJoinOrder()); + + qry.SetEnforceJoinOrder(true); + + BOOST_CHECK(qry.IsDistributedJoins()); + BOOST_CHECK(qry.IsEnforceJoinOrder()); + + cursor = cache.Query(qry); + CheckSingle(cursor, 1, "A1", 10); + + qry.SetDistributedJoins(false); + qry.SetEnforceJoinOrder(false); + + // Test simple local query. + BOOST_CHECK(!qry.IsLocal()); + + qry.SetLocal(true); + + BOOST_CHECK(qry.IsLocal()); + + cursor = cache.Query(qry); + CheckSingle(cursor, 1, "A1", 10); + + // Test query with arguments. + qry.SetSql("select _key, name, age from QueryPerson where age < ? AND name = ?"); + qry.AddArgument(20); + qry.AddArgument("A1"); + + cursor = cache.Query(qry); + CheckSingle(cursor, 1, "A1", 10); +} + +/** + * Test SQL fields query distributed joins. + */ +BOOST_AUTO_TEST_CASE(TestSqlFieldsQueryDistributedJoins) +{ + Cache cache1 = GetPersonCache(); + Cache cache2 = GetRelationCache(); + + // Starting second node. + Ignite node2 = StartNode("Node2"); + + int entryCnt = 1000; + + // Filling caches + for (int i = 0; i < entryCnt; i++) + { + std::stringstream stream; + + stream << "A" << i; + + cache1.Put(i, QueryPerson(stream.str(), i * 10, BinaryUtils::MakeDateLocal(1970 + i), + BinaryUtils::MakeTimestampLocal(2016, 1, 1, i / 60, i % 60))); + + cache2.Put(i + 1, QueryRelation(i, i * 10)); + } + + // Test query with no results. + SqlFieldsQuery qry( + "select age, name " + "from \"QueryPerson\".QueryPerson " + "inner join \"QueryRelation\".QueryRelation " + "on \"QueryPerson\".QueryPerson.age = \"QueryRelation\".QueryRelation.someVal"); + + QueryFieldsCursor cursor = cache1.Query(qry); + + // Ensure that data is not collocated, so not full result set is returned. + int recordsNum = CountRecords(cursor); + + BOOST_CHECK_GT(recordsNum, 0); + BOOST_CHECK_LT(recordsNum, entryCnt); + + qry.SetDistributedJoins(true); + + cursor = cache1.Query(qry); + + // Check that full result set is returned. + recordsNum = CountRecords(cursor); + + BOOST_CHECK_EQUAL(recordsNum, entryCnt); +} + +/** * Test fields query with single entry. */ BOOST_AUTO_TEST_CASE(TestFieldsQuerySingle) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with two fields of different type. SqlFieldsQuery qry("select age, name from QueryPerson"); @@ -725,7 +1043,8 @@ BOOST_AUTO_TEST_CASE(TestFieldsQuerySingle) CheckEmpty(cursor); // Test simple query. - cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); + cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); cursor = cache.Query(qry); @@ -761,7 +1080,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQuerySingle) BOOST_AUTO_TEST_CASE(TestFieldsQueryExceptions) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with two fields of different type. SqlFieldsQuery qry("select age, name from QueryPerson"); @@ -770,7 +1089,8 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryExceptions) CheckEmpty(cursor); // Test simple query. - cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); + cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); cursor = cache.Query(qry); @@ -806,7 +1126,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryExceptions) BOOST_AUTO_TEST_CASE(TestFieldsQueryTwo) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with two fields of different type. SqlFieldsQuery qry("select age, name from QueryPerson"); @@ -815,8 +1135,11 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryTwo) CheckEmpty(cursor); // Test simple query. - cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); - cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); + cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685))); + + cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), + BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201))); cursor = cache.Query(qry); @@ -869,7 +1192,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryTwo) BOOST_AUTO_TEST_CASE(TestFieldsQuerySeveral) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with two fields of different type. SqlFieldsQuery qry("select name, age from QueryPerson"); @@ -935,7 +1258,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQuerySeveral) BOOST_AUTO_TEST_CASE(TestFieldsQueryDateLess) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with field of type 'Date'. SqlFieldsQuery qry("select birthday from QueryPerson where birthday<'1990-01-01'"); @@ -996,7 +1319,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryDateLess) BOOST_AUTO_TEST_CASE(TestFieldsQueryDateMore) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with field of type 'Date'. SqlFieldsQuery qry("select birthday from QueryPerson where birthday>'2070-01-01'"); @@ -1057,7 +1380,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryDateMore) BOOST_AUTO_TEST_CASE(TestFieldsQueryDateEqual) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with field of type 'Date'. SqlFieldsQuery qry("select birthday from QueryPerson where birthday='2032-01-01'"); @@ -1109,7 +1432,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryDateEqual) BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampLess) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with field of type 'Timestamp'. SqlFieldsQuery qry("select recordCreated from QueryPerson where recordCreated<'2016-01-01 01:00:00'"); @@ -1170,7 +1493,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampLess) BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampMore) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with field of type 'Timestamp'. SqlFieldsQuery qry("select recordCreated from QueryPerson where recordCreated>'2016-01-01 15:30:00'"); @@ -1233,7 +1556,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampMore) BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampEqual) { // Test simple query. - Cache cache = GetCache(); + Cache cache = GetPersonCache(); // Test query with field of type 'Timestamp'. SqlFieldsQuery qry("select recordCreated from QueryPerson where recordCreated='2016-01-01 09:18:00'"); http://git-wip-us.apache.org/repos/asf/ignite/blob/33d35b3e/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h index cb7a739..0ec5d5f 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h @@ -48,8 +48,13 @@ namespace ignite * @param type Type name. * @param sql SQL string. */ - SqlQuery(const std::string& type, const std::string& sql) - : type(type), sql(sql), pageSize(1024), loc(false), args() + SqlQuery(const std::string& type, const std::string& sql) : + type(type), + sql(sql), + pageSize(1024), + loc(false), + distributedJoins(false), + args() { // No-op. } @@ -60,13 +65,18 @@ namespace ignite * @param other Other instance. */ SqlQuery(const SqlQuery& other) : - type(other.type), sql(other.sql), pageSize(other.pageSize), - loc(other.loc), args() + type(other.type), + sql(other.sql), + pageSize(other.pageSize), + loc(other.loc), + distributedJoins(other.distributedJoins), + args() { args.reserve(other.args.size()); - for (std::vector::const_iterator i = other.args.begin(); - i != other.args.end(); ++i) + typedef std::vector::const_iterator Iter; + + for (Iter i = other.args.begin(); i != other.args.end(); ++i) args.push_back((*i)->Copy()); } @@ -81,11 +91,7 @@ namespace ignite { SqlQuery tmp(other); - std::swap(type, tmp.type); - std::swap(sql, tmp.sql); - std::swap(pageSize, tmp.pageSize); - std::swap(loc, tmp.loc); - std::swap(args, tmp.args); + Swap(tmp); } return *this; @@ -96,7 +102,9 @@ namespace ignite */ ~SqlQuery() { - for (std::vector::iterator it = args.begin(); it != args.end(); ++it) + typedef std::vector::const_iterator Iter; + + for (Iter it = args.begin(); it != args.end(); ++it) delete *it; } @@ -113,6 +121,7 @@ namespace ignite std::swap(sql, other.sql); std::swap(pageSize, other.pageSize); std::swap(loc, other.loc); + std::swap(distributedJoins, other.distributedJoins); std::swap(args, other.args); } } @@ -198,6 +207,29 @@ namespace ignite } /** + * Check if distributed joins are enabled for this query. + * + * @return True If distributed joind enabled. + */ + bool IsDistributedJoins() const + { + return distributedJoins; + } + + /** + * Specify if distributed joins are enabled for this query. + * + * When disabled, join results will only contain colocated data (joins work locally). + * When enabled, joins work as expected, no matter how the data is distributed. + * + * @param enabled Distributed joins enabled. + */ + void SetDistributedJoins(bool enabled) + { + distributedJoins = enabled; + } + + /** * Add argument. * * Template argument type should be copy-constructable and @@ -229,7 +261,7 @@ namespace ignite for (std::vector::const_iterator it = args.begin(); it != args.end(); ++it) (*it)->Write(writer); - writer.WriteBool(false); // distributed joins + writer.WriteBool(distributedJoins); } private: @@ -245,6 +277,9 @@ namespace ignite /** Local flag. */ bool loc; + /** Distributed joins flag. */ + bool distributedJoins; + /** Arguments. */ std::vector args; }; http://git-wip-us.apache.org/repos/asf/ignite/blob/33d35b3e/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h index 1c8570b..10dd6ab 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h @@ -48,7 +48,12 @@ namespace ignite * @param sql SQL string. */ SqlFieldsQuery(const std::string& sql) : - sql(sql), pageSize(1024), loc(false), args() + sql(sql), + pageSize(1024), + loc(false), + distributedJoins(false), + enforceJoinOrder(false), + args() { // No-op. } @@ -60,7 +65,12 @@ namespace ignite * @param loc Whether query should be executed locally. */ SqlFieldsQuery(const std::string& sql, bool loc) : - sql(sql), pageSize(1024), loc(false), args() + sql(sql), + pageSize(1024), + loc(false), + distributedJoins(false), + enforceJoinOrder(false), + args() { // No-op. } @@ -71,13 +81,18 @@ namespace ignite * @param other Other instance. */ SqlFieldsQuery(const SqlFieldsQuery& other) : - sql(other.sql), pageSize(other.pageSize), loc(other.loc), + sql(other.sql), + pageSize(other.pageSize), + loc(other.loc), + distributedJoins(other.distributedJoins), + enforceJoinOrder(other.enforceJoinOrder), args() { args.reserve(other.args.size()); - for (std::vector::const_iterator i = other.args.begin(); - i != other.args.end(); ++i) + typedef std::vector::const_iterator Iter; + + for (Iter i = other.args.begin(); i != other.args.end(); ++i) args.push_back((*i)->Copy()); } @@ -92,10 +107,7 @@ namespace ignite { SqlFieldsQuery tmp(other); - std::swap(sql, tmp.sql); - std::swap(pageSize, tmp.pageSize); - std::swap(loc, tmp.loc); - std::swap(args, tmp.args); + Swap(tmp); } return *this; @@ -106,11 +118,31 @@ namespace ignite */ ~SqlFieldsQuery() { - for (std::vector::iterator it = args.begin(); it != args.end(); ++it) + typedef std::vector::const_iterator Iter; + + for (Iter it = args.begin(); it != args.end(); ++it) delete *it; } /** + * Efficiently swaps contents with another SqlQuery instance. + * + * @param other Other instance. + */ + void Swap(SqlFieldsQuery& other) + { + if (this != &other) + { + std::swap(sql, other.sql); + std::swap(pageSize, other.pageSize); + std::swap(loc, other.loc); + std::swap(distributedJoins, other.distributedJoins); + std::swap(enforceJoinOrder, other.enforceJoinOrder); + std::swap(args, other.args); + } + } + + /** * Get SQL string. * * @return SQL string. @@ -171,6 +203,56 @@ namespace ignite } /** + * Checks if join order of tables if enforced. + * + * @return Flag value. + */ + bool IsEnforceJoinOrder() const + { + return enforceJoinOrder; + } + + /** + * Sets flag to enforce join order of tables in the query. + * If set to true query optimizer will not reorder tables in + * join. By default is false. + * + * It is not recommended to enable this property unless you are + * sure that your indexes and the query itself are correct and + * tuned as much as possible but query optimizer still produces + * wrong join order. + * + * @param enforce Flag value. + */ + void SetEnforceJoinOrder(bool enforce) + { + enforceJoinOrder = enforce; + } + + /** + * Check if distributed joins are enabled for this query. + * + * @return True If distributed joind enabled. + */ + bool IsDistributedJoins() const + { + return distributedJoins; + } + + /** + * Specify if distributed joins are enabled for this query. + * + * When disabled, join results will only contain colocated data (joins work locally). + * When enabled, joins work as expected, no matter how the data is distributed. + * + * @param enabled Distributed joins enabled. + */ + void SetDistributedJoins(bool enabled) + { + distributedJoins = enabled; + } + + /** * Add argument. * * Template argument type should be copy-constructable and @@ -201,8 +283,8 @@ namespace ignite for (std::vector::const_iterator it = args.begin(); it != args.end(); ++it) (*it)->Write(writer); - writer.WriteBool(false); // distributed joins - writer.WriteBool(false); // enforce join order + writer.WriteBool(distributedJoins); + writer.WriteBool(enforceJoinOrder); } private: @@ -215,6 +297,12 @@ namespace ignite /** Local flag. */ bool loc; + /** Distributed joins flag. */ + bool distributedJoins; + + /** Enforce join order flag. */ + bool enforceJoinOrder; + /** Arguments. */ std::vector args; };