diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9c0c1d8f5b1a5af810ed3ddfa6e83a00df76da29..cb6ff7b599cdad01da54e4e47f65e80c18149aa1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,7 @@
+
 variables:
     GIT_SUBMODULE_STRATEGY: none
+    SBROAD_DEV_IMAGE: docker-public.binary.picodata.io/sbroad-builder:0.5.0
 
 stages:
     - build
@@ -14,7 +16,7 @@ cache:
 default:
     tags:
         - picodata
-    image: docker-public.binary.picodata.io/picodata/picodata/sbroad/sbroad-builder:0.4.1
+    image: ${SBROAD_DEV_IMAGE}
 build:
     stage: build
     script:
diff --git a/Makefile b/Makefile
index 15b4fb546609e02dcf66d2709c307631852b7d23..7331543e632c7bf3c3722df6936e0727b8e2730b 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@ else
 		SRC_LIB = libsbroad.dylib
 	endif
 endif
+IMAGE_NAME = docker-public.binary.picodata.io/sbroad-builder:0.5.0
 
 bench:
 	make clean
@@ -60,3 +61,7 @@ test_integration:
 	make run_integration
 
 test_all: test bench_check test_integration
+
+update_ci_image:
+	docker build -f ci/Dockerfile -t $(IMAGE_NAME) .
+	docker push $(IMAGE_NAME)
diff --git a/src/api/calculate_bucket_id.rs b/src/api/calculate_bucket_id.rs
index 028647a14f393bc3188bf354d2831d1c6155f4ab..ebbe9e54f33dcd692ea327b790b4544e879fdc3d 100644
--- a/src/api/calculate_bucket_id.rs
+++ b/src/api/calculate_bucket_id.rs
@@ -12,7 +12,7 @@ use crate::api::COORDINATOR_ENGINE;
 use crate::executor::engine::Coordinator;
 use crate::ir::value::Value;
 
-#[derive(Debug, Default, Serialize, PartialEq)]
+#[derive(Debug, Default, Serialize, PartialEq, Eq)]
 /// Tuple with space name and `key:value` map of values
 pub struct ArgsMap {
     /// A key:value `HashMap` with key String and custom type Value
@@ -40,7 +40,7 @@ impl<'de> Deserialize<'de> for ArgsMap {
     }
 }
 
-#[derive(Debug, Default, Serialize, PartialEq, Clone)]
+#[derive(Clone, Debug, Default, Serialize, PartialEq, Eq)]
 /// Tuple with space name and vec of values
 pub struct ArgsTuple {
     /// Vec of custom type Value
@@ -95,11 +95,11 @@ impl TryFrom<FunctionArgs> for Args {
             return Ok(Self::Map(args));
         }
 
-        return Err(QueryPlannerError::CustomError(format!(
+        Err(QueryPlannerError::CustomError(format!(
             "Parsing args {:?} error, \
             expected string, tuple with a space name, or map with a space name as an argument",
             &value
-        )));
+        )))
     }
 }
 
diff --git a/src/api/helper.rs b/src/api/helper.rs
index f05716f195ef127d2862ab9dbc554f5cfa2928b5..ba6276fadf6974b0f60aa8766146af679192212d 100644
--- a/src/api/helper.rs
+++ b/src/api/helper.rs
@@ -28,11 +28,11 @@ where
                 0
             }
             Err(e) => {
-                return tarantool::set_error!(
+                tarantool::set_error!(
                     TarantoolErrorCode::ProcC,
                     "Failed to get configuration: {}",
                     e.to_string()
-                );
+                )
             }
         }
     });
diff --git a/src/api/invalidate_cached_schema.rs b/src/api/invalidate_cached_schema.rs
index 6a67b945bc0077e3334f433ef3bedb190dc3de61..06175a46cc7bd6a7d4f30eb03648f1e586c06079 100644
--- a/src/api/invalidate_cached_schema.rs
+++ b/src/api/invalidate_cached_schema.rs
@@ -23,11 +23,11 @@ pub extern "C" fn invalidate_coordinator_cache(ctx: FunctionCtx, _: FunctionArgs
             0
         }
         Err(e) => {
-            return tarantool::set_error!(
+            tarantool::set_error!(
                 TarantoolErrorCode::ProcC,
                 "Failed to borrow the runtime while clearing cached configuration on router: {}",
                 e.to_string()
-            );
+            )
         }
     })
 }
@@ -43,11 +43,11 @@ pub extern "C" fn invalidate_segment_cache(ctx: FunctionCtx, _: FunctionArgs) ->
             0
         }
         Err(e) => {
-            return tarantool::set_error!(
+            tarantool::set_error!(
                 TarantoolErrorCode::ProcC,
                 "Failed to borrow the runtime while clearing cached configuration on a storage: {}",
                 e.to_string()
-            );
+            )
         }
     })
 }
diff --git a/src/errors.rs b/src/errors.rs
index 8914f6237d99e1d7d52fad51f7904c23b76f167c..06a73258191a37d83a35e644d09cb66c47057916 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -44,7 +44,7 @@ const UNSUPPORTED_TYPE_IR_VALUE: &str = "unsupported type ir value";
 const VALUE_OUT_OF_RANGE_ERROR: &str = "value out of range";
 const TYPE_NOT_IMPLEMENTED: &str = "type is not implemented";
 
-#[derive(Debug, Clone, PartialEq, Serialize)]
+#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
 pub enum QueryPlannerError {
     BucketIdError,
     CustomError(String),
diff --git a/src/executor/bucket.rs b/src/executor/bucket.rs
index 73cc7dddc867c6c918eca1e4ad4e3f85017bd9ff..3e2aab94ae6907460237a766071ccb1916d67e97 100644
--- a/src/executor/bucket.rs
+++ b/src/executor/bucket.rs
@@ -13,7 +13,7 @@ use crate::ir::transformation::redistribution::MotionPolicy;
 use crate::ir::value::Value;
 
 /// Buckets are used to determine which nodes to send the query to.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub enum Buckets {
     // We don't want to keep thousands of buckets in memory
     // so we use a special enum to represent all the buckets
diff --git a/src/executor/engine/cartridge/backend/sql/ir.rs b/src/executor/engine/cartridge/backend/sql/ir.rs
index a79b248ea8191555f2c95bb44f1b2dc69cf398a5..42eca870770d08d52390cf8a946151ef4f8531f4 100644
--- a/src/executor/engine/cartridge/backend/sql/ir.rs
+++ b/src/executor/engine/cartridge/backend/sql/ir.rs
@@ -15,7 +15,7 @@ use crate::ir::Node;
 
 use super::tree::SyntaxData;
 
-#[derive(Debug, PartialEq, Serialize, tlua::Push)]
+#[derive(Debug, PartialEq, Eq, Serialize, tlua::Push)]
 pub struct PatternWithParams {
     pub pattern: String,
     pub params: Vec<Value>,
diff --git a/src/executor/engine/cartridge/backend/sql/tree.rs b/src/executor/engine/cartridge/backend/sql/tree.rs
index 8a312f847ec3f1341367a5f21157cefe2f50d242..c08d604b65e842d43e4f6efe075c7e6c838dc639 100644
--- a/src/executor/engine/cartridge/backend/sql/tree.rs
+++ b/src/executor/engine/cartridge/backend/sql/tree.rs
@@ -14,7 +14,7 @@ use crate::ir::operator::{Bool, Relational};
 use crate::ir::Node;
 
 /// Payload of the syntax tree node.
-#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Serialize)]
 pub enum SyntaxData {
     /// "as alias_name"
     Alias(String),
@@ -39,7 +39,7 @@ pub enum SyntaxData {
 }
 
 /// A syntax tree node.
-#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Serialize)]
 pub struct SyntaxNode {
     /// Payload
     pub(crate) data: SyntaxData,
@@ -145,7 +145,7 @@ impl SyntaxNode {
 }
 
 /// Storage for the syntax nodes.
-#[derive(Deserialize, Serialize, PartialEq, Debug)]
+#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct SyntaxNodes {
     pub(crate) arena: Vec<SyntaxNode>,
     map: HashMap<usize, usize, RandomState>,
@@ -161,7 +161,7 @@ impl SyntaxNodes {
             children, alias, ..
         } = rel
         {
-            let right_id = *children.get(0).ok_or_else(|| {
+            let right_id = *children.first().ok_or_else(|| {
                 QueryPlannerError::CustomError("Sub-query has no children.".into())
             })?;
             let mut children: Vec<usize> = vec![
@@ -480,7 +480,7 @@ impl<'p> SyntaxPlan<'p> {
                     condition,
                     ..
                 } => {
-                    let left_id = *children.get(0).ok_or_else(|| {
+                    let left_id = *children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Inner join doesn't have a left child.".into(),
                         )
@@ -505,7 +505,7 @@ impl<'p> SyntaxPlan<'p> {
                 Relational::Projection {
                     children, output, ..
                 } => {
-                    let left_id = *children.get(0).ok_or_else(|| {
+                    let left_id = *children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError("Projection has no children.".into())
                     })?;
                     // We don't need the row node itself, only its children.
@@ -535,7 +535,7 @@ impl<'p> SyntaxPlan<'p> {
                 Relational::Selection {
                     children, filter, ..
                 } => {
-                    let left_id = *children.get(0).ok_or_else(|| {
+                    let left_id = *children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError("Selection has no children.".into())
                     })?;
                     let sn = SyntaxNode::new_pointer(
@@ -546,7 +546,7 @@ impl<'p> SyntaxPlan<'p> {
                     Ok(self.nodes.push_syntax_node(sn))
                 }
                 Relational::Except { children, .. } | Relational::UnionAll { children, .. } => {
-                    let left_id = *children.get(0).ok_or_else(|| {
+                    let left_id = *children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Union/except doesn't have a left child.".into(),
                         )
diff --git a/src/executor/engine/cartridge/config.rs b/src/executor/engine/cartridge/config.rs
index 3a5df8ad32f48c3ae52a459d4585ac6f73c99d61..a262c6ce8d1fc6d2d387cb72b4610812573582a7 100644
--- a/src/executor/engine/cartridge/config.rs
+++ b/src/executor/engine/cartridge/config.rs
@@ -18,7 +18,7 @@ use tarantool::log::{say, SayLevel};
 ///
 /// Information based on tarantool cartridge schema. Cache knows nothing about bucket distribution in the cluster,
 /// as it is managed by Tarantool's vshard module.
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct RouterConfiguration {
     /// Execute response waiting timeout in seconds.
     waiting_timeout: u64,
diff --git a/src/executor/engine/mock.rs b/src/executor/engine/mock.rs
index 2d48379f261aa101c836708d573c50a4e66218fb..aa7f621a0b7efe06fa7f24b0d627d31fecb68a96 100644
--- a/src/executor/engine/mock.rs
+++ b/src/executor/engine/mock.rs
@@ -209,7 +209,7 @@ impl ProducerResult {
                 "Metadata mismatch. Producer results can't be extended",
             )));
         }
-        self.rows.extend(result.rows.clone());
+        self.rows.extend(result.rows);
         Ok(())
     }
 }
diff --git a/src/executor/ir.rs b/src/executor/ir.rs
index cc21dbf7bdbf67ebb019b8d744b52ab4bab49dd0..27f66e94595a7956530d22f3a7ebbebd19f723b4 100644
--- a/src/executor/ir.rs
+++ b/src/executor/ir.rs
@@ -149,7 +149,7 @@ impl ExecutionPlan {
             )));
         }
 
-        let child_id = children.get(0).ok_or_else(|| {
+        let child_id = children.first().ok_or_else(|| {
             QueryPlannerError::CustomError("Failed to get the first motion child".to_string())
         })?;
 
@@ -182,7 +182,7 @@ impl ExecutionPlan {
             )));
         }
 
-        let child_id = children.get(0).ok_or_else(|| {
+        let child_id = children.first().ok_or_else(|| {
             QueryPlannerError::CustomError("Could not find subquery child".to_string())
         })?;
 
diff --git a/src/executor/vtable.rs b/src/executor/vtable.rs
index f3220765c5c9ccead24d706fad9ea4ec8455f35e..5d75a5a841465ab740c2be93ad2b1d5ca544633b 100644
--- a/src/executor/vtable.rs
+++ b/src/executor/vtable.rs
@@ -18,7 +18,7 @@ struct ShardingRecord(ShardingKey, usize);
 
 /// Result tuple storage, created by the executor. All tuples
 /// have a distribution key.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct VirtualTable {
     /// List of the columns.
     columns: Vec<Column>,
diff --git a/src/frontend/sql.rs b/src/frontend/sql.rs
index b6f8ee3a8a7b084bffa4cda9d3fc73a3d5d7d7e1..57c29518344ec2455c3baef36760669d227fec23 100644
--- a/src/frontend/sql.rs
+++ b/src/frontend/sql.rs
@@ -112,7 +112,7 @@ impl Ast for AbstractSyntaxTree {
             let node = self.nodes.get_node(*id)?;
             match &node.rule {
                 Type::Scan => {
-                    let ast_child_id = node.children.get(0).ok_or_else(|| {
+                    let ast_child_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Could not find child id in scan node".to_string(),
                         )
@@ -148,7 +148,7 @@ impl Ast for AbstractSyntaxTree {
                     }
                 }
                 Type::SubQuery => {
-                    let ast_child_id = node.children.get(0).ok_or_else(|| {
+                    let ast_child_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Child node id is not found among sub-query children.".into(),
                         )
@@ -214,10 +214,10 @@ impl Ast for AbstractSyntaxTree {
 
                     // Reference to the join node.
                     if let (Some(plan_left_id), Some(plan_right_id)) =
-                        (plan_rel_list.get(0), plan_rel_list.get(1))
+                        (plan_rel_list.first(), plan_rel_list.get(1))
                     {
                         if let (Some(ast_scan_id), Some(ast_col_name_id)) =
-                            (node.children.get(0), node.children.get(1))
+                            (node.children.first(), node.children.get(1))
                         {
                             let ast_scan = self.nodes.get_node(*ast_scan_id)?;
                             if let Type::ScanName = ast_scan.rule {
@@ -277,7 +277,7 @@ impl Ast for AbstractSyntaxTree {
                                 ));
                             }
                         } else if let (Some(ast_col_name_id), None) =
-                            (node.children.get(0), node.children.get(1))
+                            (node.children.first(), node.children.get(1))
                         {
                             // Determine the referred side of the join (left or right).
                             let col_name = get_column_name(*ast_col_name_id)?;
@@ -317,10 +317,10 @@ impl Ast for AbstractSyntaxTree {
 
                     // Reference to a single child node.
                     } else if let (Some(plan_rel_id), None) =
-                        (plan_rel_list.get(0), plan_rel_list.get(1))
+                        (plan_rel_list.first(), plan_rel_list.get(1))
                     {
                         let col_name: String = if let (Some(ast_scan_id), Some(ast_col_id)) =
-                            (node.children.get(0), node.children.get(1))
+                            (node.children.first(), node.children.get(1))
                         {
                             // Get column name.
                             let col_name = get_column_name(*ast_col_id)?;
@@ -349,7 +349,7 @@ impl Ast for AbstractSyntaxTree {
                             };
                             col_name
                         } else if let (Some(ast_col_id), None) =
-                            (node.children.get(0), node.children.get(1))
+                            (node.children.first(), node.children.get(1))
                         {
                             // Get the column name.
                             get_column_name(*ast_col_id)?
@@ -367,7 +367,7 @@ impl Ast for AbstractSyntaxTree {
                             false,
                             true,
                         )?;
-                        let ref_id = *ref_list.get(0).ok_or_else(|| {
+                        let ref_id = *ref_list.first().ok_or_else(|| {
                             QueryPlannerError::CustomError("Referred column is not found.".into())
                         })?;
                         map.add(*id, ref_id);
@@ -405,7 +405,7 @@ impl Ast for AbstractSyntaxTree {
                             "Sub-queries in projections are not implemented yet.".into(),
                         ));
                     }
-                    let plan_rel_id = *plan_rel_list.get(0).ok_or_else(|| {
+                    let plan_rel_id = *plan_rel_list.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Referred relational node is not found.".into(),
                         )
@@ -414,7 +414,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, plan_asterisk_id);
                 }
                 Type::Alias => {
-                    let ast_ref_id = node.children.get(0).ok_or_else(|| {
+                    let ast_ref_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Reference node id is not found among alias children.".into(),
                         )
@@ -439,7 +439,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, plan_alias_id);
                 }
                 Type::Column => {
-                    let ast_child_id = node.children.get(0).ok_or_else(|| {
+                    let ast_child_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError("Column has no children.".into())
                     })?;
                     let plan_child_id = map.get(*ast_child_id)?;
@@ -453,7 +453,7 @@ impl Ast for AbstractSyntaxTree {
                         // reference-to-row logic in AST code, we should unwrap it back.
                         let plan_id = if rows.get(&plan_child_id).is_some() {
                             let plan_inner_expr = plan.get_expression_node(plan_child_id)?;
-                            *plan_inner_expr.get_row_list()?.get(0).ok_or_else(|| {
+                            *plan_inner_expr.get_row_list()?.first().ok_or_else(|| {
                                 QueryPlannerError::CustomError("Row is empty.".into())
                             })?
                         } else {
@@ -474,7 +474,7 @@ impl Ast for AbstractSyntaxTree {
                 | Type::LtEq
                 | Type::NotEq
                 | Type::NotIn => {
-                    let ast_left_id = node.children.get(0).ok_or_else(|| {
+                    let ast_left_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Left node id is not found among comparison children.".into(),
                         )
@@ -491,7 +491,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, cond_id);
                 }
                 Type::IsNull | Type::IsNotNull => {
-                    let ast_child_id = node.children.get(0).ok_or_else(|| {
+                    let ast_child_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(format!("{:?} has no children.", &node.rule))
                     })?;
                     let plan_child_id = plan.as_row(map.get(*ast_child_id)?, &mut rows)?;
@@ -501,7 +501,7 @@ impl Ast for AbstractSyntaxTree {
                 }
                 Type::Between => {
                     // left BETWEEN center AND right
-                    let ast_left_id = node.children.get(0).ok_or_else(|| {
+                    let ast_left_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Left node id is not found among between children.".into(),
                         )
@@ -526,14 +526,14 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, and_id);
                 }
                 Type::Condition => {
-                    let ast_child_id = node.children.get(0).ok_or_else(|| {
+                    let ast_child_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError("Condition has no children.".into())
                     })?;
                     let plan_child_id = map.get(*ast_child_id)?;
                     map.add(*id, plan_child_id);
                 }
                 Type::InnerJoin => {
-                    let ast_left_id = node.children.get(0).ok_or_else(|| {
+                    let ast_left_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Left node id is not found among join children.".into(),
                         )
@@ -555,7 +555,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, plan_join_id);
                 }
                 Type::Selection => {
-                    let ast_child_id = node.children.get(0).ok_or_else(|| {
+                    let ast_child_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Child node id is not found among selection children.".into(),
                         )
@@ -571,7 +571,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, plan_selection_id);
                 }
                 Type::Projection => {
-                    let ast_child_id = node.children.get(0).ok_or_else(|| {
+                    let ast_child_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Child node id is not found among projection children.".into(),
                         )
@@ -583,7 +583,7 @@ impl Ast for AbstractSyntaxTree {
                         match ast_column.rule {
                             Type::Column => {
                                 let ast_alias_id =
-                                    *ast_column.children.get(0).ok_or_else(|| {
+                                    *ast_column.children.first().ok_or_else(|| {
                                         QueryPlannerError::CustomError(
                                             "Alias node id is not found among column children."
                                                 .into(),
@@ -619,7 +619,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, projection_id);
                 }
                 Type::Except => {
-                    let ast_left_id = node.children.get(0).ok_or_else(|| {
+                    let ast_left_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Left node id is not found among except children.".into(),
                         )
@@ -635,7 +635,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, plan_except_id);
                 }
                 Type::UnionAll => {
-                    let ast_left_id = node.children.get(0).ok_or_else(|| {
+                    let ast_left_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Left node id is not found among union all children.".into(),
                         )
@@ -651,7 +651,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, plan_union_all_id);
                 }
                 Type::ValuesRow => {
-                    let ast_child_id = node.children.get(0).ok_or_else(|| {
+                    let ast_child_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError("Values row has no children.".into())
                     })?;
                     let plan_child_id = map.get(*ast_child_id)?;
@@ -668,7 +668,7 @@ impl Ast for AbstractSyntaxTree {
                     map.add(*id, plan_values_id);
                 }
                 Type::Insert => {
-                    let ast_table_id = node.children.get(0).ok_or_else(|| {
+                    let ast_table_id = node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "Table node id is not found among insert children.".into(),
                         )
diff --git a/src/frontend/sql/ast.rs b/src/frontend/sql/ast.rs
index 7f54017ad87dc42c15e0cd381f300f5033a4f740..9c84363a76c70b6948b05abe7dcb3a0631e52223 100644
--- a/src/frontend/sql/ast.rs
+++ b/src/frontend/sql/ast.rs
@@ -22,7 +22,7 @@ pub(super) struct ParseTree;
 /// A list of current rules from the actual grammar.
 /// When new tokens are added to the grammar they
 /// should be also added in the current list.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub enum Type {
     Alias,
     AliasName,
@@ -133,7 +133,7 @@ impl Type {
 }
 
 /// Parse node is a wrapper over the pest pair.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct ParseNode {
     pub(in crate::frontend::sql) children: Vec<usize>,
     pub(in crate::frontend::sql) rule: Type,
@@ -153,7 +153,7 @@ impl ParseNode {
 
 /// A storage arena of the parse nodes
 /// (a node position in the arena vector acts like a reference).
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct ParseNodes {
     pub(crate) arena: Vec<ParseNode>,
 }
@@ -257,7 +257,7 @@ impl<'n> StackParseNode<'n> {
 }
 
 /// AST is a tree build on the top of the parse nodes arena.
-#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct AbstractSyntaxTree {
     pub(in crate::frontend::sql) nodes: ParseNodes,
     pub(in crate::frontend::sql) top: Option<usize>,
@@ -336,7 +336,7 @@ impl AbstractSyntaxTree {
                 )
             })?;
             let child = self.nodes.get_node(child_id)?;
-            let mut node_id = *child.children.get(0).ok_or_else(|| {
+            let mut node_id = *child.children.first().ok_or_else(|| {
                 QueryPlannerError::CustomError(
                     "Selection node doesn't contain any children.".into(),
                 )
@@ -348,7 +348,7 @@ impl AbstractSyntaxTree {
         let top_id = self.get_top()?;
         if selects.contains(&top_id) {
             let top = self.nodes.get_node(top_id)?;
-            let child_id = *top.children.get(0).ok_or_else(|| {
+            let child_id = *top.children.first().ok_or_else(|| {
                 QueryPlannerError::CustomError(
                     "Selection node doesn't contain any children.".into(),
                 )
@@ -376,7 +376,7 @@ impl AbstractSyntaxTree {
         }
 
         // Check that the first child is `Projection`.
-        let proj_id: usize = *children.get(0).ok_or(QueryPlannerError::ValueOutOfRange)?;
+        let proj_id: usize = *children.first().ok_or(QueryPlannerError::ValueOutOfRange)?;
         let proj = self
             .nodes
             .arena
@@ -432,7 +432,7 @@ impl AbstractSyntaxTree {
         selection.children.insert(0, scan_id);
 
         // Check that the first child is `Projection`.
-        let proj_id: usize = *children.get(0).ok_or(QueryPlannerError::ValueOutOfRange)?;
+        let proj_id: usize = *children.first().ok_or(QueryPlannerError::ValueOutOfRange)?;
         let proj = self
             .nodes
             .arena
@@ -498,7 +498,7 @@ impl AbstractSyntaxTree {
         join.children.insert(0, scan_id);
 
         // Check that the first child is `Projection`.
-        let proj_id: usize = *children.get(0).ok_or(QueryPlannerError::ValueOutOfRange)?;
+        let proj_id: usize = *children.first().ok_or(QueryPlannerError::ValueOutOfRange)?;
         let proj = self
             .nodes
             .arena
@@ -578,7 +578,7 @@ impl AbstractSyntaxTree {
         selection.children.insert(0, join_id);
 
         // Check that the first child is `Projection`.
-        let proj_id: usize = *children.get(0).ok_or(QueryPlannerError::ValueOutOfRange)?;
+        let proj_id: usize = *children.first().ok_or(QueryPlannerError::ValueOutOfRange)?;
         let proj = self
             .nodes
             .arena
@@ -614,7 +614,7 @@ impl AbstractSyntaxTree {
                 for child_id in &node.children {
                     let child = self.nodes.get_node(*child_id)?;
                     if let Type::Column = child.rule {
-                        let col_child_id = *child.children.get(0).ok_or_else(|| {
+                        let col_child_id = *child.children.first().ok_or_else(|| {
                             QueryPlannerError::CustomError(
                                 "Column doesn't have any children".into(),
                             )
@@ -626,11 +626,11 @@ impl AbstractSyntaxTree {
                             }
                             Type::Reference => {
                                 let col_name_id: usize = if let (Some(_), Some(col_name_id)) =
-                                    (col_child.children.get(0), col_child.children.get(1))
+                                    (col_child.children.first(), col_child.children.get(1))
                                 {
                                     *col_name_id
                                 } else if let (Some(col_name_id), None) =
-                                    (col_child.children.get(0), col_child.children.get(1))
+                                    (col_child.children.first(), col_child.children.get(1))
                                 {
                                     *col_name_id
                                 } else {
@@ -666,7 +666,7 @@ impl AbstractSyntaxTree {
                     "Parsed node is not a column.".into(),
                 ));
             }
-            let child_id = *node.children.get(0).ok_or_else(|| {
+            let child_id = *node.children.first().ok_or_else(|| {
                 QueryPlannerError::CustomError("Column doesn't have any children".into())
             })?;
             let child = self.nodes.get_node(child_id)?;
@@ -701,7 +701,7 @@ impl AbstractSyntaxTree {
             let rel_node = self.nodes.get_node(*node_id)?;
             match rel_node.rule {
                 Type::Projection => {
-                    let rel_id = rel_node.children.get(0).ok_or_else(|| {
+                    let rel_id = rel_node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "AST projection doesn't have any children.".into(),
                         )
@@ -719,7 +719,7 @@ impl AbstractSyntaxTree {
                     }
                 }
                 Type::Selection => {
-                    let rel_id = rel_node.children.get(0).ok_or_else(|| {
+                    let rel_id = rel_node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "AST selection doesn't have any children.".into(),
                         )
@@ -740,7 +740,7 @@ impl AbstractSyntaxTree {
                     }
                 }
                 Type::InnerJoin => {
-                    let left_id = rel_node.children.get(0).ok_or_else(|| {
+                    let left_id = rel_node.children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError(
                             "AST inner join doesn't have a left child.".into(),
                         )
diff --git a/src/ir.rs b/src/ir.rs
index c156abd89f73d40fd8be2c4ab2bda53a68d6565d..014795116a04a1385e1c63cc1881e9e08282c63c 100644
--- a/src/ir.rs
+++ b/src/ir.rs
@@ -34,7 +34,7 @@ pub mod value;
 ///
 /// Enum was chosen as we don't want to mess with dynamic
 /// dispatching and its performance penalties.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub enum Node {
     Expression(Expression),
     Relational(Relational),
@@ -42,7 +42,7 @@ pub enum Node {
 }
 
 /// Plan nodes storage.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct Nodes {
     /// We don't want to mess with the borrow checker and RefCell/Rc,
     /// so all nodes are stored in the single arena ("nodes" array).
@@ -88,7 +88,7 @@ impl Nodes {
 }
 
 /// Logical plan tree structure.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct Plan {
     /// Append only arena for the plan nodes.
     pub(crate) nodes: Nodes,
@@ -441,7 +441,7 @@ impl Plan {
                 let child_ids = targets.as_ref().ok_or_else(|| {
                     QueryPlannerError::CustomError("Node refs to scan node, not alias".into())
                 })?;
-                let column_index_in_list = child_ids.get(0).ok_or_else(|| {
+                let column_index_in_list = child_ids.first().ok_or_else(|| {
                     QueryPlannerError::CustomError("Invalid child index in target".into())
                 })?;
                 let col_idx_in_rel =
diff --git a/src/ir/distribution.rs b/src/ir/distribution.rs
index 4d42d080b3f2ab32b9ade71232148696d1c480c6..c1eeb142e900f19d0c76083b43c6a87c754ef6c4 100644
--- a/src/ir/distribution.rs
+++ b/src/ir/distribution.rs
@@ -33,7 +33,7 @@ impl Key {
 }
 
 /// Tuple distribution in the cluster.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub enum Distribution {
     /// A tuple can be located on any data node.
     /// Example: projection removes the segment key columns.
diff --git a/src/ir/expression.rs b/src/ir/expression.rs
index 2a693b49aa7aa8df00271a65c917a21154ff7def..8580e523bff9e99528e3c0324c9842fd9a357dc5 100644
--- a/src/ir/expression.rs
+++ b/src/ir/expression.rs
@@ -30,7 +30,7 @@ use super::{operator, Node, Nodes, Plan};
 /// and should not be changed. It ensures that we always know the
 /// name of any column in the tuple and therefore simplifies AST
 /// deserialization.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub enum Expression {
     /// Expression name.
     ///
@@ -423,7 +423,7 @@ impl Plan {
                                 ..
                             } => {
                                 let sel_child_id = if let (Some(sel_child_id), None) =
-                                    (sel_child_ids.get(0), sel_child_ids.get(1))
+                                    (sel_child_ids.first(), sel_child_ids.get(1))
                                 {
                                     *sel_child_id
                                 } else {
@@ -504,7 +504,7 @@ impl Plan {
         }
 
         result.reserve(col_names.len());
-        let target_child: usize = if let Some(target) = targets.get(0) {
+        let target_child: usize = if let Some(target) = targets.first() {
             *target
         } else {
             return Err(QueryPlannerError::CustomError("Target is empty".into()));
@@ -721,7 +721,7 @@ impl Plan {
                             "Reference node has no targets".into(),
                         ))
                     }
-                    Some(positions) => match (positions.get(0), positions.get(1)) {
+                    Some(positions) => match (positions.first(), positions.get(1)) {
                         (Some(first), None) => {
                             let child_id = children.get(*first).ok_or_else(|| {
                                 QueryPlannerError::CustomError(
diff --git a/src/ir/operator.rs b/src/ir/operator.rs
index b12a32177a976e9bdacc962ce26693f8c7979f53..dad8c6faec7d3d2a2b4c7078f302df33a5560a1d 100644
--- a/src/ir/operator.rs
+++ b/src/ir/operator.rs
@@ -125,7 +125,7 @@ impl Display for Unary {
 ///
 /// Transforms input tuple(s) into the output one using the
 /// relation algebra logic.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub enum Relational {
     Except {
         /// Contains exactly two elements: left and right node indexes
@@ -649,7 +649,7 @@ impl Plan {
             };
             children.push(chid_id);
         }
-        if let (Some(left_id), Some(right_id)) = (children.get(0), children.get(1)) {
+        if let (Some(left_id), Some(right_id)) = (children.first(), children.get(1)) {
             let output = self.add_row_for_join(*left_id, *right_id)?;
             let join = Relational::InnerJoin {
                 children: vec![*left_id, *right_id],
@@ -1073,10 +1073,10 @@ impl Plan {
         };
         match self.get_relation_node(rel_id)? {
             Relational::Selection { .. } | Relational::Projection { .. } => {
-                Ok(children.get(0) != Some(&sq_id))
+                Ok(children.first() != Some(&sq_id))
             }
             Relational::InnerJoin { .. } => {
-                Ok(children.get(0) != Some(&sq_id) && children.get(1) != Some(&sq_id))
+                Ok(children.first() != Some(&sq_id) && children.get(1) != Some(&sq_id))
             }
             _ => Ok(false),
         }
diff --git a/src/ir/relation.rs b/src/ir/relation.rs
index 5c418a73cead06b07c3f36a10de5b29055d0cd49..f658b707c7c22ad05337a3518e884d0369d40db5 100644
--- a/src/ir/relation.rs
+++ b/src/ir/relation.rs
@@ -168,7 +168,7 @@ impl Column {
 /// Table is a tuple storage in the cluster.
 ///
 /// Tables are tuple storages in the cluster.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct Table {
     /// List of the columns.
     pub columns: Vec<Column>,
diff --git a/src/ir/transformation/equality_propagation.rs b/src/ir/transformation/equality_propagation.rs
index 66e192f6fab9bc07e880b430a4090fc13239e48d..f55c1d70e7045f69808e90cb8c0a487ccba5feba 100644
--- a/src/ir/transformation/equality_propagation.rs
+++ b/src/ir/transformation/equality_propagation.rs
@@ -477,7 +477,7 @@ impl Plan {
                 Ok(EqClassExpr::EqClassRef(EqClassRef::from_ref(expr)?))
             }
             Expression::Row { list, .. } => {
-                if let (Some(col_id), None) = (list.get(0), list.get(1)) {
+                if let (Some(col_id), None) = (list.first(), list.get(1)) {
                     self.try_to_eq_class_expr(*col_id)
                 } else {
                     // We don't support more than a single column in a row.
diff --git a/src/ir/transformation/merge_tuples.rs b/src/ir/transformation/merge_tuples.rs
index 35d208ff2f607d3860434e7793f29f35bb3cf5b4..d4aca891031cec50d4d2e694cd7a0f27cc581317 100644
--- a/src/ir/transformation/merge_tuples.rs
+++ b/src/ir/transformation/merge_tuples.rs
@@ -258,6 +258,7 @@ impl Plan {
     /// # Errors
     /// - Failed to build an expression subtree for some chain.
     /// - The plan is invalid (some bugs).
+    #[allow(clippy::type_complexity)]
     pub fn expr_tree_modify_and_chains(
         &mut self,
         expr_id: usize,
diff --git a/src/ir/transformation/redistribution.rs b/src/ir/transformation/redistribution.rs
index f1b3010fd2915519dafe15e42ca6934c199ac0b2..0925d9e17c5ae793276f0a97519daf132b47604a 100644
--- a/src/ir/transformation/redistribution.rs
+++ b/src/ir/transformation/redistribution.rs
@@ -61,7 +61,7 @@ impl From<&Key> for MotionKey {
 }
 
 /// Determinate what portion of data to move between data nodes in cluster.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub enum MotionPolicy {
     /// Move all data.
     Full,
@@ -72,7 +72,7 @@ pub enum MotionPolicy {
 }
 
 /// Determine what portion of data to generate during motion.
-#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub enum DataGeneration {
     /// Nothing to generate.
     None,
@@ -541,7 +541,7 @@ impl Plan {
         let mut inner_keys: Vec<Key> = Vec::new();
 
         let children = self.get_join_children(join_id)?;
-        let outer_child = *children.get(0).ok_or_else(|| {
+        let outer_child = *children.first().ok_or_else(|| {
             QueryPlannerError::CustomError("Join node doesn't have an outer child.".into())
         })?;
         let inner_child = *children.get(1).ok_or_else(|| {
@@ -769,7 +769,8 @@ impl Plan {
                 children,
                 ..
             } => {
-                let child: usize = if let (Some(child), None) = (children.get(0), children.get(1)) {
+                let child: usize = if let (Some(child), None) = (children.first(), children.get(1))
+                {
                     *child
                 } else {
                     return Err(QueryPlannerError::CustomError(
@@ -881,7 +882,7 @@ impl Plan {
         match self.get_relation_node(rel_id)? {
             Relational::Except { children, .. } => {
                 if let (Some(left), Some(right), None) =
-                    (children.get(0), children.get(1), children.get(2))
+                    (children.first(), children.get(1), children.get(2))
                 {
                     let left_output_id = self.get_relation_node(*left)?.output();
                     let right_output_id = self.get_relation_node(*right)?.output();
diff --git a/src/ir/value.rs b/src/ir/value.rs
index f7ca38b112d8e8a2ef2531bf41d7e7368941ca4c..8d00c93be859b4c93a7eb13620aa337aaa300dcc 100644
--- a/src/ir/value.rs
+++ b/src/ir/value.rs
@@ -15,7 +15,7 @@ use crate::ir::value::double::Double;
 
 /// SQL uses three-valued logic. We need to implement
 /// it to compare values with each other.
-#[derive(Serialize, Deserialize, PartialEq, Debug)]
+#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub enum Trivalent {
     False,
     True,
@@ -148,7 +148,7 @@ impl Value {
     /// The result uses three-valued logic.
     #[must_use]
     pub fn eq(&self, other: &Value) -> Trivalent {
-        match &*self {
+        match self {
             Value::Boolean(s) => match other {
                 Value::Boolean(o) => (s == o).into(),
                 Value::Null => Trivalent::Unknown,