From f6529cd4c35c729d9033954879870fea1a3a1052 Mon Sep 17 00:00:00 2001
From: Dominik Gleich <dominik.gleich@memgraph.io>
Date: Tue, 28 Feb 2017 12:14:49 +0100
Subject: [PATCH] Clique #1 and #2 works.

Summary:
Merge branch 'dev' into clique_1

Started implementing clique.

Merge branch 'dev' into clique_1

Add multilne query reload.

Clique 1# implementation.

Merge branch 'dev' into clique_1

Clique #1 and #2 implemented.

Add delete all query. Remove unique from clique.

Reviewers: florijan, mislav.bradac, buda

Reviewed By: florijan, mislav.bradac, buda

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D73
---
 src/query/plan_compiler.hpp                   |   2 +
 tests/data/queries/core/mg_basic_002.txt      |  46 +--
 tests/integration/hardcoded_query/clique.cpp  |  33 ++
 tests/integration/hardcoded_query/clique.hpp  | 299 ++++++++++++++++++
 .../hardcoded_query/clique_scored.cpp         |  40 +++
 .../hardcoded_query/delete_all.cpp            |  26 ++
 .../hardcoded_query/match_garment.cpp         |  38 +++
 .../hardcoded_query/match_profile.cpp         |  44 +++
 .../match_profile_garment_score.cpp           |  59 ++++
 .../match_profile_garment_update_score.cpp    |  60 ++++
 tests/integration/hardcoded_query/using.hpp   |   2 +-
 tests/integration/query_engine_common.hpp     |   4 +-
 .../stream/print_record_stream.hpp            |   2 +-
 tests/manual/query_engine.cpp                 |  18 +-
 14 files changed, 647 insertions(+), 26 deletions(-)
 create mode 100644 tests/integration/hardcoded_query/clique.cpp
 create mode 100644 tests/integration/hardcoded_query/clique.hpp
 create mode 100644 tests/integration/hardcoded_query/clique_scored.cpp
 create mode 100644 tests/integration/hardcoded_query/delete_all.cpp
 create mode 100644 tests/integration/hardcoded_query/match_garment.cpp
 create mode 100644 tests/integration/hardcoded_query/match_profile.cpp
 create mode 100644 tests/integration/hardcoded_query/match_profile_garment_score.cpp
 create mode 100644 tests/integration/hardcoded_query/match_profile_garment_update_score.cpp

diff --git a/src/query/plan_compiler.hpp b/src/query/plan_compiler.hpp
index c4cef29d6..42460d6fa 100644
--- a/src/query/plan_compiler.hpp
+++ b/src/query/plan_compiler.hpp
@@ -53,7 +53,9 @@ class PlanCompiler : public Loggable {
     // generate compile command
     auto compile_command = utils::prints(
         "clang++" + flags,
+#ifdef HARDCODED_OUTPUT_STREAM
         "-DHARDCODED_OUTPUT_STREAM",
+#endif
         // "-std=c++1y -O2 -DNDEBUG",
         "-std=c++1y",    // compile flags
         in_file,         // input file
diff --git a/tests/data/queries/core/mg_basic_002.txt b/tests/data/queries/core/mg_basic_002.txt
index 222e4bdd0..e3e7dc8f4 100644
--- a/tests/data/queries/core/mg_basic_002.txt
+++ b/tests/data/queries/core/mg_basic_002.txt
@@ -1,25 +1,32 @@
+MATCH (n) DETACH DELETE n
 CREATE (g:garment {garment_id: 1234, garment_category_id: 1, conceals: 30}) RETURN g
 MATCH(g:garment {garment_id: 1234}) SET g:AA RETURN g
 MATCH(g:garment {garment_id: 1234}) SET g:BB RETURN g
 MATCH(g:garment {garment_id: 1234}) SET g:EE RETURN g
+
 CREATE (g:garment {garment_id: 2345, garment_category_id: 6, reveals: 10}) RETURN g
 MATCH(g:garment {garment_id: 2345}) SET g:CC RETURN g
 MATCH(g:garment {garment_id: 2345}) SET g:DD RETURN g
+
 CREATE (g:garment {garment_id: 3456, garment_category_id: 8}) RETURN g
 MATCH(g:garment {garment_id: 3456}) SET g:CC RETURN g
 MATCH(g:garment {garment_id: 3456}) SET g:DD RETURN g
+
 CREATE (g:garment {garment_id: 4567, garment_category_id: 15}) RETURN g
 MATCH(g:garment {garment_id: 4567}) SET g:AA RETURN g
 MATCH(g:garment {garment_id: 4567}) SET g:BB RETURN g
 MATCH(g:garment {garment_id: 4567}) SET g:DD RETURN g
+
 CREATE (g:garment {garment_id: 5678, garment_category_id: 19}) RETURN g
 MATCH(g:garment {garment_id: 5678}) SET g:BB RETURN g
 MATCH(g:garment {garment_id: 5678}) SET g:CC RETURN g
 MATCH(g:garment {garment_id: 5678}) SET g:EE RETURN g
+
 CREATE (g:garment {garment_id: 6789, garment_category_id: 3}) RETURN g
 MATCH(g:garment {garment_id: 6789}) SET g:AA RETURN g
 MATCH(g:garment {garment_id: 6789}) SET g:DD RETURN g
 MATCH(g:garment {garment_id: 6789}) SET g:EE RETURN g
+
 CREATE (g:garment {garment_id: 7890, garment_category_id: 25}) RETURN g
 MATCH(g:garment {garment_id: 7890}) SET g:AA RETURN g
 MATCH(g:garment {garment_id: 7890}) SET g:BB RETURN g
@@ -29,40 +36,28 @@ MATCH(g:garment {garment_id: 7890}) SET g:EE RETURN g
 MATCH (g1:garment {garment_id: 1234}), (g2:garment {garment_id: 4567}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 1234}), (g2:garment {garment_id: 5678}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 1234}), (g2:garment {garment_id: 6789}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 1234}),(g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 4567}), (g2:garment {garment_id: 6789}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 4567}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 4567}), (g2:garment {garment_id: 5678}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 6789}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 5678}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 3456}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 5678}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 6789}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 4567}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 3456}), (g2:garment {garment_id: 5678}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 3456}), (g2:garment {garment_id: 6789}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 3456}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 3456}), (g2:garment {garment_id: 4567}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 1234}), (g2:garment {garment_id: 4567}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 1234}), (g2:garment {garment_id: 5678}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 1234}), (g2:garment {garment_id: 6789}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
-MATCH (g1:garment {garment_id: 1234}),(g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
+MATCH (g1:garment {garment_id: 1234}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
+
 MATCH (g1:garment {garment_id: 4567}), (g2:garment {garment_id: 6789}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 4567}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 4567}), (g2:garment {garment_id: 5678}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
+
 MATCH (g1:garment {garment_id: 6789}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
+
 MATCH (g1:garment {garment_id: 5678}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
+
 MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 3456}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 5678}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 6789}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 2345}), (g2:garment {garment_id: 4567}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
+
 MATCH (g1:garment {garment_id: 3456}), (g2:garment {garment_id: 5678}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 3456}), (g2:garment {garment_id: 6789}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 3456}), (g2:garment {garment_id: 7890}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 MATCH (g1:garment {garment_id: 3456}), (g2:garment {garment_id: 4567}) CREATE (g1)-[r:default_outfit]->(g2) RETURN r
 
+
 CREATE (p:profile {profile_id: 111, partner_id: 55, reveals: 30}) RETURN p
 CREATE (p:profile {profile_id: 112, partner_id: 55}) RETURN p
 CREATE (p:profile {profile_id: 112, partner_id: 77, conceals: 10}) RETURN p
@@ -73,14 +68,27 @@ MATCH  (p:profile {profile_id: 111, partner_id: 55}), (g:garment {garment_id: 34
 MATCH  (p:profile {profile_id: 111, partner_id: 55}), (g:garment {garment_id: 4567}) CREATE (p)-[s:score]->(g) SET s.score=1000 RETURN s
 MATCH  (p:profile {profile_id: 111, partner_id: 55}), (g:garment {garment_id: 6789}) CREATE (p)-[s:score]->(g) SET s.score=1500 RETURN s
 MATCH  (p:profile {profile_id: 111, partner_id: 55}), (g:garment {garment_id: 7890}) CREATE (p)-[s:score]->(g) SET s.score=1800 RETURN s
+
 MATCH  (p:profile {profile_id: 112, partner_id: 55}), (g:garment {garment_id: 1234}) CREATE (p)-[s:score]->(g) SET s.score=2000 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 55}), (g:garment {garment_id: 4567}) CREATE (p)-[s:score]->(g) SET s.score=1500 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 55}), (g:garment {garment_id: 5678}) CREATE (p)-[s:score]->(g) SET s.score=1000 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 55}), (g:garment {garment_id: 6789}) CREATE (p)-[s:score]->(g) SET s.score=1600 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 55}), (g:garment {garment_id: 7890}) CREATE (p)-[s:score]->(g) SET s.score=1900 RETURN s
+
 MATCH  (p:profile {profile_id: 112, partner_id: 77}), (g:garment {garment_id: 1234}) CREATE (p)-[s:score]->(g) SET s.score=1500 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 77}), (g:garment {garment_id: 2345}) CREATE (p)-[s:score]->(g) SET s.score=1300 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 77}), (g:garment {garment_id: 3456}) CREATE (p)-[s:score]->(g) SET s.score=1300 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 77}), (g:garment {garment_id: 5678}) CREATE (p)-[s:score]->(g) SET s.score=1200 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 77}), (g:garment {garment_id: 6789}) CREATE (p)-[s:score]->(g) SET s.score=1700 RETURN s
 MATCH  (p:profile {profile_id: 112, partner_id: 77}), (g:garment {garment_id: 7890}) CREATE (p)-[s:score]->(g) SET s.score=1900 RETURN s
+
+
+MATCH (g:garment {garment_id: 1234}) RETURN g
+MATCH (p:profile {profile_id: 112, partner_id: 77}) RETURN p
+MATCH (p:profile {profile_id: 112, partner_id: 77})-[s:score]-(g:garment {garment_id: 1234}) RETURN s
+MATCH (p:profile {profile_id: 112, partner_id: 77})-[s:score]-(g:garment {garment_id: 1234}) SET s.score = 3137 RETURN s
+MATCH (p:profile {profile_id: 112, partner_id: 77})-[s:score]-(g:garment {garment_id: 1234}) SET s.score = 1500 RETURN s
+
+MATCH (a:garment)-[:default_outfit]-(b:garment)-[:default_outfit]-(c:garment)-[:default_outfit]-(d:garment)-[:default_outfit]-(a:garment)-[:default_outfit]-(c:garment), (b:garment)-[:default_outfit]-(d:garment) WHERE a.garment_id=1234 RETURN a.garment_id,b.garment_id,c.garment_id,d.garment_id
+MATCH (a:garment)-[:default_outfit]-(b:garment)-[:default_outfit]-(c:garment)-[:default_outfit]-(d:garment)-[:default_outfit]-(a:garment)-[:default_outfit]-(c:garment), (b:garment)-[:default_outfit]-(d:garment), (e:profile {profile_id: 112, partner_id: 55})-[s1:score]-(a:garment),(e:profile {profile_id: 112, partner_id: 55})-[s2:score]-(b:garment), (e:profile {profile_id: 112, partner_id: 55})-[s3:score]-(c:garment), (e:profile {profile_id: 112, partner_id: 55})-[s4:score]-(d:garment) WHERE a.garment_id=1234 RETURN a.garment_id,b.garment_id,c.garment_id,d.garment_id, s1.score+s2.score+s3.score+s4.score ORDER BY s1.score+s2.score+s3.score+s4.score DESC LIMIT 10
+
diff --git a/tests/integration/hardcoded_query/clique.cpp b/tests/integration/hardcoded_query/clique.cpp
new file mode 100644
index 000000000..39b20f740
--- /dev/null
+++ b/tests/integration/hardcoded_query/clique.cpp
@@ -0,0 +1,33 @@
+#include <algorithm>
+#include <bitset>
+#include <iostream>
+#include <string>
+
+#include "clique.hpp"
+#include "query/plan_interface.hpp"
+#include "storage/edge_accessor.hpp"
+#include "storage/vertex_accessor.hpp"
+#include "using.hpp"
+#include "utils/assert.hpp"
+
+using std::cout;
+using std::endl;
+
+// Query: MATCH
+//  (a:garment)-[:default_outfit]-(b:garment)-[:default_outfit]-(c:garment)-[:default_outfit]-(d:garment)-[:default_outfit]-(a:garment)-[:default_outfit]-(c:garment),
+//  (b:garment)-[:default_outfit]-(d:garment) WHERE a.garment_id=1234 RETURN
+//  a.garment_id,b.garment_id,c.garment_id,d.garment_id
+
+class CPUPlan : public PlanInterface<Stream> {
+ public:
+  bool run(GraphDbAccessor &db_accessor, const TypedValueStore<> &args,
+           Stream &stream) {
+    return run_general_query(db_accessor, args, stream, CliqueQuery::FIND_ALL);
+  }
+
+  ~CPUPlan() {}
+};
+
+extern "C" PlanInterface<Stream> *produce() { return new CPUPlan(); }
+
+extern "C" void destruct(PlanInterface<Stream> *p) { delete p; }
diff --git a/tests/integration/hardcoded_query/clique.hpp b/tests/integration/hardcoded_query/clique.hpp
new file mode 100644
index 000000000..6dec7455d
--- /dev/null
+++ b/tests/integration/hardcoded_query/clique.hpp
@@ -0,0 +1,299 @@
+#include <algorithm>
+#include <bitset>
+#include <iostream>
+#include <string>
+
+#include "query/plan_interface.hpp"
+#include "storage/edge_accessor.hpp"
+#include "storage/vertex_accessor.hpp"
+#include "using.hpp"
+#include "utils/assert.hpp"
+
+using std::cout;
+using std::endl;
+
+// General Query: MATCH
+//  (a:garment)-[:default_outfit]-(b:garment)-[:default_outfit]-(c:garment)-[:default_outfit]-(d:garment)-[:default_outfit]-(a:garment)-[:default_outfit]-(c:garment),
+//  (b:garment)-[:default_outfit]-(d:garment), (e:profile {profile_id: 112,
+//  partner_id: 55})-[s1:score]-(a:garment),(e:profile {profile_id: 112,
+//  partner_id: 55})-[s2:score]-(b:garment), (e:profile {profile_id: 112,
+//  partner_id: 55})-[s3:score]-(c:garment), (e:profile {profile_id: 112,
+//  partner_id: 55})-[s4:score]-(d:garment) WHERE a.garment_id=1234 RETURN
+//  a.garment_id,b.garment_id,c.garment_id,d.garment_id,
+//  s1.score+s2.score+s3.score+s4.score ORDER BY
+//  s1.score+s2.score+s3.score+s4.score DESC LIMIT 10
+
+template <typename TStore>
+/**
+ * Bitset data structure with a number of bits provided in constructor.
+ * @tparam type of underlying bit storage: int32, int64, char, etc.
+ */
+class Bitset {
+ public:
+  /**
+   *  Create bitset.
+   *  @param sz size of bitset
+   */
+  Bitset(size_t sz) : block_size_(8 * sizeof(TStore)) {
+    if (sz % block_size_ != 0) sz += block_size_;
+    blocks_.resize(sz / block_size_);
+  }
+  /**
+   *  Set bit to one.
+   *  @param idx position of bit.
+   */
+  void Set(int idx) {
+    debug_assert(idx < static_cast<int64_t>(blocks_.size()) * block_size_,
+                 "Invalid bit location.");
+    int bucket = idx / block_size_;
+    blocks_[bucket] |= TStore(1) << idx % block_size_;
+  }
+  /**
+   *  Return bit at position.
+   *  @param idx position of bit.
+   *  @return 1/0.
+   */
+  bool At(int idx) const {
+    debug_assert(idx < static_cast<int64_t>(blocks_.size()) * block_size_,
+                 "Invalid bit location.");
+    int bucket = idx / block_size_;
+    return (blocks_[bucket] >> (idx % block_size_)) & 1;
+  }
+  /**
+   *  Intersect two bitsets
+   *  @param other bitset.
+   *  @return intersection.
+   */
+  Bitset<TStore> Intersect(const Bitset<TStore> &other) {
+    debug_assert(this->blocks_.size() == other.size(),
+                 "Bitsets are not of equal size.");
+    Bitset<TStore> ret(this->blocks_.size() * this->block_size_);
+    for (int i = 0; i < (int)this->blocks_.size(); ++i) {
+      ret.blocks_[i] = this->blocks_[i] & other.blocks_[i];
+      continue;
+    }
+    return ret;
+  }
+  /**
+   *  Positions of bits set to 1.
+   *  @return positions of bits set to 1.
+   */
+  std::vector<int> Ones() const {
+    std::vector<int> ret;
+    int ret_idx = 0;
+    for (auto x : blocks_) {
+      while (x) {
+        auto pos = CountTrailingZeroes(x & -x);
+        x -= x & -x;
+        ret.push_back(ret_idx + pos);
+      }
+      ret_idx += block_size_;
+    }
+    return ret;
+  }
+
+ private:
+  /**
+   * Calculate number of trailing zeroes in a binary number, usually a power
+   * of two.
+   * @return number of trailing zeroes.
+   */
+  size_t CountTrailingZeroes(TStore v) const {
+    size_t ret = 0;
+    while (v >> 32) ret += 32, v >>= 32;
+    if (v >> 16) ret += 16, v >>= 16;
+    if (v >> 8) ret += 8, v >>= 8;
+    if (v >> 4) ret += 4, v >>= 4;
+    if (v >> 2) ret += 2, v >>= 2;
+    if (v >> 1) ret += 1, v >>= 1;
+    return ret;
+  }
+  std::vector<TStore> blocks_;
+  const size_t block_size_;
+};
+
+enum CliqueQuery { SCORE_AND_LIMIT, FIND_ALL };
+
+bool run_general_query(GraphDbAccessor &db_accessor,
+                       const TypedValueStore<> &args, Stream &stream,
+                       enum CliqueQuery query_type) {
+  stream.write_fields(
+      {"a.garment_id", "b.garment_id", "c.garment_id", "d.garment_id"});
+  std::vector<VertexAccessor> vertices = db_accessor.vertices();
+  std::vector<EdgeAccessor> edges = db_accessor.edges();
+
+  std::vector<VertexAccessor *> vertices_indexed;
+  std::vector<EdgeAccessor *> edges_indexed;
+
+  int profile_index = -1;
+  for (int i = 0; i < (int)vertices.size(); ++i) {
+    if (vertices[i].has_label(db_accessor.label("garment")))
+      vertices_indexed.push_back(&vertices[i]);
+    if (query_type == CliqueQuery::SCORE_AND_LIMIT &&
+        vertices[i].has_label(db_accessor.label("profile"))) {
+      auto has_prop =
+          vertices[i].PropsAt(db_accessor.property("profile_id")) == args.at(0);
+      if (has_prop.type_ == TypedValue::Type::Null) continue;
+      if (has_prop.Value<bool>() == false) continue;
+      has_prop =
+          vertices[i].PropsAt(db_accessor.property("partner_id")) == args.at(1);
+      if (has_prop.type_ == TypedValue::Type::Null) continue;
+      if (has_prop.Value<bool>() == false) continue;
+      profile_index = i;
+    }
+  }
+  for (int i = 0; i < (int)edges.size(); ++i) {
+    if (edges[i].edge_type() == db_accessor.edge_type("default_outfit") ||
+        edges[i].edge_type() == db_accessor.edge_type("score"))
+      edges_indexed.push_back(&edges[i]);
+  }
+  const int n = vertices_indexed.size();
+  auto cmp_vertex = [](const VertexAccessor *a,
+                       const VertexAccessor *b) -> bool { return *a < *b; };
+  auto cmp_edge = [](const EdgeAccessor *a, const EdgeAccessor *b) -> bool {
+    if (a->from() != b->from()) return a->from() < b->from();
+    return a->to() < b->to();
+  };
+  /**
+   * Index of vertex in a list of vertices_indexed.
+   * @param v VertexAccessor to a vertex.
+   * @return position of vertex or -1 if it doesn't exist.
+   */
+  auto query = [&vertices_indexed,
+                &cmp_vertex](const VertexAccessor &v) -> int {
+    int pos = lower_bound(vertices_indexed.begin(), vertices_indexed.end(), &v,
+                          cmp_vertex) -
+              vertices_indexed.begin();
+    if (pos == (int)vertices_indexed.size() || *vertices_indexed[pos] != v)
+      return -1;
+    return pos;
+  };
+  /**
+   * Update bitset of neighbours. Set bit to 1 for index of every vertex
+   * endpoint of edges with type default_outfit.
+   * @param bitset bitset to update.
+   * @param edges edges from which to update bitset.
+   */
+  auto update = [&db_accessor, &query](Bitset<int64_t> &bitset,
+                                       const std::vector<EdgeAccessor> &edges) {
+    for (auto e : edges) {
+      if (e.edge_type() != db_accessor.edge_type("default_outfit")) continue;
+      const int from = query(e.from());
+      const int to = query(e.to());
+      if (from == -1 || to == -1) continue;
+      bitset.Set(from);
+      bitset.Set(to);
+    }
+  };
+  std::sort(vertices_indexed.begin(), vertices_indexed.end(), cmp_vertex);
+  std::sort(edges_indexed.begin(), edges_indexed.end(), cmp_edge);
+  std::vector<Bitset<int64_t>> connected;
+  for (int i = 0; i < n; ++i) {
+    Bitset<int64_t> connected_to(n);
+    update(connected_to, vertices_indexed[i]->in());
+    update(connected_to, vertices_indexed[i]->out());
+    connected.push_back(connected_to);
+  }
+  std::vector<std::vector<int>> results;
+  for (int i = 0; i < n; ++i) {
+    const VertexAccessor v = *vertices_indexed[i];
+    auto cmp_res = v.PropsAt(db_accessor.property("garment_id")) ==
+                   args.at(query_type == CliqueQuery::SCORE_AND_LIMIT ? 8 : 0);
+    if (cmp_res.type_ != TypedValue::Type::Bool) continue;
+    if (cmp_res.Value<bool>() != true) continue;
+    auto neigh = connected[i].Ones();
+    for (int j : neigh) {
+      if (j == i) continue;
+      for (int k : connected[j].Intersect(connected[i]).Ones()) {
+        if (k == i) continue;
+        if (k == j) continue;
+        Bitset<int64_t> intersection = connected[j].Intersect(connected[k]);
+        for (int l : intersection.Ones()) {
+          if (l == i) continue;
+          if (l == j) continue;
+          if (l == k) continue;
+          if (connected[l].At(i) == false) continue;
+          results.push_back({i, j, k, l});
+        }
+      }
+    }
+  }
+  /**
+   * Get edge index of edge associated with two vertices.
+   * @param first one vertex endpoint
+   * @param second other vertex endpoint
+   * @return EdgeAccessor* if it exists, nullptr otherwise.
+   */
+  auto get_edge = [&edges_indexed](
+      const VertexAccessor &first,
+      const VertexAccessor &second) -> EdgeAccessor * {
+    auto cmp_edge_to_pair = [](
+        const EdgeAccessor *edge,
+        const pair<const VertexAccessor *, const VertexAccessor *> &e) -> bool {
+      if (edge->from() != *e.first) return edge->from() < *e.first;
+      if (edge->to() != *e.second) return edge->to() < *e.second;
+      return false;
+    };
+    auto pos = lower_bound(edges_indexed.begin(), edges_indexed.end(),
+                           std::make_pair(&first, &second), cmp_edge_to_pair) -
+               edges_indexed.begin();
+    if (pos != (int)edges_indexed.size() &&
+        edges_indexed[pos]->from() == first &&
+        edges_indexed[pos]->to() == second)
+      return edges_indexed[pos];
+    pos = lower_bound(edges_indexed.begin(), edges_indexed.end(),
+                      std::make_pair(&second, &first), cmp_edge_to_pair) -
+          edges_indexed.begin();
+    if (pos != (int)edges_indexed.size() &&
+        edges_indexed[pos]->from() == second &&
+        edges_indexed[pos]->to() == first)
+      return edges_indexed[pos];
+    debug_assert(false, "Edge doesn't exist.");
+    return nullptr;
+  };
+
+  /**
+   * Calculate score of clique by profile_index if it exists.
+   * @param V index of clique vertices in vertices_indexed.
+   * @return score if profile_index exists, else 0.
+   */
+  auto calc_score = [&db_accessor, &vertices, &profile_index, &vertices_indexed,
+                     &get_edge](const std::vector<int> &V) -> int {
+    int res = 0;
+    if (profile_index == -1) return 0;
+    for (auto x : V) {
+      auto edge = get_edge(vertices[profile_index], *vertices_indexed[x]);
+      if (edge == nullptr) continue;
+      auto prop = edge->PropsAt(db_accessor.property("score"));
+      if (prop.type_ == TypedValue::Type::Int) res += prop.Value<int>();
+    }
+    return res;
+  };
+  if (query_type == CliqueQuery::SCORE_AND_LIMIT) {
+    auto cmp_results = [&calc_score](const std::vector<int> &first,
+                                     const std::vector<int> &second) {
+      return calc_score(first) < calc_score(second);
+    };
+    sort(results.begin(), results.end(), cmp_results);
+    reverse(results.begin(), results.end());
+  }
+  const int limit = query_type == CliqueQuery::SCORE_AND_LIMIT
+                        ? args.at((int)args.size() - 1).Value<int>()
+                        : (int)results.size();
+  for (int i = 0; i < std::min(limit, (int)results.size()); ++i) {
+    stream.write_record();
+    stream.write_list_header(query_type == CliqueQuery::SCORE_AND_LIMIT ? 5
+                                                                        : 4);
+    for (auto x : results[i]) {
+      stream.write(vertices_indexed[x]
+                       ->PropsAt(db_accessor.property("garment_id"))
+                       .Value<int>());
+    }
+    if (query_type == CliqueQuery::SCORE_AND_LIMIT)
+      stream.write(calc_score(results[i]));
+  }
+  stream.write_empty_fields();
+  stream.write_meta("r");
+  db_accessor.transaction_.commit();
+  return true;
+}
diff --git a/tests/integration/hardcoded_query/clique_scored.cpp b/tests/integration/hardcoded_query/clique_scored.cpp
new file mode 100644
index 000000000..c091f7a01
--- /dev/null
+++ b/tests/integration/hardcoded_query/clique_scored.cpp
@@ -0,0 +1,40 @@
+#include <algorithm>
+#include <bitset>
+#include <iostream>
+#include <string>
+
+#include "clique.hpp"
+#include "query/plan_interface.hpp"
+#include "storage/edge_accessor.hpp"
+#include "storage/vertex_accessor.hpp"
+#include "using.hpp"
+#include "utils/assert.hpp"
+
+using std::cout;
+using std::endl;
+
+// Query: MATCH
+//  (a:garment)-[:default_outfit]-(b:garment)-[:default_outfit]-(c:garment)-[:default_outfit]-(d:garment)-[:default_outfit]-(a:garment)-[:default_outfit]-(c:garment),
+//  (b:garment)-[:default_outfit]-(d:garment), (e:profile {profile_id: 112,
+//  partner_id: 55})-[s1:score]-(a:garment),(e:profile {profile_id: 112,
+//  partner_id: 55})-[s2:score]-(b:garment), (e:profile {profile_id: 112,
+//  partner_id: 55})-[s3:score]-(c:garment), (e:profile {profile_id: 112,
+//  partner_id: 55})-[s4:score]-(d:garment) WHERE a.garment_id=1234 RETURN
+//  a.garment_id,b.garment_id,c.garment_id,d.garment_id,
+//  s1.score+s2.score+s3.score+s4.score ORDER BY
+//  s1.score+s2.score+s3.score+s4.score DESC LIMIT 10
+
+class CPUPlan : public PlanInterface<Stream> {
+ public:
+  bool run(GraphDbAccessor &db_accessor, const TypedValueStore<> &args,
+           Stream &stream) {
+    return run_general_query(db_accessor, args, stream,
+                             CliqueQuery::SCORE_AND_LIMIT);
+  }
+
+  ~CPUPlan() {}
+};
+
+extern "C" PlanInterface<Stream> *produce() { return new CPUPlan(); }
+
+extern "C" void destruct(PlanInterface<Stream> *p) { delete p; }
diff --git a/tests/integration/hardcoded_query/delete_all.cpp b/tests/integration/hardcoded_query/delete_all.cpp
new file mode 100644
index 000000000..f0303654f
--- /dev/null
+++ b/tests/integration/hardcoded_query/delete_all.cpp
@@ -0,0 +1,26 @@
+#include <iostream>
+#include <string>
+
+#include "query/plan_interface.hpp"
+#include "using.hpp"
+
+using std::cout;
+using std::endl;
+
+// Query: MATCH (n) DETACH DELETE n
+
+class CPUPlan : public PlanInterface<Stream> {
+ public:
+  bool run(GraphDbAccessor &db_accessor, const TypedValueStore<> &args,
+           Stream &stream) {
+    for (auto v : db_accessor.vertices()) db_accessor.detach_remove_vertex(v);
+    db_accessor.transaction_.commit();
+    return true;
+  }
+
+  ~CPUPlan() {}
+};
+
+extern "C" PlanInterface<Stream> *produce() { return new CPUPlan(); }
+
+extern "C" void destruct(PlanInterface<Stream> *p) { delete p; }
diff --git a/tests/integration/hardcoded_query/match_garment.cpp b/tests/integration/hardcoded_query/match_garment.cpp
new file mode 100644
index 000000000..42b4786e2
--- /dev/null
+++ b/tests/integration/hardcoded_query/match_garment.cpp
@@ -0,0 +1,38 @@
+#include <iostream>
+#include <string>
+
+#include "query/plan_interface.hpp"
+#include "storage/edge_accessor.hpp"
+#include "storage/vertex_accessor.hpp"
+#include "using.hpp"
+
+using std::cout;
+using std::endl;
+
+// Query: MATCH (g:garment {garment_id: 1234}) RETURN g
+
+class CPUPlan : public PlanInterface<Stream> {
+ public:
+  bool run(GraphDbAccessor &db_accessor, const TypedValueStore<> &args,
+           Stream &stream) {
+    stream.write_field("g");
+    for (auto vertex : db_accessor.vertices()) {
+      if (vertex.has_label(db_accessor.label("garment"))) {
+        auto prop = vertex.PropsAt(db_accessor.property("garment_id"));
+        if (prop.type_ == TypedValue::Type::Null) continue;
+        auto cmp = prop == args.at(0);
+        if (cmp.type_ != TypedValue::Type::Bool) continue;
+        if (cmp.Value<bool>() != true) continue;
+        stream.write_vertex_record(vertex);
+      }
+    }
+    stream.write_meta("r");
+    db_accessor.transaction_.commit();
+    return true;
+  }
+  ~CPUPlan() {}
+};
+
+extern "C" PlanInterface<Stream> *produce() { return new CPUPlan(); }
+
+extern "C" void destruct(PlanInterface<Stream> *p) { delete p; }
diff --git a/tests/integration/hardcoded_query/match_profile.cpp b/tests/integration/hardcoded_query/match_profile.cpp
new file mode 100644
index 000000000..0cb626bb4
--- /dev/null
+++ b/tests/integration/hardcoded_query/match_profile.cpp
@@ -0,0 +1,44 @@
+#include <iostream>
+#include <string>
+
+#include "query/plan_interface.hpp"
+#include "storage/edge_accessor.hpp"
+#include "storage/vertex_accessor.hpp"
+#include "using.hpp"
+
+using std::cout;
+using std::endl;
+
+// Query: MATCH (p:profile {profile_id: 112, partner_id: 77}) RETURN p
+
+class CPUPlan : public PlanInterface<Stream> {
+ public:
+  bool run(GraphDbAccessor &db_accessor, const TypedValueStore<> &args,
+           Stream &stream) {
+    stream.write_field("p");
+    for (auto vertex : db_accessor.vertices()) {
+      if (vertex.has_label(db_accessor.label("profile"))) {
+        auto prop = vertex.PropsAt(db_accessor.property("profile_id"));
+        if (prop.type_ == TypedValue::Type::Null) continue;
+        auto cmp = prop == args.at(0);
+        if (cmp.type_ != TypedValue::Type::Bool) continue;
+        if (cmp.Value<bool>() != true) continue;
+
+        auto prop2 = vertex.PropsAt(db_accessor.property("partner_id"));
+        if (prop2.type_ == TypedValue::Type::Null) continue;
+        auto cmp2 = prop2 == args.at(1);
+        if (cmp2.type_ != TypedValue::Type::Bool) continue;
+        if (cmp2.Value<bool>() != true) continue;
+        stream.write_vertex_record(vertex);
+      }
+    }
+    stream.write_meta("r");
+    db_accessor.transaction_.commit();
+    return true;
+  }
+  ~CPUPlan() {}
+};
+
+extern "C" PlanInterface<Stream> *produce() { return new CPUPlan(); }
+
+extern "C" void destruct(PlanInterface<Stream> *p) { delete p; }
diff --git a/tests/integration/hardcoded_query/match_profile_garment_score.cpp b/tests/integration/hardcoded_query/match_profile_garment_score.cpp
new file mode 100644
index 000000000..95845bef8
--- /dev/null
+++ b/tests/integration/hardcoded_query/match_profile_garment_score.cpp
@@ -0,0 +1,59 @@
+#include <iostream>
+#include <string>
+
+#include "query/plan_interface.hpp"
+#include "storage/edge_accessor.hpp"
+#include "storage/vertex_accessor.hpp"
+#include "using.hpp"
+
+using std::cout;
+using std::endl;
+
+// Query: MATCH (p:profile {profile_id: 111, partner_id:
+//  55})-[s:score]-(g:garment
+//  {garment_id: 1234}) RETURN s
+
+class CPUPlan : public PlanInterface<Stream> {
+ public:
+  bool run(GraphDbAccessor &db_accessor, const TypedValueStore<> &args,
+           Stream &stream) {
+    stream.write_field("s");
+    auto profile = [&db_accessor, &args](const VertexAccessor &v) -> bool {
+      auto prop = v.PropsAt(db_accessor.property("profile_id"));
+      if (prop.type_ == TypedValue::Type::Null) return false;
+      auto cmp = prop == args.at(0);
+      if (cmp.type_ != TypedValue::Type::Bool) return false;
+      if (cmp.Value<bool>() != true) return false;
+
+      auto prop2 = v.PropsAt(db_accessor.property("partner_id"));
+      if (prop2.type_ == TypedValue::Type::Null) return false;
+      auto cmp2 = prop2 == args.at(1);
+      if (cmp2.type_ != TypedValue::Type::Bool) return false;
+      return cmp2.Value<bool>();
+    };
+    auto garment = [&db_accessor, &args](const VertexAccessor &v) -> bool {
+      auto prop = v.PropsAt(db_accessor.property("garment_id"));
+      if (prop.type_ == TypedValue::Type::Null) return false;
+      auto cmp = prop == args.at(2);
+      if (cmp.type_ != TypedValue::Type::Bool) return false;
+      return cmp.Value<bool>();
+    };
+    for (auto edge : db_accessor.edges()) {
+      auto from = edge.from();
+      auto to = edge.to();
+      if (edge.edge_type() != db_accessor.edge_type("score")) continue;
+      if ((profile(from) && garment(to)) || (profile(to) && garment(from))) {
+        stream.write_edge_record(edge);
+      }
+    }
+    stream.write_meta("r");
+    db_accessor.transaction_.commit();
+    return true;
+  }
+
+  ~CPUPlan() {}
+};
+
+extern "C" PlanInterface<Stream> *produce() { return new CPUPlan(); }
+
+extern "C" void destruct(PlanInterface<Stream> *p) { delete p; }
diff --git a/tests/integration/hardcoded_query/match_profile_garment_update_score.cpp b/tests/integration/hardcoded_query/match_profile_garment_update_score.cpp
new file mode 100644
index 000000000..180923d9c
--- /dev/null
+++ b/tests/integration/hardcoded_query/match_profile_garment_update_score.cpp
@@ -0,0 +1,60 @@
+#include <iostream>
+#include <string>
+
+#include "query/plan_interface.hpp"
+#include "storage/edge_accessor.hpp"
+#include "storage/vertex_accessor.hpp"
+#include "using.hpp"
+
+using std::cout;
+using std::endl;
+
+// Query: MATCH (p:profile {profile_id: 111, partner_id:
+//  55})-[s:score]-(g:garment
+//  {garment_id: 1234}) SET s.score = 3137 RETURN s
+
+class CPUPlan : public PlanInterface<Stream> {
+ public:
+  bool run(GraphDbAccessor &db_accessor, const TypedValueStore<> &args,
+           Stream &stream) {
+    stream.write_field("s");
+    auto profile = [&db_accessor, &args](const VertexAccessor &v) -> bool {
+      auto prop = v.PropsAt(db_accessor.property("profile_id"));
+      if (prop.type_ == TypedValue::Type::Null) return false;
+      auto cmp = prop == args.at(0);
+      if (cmp.type_ != TypedValue::Type::Bool) return false;
+      if (cmp.Value<bool>() != true) return false;
+
+      auto prop2 = v.PropsAt(db_accessor.property("partner_id"));
+      if (prop2.type_ == TypedValue::Type::Null) return false;
+      auto cmp2 = prop2 == args.at(1);
+      if (cmp2.type_ != TypedValue::Type::Bool) return false;
+      return cmp2.Value<bool>();
+    };
+    auto garment = [&db_accessor, &args](const VertexAccessor &v) -> bool {
+      auto prop = v.PropsAt(db_accessor.property("garment_id"));
+      if (prop.type_ == TypedValue::Type::Null) return false;
+      auto cmp = prop == args.at(2);
+      if (cmp.type_ != TypedValue::Type::Bool) return false;
+      return cmp.Value<bool>();
+    };
+    for (auto edge : db_accessor.edges()) {
+      auto from = edge.from();
+      auto to = edge.to();
+      if (edge.edge_type() != db_accessor.edge_type("score")) continue;
+      if ((profile(from) && garment(to)) || (profile(to) && garment(from))) {
+        edge.PropsSet(db_accessor.property("score"), args.at(3));
+        stream.write_edge_record(edge);
+      }
+    }
+    stream.write_meta("rw");
+    db_accessor.transaction_.commit();
+    return true;
+  }
+
+  ~CPUPlan() {}
+};
+
+extern "C" PlanInterface<Stream> *produce() { return new CPUPlan(); }
+
+extern "C" void destruct(PlanInterface<Stream> *p) { delete p; }
diff --git a/tests/integration/hardcoded_query/using.hpp b/tests/integration/hardcoded_query/using.hpp
index 892bed8e0..35ed43da0 100644
--- a/tests/integration/hardcoded_query/using.hpp
+++ b/tests/integration/hardcoded_query/using.hpp
@@ -2,7 +2,7 @@
 
 // the flag is only used in hardcoded queries compilation
 //     see usage in plan_compiler.hpp
-#ifdef HARDCODED_OUTPUT_STREAM
+#ifndef HARDCODED_OUTPUT_STREAM
 #include "communication/bolt/communication.hpp"
 using Stream = communication::OutputStream;
 #else
diff --git a/tests/integration/query_engine_common.hpp b/tests/integration/query_engine_common.hpp
index 153b18fd8..2d9497411 100644
--- a/tests/integration/query_engine_common.hpp
+++ b/tests/integration/query_engine_common.hpp
@@ -98,8 +98,8 @@ auto LoadQueryPlans(Logger &log, QueryEngineT &engine,
       auto query = trim(line.substr(pos + query_mark.size()));
       while (i + 1 < (int)lines.size() &&
              lines[i + 1].find(comment) != std::string::npos) {
-        query += trim(
-            lines[i + 1].substr(lines[i + 1].find(comment) + comment.length()));
+        query +=
+            lines[i + 1].substr(lines[i + 1].find(comment) + comment.length());
         ++i;
       }
       // load/compile implementations only for the queries which are
diff --git a/tests/integration/stream/print_record_stream.hpp b/tests/integration/stream/print_record_stream.hpp
index 1b1ad3a97..e05309b35 100644
--- a/tests/integration/stream/print_record_stream.hpp
+++ b/tests/integration/stream/print_record_stream.hpp
@@ -63,7 +63,7 @@ class PrintRecordStream {
     stream << "Field: " << field << '\n';
   }
 
-  void write(const TypedValue &value) { stream << value; }
+  void write(const TypedValue &value) { stream << value << " "; }
   void write_list_header(size_t size) { stream << "List: " << size << '\n'; }
 
   void write_record() { stream << "Record\n"; }
diff --git a/tests/manual/query_engine.cpp b/tests/manual/query_engine.cpp
index c0ef4f9e0..f9d7c10f8 100644
--- a/tests/manual/query_engine.cpp
+++ b/tests/manual/query_engine.cpp
@@ -1,3 +1,4 @@
+#define HARDCODED_OUTPUT_STREAM
 #include "../integration/query_engine_common.hpp"
 #include "dbms/dbms.hpp"
 
@@ -39,12 +40,23 @@ int main(int argc, char* argv[]) {
           // take only cpp files
           if (event.path.extension() != ".cpp") return;
 
-          auto query_mark = std::string("// Query: ");
+          auto comment = std::string("// ");
+          auto query_mark = comment + std::string("Query: ");
           auto lines = read_lines(event.path);
-          for (auto& line : lines) {
+          for (int i = 0; i < (int)lines.size(); ++i) {
+            // find query in the line
+            auto& line = lines[i];
             auto pos = line.find(query_mark);
+            // if query doesn't exist pass
             if (pos == std::string::npos) continue;
-            auto query = line.substr(pos + query_mark.size());
+            auto query = trim(line.substr(pos + query_mark.size()));
+            while (i + 1 < (int)lines.size() &&
+                   lines[i + 1].find(comment) != std::string::npos) {
+              query += lines[i + 1].substr(lines[i + 1].find(comment) +
+                                           comment.length());
+              ++i;
+            }
+
             log.info("Reload: {}", query);
             query_engine.Unload(query);
             try {