aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/tests/sql/suites/join
diff options
context:
space:
mode:
authorMaxim Yurchuk <maxim-yurchuk@ydb.tech>2024-11-20 17:37:57 +0000
committerGitHub <noreply@github.com>2024-11-20 17:37:57 +0000
commitf76323e9b295c15751e51e3443aa47a36bee8023 (patch)
tree4113c8cad473a33e0f746966e0cf087252fa1d7a /yql/essentials/tests/sql/suites/join
parent753ecb8d410a4cb459c26f3a0082fb2d1724fe63 (diff)
parenta7b9a6afea2a9d7a7bfac4c5eb4c1a8e60adb9e6 (diff)
downloadydb-f76323e9b295c15751e51e3443aa47a36bee8023.tar.gz
Merge pull request #11788 from ydb-platform/mergelibs-241120-1113
Library import 241120-1113
Diffstat (limited to 'yql/essentials/tests/sql/suites/join')
-rw-r--r--yql/essentials/tests/sql/suites/join/aggr_diff_order.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/alias_where_group-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/alias_where_group.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/alias_where_group.sql16
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_dup-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_dup.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_dup.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys.sql23
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_nodup-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_nodup.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_common_nodup.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/branch.txt15
-rw-r--r--yql/essentials/tests/sql/suites/join/branch.txt.attr7
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in_in-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in_in.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in_in.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in_in_in-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in_in_in.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_dis_in_in_in.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in_in-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in_in.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in_in.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in_in_in-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in_in_in.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/bush_in_in_in.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables.sql16
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_a.txt14
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_a.txt.attr61
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_b.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_b.txt.attr34
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_c.txt5
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_c.txt.attr34
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_d.txt11
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_d.txt.attr50
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_only_sorted_merge.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/cbo_4tables_only_sorted_merge.sql17
-rw-r--r--yql/essentials/tests/sql/suites/join/commonjoin_unused_keys.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/commonjoin_unused_keys.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/compact_join.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/compact_join.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_check_key_mem-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_check_key_mem.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_check_key_mem.sql40
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_check_key_mem2-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_check_key_mem2.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_check_key_mem2.sql16
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_key-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_key.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_key.sql31
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_key.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/convert_key.txt.attr7
-rw-r--r--yql/essentials/tests/sql/suites/join/count_bans-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/count_bans.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/count_bans.sql45
-rw-r--r--yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/default.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/do_not_suppres_equijoin_input_sorts.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/do_not_suppres_equijoin_input_sorts.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/empty_dynamic.txt0
-rw-r--r--yql/essentials/tests/sql/suites/join/empty_dynamic.txt.attr22
-rw-r--r--yql/essentials/tests/sql/suites/join/emptyjoin_unused_keys.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/emptyjoin_unused_keys.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_by_expr-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_by_expr.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_by_expr.sql3
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_asterisk-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_asterisk.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_asterisk.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_simple-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_simple.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_three_simple.sql3
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys.sql3
-rw-r--r--yql/essentials/tests/sql/suites/join/filter_joined-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/filter_joined.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/filter_joined.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/flatten_columns1-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/flatten_columns1.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/flatten_columns1.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/flatten_columns2-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/flatten_columns2.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/flatten_columns2.sql20
-rw-r--r--yql/essentials/tests/sql/suites/join/force_merge_join.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/from_in_front_join-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/from_in_front_join.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/from_in_front_join.sql3
-rw-r--r--yql/essentials/tests/sql/suites/join/full_equal_not_null-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/full_equal_not_null.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/full_equal_not_null.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/full_equal_null-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/full_equal_null.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/full_equal_null.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/full_join-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/full_join.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/full_join.sql19
-rw-r--r--yql/essentials/tests/sql/suites/join/full_trivial-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/full_trivial.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/full_trivial.sql5
-rw-r--r--yql/essentials/tests/sql/suites/join/full_trivial_udf_call-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/full_trivial_udf_call.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/full_trivial_udf_call.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/gj_countries1.txt25
-rw-r--r--yql/essentials/tests/sql/suites/join/gj_countries1.txt.attr18
-rw-r--r--yql/essentials/tests/sql/suites/join/gj_customers1.txt100
-rw-r--r--yql/essentials/tests/sql/suites/join/gj_customers1.txt.attr18
-rw-r--r--yql/essentials/tests/sql/suites/join/grace_join1-grace.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/grace_join1-map.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/grace_join1-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/grace_join1.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/grace_join1.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/grace_join2.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/grace_join2.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/group_compact_by.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/group_compact_by.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs.sql23
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples.sql22
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_null_key-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_null_key.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_null_key.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_set_key-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_set_key.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_set_key.sql21
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_set_key_any-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_set_key_any.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inmem_with_set_key_any.sql21
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_all-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_all.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_all.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_all_right-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_all_right.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_all_right.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_grouped-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_grouped.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_grouped.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_grouped_by_expr-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_grouped_by_expr.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_grouped_by_expr.sql3
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_on_key_only-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_on_key_only.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_on_key_only.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_table_and_view.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_trivial-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_trivial.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_trivial.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_trivial_from_concat-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_trivial_from_concat.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_trivial_from_concat.sql3
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_with_order-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_with_order.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_with_order.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_with_select-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_with_select.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/inner_with_select.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/input.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/input1.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input2.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input3.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input4.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input5.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input6.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input6.txt.attr9
-rw-r--r--yql/essentials/tests/sql/suites/join/input7.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input8.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input8.txt.attr13
-rw-r--r--yql/essentials/tests/sql/suites/join/input9.txt10
-rw-r--r--yql/essentials/tests/sql/suites/join/input9.txt.attr11
-rw-r--r--yql/essentials/tests/sql/suites/join/input_intersect.txt14
-rw-r--r--yql/essentials/tests/sql/suites/join/input_left.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input_left.txt.attr7
-rw-r--r--yql/essentials/tests/sql/suites/join/input_right.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/input_right.txt.attr7
-rw-r--r--yql/essentials/tests/sql/suites/join/input_tutorial_users.txt12
-rw-r--r--yql/essentials/tests/sql/suites/join/join_and_distinct_key-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/join_and_distinct_key.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/join_and_distinct_key.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/join_and_distinct_key_without_correlation.sqlx6
-rw-r--r--yql/essentials/tests/sql/suites/join/join_cbo_3_tables.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/join_cbo_3_tables.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_common_table-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_common_table.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_common_table.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_inmem-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_inmem.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_inmem.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_map_table-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_map_table.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/join_comp_map_table.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/join_key_cmp_udf-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/join_key_cmp_udf.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/join_key_cmp_udf.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/join_left_cbo.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/join_left_cbo.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/join_right_cbo.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/join_right_cbo.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/join_table_conflict_fail-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/join_table_conflict_fail.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/join_table_conflict_fail.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/join_with_dot_without_alias.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/join_with_dot_without_alias.sqlx6
-rw-r--r--yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_column-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_column.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_column.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access.sql22
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access.sql18
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_names-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_names.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/join_without_correlation_names.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/kv1_sorted.txt32
-rw-r--r--yql/essentials/tests/sql/suites/join/kv1_sorted.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/kv1_sorted1.txt2
-rw-r--r--yql/essentials/tests/sql/suites/join/kv1_sorted1.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/kv2_sorted.txt22
-rw-r--r--yql/essentials/tests/sql/suites/join/kv2_sorted.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/kv2_sorted1.txt2
-rw-r--r--yql/essentials/tests/sql/suites/join/kv2_sorted1.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/kv3_sorted.txt8
-rw-r--r--yql/essentials/tests/sql/suites/join/kv3_sorted.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/kv4_sorted.txt18
-rw-r--r--yql/essentials/tests/sql/suites/join/kv4_sorted.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/kv5_sorted.txt13
-rw-r--r--yql/essentials/tests/sql/suites/join/kv5_sorted.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/late_mergejoin_on_empty.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/late_mergejoin_on_empty.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/leaf.txt17
-rw-r--r--yql/essentials/tests/sql/suites/join/leaf.txt.attr6
-rw-r--r--yql/essentials/tests/sql/suites/join/left_all-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_all.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_all.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/left_cast_to_string-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_cast_to_string.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_cast_to_string.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_input1.txt8
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_input1.txt.attr10
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_input2.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_input2.txt.attr8
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_input3.txt1
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_input3.txt.attr8
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_null_column-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_null_column.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_null_column.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_left.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_left.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_right.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_right.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_no_opt.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_no_opt.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_null.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_null.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_simple.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_right_pushdown_simple.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_with_self_aggr-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_with_self_aggr.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_join_with_self_aggr.sql51
-rw-r--r--yql/essentials/tests/sql/suites/join/left_null_literal-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/left_null_literal.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/left_null_literal.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/left_only_semi_and_other-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_only_semi_and_other.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_only_semi_and_other.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/left_only_with_other-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_only_with_other.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_only_with_other.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/left_semi_with_other-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_semi_with_other.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_semi_with_other.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/left_trivial-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/left_trivial.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/left_trivial.sql5
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee.sql30
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst.sql28
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug8533-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug8533.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_bug8533.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_not_selected-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_not_selected.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_not_selected.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_take_skip.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_take_skip.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_unused_keys.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_unused_keys.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_with_cache-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_with_cache.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/lookupjoin_with_cache.sql19
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_dup_key-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_dup_key.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_dup_key.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence-off.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_left_null_column-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_left_null_column.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_left_null_column.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many.sql16
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt.sql23
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys.sql18
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_sharded.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_unused_keys.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_unused_keys.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read.sql20
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce.sql5
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_big_primary-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_big_primary.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_big_primary.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_choose_primary-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_choose_primary.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_choose_primary.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align1-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align1.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align1.sql26
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align2-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align2.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align2.sql22
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align3-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align3.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_align3.sql19
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted.sql5
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_per_link-off.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_per_link.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_force_per_link.sql18
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_input1.txt20
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_input1.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_input2.txt5
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_input2.txt.attr60
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_left_null_column-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_left_null_column.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_left_null_column.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort.sql42
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_unmatched.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_unmatched.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner-off.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_small_primary-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_small_primary.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_small_primary.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_inner.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_inner.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_left.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_left.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_nomatch.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_nomatch.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_right.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_right.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_unused_keys.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_unused_keys.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names.sql19
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename.sql19
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_table_range-off.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_table_range.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/mergejoin_with_table_range.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/nested_semi_join-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/nested_semi_join.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/nested_semi_join.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/opt_on_opt_side-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/opt_on_opt_side.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/opt_on_opt_side.sql20
-rw-r--r--yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group.sql24
-rw-r--r--yql/essentials/tests/sql/suites/join/order_of_qualified-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/order_of_qualified.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/order_of_qualified.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_cross-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_cross.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_cross.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner_filter-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner_filter.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_inner_filter.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_left_cross-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_left_cross.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_left_cross.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_multiparents-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_multiparents.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_multiparents.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_semi-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_semi.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_common_semi.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_context_dep-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_context_dep.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_context_dep.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_cross-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_cross.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_cross.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_inner-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_inner.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_inner.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_semi-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_semi.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_map_semi.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_extrasort1-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_extrasort1.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_extrasort1.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_extrasort2-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_extrasort2.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_extrasort2.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_inner-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_inner.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_inner.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_with_remap-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_with_remap.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_merge_with_remap.sql17
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_no_premap-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_no_premap.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_no_premap.sql27
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_context_dep-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_context_dep.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_context_dep.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_cross-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_cross.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_cross.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_exclusion-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_exclusion.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_exclusion.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_inner-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_inner.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_inner.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_left-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_left.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_left.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_left_semi-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_left_semi.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_left_semi.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_null_column-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_null_column.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_null_column.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_random-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_random.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_random.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_renaming-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_renaming.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_renaming.sql8
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_rownumber-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_rownumber.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pullup_rownumber.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_strict_udf.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_strict_udf.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/pushdown_filter_over_left-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/pushdown_filter_over_left.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/pushdown_filter_over_left.sql6
-rw-r--r--yql/essentials/tests/sql/suites/join/right_trivial-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/right_trivial.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/right_trivial.sql5
-rw-r--r--yql/essentials/tests/sql/suites/join/root.txt20
-rw-r--r--yql/essentials/tests/sql/suites/join/root.txt.attr8
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter-replicate.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter.sql4
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename.sql2
-rw-r--r--yql/essentials/tests/sql/suites/join/simple_columns_partial-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/simple_columns_partial.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/simple_columns_partial.sql23
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_k1.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_k1.txt.attr19
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_k2.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_k2.txt.attr19
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key1.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key1.txt.attr19
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key2.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key2.txt.attr19
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key3.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key3.txt.attr19
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key4.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key4.txt.attr19
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key_subkey.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_key_subkey.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1_1.txt10
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1_1.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1_dup.txt8
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1_dup.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1_opt.txt5
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1_opt.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1_unique.txt4
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv1_unique.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv2.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv2.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv2_dup.txt6
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv2_dup.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv2_empty.txt0
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv2_empty.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv2_opt.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv2_opt.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv3.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_by_kv3.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_uniq.txt8
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_uniq.txt.attr12
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_uniq1.txt14
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_uniq1.txt.attr12
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_uniq2.txt14
-rw-r--r--yql/essentials/tests/sql/suites/join/sorted_uniq2.txt.attr12
-rw-r--r--yql/essentials/tests/sql/suites/join/spider_info.txt8
-rw-r--r--yql/essentials/tests/sql/suites/join/split_to_list_as_key-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/split_to_list_as_key.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/split_to_list_as_key.sql7
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners_premap-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners_premap.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners_premap.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_mirror-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_mirror.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_mirror.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_multi-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_multi.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_multi.sql22
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_semionly-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_semionly.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_semionly.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_semionly_premap-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_semionly_premap.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_semionly_premap.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_with_diff_complex_key.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/star_join_with_diff_complex_key.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/starjoin_unused_keys.cfg6
-rw-r--r--yql/essentials/tests/sql/suites/join/starjoin_unused_keys.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/strict_keys-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/strict_keys.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/strict_keys.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/table_funcs_spec_join.sqlx9
-rw-r--r--yql/essentials/tests/sql/suites/join/test_join_1.txt1000
-rw-r--r--yql/essentials/tests/sql/suites/join/test_join_2.txt100
-rw-r--r--yql/essentials/tests/sql/suites/join/three_equalities-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/three_equalities.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/three_equalities.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/three_equalities_paren-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/three_equalities_paren.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/three_equalities_paren.sql11
-rw-r--r--yql/essentials/tests/sql/suites/join/trivial_view-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/trivial_view.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/trivial_view.sql9
-rw-r--r--yql/essentials/tests/sql/suites/join/two_aggrs.sql18
-rw-r--r--yql/essentials/tests/sql/suites/join/uniqkeys.txt10
-rw-r--r--yql/essentials/tests/sql/suites/join/uniqkeys.txt.attr12
-rw-r--r--yql/essentials/tests/sql/suites/join/view_input.txt3
-rw-r--r--yql/essentials/tests/sql/suites/join/view_input.txt.attr31
-rw-r--r--yql/essentials/tests/sql/suites/join/vk1_sorted.txt32
-rw-r--r--yql/essentials/tests/sql/suites/join/vk1_sorted.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/vk2_sorted.txt22
-rw-r--r--yql/essentials/tests/sql/suites/join/vk2_sorted.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/vk3_sorted.txt8
-rw-r--r--yql/essentials/tests/sql/suites/join/vk3_sorted.txt.attr25
-rw-r--r--yql/essentials/tests/sql/suites/join/wrong_order_by_col.sqlx16
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-12022-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-12022.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-12022.sql13
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14829_left-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14829_left.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14829_left.sql35
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14829_leftonly-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14829_leftonly.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14829_leftonly.sql35
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14847-off.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14847.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-14847.sql23
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-16011.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-16011.sql27
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-19081.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-19081.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-4275-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-4275.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-4275.sql10
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-4275.txt6
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-4275.txt.attr40
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-6199-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-6199.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-6199.sql12
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-6297-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-6297.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-6297.sql21
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8125-off.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8125.cfg1
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8125.sql29
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8131-off.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8131.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8131.sql14
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8980-off.cfg7
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8980.cfg5
-rw-r--r--yql/essentials/tests/sql/suites/join/yql-8980.sql15
-rw-r--r--yql/essentials/tests/sql/suites/join/yql_465-off.cfg4
-rw-r--r--yql/essentials/tests/sql/suites/join/yql_465.cfg2
-rw-r--r--yql/essentials/tests/sql/suites/join/yql_465.sql3
772 files changed, 7588 insertions, 0 deletions
diff --git a/yql/essentials/tests/sql/suites/join/aggr_diff_order.sql b/yql/essentials/tests/sql/suites/join/aggr_diff_order.sql
new file mode 100644
index 0000000000..21762aa6c1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/aggr_diff_order.sql
@@ -0,0 +1,14 @@
+USE plato;
+
+PRAGMA yt.JoinMergeForce = "1";
+pragma yt.JoinMergeTablesLimit="10";
+
+SELECT key1, subkey1
+FROM
+ (
+ SELECT a.key as key1, a.subkey as subkey1
+ FROM ANY (SELECT * FROM Input8 WHERE subkey != "bar") AS a
+ JOIN ANY (SELECT * FROM Input8 WHERE subkey != "foo") AS b
+ ON a.key = b.key AND a.subkey = b.subkey
+ )
+GROUP COMPACT BY subkey1, key1;
diff --git a/yql/essentials/tests/sql/suites/join/alias_where_group-off.cfg b/yql/essentials/tests/sql/suites/join/alias_where_group-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/alias_where_group-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/alias_where_group.cfg b/yql/essentials/tests/sql/suites/join/alias_where_group.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/alias_where_group.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/alias_where_group.sql b/yql/essentials/tests/sql/suites/join/alias_where_group.sql
new file mode 100644
index 0000000000..bc7f28419c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/alias_where_group.sql
@@ -0,0 +1,16 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+SELECT
+ key,
+ subkey
+FROM Input3 as ia
+INNER JOIN Input4 as ib
+USING(key)
+WHERE
+ ib.subkey = '2'
+GROUP BY
+ ia.key as key,
+ ia.value as subkey
+ORDER BY key \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_dup-off.cfg b/yql/essentials/tests/sql/suites/join/anyjoin_common_dup-off.cfg
new file mode 100644
index 0000000000..ada3709d76
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_dup-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1_dup.txt
+in Input2 sorted_by_kv2_dup.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_dup.cfg b/yql/essentials/tests/sql/suites/join/anyjoin_common_dup.cfg
new file mode 100644
index 0000000000..5186b3d003
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_dup.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1_dup.txt
+in Input2 sorted_by_kv2_dup.txt
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_dup.sql b/yql/essentials/tests/sql/suites/join/anyjoin_common_dup.sql
new file mode 100644
index 0000000000..977215d43a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_dup.sql
@@ -0,0 +1,9 @@
+/* syntax version 1 */
+PRAGMA DisableSimpleColumns;
+use plato;
+
+select * from Input1 as a right join Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from any Input1 as a right join Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from Input1 as a right join any Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from any Input1 as a right join any Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys-off.cfg b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys.cfg b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys.sql b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys.sql
new file mode 100644
index 0000000000..bbde851b43
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodata_keys.sql
@@ -0,0 +1,23 @@
+/* postgres can not */
+/* syntax version 1 */
+
+USE plato;
+
+$a = SELECT AsTuple(1, 2) AS k1, 1 AS k2, 2 AS v;
+
+$b = SELECT AsTuple(1, 2) AS k1, 1 AS k2, 3 AS v1
+ UNION ALL
+ SELECT AsTuple(1, 2) AS k1, 1 AS k2, 3 AS v1;
+
+INSERT INTO @a
+SELECT * FROM $a;
+
+INSERT INTO @b
+SELECT * FROM $b;
+
+COMMIT;
+
+SELECT * FROM @a AS a LEFT JOIN ANY @b AS b using(k1,k2);
+SELECT * FROM @a AS a LEFT JOIN @b AS b using(k1,k2);
+
+
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup-off.cfg b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup.cfg b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup.sql b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup.sql
new file mode 100644
index 0000000000..977215d43a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_common_nodup.sql
@@ -0,0 +1,9 @@
+/* syntax version 1 */
+PRAGMA DisableSimpleColumns;
+use plato;
+
+select * from Input1 as a right join Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from any Input1 as a right join Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from Input1 as a right join any Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from any Input1 as a right join any Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup-off.cfg b/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup.cfg b/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup.sql b/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup.sql
new file mode 100644
index 0000000000..7d9a857905
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/anyjoin_merge_nodup.sql
@@ -0,0 +1,10 @@
+/* syntax version 1 */
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+
+select * from Input1 as a join Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from any Input1 as a join Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from Input1 as a join any Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+select * from any Input1 as a join any Input2 as b on a.k1 = b.k2 order by a.v1, b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/branch.txt b/yql/essentials/tests/sql/suites/join/branch.txt
new file mode 100644
index 0000000000..35d1356535
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/branch.txt
@@ -0,0 +1,15 @@
+{"key"=13u;"leaf"=#;"value"=";dx;lwk;ed"};
+{"key"=17u;"leaf"=5u;"value"="dkeo3o"};
+{"key"=15u;"leaf"=#;"value"=#};
+{"key"=14u;"leaf"=#;"value"="neduiejud"};
+{"key"=10u;"leaf"=1u;"value"="lwk;lde;lw"};
+{"key"=10u;"leaf"=2u;"value"="&&"};
+{"key"=10u;"leaf"=2u;"value"="&&"};
+{"key"=18u;"leaf"=8u;"value"="98743897894"};
+{"key"=18u;"leaf"=3u;"value"="13"};
+{"key"=18u;"leaf"=#;"value"=#};
+{"key"=11u;"leaf"=4u;"value"=#};
+{"key"=19u;"leaf"=#;"value"="huiyhuihji"};
+{"key"=20u;"leaf"=9u;"value"=".xdws;"};
+{"key"=16u;"leaf"=#;"value"="!!!!!!!!!!"};
+{"key"=12u;"leaf"=3u;"value"=#};
diff --git a/yql/essentials/tests/sql/suites/join/branch.txt.attr b/yql/essentials/tests/sql/suites/join/branch.txt.attr
new file mode 100644
index 0000000000..4a77dc3233
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/branch.txt.attr
@@ -0,0 +1,7 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"Uint64"]];
+ ["leaf";["OptionalType";["DataType";"Uint64"]]];
+ ["value";["OptionalType";["DataType";"String"]]]]
+ ];
+}}
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in-off.cfg b/yql/essentials/tests/sql/suites/join/bush_dis_in-off.cfg
new file mode 100644
index 0000000000..f091bc1467
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in-off.cfg
@@ -0,0 +1,5 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in.cfg b/yql/essentials/tests/sql/suites/join/bush_dis_in.cfg
new file mode 100644
index 0000000000..684f34abfd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in.cfg
@@ -0,0 +1,3 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in.sql b/yql/essentials/tests/sql/suites/join/bush_dis_in.sql
new file mode 100644
index 0000000000..82a9d54d6f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+USE plato;
+select * from (
+ SELECT DISTINCT i1.key AS Key, i1.value as Value, i2.value as Join
+ FROM Roots AS i1
+ INNER JOIN Leaves AS i2 ON i1.leaf = i2.key
+ UNION ALL
+ SELECT DISTINCT i1.key AS Key, i1.value as Value, i2.value as Join
+ FROM Roots AS i1
+ INNER JOIN Branches AS i2 ON i1.branch = i2.key
+) order by Key, Value, Join;
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in_in-off.cfg b/yql/essentials/tests/sql/suites/join/bush_dis_in_in-off.cfg
new file mode 100644
index 0000000000..f091bc1467
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in_in-off.cfg
@@ -0,0 +1,5 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in_in.cfg b/yql/essentials/tests/sql/suites/join/bush_dis_in_in.cfg
new file mode 100644
index 0000000000..684f34abfd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in_in.cfg
@@ -0,0 +1,3 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in_in.sql b/yql/essentials/tests/sql/suites/join/bush_dis_in_in.sql
new file mode 100644
index 0000000000..bd1989e82d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in_in.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+USE plato;
+SELECT DISTINCT i1.key AS Key, i1.value AS Value, i2.value AS Leaf, i3.value AS Branch
+FROM Roots AS i1
+INNER JOIN Leaves AS i2 ON i1.leaf = i2.key
+INNER JOIN Branches AS i3 ON i1.branch = i3.key
+ORDER BY Leaf, Branch;
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in-off.cfg b/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in-off.cfg
new file mode 100644
index 0000000000..f091bc1467
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in-off.cfg
@@ -0,0 +1,5 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in.cfg b/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in.cfg
new file mode 100644
index 0000000000..684f34abfd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in.cfg
@@ -0,0 +1,3 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
diff --git a/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in.sql b/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in.sql
new file mode 100644
index 0000000000..22d12df7c5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_dis_in_in_in.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+USE plato;
+SELECT DISTINCT i1.key AS Key, i1.value as Value, i2.value As Leaf, i3.value AS Branch, i4.value AS Branch_Leaf
+FROM Roots AS i1
+INNER JOIN Leaves AS i2 ON i1.leaf = i2.key
+INNER JOIN Branches AS i3 ON i1.branch = i3.key
+INNER JOIN Leaves AS i4 ON i3.leaf = i4.key
+ORDER BY Leaf, Branch, Branch_Leaf;
diff --git a/yql/essentials/tests/sql/suites/join/bush_in-off.cfg b/yql/essentials/tests/sql/suites/join/bush_in-off.cfg
new file mode 100644
index 0000000000..f091bc1467
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in-off.cfg
@@ -0,0 +1,5 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/bush_in.cfg b/yql/essentials/tests/sql/suites/join/bush_in.cfg
new file mode 100644
index 0000000000..684f34abfd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in.cfg
@@ -0,0 +1,3 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
diff --git a/yql/essentials/tests/sql/suites/join/bush_in.sql b/yql/essentials/tests/sql/suites/join/bush_in.sql
new file mode 100644
index 0000000000..af77ba34e3
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+USE plato;
+select * from (
+ SELECT i1.key AS Key, i1.value as Value, i2.value as Join
+ FROM Roots AS i1
+ INNER JOIN Leaves AS i2 ON i1.leaf = i2.key
+ UNION ALL
+ SELECT i1.key AS Key, i1.value as Value, i2.value as Join
+ FROM Roots AS i1
+ INNER JOIN Branches AS i2 ON i1.branch = i2.key
+) order by Key, Value, Join;
diff --git a/yql/essentials/tests/sql/suites/join/bush_in_in-off.cfg b/yql/essentials/tests/sql/suites/join/bush_in_in-off.cfg
new file mode 100644
index 0000000000..f091bc1467
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in_in-off.cfg
@@ -0,0 +1,5 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/bush_in_in.cfg b/yql/essentials/tests/sql/suites/join/bush_in_in.cfg
new file mode 100644
index 0000000000..684f34abfd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in_in.cfg
@@ -0,0 +1,3 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
diff --git a/yql/essentials/tests/sql/suites/join/bush_in_in.sql b/yql/essentials/tests/sql/suites/join/bush_in_in.sql
new file mode 100644
index 0000000000..bf385a0ea9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in_in.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+USE plato;
+SELECT i1.key AS Key, i1.value AS Value, i2.value AS Leaf, i3.value AS Branch
+FROM Roots AS i1
+INNER JOIN Leaves AS i2 ON i1.leaf = i2.key
+INNER JOIN Branches AS i3 ON i1.branch = i3.key
+ORDER BY Leaf, Branch;
diff --git a/yql/essentials/tests/sql/suites/join/bush_in_in_in-off.cfg b/yql/essentials/tests/sql/suites/join/bush_in_in_in-off.cfg
new file mode 100644
index 0000000000..f091bc1467
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in_in_in-off.cfg
@@ -0,0 +1,5 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/bush_in_in_in.cfg b/yql/essentials/tests/sql/suites/join/bush_in_in_in.cfg
new file mode 100644
index 0000000000..684f34abfd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in_in_in.cfg
@@ -0,0 +1,3 @@
+in Roots root.txt
+in Leaves leaf.txt
+in Branches branch.txt
diff --git a/yql/essentials/tests/sql/suites/join/bush_in_in_in.sql b/yql/essentials/tests/sql/suites/join/bush_in_in_in.sql
new file mode 100644
index 0000000000..901aa219d9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/bush_in_in_in.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+USE plato;
+SELECT i1.key AS Key, i1.value as Value, i2.value As Leaf, i3.value AS Branch, i4.value AS Branch_Leaf
+FROM Roots AS i1
+INNER JOIN Leaves AS i2 ON i1.leaf = i2.key
+INNER JOIN Branches AS i3 ON i1.branch = i3.key
+INNER JOIN Leaves AS i4 ON i3.leaf = i4.key;
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables.cfg b/yql/essentials/tests/sql/suites/join/cbo_4tables.cfg
new file mode 100644
index 0000000000..a3f4d2aec3
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables.cfg
@@ -0,0 +1,5 @@
+providers dummy
+in InputA cbo_4tables_a.txt
+in InputB cbo_4tables_b.txt
+in InputC cbo_4tables_c.txt
+in InputD cbo_4tables_d.txt
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables.sql b/yql/essentials/tests/sql/suites/join/cbo_4tables.sql
new file mode 100644
index 0000000000..b96f5c3a79
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables.sql
@@ -0,0 +1,16 @@
+USE plato;
+
+pragma CostBasedOptimizer="native";
+pragma yt.MapJoinLimit="1000";
+pragma yt.LookupJoinLimit="1000";
+pragma yt.LookupJoinMaxRows="100";
+pragma yt.ExtendedStatsMaxChunkCount="0";
+pragma yt.JoinMergeTablesLimit="100";
+
+SELECT
+ InputA.Key1, InputA.Key2, InputA.Value, InputB.val, InputC.v, InputD.value as vald
+FROM
+ InputA
+ INNER JOIN InputD ON InputA.Key2 = InputD.k
+ INNER JOIN InputB ON InputA.Fk1 = InputB.k
+ INNER JOIN InputC ON InputA.Key1 = InputC.k
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_a.txt b/yql/essentials/tests/sql/suites/join/cbo_4tables_a.txt
new file mode 100644
index 0000000000..6c0c166030
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_a.txt
@@ -0,0 +1,14 @@
+{"Key1"=101;"Key2"="One";"Fk1"=#;"Value"="no_right_key_1"};
+{"Key1"=102;"Key2"="Two";"Fk1"=#;"Value"="no_right_key_2"};
+{"Key1"=103;"Key2"="Three";"Fk1"="Name1";"Value"="Value1"};
+{"Key1"=104;"Key2"="One";"Fk1"="Name2";"Value"="Value2"};
+{"Key1"=104;"Key2"="Two";"Fk1"="Name2";"Value"="Value3"};
+{"Key1"=105;"Key2"="One";"Fk1"="Name3";"Value"="no_right_key_3"};
+{"Key1"=106;"Key2"="One";"Fk1"="Name4";"Value"=#};
+{"Key1"=106;"Key2"="Two";"Fk1"="Name4";"Value"="Value4"};
+{"Key1"=107;"Key2"="Seventeen";"Fk1"="Name4";"Value"="Value4"};
+{"Key1"=108;"Key2"="Two";"Fk1"="Name4";"Value"="Value4"};
+{"Key1"=109;"Key2"="Two";"Fk1"="Name1";"Value"="Value4"};
+{"Key1"=110;"Key2"="Four";"Fk1"="Name5";"Value"="Value4"};
+{"Key1"=111;"Key2"="Three";"Fk1"="Name4";"Value"="Value4"};
+{"Key1"=111;"Key2"="Two";"Fk1"="Name4";"Value"="Value4"};
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_a.txt.attr b/yql/essentials/tests/sql/suites/join/cbo_4tables_a.txt.attr
new file mode 100644
index 0000000000..295e5a3d06
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_a.txt.attr
@@ -0,0 +1,61 @@
+{
+ "_yql_row_spec"={
+ "Type"=["StructType";[
+ ["Key1";["DataType";"Int32"]];
+ ["Key2";["DataType";"String"]];
+ ["Fk1";["OptionalType";["DataType";"String"]]];
+ ["Value";["OptionalType";["DataType";"String"]]]]
+ ];
+ "SortDirections"=[1;1];
+ "SortedBy"=["Key1";"Key2"];
+ "SortedByTypes"=[["DataType";"Int32";];["DataType";"String"]];
+ "SortMembers"=["Key1";"Key2"];
+ };
+ "schema" = <"strict" = %true; "unique_keys" = %false>
+ [
+ {
+ "name" = "Key1";
+ "sort_order" = "ascending";
+ "type" = "int64";
+ "type_v3" = {"type_name" = "optional"; item = "int64"}
+ };
+ {
+ "name" = "Key2";
+ "sort_order" = "ascending";
+ "type" = "string";
+ "type_v3" = {"type_name" = "optional"; item = "string"}
+ };
+ {
+ "name" = "Fk1";
+ "type" = "string";
+ "type_v3" = {"type_name" = "optional"; item = "string"}
+ };
+ {
+ "name" = "Value";
+ "type" = "string";
+ "type_v3" = {"type_name" = "optional"; item = "string"}
+ };
+ ];
+ "extended_stats" = [
+ {
+ "column_name" = "Key1";
+ "data_weight" = 56;
+ "num_unique_vals" = 11;
+ };
+ {
+ "column_name" = "Key2";
+ "data_weight" = 66;
+ "num_unique_vals" = 5;
+ };
+ {
+ "column_name" = "Fk1";
+ "data_weight" = 70;
+ "num_unique_vals" = 5;
+ };
+ {
+ "column_name" = "Value";
+ "data_weight" = 98;
+ "num_unique_vals" = 6;
+ }
+ ]
+}
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_b.txt b/yql/essentials/tests/sql/suites/join/cbo_4tables_b.txt
new file mode 100644
index 0000000000..9ef08e2fb7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_b.txt
@@ -0,0 +1,3 @@
+{"k"="Name2";"val"="Misha"};
+{"k"="Name2";"val"="Sasha"};
+{"k"="Name3";"val"="Ksyusha"};
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_b.txt.attr b/yql/essentials/tests/sql/suites/join/cbo_4tables_b.txt.attr
new file mode 100644
index 0000000000..460ca717f8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_b.txt.attr
@@ -0,0 +1,34 @@
+{
+ "_yql_row_spec"={
+ "Type"=["StructType";[
+ ["k";["OptionalType";["DataType";"String"]]];
+ ["val";["OptionalType";["DataType";"String"]]]]
+ ];
+ };
+
+ "schema" = <"strict" = %true; "unique_keys" = %false>
+ [
+ {
+ "name" = "k";
+ "type" = "string";
+ "type_v3" = {"type_name" = "optional"; item = "string"}
+ };
+ {
+ "name" = "val";
+ "type" = "string";
+ "type_v3" = {"type_name" = "optional"; item = "string"}
+ };
+ ];
+ "extended_stats" = [
+ {
+ "column_name" = "k";
+ "data_weight" = 18;
+ "num_unique_vals" = 2;
+ };
+ {
+ "column_name" = "val";
+ "data_weight" = 20;
+ "num_unique_vals" = 3;
+ }
+ ]
+}
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_c.txt b/yql/essentials/tests/sql/suites/join/cbo_4tables_c.txt
new file mode 100644
index 0000000000..803ff2ca0d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_c.txt
@@ -0,0 +1,5 @@
+{"k"=104;v=4};
+{"k"=105;v=5};
+{"k"=106;v=6};
+{"k"=107;v=6};
+{"k"=111;v=10};
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_c.txt.attr b/yql/essentials/tests/sql/suites/join/cbo_4tables_c.txt.attr
new file mode 100644
index 0000000000..fb108546cd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_c.txt.attr
@@ -0,0 +1,34 @@
+{
+ "_yql_row_spec"={
+ "Type"=["StructType";[
+ ["k";["OptionalType";["DataType";"Int64"]]];
+ ["v";["OptionalType";["DataType";"Int64"]]]]
+ ];
+ };
+
+ "schema" = <"strict" = %true; "unique_keys" = %false>
+ [
+ {
+ "name" = "k";
+ "type" = "int64";
+ "type_v3" = {"type_name" = "optional"; item = "int64"}
+ };
+ {
+ "name" = "v";
+ "type" = "int64";
+ "type_v3" = {"type_name" = "optional"; item = "int64"}
+ };
+ ];
+ "extended_stats" = [
+ {
+ "column_name" = "k";
+ "data_weight" = 12;
+ "num_unique_vals" = 3;
+ };
+ {
+ "column_name" = "v";
+ "data_weight" = 12;
+ "num_unique_vals" = 3;
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_d.txt b/yql/essentials/tests/sql/suites/join/cbo_4tables_d.txt
new file mode 100644
index 0000000000..13684e9905
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_d.txt
@@ -0,0 +1,11 @@
+{id=3;"k"="One";"value"=17};
+{id=5;"k"="Two";"value"=17};
+{id=13;"k"="One";"value"=0};
+{id=23;"k"="Three";"value"=-44};
+{id=27;"k"="Ten";"value"=17};
+{id=33;"k"="Zero";"value"=1024};
+{id=38;"k"="Seventeen";"value"=17};
+{id=39;"k"="One";"value"=23};
+{id=40;"k"="Three";"value"=17};
+{id=42;"k"="Four";"value"=25};
+{id=50;"k"="One";"value"=17};
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_d.txt.attr b/yql/essentials/tests/sql/suites/join/cbo_4tables_d.txt.attr
new file mode 100644
index 0000000000..8050807ed9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_d.txt.attr
@@ -0,0 +1,50 @@
+{
+ "_yql_row_spec"={
+ "Type"=["StructType";[
+ ["id";["DataType";"Int32"]];
+ ["k";["OptionalType";["DataType";"String"]]];
+ ["value";["OptionalType";["DataType";"Int64"]]]]
+ ];
+ "SortDirections"=[1];
+ "SortedBy"=["id"];
+ "SortedByTypes"=[["DataType";"Int32"]];
+ "SortMembers"=["id"];
+ };
+
+ "schema" = <"strict" = %true; "unique_keys" = %false>
+ [
+ {
+ "name" = "id";
+ "sort_order" = "ascending";
+ "type" = "int64";
+ "type_v3" = {"type_name" = "optional"; item = "int64"}
+ };
+ {
+ "name" = "k";
+ "type" = "string";
+ "type_v3" = {"type_name" = "optional"; item = "string"}
+ };
+ {
+ "name" = "value";
+ "type" = "int64";
+ "type_v3" = {"type_name" = "optional"; item = "int64"}
+ };
+ ];
+ "extended_stats" = [
+ {
+ "column_name" = "id";
+ "data_weight" = 44;
+ "num_unique_vals" = 11;
+ };
+ {
+ "column_name" = "k";
+ "data_weight" = 66;
+ "num_unique_vals" = 7;
+ };
+ {
+ "column_name" = "value";
+ "data_weight" = 44;
+ "num_unique_vals" = 6;
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_only_sorted_merge.cfg b/yql/essentials/tests/sql/suites/join/cbo_4tables_only_sorted_merge.cfg
new file mode 100644
index 0000000000..a5101acc8c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_only_sorted_merge.cfg
@@ -0,0 +1,5 @@
+providers yt
+in InputA cbo_4tables_a.txt
+in InputB cbo_4tables_b.txt
+in InputC cbo_4tables_c.txt
+in InputD cbo_4tables_d.txt
diff --git a/yql/essentials/tests/sql/suites/join/cbo_4tables_only_sorted_merge.sql b/yql/essentials/tests/sql/suites/join/cbo_4tables_only_sorted_merge.sql
new file mode 100644
index 0000000000..1dce1a70fa
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cbo_4tables_only_sorted_merge.sql
@@ -0,0 +1,17 @@
+USE plato;
+
+pragma CostBasedOptimizer="native";
+pragma yt.MapJoinLimit="1000";
+pragma yt.LookupJoinLimit="1000";
+pragma yt.LookupJoinMaxRows="100";
+pragma yt.ExtendedStatsMaxChunkCount="0";
+pragma yt.JoinMergeTablesLimit="100";
+pragma yt.JoinMergeForce="true";
+
+SELECT
+ InputA.Key1, InputA.Key2, InputA.Value, InputB.val, InputC.v, InputD.value as vald
+FROM
+ InputA
+ INNER JOIN InputD ON InputA.Key2 = InputD.k
+ INNER JOIN InputB ON InputA.Fk1 = InputB.k
+ INNER JOIN InputC ON InputA.Key1 = InputC.k
diff --git a/yql/essentials/tests/sql/suites/join/commonjoin_unused_keys.cfg b/yql/essentials/tests/sql/suites/join/commonjoin_unused_keys.cfg
new file mode 100644
index 0000000000..9a930ffe48
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/commonjoin_unused_keys.cfg
@@ -0,0 +1,6 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/commonjoin_unused_keys.sql b/yql/essentials/tests/sql/suites/join/commonjoin_unused_keys.sql
new file mode 100644
index 0000000000..8d4a07952d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/commonjoin_unused_keys.sql
@@ -0,0 +1,11 @@
+/* syntax version 1 */
+use plato;
+
+select
+
+v3
+
+from Input1 as a
+join Input2 as b on (a.k1 = b.k2)
+join Input3 as c on (a.k1 = c.k3)
+order by v3;
diff --git a/yql/essentials/tests/sql/suites/join/compact_join.cfg b/yql/essentials/tests/sql/suites/join/compact_join.cfg
new file mode 100644
index 0000000000..936236defd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/compact_join.cfg
@@ -0,0 +1,2 @@
+in InputLeft input_left.txt
+in InputRight input_right.txt
diff --git a/yql/essentials/tests/sql/suites/join/compact_join.sql b/yql/essentials/tests/sql/suites/join/compact_join.sql
new file mode 100644
index 0000000000..505bdb34fc
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/compact_join.sql
@@ -0,0 +1,11 @@
+USE plato;
+
+$stream = SELECT a.k AS k, a.sk AS ask, a.v AS av
+FROM InputLeft AS a
+INNER JOIN /*+ merge() compact() */ InputRight AS b
+USING (k, sk, v);
+
+SELECT k, ask, av
+FROM $stream
+GROUP /*+ compact() */ BY (k, ask, av)
+ORDER BY k, ask, av; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/convert_check_key_mem-off.cfg b/yql/essentials/tests/sql/suites/join/convert_check_key_mem-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_check_key_mem-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/convert_check_key_mem.cfg b/yql/essentials/tests/sql/suites/join/convert_check_key_mem.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_check_key_mem.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/convert_check_key_mem.sql b/yql/essentials/tests/sql/suites/join/convert_check_key_mem.sql
new file mode 100644
index 0000000000..5902507e2f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_check_key_mem.sql
@@ -0,0 +1,40 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+
+$a = AsList(
+ AsStruct(255ut AS K, 1 AS V),
+ AsStruct(127ut AS K, 2 AS V),
+ AsStruct(0ut AS K, 3 AS V));
+
+$b = AsList(
+ AsStruct(Int8("-1") AS K, 1u AS V),
+ AsStruct(Int8("127") AS K, 2u AS V),
+ AsStruct(Int8("0") AS K, 3u AS V));
+
+$aopt = AsList(
+ AsStruct(Just(255ut) AS K, 1 AS V),
+ AsStruct(Just(127ut) AS K, 2 AS V),
+ AsStruct(Just(0ut) AS K, 3 AS V),
+ AsStruct(Nothing(ParseType("Uint8?")) AS K, 2 AS V));
+
+$bopt = AsList(
+ AsStruct(Just(Int8("-1")) AS K, 1u AS V),
+ AsStruct(Just(Int8("127")) AS K, 2u AS V),
+ AsStruct(Just(Int8("0")) AS K, 3u AS V),
+ AsStruct(Nothing(ParseType("Int8?")) AS K, 2u AS V));
+
+select a.K, b.V from as_table($a) as a
+ join as_table($b) as b on a.K = b.K and a.V = b.V
+order by a.K, b.V;
+
+select a.K, b.V from as_table($aopt) as a
+ join as_table($b) as b on a.K = b.K and a.V = b.V
+order by a.K, b.V;
+
+select a.K, b.V from as_table($a) as a
+ join as_table($bopt) as b on a.K = b.K and a.V = b.V
+order by a.K, b.V;
+
+select a.K, b.V from as_table($aopt) as a
+ join as_table($bopt) as b on a.K = b.K and a.V = b.V
+order by a.K, b.V;
diff --git a/yql/essentials/tests/sql/suites/join/convert_check_key_mem2-off.cfg b/yql/essentials/tests/sql/suites/join/convert_check_key_mem2-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_check_key_mem2-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/convert_check_key_mem2.cfg b/yql/essentials/tests/sql/suites/join/convert_check_key_mem2.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_check_key_mem2.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/convert_check_key_mem2.sql b/yql/essentials/tests/sql/suites/join/convert_check_key_mem2.sql
new file mode 100644
index 0000000000..d4afb00ee7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_check_key_mem2.sql
@@ -0,0 +1,16 @@
+/* postgres can not */
+PRAGMA DisableSimpleColumns;
+
+$a = AsList(
+ AsStruct(255ut AS K, 1 AS V),
+ AsStruct(127ut AS K, 2 AS V),
+ AsStruct(0ut AS K, 3 AS V));
+
+$b = AsList(
+ AsStruct(Int8("-1") AS K, 1 AS V),
+ AsStruct(Int8("127") AS K, 2 AS V),
+ AsStruct(Int8("0") AS K, 3 AS V));
+
+select a.K, b.V from as_table($a) as a
+ join as_table($b) as b on a.K = b.K and a.V = b.V
+order by a.K, b.V;
diff --git a/yql/essentials/tests/sql/suites/join/convert_key-off.cfg b/yql/essentials/tests/sql/suites/join/convert_key-off.cfg
new file mode 100644
index 0000000000..9e8955692d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_key-off.cfg
@@ -0,0 +1,4 @@
+in Input convert_key.txt
+res result.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/convert_key.cfg b/yql/essentials/tests/sql/suites/join/convert_key.cfg
new file mode 100644
index 0000000000..dd4bfb988d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_key.cfg
@@ -0,0 +1,2 @@
+in Input convert_key.txt
+res result.txt
diff --git a/yql/essentials/tests/sql/suites/join/convert_key.sql b/yql/essentials/tests/sql/suites/join/convert_key.sql
new file mode 100644
index 0000000000..0d5ca60885
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_key.sql
@@ -0,0 +1,31 @@
+/* postgres can not */
+USE plato;
+
+PRAGMA SimpleColumns;
+pragma yt.MapJoinLimit="1m";
+
+$join_result =
+(
+ SELECT
+ i1.k1 as i1_k1,
+ i1.k2 as i1_k2,
+ i1.value as i1_value,
+ i2.k1 as i2_k1,
+ i2.k2 as i2_k2,
+ i2.value as i2_value
+ FROM
+ Input as i1
+ LEFT JOIN
+ (
+ SELECT
+ i2.value as value,
+ cast(i2.k1 as double) as k1,
+ cast(i2.k2 as double) as k2
+ FROM Input as i2
+ ) as i2
+ ON
+ i1.k1 == i2.k1 AND
+ i1.k2 == i2.k2
+);
+
+SELECT * FROM $join_result;
diff --git a/yql/essentials/tests/sql/suites/join/convert_key.txt b/yql/essentials/tests/sql/suites/join/convert_key.txt
new file mode 100644
index 0000000000..0f8369d4db
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_key.txt
@@ -0,0 +1,4 @@
+{"k1"=417840;"k2"=417480;"value"="aaa"};
+{"k1"=417840;"k2"=417480;"value"="ddd"};
+{"k1"=417840;"k2"=417480;"value"="abc"};
+{"k1"=417840;"k2"=417480;"value"="aaa"};
diff --git a/yql/essentials/tests/sql/suites/join/convert_key.txt.attr b/yql/essentials/tests/sql/suites/join/convert_key.txt.attr
new file mode 100644
index 0000000000..63d2666582
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/convert_key.txt.attr
@@ -0,0 +1,7 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["k1";["DataType";"Int64"]];
+ ["k2";["DataType";"Int64"]];
+ ["value";["DataType";"String"]]]
+ ];
+}}
diff --git a/yql/essentials/tests/sql/suites/join/count_bans-off.cfg b/yql/essentials/tests/sql/suites/join/count_bans-off.cfg
new file mode 100644
index 0000000000..764ce5fc59
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/count_bans-off.cfg
@@ -0,0 +1,4 @@
+in spider_info spider_info.txt
+udf url_udf
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/count_bans.cfg b/yql/essentials/tests/sql/suites/join/count_bans.cfg
new file mode 100644
index 0000000000..2e4220b630
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/count_bans.cfg
@@ -0,0 +1,2 @@
+in spider_info spider_info.txt
+udf url_udf
diff --git a/yql/essentials/tests/sql/suites/join/count_bans.sql b/yql/essentials/tests/sql/suites/join/count_bans.sql
new file mode 100644
index 0000000000..499db2c7f7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/count_bans.sql
@@ -0,0 +1,45 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$records = (
+SELECT
+ key as ip,
+ subkey AS recordType,
+ Url::GetHost(value) AS host
+FROM spider_info
+);
+
+$results = (
+SELECT
+ ip,
+ host,
+ count(*) AS request_count
+FROM $records
+WHERE host IS NOT NULL AND recordType == "RESULT"
+GROUP BY ip, host
+);
+
+$bans = (
+SELECT
+ ip,
+ host,
+ count(*) AS fetcher_count
+FROM $records
+WHERE host IS NOT NULL AND recordType == "BAN_DETECTED"
+GROUP BY ip, host
+);
+
+SELECT
+ results.ip AS ip,
+ results.host AS host,
+ results.request_count AS request_count,
+ bans.fetcher_count AS fetcher_count
+FROM
+ $results AS results
+ INNER JOIN
+ $bans AS bans
+ ON bans.ip == results.ip
+ AND bans.host == results.host
+ORDER BY fetcher_count DESC
+;
diff --git a/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list-off.cfg b/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list.cfg b/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list.sql b/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list.sql
new file mode 100644
index 0000000000..3f10761c07
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/cross_join_with_lazy_list.sql
@@ -0,0 +1,10 @@
+$list = AsList(AsStruct('one' AS x), AsStruct('two' AS x));
+$lazy = ListMap(ListFromRange(1s, 3s), ($i)->{ RETURN AsStruct($i AS y) });
+
+SELECT *
+ FROM AS_TABLE($list) as l
+ CROSS JOIN AS_TABLE($lazy) as r;
+
+SELECT *
+ FROM AS_TABLE($lazy) as l
+ CROSS JOIN AS_TABLE($list) as r;
diff --git a/yql/essentials/tests/sql/suites/join/default.cfg b/yql/essentials/tests/sql/suites/join/default.cfg
new file mode 100644
index 0000000000..429c022594
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/default.cfg
@@ -0,0 +1,6 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+in Input8 input8.txt
diff --git a/yql/essentials/tests/sql/suites/join/do_not_suppres_equijoin_input_sorts.cfg b/yql/essentials/tests/sql/suites/join/do_not_suppres_equijoin_input_sorts.cfg
new file mode 100644
index 0000000000..89a1fdcc94
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/do_not_suppres_equijoin_input_sorts.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv1_1.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/do_not_suppres_equijoin_input_sorts.sql b/yql/essentials/tests/sql/suites/join/do_not_suppres_equijoin_input_sorts.sql
new file mode 100644
index 0000000000..314c680b69
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/do_not_suppres_equijoin_input_sorts.sql
@@ -0,0 +1,8 @@
+USE plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma DisableSimpleColumns;
+
+select
+ *
+from Input1 as t1 cross join Input2 as t2
+where t1.k1 == t2.k1 and t1.k1 < "zzz";
diff --git a/yql/essentials/tests/sql/suites/join/empty_dynamic.txt b/yql/essentials/tests/sql/suites/join/empty_dynamic.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/empty_dynamic.txt
diff --git a/yql/essentials/tests/sql/suites/join/empty_dynamic.txt.attr b/yql/essentials/tests/sql/suites/join/empty_dynamic.txt.attr
new file mode 100644
index 0000000000..fad9c383f9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/empty_dynamic.txt.attr
@@ -0,0 +1,22 @@
+{
+ "_yql_dynamic"=%true;
+ "schema"=<
+ "strict" = %true;
+ "unique_keys" = %true
+ >[
+ {
+ "name" = "key";
+ "type" = "string";
+ "sort_order" = "ascending";
+ };
+ {
+ "name" = "subkey";
+ "type" = "string";
+ "sort_order" = "ascending";
+ };
+ {
+ "name" = "value";
+ "type" = "string";
+ };
+ ]
+} \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/emptyjoin_unused_keys.cfg b/yql/essentials/tests/sql/suites/join/emptyjoin_unused_keys.cfg
new file mode 100644
index 0000000000..9a930ffe48
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/emptyjoin_unused_keys.cfg
@@ -0,0 +1,6 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/emptyjoin_unused_keys.sql b/yql/essentials/tests/sql/suites/join/emptyjoin_unused_keys.sql
new file mode 100644
index 0000000000..3e50bfd2df
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/emptyjoin_unused_keys.sql
@@ -0,0 +1,15 @@
+/* syntax version 1 */
+use plato;
+
+insert into @Input1
+select '' as k1, '' as v1, '' as u1 limit 0;
+commit;
+
+select
+
+v3
+
+from @Input1 as a
+join Input2 as b on (a.k1 = b.k2)
+right join Input3 as c on (a.k1 = c.k3)
+order by v3;
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_by_expr-off.cfg b/yql/essentials/tests/sql/suites/join/equi_join_by_expr-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_by_expr-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_by_expr.cfg b/yql/essentials/tests/sql/suites/join/equi_join_by_expr.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_by_expr.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_by_expr.sql b/yql/essentials/tests/sql/suites/join/equi_join_by_expr.sql
new file mode 100644
index 0000000000..d2cad73469
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_by_expr.sql
@@ -0,0 +1,3 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+SELECT * FROM plato.Input2 as A JOIN plato.Input3 as B ON CAST(A.key AS INT) + 1 == CAST(B.key AS INT);
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk-off.cfg b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk-off.cfg
new file mode 100644
index 0000000000..3ff2f86249
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk-off.cfg
@@ -0,0 +1,5 @@
+in A input1.txt
+in B input2.txt
+in C input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk.cfg b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk.cfg
new file mode 100644
index 0000000000..24c926d868
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk.cfg
@@ -0,0 +1,3 @@
+in A input1.txt
+in B input2.txt
+in C input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk.sql b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk.sql
new file mode 100644
index 0000000000..9c56228f58
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+SELECT A.*, C.subkey as goal,B.*
+FROM plato.A
+JOIN plato.B ON A.key == B.key
+JOIN plato.C ON B.subkey == C.subkey
+ORDER BY A.key;
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval-off.cfg b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval-off.cfg
new file mode 100644
index 0000000000..3ff2f86249
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval-off.cfg
@@ -0,0 +1,5 @@
+in A input1.txt
+in B input2.txt
+in C input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval.cfg b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval.cfg
new file mode 100644
index 0000000000..24c926d868
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval.cfg
@@ -0,0 +1,3 @@
+in A input1.txt
+in B input2.txt
+in C input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval.sql b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval.sql
new file mode 100644
index 0000000000..8ad0ef844c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_asterisk_eval.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+SELECT A.*, C.subkey as goal,B.*, A.value || C.value as ac_val_concat
+FROM plato.A
+JOIN plato.B ON A.key == B.key
+JOIN plato.C ON B.subkey == C.subkey
+ORDER BY A.key, goal, ac_val_concat;
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_simple-off.cfg b/yql/essentials/tests/sql/suites/join/equi_join_three_simple-off.cfg
new file mode 100644
index 0000000000..3ff2f86249
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_simple-off.cfg
@@ -0,0 +1,5 @@
+in A input1.txt
+in B input2.txt
+in C input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_simple.cfg b/yql/essentials/tests/sql/suites/join/equi_join_three_simple.cfg
new file mode 100644
index 0000000000..24c926d868
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_simple.cfg
@@ -0,0 +1,3 @@
+in A input1.txt
+in B input2.txt
+in C input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_three_simple.sql b/yql/essentials/tests/sql/suites/join/equi_join_three_simple.sql
new file mode 100644
index 0000000000..c620849a45
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_three_simple.sql
@@ -0,0 +1,3 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+SELECT * FROM plato.A JOIN plato.B ON A.key == B.key JOIN plato.C ON A.subkey == C.subkey;
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys-off.cfg b/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys-off.cfg
new file mode 100644
index 0000000000..c0badaaad9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys-off.cfg
@@ -0,0 +1,4 @@
+in A input1.txt
+in B input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys.cfg b/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys.cfg
new file mode 100644
index 0000000000..661ab46dee
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys.cfg
@@ -0,0 +1,2 @@
+in A input1.txt
+in B input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys.sql b/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys.sql
new file mode 100644
index 0000000000..1119ca50ea
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/equi_join_two_mult_keys.sql
@@ -0,0 +1,3 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+SELECT * FROM plato.A JOIN plato.B ON A.key == B.key AND A.subkey == B.subkey;
diff --git a/yql/essentials/tests/sql/suites/join/filter_joined-off.cfg b/yql/essentials/tests/sql/suites/join/filter_joined-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/filter_joined-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/filter_joined.cfg b/yql/essentials/tests/sql/suites/join/filter_joined.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/filter_joined.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/filter_joined.sql b/yql/essentials/tests/sql/suites/join/filter_joined.sql
new file mode 100644
index 0000000000..2b75c56856
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/filter_joined.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+SELECT b.key
+FROM Input2 as a
+RIGHT JOIN Input3 as b ON a.key == b.key
+WHERE a.key IS NULL
+ORDER BY b.key;
diff --git a/yql/essentials/tests/sql/suites/join/flatten_columns1-off.cfg b/yql/essentials/tests/sql/suites/join/flatten_columns1-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/flatten_columns1-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/flatten_columns1.cfg b/yql/essentials/tests/sql/suites/join/flatten_columns1.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/flatten_columns1.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/flatten_columns1.sql b/yql/essentials/tests/sql/suites/join/flatten_columns1.sql
new file mode 100644
index 0000000000..ada242dc80
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/flatten_columns1.sql
@@ -0,0 +1,14 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+SELECT * FROM (
+SELECT
+ AsStruct(key as key, subkey as subkey),
+ AsStruct("value: " || value as value)
+FROM Input1
+) as a
+FLATTEN COLUMNS
+JOIN Input2
+USING (key)
+ORDER BY Input2.key;
diff --git a/yql/essentials/tests/sql/suites/join/flatten_columns2-off.cfg b/yql/essentials/tests/sql/suites/join/flatten_columns2-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/flatten_columns2-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/flatten_columns2.cfg b/yql/essentials/tests/sql/suites/join/flatten_columns2.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/flatten_columns2.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/flatten_columns2.sql b/yql/essentials/tests/sql/suites/join/flatten_columns2.sql
new file mode 100644
index 0000000000..9ae2d879e4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/flatten_columns2.sql
@@ -0,0 +1,20 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+SELECT * FROM (
+SELECT
+ AsStruct(key as key, subkey as subkey),
+ AsStruct("value1: " || value as value)
+FROM Input1
+) as a
+FLATTEN COLUMNS
+JOIN (
+SELECT
+ AsStruct(key as key, subkey as subkey),
+ AsStruct("value2: " || value as value)
+FROM Input2
+) as b
+FLATTEN COLUMNS
+USING (key)
+ORDER BY a.key;
diff --git a/yql/essentials/tests/sql/suites/join/force_merge_join.sql b/yql/essentials/tests/sql/suites/join/force_merge_join.sql
new file mode 100644
index 0000000000..80aaedfb0a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/force_merge_join.sql
@@ -0,0 +1,9 @@
+USE plato;
+
+PRAGMA yt.JoinMergeForce = "1";
+pragma yt.JoinMergeTablesLimit="10";
+
+SELECT a.key as key1
+ FROM (SELECT * FROM plato.Input1 WHERE subkey != "bar") AS a
+ JOIN (SELECT * FROM plato.Input1 WHERE subkey != "foo") AS b ON a.key = b.key
+WHERE a.key != "1" OR b.key != "2";
diff --git a/yql/essentials/tests/sql/suites/join/from_in_front_join-off.cfg b/yql/essentials/tests/sql/suites/join/from_in_front_join-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/from_in_front_join-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/from_in_front_join.cfg b/yql/essentials/tests/sql/suites/join/from_in_front_join.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/from_in_front_join.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/from_in_front_join.sql b/yql/essentials/tests/sql/suites/join/from_in_front_join.sql
new file mode 100644
index 0000000000..2e1c8489de
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/from_in_front_join.sql
@@ -0,0 +1,3 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+from plato.Input1 inner join plato.Input3 using (key) select Input1.key, Input1.subkey, Input3.value; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/full_equal_not_null-off.cfg b/yql/essentials/tests/sql/suites/join/full_equal_not_null-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_equal_not_null-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/full_equal_not_null.cfg b/yql/essentials/tests/sql/suites/join/full_equal_not_null.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_equal_not_null.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/full_equal_not_null.sql b/yql/essentials/tests/sql/suites/join/full_equal_not_null.sql
new file mode 100644
index 0000000000..39de950979
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_equal_not_null.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select count(*) from (select cast(subkey as int) as v1, subkey from plato.Input1) as a full join (select cast(subkey as int) as v2, subkey from plato.Input1) as b on a.v1 = b.v2; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/full_equal_null-off.cfg b/yql/essentials/tests/sql/suites/join/full_equal_null-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_equal_null-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/full_equal_null.cfg b/yql/essentials/tests/sql/suites/join/full_equal_null.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_equal_null.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/full_equal_null.sql b/yql/essentials/tests/sql/suites/join/full_equal_null.sql
new file mode 100644
index 0000000000..ed1d8077cd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_equal_null.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select count(*) from (select cast(value as int) as v1, subkey from plato.Input1) as a full join (select cast(value as int) as v2, subkey from plato.Input1) as b on a.v1 = b.v2;
diff --git a/yql/essentials/tests/sql/suites/join/full_join-off.cfg b/yql/essentials/tests/sql/suites/join/full_join-off.cfg
new file mode 100644
index 0000000000..483714d007
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_join-off.cfg
@@ -0,0 +1,4 @@
+in test_join_1 test_join_1.txt
+in test_join_2 test_join_2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/full_join.cfg b/yql/essentials/tests/sql/suites/join/full_join.cfg
new file mode 100644
index 0000000000..ec3dcd7a74
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_join.cfg
@@ -0,0 +1,2 @@
+in test_join_1 test_join_1.txt
+in test_join_2 test_join_2.txt
diff --git a/yql/essentials/tests/sql/suites/join/full_join.sql b/yql/essentials/tests/sql/suites/join/full_join.sql
new file mode 100644
index 0000000000..4f1e839311
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_join.sql
@@ -0,0 +1,19 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+SELECT
+ a.key AS a_key,
+ b.key AS b_key,
+ a.value AS a_value,
+ b.value AS b_value
+FROM
+ `test_join_1` AS a
+FULL JOIN
+ `test_join_2` AS b
+ON
+ a.key == b.subkey
+ORDER BY
+ b_key, a_key
+LIMIT 25
+;
+
diff --git a/yql/essentials/tests/sql/suites/join/full_trivial-off.cfg b/yql/essentials/tests/sql/suites/join/full_trivial-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_trivial-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/full_trivial.cfg b/yql/essentials/tests/sql/suites/join/full_trivial.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_trivial.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/full_trivial.sql b/yql/essentials/tests/sql/suites/join/full_trivial.sql
new file mode 100644
index 0000000000..bb6fa176f7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_trivial.sql
@@ -0,0 +1,5 @@
+PRAGMA DisableSimpleColumns;
+select coalesce(Input1.key, "_null") as a, coalesce(Input1.subkey, "_null") as b, coalesce(Input3.value, "_null") as c
+from plato.Input1
+full join plato.Input3 using (key)
+order by a, b, c; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/full_trivial_udf_call-off.cfg b/yql/essentials/tests/sql/suites/join/full_trivial_udf_call-off.cfg
new file mode 100644
index 0000000000..2c2cb4cb8d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_trivial_udf_call-off.cfg
@@ -0,0 +1,7 @@
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+udf simple_udf
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/full_trivial_udf_call.cfg b/yql/essentials/tests/sql/suites/join/full_trivial_udf_call.cfg
new file mode 100644
index 0000000000..4d2ebba571
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_trivial_udf_call.cfg
@@ -0,0 +1,5 @@
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+udf simple_udf
diff --git a/yql/essentials/tests/sql/suites/join/full_trivial_udf_call.sql b/yql/essentials/tests/sql/suites/join/full_trivial_udf_call.sql
new file mode 100644
index 0000000000..d2acbd2b88
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/full_trivial_udf_call.sql
@@ -0,0 +1,6 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+select Input1.key, Input1.subkey, SimpleUdf::Concat(coalesce(Input1.value, ""), coalesce(Input3.value, "")) as value
+from plato.Input1
+full join plato.Input3 using (key)
+order by Input1.key, Input1.subkey, value; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/gj_countries1.txt b/yql/essentials/tests/sql/suites/join/gj_countries1.txt
new file mode 100644
index 0000000000..b1bea9c8e2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/gj_countries1.txt
@@ -0,0 +1,25 @@
+{"country_id"="0"; "country_name"="0"};
+{"country_id"="1"; "country_name"="1"};
+{"country_id"="2"; "country_name"="2"};
+{"country_id"="3"; "country_name"="3"};
+{"country_id"="4"; "country_name"="4"};
+{"country_id"="5"; "country_name"="5"};
+{"country_id"="6"; "country_name"="6"};
+{"country_id"="7"; "country_name"="7"};
+{"country_id"="8"; "country_name"="8"};
+{"country_id"="9"; "country_name"="9"};
+{"country_id"="10"; "country_name"="10"};
+{"country_id"="11"; "country_name"="11"};
+{"country_id"="12"; "country_name"="12"};
+{"country_id"="13"; "country_name"="13"};
+{"country_id"="14"; "country_name"="14"};
+{"country_id"="15"; "country_name"="15"};
+{"country_id"="16"; "country_name"="16"};
+{"country_id"="17"; "country_name"="17"};
+{"country_id"="18"; "country_name"="18"};
+{"country_id"="19"; "country_name"="19"};
+{"country_id"="20"; "country_name"="20"};
+{"country_id"="21"; "country_name"="21"};
+{"country_id"="22"; "country_name"="22"};
+{"country_id"="23"; "country_name"="23"};
+{"country_id"="24"; "country_name"="24"};
diff --git a/yql/essentials/tests/sql/suites/join/gj_countries1.txt.attr b/yql/essentials/tests/sql/suites/join/gj_countries1.txt.attr
new file mode 100644
index 0000000000..f9b5e0e010
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/gj_countries1.txt.attr
@@ -0,0 +1,18 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "country_id";
+ "required" = %true;
+ "type" = "string"
+ };
+ {
+ "name" = "country_name";
+ "required" = %true;
+ "type" = "string"
+ };
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/gj_customers1.txt b/yql/essentials/tests/sql/suites/join/gj_customers1.txt
new file mode 100644
index 0000000000..95cade958b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/gj_customers1.txt
@@ -0,0 +1,100 @@
+{"customer_id"="0"; "country_id"="0"};
+{"customer_id"="1"; "country_id"="0"};
+{"customer_id"="2"; "country_id"="21"};
+{"customer_id"="3"; "country_id"="24"};
+{"customer_id"="4"; "country_id"="8"};
+{"customer_id"="5"; "country_id"="12"};
+{"customer_id"="6"; "country_id"="0"};
+{"customer_id"="7"; "country_id"="15"};
+{"customer_id"="8"; "country_id"="14"};
+{"customer_id"="9"; "country_id"="5"};
+{"customer_id"="10"; "country_id"="3"};
+{"customer_id"="11"; "country_id"="19"};
+{"customer_id"="12"; "country_id"="12"};
+{"customer_id"="13"; "country_id"="24"};
+{"customer_id"="14"; "country_id"="4"};
+{"customer_id"="15"; "country_id"="11"};
+{"customer_id"="16"; "country_id"="3"};
+{"customer_id"="17"; "country_id"="4"};
+{"customer_id"="18"; "country_id"="5"};
+{"customer_id"="19"; "country_id"="2"};
+{"customer_id"="20"; "country_id"="16"};
+{"customer_id"="21"; "country_id"="2"};
+{"customer_id"="22"; "country_id"="19"};
+{"customer_id"="23"; "country_id"="11"};
+{"customer_id"="24"; "country_id"="8"};
+{"customer_id"="25"; "country_id"="19"};
+{"customer_id"="26"; "country_id"="23"};
+{"customer_id"="27"; "country_id"="10"};
+{"customer_id"="28"; "country_id"="15"};
+{"customer_id"="29"; "country_id"="7"};
+{"customer_id"="30"; "country_id"="18"};
+{"customer_id"="31"; "country_id"="16"};
+{"customer_id"="32"; "country_id"="8"};
+{"customer_id"="33"; "country_id"="14"};
+{"customer_id"="34"; "country_id"="16"};
+{"customer_id"="35"; "country_id"="17"};
+{"customer_id"="36"; "country_id"="2"};
+{"customer_id"="37"; "country_id"="16"};
+{"customer_id"="38"; "country_id"="7"};
+{"customer_id"="39"; "country_id"="16"};
+{"customer_id"="40"; "country_id"="22"};
+{"customer_id"="41"; "country_id"="11"};
+{"customer_id"="42"; "country_id"="11"};
+{"customer_id"="43"; "country_id"="9"};
+{"customer_id"="44"; "country_id"="10"};
+{"customer_id"="45"; "country_id"="16"};
+{"customer_id"="46"; "country_id"="21"};
+{"customer_id"="47"; "country_id"="13"};
+{"customer_id"="48"; "country_id"="20"};
+{"customer_id"="49"; "country_id"="2"};
+{"customer_id"="50"; "country_id"="16"};
+{"customer_id"="51"; "country_id"="12"};
+{"customer_id"="52"; "country_id"="4"};
+{"customer_id"="53"; "country_id"="10"};
+{"customer_id"="54"; "country_id"="23"};
+{"customer_id"="55"; "country_id"="12"};
+{"customer_id"="56"; "country_id"="5"};
+{"customer_id"="57"; "country_id"="22"};
+{"customer_id"="58"; "country_id"="23"};
+{"customer_id"="59"; "country_id"="21"};
+{"customer_id"="60"; "country_id"="4"};
+{"customer_id"="61"; "country_id"="17"};
+{"customer_id"="62"; "country_id"="12"};
+{"customer_id"="63"; "country_id"="13"};
+{"customer_id"="64"; "country_id"="6"};
+{"customer_id"="65"; "country_id"="3"};
+{"customer_id"="66"; "country_id"="5"};
+{"customer_id"="67"; "country_id"="8"};
+{"customer_id"="68"; "country_id"="20"};
+{"customer_id"="69"; "country_id"="12"};
+{"customer_id"="70"; "country_id"="0"};
+{"customer_id"="71"; "country_id"="17"};
+{"customer_id"="72"; "country_id"="23"};
+{"customer_id"="73"; "country_id"="12"};
+{"customer_id"="74"; "country_id"="2"};
+{"customer_id"="75"; "country_id"="9"};
+{"customer_id"="76"; "country_id"="3"};
+{"customer_id"="77"; "country_id"="24"};
+{"customer_id"="78"; "country_id"="23"};
+{"customer_id"="79"; "country_id"="23"};
+{"customer_id"="80"; "country_id"="1"};
+{"customer_id"="81"; "country_id"="14"};
+{"customer_id"="82"; "country_id"="11"};
+{"customer_id"="83"; "country_id"="5"};
+{"customer_id"="84"; "country_id"="0"};
+{"customer_id"="85"; "country_id"="9"};
+{"customer_id"="86"; "country_id"="18"};
+{"customer_id"="87"; "country_id"="5"};
+{"customer_id"="88"; "country_id"="6"};
+{"customer_id"="89"; "country_id"="17"};
+{"customer_id"="90"; "country_id"="1"};
+{"customer_id"="91"; "country_id"="10"};
+{"customer_id"="92"; "country_id"="9"};
+{"customer_id"="93"; "country_id"="14"};
+{"customer_id"="94"; "country_id"="23"};
+{"customer_id"="95"; "country_id"="16"};
+{"customer_id"="96"; "country_id"="18"};
+{"customer_id"="97"; "country_id"="3"};
+{"customer_id"="98"; "country_id"="0"};
+{"customer_id"="99"; "country_id"="13"};
diff --git a/yql/essentials/tests/sql/suites/join/gj_customers1.txt.attr b/yql/essentials/tests/sql/suites/join/gj_customers1.txt.attr
new file mode 100644
index 0000000000..34f229c4fa
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/gj_customers1.txt.attr
@@ -0,0 +1,18 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "customer_id";
+ "required" = %true;
+ "type" = "string"
+ };
+ {
+ "name" = "country_id";
+ "required" = %true;
+ "type" = "string"
+ };
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/grace_join1-grace.cfg b/yql/essentials/tests/sql/suites/join/grace_join1-grace.cfg
new file mode 100644
index 0000000000..11f6f5b18b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/grace_join1-grace.cfg
@@ -0,0 +1,4 @@
+in customers1 gj_customers1.txt
+in countries1 gj_countries1.txt
+providers dq
+pragma Dq.HashJoinMode='grace';
diff --git a/yql/essentials/tests/sql/suites/join/grace_join1-map.cfg b/yql/essentials/tests/sql/suites/join/grace_join1-map.cfg
new file mode 100644
index 0000000000..f787c0665b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/grace_join1-map.cfg
@@ -0,0 +1,4 @@
+in customers1 gj_customers1.txt
+in countries1 gj_countries1.txt
+providers dq
+pragma Dq.HashJoinMode='map';
diff --git a/yql/essentials/tests/sql/suites/join/grace_join1-off.cfg b/yql/essentials/tests/sql/suites/join/grace_join1-off.cfg
new file mode 100644
index 0000000000..5c48d49545
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/grace_join1-off.cfg
@@ -0,0 +1,5 @@
+in customers1 gj_customers1.txt
+in countries1 gj_countries1.txt
+providers dq
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/grace_join1.cfg b/yql/essentials/tests/sql/suites/join/grace_join1.cfg
new file mode 100644
index 0000000000..a64c260418
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/grace_join1.cfg
@@ -0,0 +1,3 @@
+in customers1 gj_customers1.txt
+in countries1 gj_countries1.txt
+providers dq
diff --git a/yql/essentials/tests/sql/suites/join/grace_join1.sql b/yql/essentials/tests/sql/suites/join/grace_join1.sql
new file mode 100644
index 0000000000..42d4fdf492
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/grace_join1.sql
@@ -0,0 +1,11 @@
+USE plato;
+pragma DisableSimpleColumns;
+
+select
+cust.customer_id, cntr.country_name
+from
+plato.countries1 as cntr
+join
+plato.customers1 as cust
+on cntr.country_id = cust.country_id
+where cntr.country_id = "11";
diff --git a/yql/essentials/tests/sql/suites/join/grace_join2.cfg b/yql/essentials/tests/sql/suites/join/grace_join2.cfg
new file mode 100644
index 0000000000..7fa7de708f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/grace_join2.cfg
@@ -0,0 +1,3 @@
+in customers1 gj_customers1.txt
+providers dq
+pragma Dq.HashJoinMode='graceandself';
diff --git a/yql/essentials/tests/sql/suites/join/grace_join2.sql b/yql/essentials/tests/sql/suites/join/grace_join2.sql
new file mode 100644
index 0000000000..1b10d992e3
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/grace_join2.sql
@@ -0,0 +1,10 @@
+USE plato;
+pragma DisableSimpleColumns;
+
+select
+c1.customer_id, c2.customer_id
+from
+plato.customers1 as c1
+join
+plato.customers1 as c2
+on c1.country_id = c2.country_id order by c1.customer_id, c2.customer_id;
diff --git a/yql/essentials/tests/sql/suites/join/group_compact_by.cfg b/yql/essentials/tests/sql/suites/join/group_compact_by.cfg
new file mode 100644
index 0000000000..7697efeaa2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/group_compact_by.cfg
@@ -0,0 +1 @@
+in Input input8.txt
diff --git a/yql/essentials/tests/sql/suites/join/group_compact_by.sql b/yql/essentials/tests/sql/suites/join/group_compact_by.sql
new file mode 100644
index 0000000000..d5f33612df
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/group_compact_by.sql
@@ -0,0 +1,14 @@
+USE plato;
+
+PRAGMA yt.JoinMergeForce = "1";
+pragma yt.JoinMergeTablesLimit="10";
+
+SELECT key1, subkey1
+FROM
+ (
+ SELECT a.key as key1, a.subkey as subkey1
+ FROM (SELECT * FROM Input WHERE subkey != "bar") AS a
+ JOIN (SELECT * FROM Input WHERE subkey != "foo") AS b
+ ON a.key = b.key AND a.subkey = b.subkey
+ )
+GROUP COMPACT BY key1, subkey1;
diff --git a/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs-off.cfg b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs.cfg b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs.sql b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs.sql
new file mode 100644
index 0000000000..ec4ad06056
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_structs.sql
@@ -0,0 +1,23 @@
+/* syntax version 1 */
+$l = [
+ <|Key:<|a:1, b:2, c:null|>, Lhs:"1,2,#"|>,
+ <|Key:<|a:2, b:3, c:null|>, Lhs:"4,5,#"|>,
+];
+
+$r = [
+ <|Key:<|a:1, b:2, c:3|>, Rhs:"1,2,3"|>,
+ <|Key:<|a:4, b:5, c:6|>, Rhs:"4,5,6"|>,
+];
+
+select Lhs, Rhs from AS_TABLE($l) as l left join AS_TABLE($r) as r using(Key);
+select Lhs from AS_TABLE($l) as l left semi join AS_TABLE($r) as r using(Key);
+select Lhs from AS_TABLE($l) as l left only join AS_TABLE($r) as r using(Key);
+
+select Rhs, Lhs from AS_TABLE($l) as l right join AS_TABLE($r) as r using(Key);
+select Rhs from AS_TABLE($l) as l right semi join AS_TABLE($r) as r using(Key);
+select Rhs from AS_TABLE($l) as l right only join AS_TABLE($r) as r using(Key);
+
+select Lhs, Rhs from AS_TABLE($l) as l inner join AS_TABLE($r) as r using(Key);
+select Lhs, Rhs from AS_TABLE($l) as l full join AS_TABLE($r) as r using(Key);
+select Lhs, Rhs from AS_TABLE($l) as l exclusion join AS_TABLE($r) as r using(Key);
+
diff --git a/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples-off.cfg b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples.cfg b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples.sql b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples.sql
new file mode 100644
index 0000000000..18a95e6c49
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_by_uncomparable_tuples.sql
@@ -0,0 +1,22 @@
+/* syntax version 1 */
+$l = AsList(
+ AsStruct(AsTuple(1,2,3) as Key, "1,2,3" as Lhs),
+ AsStruct(AsTuple(1,2,4) as Key, "1,2,4" as Lhs)
+);
+
+$r = AsList(
+ AsStruct(AsTuple(1,2) as Key, "1,2" as Rhs),
+ AsStruct(AsTuple(2,3) as Key, "2,3" as Rhs)
+);
+
+select Lhs, Rhs from AS_TABLE($l) as l left join AS_TABLE($r) as r using(Key);
+select Lhs from AS_TABLE($l) as l left semi join AS_TABLE($r) as r using(Key);
+select Lhs from AS_TABLE($l) as l left only join AS_TABLE($r) as r using(Key);
+
+select Rhs, Lhs from AS_TABLE($l) as l right join AS_TABLE($r) as r using(Key);
+select Rhs from AS_TABLE($l) as l right semi join AS_TABLE($r) as r using(Key);
+select Rhs from AS_TABLE($l) as l right only join AS_TABLE($r) as r using(Key);
+
+select Lhs, Rhs from AS_TABLE($l) as l inner join AS_TABLE($r) as r using(Key);
+select Lhs, Rhs from AS_TABLE($l) as l full join AS_TABLE($r) as r using(Key);
+select Lhs, Rhs from AS_TABLE($l) as l exclusion join AS_TABLE($r) as r using(Key);
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_null_key-off.cfg b/yql/essentials/tests/sql/suites/join/inmem_with_null_key-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_null_key-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_null_key.cfg b/yql/essentials/tests/sql/suites/join/inmem_with_null_key.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_null_key.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_null_key.sql b/yql/essentials/tests/sql/suites/join/inmem_with_null_key.sql
new file mode 100644
index 0000000000..2e19fd2d6e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_null_key.sql
@@ -0,0 +1,9 @@
+/* postgres can not */
+
+$a = (select null as a, 1 as b);
+$b = (select null as a, 1 as b);
+
+select a.*
+from $a as a
+left only join $b as b
+using(a);
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_set_key-off.cfg b/yql/essentials/tests/sql/suites/join/inmem_with_set_key-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_set_key-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_set_key.cfg b/yql/essentials/tests/sql/suites/join/inmem_with_set_key.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_set_key.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_set_key.sql b/yql/essentials/tests/sql/suites/join/inmem_with_set_key.sql
new file mode 100644
index 0000000000..8ac235b3df
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_set_key.sql
@@ -0,0 +1,21 @@
+/* syntax version 1 */
+PRAGMA DisableSimpleColumns;
+
+$one = [<|'a':{"1"}, 'b':2|>, <|'a':{"2"}, 'b':3|>, <|'a':{"3"}, 'b':4|>, <|'a':{"1"}, 'b':8|>];
+$two = [<|'c':{Just("1")}, 'd':2|>, <|'c':{}, 'd':3|>, <|'c':null, 'd':4|>, <|'c':{Just("1")}, 'd':9|>];
+$foo = [<|'e':{"1"u}, 'f':-2|>, <|'e':{"1"u,"2"u}, 'f':-3|>, <|'e':null, 'f':-4|>, <|'e':{"1"u}, 'f':-9|>];
+$bar = [<|'g':{Just("1"u)}, 'h':1.|>, <|'g':{}, 'h':2.2|>, <|'g':{Just("1"u),Just("2"u)}, 'h':3.3|>, <|'g':{Just("1"u)}, 'h':4.4|>];
+
+SELECT
+ListSort(DictItems(bar.g)) as bar_g, bar.h,
+ListSort(DictItems(foo.e)) as foo_e, foo.f,
+ListSort(DictItems(one.a)) as one_a, one.b,
+ListSort(DictItems(two.c)) as two_c, two.d
+FROM AS_TABLE($one) AS one
+INNER JOIN AS_TABLE($two) AS two
+ON one.a == two.c
+LEFT JOIN AS_TABLE($foo) AS foo
+ON foo.e == two.c
+FULL JOIN AS_TABLE($bar) AS bar
+ON bar.g == one.a
+ORDER BY bar_g, bar.h, foo_e, foo.f, one_a, one.b, two_c, two.d
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any-off.cfg b/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any.cfg b/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any.sql b/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any.sql
new file mode 100644
index 0000000000..fc7d7be5c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inmem_with_set_key_any.sql
@@ -0,0 +1,21 @@
+/* syntax version 1 */
+PRAGMA DisableSimpleColumns;
+
+$one = [<|'a':{"1"}, 'b':2|>, <|'a':{"2"}, 'b':3|>, <|'a':{"3"}, 'b':4|>, <|'a':{"1"}, 'b':8|>];
+$two = [<|'c':{Just("1")}, 'd':2|>, <|'c':{}, 'd':3|>, <|'c':null, 'd':4|>, <|'c':{Just("1")}, 'd':9|>];
+$foo = [<|'e':{"1"u}, 'f':-2|>, <|'e':{"1"u,"2"u}, 'f':-3|>, <|'e':null, 'f':-4|>, <|'e':{"1"u}, 'f':-9|>];
+$bar = [<|'g':{Just("1"u)}, 'h':1.|>, <|'g':{}, 'h':2.2|>, <|'g':{Just("1"u),Just("2"u)}, 'h':3.3|>, <|'g':{Just("1"u)}, 'h':4.4|>];
+
+SELECT
+ListSort(DictItems(bar.g)) as bar_g, bar.h,
+ListSort(DictItems(foo.e)) as foo_e, foo.f,
+ListSort(DictItems(one.a)) as one_a, one.b,
+ListSort(DictItems(two.c)) as two_c, two.d
+FROM ANY AS_TABLE($one) AS one
+INNER JOIN ANY AS_TABLE($two) AS two
+ON one.a == two.c
+LEFT JOIN ANY AS_TABLE($foo) AS foo
+ON foo.e == two.c
+FULL JOIN ANY AS_TABLE($bar) AS bar
+ON bar.g == one.a
+ORDER BY bar_g, bar.h, foo_e, foo.f, one_a, one.b, two_c, two.d
diff --git a/yql/essentials/tests/sql/suites/join/inner_all-off.cfg b/yql/essentials/tests/sql/suites/join/inner_all-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_all-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_all.cfg b/yql/essentials/tests/sql/suites/join/inner_all.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_all.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_all.sql b/yql/essentials/tests/sql/suites/join/inner_all.sql
new file mode 100644
index 0000000000..22803ca6b6
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_all.sql
@@ -0,0 +1,6 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+SELECT *
+FROM Input2 AS a
+JOIN Input3 AS b
+ON a.value == b.value;
diff --git a/yql/essentials/tests/sql/suites/join/inner_all_right-off.cfg b/yql/essentials/tests/sql/suites/join/inner_all_right-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_all_right-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_all_right.cfg b/yql/essentials/tests/sql/suites/join/inner_all_right.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_all_right.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_all_right.sql b/yql/essentials/tests/sql/suites/join/inner_all_right.sql
new file mode 100644
index 0000000000..ec84b11ad4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_all_right.sql
@@ -0,0 +1,6 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+SELECT b.*
+FROM Input2 AS a
+JOIN Input3 AS b
+ON a.value == b.value;
diff --git a/yql/essentials/tests/sql/suites/join/inner_grouped-off.cfg b/yql/essentials/tests/sql/suites/join/inner_grouped-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_grouped-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_grouped.cfg b/yql/essentials/tests/sql/suites/join/inner_grouped.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_grouped.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_grouped.sql b/yql/essentials/tests/sql/suites/join/inner_grouped.sql
new file mode 100644
index 0000000000..14d580b119
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_grouped.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select Input1.key as key, max(Input3.value) as value from plato.Input1 inner join plato.Input3 using (key) group by Input1.key order by key;
diff --git a/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr-off.cfg b/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr.cfg b/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr.sql b/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr.sql
new file mode 100644
index 0000000000..97f05fef2d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_grouped_by_expr.sql
@@ -0,0 +1,3 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+select keyz, max(Input3.value) as value from plato.Input1 inner join plato.Input3 using (key) group by Input1.key as keyz order by keyz;
diff --git a/yql/essentials/tests/sql/suites/join/inner_on_key_only-off.cfg b/yql/essentials/tests/sql/suites/join/inner_on_key_only-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_on_key_only-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_on_key_only.cfg b/yql/essentials/tests/sql/suites/join/inner_on_key_only.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_on_key_only.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_on_key_only.sql b/yql/essentials/tests/sql/suites/join/inner_on_key_only.sql
new file mode 100644
index 0000000000..e2d7e57d63
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_on_key_only.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select Input1.key, Input1.subkey, Input3.value from plato.Input1 inner join plato.Input3 on Input1.key = Input3.key; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/inner_table_and_view.cfg b/yql/essentials/tests/sql/suites/join/inner_table_and_view.cfg
new file mode 100644
index 0000000000..8b7633b301
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_table_and_view.cfg
@@ -0,0 +1 @@
+in Input view_input.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_trivial-off.cfg b/yql/essentials/tests/sql/suites/join/inner_trivial-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_trivial-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_trivial.cfg b/yql/essentials/tests/sql/suites/join/inner_trivial.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_trivial.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_trivial.sql b/yql/essentials/tests/sql/suites/join/inner_trivial.sql
new file mode 100644
index 0000000000..19db34045c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_trivial.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select Input1.key, Input1.subkey, Input3.value from plato.Input1 inner join plato.Input3 using (key); \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat-off.cfg b/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat.cfg b/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat.sql b/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat.sql
new file mode 100644
index 0000000000..aa317b9784
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_trivial_from_concat.sql
@@ -0,0 +1,3 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+select A.key, A.subkey, B.value from plato.concat(Input1, Input2) as A inner join plato.Input3 as B using (key); \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/inner_with_order-off.cfg b/yql/essentials/tests/sql/suites/join/inner_with_order-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_with_order-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_with_order.cfg b/yql/essentials/tests/sql/suites/join/inner_with_order.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_with_order.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_with_order.sql b/yql/essentials/tests/sql/suites/join/inner_with_order.sql
new file mode 100644
index 0000000000..471fb485ec
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_with_order.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select Input1.key as key, Input1.subkey, Input3.value from plato.Input1 inner join plato.Input3 using (key) order by key desc; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/inner_with_select-off.cfg b/yql/essentials/tests/sql/suites/join/inner_with_select-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_with_select-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/inner_with_select.cfg b/yql/essentials/tests/sql/suites/join/inner_with_select.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_with_select.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/inner_with_select.sql b/yql/essentials/tests/sql/suites/join/inner_with_select.sql
new file mode 100644
index 0000000000..b1e0c35edd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/inner_with_select.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+select
+ Input1.key as key,
+ Input1.subkey as subkey,
+ selected.value as value
+from plato.Input1
+inner join (select key, value || value as value from plato.Input3) as selected
+ using (key)
+order by key desc; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/input.txt b/yql/essentials/tests/sql/suites/join/input.txt
new file mode 100644
index 0000000000..96d1fdd0ab
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input.txt
@@ -0,0 +1,3 @@
+{"key"="foo";"subkey"="bar";"value"="wat"};
+{"key"="bar";"subkey"="wat";"value"="wtf"};
+{"key"="wtf";"subkey"="foo";"value"="bar"};
diff --git a/yql/essentials/tests/sql/suites/join/input1.txt b/yql/essentials/tests/sql/suites/join/input1.txt
new file mode 100644
index 0000000000..f53757c309
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input1.txt
@@ -0,0 +1,4 @@
+{"key"="075";"subkey"="1";"value"="abc"};
+{"key"="800";"subkey"="1";"value"="ddd"};
+{"key"="020";"subkey"="1";"value"="q"};
+{"key"="150";"subkey"="1";"value"="qzz"};
diff --git a/yql/essentials/tests/sql/suites/join/input2.txt b/yql/essentials/tests/sql/suites/join/input2.txt
new file mode 100644
index 0000000000..07af3b4647
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input2.txt
@@ -0,0 +1,4 @@
+{"key"="075";"subkey"="2";"value"="abc"};
+{"key"="800";"subkey"="2";"value"="ddd"};
+{"key"="020";"subkey"="2";"value"="q"};
+{"key"="150";"subkey"="2";"value"="qzz"};
diff --git a/yql/essentials/tests/sql/suites/join/input3.txt b/yql/essentials/tests/sql/suites/join/input3.txt
new file mode 100644
index 0000000000..1dc1bcc60b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input3.txt
@@ -0,0 +1,4 @@
+{"key"="075";"subkey"="3";"value"="abd"};
+{"key"="800";"subkey"="3";"value"="ddd"};
+{"key"="021";"subkey"="3";"value"="q"};
+{"key"="151";"subkey"="3";"value"="qzz"};
diff --git a/yql/essentials/tests/sql/suites/join/input4.txt b/yql/essentials/tests/sql/suites/join/input4.txt
new file mode 100644
index 0000000000..a3185b8d9a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input4.txt
@@ -0,0 +1,4 @@
+{"key"="075";"subkey"="3";"value"="abd"};
+{"key"="800";"subkey"="2";"value"="ddd"};
+{"key"="021";"subkey"="2";"value"="q"};
+{"key"="151";"subkey"="2";"value"="qzz"};
diff --git a/yql/essentials/tests/sql/suites/join/input5.txt b/yql/essentials/tests/sql/suites/join/input5.txt
new file mode 100644
index 0000000000..e5f4a7ae33
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input5.txt
@@ -0,0 +1,4 @@
+{"key"="1";"subkey"="a";"value"="value1_1"};
+{"key"="INVALID";"subkey"="b";"value"="value1_2"};
+{"key"="3";"subkey"="c";"value"="value1_3"};
+{"key"="4";"subkey"="d";"value"="value1_4"};
diff --git a/yql/essentials/tests/sql/suites/join/input6.txt b/yql/essentials/tests/sql/suites/join/input6.txt
new file mode 100644
index 0000000000..ae3f3dd0d2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input6.txt
@@ -0,0 +1,4 @@
+{"key1"="1";"subkey1"="a";"key"="1";"subkey"="a";"value"="value1_1"};
+{"key1"="INVALID";"subkey1"="b";"key"="INVALID";"subkey"="b";"value"="value1_2"};
+{"key1"="3";"subkey1"="c";"key"="3";"subkey"="c";"value"="value1_3"};
+{"key1"="4";"subkey1"="d";"key"="4";"subkey"="d";"value"="value1_4"};
diff --git a/yql/essentials/tests/sql/suites/join/input6.txt.attr b/yql/essentials/tests/sql/suites/join/input6.txt.attr
new file mode 100644
index 0000000000..ad1624a955
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input6.txt.attr
@@ -0,0 +1,9 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key1";["DataType";"Utf8"]];
+ ["subkey1";["DataType";"Utf8"]];
+ ["key";["DataType";"Utf8"]];
+ ["subkey";["DataType";"Utf8"]];
+ ["value";["DataType";"Utf8"]]]
+ ];
+}}
diff --git a/yql/essentials/tests/sql/suites/join/input7.txt b/yql/essentials/tests/sql/suites/join/input7.txt
new file mode 100644
index 0000000000..5a8860b91d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input7.txt
@@ -0,0 +1,4 @@
+{"key"="075";"subkey"="2";"value"="abcaaa"};
+{"key"="800";"subkey"="2";"value"="dddaaa"};
+{"key"="020";"subkey"="2";"value"="qaaa"};
+{"key"="150";"subkey"="2";"value"="qzzaaa"};
diff --git a/yql/essentials/tests/sql/suites/join/input8.txt b/yql/essentials/tests/sql/suites/join/input8.txt
new file mode 100644
index 0000000000..2417d71bb3
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input8.txt
@@ -0,0 +1,4 @@
+{"key"="020";"subkey"="1";"value"="q"};
+{"key"="075";"subkey"="2";"value"="abc"};
+{"key"="150";"subkey"="3";"value"="qzz"};
+{"key"="800";"subkey"="4";"value"="ddd"};
diff --git a/yql/essentials/tests/sql/suites/join/input8.txt.attr b/yql/essentials/tests/sql/suites/join/input8.txt.attr
new file mode 100644
index 0000000000..7ec3f318dc
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input8.txt.attr
@@ -0,0 +1,13 @@
+{
+ "_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"String"]];
+ ["subkey";["DataType";"String"]];
+ ["value";["DataType";"String"]]]
+ ];
+ "SortDirections"=[1;1];
+ "SortedBy"=["key";"subkey"];
+ "SortedByTypes"=[["DataType";"String"];["DataType";"String"]];
+ "SortMembers"=["key";"subkey"];
+ }
+} \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/input9.txt b/yql/essentials/tests/sql/suites/join/input9.txt
new file mode 100644
index 0000000000..b214aab0d9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input9.txt
@@ -0,0 +1,10 @@
+{"key"="023";"subkey"="3";"value"="aaa"};
+{"key"="037";"subkey"="5";"value"="ddd"};
+{"key"="075";"subkey"="1";"value"="abc"};
+{"key"="150";"subkey"="1";"value"="aaa"};
+{"key"="150";"subkey"="3";"value"="iii"};
+{"key"="150";"subkey"="8";"value"="zzz"};
+{"key"="200";"subkey"="7";"value"="qqq"};
+{"key"="527";"subkey"="4";"value"="bbb"};
+{"key"="761";"subkey"="6";"value"="ccc"};
+{"key"="911";"subkey"="2";"value"="kkk"};
diff --git a/yql/essentials/tests/sql/suites/join/input9.txt.attr b/yql/essentials/tests/sql/suites/join/input9.txt.attr
new file mode 100644
index 0000000000..ed13e20223
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input9.txt.attr
@@ -0,0 +1,11 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"String"]];
+ ["subkey";["DataType";"String"]];
+ ["value";["DataType";"String"]]
+ ]];
+ "SortDirections"=[1;1;];
+ "SortedBy"=["key";"subkey";];
+ "SortedByTypes"=[["DataType";"String";];["DataType";"String";];];
+ "SortMembers"=["key";"subkey";];
+}}
diff --git a/yql/essentials/tests/sql/suites/join/input_intersect.txt b/yql/essentials/tests/sql/suites/join/input_intersect.txt
new file mode 100644
index 0000000000..42bcf2179e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input_intersect.txt
@@ -0,0 +1,14 @@
+{"key"="075";"subkey"="911";"value"="abc"};
+{"key"="911";"subkey"="1";"value"="kkk"};
+{"key"="023";"subkey"="527";"value"="aaa"};
+{"key"="527";"subkey"="023";"value"="bbb"};
+{"key"="037";"subkey"="075";"value"="ddd"};
+{"key"="761";"subkey"="911";"value"="ccc"};
+{"key"="200";"subkey"="075";"value"="qqq"};
+{"key"="150";"subkey"="075";"value"="zzz"};
+{"key"="023";"subkey"="911";"value"="vca"};
+{"key"="527";"subkey"="150";"value"="oef"};
+{"key"="037";"subkey"="761";"value"="vdf"};
+{"key"="761";"subkey"="037";"value"="aet"};
+{"key"="200";"subkey"="150";"value"="fdb"};
+{"key"="150";"subkey"="037";"value"="bfs"};
diff --git a/yql/essentials/tests/sql/suites/join/input_left.txt b/yql/essentials/tests/sql/suites/join/input_left.txt
new file mode 100644
index 0000000000..ac67f72937
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input_left.txt
@@ -0,0 +1,4 @@
+{k=1u;sk="100";v="abc"};
+{k=2u;sk="200";v="def"};
+{k=3u;sk="300";v="ghi"};
+{k=5u;sk="500";v="mno"};
diff --git a/yql/essentials/tests/sql/suites/join/input_left.txt.attr b/yql/essentials/tests/sql/suites/join/input_left.txt.attr
new file mode 100644
index 0000000000..58ca2c84ba
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input_left.txt.attr
@@ -0,0 +1,7 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["k";["DataType";"Uint64"]];
+ ["sk";["DataType";"Utf8"]];
+ ["v";["DataType";"Utf8"]];
+ ]];
+}}
diff --git a/yql/essentials/tests/sql/suites/join/input_right.txt b/yql/essentials/tests/sql/suites/join/input_right.txt
new file mode 100644
index 0000000000..7a094e2b95
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input_right.txt
@@ -0,0 +1,4 @@
+{k=1u;sk="100";v="ABC"};
+{k=3u;sk="300";v="GHI"};
+{k=4u;sk="400";v="JKL"};
+{k=5u;sk="500";v="MNO"};
diff --git a/yql/essentials/tests/sql/suites/join/input_right.txt.attr b/yql/essentials/tests/sql/suites/join/input_right.txt.attr
new file mode 100644
index 0000000000..58ca2c84ba
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input_right.txt.attr
@@ -0,0 +1,7 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["k";["DataType";"Uint64"]];
+ ["sk";["DataType";"Utf8"]];
+ ["v";["DataType";"Utf8"]];
+ ]];
+}}
diff --git a/yql/essentials/tests/sql/suites/join/input_tutorial_users.txt b/yql/essentials/tests/sql/suites/join/input_tutorial_users.txt
new file mode 100644
index 0000000000..4a18a0dd29
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/input_tutorial_users.txt
@@ -0,0 +1,12 @@
+{"key"="15";"subkey"="213";"value"="Anya"};
+{"key"="25";"subkey"="225";"value"="Petr"};
+{"key"="17";"subkey"="1";"value"="Masha"};
+{"key"="5";"subkey"="225";"value"="Alena"};
+{"key"="23";"subkey"="2";"value"="Irina"};
+{"key"="13";"subkey"="21";"value"="Inna"};
+{"key"="33";"subkey"="125";"value"="Ivan"};
+{"key"="45";"subkey"="225";"value"="Asya"};
+{"key"="27";"subkey"="125";"value"="German"};
+{"key"="41";"subkey"="225";"value"="Olya"};
+{"key"="35";"subkey"="2";"value"="Slava"};
+{"key"="56";"subkey"="2";"value"="Elena"};
diff --git a/yql/essentials/tests/sql/suites/join/join_and_distinct_key-off.cfg b/yql/essentials/tests/sql/suites/join/join_and_distinct_key-off.cfg
new file mode 100644
index 0000000000..76a2a2b6a4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_and_distinct_key-off.cfg
@@ -0,0 +1,3 @@
+in Input input_intersect.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_and_distinct_key.cfg b/yql/essentials/tests/sql/suites/join/join_and_distinct_key.cfg
new file mode 100644
index 0000000000..3df7813790
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_and_distinct_key.cfg
@@ -0,0 +1 @@
+in Input input_intersect.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_and_distinct_key.sql b/yql/essentials/tests/sql/suites/join/join_and_distinct_key.sql
new file mode 100644
index 0000000000..08037b8f7d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_and_distinct_key.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+SELECT
+ count(i1.key) as count,
+ count(distinct i1.key) as uniq_count
+FROM plato.Input as i1 JOIN plato.Input AS i2 on cast(i1.key as uint32) / 100 == cast(i2.subkey as uint32) / 100
+;
diff --git a/yql/essentials/tests/sql/suites/join/join_and_distinct_key_without_correlation.sqlx b/yql/essentials/tests/sql/suites/join/join_and_distinct_key_without_correlation.sqlx
new file mode 100644
index 0000000000..1a8713cd30
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_and_distinct_key_without_correlation.sqlx
@@ -0,0 +1,6 @@
+use plato;
+
+SELECT
+ count(distinct key) as uniq_count -- distinct qualifier required correlation name
+FROM Input as i1 JOIN Input AS i2 on cast(i1.key as uint32) / 100 == cast(i2.subkey as uint32) / 100
+;
diff --git a/yql/essentials/tests/sql/suites/join/join_cbo_3_tables.cfg b/yql/essentials/tests/sql/suites/join/join_cbo_3_tables.cfg
new file mode 100644
index 0000000000..6978b80cd9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_cbo_3_tables.cfg
@@ -0,0 +1,4 @@
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_cbo_3_tables.sql b/yql/essentials/tests/sql/suites/join/join_cbo_3_tables.sql
new file mode 100644
index 0000000000..12d53dd38f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_cbo_3_tables.sql
@@ -0,0 +1,10 @@
+use plato;
+
+pragma CostBasedOptimizer="pg";
+
+select i1.value, i2.value, i3.value, i4.value
+from Input1 as i1
+join Input2 as i2 on i1.key=i2.key
+join Input3 as i3 on i1.key=i3.key
+join Input4 as i4 on i1.key=i4.key
+order by i1.value, i2.value, i3.value, i4.value;
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_common_table-off.cfg b/yql/essentials/tests/sql/suites/join/join_comp_common_table-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_common_table-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_common_table.cfg b/yql/essentials/tests/sql/suites/join/join_comp_common_table.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_common_table.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_common_table.sql b/yql/essentials/tests/sql/suites/join/join_comp_common_table.sql
new file mode 100644
index 0000000000..770d18ecd5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_common_table.sql
@@ -0,0 +1,15 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+use plato;
+
+$i = (select AsList(key) as x from Input);
+$j = (select Just(AsList(key)) as y from Input);
+select a.x as zzz,b.y as fff from $i as a inner join $j as b on a.x = b.y order by zzz,fff;
+select a.x as zzz,b.y as fff from $i as a right join $j as b on a.x = b.y order by zzz,fff;
+select a.x as zzz,b.y as fff from $i as a left join $j as b on a.x = b.y order by zzz,fff;
+select a.x as zzz from $i as a left semi join $j as b on a.x = b.y order by zzz;
+select a.x as zzz from $i as a left only join $j as b on a.x = b.y order by zzz;
+select b.y as fff from $i as a right semi join $j as b on a.x = b.y order by fff;
+select b.y as fff from $i as a right only join $j as b on a.x = b.y order by fff;
+select a.x as zzz,b.y as fff from $i as a full join $j as b on a.x = b.y order by zzz,fff;
+select a.x as zzz,b.y as fff from $i as a exclusion join $j as b on a.x = b.y order by zzz,fff;
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_inmem-off.cfg b/yql/essentials/tests/sql/suites/join/join_comp_inmem-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_inmem-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_inmem.cfg b/yql/essentials/tests/sql/suites/join/join_comp_inmem.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_inmem.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_inmem.sql b/yql/essentials/tests/sql/suites/join/join_comp_inmem.sql
new file mode 100644
index 0000000000..6c0c174d7b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_inmem.sql
@@ -0,0 +1,13 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+$i = (select AsList("foo") as x);
+$j = (select Just(AsList("foo")) as y);
+select a.x as zzz,b.y as fff from $i as a inner join $j as b on a.x = b.y;
+select a.x as zzz,b.y as fff from $i as a right join $j as b on a.x = b.y;
+select a.x as zzz,b.y as fff from $i as a left join $j as b on a.x = b.y;
+select a.x as zzz from $i as a left semi join $j as b on a.x = b.y;
+select a.x as zzz from $i as a left only join $j as b on a.x = b.y;
+select b.y as fff from $i as a right semi join $j as b on a.x = b.y;
+select b.y as fff from $i as a right only join $j as b on a.x = b.y;
+select a.x as zzz,b.y as fff from $i as a full join $j as b on a.x = b.y;
+select a.x as zzz,b.y as fff from $i as a exclusion join $j as b on a.x = b.y;
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_map_table-off.cfg b/yql/essentials/tests/sql/suites/join/join_comp_map_table-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_map_table-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_map_table.cfg b/yql/essentials/tests/sql/suites/join/join_comp_map_table.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_map_table.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_comp_map_table.sql b/yql/essentials/tests/sql/suites/join/join_comp_map_table.sql
new file mode 100644
index 0000000000..4f64d5e685
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_comp_map_table.sql
@@ -0,0 +1,14 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+pragma yt.MapJoinLimit="1m";
+use plato;
+
+$i = (select AsList(key) as x from Input);
+$j = (select Just(AsList(key)) as y from Input);
+select a.x as zzz,b.y as fff from $i as a inner join $j as b on a.x = b.y;
+select a.x as zzz,b.y as fff from $i as a right join $j as b on a.x = b.y;
+select a.x as zzz,b.y as fff from $i as a left join $j as b on a.x = b.y;
+select a.x as zzz from $i as a left semi join $j as b on a.x = b.y;
+select a.x as zzz from $i as a left only join $j as b on a.x = b.y;
+select b.y as fff from $i as a right semi join $j as b on a.x = b.y;
+select b.y as fff from $i as a right only join $j as b on a.x = b.y;
diff --git a/yql/essentials/tests/sql/suites/join/join_key_cmp_udf-off.cfg b/yql/essentials/tests/sql/suites/join/join_key_cmp_udf-off.cfg
new file mode 100644
index 0000000000..3892ddff67
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_key_cmp_udf-off.cfg
@@ -0,0 +1,4 @@
+in Input input.txt
+udf string_udf
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_key_cmp_udf.cfg b/yql/essentials/tests/sql/suites/join/join_key_cmp_udf.cfg
new file mode 100644
index 0000000000..c6596e362c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_key_cmp_udf.cfg
@@ -0,0 +1,2 @@
+in Input input.txt
+udf string_udf
diff --git a/yql/essentials/tests/sql/suites/join/join_key_cmp_udf.sql b/yql/essentials/tests/sql/suites/join/join_key_cmp_udf.sql
new file mode 100644
index 0000000000..70a160e96d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_key_cmp_udf.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+--INSERT INTO Output
+SELECT
+ ib.*
+FROM Input as ia
+JOIN Input as ib
+ON Unicode::ToUpper(CAST(ia.key AS Utf8)) == ib.subkey
+ORDER BY ib.key, ib.subkey
diff --git a/yql/essentials/tests/sql/suites/join/join_left_cbo.cfg b/yql/essentials/tests/sql/suites/join/join_left_cbo.cfg
new file mode 100644
index 0000000000..559fde513f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_left_cbo.cfg
@@ -0,0 +1,2 @@
+in Input1 input1.txt
+in Input2 input2.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_left_cbo.sql b/yql/essentials/tests/sql/suites/join/join_left_cbo.sql
new file mode 100644
index 0000000000..81b974bdce
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_left_cbo.sql
@@ -0,0 +1,8 @@
+use plato;
+
+pragma CostBasedOptimizer="PG";
+
+select i1.value, i2.value
+from Input1 as i1
+left join Input2 as i2 on i1.key=i2.key
+order by i1.value, i2.value;
diff --git a/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by-off.cfg b/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by.cfg b/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by.sql b/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by.sql
new file mode 100644
index 0000000000..1f3f1f4d95
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_no_correlation_in_order_by.sql
@@ -0,0 +1,12 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$data = (SELECT key as kk, subkey as sk, value as val FROM Input WHERE cast(key as uint32)/100 > 3);
+
+--INSERT INTO Output
+SELECT
+ *
+FROM Input JOIN $data as d ON Input.subkey = d.kk
+ORDER BY key, val
+;
diff --git a/yql/essentials/tests/sql/suites/join/join_right_cbo.cfg b/yql/essentials/tests/sql/suites/join/join_right_cbo.cfg
new file mode 100644
index 0000000000..559fde513f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_right_cbo.cfg
@@ -0,0 +1,2 @@
+in Input1 input1.txt
+in Input2 input2.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_right_cbo.sql b/yql/essentials/tests/sql/suites/join/join_right_cbo.sql
new file mode 100644
index 0000000000..7b9378a9ec
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_right_cbo.sql
@@ -0,0 +1,8 @@
+use plato;
+
+pragma CostBasedOptimizer="PG";
+
+select i1.value, i2.value
+from Input1 as i1
+right join Input2 as i2 on i1.key=i2.key
+order by i1.value, i2.value;
diff --git a/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by-off.cfg b/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by.cfg b/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by.sql b/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by.sql
new file mode 100644
index 0000000000..4065705a77
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_semi_correlation_in_order_by.sql
@@ -0,0 +1,12 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$data = (SELECT key as kk, subkey as sk, value as val FROM Input WHERE cast(key as uint32)/100 > 3);
+
+--INSERT INTO Output
+SELECT
+ *
+FROM Input JOIN $data as d ON Input.subkey = d.kk
+ORDER BY key, d.val
+;
diff --git a/yql/essentials/tests/sql/suites/join/join_table_conflict_fail-off.cfg b/yql/essentials/tests/sql/suites/join/join_table_conflict_fail-off.cfg
new file mode 100644
index 0000000000..4408d29e54
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_table_conflict_fail-off.cfg
@@ -0,0 +1,3 @@
+xfail
+in Input input.txtproviders dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_table_conflict_fail.cfg b/yql/essentials/tests/sql/suites/join/join_table_conflict_fail.cfg
new file mode 100644
index 0000000000..9217c920f8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_table_conflict_fail.cfg
@@ -0,0 +1,2 @@
+xfail
+in Input input.txt \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/join_table_conflict_fail.sql b/yql/essentials/tests/sql/suites/join/join_table_conflict_fail.sql
new file mode 100644
index 0000000000..e499d334b0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_table_conflict_fail.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$data = (SELECT key as kk, subkey as sk, value || value as value FROM Input WHERE cast(key as uint32)/100 > 3);
+
+--INSERT INTO Output
+SELECT
+ value, key -- value is conflicted between Input and d sources
+FROM Input JOIN $data as d ON Input.subkey = d.kk
+;
diff --git a/yql/essentials/tests/sql/suites/join/join_with_dot_without_alias.cfg b/yql/essentials/tests/sql/suites/join/join_with_dot_without_alias.cfg
new file mode 100644
index 0000000000..702bbb5a52
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_with_dot_without_alias.cfg
@@ -0,0 +1,2 @@
+in Input input.txt
+in Input.with.dot input_tutorial_users.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_with_dot_without_alias.sqlx b/yql/essentials/tests/sql/suites/join/join_with_dot_without_alias.sqlx
new file mode 100644
index 0000000000..01b6c5374a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_with_dot_without_alias.sqlx
@@ -0,0 +1,6 @@
+USE plato;
+SELECT
+ t.key, t.value
+FROM Input as t
+LEFT SEMI JOIN `Input.with.dot`
+USING(subkey);
diff --git a/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted-off.cfg b/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted-off.cfg
new file mode 100644
index 0000000000..49af2b95f4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted-off.cfg
@@ -0,0 +1,4 @@
+in SortedByKey sorted_by_key1.txt
+in SortedByKeySubkey sorted_by_key_subkey.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted.cfg b/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted.cfg
new file mode 100644
index 0000000000..464068db6a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted.cfg
@@ -0,0 +1,2 @@
+in SortedByKey sorted_by_key1.txt
+in SortedByKeySubkey sorted_by_key_subkey.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted.sql b/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted.sql
new file mode 100644
index 0000000000..9b350d29a8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_with_duplicate_keys_on_sorted.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+
+
+FROM SortedByKeySubkey AS a JOIN SortedByKey AS b ON a.key=b.key AND a.subkey=b.key
+SELECT * ORDER BY a.value, b.value;
diff --git a/yql/essentials/tests/sql/suites/join/join_without_column-off.cfg b/yql/essentials/tests/sql/suites/join/join_without_column-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_column-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_without_column.cfg b/yql/essentials/tests/sql/suites/join/join_without_column.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_column.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_without_column.sql b/yql/essentials/tests/sql/suites/join/join_without_column.sql
new file mode 100644
index 0000000000..4c9c4bd612
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_column.sql
@@ -0,0 +1,14 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$data = (SELECT key as kk, subkey as sk, value FROM Input WHERE cast(key as uint32)/100 < 5);
+
+--INSERT INTO Output
+SELECT
+ *
+WITHOUT
+ d.value
+FROM Input JOIN $data as d ON Input.subkey = cast(cast(d.kk as uint32)/100 as string)
+ORDER BY key
+;
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access-off.cfg b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access-off.cfg
new file mode 100644
index 0000000000..76a2a2b6a4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access-off.cfg
@@ -0,0 +1,3 @@
+in Input input_intersect.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access.cfg b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access.cfg
new file mode 100644
index 0000000000..3df7813790
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access.cfg
@@ -0,0 +1 @@
+in Input input_intersect.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access.sql b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access.sql
new file mode 100644
index 0000000000..280a971538
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_dict_access.sql
@@ -0,0 +1,22 @@
+/* syntax version 1 */
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+use plato;
+
+$data_dict = (select
+ mod,
+ YQL::ToIndexDict(ListSort(aggregate_list(key))) as dk,
+ ListSort(aggregate_list(subkey)) as ls,
+ ListSort(aggregate_list(value)) as lv
+from Input
+group by cast(key as uint32) % 10 as mod);
+
+--INSERT INTO Output
+SELECT
+--DISTINCT
+ dk[2],
+ key,
+ value
+FROM Input JOIN $data_dict AS d on cast(Input.key as uint32) / 100 == d.mod
+order by key, value
+;
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access-off.cfg b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access-off.cfg
new file mode 100644
index 0000000000..76a2a2b6a4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access-off.cfg
@@ -0,0 +1,3 @@
+in Input input_intersect.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access.cfg b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access.cfg
new file mode 100644
index 0000000000..3df7813790
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access.cfg
@@ -0,0 +1 @@
+in Input input_intersect.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access.sql b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access.sql
new file mode 100644
index 0000000000..d1934f0bfc
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_and_struct_access.sql
@@ -0,0 +1,18 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+use plato;
+
+$data = ( select
+ cast(key as uint32) % 10 as mod,
+ (key as kk, subkey as sk) as struct_field
+from Input);
+
+--INSERT INTO Output
+SELECT
+ mod,
+ struct_field.kk as mod_key,
+ key,
+ value
+FROM Input JOIN $data AS d on cast(Input.key as uint32) / 100 == d.mod
+order by key, mod_key, value
+;
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_names-off.cfg b/yql/essentials/tests/sql/suites/join/join_without_correlation_names-off.cfg
new file mode 100644
index 0000000000..76a2a2b6a4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_names-off.cfg
@@ -0,0 +1,3 @@
+in Input input_intersect.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_names.cfg b/yql/essentials/tests/sql/suites/join/join_without_correlation_names.cfg
new file mode 100644
index 0000000000..3df7813790
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_names.cfg
@@ -0,0 +1 @@
+in Input input_intersect.txt
diff --git a/yql/essentials/tests/sql/suites/join/join_without_correlation_names.sql b/yql/essentials/tests/sql/suites/join/join_without_correlation_names.sql
new file mode 100644
index 0000000000..98922c13e0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/join_without_correlation_names.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$data = (SELECT key as kk, subkey as sk, value as val FROM Input WHERE cast(key as uint32)/100 > 3);
+
+--INSERT INTO Output
+SELECT
+ value, val, key, sk
+FROM Input JOIN $data as d ON Input.subkey = d.kk
+ORDER BY value, val;
diff --git a/yql/essentials/tests/sql/suites/join/kv1_sorted.txt b/yql/essentials/tests/sql/suites/join/kv1_sorted.txt
new file mode 100644
index 0000000000..32006a80c5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv1_sorted.txt
@@ -0,0 +1,32 @@
+{"k1"="01";"v1"="1";"u1"="01"};
+{"k1"="01";"v1"="2";"u1"="02"};
+
+{"k1"="02";"v1"="1";"u1"="03"};
+{"k1"="02";"v1"="1";"u1"="04"};
+{"k1"="02";"v1"="2";"u1"="05"};
+{"k1"="02";"v1"="2";"u1"="06"};
+
+{"k1"="03";"v1"=#; "u1"="07"};
+{"k1"="03";"v1"="1";"u1"="08"};
+{"k1"="03";"v1"="2";"u1"="09"};
+
+{"k1"="04";"v1"="1";"u1"="10"};
+{"k1"="04";"v1"="2";"u1"="11"};
+
+{"k1"="05";"v1"="1";"u1"="12"};
+{"k1"="05";"v1"="2";"u1"="13"};
+
+{"k1"="06";"v1"="1";"u1"="14"};
+{"k1"="06";"v1"="2";"u1"="15"};
+
+{"k1"="07";"v1"="1";"u1"="16"};
+{"k1"="07";"v1"="2";"u1"="17"};
+
+{"k1"="08";"v1"="1";"u1"="18"};
+{"k1"="08";"v1"="2";"u1"="19"};
+
+{"k1"="09";"v1"="1";"u1"="20"};
+{"k1"="09";"v1"="2";"u1"="21"};
+
+{"k1"="10";"v1"="1";"u1"="22"};
+{"k1"="10";"v1"="2";"u1"="23"};
diff --git a/yql/essentials/tests/sql/suites/join/kv1_sorted.txt.attr b/yql/essentials/tests/sql/suites/join/kv1_sorted.txt.attr
new file mode 100644
index 0000000000..0b9487ba64
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv1_sorted.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v1";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/kv1_sorted1.txt b/yql/essentials/tests/sql/suites/join/kv1_sorted1.txt
new file mode 100644
index 0000000000..45fc02595f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv1_sorted1.txt
@@ -0,0 +1,2 @@
+{"k1"="01";"v1"="1";"u1"="01"};
+{"k1"="01";"v1"="2";"u1"="02"};
diff --git a/yql/essentials/tests/sql/suites/join/kv1_sorted1.txt.attr b/yql/essentials/tests/sql/suites/join/kv1_sorted1.txt.attr
new file mode 100644
index 0000000000..0b9487ba64
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv1_sorted1.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v1";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/kv2_sorted.txt b/yql/essentials/tests/sql/suites/join/kv2_sorted.txt
new file mode 100644
index 0000000000..2ce5f4119f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv2_sorted.txt
@@ -0,0 +1,22 @@
+{"k2"="02";"v2"="1";"u2"="01"};
+{"k2"="02";"v2"="1";"u2"="02"};
+{"k2"="02";"v2"="2";"u2"="03"};
+{"k2"="02";"v2"="2";"u2"="04"};
+
+{"k2"="03";"v2"="1";"u2"="05"};
+{"k2"="03";"v2"="2";"u2"="06"};
+
+{"k2"="04";"v2"="1";"u2"="07"};
+{"k2"="04";"v2"="2";"u2"="08"};
+
+{"k2"="05";"v2"="1";"u2"="09"};
+{"k2"="05";"v2"="2";"u2"="10"};
+
+{"k2"="06";"v2"="1";"u2"="11"};
+{"k2"="06";"v2"="2";"u2"="12"};
+
+{"k2"="07";"v2"="1";"u2"="13"};
+{"k2"="07";"v2"="2";"u2"="14"};
+
+{"k2"="09";"v2"="1";"u2"="15"};
+{"k2"="09";"v2"="2";"u2"="16"};
diff --git a/yql/essentials/tests/sql/suites/join/kv2_sorted.txt.attr b/yql/essentials/tests/sql/suites/join/kv2_sorted.txt.attr
new file mode 100644
index 0000000000..387ceb1b55
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv2_sorted.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u2";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/kv2_sorted1.txt b/yql/essentials/tests/sql/suites/join/kv2_sorted1.txt
new file mode 100644
index 0000000000..3bd67e7caa
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv2_sorted1.txt
@@ -0,0 +1,2 @@
+{"k2"="01";"v2"="1";"u2"="01"};
+{"k2"="01";"v2"="2";"u2"="03"};
diff --git a/yql/essentials/tests/sql/suites/join/kv2_sorted1.txt.attr b/yql/essentials/tests/sql/suites/join/kv2_sorted1.txt.attr
new file mode 100644
index 0000000000..387ceb1b55
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv2_sorted1.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u2";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/kv3_sorted.txt b/yql/essentials/tests/sql/suites/join/kv3_sorted.txt
new file mode 100644
index 0000000000..c9ef7d9a22
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv3_sorted.txt
@@ -0,0 +1,8 @@
+{"k3"=#; "v3"="1";"u3"="01"};
+{"k3"=#; "v3"="2";"u3"="02"};
+
+{"k3"="04";"v3"="1";"u3"="03"};
+{"k3"="04";"v3"="2";"u3"="04"};
+
+{"k3"="05";"v3"="1";"u3"="05"};
+{"k3"="05";"v3"="2";"u3"="06"};
diff --git a/yql/essentials/tests/sql/suites/join/kv3_sorted.txt.attr b/yql/essentials/tests/sql/suites/join/kv3_sorted.txt.attr
new file mode 100644
index 0000000000..90e6a79548
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv3_sorted.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k3";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v3";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u3";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/kv4_sorted.txt b/yql/essentials/tests/sql/suites/join/kv4_sorted.txt
new file mode 100644
index 0000000000..a355cbb673
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv4_sorted.txt
@@ -0,0 +1,18 @@
+{"k4"="03";"v4"=#; "u4"="01"};
+{"k4"="03";"v4"="1";"u4"="02"};
+{"k4"="03";"v4"="2";"u4"="03"};
+
+{"k4"="04";"v4"="1";"u4"="04"};
+{"k4"="04";"v4"="2";"u4"="05"};
+
+{"k4"="05";"v4"="1";"u4"="06"};
+{"k4"="05";"v4"="2";"u4"="07"};
+
+{"k4"="06";"v4"="1";"u4"="08"};
+{"k4"="06";"v4"="2";"u4"="09"};
+
+{"k4"="07";"v4"="1";"u4"="10"};
+{"k4"="07";"v4"="2";"u4"="11"};
+
+{"k4"="08";"v4"="1";"u4"="12"};
+{"k4"="08";"v4"="2";"u4"="13"};
diff --git a/yql/essentials/tests/sql/suites/join/kv4_sorted.txt.attr b/yql/essentials/tests/sql/suites/join/kv4_sorted.txt.attr
new file mode 100644
index 0000000000..ea731dd20b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv4_sorted.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %true
+ >
+ [
+ {
+ "name" = "k4";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v4";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u4";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/kv5_sorted.txt b/yql/essentials/tests/sql/suites/join/kv5_sorted.txt
new file mode 100644
index 0000000000..748994c8e8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv5_sorted.txt
@@ -0,0 +1,13 @@
+{"k5"=# ;"v5"="1";"u5"="01"};
+{"k5"=# ;"v5"="2";"u5"="02"};
+
+{"k5"="02";"v5"="1";"u5"="03"};
+{"k5"="02";"v5"="1";"u5"="04"};
+{"k5"="02";"v5"="2";"u5"="05"};
+{"k5"="02";"v5"="2";"u5"="06"};
+
+{"k5"="03";"v5"="1";"u5"="07"};
+{"k5"="03";"v5"="2";"u5"="08"};
+
+{"k5"="09";"v5"="1";"u5"="09"};
+{"k5"="09";"v5"="2";"u5"="10"};
diff --git a/yql/essentials/tests/sql/suites/join/kv5_sorted.txt.attr b/yql/essentials/tests/sql/suites/join/kv5_sorted.txt.attr
new file mode 100644
index 0000000000..05a419bcca
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/kv5_sorted.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k5";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v5";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u5";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/late_mergejoin_on_empty.cfg b/yql/essentials/tests/sql/suites/join/late_mergejoin_on_empty.cfg
new file mode 100644
index 0000000000..04719e2ed1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/late_mergejoin_on_empty.cfg
@@ -0,0 +1,2 @@
+in Input input1.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/late_mergejoin_on_empty.sql b/yql/essentials/tests/sql/suites/join/late_mergejoin_on_empty.sql
new file mode 100644
index 0000000000..b0dd13c10d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/late_mergejoin_on_empty.sql
@@ -0,0 +1,8 @@
+use plato;
+PRAGMA DisableSimpleColumns;
+pragma yt.JoinMergeTablesLimit="100";
+
+select * from
+(select * from Input where key < "020") as a
+left only join (select subkey from Input where key < "010") as b on a.subkey = b.subkey
+join /*+ merge() */ (select key, value from Input) as c on a.key = c.key
diff --git a/yql/essentials/tests/sql/suites/join/leaf.txt b/yql/essentials/tests/sql/suites/join/leaf.txt
new file mode 100644
index 0000000000..0de2350ffa
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/leaf.txt
@@ -0,0 +1,17 @@
+{"key"=0u;"value"="zero"};
+{"key"=0u;"value"=#};
+{"key"=0u;"value"="null"};
+{"key"=1u;"value"="one"};
+{"key"=2u;"value"="two"};
+{"key"=2u;"value"="two"};
+{"key"=2u;"value"="pair"};
+{"key"=3u;"value"="three"};
+{"key"=6u;"value"="six"};
+{"key"=6u;"value"="3+3"};
+{"key"=3u;"value"="1+1+1"};
+{"key"=7u;"value"="seven"};
+{"key"=9u;"value"="nine"};
+{"key"=8u;"value"="eight"};
+{"key"=5u;"value"="five"};
+{"key"=4u;"value"="2*2"};
+{"key"=4u;"value"="four"};
diff --git a/yql/essentials/tests/sql/suites/join/leaf.txt.attr b/yql/essentials/tests/sql/suites/join/leaf.txt.attr
new file mode 100644
index 0000000000..0a764a6b82
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/leaf.txt.attr
@@ -0,0 +1,6 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"Uint64"]];
+ ["value";["OptionalType";["DataType";"String"]]]]
+ ];
+}}
diff --git a/yql/essentials/tests/sql/suites/join/left_all-off.cfg b/yql/essentials/tests/sql/suites/join/left_all-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_all-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_all.cfg b/yql/essentials/tests/sql/suites/join/left_all.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_all.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_all.sql b/yql/essentials/tests/sql/suites/join/left_all.sql
new file mode 100644
index 0000000000..b980bc85d2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_all.sql
@@ -0,0 +1,6 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+SELECT *
+FROM Input2 AS a
+LEFT JOIN Input3 AS b
+ON a.value == b.value;
diff --git a/yql/essentials/tests/sql/suites/join/left_cast_to_string-off.cfg b/yql/essentials/tests/sql/suites/join/left_cast_to_string-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_cast_to_string-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_cast_to_string.cfg b/yql/essentials/tests/sql/suites/join/left_cast_to_string.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_cast_to_string.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_cast_to_string.sql b/yql/essentials/tests/sql/suites/join/left_cast_to_string.sql
new file mode 100644
index 0000000000..5d41a78255
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_cast_to_string.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select Input1.key as key, Input1.subkey, Cast(Input3.value as varchar) as value from plato.Input1 left join plato.Input3 using (key) order by key; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/left_join_input1.txt b/yql/essentials/tests/sql/suites/join/left_join_input1.txt
new file mode 100644
index 0000000000..ff0c12e814
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_input1.txt
@@ -0,0 +1,8 @@
+{"Key1"=101;"Key2"="One";"Fk1"=#;"Value"="no_right_key_1"};
+{"Key1"=102;"Key2"="Two";"Fk1"=#;"Value"="no_right_key_2"};
+{"Key1"=103;"Key2"="Three";"Fk1"="Name1";"Value"="Value1"};
+{"Key1"=104;"Key2"="One";"Fk1"="Name2";"Value"="Value2"};
+{"Key1"=104;"Key2"="Two";"Fk1"="Name2";"Value"="Value3"};
+{"Key1"=105;"Key2"="One";"Fk1"="Name3";"Value"="no_right_key_3"};
+{"Key1"=106;"Key2"="One";"Fk1"="Name4";"Value"=#};
+{"Key1"=106;"Key2"="Two";"Fk1"="Name4";"Value"="Value4"};
diff --git a/yql/essentials/tests/sql/suites/join/left_join_input1.txt.attr b/yql/essentials/tests/sql/suites/join/left_join_input1.txt.attr
new file mode 100644
index 0000000000..4f113053bc
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_input1.txt.attr
@@ -0,0 +1,10 @@
+{
+ "_yql_row_spec"={
+ "Type"=["StructType";[
+ ["Key1";["OptionalType";["DataType";"Int32"]]];
+ ["Key2";["OptionalType";["DataType";"String"]]];
+ ["Fk1";["OptionalType";["DataType";"String"]]];
+ ["Value";["OptionalType";["DataType";"String"]]]]
+ ];
+ };
+}
diff --git a/yql/essentials/tests/sql/suites/join/left_join_input2.txt b/yql/essentials/tests/sql/suites/join/left_join_input2.txt
new file mode 100644
index 0000000000..94730fa38c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_input2.txt
@@ -0,0 +1,3 @@
+{"Key"="Name1";"Value"=1001};
+{"Key"="Name2";"Value"=1002};
+{"Key"="Name4";"Value"=#};
diff --git a/yql/essentials/tests/sql/suites/join/left_join_input2.txt.attr b/yql/essentials/tests/sql/suites/join/left_join_input2.txt.attr
new file mode 100644
index 0000000000..be5e16e2ca
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_input2.txt.attr
@@ -0,0 +1,8 @@
+{
+ "_yql_row_spec"={
+ "Type"=["StructType";[
+ ["Key";["DataType";"String"]];
+ ["Value";["OptionalType";["DataType";"Int32"]]]]
+ ];
+ }
+}
diff --git a/yql/essentials/tests/sql/suites/join/left_join_input3.txt b/yql/essentials/tests/sql/suites/join/left_join_input3.txt
new file mode 100644
index 0000000000..596c900d7d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_input3.txt
@@ -0,0 +1 @@
+{"Key"="Name2";"Value"=12345};
diff --git a/yql/essentials/tests/sql/suites/join/left_join_input3.txt.attr b/yql/essentials/tests/sql/suites/join/left_join_input3.txt.attr
new file mode 100644
index 0000000000..be5e16e2ca
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_input3.txt.attr
@@ -0,0 +1,8 @@
+{
+ "_yql_row_spec"={
+ "Type"=["StructType";[
+ ["Key";["DataType";"String"]];
+ ["Value";["OptionalType";["DataType";"Int32"]]]]
+ ];
+ }
+}
diff --git a/yql/essentials/tests/sql/suites/join/left_join_null_column-off.cfg b/yql/essentials/tests/sql/suites/join/left_join_null_column-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_null_column-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_join_null_column.cfg b/yql/essentials/tests/sql/suites/join/left_join_null_column.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_null_column.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_join_null_column.sql b/yql/essentials/tests/sql/suites/join/left_join_null_column.sql
new file mode 100644
index 0000000000..c7e38d6e0c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_null_column.sql
@@ -0,0 +1,9 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+$t = [<|"x":"150", "y":1, "z":Null|>, <|"x":"150", "y":2, "z":Null|>];
+
+SELECT * FROM Input1 AS a LEFT JOIN AS_TABLE($t) AS b ON a.key = b.x ORDER BY key, y;
+
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_left.cfg b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_left.cfg
new file mode 100644
index 0000000000..a0d2d24b7f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_left.cfg
@@ -0,0 +1,3 @@
+in Input1 left_join_input1.txt
+in Input2 left_join_input2.txt
+in Input3 left_join_input3.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_left.sql b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_left.sql
new file mode 100644
index 0000000000..da815ce13b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_left.sql
@@ -0,0 +1,11 @@
+PRAGMA FilterPushdownOverJoinOptionalSide;
+
+SELECT t1.Key1, t1.Key2, t1.Fk1, t1.Value, t2.Key, t2.Value, t3.Value
+
+FROM plato.Input1 AS t1
+LEFT JOIN plato.Input2 AS t2
+ON t1.Fk1 = t2.Key
+INNER JOIN plato.Input3 as t3
+ON t1.Fk1 = t3.Key
+
+WHERE t2.Value > 1001;
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_right.cfg b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_right.cfg
new file mode 100644
index 0000000000..a0d2d24b7f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_right.cfg
@@ -0,0 +1,3 @@
+in Input1 left_join_input1.txt
+in Input2 left_join_input2.txt
+in Input3 left_join_input3.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_right.sql b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_right.sql
new file mode 100644
index 0000000000..fe7fdeea48
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_nested_right.sql
@@ -0,0 +1,10 @@
+PRAGMA FilterPushdownOverJoinOptionalSide;
+
+SELECT t1.Key1, t1.Key2, t1.Fk1, t1.Value, t2.Key, t2.Value, t3.Value
+
+FROM plato.Input1 AS t1
+CROSS JOIN plato.Input3 AS t3
+LEFT JOIN plato.Input2 AS t2
+ON t1.Fk1 = t2.Key
+
+WHERE t2.Value > 1001;
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_no_opt.cfg b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_no_opt.cfg
new file mode 100644
index 0000000000..a0d2d24b7f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_no_opt.cfg
@@ -0,0 +1,3 @@
+in Input1 left_join_input1.txt
+in Input2 left_join_input2.txt
+in Input3 left_join_input3.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_no_opt.sql b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_no_opt.sql
new file mode 100644
index 0000000000..de596ae77b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_no_opt.sql
@@ -0,0 +1,7 @@
+PRAGMA FilterPushdownOverJoinOptionalSide;
+
+SELECT t1.Key1, t1.Key2, t1.Fk1, t1.Value, t2.Key, t2.Value FROM plato.Input2 AS t2
+RIGHT JOIN plato.Input1 AS t1
+ON t2.Key = t1.Fk1
+WHERE t1.Key1 > 104
+ORDER BY t1.Key1, t1.Key2;
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_null.cfg b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_null.cfg
new file mode 100644
index 0000000000..a0d2d24b7f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_null.cfg
@@ -0,0 +1,3 @@
+in Input1 left_join_input1.txt
+in Input2 left_join_input2.txt
+in Input3 left_join_input3.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_null.sql b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_null.sql
new file mode 100644
index 0000000000..ec45c754b4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_null.sql
@@ -0,0 +1,7 @@
+PRAGMA FilterPushdownOverJoinOptionalSide;
+
+SELECT t1.Key1, t1.Key2, t1.Fk1, t1.Value, t2.Key, t2.Value FROM plato.Input1 AS t1
+LEFT JOIN plato.Input2 AS t2
+ON t1.Fk1 = t2.Key
+WHERE t2.Value IS NULL
+ORDER BY t1.Key1, t1.Key2;
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_simple.cfg b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_simple.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_simple.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_simple.sql b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_simple.sql
new file mode 100644
index 0000000000..e1c15a8d52
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_right_pushdown_simple.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA FilterPushdownOverJoinOptionalSide;
+
+use plato;
+SELECT *
+FROM Input2 AS a
+LEFT JOIN Input3 AS b
+ON a.value == b.value
+WHERE b.value >= "ddd";
diff --git a/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr-off.cfg b/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr.cfg b/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr.sql b/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr.sql
new file mode 100644
index 0000000000..5ce4892df9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_join_with_self_aggr.sql
@@ -0,0 +1,51 @@
+
+$a = [
+ AsStruct(
+ 'a' as x,
+ 1 as y
+ ),
+ AsStruct(
+ 'a' as x,
+ 1 as y
+ ),
+ AsStruct(
+ 'a' as x,
+ 2 as y
+ ),
+ AsStruct(
+ 'a' as x,
+ 3 as y
+ ),
+ AsStruct(
+ 'b' as x,
+ 1 as y
+ ),
+ AsStruct(
+ 'b' as x,
+ 2 as y
+ ),
+ AsStruct(
+ 'b' as x,
+ 3 as y
+ ),
+ AsStruct(
+ 'c' as x,
+ 1 as y
+ ),
+];
+
+$a = select x as bar, y as foo from AS_TABLE($a);
+
+$b =
+SELECT
+ a.bar as bar, count(*) as cnt
+from $a as a
+inner join (
+ select bar, min(foo) as foo
+ from $a
+ group by bar
+) as b using (foo, bar)
+group by a.bar;
+
+
+select * from $a as a left join $b as b using (bar);
diff --git a/yql/essentials/tests/sql/suites/join/left_null_literal-off.cfg b/yql/essentials/tests/sql/suites/join/left_null_literal-off.cfg
new file mode 100644
index 0000000000..a838c2cc3a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_null_literal-off.cfg
@@ -0,0 +1,3 @@
+out Output output.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_null_literal.cfg b/yql/essentials/tests/sql/suites/join/left_null_literal.cfg
new file mode 100644
index 0000000000..9b85bd0ae8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_null_literal.cfg
@@ -0,0 +1 @@
+out Output output.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_null_literal.sql b/yql/essentials/tests/sql/suites/join/left_null_literal.sql
new file mode 100644
index 0000000000..4325869895
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_null_literal.sql
@@ -0,0 +1,8 @@
+/* syntax version 1 */
+use plato;
+
+$foo = [<|"x":1|>];
+$bar = [<|"x":1, "y":Null|>];
+
+insert into Output
+select * from AS_TABLE($foo) as a LEFT JOIN AS_TABLE($bar) as b USING(x);
diff --git a/yql/essentials/tests/sql/suites/join/left_only_semi_and_other-off.cfg b/yql/essentials/tests/sql/suites/join/left_only_semi_and_other-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_only_semi_and_other-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_only_semi_and_other.cfg b/yql/essentials/tests/sql/suites/join/left_only_semi_and_other.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_only_semi_and_other.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_only_semi_and_other.sql b/yql/essentials/tests/sql/suites/join/left_only_semi_and_other.sql
new file mode 100644
index 0000000000..3258c30324
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_only_semi_and_other.sql
@@ -0,0 +1,15 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$data1 = (select cast(key as uint32) as key, subkey, value from Input1);
+$data2 = (select cast(key as uint32) % 100u as key, subkey, value from Input3);
+
+--INSERT INTO Output
+SELECT
+ i1.*
+FROM $data1 as i1
+LEFT ONLY JOIN $data2 as i2 ON i1.key = i2.key
+LEFT SEMI JOIN $data1 as i3 ON i1.key = i3.key
+LEFT OUTER JOIN $data1 as i4 ON i1.key = i4.key
+ORDER BY i1.key
diff --git a/yql/essentials/tests/sql/suites/join/left_only_with_other-off.cfg b/yql/essentials/tests/sql/suites/join/left_only_with_other-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_only_with_other-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_only_with_other.cfg b/yql/essentials/tests/sql/suites/join/left_only_with_other.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_only_with_other.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_only_with_other.sql b/yql/essentials/tests/sql/suites/join/left_only_with_other.sql
new file mode 100644
index 0000000000..65b1bf178d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_only_with_other.sql
@@ -0,0 +1,14 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$data1 = (select cast(key as uint32) as key, subkey, value from Input1);
+$data2 = (select cast(key as uint32) % 100u as key, subkey, value from Input1);
+
+--INSERT INTO Output
+SELECT
+ i1.*
+FROM $data1 as i1
+LEFT ONLY JOIN $data2 as i2 ON i1.key = i2.key
+JOIN $data1 as i3 ON i1.key = i3.key
+;
diff --git a/yql/essentials/tests/sql/suites/join/left_semi_with_other-off.cfg b/yql/essentials/tests/sql/suites/join/left_semi_with_other-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_semi_with_other-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_semi_with_other.cfg b/yql/essentials/tests/sql/suites/join/left_semi_with_other.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_semi_with_other.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_semi_with_other.sql b/yql/essentials/tests/sql/suites/join/left_semi_with_other.sql
new file mode 100644
index 0000000000..0ac01a9e53
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_semi_with_other.sql
@@ -0,0 +1,15 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+$data1 = (select cast(key as uint32) as key, subkey, value from Input1);
+$data2 = (select cast(key as uint32) % 100u as key, subkey, value from Input2);
+
+--INSERT INTO Output
+SELECT
+ i1.*
+FROM $data1 as i1
+LEFT SEMI JOIN $data2 as i2 ON i1.key = i2.key
+LEFT OUTER JOIN $data1 as i3 ON i1.key = i3.key
+ORDER BY i1.key
+;
diff --git a/yql/essentials/tests/sql/suites/join/left_trivial-off.cfg b/yql/essentials/tests/sql/suites/join/left_trivial-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_trivial-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/left_trivial.cfg b/yql/essentials/tests/sql/suites/join/left_trivial.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_trivial.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/left_trivial.sql b/yql/essentials/tests/sql/suites/join/left_trivial.sql
new file mode 100644
index 0000000000..ae448327da
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/left_trivial.sql
@@ -0,0 +1,5 @@
+PRAGMA DisableSimpleColumns;
+select Input1.key, Input1.subkey, Input3.value
+from plato.Input1
+left join plato.Input3 using (key)
+order by Input1.key; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee.sql
new file mode 100644
index 0000000000..63d400bf94
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_csee.sql
@@ -0,0 +1,30 @@
+/* ignore runonopt plan diff */
+USE plato;
+PRAGMA DisableSimpleColumns;
+PRAGMA yt.LookupJoinLimit="64k";
+PRAGMA yt.LookupJoinMaxRows="100";
+
+$campaigns_data = AsList(
+ AsStruct(Just(1) as id),
+ AsStruct(Just(2) as id));
+
+$strategies_data = AsList(
+ AsStruct(Just(1) as id),
+ AsStruct(Just(2) as id));
+
+$lottery_data = AsList(
+ AsStruct(Just(1) as id, Just(2) as campaign_id, Just(3) as strategy_id));
+
+
+INSERT INTO @campaigns SELECT * FROM AS_TABLE($campaigns_data) ORDER BY id;
+INSERT INTO @strategies SELECT * FROM AS_TABLE($strategies_data) ORDER BY id;
+INSERT INTO @lottery SELECT * FROM AS_TABLE($lottery_data) ORDER BY id;
+
+COMMIT;
+
+SELECT
+ lottery.id AS lottery_id
+FROM @lottery AS lottery
+ JOIN @campaigns AS campaigns ON lottery.campaign_id = campaigns.id
+ JOIN @strategies AS strategies ON lottery.strategy_id = strategies.id
+WHERE 1 < 0
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst.sql
new file mode 100644
index 0000000000..e91ef8f7c2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug7646_subst.sql
@@ -0,0 +1,28 @@
+USE plato;
+PRAGMA DisableSimpleColumns;
+PRAGMA yt.LookupJoinLimit="64k";
+PRAGMA yt.LookupJoinMaxRows="100";
+
+$campaigns_data = AsList(
+ AsStruct(Just(1) as id),
+ AsStruct(Just(2) as id));
+
+$strategies_data = AsList(
+ AsStruct(Just(1) as id),
+ AsStruct(Just(2) as id));
+
+$lottery_data = AsList(
+ AsStruct(Just(1) as id, Just(2) as campaign_id, Just(3) as strategy_id));
+
+
+INSERT INTO @campaigns SELECT * FROM AS_TABLE($campaigns_data) ORDER BY id;
+INSERT INTO @strategies SELECT * FROM AS_TABLE($strategies_data) ORDER BY id;
+INSERT INTO @lottery SELECT * FROM AS_TABLE($lottery_data) ORDER BY id;
+
+COMMIT;
+
+SELECT
+ lottery.id AS lottery_id
+FROM @lottery AS lottery
+ JOIN @campaigns AS campaigns ON lottery.campaign_id = campaigns.id
+ JOIN @strategies AS strategies ON lottery.strategy_id = strategies.id
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533.sql
new file mode 100644
index 0000000000..8e2b401fa0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_bug8533.sql
@@ -0,0 +1,11 @@
+/* syntax version 1 */
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- tables should be swapped (Input1 is bigger)
+select * from Input2 as a
+inner join any Input1 as b on a.k2 = b.k1;
+
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_inner.sql
new file mode 100644
index 0000000000..a85dec245c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- tables should be swapped (Input1 is bigger)
+select * from Input2 as a
+inner join Input1 as b on a.k2 = b.k1 and a.v2 = b.v1;
+
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o-off.cfg
new file mode 100644
index 0000000000..473c367b92
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o.cfg
new file mode 100644
index 0000000000..0e1c5e12b2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o.sql
new file mode 100644
index 0000000000..a85dec245c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- tables should be swapped (Input1 is bigger)
+select * from Input2 as a
+inner join Input1 as b on a.k2 = b.k1 and a.v2 = b.v1;
+
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o-off.cfg
new file mode 100644
index 0000000000..cb6cc9dbbf
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv2_opt.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o.cfg
new file mode 100644
index 0000000000..a567b5178d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv2_opt.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o.sql
new file mode 100644
index 0000000000..a85dec245c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_1o2o.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- tables should be swapped (Input1 is bigger)
+select * from Input2 as a
+inner join Input1 as b on a.k2 = b.k1 and a.v2 = b.v1;
+
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o-off.cfg
new file mode 100644
index 0000000000..8dc359be1d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2_opt.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o.cfg
new file mode 100644
index 0000000000..a636052ccc
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2_opt.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o.sql
new file mode 100644
index 0000000000..a85dec245c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_2o.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- tables should be swapped (Input1 is bigger)
+select * from Input2 as a
+inner join Input1 as b on a.k2 = b.k1 and a.v2 = b.v1;
+
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq.sql
new file mode 100644
index 0000000000..afbfb0757b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_inner_empty_subq.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+select * from Input1 as a
+inner join (select * from Input2 where k2 = "not_existent") as b on a.k1 = b.k2;
+
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected.sql
new file mode 100644
index 0000000000..1f0f03b410
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_not_selected.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- no lookup join in this case
+select * from Input1 as a
+left join Input2 as b on a.k1 = b.k2;
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_semi.sql
new file mode 100644
index 0000000000..79093ae0fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- prefix of sort keys
+select * from Input1 as a
+left semi join Input2 as b on a.k1 = b.k2
+order by a.k1;
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o-off.cfg
new file mode 100644
index 0000000000..473c367b92
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o.cfg
new file mode 100644
index 0000000000..0e1c5e12b2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o.sql
new file mode 100644
index 0000000000..79093ae0fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- prefix of sort keys
+select * from Input1 as a
+left semi join Input2 as b on a.k1 = b.k2
+order by a.k1;
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o-off.cfg
new file mode 100644
index 0000000000..cb6cc9dbbf
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv2_opt.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o.cfg
new file mode 100644
index 0000000000..a567b5178d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1_opt.txt
+in Input2 sorted_by_kv2_opt.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o.sql
new file mode 100644
index 0000000000..79093ae0fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_1o2o.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- prefix of sort keys
+select * from Input1 as a
+left semi join Input2 as b on a.k1 = b.k2
+order by a.k1;
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o-off.cfg
new file mode 100644
index 0000000000..8dc359be1d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2_opt.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o.cfg
new file mode 100644
index 0000000000..a636052ccc
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2_opt.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o.sql
new file mode 100644
index 0000000000..79093ae0fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_2o.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- prefix of sort keys
+select * from Input1 as a
+left semi join Input2 as b on a.k1 = b.k2
+order by a.k1;
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty-off.cfg
new file mode 100644
index 0000000000..29c54dddd7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2_empty.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty.cfg
new file mode 100644
index 0000000000..b8938b393e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2_empty.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty.sql
new file mode 100644
index 0000000000..79093ae0fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_empty.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- prefix of sort keys
+select * from Input1 as a
+left semi join Input2 as b on a.k1 = b.k2
+order by a.k1;
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq.sql
new file mode 100644
index 0000000000..96cb5ca79a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_semi_subq.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+-- prefix of sort keys
+select * from Input1 as a
+left semi join (select * from Input2 where k2 != "ccc") as b on a.k1 = b.k2
+order by a.k1;
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_take_skip.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_take_skip.cfg
new file mode 100644
index 0000000000..8790d17dc7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_take_skip.cfg
@@ -0,0 +1,2 @@
+in Input input9.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_take_skip.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_take_skip.sql
new file mode 100644
index 0000000000..de1195209c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_take_skip.sql
@@ -0,0 +1,12 @@
+USE plato;
+PRAGMA yt.LookupJoinMaxRows="3";
+pragma yt.LookupJoinLimit = '10M';
+
+insert into @big
+select * from (select ListMap(ListFromRange(1, 100), ($x)->(Unwrap(CAST($x as String)))) as key) flatten list by key order by key;
+commit;
+
+$small = select substring(key, 0, 2) as key, subkey || '000' as subkey from Input order by key limit 5 offset 8;
+
+select * from @big as a join $small as b using(key) order by key;
+
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_unused_keys.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_unused_keys.cfg
new file mode 100644
index 0000000000..9a930ffe48
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_unused_keys.cfg
@@ -0,0 +1,6 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_unused_keys.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_unused_keys.sql
new file mode 100644
index 0000000000..cd0840eefe
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_unused_keys.sql
@@ -0,0 +1,13 @@
+/* syntax version 1 */
+use plato;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+
+select
+
+v3
+
+from Input1 as a
+join Input2 as b on (a.k1 = b.k2)
+join Input3 as c on (a.k1 = c.k3)
+order by v3;
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache-off.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache-off.cfg
new file mode 100644
index 0000000000..e7286dfd15
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache-off.cfg
@@ -0,0 +1,3 @@
+in Input sorted_by_key_subkey.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache.cfg b/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache.cfg
new file mode 100644
index 0000000000..2e90092760
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache.cfg
@@ -0,0 +1 @@
+in Input sorted_by_key_subkey.txt
diff --git a/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache.sql b/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache.sql
new file mode 100644
index 0000000000..0aeadca09a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/lookupjoin_with_cache.sql
@@ -0,0 +1,19 @@
+/* postgres can not */
+/* kikimr can not */
+use plato;
+PRAGMA DisableSimpleColumns;
+pragma yt.LookupJoinLimit="64k";
+pragma yt.LookupJoinMaxRows="100";
+pragma yt.QueryCacheMode="normal";
+pragma yt.QueryCacheUseForCalc="true";
+
+insert into @tmp with truncate
+select * from Input
+where subkey == "bbb"
+order by key;
+
+commit;
+
+select * from Input as a
+inner join @tmp as b on a.key = b.key
+order by a.key, a.subkey;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_dup_key-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_dup_key-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_dup_key-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_dup_key.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_dup_key.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_dup_key.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_dup_key.sql b/yql/essentials/tests/sql/suites/join/mapjoin_dup_key.sql
new file mode 100644
index 0000000000..54066e1d90
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_dup_key.sql
@@ -0,0 +1,10 @@
+use plato;
+
+/* postgres can not */
+/* kikimr can not */
+
+pragma DisableSimpleColumns;
+pragma yt.MapJoinLimit="1m";
+
+select *
+from Input1 as a join Input2 as b on a.key = b.key and a.subkey = b.key;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite-off.cfg
new file mode 100644
index 0000000000..e76fa257e2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite-off.cfg
@@ -0,0 +1,4 @@
+in Input uniqkeys.txt
+res result.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite.cfg
new file mode 100644
index 0000000000..0e7b4058e1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite.cfg
@@ -0,0 +1,2 @@
+in Input uniqkeys.txt
+res result.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite.sql b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite.sql
new file mode 100644
index 0000000000..de352022c9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite.sql
@@ -0,0 +1,8 @@
+/* postgres can not */
+USE plato;
+pragma DisableSimpleColumns;
+pragma yt.MapJoinLimit="1m";
+
+$subq = (SELECT CAST((CAST(subkey AS Int32) + 1) AS String) AS subkey_plus_one FROM Input);
+
+SELECT * FROM Input AS a JOIN $subq AS b ON a.subkey = b.subkey_plus_one order by subkey, key;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence-off.cfg
new file mode 100644
index 0000000000..03784127c6
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence-off.cfg
@@ -0,0 +1,6 @@
+in Input uniqkeys.txt
+in Dict1 sorted_uniq.txt
+in Dict2 sorted_uniq1.txt
+res result.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence.cfg
new file mode 100644
index 0000000000..eff6a05aeb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence.cfg
@@ -0,0 +1,4 @@
+in Input uniqkeys.txt
+in Dict1 sorted_uniq.txt
+in Dict2 sorted_uniq1.txt
+res result.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence.sql b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence.sql
new file mode 100644
index 0000000000..bd93d67218
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_sequence.sql
@@ -0,0 +1,13 @@
+/* postgres can not */
+USE plato;
+pragma DisableSimpleColumns;
+pragma yt.MapJoinLimit="1m";
+
+$subq = (SELECT key, CAST((CAST(subkey AS Int32) + 1) AS String) AS subkey_plus_one FROM Input);
+
+FROM $subq AS a
+JOIN Dict1 AS d1
+ON a.subkey_plus_one = d1.subkey
+JOIN Dict2 AS d2
+ON a.key = d2.key
+SELECT * ORDER BY a.key, a.subkey_plus_one;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star-off.cfg
new file mode 100644
index 0000000000..e76fa257e2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star-off.cfg
@@ -0,0 +1,4 @@
+in Input uniqkeys.txt
+res result.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star.cfg
new file mode 100644
index 0000000000..0e7b4058e1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star.cfg
@@ -0,0 +1,2 @@
+in Input uniqkeys.txt
+res result.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star.sql b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star.sql
new file mode 100644
index 0000000000..806a6ad8c9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_early_rewrite_star.sql
@@ -0,0 +1,9 @@
+/* postgres can not */
+USE plato;
+pragma DisableSimpleColumns;
+pragma yt.MapJoinLimit="1m";
+pragma yt.JoinEnableStarJoin="true";
+
+$subq = (SELECT CAST((CAST(subkey AS Int32) + 1) AS String) AS subkey_plus_one FROM Input);
+
+SELECT * FROM Input AS a JOIN $subq AS b ON a.subkey = b.subkey_plus_one order by subkey, key;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column.sql b/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column.sql
new file mode 100644
index 0000000000..df7b2ab987
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_left_null_column.sql
@@ -0,0 +1,11 @@
+/* syntax version 1 */
+/* postgres can not */
+
+PRAGMA yt.MapJoinLimit="1m";
+
+USE plato;
+
+$t = [<|"x":"150", "y":1, "z":Null|>, <|"x":"150", "y":2, "z":Null|>];
+
+SELECT * FROM Input1 AS a LEFT JOIN AS_TABLE($t) AS b ON a.key = b.x ORDER BY key, y;
+
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single-off.cfg
new file mode 100644
index 0000000000..c658c9ddb5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single-off.cfg
@@ -0,0 +1,3 @@
+in Input input6.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single.cfg
new file mode 100644
index 0000000000..684f1dbee4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single.cfg
@@ -0,0 +1 @@
+in Input input6.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single.sql b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single.sql
new file mode 100644
index 0000000000..518d33b511
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_non_optional_left_only_single.sql
@@ -0,0 +1,15 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+$t = [<|"key1":"1", "subkey1":"a", "key":"1", "subkey":"a", "value":"value2_1"|>, <|"key1":"4", "subkey1":"d", "key":"4", "subkey":"d", "value":"value2_4"|>, <|"key1":"-5", "subkey1":"e", "key":"-5", "subkey":"e", "value":"value2_5"|>];
+
+SELECT *
+FROM
+ Input AS A
+LEFT ONLY JOIN
+ AS_TABLE($t) AS B
+ON
+ AsTuple(A.key, AsTuple(A.subkey, A.subkey1)) = AsTuple(B.key, AsTuple(B.subkey, B.subkey1))
+ORDER BY `key`;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single-off.cfg
new file mode 100644
index 0000000000..440cd8b680
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single-off.cfg
@@ -0,0 +1,3 @@
+in Input input5.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single.cfg
new file mode 100644
index 0000000000..000848a05d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single.cfg
@@ -0,0 +1 @@
+in Input input5.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single.sql b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single.sql
new file mode 100644
index 0000000000..d6eab69ed8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_only_single.sql
@@ -0,0 +1,15 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+$t = [<|"key":"1", "subkey":"a", "value":"value2_1"|>, <|"key":"4", "subkey":"d", "value":"value2_4"|>, <|"key":"-5", "subkey":"e", "value":"value2_5"|>];
+
+SELECT *
+FROM
+ Input AS A
+LEFT ONLY JOIN
+ AS_TABLE($t) AS B
+ON
+ AsTuple(cast(A.key as uint64), cast(A.subkey as String)) = AsTuple(cast(B.key as int64), cast(B.subkey as Utf8))
+ORDER BY `key`;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many-off.cfg
new file mode 100644
index 0000000000..c658c9ddb5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many-off.cfg
@@ -0,0 +1,3 @@
+in Input input6.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many.cfg
new file mode 100644
index 0000000000..684f1dbee4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many.cfg
@@ -0,0 +1 @@
+in Input input6.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many.sql b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many.sql
new file mode 100644
index 0000000000..1175356b1d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_many.sql
@@ -0,0 +1,16 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+$t = [<|"key1":"1", "subkey1":"a", "key":"1", "subkey":"a", "value":"value2_1"|>, <|"key1":"4", "subkey1":"d", "key":"4", "subkey":"d", "value":"value2_4"|>, <|"key1":"-5", "subkey1":"e", "key":"-5", "subkey":"e", "value":"value2_5"|>];
+
+SELECT *
+FROM
+ Input AS A
+LEFT SEMI JOIN
+ AS_TABLE($t) AS B
+ON
+ AsTuple(cast(A.key as uint64), cast(A.subkey as String)) = AsTuple(cast(B.key as int64), cast(B.subkey as Utf8))
+ AND AsTuple(cast(A.key1 as uint64), cast(A.subkey1 as String)) = AsTuple(cast(B.key1 as int64), cast(B.subkey1 as Utf8))
+ORDER BY `key`;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single-off.cfg
new file mode 100644
index 0000000000..440cd8b680
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single-off.cfg
@@ -0,0 +1,3 @@
+in Input input5.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single.cfg
new file mode 100644
index 0000000000..000848a05d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single.cfg
@@ -0,0 +1 @@
+in Input input5.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single.sql b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single.sql
new file mode 100644
index 0000000000..959c476b80
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_complex_type_optional_left_semi_single.sql
@@ -0,0 +1,15 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+$t = [<|"key":"1", "subkey":"a", "value":"value2_1"|>, <|"key":"4", "subkey":"d", "value":"value2_4"|>, <|"key":"-5", "subkey":"e", "value":"value2_5"|>];
+
+SELECT *
+FROM
+ Input AS A
+LEFT SEMI JOIN
+ AS_TABLE($t) AS B
+ON
+ AsTuple(cast(A.key as uint64), cast(A.subkey as String)) = AsTuple(cast(B.key as int64), cast(B.subkey as Utf8))
+ORDER BY `key`;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord-off.cfg
new file mode 100644
index 0000000000..2dd54c12a3
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord-off.cfg
@@ -0,0 +1,5 @@
+in Input input4.txt
+res result.txt
+providers yt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord.cfg
new file mode 100644
index 0000000000..b4bb56a6bb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord.cfg
@@ -0,0 +1,3 @@
+in Input input4.txt
+res result.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord.sql b/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord.sql
new file mode 100644
index 0000000000..660b2d36b4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_tablerecord.sql
@@ -0,0 +1,10 @@
+use plato;
+pragma yt.MapJoinLimit="1M";
+
+$i = select TableRecordIndex() as ind, t.* from Input as t;
+$filter = select min(ind) as ind from $i group by subkey;
+
+select
+ *
+from Input
+where TableRecordIndex() in $filter;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type-off.cfg
new file mode 100644
index 0000000000..c658c9ddb5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type-off.cfg
@@ -0,0 +1,3 @@
+in Input input6.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type.cfg
new file mode 100644
index 0000000000..684f1dbee4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type.cfg
@@ -0,0 +1 @@
+in Input input6.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type.sql b/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type.sql
new file mode 100644
index 0000000000..2ee1b912b2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_on_very_complex_type.sql
@@ -0,0 +1,15 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+$t = [<|"key1":"1", "subkey1":"a", "key":"1", "subkey":"a", "value":"value2_1"|>, <|"key1":"4", "subkey1":"d", "key":"4", "subkey":"d", "value":"value2_4"|>, <|"key1":"-5", "subkey1":"e", "key":"-5", "subkey":"e", "value":"value2_5"|>];
+
+SELECT *
+FROM
+ Input AS A
+LEFT SEMI JOIN
+ AS_TABLE($t) AS B
+ON
+ AsTuple(A.subkey, AsTuple(A.subkey1, AsTuple(CAST(A.key AS Int64), CAST(A.key1 AS Uint64)))) = AsTuple(B.subkey, AsTuple(B.subkey1, AsTuple(CAST(B.key AS Uint64), CAST(B.key1 AS Int64))))
+ORDER BY `key`;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt.sql b/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt.sql
new file mode 100644
index 0000000000..73171384f0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_opt_vs_2xopt.sql
@@ -0,0 +1,23 @@
+use plato;
+
+pragma yt.MapJoinLimit="1m";
+
+$t1 = AsList(
+ AsStruct(Just(1) AS Key),
+ AsStruct(Just(2) AS Key),
+ AsStruct(Just(3) AS Key));
+
+$t2 = AsList(
+ AsStruct(Just(Just(2)) AS Key),
+ AsStruct(Just(Just(3)) AS Key),
+ AsStruct(Just(Just(4)) AS Key),
+ AsStruct(Just(Just(5)) AS Key),
+ AsStruct(Just(Just(6)) AS Key));
+
+insert into @t1 select * from as_table($t1);
+insert into @t2 select * from as_table($t2);
+
+commit;
+
+select *
+from @t1 as a join @t2 as b using(Key);
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys-off.cfg
new file mode 100644
index 0000000000..e76fa257e2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys-off.cfg
@@ -0,0 +1,4 @@
+in Input uniqkeys.txt
+res result.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys.cfg
new file mode 100644
index 0000000000..0e7b4058e1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys.cfg
@@ -0,0 +1,2 @@
+in Input uniqkeys.txt
+res result.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys.sql b/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys.sql
new file mode 100644
index 0000000000..2d152113e4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_partial_uniq_keys.sql
@@ -0,0 +1,18 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+/* kikimr can not */
+/* ignore runonopt plan diff */
+USE plato;
+pragma yt.MapJoinLimit="1m";
+
+-- YQL-5582
+$join = (select
+ a.key as key,
+ a.subkey as subkey,
+ a.value as value
+from (select * from Input where value > "bbb") as a
+left join Input as b
+on a.key = b.key);
+
+
+select count(*) from $join;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_sharded.sql b/yql/essentials/tests/sql/suites/join/mapjoin_sharded.sql
new file mode 100644
index 0000000000..e5af0c4509
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_sharded.sql
@@ -0,0 +1,13 @@
+use plato;
+
+/* postgres can not */
+/* kikimr can not */
+
+pragma DisableSimpleColumns;
+/* yt_local_var: MAP_JOIN_LIMIT = 30 */
+/* yqlrun_var: MAP_JOIN_LIMIT = 1000 */
+pragma yt.MapJoinLimit="MAP_JOIN_LIMIT";
+pragma yt.MapJoinShardCount = "10";
+
+select *
+from Input1 as a join Input2 as b on a.key = b.key and a.subkey = b.key;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_unused_keys.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_unused_keys.cfg
new file mode 100644
index 0000000000..9a930ffe48
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_unused_keys.cfg
@@ -0,0 +1,6 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_unused_keys.sql b/yql/essentials/tests/sql/suites/join/mapjoin_unused_keys.sql
new file mode 100644
index 0000000000..d574e50062
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_unused_keys.sql
@@ -0,0 +1,13 @@
+/* syntax version 1 */
+use plato;
+pragma yt.MapJoinLimit="1m";
+pragma yt.DisableOptimizers="PhysicalOptimizer-FuseInnerMap";
+
+select
+
+v3
+
+from Input1 as a
+join Input2 as b on (a.k1 = b.k2)
+join Input3 as c on (a.k1 = c.k3)
+order by v3;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous-off.cfg
new file mode 100644
index 0000000000..08630ad2c5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous-off.cfg
@@ -0,0 +1,4 @@
+in Input input1.txt
+res result.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous.cfg
new file mode 100644
index 0000000000..c8889a670f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous.cfg
@@ -0,0 +1,2 @@
+in Input input1.txt
+res result.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous.sql b/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous.sql
new file mode 100644
index 0000000000..0a6476fbda
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_anonymous.sql
@@ -0,0 +1,12 @@
+/* postgres can not */
+/* kikimr can not */
+use plato;
+pragma DisableSimpleColumns;
+
+pragma yt.MapJoinLimit="1m";
+
+insert into @tmp select * from Input where key > "100";
+commit;
+
+select * from Input as a
+left join @tmp as b on a.key = b.key;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read-off.cfg
new file mode 100644
index 0000000000..63f3b16e05
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read-off.cfg
@@ -0,0 +1,3 @@
+in Input input1.txt
+res result.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read.cfg
new file mode 100644
index 0000000000..5b34491eb1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read.cfg
@@ -0,0 +1,4 @@
+in Input input1.txt
+res result.txt
+providers yt
+
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read.sql b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read.sql
new file mode 100644
index 0000000000..eae0db98d5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_read.sql
@@ -0,0 +1,20 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+/* kikimr can not */
+use plato;
+pragma yt.mapjoinlimit="1m";
+
+$cnt = (select count(*) from Input);
+$offset = ($cnt + 10) ?? 0;
+
+$in1 = (select key from Input where key != "" order by key limit 10 offset $offset);
+
+select * from Input as a
+left join $in1 as b on a.key = b.key;
+
+$limit = ($cnt / 100) ?? 0;
+
+$in2 = (select key from Input where key != "" limit $limit);
+
+select * from Input as a
+left only join $in2 as b on a.key = b.key;
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct-off.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct-off.cfg
new file mode 100644
index 0000000000..08630ad2c5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct-off.cfg
@@ -0,0 +1,4 @@
+in Input input1.txt
+res result.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct.cfg b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct.cfg
new file mode 100644
index 0000000000..c8889a670f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct.cfg
@@ -0,0 +1,2 @@
+in Input input1.txt
+res result.txt
diff --git a/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct.sql b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct.sql
new file mode 100644
index 0000000000..c0fcc01374
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mapjoin_with_empty_struct.sql
@@ -0,0 +1,14 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+/* kikimr can not */
+/* ignore yt detailed plan diff */
+use plato;
+pragma yt.MapJoinLimit="10M";
+
+$sizes = (
+ SELECT
+ 0 AS id
+ FROM Input
+);
+
+SELECT d.key FROM Input as d CROSS JOIN $sizes as s ORDER BY d.key;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce-off.cfg
new file mode 100644
index 0000000000..489ecd7e4a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce-off.cfg
@@ -0,0 +1,3 @@
+in Input sorted_uniq2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce.cfg
new file mode 100644
index 0000000000..de96d331e1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce.cfg
@@ -0,0 +1 @@
+in Input sorted_uniq2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce.sql b/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce.sql
new file mode 100644
index 0000000000..bcd9751286
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_any_no_join_reduce.sql
@@ -0,0 +1,5 @@
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="2";
+
+select * from Input where key in (select "023" as key union all select "911" as key union all select "911" as key);
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_big_primary-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_big_primary.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_big_primary.sql b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary.sql
new file mode 100644
index 0000000000..a05dcc865c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+pragma yt.JoinMergeUseSmallAsPrimary="false";
+
+-- Input2 is smaller than Input1
+select * from Input1 as a join Input2 as b on a.k1 = b.k2
+order by a.v1, b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique-off.cfg
new file mode 100644
index 0000000000..e41a2c5556
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1_unique.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique.cfg
new file mode 100644
index 0000000000..c0114c4136
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1_unique.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique.sql b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique.sql
new file mode 100644
index 0000000000..79ac405416
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_big_primary_unique.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+pragma yt.JoinMergeUseSmallAsPrimary="false";
+
+-- Input2 is smaller than Input1, but Input1 has unique keys
+select * from Input1 as a join Input2 as b on a.k1 = b.k2 and a.v1 = b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary.sql b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary.sql
new file mode 100644
index 0000000000..97d4a93ea3
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+
+-- Input2 is smaller than Input1
+select * from Input1 as a join Input2 as b on a.k1 = b.k2
+order by a.v1, b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry.cfg
new file mode 100644
index 0000000000..23a3ae77d0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+pragma yt.ParallelOperationsLimit="1"
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry.sql b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry.sql
new file mode 100644
index 0000000000..aad534d5dd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_choose_primary_with_retry.sql
@@ -0,0 +1,12 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+
+-- emulate monsters in big table
+pragma yt.JoinMergeReduceJobMaxSize="1";
+
+-- Input2 is smaller than Input1
+select * from Input1 as a join Input2 as b on a.k1 = b.k2
+order by a.v1, b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align1-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_align1-off.cfg
new file mode 100644
index 0000000000..9299e9217a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align1-off.cfg
@@ -0,0 +1,3 @@
+providers yt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align1.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_align1.cfg
new file mode 100644
index 0000000000..bb349dd8ab
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align1.cfg
@@ -0,0 +1 @@
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align1.sql b/yql/essentials/tests/sql/suites/join/mergejoin_force_align1.sql
new file mode 100644
index 0000000000..3504fd3cf1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align1.sql
@@ -0,0 +1,26 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+pragma yt.JoinMergeTablesLimit="100";
+pragma yt.JoinMergeForce;
+
+insert into @t1
+select 1 as k1, 10 as v1;
+
+insert into @t2
+select 1u as k2, 100 as v2;
+
+insert into @t3
+select 1us as k3, 1000 as v3;
+
+insert into @t4
+select 1s as k4, 10000 as v4;
+
+commit;
+
+
+select * from (select * from @t1 as a join @t3 as c on a.k1 = c.k3) as ac
+ join (select * from @t2 as b join @t4 as d on b.k2 = d.k4) as bd on ac.k1 = bd.k2 and ac.k3 = bd.k4;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align2-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_align2-off.cfg
new file mode 100644
index 0000000000..9299e9217a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align2-off.cfg
@@ -0,0 +1,3 @@
+providers yt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align2.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_align2.cfg
new file mode 100644
index 0000000000..bb349dd8ab
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align2.cfg
@@ -0,0 +1 @@
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align2.sql b/yql/essentials/tests/sql/suites/join/mergejoin_force_align2.sql
new file mode 100644
index 0000000000..695adedf4a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align2.sql
@@ -0,0 +1,22 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+pragma yt.JoinMergeTablesLimit="100";
+
+insert into @t1
+select 1 as k1, 10 as v1;
+
+insert into @t2
+select 1u as k2, 100 as v2;
+
+insert into @t3
+select 1us as k3, 1000 as v3;
+
+commit;
+
+select * from @t2 as b
+ left join /*+ merge() */ @t3 as c on b.k2 = c.k3
+ left join @t1 as a on a.k1 = b.k2 and a.k1=c.k3;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align3-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_align3-off.cfg
new file mode 100644
index 0000000000..9299e9217a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align3-off.cfg
@@ -0,0 +1,3 @@
+providers yt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align3.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_align3.cfg
new file mode 100644
index 0000000000..bb349dd8ab
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align3.cfg
@@ -0,0 +1 @@
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_align3.sql b/yql/essentials/tests/sql/suites/join/mergejoin_force_align3.sql
new file mode 100644
index 0000000000..1cb847dd29
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_align3.sql
@@ -0,0 +1,19 @@
+/* syntax version 1 */
+/* postgres can not */
+
+USE plato;
+
+pragma yt.JoinMergeTablesLimit="100";
+pragma yt.JoinMergeForce;
+
+insert into @t1
+select (1, 1u) as k1, 100u as v1;
+
+insert into @t2
+select (1u, 1) as k2, 100 as v2;
+
+
+commit;
+
+select * from @t1 as a join @t2 as b on a.k1 = b.k2 and a.v1 = b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted.sql b/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted.sql
new file mode 100644
index 0000000000..a7cd554ffb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_no_sorted.sql
@@ -0,0 +1,5 @@
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeForce="true";
+
+select a.key as key from Input1 as a join Input2 as b using(key) order by key;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted-off.cfg
new file mode 100644
index 0000000000..644d022f87
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted-off.cfg
@@ -0,0 +1,4 @@
+in Input input1.txt
+in InputSorted sorted_uniq.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted.cfg
new file mode 100644
index 0000000000..a85b008cc0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted.cfg
@@ -0,0 +1,2 @@
+in Input input1.txt
+in InputSorted sorted_uniq.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted.sql b/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted.sql
new file mode 100644
index 0000000000..ad74c2340b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_one_sorted.sql
@@ -0,0 +1,6 @@
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeForce="true";
+pragma yt.JoinMergeUnsortedFactor="0";
+
+select a.key as key from InputSorted as a join Input as b using(key) order by key;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link-off.cfg
new file mode 100644
index 0000000000..7f40aa5617
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link-off.cfg
@@ -0,0 +1,6 @@
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+providers yt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link.cfg
new file mode 100644
index 0000000000..f22309ab5f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link.cfg
@@ -0,0 +1,4 @@
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link.sql b/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link.sql
new file mode 100644
index 0000000000..7a30768b9f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_force_per_link.sql
@@ -0,0 +1,18 @@
+/* syntax version 1 */
+/* postgres can not */
+
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+
+select
+ a.key as k1,
+ b.key as k2,
+ c.key as k3,
+ a.subkey as sk1,
+ b.subkey as sk2,
+ c.subkey as sk3
+from
+ Input1 as a join Input2 as b on a.key = b.key
+ join /*+ merge() */ Input3 as c on b.key = c.key
+order by k3
+;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_input1.txt b/yql/essentials/tests/sql/suites/join/mergejoin_input1.txt
new file mode 100644
index 0000000000..7ba5b163db
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_input1.txt
@@ -0,0 +1,20 @@
+{"PhraseID"=0u;"BaseNo"=53u;"Text"="julbo elara otg";};
+{"PhraseID"=0u;"BaseNo"=86u;"Text"="07644200";};
+{"PhraseID"=1u;"BaseNo"=1u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=2u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=3u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=4u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=5u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=6u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=7u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=8u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=9u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=10u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=11u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=12u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=13u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=14u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=15u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=16u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=17u;"Text"="julbo elara otg";};
+{"PhraseID"=1u;"BaseNo"=18u;"Text"="julbo elara otg";};
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_input1.txt.attr b/yql/essentials/tests/sql/suites/join/mergejoin_input1.txt.attr
new file mode 100644
index 0000000000..6a779223f1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_input1.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "PhraseID";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "uint64"
+ };
+ {
+ "name" = "BaseNo";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "uint16"
+ };
+ {
+ "name" = "Text";
+ "required" = %false;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_input2.txt b/yql/essentials/tests/sql/suites/join/mergejoin_input2.txt
new file mode 100644
index 0000000000..57ff5110b2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_input2.txt
@@ -0,0 +1,5 @@
+{"BannerID"=11830670;"ResultCost"=70000;"ResultFlatCost"=70000;"PhraseID"=0u;"BaseNo"=86u;};
+{"BannerID"=12963892;"ResultCost"=3000;"ResultFlatCost"=0;"PhraseID"=0u;"BaseNo"=53u;};
+{"BannerID"=12977828;"ResultCost"=3000;"ResultFlatCost"=0;"PhraseID"=1u;"BaseNo"=1u;};
+{"BannerID"=13005350;"ResultCost"=3000;"ResultFlatCost"=0;"PhraseID"=1u;"BaseNo"=3u;};
+{"BannerID"=14145807;"ResultCost"=3000;"ResultFlatCost"=0;"PhraseID"=1u;"BaseNo"=10u;};
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_input2.txt.attr b/yql/essentials/tests/sql/suites/join/mergejoin_input2.txt.attr
new file mode 100644
index 0000000000..1a5403e22b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_input2.txt.attr
@@ -0,0 +1,60 @@
+{
+ "_yql_row_spec" = {
+ "StrictSchema" = %true;
+ "Type" = [
+ "StructType";
+ [
+ [
+ "BannerID";
+ [
+ "OptionalType";
+ [
+ "DataType";
+ "Int64"
+ ]
+ ]
+ ];
+ [
+ "BaseNo";
+ [
+ "OptionalType";
+ [
+ "DataType";
+ "Uint16"
+ ]
+ ]
+ ];
+ [
+ "PhraseID";
+ [
+ "OptionalType";
+ [
+ "DataType";
+ "Uint64"
+ ]
+ ]
+ ];
+ [
+ "ResultCost";
+ [
+ "OptionalType";
+ [
+ "DataType";
+ "Int64"
+ ]
+ ]
+ ];
+ [
+ "ResultFlatCost";
+ [
+ "OptionalType";
+ [
+ "DataType";
+ "Int64"
+ ]
+ ]
+ ]
+ ]
+ ]
+ };
+}
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column-off.cfg
new file mode 100644
index 0000000000..0eb1ab8cde
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column-off.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted_by_kv1.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column.cfg
new file mode 100644
index 0000000000..fa48e4fa82
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column.cfg
@@ -0,0 +1 @@
+in Input1 sorted_by_kv1.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column.sql b/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column.sql
new file mode 100644
index 0000000000..1dd27bcc3a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_left_null_column.sql
@@ -0,0 +1,13 @@
+/* syntax version 1 */
+/* postgres can not */
+
+PRAGMA yt.JoinMergeTablesLimit="10";
+PRAGMA yt.JoinAllowColumnRenames="true";
+PRAGMA yt.JoinMergeUnsortedFactor="5.0";
+
+USE plato;
+
+$t = [<|"x":"bbb", "y":1, "z":Null|>, <|"x":"bbb", "y":2, "z":Null|>];
+
+SELECT * FROM Input1 AS a LEFT JOIN AS_TABLE($t) AS b ON a.k1 = b.x ORDER BY k1, y;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort-off.cfg
new file mode 100644
index 0000000000..a15ee3ce2e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort-off.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort.cfg
new file mode 100644
index 0000000000..4d81d34ed9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort.cfg
@@ -0,0 +1,3 @@
+in Input1 kv1_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort.sql b/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort.sql
new file mode 100644
index 0000000000..c5ddba7f1b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_narrows_output_sort.sql
@@ -0,0 +1,11 @@
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3";
+pragma yt.JoinAllowColumnRenames="true";
+pragma SimpleColumns;
+
+from Input3 as c
+join Input4 as d on c.k3 = d.k4
+right only join Input1 as a on a.k1 = c.k3 and a.v1 = c.v3
+select * order by u1
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort-off.cfg
new file mode 100644
index 0000000000..8e80f78742
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort-off.cfg
@@ -0,0 +1,4 @@
+in SortedByKey sorted_uniq.txt
+in SortedBySubkeyValue sorted_uniq1.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort.cfg
new file mode 100644
index 0000000000..ea9e6ce443
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort.cfg
@@ -0,0 +1,2 @@
+in SortedByKey sorted_uniq.txt
+in SortedBySubkeyValue sorted_uniq1.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort.sql b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort.sql
new file mode 100644
index 0000000000..24b8a2901b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort.sql
@@ -0,0 +1,42 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="0";
+pragma yt.JoinAllowColumnRenames="true";
+pragma yt.JoinMergeSetTopLevelFullSort="true";
+
+FROM SortedBySubkeyValue AS a INNER JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT b.key, a.subkey, a.value
+ORDER BY a.subkey, a.value, b.key;
+
+FROM SortedBySubkeyValue AS a RIGHT JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT b.key, a.subkey, a.value
+ORDER BY b.key;
+
+FROM SortedBySubkeyValue AS a LEFT JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT b.key, a.subkey, a.value
+ORDER BY a.subkey, a.value;
+
+FROM SortedBySubkeyValue AS a FULL JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT b.key, a.subkey, a.value
+ORDER BY b.key, a.subkey, a.value;
+
+FROM SortedBySubkeyValue AS a RIGHT ONLY JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT b.key
+ORDER BY b.key;
+
+FROM SortedBySubkeyValue AS a LEFT ONLY JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT a.subkey, a.value
+ORDER BY a.subkey, a.value;
+
+FROM SortedBySubkeyValue AS a EXCLUSION JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT b.key, a.subkey, a.value
+ORDER BY b.key, a.subkey, a.value;
+
+FROM SortedBySubkeyValue AS a RIGHT SEMI JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT b.key
+ORDER BY b.key;
+
+FROM SortedBySubkeyValue AS a LEFT SEMI JOIN SortedByKey AS b ON a.subkey = b.key
+SELECT a.subkey, a.value
+ORDER BY a.subkey, a.value;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross-off.cfg
new file mode 100644
index 0000000000..287d1fa1ed
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross-off.cfg
@@ -0,0 +1,5 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross.cfg
new file mode 100644
index 0000000000..88a5beef60
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross.sql b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross.sql
new file mode 100644
index 0000000000..8775257805
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_cross.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="0";
+pragma yt.JoinAllowColumnRenames="true";
+pragma yt.JoinMergeSetTopLevelFullSort="true";
+
+FROM Input1 AS a JOIN Input2 AS b ON b.k2 = a.k1
+ CROSS JOIN Input3 AS c
+SELECT c.k3 AS ck3, c.k3 AS ck3_extra, c.v3, a.k1 as ak1 ORDER BY ak1, ck3;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested-off.cfg
new file mode 100644
index 0000000000..7859898010
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested-off.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested.cfg
new file mode 100644
index 0000000000..086641db8d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested.cfg
@@ -0,0 +1,3 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested.sql b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested.sql
new file mode 100644
index 0000000000..3e01d0acda
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_nested.sql
@@ -0,0 +1,12 @@
+/* ignore yt detailed plan diff */
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="0";
+pragma yt.JoinAllowColumnRenames="true";
+
+FROM Input1 AS a JOIN Input2 AS b ON b.k2 = a.k1 AND a.v1 = b.v2
+ JOIN Input3 AS c ON a.k1 = c.k3 AND a.v1 = c.v3
+SELECT c.k3 AS ck3, c.k3 AS ck3_extra, c.k3 AS ck3_extra2, c.v3, a.k1 as ak1
+ORDER BY ck3, ck3_extra, ck3_extra2, c.v3 -- should be noop
+;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_unmatched.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_unmatched.cfg
new file mode 100644
index 0000000000..c13c3496d1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_unmatched.cfg
@@ -0,0 +1,3 @@
+in Input1 kv1_sorted1.txt
+in Input2 kv2_sorted1.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_unmatched.sql b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_unmatched.sql
new file mode 100644
index 0000000000..bc9b116f5d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_saves_output_sort_unmatched.sql
@@ -0,0 +1,11 @@
+/* ignore yt detailed plan diff */
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="0";
+pragma yt.JoinAllowColumnRenames="true";
+
+FROM Input1 AS a JOIN Input2 AS b ON b.k2 = a.k1 AND a.v1 = b.v2
+SELECT b.k2 AS bk2, b.v2 as bv2, a.k1 as ak1
+ORDER BY bv2 -- should be a separate sort
+;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner-off.cfg
new file mode 100644
index 0000000000..d2366da42e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner-off.cfg
@@ -0,0 +1,6 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner.cfg
new file mode 100644
index 0000000000..829b6d19f2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner.cfg
@@ -0,0 +1,4 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner.sql b/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner.sql
new file mode 100644
index 0000000000..4897e2737b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_semi_composite_to_inner.sql
@@ -0,0 +1,13 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3";
+pragma yt.JoinAllowColumnRenames="true";
+
+$semi = select * from Input3 as c join Input4 as d on c.k3 = d.k4;
+
+from $semi as semi
+right semi join Input1 as a on a.k1 = semi.k3 and a.v1 = semi.v3
+join Input2 as b on b.k2 = a.k1 and b.v2 = a.v1
+select * order by u1;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner-off.cfg
new file mode 100644
index 0000000000..aed2b8c61b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner-off.cfg
@@ -0,0 +1,4 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner.cfg
new file mode 100644
index 0000000000..6098eb907d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner.cfg
@@ -0,0 +1,2 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner.sql b/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner.sql
new file mode 100644
index 0000000000..3778d9f05b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_semi_to_inner.sql
@@ -0,0 +1,10 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="0";
+pragma yt.JoinAllowColumnRenames="true";
+
+from Input1 as a
+left semi join Input2 as b on a.k1 = b.k2 and a.v1 = b.v2
+select * order by u1
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_small_primary-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_small_primary-off.cfg
new file mode 100644
index 0000000000..1f7a620911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_small_primary-off.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_small_primary.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_small_primary.cfg
new file mode 100644
index 0000000000..df8cd9f2c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_small_primary.cfg
@@ -0,0 +1,2 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_small_primary.sql b/yql/essentials/tests/sql/suites/join/mergejoin_small_primary.sql
new file mode 100644
index 0000000000..be3ce895b1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_small_primary.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+pragma yt.JoinMergeUseSmallAsPrimary="true";
+
+-- Input2 is smaller than Input1
+select * from Input2 as b join Input1 as a on a.k1 = b.k2
+order by a.v1, b.v2;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_inner.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_inner.cfg
new file mode 100644
index 0000000000..1af5db027b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_inner.cfg
@@ -0,0 +1,3 @@
+providers yt
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_inner.sql b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_inner.sql
new file mode 100644
index 0000000000..86a76d3573
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_inner.sql
@@ -0,0 +1,15 @@
+/* ignore yt detailed plan diff */
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+
+$inner =
+ (FROM Input1 AS a JOIN Input2 AS b ON b.k2 = a.k1 AND a.v1 = b.v2
+ SELECT b.k2 AS bk2, b.k2 AS bk2_extra, b.v2 AS bv2, a.k1 as ak1);
+
+SELECT * FROM $inner ORDER BY bv2, bk2_extra;
+SELECT * FROM $inner ORDER BY bk2, bk2_extra, bv2;
+SELECT * FROM $inner ORDER BY bk2_extra, bv2;
+SELECT * FROM $inner ORDER BY bk2_extra;
+SELECT * FROM $inner ORDER BY ak1;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_left.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_left.cfg
new file mode 100644
index 0000000000..2de8793752
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_left.cfg
@@ -0,0 +1,3 @@
+providers yt
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_left.sql b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_left.sql
new file mode 100644
index 0000000000..16c281d696
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_left.sql
@@ -0,0 +1,14 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+
+$left =
+ (FROM Input1 AS a LEFT JOIN Input2 AS b ON b.k2 = a.k1
+ SELECT b.k2 AS bk2, b.k2 AS bk2_extra, b.v2 AS bv2, a.k1 as ak1);
+
+SELECT * FROM $left ORDER BY bv2, bk2_extra;
+SELECT * FROM $left ORDER BY bk2, bk2_extra, bv2;
+SELECT * FROM $left ORDER BY bk2_extra, bv2;
+SELECT * FROM $left ORDER BY bk2_extra;
+SELECT * FROM $left ORDER BY ak1;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_nomatch.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_nomatch.cfg
new file mode 100644
index 0000000000..2de8793752
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_nomatch.cfg
@@ -0,0 +1,3 @@
+providers yt
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_nomatch.sql b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_nomatch.sql
new file mode 100644
index 0000000000..ed613582c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_nomatch.sql
@@ -0,0 +1,8 @@
+/* ignore yt detailed plan diff */
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+
+FROM Input1 AS a JOIN Input2 AS b ON b.k2 = a.k1
+SELECT b.v2 AS bv2, a.k1 as ak1 ORDER BY ak1, bv2;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_right.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_right.cfg
new file mode 100644
index 0000000000..1af5db027b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_right.cfg
@@ -0,0 +1,3 @@
+providers yt
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_right.sql b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_right.sql
new file mode 100644
index 0000000000..2e4238f110
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_sorts_output_for_sort_right.sql
@@ -0,0 +1,14 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinAllowColumnRenames="true";
+
+$right =
+ (FROM Input1 AS a RIGHT JOIN Input2 AS b ON b.k2 = a.k1 AND a.v1 = b.v2
+ SELECT b.k2 AS bk2, b.k2 AS bk2_extra, b.v2 AS bv2, a.k1 as ak1, a.v1 as av1);
+
+SELECT * FROM $right ORDER BY bv2, bk2_extra;
+SELECT * FROM $right ORDER BY bk2, bk2_extra, bv2;
+SELECT * FROM $right ORDER BY bk2_extra, bv2;
+SELECT * FROM $right ORDER BY bk2_extra;
+SELECT * FROM $right ORDER BY ak1, av1;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_unused_keys.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_unused_keys.cfg
new file mode 100644
index 0000000000..9a930ffe48
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_unused_keys.cfg
@@ -0,0 +1,6 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_unused_keys.sql b/yql/essentials/tests/sql/suites/join/mergejoin_unused_keys.sql
new file mode 100644
index 0000000000..78bc056914
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_unused_keys.sql
@@ -0,0 +1,12 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+
+select
+
+v3
+
+from Input1 as a
+join Input2 as b on (a.k1 = b.k2)
+join Input3 as c on (a.k1 = c.k3)
+order by v3;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names-off.cfg
new file mode 100644
index 0000000000..8e80f78742
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names-off.cfg
@@ -0,0 +1,4 @@
+in SortedByKey sorted_uniq.txt
+in SortedBySubkeyValue sorted_uniq1.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names.cfg
new file mode 100644
index 0000000000..ea9e6ce443
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names.cfg
@@ -0,0 +1,2 @@
+in SortedByKey sorted_uniq.txt
+in SortedBySubkeyValue sorted_uniq1.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names.sql b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names.sql
new file mode 100644
index 0000000000..7fe038ad6a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names.sql
@@ -0,0 +1,19 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+pragma yt.JoinAllowColumnRenames="true";
+
+
+FROM SortedBySubkeyValue as a JOIN SortedByKey as b on a.subkey=b.key
+SELECT * ORDER BY a.subkey, b.key;
+
+FROM SortedBySubkeyValue as a JOIN SortedByKey as b on a.subkey=b.key
+SELECT a.subkey, b.key ORDER BY a.subkey, b.key;
+
+
+FROM SortedBySubkeyValue as a LEFT JOIN SortedByKey as b on a.subkey=b.key
+SELECT * ORDER BY a.subkey;
+
+FROM SortedBySubkeyValue as a RIGHT JOIN SortedByKey as b on a.subkey=b.key
+SELECT * ORDER BY b.key;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested-off.cfg
new file mode 100644
index 0000000000..5d2e73b721
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested-off.cfg
@@ -0,0 +1,5 @@
+in Input sorted_by_key1.txt
+in Input1 sorted_by_k1.txt
+in Input2 sorted_by_k2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested.cfg
new file mode 100644
index 0000000000..15fbfe10b8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested.cfg
@@ -0,0 +1,3 @@
+in Input sorted_by_key1.txt
+in Input1 sorted_by_k1.txt
+in Input2 sorted_by_k2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested.sql b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested.sql
new file mode 100644
index 0000000000..427553d99e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nested.sql
@@ -0,0 +1,11 @@
+/* ignore yt detailed plan diff */
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+pragma yt.JoinAllowColumnRenames="true";
+
+FROM Input AS a JOIN Input1 AS b ON b.k1=a.key
+ JOIN Input2 AS c ON a.key=c.k2
+SELECT a.value as avalue, b.v1, c.k2 as ck2 ORDER BY avalue, b.v1, ck2;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted-off.cfg
new file mode 100644
index 0000000000..ec195ece46
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted-off.cfg
@@ -0,0 +1,4 @@
+in Unsorted input2.txt
+in SortedBySubkeyValue sorted_uniq1.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted.cfg
new file mode 100644
index 0000000000..e049d17dbf
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted.cfg
@@ -0,0 +1,2 @@
+in Unsorted input2.txt
+in SortedBySubkeyValue sorted_uniq1.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted.sql b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted.sql
new file mode 100644
index 0000000000..d97fb38e04
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_nonsorted.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="100.0";
+pragma yt.JoinAllowColumnRenames="true";
+
+$unsorted = (SELECT key, CAST((CAST(subkey as Int32) + 2) as String) as sk, value as val FROM Unsorted);
+
+FROM SortedBySubkeyValue AS a JOIN $unsorted AS b ON a.subkey=b.sk AND a.value=b.val
+SELECT * ORDER BY a.key,b.key;
+
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename-off.cfg
new file mode 100644
index 0000000000..8e80f78742
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename-off.cfg
@@ -0,0 +1,4 @@
+in SortedByKey sorted_uniq.txt
+in SortedBySubkeyValue sorted_uniq1.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename.cfg
new file mode 100644
index 0000000000..ea9e6ce443
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename.cfg
@@ -0,0 +1,2 @@
+in SortedByKey sorted_uniq.txt
+in SortedBySubkeyValue sorted_uniq1.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename.sql b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename.sql
new file mode 100644
index 0000000000..07ad22faf7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_different_key_names_norename.sql
@@ -0,0 +1,19 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+pragma yt.JoinAllowColumnRenames="false";
+
+
+FROM SortedBySubkeyValue as a JOIN SortedByKey as b on a.subkey=b.key
+SELECT * ORDER BY a.subkey, b.key;
+
+FROM SortedBySubkeyValue as a JOIN SortedByKey as b on a.subkey=b.key
+SELECT a.subkey, b.key ORDER BY a.subkey, b.key;
+
+
+FROM SortedBySubkeyValue as a LEFT JOIN SortedByKey as b on a.subkey=b.key
+SELECT * ORDER BY a.subkey;
+
+FROM SortedBySubkeyValue as a RIGHT JOIN SortedByKey as b on a.subkey=b.key
+SELECT * ORDER BY b.key;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order-off.cfg
new file mode 100644
index 0000000000..01597c0916
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order-off.cfg
@@ -0,0 +1,4 @@
+in Input1 mergejoin_input1.txt
+in Input2 mergejoin_input2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order.cfg
new file mode 100644
index 0000000000..3ea969d8b4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order.cfg
@@ -0,0 +1,2 @@
+in Input1 mergejoin_input1.txt
+in Input2 mergejoin_input2.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order.sql b/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order.sql
new file mode 100644
index 0000000000..5cc0731682
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_reverse_key_order.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+
+SELECT pd.Text
+ FROM Input2 as m2
+ INNER JOIN Input1 as pd
+ USING (BaseNo, PhraseID)
+ORDER BY pd.Text;
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range-off.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range-off.cfg
new file mode 100644
index 0000000000..7dd23dd911
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range-off.cfg
@@ -0,0 +1,6 @@
+in Left1 sorted_by_key1.txt
+in Left2 sorted_by_key2.txt
+in Right1 sorted_by_key3.txt
+in Right2 sorted_by_key4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range.cfg b/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range.cfg
new file mode 100644
index 0000000000..5182327159
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range.cfg
@@ -0,0 +1,4 @@
+in Left1 sorted_by_key1.txt
+in Left2 sorted_by_key2.txt
+in Right1 sorted_by_key3.txt
+in Right2 sorted_by_key4.txt
diff --git a/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range.sql b/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range.sql
new file mode 100644
index 0000000000..95f96e883f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/mergejoin_with_table_range.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+
+SELECT *
+ FROM CONCAT("Left1", "Left2") as a
+ INNER JOIN CONCAT("Right1", "Right2") as b
+ USING(key)
+ORDER BY a.value,b.value;
+
diff --git a/yql/essentials/tests/sql/suites/join/nested_semi_join-off.cfg b/yql/essentials/tests/sql/suites/join/nested_semi_join-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nested_semi_join-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/nested_semi_join.cfg b/yql/essentials/tests/sql/suites/join/nested_semi_join.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nested_semi_join.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/nested_semi_join.sql b/yql/essentials/tests/sql/suites/join/nested_semi_join.sql
new file mode 100644
index 0000000000..f8b8277292
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nested_semi_join.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+use plato;
+
+$w1 = (select u.subkey as subkey, u.value as value from Input1 as u left semi join Input1 as v on u.key == v.key);
+
+$t1 = (select x.value from Input1 as x left semi join $w1 as y on x.subkey == y.subkey);
+
+select * from $t1;
diff --git a/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn-off.cfg b/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn-off.cfg
new file mode 100644
index 0000000000..893ac062c3
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn-off.cfg
@@ -0,0 +1,5 @@
+in Input1 empty_dynamic.txt
+in Input2 empty_dynamic.txt
+providers yt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn.cfg b/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn.cfg
new file mode 100644
index 0000000000..9b9c114a16
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn.cfg
@@ -0,0 +1,3 @@
+in Input1 empty_dynamic.txt
+in Input2 empty_dynamic.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn.sql b/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn.sql
new file mode 100644
index 0000000000..cb7b8b50d4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/no_empty_join_for_dyn.sql
@@ -0,0 +1,6 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+SELECT *
+FROM plato.Input1 as A
+INNER JOIN plato.Input2 as B
+ON A.key=B.key;
diff --git a/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner-off.cfg b/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner.cfg b/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner.sql b/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner.sql
new file mode 100644
index 0000000000..ed4f7c70ca
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nopushdown_filter_over_inner.sql
@@ -0,0 +1,6 @@
+/* postgres can not */
+PRAGMA DisableSimpleColumns;
+use plato;
+
+-- should not pushdown
+select * from Input1 as a inner join Input2 as b on a.key = b.key where Unwrap(cast(a.key as Int32)) > 100 order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on-off.cfg b/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on.cfg b/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on.sql b/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on.sql
new file mode 100644
index 0000000000..8e43238765
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/nopushdown_filter_with_depends_on.sql
@@ -0,0 +1,8 @@
+/* postgres can not */
+/* hybridfile can not */
+/* custom check: len(yt_res_yson[0]['Write'][0]['Data']) < 4 */
+use plato;
+
+-- should not pushdown
+select * from Input1 as a left semi join Input2 as b using(key) where Random(TableRow()) < 0.1 order by key;
+
diff --git a/yql/essentials/tests/sql/suites/join/opt_on_opt_side-off.cfg b/yql/essentials/tests/sql/suites/join/opt_on_opt_side-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/opt_on_opt_side-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/opt_on_opt_side.cfg b/yql/essentials/tests/sql/suites/join/opt_on_opt_side.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/opt_on_opt_side.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/opt_on_opt_side.sql b/yql/essentials/tests/sql/suites/join/opt_on_opt_side.sql
new file mode 100644
index 0000000000..f4abb9909e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/opt_on_opt_side.sql
@@ -0,0 +1,20 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+SELECT
+ A.key,
+ B.subkey
+FROM
+ Input2 AS A
+LEFT JOIN
+ (
+ SELECT
+ key,
+ CAST(key AS INT) AS subkey
+ FROM
+ Input3
+ ) AS B
+ON
+ A.key == B.key
+ORDER BY A.key
+;
diff --git a/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group-off.cfg b/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group.cfg b/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group.sql b/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group.sql
new file mode 100644
index 0000000000..f01cd2147d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/opt_on_opt_side_with_group.sql
@@ -0,0 +1,24 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+SELECT
+ A.key as key,
+ B.subkey,
+ COUNT(*) AS count
+FROM
+ Input2 AS A
+LEFT JOIN
+ (
+ SELECT
+ key,
+ CAST(key AS INT) AS subkey
+ FROM
+ Input3
+ ) AS B
+ON
+ A.key == B.key
+GROUP BY
+ A.key, B.subkey
+ORDER BY
+ key
+;
diff --git a/yql/essentials/tests/sql/suites/join/order_of_qualified-off.cfg b/yql/essentials/tests/sql/suites/join/order_of_qualified-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/order_of_qualified-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/order_of_qualified.cfg b/yql/essentials/tests/sql/suites/join/order_of_qualified.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/order_of_qualified.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/order_of_qualified.sql b/yql/essentials/tests/sql/suites/join/order_of_qualified.sql
new file mode 100644
index 0000000000..a28e3beaea
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/order_of_qualified.sql
@@ -0,0 +1,6 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+SELECT b.*,1 as q,a.*
+FROM Input2 AS a
+JOIN Input3 AS b
+ON a.value == b.value;
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_cross-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_cross-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_cross-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_cross.cfg b/yql/essentials/tests/sql/suites/join/premap_common_cross.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_cross.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_cross.sql b/yql/essentials/tests/sql/suites/join/premap_common_cross.sql
new file mode 100644
index 0000000000..2790c4a108
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_cross.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+from (select key as akey, subkey, value as avalue from Input1) as a
+cross join Input2 as b
+select a.akey, a.subkey, b.subkey, b.value
+order by a.akey, a.subkey, b.subkey, b.value;
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_inner-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner.cfg b/yql/essentials/tests/sql/suites/join/premap_common_inner.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner.sql b/yql/essentials/tests/sql/suites/join/premap_common_inner.sql
new file mode 100644
index 0000000000..eab52d0662
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+from (select key, subkey, 1 as value from Input1) as a
+join Input2 as b using(key)
+select a.key, a.subkey, a.value, b.value
+order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides.cfg b/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides.sql b/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides.sql
new file mode 100644
index 0000000000..7689cc7fa6
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner_both_sides.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+from (select key, subkey, 1 as value from Input1) as a
+join (select key, subkey, 2 as value from Input2) as b using(key)
+select a.key as key, a.subkey, a.value, b.subkey, b.value
+order by key;
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner_filter-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_inner_filter-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner_filter-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner_filter.cfg b/yql/essentials/tests/sql/suites/join/premap_common_inner_filter.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner_filter.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_inner_filter.sql b/yql/essentials/tests/sql/suites/join/premap_common_inner_filter.sql
new file mode 100644
index 0000000000..24d54e5f9c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_inner_filter.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+from (select key, subkey || key as subkey, value from Input1 where value != "ddd") as a
+join Input2 as b using(key)
+select a.key, a.subkey, b.value
+order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_left_cross-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_left_cross-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_left_cross-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_left_cross.cfg b/yql/essentials/tests/sql/suites/join/premap_common_left_cross.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_left_cross.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_left_cross.sql b/yql/essentials/tests/sql/suites/join/premap_common_left_cross.sql
new file mode 100644
index 0000000000..a7c8302df9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_left_cross.sql
@@ -0,0 +1,13 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+$one = (select key, 1 as subkey, value from Input1);
+$two = (select key, value from Input2);
+$three = (select key, value, 2 as subkey from Input3);
+
+from $one as a
+cross join $two as b
+left join $three as c on (c.key = a.key and c.value = b.value)
+select * order by a.key,a.subkey,b.key,b.value
+
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_multiparents-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_multiparents-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_multiparents-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_multiparents.cfg b/yql/essentials/tests/sql/suites/join/premap_common_multiparents.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_multiparents.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_multiparents.sql b/yql/essentials/tests/sql/suites/join/premap_common_multiparents.sql
new file mode 100644
index 0000000000..e31ee06f4e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_multiparents.sql
@@ -0,0 +1,15 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+$map = (select key, subkey, 1 as value, 2 as another from Input1);
+
+from $map as a
+join Input2 as b using(key)
+select a.key, a.value, b.value
+order by a.key,a.value;
+
+from $map as a
+join Input3 as b using(key)
+select a.key, a.value, a.subkey, b.value
+order by a.key,a.value;
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap.cfg b/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap.sql b/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap.sql
new file mode 100644
index 0000000000..e49c29fa42
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_multiparents_no_premap.sql
@@ -0,0 +1,14 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+$map = (select key, subkey, 1 as value, 2 as another from Input1);
+
+from $map as a
+join Input2 as b using(key)
+select a.key, a.value, b.value
+order by a.key,a.value;
+
+from $map as a
+select a.key, a.value, a.subkey
+order by a.key,a.value;
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent.cfg b/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent.sql b/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent.sql
new file mode 100644
index 0000000000..1bd47b60a0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_right_tablecontent.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+
+$keys = (select key from Input3);
+
+from (select key, value, key IN $keys as flag from Input1) as a
+right join (select key, key IN $keys as flag from Input2) as b using(key)
+select a.key, a.value, a.flag, b.flag
+order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_semi-off.cfg b/yql/essentials/tests/sql/suites/join/premap_common_semi-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_semi-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_semi.cfg b/yql/essentials/tests/sql/suites/join/premap_common_semi.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_semi.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_common_semi.sql b/yql/essentials/tests/sql/suites/join/premap_common_semi.sql
new file mode 100644
index 0000000000..343b8748b7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_common_semi.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+from (select key, subkey as asubkey, value from Input1) as a
+left semi join (select key, 1 as value from Input2) as b using(key)
+select a.key, a.asubkey
+order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/premap_context_dep-off.cfg b/yql/essentials/tests/sql/suites/join/premap_context_dep-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_context_dep-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_context_dep.cfg b/yql/essentials/tests/sql/suites/join/premap_context_dep.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_context_dep.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_context_dep.sql b/yql/essentials/tests/sql/suites/join/premap_context_dep.sql
new file mode 100644
index 0000000000..277a634626
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_context_dep.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+from (select key, subkey || key as subkey, value, TableRecordIndex() as tr from Input1) as a
+join Input2 as b using(key)
+select a.key, a.subkey, a.tr, b.value
+order by a.key, a.tr;
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_cross-off.cfg b/yql/essentials/tests/sql/suites/join/premap_map_cross-off.cfg
new file mode 100644
index 0000000000..287d1fa1ed
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_cross-off.cfg
@@ -0,0 +1,5 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_cross.cfg b/yql/essentials/tests/sql/suites/join/premap_map_cross.cfg
new file mode 100644
index 0000000000..88a5beef60
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_cross.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_cross.sql b/yql/essentials/tests/sql/suites/join/premap_map_cross.sql
new file mode 100644
index 0000000000..75ec5b34cf
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_cross.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+pragma yt.MapJoinLimit="1m";
+
+from (select k1, v1, Just(1) as u1 from Input1) as a
+cross join (select k2, v2, Just(2) as u2 from Input2) as b
+select *
+order by a.k1,b.k2,a.v1,b.v2;
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_inner-off.cfg b/yql/essentials/tests/sql/suites/join/premap_map_inner-off.cfg
new file mode 100644
index 0000000000..287d1fa1ed
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_inner-off.cfg
@@ -0,0 +1,5 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_inner.cfg b/yql/essentials/tests/sql/suites/join/premap_map_inner.cfg
new file mode 100644
index 0000000000..88a5beef60
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_inner.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_inner.sql b/yql/essentials/tests/sql/suites/join/premap_map_inner.sql
new file mode 100644
index 0000000000..737b8a2de0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_inner.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+pragma yt.MapJoinLimit="1m";
+
+from (select k1, v1 as u1 from Input1) as a
+join (select k2, v2 as u2 from Input2) as b on a.k1 = b.k2
+select a.k1,a.u1,b.u2
+order by a.k1,a.u1;
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_semi-off.cfg b/yql/essentials/tests/sql/suites/join/premap_map_semi-off.cfg
new file mode 100644
index 0000000000..287d1fa1ed
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_semi-off.cfg
@@ -0,0 +1,5 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_semi.cfg b/yql/essentials/tests/sql/suites/join/premap_map_semi.cfg
new file mode 100644
index 0000000000..88a5beef60
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_semi.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_map_semi.sql b/yql/essentials/tests/sql/suites/join/premap_map_semi.sql
new file mode 100644
index 0000000000..c8ea1a1ef8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_map_semi.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+pragma yt.MapJoinLimit="1m";
+
+from (select k1, v1 || u1 as v1 from Input1) as a
+left semi join (select k2, u2 || v2 as u2 from Input2) as b on a.k1 = b.k2
+select *
+order by a.k1,a.v1;
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1-off.cfg b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1-off.cfg
new file mode 100644
index 0000000000..01597c0916
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1-off.cfg
@@ -0,0 +1,4 @@
+in Input1 mergejoin_input1.txt
+in Input2 mergejoin_input2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1.cfg b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1.cfg
new file mode 100644
index 0000000000..3ea969d8b4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1.cfg
@@ -0,0 +1,2 @@
+in Input1 mergejoin_input1.txt
+in Input2 mergejoin_input2.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1.sql b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1.sql
new file mode 100644
index 0000000000..46cc25e42e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort1.sql
@@ -0,0 +1,12 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+
+
+SELECT pd.Text, pd.PhraseID, m2.BaseNo
+ FROM Input2 as m2
+ INNER JOIN (select PhraseID, BaseNo, True as Text from Input1) as pd
+ USING (BaseNo, PhraseID)
+ORDER BY pd.PhraseID, m2.BaseNo;
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2-off.cfg b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2-off.cfg
new file mode 100644
index 0000000000..01597c0916
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2-off.cfg
@@ -0,0 +1,4 @@
+in Input1 mergejoin_input1.txt
+in Input2 mergejoin_input2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2.cfg b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2.cfg
new file mode 100644
index 0000000000..3ea969d8b4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2.cfg
@@ -0,0 +1,2 @@
+in Input1 mergejoin_input1.txt
+in Input2 mergejoin_input2.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2.sql b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2.sql
new file mode 100644
index 0000000000..b8d4f8e5f3
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_extrasort2.sql
@@ -0,0 +1,12 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+
+
+SELECT pd.Text, m2.BannerID
+ FROM (select BaseNo, PhraseID, 100 as BannerID from Input2) as m2
+ INNER JOIN (select PhraseID, BaseNo, 999 as Text from Input1) as pd
+ USING (BaseNo, PhraseID)
+ORDER BY pd.Text, m2.BannerID;
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_inner-off.cfg b/yql/essentials/tests/sql/suites/join/premap_merge_inner-off.cfg
new file mode 100644
index 0000000000..287d1fa1ed
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_inner-off.cfg
@@ -0,0 +1,5 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_inner.cfg b/yql/essentials/tests/sql/suites/join/premap_merge_inner.cfg
new file mode 100644
index 0000000000..88a5beef60
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_inner.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv2.txt
+in Input3 sorted_by_kv3.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_inner.sql b/yql/essentials/tests/sql/suites/join/premap_merge_inner.sql
new file mode 100644
index 0000000000..2557b94ac4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_inner.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+
+from (select k1, v1 as u1 from Input1) as a
+join (select k2, v2 as u2 from Input2) as b on a.k1 = b.k2
+select a.k1,a.u1,b.u2
+order by a.k1,a.u1;
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_with_remap-off.cfg b/yql/essentials/tests/sql/suites/join/premap_merge_with_remap-off.cfg
new file mode 100644
index 0000000000..01597c0916
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_with_remap-off.cfg
@@ -0,0 +1,4 @@
+in Input1 mergejoin_input1.txt
+in Input2 mergejoin_input2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_with_remap.cfg b/yql/essentials/tests/sql/suites/join/premap_merge_with_remap.cfg
new file mode 100644
index 0000000000..3ea969d8b4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_with_remap.cfg
@@ -0,0 +1,2 @@
+in Input1 mergejoin_input1.txt
+in Input2 mergejoin_input2.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_merge_with_remap.sql b/yql/essentials/tests/sql/suites/join/premap_merge_with_remap.sql
new file mode 100644
index 0000000000..6a582ffa76
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_merge_with_remap.sql
@@ -0,0 +1,17 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+pragma yt.JoinMergeTablesLimit="10";
+pragma yt.JoinMergeUnsortedFactor="3.0";
+
+INSERT INTO @inp2
+SELECT * FROM Input2
+ORDER BY BaseNo DESC;
+
+COMMIT;
+
+SELECT pd.BaseNo, m2.PhraseID, m2.Extra
+ FROM Input1 as pd
+ LEFT JOIN (select BaseNo, PhraseID, 1 as Extra from @inp2) as m2
+ USING (BaseNo, PhraseID)
+ORDER BY pd.BaseNo, m2.PhraseID, m2.Extra;
diff --git a/yql/essentials/tests/sql/suites/join/premap_no_premap-off.cfg b/yql/essentials/tests/sql/suites/join/premap_no_premap-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_no_premap-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_no_premap.cfg b/yql/essentials/tests/sql/suites/join/premap_no_premap.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_no_premap.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_no_premap.sql b/yql/essentials/tests/sql/suites/join/premap_no_premap.sql
new file mode 100644
index 0000000000..533fa758ce
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_no_premap.sql
@@ -0,0 +1,27 @@
+PRAGMA DisableSimpleColumns;
+PRAGMA DisablePullUpFlatMapOverJoin;
+use plato;
+
+-- not renaming
+from (select key, subkey || key as subkey, value from Input1) as a
+join Input2 as b using(key)
+select a.key, a.subkey, b.value
+order by a.key;
+
+-- not fixed size
+from (select key, "aaa" as subkey, value from Input1) as a
+join Input2 as b using(key)
+select a.key, a.subkey, b.value
+order by a.key;
+
+-- to many Justs
+from (select key, Just(Just(1)) as subkey, value from Input1) as a
+join Input2 as b using(key)
+select a.key, a.subkey, b.value
+order by a.key;
+
+-- container
+from (select key, AsTuple(1) as subkey, value from Input1) as a
+join Input2 as b using(key)
+select a.key, a.subkey, b.value
+order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap-off.cfg b/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap.cfg b/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap.sql b/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap.sql
new file mode 100644
index 0000000000..0163d931ba
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/premap_nonseq_flatmap.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+$hashes = (
+ SELECT multiplier AS hash
+ FROM (SELECT ListFromRange(0, 3) AS multiplier)
+ FLATTEN BY multiplier
+);
+
+SELECT * FROM Input1 AS a CROSS JOIN $hashes AS h
+ORDER BY a.key,a.subkey,h.hash;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_context_dep-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_context_dep-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_context_dep-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_context_dep.cfg b/yql/essentials/tests/sql/suites/join/pullup_context_dep.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_context_dep.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_context_dep.sql b/yql/essentials/tests/sql/suites/join/pullup_context_dep.sql
new file mode 100644
index 0000000000..5c8b94fc25
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_context_dep.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key, subkey || key as subkey, value, TablePath() as tp from Input1) as a
+join Input2 as b using(key)
+select a.key, a.subkey, a.tp, b.value
+order by a.key, a.tp;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_cross-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_cross-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_cross-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_cross.cfg b/yql/essentials/tests/sql/suites/join/pullup_cross.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_cross.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_cross.sql b/yql/essentials/tests/sql/suites/join/pullup_cross.sql
new file mode 100644
index 0000000000..7b5f75f0ba
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_cross.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key, subkey || key as subkey, value || "v" as value from Input1) as a
+cross join Input2 as b
+select a.key, a.subkey, b.subkey, b.value
+order by a.key, a.subkey, b.subkey, b.value;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_exclusion-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_exclusion-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_exclusion-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_exclusion.cfg b/yql/essentials/tests/sql/suites/join/pullup_exclusion.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_exclusion.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_exclusion.sql b/yql/essentials/tests/sql/suites/join/pullup_exclusion.sql
new file mode 100644
index 0000000000..b865107bbf
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_exclusion.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key, subkey || key as subkey, value from Input1) as a
+exclusion join (select key || subkey as subkey, key, 1 as value from Input2) as b on a.key = b.key
+select a.key as akey, b.key as bkey, a.subkey, b.subkey, b.value
+order by akey;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_inner-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_inner-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_inner-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_inner.cfg b/yql/essentials/tests/sql/suites/join/pullup_inner.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_inner.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_inner.sql b/yql/essentials/tests/sql/suites/join/pullup_inner.sql
new file mode 100644
index 0000000000..097302e12e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_inner.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key, subkey || key as subkey, value from Input1) as a
+join (select key || subkey as subkey, key, 1 as value from Input2) as b on a.key = b.key
+select a.key as akey, b.key as bkey, a.subkey, b.subkey, b.value
+order by akey;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_left-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_left-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_left-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_left.cfg b/yql/essentials/tests/sql/suites/join/pullup_left.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_left.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_left.sql b/yql/essentials/tests/sql/suites/join/pullup_left.sql
new file mode 100644
index 0000000000..1784fea6cc
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_left.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key, subkey || key as subkey, value from Input1) as a
+left join (select key || subkey as subkey, key, 1 as value from Input2) as b on a.key = b.key
+select a.key as akey, b.key as bkey, a.subkey, b.subkey, b.value
+order by akey;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_left_semi-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_left_semi-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_left_semi-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_left_semi.cfg b/yql/essentials/tests/sql/suites/join/pullup_left_semi.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_left_semi.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_left_semi.sql b/yql/essentials/tests/sql/suites/join/pullup_left_semi.sql
new file mode 100644
index 0000000000..feeec671b6
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_left_semi.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key, subkey || key as subkey, value from Input1) as a
+left semi join (select key || subkey as subkey, key, 1 as value from Input2) as b on a.key = b.key
+select a.key as akey, a.subkey
+order by akey;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_null_column-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_null_column-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_null_column-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_null_column.cfg b/yql/essentials/tests/sql/suites/join/pullup_null_column.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_null_column.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_null_column.sql b/yql/essentials/tests/sql/suites/join/pullup_null_column.sql
new file mode 100644
index 0000000000..d7a5c88783
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_null_column.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from Input1 as a
+left join (select key, null as subkey, 1 as value from Input2) as b on a.key = b.key
+select a.key as akey, b.key as bkey, a.subkey, b.subkey, b.value
+order by akey;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_random-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_random-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_random-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_random.cfg b/yql/essentials/tests/sql/suites/join/pullup_random.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_random.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_random.sql b/yql/essentials/tests/sql/suites/join/pullup_random.sql
new file mode 100644
index 0000000000..f884b2d8fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_random.sql
@@ -0,0 +1,8 @@
+/* kikimr can not - due to random */
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key, subkey || key as subkey, value, RANDOM(value || "x") <= 1.0 as rn from Input1) as a
+join Input2 as b using(key)
+select a.key, a.subkey, a.rn, b.value
+order by a.key, a.rn;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_renaming-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_renaming-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_renaming-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_renaming.cfg b/yql/essentials/tests/sql/suites/join/pullup_renaming.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_renaming.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_renaming.sql b/yql/essentials/tests/sql/suites/join/pullup_renaming.sql
new file mode 100644
index 0000000000..0f13acd39f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_renaming.sql
@@ -0,0 +1,8 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key as akey1, key as akey2, subkey || key as subkey, value from Input1) as a
+left join (select key || subkey as subkey, key as bkey1, key as bkey2, 1 as value from Input2) as b
+on a.akey1 = b.bkey1 and a.akey1 = b.bkey2 and a.akey2 = b.bkey1
+select a.akey1 as akey1, b.bkey1 as bkey1, a.subkey, b.subkey, b.value
+order by akey1, bkey1;
diff --git a/yql/essentials/tests/sql/suites/join/pullup_rownumber-off.cfg b/yql/essentials/tests/sql/suites/join/pullup_rownumber-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_rownumber-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pullup_rownumber.cfg b/yql/essentials/tests/sql/suites/join/pullup_rownumber.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_rownumber.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pullup_rownumber.sql b/yql/essentials/tests/sql/suites/join/pullup_rownumber.sql
new file mode 100644
index 0000000000..a40f65b939
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pullup_rownumber.sql
@@ -0,0 +1,7 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from (select key, subkey || key as subkey, value, ROW_NUMBER() over w as rn from Input1 window w as ()) as a
+join Input2 as b using(key)
+select a.key, a.subkey, a.rn, b.value
+order by a.key, a.rn;
diff --git a/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict-off.cfg b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict.cfg b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict.sql b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict.sql
new file mode 100644
index 0000000000..e6fd2ce9af
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_assume_strict.sql
@@ -0,0 +1,6 @@
+/* postgres can not */
+PRAGMA DisableSimpleColumns;
+use plato;
+
+-- should pushdown
+select * from Input1 as a inner join Input2 as b on a.key = b.key where AssumeStrict(Unwrap(cast(a.key as Int32))) > 100 order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_strict_udf.cfg b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_strict_udf.cfg
new file mode 100644
index 0000000000..75143a2d4b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_strict_udf.cfg
@@ -0,0 +1,3 @@
+in Input1 input1.txt
+in Input2 input2.txt
+udf math_udf
diff --git a/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_strict_udf.sql b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_strict_udf.sql
new file mode 100644
index 0000000000..12ab5e8f6d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_inner_with_strict_udf.sql
@@ -0,0 +1,6 @@
+/* postgres can not */
+PRAGMA DisableSimpleColumns;
+use plato;
+
+-- should pushdown
+select * from Input1 as a inner join Input2 as b on a.key = b.key where Math::IsFinite(cast(a.key as Double)) order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left-off.cfg b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left.cfg b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left.sql b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left.sql
new file mode 100644
index 0000000000..d5b8567576
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/pushdown_filter_over_left.sql
@@ -0,0 +1,6 @@
+/* postgres can not */
+PRAGMA DisableSimpleColumns;
+use plato;
+
+-- should pushdown
+select * from Input1 as a left join Input2 as b on a.key = b.key where Unwrap(cast(a.key as Int32)) > 100 order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/right_trivial-off.cfg b/yql/essentials/tests/sql/suites/join/right_trivial-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/right_trivial-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/right_trivial.cfg b/yql/essentials/tests/sql/suites/join/right_trivial.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/right_trivial.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/right_trivial.sql b/yql/essentials/tests/sql/suites/join/right_trivial.sql
new file mode 100644
index 0000000000..d63d52b615
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/right_trivial.sql
@@ -0,0 +1,5 @@
+PRAGMA DisableSimpleColumns;
+select coalesce(Input1.key, "_null") as a, coalesce(Input1.subkey, "_null") as b, coalesce(Input3.value, "_null") as c
+from plato.Input1
+right join plato.Input3 using (key)
+order by a, b, c; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/root.txt b/yql/essentials/tests/sql/suites/join/root.txt
new file mode 100644
index 0000000000..fc60ef431f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/root.txt
@@ -0,0 +1,20 @@
+{"key"=023u;"leaf"=3u;"branch"=10u;"value"="xxx"};
+{"key"=037u;"leaf"=5u;"branch"=#;"value"="ddd"};
+{"key"=075u;"leaf"=1u;"branch"=#;"value"="abc"};
+{"key"=150u;"leaf"=1u;"branch"=19u;"value"="aaa"};
+{"key"=150u;"leaf"=#;"branch"=18u;"value"="iii"};
+{"key"=150u;"leaf"=8u;"branch"=12u;"value"="zzz"};
+{"key"=200u;"leaf"=7u;"branch"=11u;"value"=#};
+{"key"=200u;"leaf"=7u;"branch"=11u;"value"=#};
+{"key"=666u;"leaf"=#;"branch"=#;"value"="bad"};
+{"key"=777u;"leaf"=2u;"branch"=#;"value"="lol"};
+{"key"=888u;"leaf"=#;"branch"=14u;"value"="dad"};
+{"key"=527u;"leaf"=#;"branch"=11u;"value"="bbb"};
+{"key"=761u;"leaf"=6u;"branch"=13u;"value"="ccc"};
+{"key"=911u;"leaf"=#;"branch"=17u;"value"=#};
+{"key"=999u;"leaf"=90u;"branch"=10u;"value"="not"};
+{"key"=090u;"leaf"=4u;"branch"=15u;"value"="ups"};
+{"key"=090u;"leaf"=4u;"branch"=15u;"value"="ups"};
+{"key"=111u;"leaf"=100u;"branch"=19u;"value"="jjj"};
+{"key"=222u;"leaf"=9u;"branch"=100u;"value"="ttt"};
+{"key"=000u;"leaf"=100u;"branch"=100u;"value"="000"};
diff --git a/yql/essentials/tests/sql/suites/join/root.txt.attr b/yql/essentials/tests/sql/suites/join/root.txt.attr
new file mode 100644
index 0000000000..8cfa8bc1a9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/root.txt.attr
@@ -0,0 +1,8 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"Uint64"]];
+ ["leaf";["OptionalType";["DataType";"Uint64"]]];
+ ["branch";["OptionalType";["DataType";"Uint64"]]];
+ ["value";["OptionalType";["DataType";"String"]]]]
+ ];
+}}
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted-off.cfg b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted-off.cfg
new file mode 100644
index 0000000000..579f91d547
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted-off.cfg
@@ -0,0 +1,4 @@
+in Input sorted_uniq.txt
+
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted.cfg b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted.cfg
new file mode 100644
index 0000000000..e6665422d5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted.cfg
@@ -0,0 +1,2 @@
+in Input sorted_uniq.txt
+
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted.sql b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted.sql
new file mode 100644
index 0000000000..dc33eadc98
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select * from plato.Input as a inner join plato.Input as b on a.key = b.key;
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter-off.cfg b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter-off.cfg
new file mode 100644
index 0000000000..579f91d547
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter-off.cfg
@@ -0,0 +1,4 @@
+in Input sorted_uniq.txt
+
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter-replicate.cfg b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter-replicate.cfg
new file mode 100644
index 0000000000..1aa0bdd86e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter-replicate.cfg
@@ -0,0 +1,6 @@
+in Input sorted_uniq.txt
+
+providers dq
+pragma dq.HashJoinMode="off";
+pragma dq.SplitStageOnDqReplicate="false";
+pragma dq.SpillingEngine="disable";
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter.cfg b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter.cfg
new file mode 100644
index 0000000000..e6665422d5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter.cfg
@@ -0,0 +1,2 @@
+in Input sorted_uniq.txt
+
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter.sql b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter.sql
new file mode 100644
index 0000000000..7134d1c830
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_filter.sql
@@ -0,0 +1,4 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+$in = (select * from plato.Input where key > "100");
+select * from $in as a inner join $in as b on a.key = b.key;
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename-off.cfg b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename-off.cfg
new file mode 100644
index 0000000000..579f91d547
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename-off.cfg
@@ -0,0 +1,4 @@
+in Input sorted_uniq.txt
+
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename.cfg b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename.cfg
new file mode 100644
index 0000000000..e6665422d5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename.cfg
@@ -0,0 +1,2 @@
+in Input sorted_uniq.txt
+
diff --git a/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename.sql b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename.sql
new file mode 100644
index 0000000000..51746196d6
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/selfjoin_on_sorted_with_rename.sql
@@ -0,0 +1,2 @@
+PRAGMA DisableSimpleColumns;
+select a.key as key, b.subkey as subkey, b.value as value from plato.Input as a inner join plato.Input as b on a.key = b.key;
diff --git a/yql/essentials/tests/sql/suites/join/simple_columns_partial-off.cfg b/yql/essentials/tests/sql/suites/join/simple_columns_partial-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/simple_columns_partial-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/simple_columns_partial.cfg b/yql/essentials/tests/sql/suites/join/simple_columns_partial.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/simple_columns_partial.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/simple_columns_partial.sql b/yql/essentials/tests/sql/suites/join/simple_columns_partial.sql
new file mode 100644
index 0000000000..da45ff2766
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/simple_columns_partial.sql
@@ -0,0 +1,23 @@
+/* postgres can not */
+use plato;
+pragma SimpleColumns;
+
+SELECT *
+FROM `Input2` AS a
+LEFT SEMI JOIN `Input3` AS b
+ON a.value == b.value;
+
+SELECT *
+FROM `Input2` AS a
+LEFT ONLY JOIN `Input3` AS b
+ON a.value == b.value;
+
+SELECT *
+FROM `Input2` AS a
+RIGHT SEMI JOIN `Input3` AS b
+ON a.value == b.value;
+
+SELECT *
+FROM `Input2` AS a
+RIGHT ONLY JOIN `Input3` AS b
+ON a.value == b.value;
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_k1.txt b/yql/essentials/tests/sql/suites/join/sorted_by_k1.txt
new file mode 100644
index 0000000000..5da1f87a4d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_k1.txt
@@ -0,0 +1,3 @@
+{"k1"="bbb";"v1"="v11"};
+{"k1"="ccc";"v1"="v12"};
+{"k1"="ddd";"v1"="v13"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_k1.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_k1.txt.attr
new file mode 100644
index 0000000000..9cef99eb90
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_k1.txt.attr
@@ -0,0 +1,19 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_k2.txt b/yql/essentials/tests/sql/suites/join/sorted_by_k2.txt
new file mode 100644
index 0000000000..96a4c1b787
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_k2.txt
@@ -0,0 +1,3 @@
+{"k2"="ccc";"v2"="v21"};
+{"k2"="ddd";"v2"="v22"};
+{"k2"="eee";"v2"="v23"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_k2.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_k2.txt.attr
new file mode 100644
index 0000000000..39faeeb22c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_k2.txt.attr
@@ -0,0 +1,19 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v2";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key1.txt b/yql/essentials/tests/sql/suites/join/sorted_by_key1.txt
new file mode 100644
index 0000000000..6a547a4465
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key1.txt
@@ -0,0 +1,3 @@
+{"key"="aaa";"value"="a11"};
+{"key"="bbb";"value"="a12"};
+{"key"="ccc";"value"="a13"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key1.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_key1.txt.attr
new file mode 100644
index 0000000000..852ba949fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key1.txt.attr
@@ -0,0 +1,19 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "key";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "value";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key2.txt b/yql/essentials/tests/sql/suites/join/sorted_by_key2.txt
new file mode 100644
index 0000000000..f902c54666
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key2.txt
@@ -0,0 +1,3 @@
+{"key"="bbb";"value"="a21"};
+{"key"="ccc";"value"="a22"};
+{"key"="ddd";"value"="a23"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key2.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_key2.txt.attr
new file mode 100644
index 0000000000..852ba949fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key2.txt.attr
@@ -0,0 +1,19 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "key";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "value";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key3.txt b/yql/essentials/tests/sql/suites/join/sorted_by_key3.txt
new file mode 100644
index 0000000000..57cd6157f9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key3.txt
@@ -0,0 +1,3 @@
+{"key"="aaa";"value"="b11"};
+{"key"="ccc";"value"="b12"};
+{"key"="ddd";"value"="b13"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key3.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_key3.txt.attr
new file mode 100644
index 0000000000..852ba949fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key3.txt.attr
@@ -0,0 +1,19 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "key";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "value";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key4.txt b/yql/essentials/tests/sql/suites/join/sorted_by_key4.txt
new file mode 100644
index 0000000000..27a6a9b1bd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key4.txt
@@ -0,0 +1,3 @@
+{"key"="ccc";"value"="b21"};
+{"key"="ddd";"value"="b22"};
+{"key"="eee";"value"="b23"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key4.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_key4.txt.attr
new file mode 100644
index 0000000000..852ba949fb
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key4.txt.attr
@@ -0,0 +1,19 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "key";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "value";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key_subkey.txt b/yql/essentials/tests/sql/suites/join/sorted_by_key_subkey.txt
new file mode 100644
index 0000000000..0eca8aa4bd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key_subkey.txt
@@ -0,0 +1,3 @@
+{"key"="aaa";"subkey"="bbb";"value"="ks1"};
+{"key"="bbb";"subkey"="bbb";"value"="ks2"};
+{"key"="bbb";"subkey"="ccc";"value"="ks3"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_key_subkey.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_key_subkey.txt.attr
new file mode 100644
index 0000000000..1752b0ee6d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_key_subkey.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "key";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "subkey";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "value";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv1.txt
new file mode 100644
index 0000000000..d8ba8879fe
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1.txt
@@ -0,0 +1,4 @@
+{"k1"="aaa";"v1"="v11";"u1"="u11"};
+{"k1"="bbb";"v1"="v12";"u1"="u12"};
+{"k1"="ccc";"v1"="v13";"u1"="u13"};
+{"k1"="ddd";"v1"="v14";"u1"="u14"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv1.txt.attr
new file mode 100644
index 0000000000..4185224ec0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1_1.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_1.txt
new file mode 100644
index 0000000000..7d1d077ae0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_1.txt
@@ -0,0 +1,10 @@
+{"k1"="aaa";"v1"="v11";"u1"="u11"};
+{"k1"="bbb";"v1"="v12";"u1"="u12"};
+{"k1"="ccc";"v1"="v13";"u1"="u13"};
+{"k1"="ddd";"v1"="v14";"u1"="u14"};
+{"k1"="eee";"v1"="v15";"u1"="u15"};
+{"k1"="fff";"v1"="v16";"u1"="u16"};
+{"k1"="ggg";"v1"="v17";"u1"="u17"};
+{"k1"="hhh";"v1"="v18";"u1"="u18"};
+{"k1"="iii";"v1"="v19";"u1"="u19"};
+{"k1"="jjj";"v1"="v20";"u1"="u20"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1_1.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_1.txt.attr
new file mode 100644
index 0000000000..4185224ec0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_1.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1_dup.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_dup.txt
new file mode 100644
index 0000000000..b51b68a8f5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_dup.txt
@@ -0,0 +1,8 @@
+{"k1"="aaa";"v1"="v11";"u1"="u11"};
+{"k1"="aaa";"v1"="v15";"u1"="u15"};
+{"k1"="bbb";"v1"="v12";"u1"="u12"};
+{"k1"="bbb";"v1"="v16";"u1"="u16"};
+{"k1"="ccc";"v1"="v13";"u1"="u13"};
+{"k1"="ccc";"v1"="v17";"u1"="u17"};
+{"k1"="ddd";"v1"="v14";"u1"="u14"};
+{"k1"="ddd";"v1"="v18";"u1"="u18"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1_dup.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_dup.txt.attr
new file mode 100644
index 0000000000..4185224ec0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_dup.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1_opt.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_opt.txt
new file mode 100644
index 0000000000..647c550221
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_opt.txt
@@ -0,0 +1,5 @@
+{"k1"=#; "v1"="v10";"u1"="u10"};
+{"k1"="aaa";"v1"="v11";"u1"="u11"};
+{"k1"="bbb";"v1"="v12";"u1"="u12"};
+{"k1"="ccc";"v1"="v13";"u1"="u13"};
+{"k1"="ddd";"v1"="v14";"u1"="u14"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1_opt.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_opt.txt.attr
new file mode 100644
index 0000000000..aee2f17230
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_opt.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k1";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v1";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1_unique.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_unique.txt
new file mode 100644
index 0000000000..d8ba8879fe
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_unique.txt
@@ -0,0 +1,4 @@
+{"k1"="aaa";"v1"="v11";"u1"="u11"};
+{"k1"="bbb";"v1"="v12";"u1"="u12"};
+{"k1"="ccc";"v1"="v13";"u1"="u13"};
+{"k1"="ddd";"v1"="v14";"u1"="u14"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv1_unique.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_unique.txt.attr
new file mode 100644
index 0000000000..6059c56833
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv1_unique.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %true
+ >
+ [
+ {
+ "name" = "k1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv2.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv2.txt
new file mode 100644
index 0000000000..33b04d59da
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv2.txt
@@ -0,0 +1,3 @@
+{"k2"="bbb";"v2"="v21";"u2"="u21"};
+{"k2"="ccc";"v2"="v22";"u2"="u22"};
+{"k2"="ddd";"v2"="v23";"u2"="u23"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv2.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv2.txt.attr
new file mode 100644
index 0000000000..387ceb1b55
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv2.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u2";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv2_dup.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_dup.txt
new file mode 100644
index 0000000000..80a400c3e6
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_dup.txt
@@ -0,0 +1,6 @@
+{"k2"="bbb";"v2"="v21";"u2"="u21"};
+{"k2"="bbb";"v2"="v24";"u2"="u24"};
+{"k2"="ccc";"v2"="v22";"u2"="u22"};
+{"k2"="ccc";"v2"="v25";"u2"="u25"};
+{"k2"="ddd";"v2"="v23";"u2"="u23"};
+{"k2"="ddd";"v2"="v26";"u2"="u26"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv2_dup.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_dup.txt.attr
new file mode 100644
index 0000000000..387ceb1b55
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_dup.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u2";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv2_empty.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_empty.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_empty.txt
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv2_empty.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_empty.txt.attr
new file mode 100644
index 0000000000..387ceb1b55
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_empty.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u2";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv2_opt.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_opt.txt
new file mode 100644
index 0000000000..817b066cf5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_opt.txt
@@ -0,0 +1,3 @@
+{"k2"=#; "v2"=#; "u2"="u20"};
+{"k2"="bbb";"v2"="v21";"u2"="u21"};
+{"k2"="ccc";"v2"="v22";"u2"="u22"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv2_opt.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_opt.txt.attr
new file mode 100644
index 0000000000..d10189b748
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv2_opt.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k2";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v2";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u2";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv3.txt b/yql/essentials/tests/sql/suites/join/sorted_by_kv3.txt
new file mode 100644
index 0000000000..13d78d00ec
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv3.txt
@@ -0,0 +1,3 @@
+{"k3"="ccc";"v3"="v31";"u3"="u31"};
+{"k3"="ddd";"v3"="v32";"u3"="u32"};
+{"k3"="eee";"v3"="v33";"u3"="u33"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_by_kv3.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_by_kv3.txt.attr
new file mode 100644
index 0000000000..3b51f7ab03
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_by_kv3.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "k3";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "v3";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u3";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_uniq.txt b/yql/essentials/tests/sql/suites/join/sorted_uniq.txt
new file mode 100644
index 0000000000..3aa17b8d65
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_uniq.txt
@@ -0,0 +1,8 @@
+{"key"="023";"subkey"="3";"value"="aaa"};
+{"key"="037";"subkey"="5";"value"="ddd"};
+{"key"="075";"subkey"="1";"value"="abc"};
+{"key"="150";"subkey"="1";"value"="aaa"};
+{"key"="200";"subkey"="7";"value"="qqq"};
+{"key"="527";"subkey"="4";"value"="bbb"};
+{"key"="761";"subkey"="6";"value"="ccc"};
+{"key"="911";"subkey"="2";"value"="kkk"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_uniq.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_uniq.txt.attr
new file mode 100644
index 0000000000..3cbe9af3fd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_uniq.txt.attr
@@ -0,0 +1,12 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"String"]];
+ ["subkey";["DataType";"String"]];
+ ["value";["DataType";"String"]]
+ ]];
+ "SortDirections"=[1;];
+ "SortedBy"=["key";];
+ "SortedByTypes"=[["DataType";"String";];];
+ "SortMembers"=["key";];
+ "UniqueKeys"=%true;
+}}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_uniq1.txt b/yql/essentials/tests/sql/suites/join/sorted_uniq1.txt
new file mode 100644
index 0000000000..e84b5f77d1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_uniq1.txt
@@ -0,0 +1,14 @@
+{"key"="023";"subkey"="1";"value"="aaa"};
+{"key"="037";"subkey"="120";"value"="aab"};
+{"key"="075";"subkey"="150";"value"="abc"};
+{"key"="150";"subkey"="2";"value"="bbb"};
+{"key"="200";"subkey"="3";"value"="ccc"};
+{"key"="527";"subkey"="4";"value"="ddd"};
+{"key"="761";"subkey"="527";"value"="kkk"};
+{"key"="911";"subkey"="761";"value"="qqq"};
+{"key"="912";"subkey"="762";"value"="qqr"};
+{"key"="913";"subkey"="763";"value"="qqs"};
+{"key"="914";"subkey"="764";"value"="qqt"};
+{"key"="915";"subkey"="765";"value"="qqu"};
+{"key"="916";"subkey"="766";"value"="qqv"};
+{"key"="917";"subkey"="767";"value"="qqw"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_uniq1.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_uniq1.txt.attr
new file mode 100644
index 0000000000..fad1fb2801
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_uniq1.txt.attr
@@ -0,0 +1,12 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"String"]];
+ ["subkey";["DataType";"String"]];
+ ["value";["DataType";"String"]]
+ ]];
+ "SortDirections"=[1;1;];
+ "SortedBy"=["subkey";"value"];
+ "SortedByTypes"=[["DataType";"String";];["DataType";"String";];];
+ "SortMembers"=["subkey";"value"];
+ "UniqueKeys"=%true;
+}}
diff --git a/yql/essentials/tests/sql/suites/join/sorted_uniq2.txt b/yql/essentials/tests/sql/suites/join/sorted_uniq2.txt
new file mode 100644
index 0000000000..e84b5f77d1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_uniq2.txt
@@ -0,0 +1,14 @@
+{"key"="023";"subkey"="1";"value"="aaa"};
+{"key"="037";"subkey"="120";"value"="aab"};
+{"key"="075";"subkey"="150";"value"="abc"};
+{"key"="150";"subkey"="2";"value"="bbb"};
+{"key"="200";"subkey"="3";"value"="ccc"};
+{"key"="527";"subkey"="4";"value"="ddd"};
+{"key"="761";"subkey"="527";"value"="kkk"};
+{"key"="911";"subkey"="761";"value"="qqq"};
+{"key"="912";"subkey"="762";"value"="qqr"};
+{"key"="913";"subkey"="763";"value"="qqs"};
+{"key"="914";"subkey"="764";"value"="qqt"};
+{"key"="915";"subkey"="765";"value"="qqu"};
+{"key"="916";"subkey"="766";"value"="qqv"};
+{"key"="917";"subkey"="767";"value"="qqw"};
diff --git a/yql/essentials/tests/sql/suites/join/sorted_uniq2.txt.attr b/yql/essentials/tests/sql/suites/join/sorted_uniq2.txt.attr
new file mode 100644
index 0000000000..09cc6be90d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/sorted_uniq2.txt.attr
@@ -0,0 +1,12 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"String"]];
+ ["subkey";["DataType";"String"]];
+ ["value";["DataType";"String"]]
+ ]];
+ "SortDirections"=[1;];
+ "SortedBy"=["key"];
+ "SortedByTypes"=[["DataType";"String";]];
+ "SortMembers"=["key";];
+ "UniqueKeys"=%true;
+}}
diff --git a/yql/essentials/tests/sql/suites/join/spider_info.txt b/yql/essentials/tests/sql/suites/join/spider_info.txt
new file mode 100644
index 0000000000..f8c75fb66e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/spider_info.txt
@@ -0,0 +1,8 @@
+{"key"="1.1.1.1";"subkey"="RESULT";"value"="http://www.foo.bar/wtf"};
+{"key"="1.1.1.1";"subkey"="RESULT";"value"="http://www.foo.bar/spam"};
+{"key"="1.1.1.1";"subkey"="BAN_DETECTED";"value"="http://www.foo.bar/spam"};
+{"key"="2.2.2.2";"subkey"="RESULT";"value"="http://www.spam.ru/foo"};
+{"key"="2.2.2.2";"subkey"="BAN_DETECTED";"value"="http://www.spam.ru/foo"};
+{"key"="2.2.2.2";"subkey"="RESULT";"value"="http://www.spam.ru/bar"};
+{"key"="2.2.2.2";"subkey"="BAN_DETECTED";"value"="http://www.spam.ru/bar"};
+{"key"="2.2.2.2";"subkey"="RESULT";"value"="http://www.yandex.ru/wat"};
diff --git a/yql/essentials/tests/sql/suites/join/split_to_list_as_key-off.cfg b/yql/essentials/tests/sql/suites/join/split_to_list_as_key-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/split_to_list_as_key-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/split_to_list_as_key.cfg b/yql/essentials/tests/sql/suites/join/split_to_list_as_key.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/split_to_list_as_key.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/split_to_list_as_key.sql b/yql/essentials/tests/sql/suites/join/split_to_list_as_key.sql
new file mode 100644
index 0000000000..64be5ae083
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/split_to_list_as_key.sql
@@ -0,0 +1,7 @@
+/* syntax version 1 */
+PRAGMA DisableSimpleColumns;
+use plato;
+
+from Input1 as a
+join Input2 as b on a.key = String::SplitToList(b.key, "_")[0]
+select * order by a.key,a.subkey,b.subkey
diff --git a/yql/essentials/tests/sql/suites/join/star_join-off.cfg b/yql/essentials/tests/sql/suites/join/star_join-off.cfg
new file mode 100644
index 0000000000..64e0857bc5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join-off.cfg
@@ -0,0 +1,7 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/star_join.cfg b/yql/essentials/tests/sql/suites/join/star_join.cfg
new file mode 100644
index 0000000000..a884c15308
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/star_join.sql b/yql/essentials/tests/sql/suites/join/star_join.sql
new file mode 100644
index 0000000000..19c7c910ce
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join.sql
@@ -0,0 +1,12 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+
+
+$rightSemi = select * from Input2 as b right semi join Input1 as a on a.v1 = b.v2 and a.k1 = b.k2;
+$leftOnly = select * from $rightSemi as rs left only join Input3 as c on rs.k1 = c.k3 and rs.v1 = c.v3;
+$right = select * from Input4 as d right join $leftOnly as lo on d.v4 = lo.v1 and lo.k1 = d.k4;
+$inner = select * from $right as r join any Input5 as e on r.k1 = e.k5 and e.v5 = r.v1;
+
+select * from $inner order by u1,u5;
+
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners-off.cfg b/yql/essentials/tests/sql/suites/join/star_join_inners-off.cfg
new file mode 100644
index 0000000000..7859898010
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners-off.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners.cfg b/yql/essentials/tests/sql/suites/join/star_join_inners.cfg
new file mode 100644
index 0000000000..086641db8d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners.cfg
@@ -0,0 +1,3 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners.sql b/yql/essentials/tests/sql/suites/join/star_join_inners.sql
new file mode 100644
index 0000000000..9396fe8f6d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners.sql
@@ -0,0 +1,9 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+
+from any Input2 as b
+join any Input1 as a on b.k2 = a.k1 and a.v1 = b.v2
+join any Input3 as c on a.k1 = c.k3 and c.v3 = a.v1
+select * order by u1
+
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners_premap-off.cfg b/yql/essentials/tests/sql/suites/join/star_join_inners_premap-off.cfg
new file mode 100644
index 0000000000..7859898010
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners_premap-off.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners_premap.cfg b/yql/essentials/tests/sql/suites/join/star_join_inners_premap.cfg
new file mode 100644
index 0000000000..086641db8d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners_premap.cfg
@@ -0,0 +1,3 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners_premap.sql b/yql/essentials/tests/sql/suites/join/star_join_inners_premap.sql
new file mode 100644
index 0000000000..4cf67ca9ab
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners_premap.sql
@@ -0,0 +1,13 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+pragma DisablePullUpFlatMapOverJoin;
+
+$a = select k1,v1,u1, 1 as t1 from Input1;
+$c = select k3,v3,u3, 3 as t3 from Input3;
+
+from any Input2 as b
+join any $a as a on b.k2 = a.k1 and a.v1 = b.v2
+join any $c as c on a.k1 = c.k3 and c.v3 = a.v1
+select * order by u1
+
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted-off.cfg b/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted-off.cfg
new file mode 100644
index 0000000000..45c529ffa9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted-off.cfg
@@ -0,0 +1,5 @@
+in Input1 vk1_sorted.txt
+in Input2 vk2_sorted.txt
+in Input3 vk3_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted.cfg b/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted.cfg
new file mode 100644
index 0000000000..354c0f1d8d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted.cfg
@@ -0,0 +1,3 @@
+in Input1 vk1_sorted.txt
+in Input2 vk2_sorted.txt
+in Input3 vk3_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted.sql b/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted.sql
new file mode 100644
index 0000000000..9396fe8f6d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_inners_vk_sorted.sql
@@ -0,0 +1,9 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+
+from any Input2 as b
+join any Input1 as a on b.k2 = a.k1 and a.v1 = b.v2
+join any Input3 as c on a.k1 = c.k3 and c.v3 = a.v1
+select * order by u1
+
diff --git a/yql/essentials/tests/sql/suites/join/star_join_mirror-off.cfg b/yql/essentials/tests/sql/suites/join/star_join_mirror-off.cfg
new file mode 100644
index 0000000000..64e0857bc5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_mirror-off.cfg
@@ -0,0 +1,7 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/star_join_mirror.cfg b/yql/essentials/tests/sql/suites/join/star_join_mirror.cfg
new file mode 100644
index 0000000000..a884c15308
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_mirror.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/star_join_mirror.sql b/yql/essentials/tests/sql/suites/join/star_join_mirror.sql
new file mode 100644
index 0000000000..8aaf6431b0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_mirror.sql
@@ -0,0 +1,11 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+
+$leftSemi = select * from Input1 as a left semi join Input2 as b on b.k2 = a.k1 and a.v1 = b.v2;
+$rightOnly = select * from Input3 as c right only join $leftSemi as ls on ls.k1 = c.k3 and ls.v1 = c.v3;
+$left = select * from $rightOnly as ro left join Input4 as d on ro.v1 = d.v4 and d.k4 = ro.k1;
+$inner = select * from any Input5 as e join $left as l on e.k5 = l.k1 and l.v1 = e.v5;
+
+select * from $inner order by u1,u5;
+
diff --git a/yql/essentials/tests/sql/suites/join/star_join_multi-off.cfg b/yql/essentials/tests/sql/suites/join/star_join_multi-off.cfg
new file mode 100644
index 0000000000..64e0857bc5
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_multi-off.cfg
@@ -0,0 +1,7 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/star_join_multi.cfg b/yql/essentials/tests/sql/suites/join/star_join_multi.cfg
new file mode 100644
index 0000000000..a884c15308
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_multi.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/star_join_multi.sql b/yql/essentials/tests/sql/suites/join/star_join_multi.sql
new file mode 100644
index 0000000000..b6553ce006
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_multi.sql
@@ -0,0 +1,22 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+
+
+-- first Star JOIN chain
+$rightSemi = select * from Input2 as b right semi join Input1 as a on a.v1 = b.v2 and a.k1 = b.k2;
+$leftOnly = select * from $rightSemi as rs left only join Input3 as c on rs.k1 = c.k3 and rs.v1 = c.v3;
+$right = select * from Input4 as d right join $leftOnly as lo on d.v4 = lo.v1 and lo.k1 = d.k4;
+$chain1 = select * from $right as r join any Input5 as e on r.k1 = e.k5 and e.v5 = r.v1;
+
+-- second Star JOIN chain (mirror reflection of first one)
+$leftSemi = select * from Input1 as a1 left semi join Input2 as b1 on b1.k2 = a1.k1 and a1.v1 = b1.v2;
+$rightOnly = select * from Input3 as c1 right only join $leftSemi as ls on ls.k1 = c1.k3 and ls.v1 = c1.v3;
+$left = select * from $rightOnly as ro left join Input4 as d1 on ro.v1 = d1.v4 and d1.k4 = ro.k1;
+$chain2 = select * from any Input5 as e1 join $left as l on e1.k5 = l.k1 and l.v1 = e1.v5;
+
+
+select left.k1 as k1, right.v1 as v1 from
+$chain1 as left join $chain2 as right on left.k1 = right.k1 and left.v1 = right.v1
+order by k1,v1;
+
diff --git a/yql/essentials/tests/sql/suites/join/star_join_semionly-off.cfg b/yql/essentials/tests/sql/suites/join/star_join_semionly-off.cfg
new file mode 100644
index 0000000000..7859898010
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_semionly-off.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/star_join_semionly.cfg b/yql/essentials/tests/sql/suites/join/star_join_semionly.cfg
new file mode 100644
index 0000000000..086641db8d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_semionly.cfg
@@ -0,0 +1,3 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/star_join_semionly.sql b/yql/essentials/tests/sql/suites/join/star_join_semionly.sql
new file mode 100644
index 0000000000..bd158ea86d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_semionly.sql
@@ -0,0 +1,9 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+
+from Input1 as a
+left semi join Input2 as b on a.k1 = b.k2
+left only join Input3 as c on a.k1 = c.k3
+select * order by u1
+
diff --git a/yql/essentials/tests/sql/suites/join/star_join_semionly_premap-off.cfg b/yql/essentials/tests/sql/suites/join/star_join_semionly_premap-off.cfg
new file mode 100644
index 0000000000..7859898010
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_semionly_premap-off.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/star_join_semionly_premap.cfg b/yql/essentials/tests/sql/suites/join/star_join_semionly_premap.cfg
new file mode 100644
index 0000000000..086641db8d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_semionly_premap.cfg
@@ -0,0 +1,3 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
diff --git a/yql/essentials/tests/sql/suites/join/star_join_semionly_premap.sql b/yql/essentials/tests/sql/suites/join/star_join_semionly_premap.sql
new file mode 100644
index 0000000000..370490c9fd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_semionly_premap.sql
@@ -0,0 +1,14 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+pragma DisablePullUpFlatMapOverJoin;
+
+$a = select k1,v1,u1, 1 as t1 from Input1;
+$b = select k2,v2,u2, 2 as t2 from Input2;
+$c = select k3,v3,u3, 3 as t3 from Input3;
+
+from $a as a
+left semi join $b as b on a.k1 = b.k2
+left only join $c as c on a.k1 = c.k3
+select * order by u1
+
diff --git a/yql/essentials/tests/sql/suites/join/star_join_with_diff_complex_key.cfg b/yql/essentials/tests/sql/suites/join/star_join_with_diff_complex_key.cfg
new file mode 100644
index 0000000000..00227305fc
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_with_diff_complex_key.cfg
@@ -0,0 +1,5 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/star_join_with_diff_complex_key.sql b/yql/essentials/tests/sql/suites/join/star_join_with_diff_complex_key.sql
new file mode 100644
index 0000000000..94408a517e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/star_join_with_diff_complex_key.sql
@@ -0,0 +1,10 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+
+
+select *
+from Input1 as a
+join any Input2 as b on a.k1 = b.k2 AND a.v1 = b.v2
+join any Input3 as c on a.k1 = c.k3 AND a.v1 = c.v3
+left join Input4 as d on (c.v3, c.u3) = (d.v4, d.u4)
diff --git a/yql/essentials/tests/sql/suites/join/starjoin_unused_keys.cfg b/yql/essentials/tests/sql/suites/join/starjoin_unused_keys.cfg
new file mode 100644
index 0000000000..9a930ffe48
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/starjoin_unused_keys.cfg
@@ -0,0 +1,6 @@
+in Input1 kv1_sorted.txt
+in Input2 kv2_sorted.txt
+in Input3 kv3_sorted.txt
+in Input4 kv4_sorted.txt
+in Input5 kv5_sorted.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/starjoin_unused_keys.sql b/yql/essentials/tests/sql/suites/join/starjoin_unused_keys.sql
new file mode 100644
index 0000000000..4f2d3d932d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/starjoin_unused_keys.sql
@@ -0,0 +1,13 @@
+/* syntax version 1 */
+use plato;
+pragma yt.JoinEnableStarJoin="true";
+
+select
+
+v3
+
+from any Input1 as a
+join any Input2 as b on (a.k1 = b.k2 and a.v1 = b.v2)
+join any Input3 as c on (a.k1 = c.k3 and a.v1 = c.v3)
+join Input4 as d on (a.k1 = d.k4)
+order by v3;
diff --git a/yql/essentials/tests/sql/suites/join/strict_keys-off.cfg b/yql/essentials/tests/sql/suites/join/strict_keys-off.cfg
new file mode 100644
index 0000000000..e334c38f00
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/strict_keys-off.cfg
@@ -0,0 +1,5 @@
+xfail
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv1_opt.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/strict_keys.cfg b/yql/essentials/tests/sql/suites/join/strict_keys.cfg
new file mode 100644
index 0000000000..b54c86b56b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/strict_keys.cfg
@@ -0,0 +1,3 @@
+xfail
+in Input1 sorted_by_kv1.txt
+in Input2 sorted_by_kv1_opt.txt
diff --git a/yql/essentials/tests/sql/suites/join/strict_keys.sql b/yql/essentials/tests/sql/suites/join/strict_keys.sql
new file mode 100644
index 0000000000..e9382fa7fa
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/strict_keys.sql
@@ -0,0 +1,11 @@
+/* syntax version 1 */
+/* postgres can not */
+use plato;
+
+define subquery $strict() as
+ pragma StrictJoinKeyTypes;
+ select count(*) from Input1 as a join Input2 as b using(k1)
+end define;
+
+select count(*) from Input1 as a join Input2 as b using(k1);
+select * from $strict();
diff --git a/yql/essentials/tests/sql/suites/join/table_funcs_spec_join.sqlx b/yql/essentials/tests/sql/suites/join/table_funcs_spec_join.sqlx
new file mode 100644
index 0000000000..05b06478d8
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/table_funcs_spec_join.sqlx
@@ -0,0 +1,9 @@
+/* postgres can not */
+use plato;
+
+--insert into Output
+select
+ TablePath() as table_path
+from Input as a join Input as b using(key)
+where a.key = '200'
+;
diff --git a/yql/essentials/tests/sql/suites/join/test_join_1.txt b/yql/essentials/tests/sql/suites/join/test_join_1.txt
new file mode 100644
index 0000000000..e6eac2eaa2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/test_join_1.txt
@@ -0,0 +1,1000 @@
+{"key"="1";"subkey"="1";"value"="999"};
+{"key"="2";"subkey"="4";"value"="998"};
+{"key"="3";"subkey"="9";"value"="997"};
+{"key"="4";"subkey"="16";"value"="996"};
+{"key"="5";"subkey"="25";"value"="995"};
+{"key"="6";"subkey"="36";"value"="994"};
+{"key"="7";"subkey"="49";"value"="993"};
+{"key"="8";"subkey"="64";"value"="992"};
+{"key"="9";"subkey"="81";"value"="991"};
+{"key"="10";"subkey"="100";"value"="990"};
+{"key"="11";"subkey"="121";"value"="989"};
+{"key"="12";"subkey"="144";"value"="988"};
+{"key"="13";"subkey"="169";"value"="987"};
+{"key"="14";"subkey"="196";"value"="986"};
+{"key"="15";"subkey"="225";"value"="985"};
+{"key"="16";"subkey"="256";"value"="984"};
+{"key"="17";"subkey"="289";"value"="983"};
+{"key"="18";"subkey"="324";"value"="982"};
+{"key"="19";"subkey"="361";"value"="981"};
+{"key"="20";"subkey"="400";"value"="980"};
+{"key"="21";"subkey"="441";"value"="979"};
+{"key"="22";"subkey"="484";"value"="978"};
+{"key"="23";"subkey"="529";"value"="977"};
+{"key"="24";"subkey"="576";"value"="976"};
+{"key"="25";"subkey"="625";"value"="975"};
+{"key"="26";"subkey"="676";"value"="974"};
+{"key"="27";"subkey"="729";"value"="973"};
+{"key"="28";"subkey"="784";"value"="972"};
+{"key"="29";"subkey"="841";"value"="971"};
+{"key"="30";"subkey"="900";"value"="970"};
+{"key"="31";"subkey"="961";"value"="969"};
+{"key"="32";"subkey"="1024";"value"="968"};
+{"key"="33";"subkey"="1089";"value"="967"};
+{"key"="34";"subkey"="1156";"value"="966"};
+{"key"="35";"subkey"="1225";"value"="965"};
+{"key"="36";"subkey"="1296";"value"="964"};
+{"key"="37";"subkey"="1369";"value"="963"};
+{"key"="38";"subkey"="1444";"value"="962"};
+{"key"="39";"subkey"="1521";"value"="961"};
+{"key"="40";"subkey"="1600";"value"="960"};
+{"key"="41";"subkey"="1681";"value"="959"};
+{"key"="42";"subkey"="1764";"value"="958"};
+{"key"="43";"subkey"="1849";"value"="957"};
+{"key"="44";"subkey"="1936";"value"="956"};
+{"key"="45";"subkey"="2025";"value"="955"};
+{"key"="46";"subkey"="2116";"value"="954"};
+{"key"="47";"subkey"="2209";"value"="953"};
+{"key"="48";"subkey"="2304";"value"="952"};
+{"key"="49";"subkey"="2401";"value"="951"};
+{"key"="50";"subkey"="2500";"value"="950"};
+{"key"="51";"subkey"="2601";"value"="949"};
+{"key"="52";"subkey"="2704";"value"="948"};
+{"key"="53";"subkey"="2809";"value"="947"};
+{"key"="54";"subkey"="2916";"value"="946"};
+{"key"="55";"subkey"="3025";"value"="945"};
+{"key"="56";"subkey"="3136";"value"="944"};
+{"key"="57";"subkey"="3249";"value"="943"};
+{"key"="58";"subkey"="3364";"value"="942"};
+{"key"="59";"subkey"="3481";"value"="941"};
+{"key"="60";"subkey"="3600";"value"="940"};
+{"key"="61";"subkey"="3721";"value"="939"};
+{"key"="62";"subkey"="3844";"value"="938"};
+{"key"="63";"subkey"="3969";"value"="937"};
+{"key"="64";"subkey"="4096";"value"="936"};
+{"key"="65";"subkey"="4225";"value"="935"};
+{"key"="66";"subkey"="4356";"value"="934"};
+{"key"="67";"subkey"="4489";"value"="933"};
+{"key"="68";"subkey"="4624";"value"="932"};
+{"key"="69";"subkey"="4761";"value"="931"};
+{"key"="70";"subkey"="4900";"value"="930"};
+{"key"="71";"subkey"="5041";"value"="929"};
+{"key"="72";"subkey"="5184";"value"="928"};
+{"key"="73";"subkey"="5329";"value"="927"};
+{"key"="74";"subkey"="5476";"value"="926"};
+{"key"="75";"subkey"="5625";"value"="925"};
+{"key"="76";"subkey"="5776";"value"="924"};
+{"key"="77";"subkey"="5929";"value"="923"};
+{"key"="78";"subkey"="6084";"value"="922"};
+{"key"="79";"subkey"="6241";"value"="921"};
+{"key"="80";"subkey"="6400";"value"="920"};
+{"key"="81";"subkey"="6561";"value"="919"};
+{"key"="82";"subkey"="6724";"value"="918"};
+{"key"="83";"subkey"="6889";"value"="917"};
+{"key"="84";"subkey"="7056";"value"="916"};
+{"key"="85";"subkey"="7225";"value"="915"};
+{"key"="86";"subkey"="7396";"value"="914"};
+{"key"="87";"subkey"="7569";"value"="913"};
+{"key"="88";"subkey"="7744";"value"="912"};
+{"key"="89";"subkey"="7921";"value"="911"};
+{"key"="90";"subkey"="8100";"value"="910"};
+{"key"="91";"subkey"="8281";"value"="909"};
+{"key"="92";"subkey"="8464";"value"="908"};
+{"key"="93";"subkey"="8649";"value"="907"};
+{"key"="94";"subkey"="8836";"value"="906"};
+{"key"="95";"subkey"="9025";"value"="905"};
+{"key"="96";"subkey"="9216";"value"="904"};
+{"key"="97";"subkey"="9409";"value"="903"};
+{"key"="98";"subkey"="9604";"value"="902"};
+{"key"="99";"subkey"="9801";"value"="901"};
+{"key"="100";"subkey"="10000";"value"="900"};
+{"key"="101";"subkey"="10201";"value"="899"};
+{"key"="102";"subkey"="10404";"value"="898"};
+{"key"="103";"subkey"="10609";"value"="897"};
+{"key"="104";"subkey"="10816";"value"="896"};
+{"key"="105";"subkey"="11025";"value"="895"};
+{"key"="106";"subkey"="11236";"value"="894"};
+{"key"="107";"subkey"="11449";"value"="893"};
+{"key"="108";"subkey"="11664";"value"="892"};
+{"key"="109";"subkey"="11881";"value"="891"};
+{"key"="110";"subkey"="12100";"value"="890"};
+{"key"="111";"subkey"="12321";"value"="889"};
+{"key"="112";"subkey"="12544";"value"="888"};
+{"key"="113";"subkey"="12769";"value"="887"};
+{"key"="114";"subkey"="12996";"value"="886"};
+{"key"="115";"subkey"="13225";"value"="885"};
+{"key"="116";"subkey"="13456";"value"="884"};
+{"key"="117";"subkey"="13689";"value"="883"};
+{"key"="118";"subkey"="13924";"value"="882"};
+{"key"="119";"subkey"="14161";"value"="881"};
+{"key"="120";"subkey"="14400";"value"="880"};
+{"key"="121";"subkey"="14641";"value"="879"};
+{"key"="122";"subkey"="14884";"value"="878"};
+{"key"="123";"subkey"="15129";"value"="877"};
+{"key"="124";"subkey"="15376";"value"="876"};
+{"key"="125";"subkey"="15625";"value"="875"};
+{"key"="126";"subkey"="15876";"value"="874"};
+{"key"="127";"subkey"="16129";"value"="873"};
+{"key"="128";"subkey"="16384";"value"="872"};
+{"key"="129";"subkey"="16641";"value"="871"};
+{"key"="130";"subkey"="16900";"value"="870"};
+{"key"="131";"subkey"="17161";"value"="869"};
+{"key"="132";"subkey"="17424";"value"="868"};
+{"key"="133";"subkey"="17689";"value"="867"};
+{"key"="134";"subkey"="17956";"value"="866"};
+{"key"="135";"subkey"="18225";"value"="865"};
+{"key"="136";"subkey"="18496";"value"="864"};
+{"key"="137";"subkey"="18769";"value"="863"};
+{"key"="138";"subkey"="19044";"value"="862"};
+{"key"="139";"subkey"="19321";"value"="861"};
+{"key"="140";"subkey"="19600";"value"="860"};
+{"key"="141";"subkey"="19881";"value"="859"};
+{"key"="142";"subkey"="20164";"value"="858"};
+{"key"="143";"subkey"="20449";"value"="857"};
+{"key"="144";"subkey"="20736";"value"="856"};
+{"key"="145";"subkey"="21025";"value"="855"};
+{"key"="146";"subkey"="21316";"value"="854"};
+{"key"="147";"subkey"="21609";"value"="853"};
+{"key"="148";"subkey"="21904";"value"="852"};
+{"key"="149";"subkey"="22201";"value"="851"};
+{"key"="150";"subkey"="22500";"value"="850"};
+{"key"="151";"subkey"="22801";"value"="849"};
+{"key"="152";"subkey"="23104";"value"="848"};
+{"key"="153";"subkey"="23409";"value"="847"};
+{"key"="154";"subkey"="23716";"value"="846"};
+{"key"="155";"subkey"="24025";"value"="845"};
+{"key"="156";"subkey"="24336";"value"="844"};
+{"key"="157";"subkey"="24649";"value"="843"};
+{"key"="158";"subkey"="24964";"value"="842"};
+{"key"="159";"subkey"="25281";"value"="841"};
+{"key"="160";"subkey"="25600";"value"="840"};
+{"key"="161";"subkey"="25921";"value"="839"};
+{"key"="162";"subkey"="26244";"value"="838"};
+{"key"="163";"subkey"="26569";"value"="837"};
+{"key"="164";"subkey"="26896";"value"="836"};
+{"key"="165";"subkey"="27225";"value"="835"};
+{"key"="166";"subkey"="27556";"value"="834"};
+{"key"="167";"subkey"="27889";"value"="833"};
+{"key"="168";"subkey"="28224";"value"="832"};
+{"key"="169";"subkey"="28561";"value"="831"};
+{"key"="170";"subkey"="28900";"value"="830"};
+{"key"="171";"subkey"="29241";"value"="829"};
+{"key"="172";"subkey"="29584";"value"="828"};
+{"key"="173";"subkey"="29929";"value"="827"};
+{"key"="174";"subkey"="30276";"value"="826"};
+{"key"="175";"subkey"="30625";"value"="825"};
+{"key"="176";"subkey"="30976";"value"="824"};
+{"key"="177";"subkey"="31329";"value"="823"};
+{"key"="178";"subkey"="31684";"value"="822"};
+{"key"="179";"subkey"="32041";"value"="821"};
+{"key"="180";"subkey"="32400";"value"="820"};
+{"key"="181";"subkey"="32761";"value"="819"};
+{"key"="182";"subkey"="33124";"value"="818"};
+{"key"="183";"subkey"="33489";"value"="817"};
+{"key"="184";"subkey"="33856";"value"="816"};
+{"key"="185";"subkey"="34225";"value"="815"};
+{"key"="186";"subkey"="34596";"value"="814"};
+{"key"="187";"subkey"="34969";"value"="813"};
+{"key"="188";"subkey"="35344";"value"="812"};
+{"key"="189";"subkey"="35721";"value"="811"};
+{"key"="190";"subkey"="36100";"value"="810"};
+{"key"="191";"subkey"="36481";"value"="809"};
+{"key"="192";"subkey"="36864";"value"="808"};
+{"key"="193";"subkey"="37249";"value"="807"};
+{"key"="194";"subkey"="37636";"value"="806"};
+{"key"="195";"subkey"="38025";"value"="805"};
+{"key"="196";"subkey"="38416";"value"="804"};
+{"key"="197";"subkey"="38809";"value"="803"};
+{"key"="198";"subkey"="39204";"value"="802"};
+{"key"="199";"subkey"="39601";"value"="801"};
+{"key"="200";"subkey"="40000";"value"="800"};
+{"key"="201";"subkey"="40401";"value"="799"};
+{"key"="202";"subkey"="40804";"value"="798"};
+{"key"="203";"subkey"="41209";"value"="797"};
+{"key"="204";"subkey"="41616";"value"="796"};
+{"key"="205";"subkey"="42025";"value"="795"};
+{"key"="206";"subkey"="42436";"value"="794"};
+{"key"="207";"subkey"="42849";"value"="793"};
+{"key"="208";"subkey"="43264";"value"="792"};
+{"key"="209";"subkey"="43681";"value"="791"};
+{"key"="210";"subkey"="44100";"value"="790"};
+{"key"="211";"subkey"="44521";"value"="789"};
+{"key"="212";"subkey"="44944";"value"="788"};
+{"key"="213";"subkey"="45369";"value"="787"};
+{"key"="214";"subkey"="45796";"value"="786"};
+{"key"="215";"subkey"="46225";"value"="785"};
+{"key"="216";"subkey"="46656";"value"="784"};
+{"key"="217";"subkey"="47089";"value"="783"};
+{"key"="218";"subkey"="47524";"value"="782"};
+{"key"="219";"subkey"="47961";"value"="781"};
+{"key"="220";"subkey"="48400";"value"="780"};
+{"key"="221";"subkey"="48841";"value"="779"};
+{"key"="222";"subkey"="49284";"value"="778"};
+{"key"="223";"subkey"="49729";"value"="777"};
+{"key"="224";"subkey"="50176";"value"="776"};
+{"key"="225";"subkey"="50625";"value"="775"};
+{"key"="226";"subkey"="51076";"value"="774"};
+{"key"="227";"subkey"="51529";"value"="773"};
+{"key"="228";"subkey"="51984";"value"="772"};
+{"key"="229";"subkey"="52441";"value"="771"};
+{"key"="230";"subkey"="52900";"value"="770"};
+{"key"="231";"subkey"="53361";"value"="769"};
+{"key"="232";"subkey"="53824";"value"="768"};
+{"key"="233";"subkey"="54289";"value"="767"};
+{"key"="234";"subkey"="54756";"value"="766"};
+{"key"="235";"subkey"="55225";"value"="765"};
+{"key"="236";"subkey"="55696";"value"="764"};
+{"key"="237";"subkey"="56169";"value"="763"};
+{"key"="238";"subkey"="56644";"value"="762"};
+{"key"="239";"subkey"="57121";"value"="761"};
+{"key"="240";"subkey"="57600";"value"="760"};
+{"key"="241";"subkey"="58081";"value"="759"};
+{"key"="242";"subkey"="58564";"value"="758"};
+{"key"="243";"subkey"="59049";"value"="757"};
+{"key"="244";"subkey"="59536";"value"="756"};
+{"key"="245";"subkey"="60025";"value"="755"};
+{"key"="246";"subkey"="60516";"value"="754"};
+{"key"="247";"subkey"="61009";"value"="753"};
+{"key"="248";"subkey"="61504";"value"="752"};
+{"key"="249";"subkey"="62001";"value"="751"};
+{"key"="250";"subkey"="62500";"value"="750"};
+{"key"="251";"subkey"="63001";"value"="749"};
+{"key"="252";"subkey"="63504";"value"="748"};
+{"key"="253";"subkey"="64009";"value"="747"};
+{"key"="254";"subkey"="64516";"value"="746"};
+{"key"="255";"subkey"="65025";"value"="745"};
+{"key"="256";"subkey"="65536";"value"="744"};
+{"key"="257";"subkey"="66049";"value"="743"};
+{"key"="258";"subkey"="66564";"value"="742"};
+{"key"="259";"subkey"="67081";"value"="741"};
+{"key"="260";"subkey"="67600";"value"="740"};
+{"key"="261";"subkey"="68121";"value"="739"};
+{"key"="262";"subkey"="68644";"value"="738"};
+{"key"="263";"subkey"="69169";"value"="737"};
+{"key"="264";"subkey"="69696";"value"="736"};
+{"key"="265";"subkey"="70225";"value"="735"};
+{"key"="266";"subkey"="70756";"value"="734"};
+{"key"="267";"subkey"="71289";"value"="733"};
+{"key"="268";"subkey"="71824";"value"="732"};
+{"key"="269";"subkey"="72361";"value"="731"};
+{"key"="270";"subkey"="72900";"value"="730"};
+{"key"="271";"subkey"="73441";"value"="729"};
+{"key"="272";"subkey"="73984";"value"="728"};
+{"key"="273";"subkey"="74529";"value"="727"};
+{"key"="274";"subkey"="75076";"value"="726"};
+{"key"="275";"subkey"="75625";"value"="725"};
+{"key"="276";"subkey"="76176";"value"="724"};
+{"key"="277";"subkey"="76729";"value"="723"};
+{"key"="278";"subkey"="77284";"value"="722"};
+{"key"="279";"subkey"="77841";"value"="721"};
+{"key"="280";"subkey"="78400";"value"="720"};
+{"key"="281";"subkey"="78961";"value"="719"};
+{"key"="282";"subkey"="79524";"value"="718"};
+{"key"="283";"subkey"="80089";"value"="717"};
+{"key"="284";"subkey"="80656";"value"="716"};
+{"key"="285";"subkey"="81225";"value"="715"};
+{"key"="286";"subkey"="81796";"value"="714"};
+{"key"="287";"subkey"="82369";"value"="713"};
+{"key"="288";"subkey"="82944";"value"="712"};
+{"key"="289";"subkey"="83521";"value"="711"};
+{"key"="290";"subkey"="84100";"value"="710"};
+{"key"="291";"subkey"="84681";"value"="709"};
+{"key"="292";"subkey"="85264";"value"="708"};
+{"key"="293";"subkey"="85849";"value"="707"};
+{"key"="294";"subkey"="86436";"value"="706"};
+{"key"="295";"subkey"="87025";"value"="705"};
+{"key"="296";"subkey"="87616";"value"="704"};
+{"key"="297";"subkey"="88209";"value"="703"};
+{"key"="298";"subkey"="88804";"value"="702"};
+{"key"="299";"subkey"="89401";"value"="701"};
+{"key"="300";"subkey"="90000";"value"="700"};
+{"key"="301";"subkey"="90601";"value"="699"};
+{"key"="302";"subkey"="91204";"value"="698"};
+{"key"="303";"subkey"="91809";"value"="697"};
+{"key"="304";"subkey"="92416";"value"="696"};
+{"key"="305";"subkey"="93025";"value"="695"};
+{"key"="306";"subkey"="93636";"value"="694"};
+{"key"="307";"subkey"="94249";"value"="693"};
+{"key"="308";"subkey"="94864";"value"="692"};
+{"key"="309";"subkey"="95481";"value"="691"};
+{"key"="310";"subkey"="96100";"value"="690"};
+{"key"="311";"subkey"="96721";"value"="689"};
+{"key"="312";"subkey"="97344";"value"="688"};
+{"key"="313";"subkey"="97969";"value"="687"};
+{"key"="314";"subkey"="98596";"value"="686"};
+{"key"="315";"subkey"="99225";"value"="685"};
+{"key"="316";"subkey"="99856";"value"="684"};
+{"key"="317";"subkey"="100489";"value"="683"};
+{"key"="318";"subkey"="101124";"value"="682"};
+{"key"="319";"subkey"="101761";"value"="681"};
+{"key"="320";"subkey"="102400";"value"="680"};
+{"key"="321";"subkey"="103041";"value"="679"};
+{"key"="322";"subkey"="103684";"value"="678"};
+{"key"="323";"subkey"="104329";"value"="677"};
+{"key"="324";"subkey"="104976";"value"="676"};
+{"key"="325";"subkey"="105625";"value"="675"};
+{"key"="326";"subkey"="106276";"value"="674"};
+{"key"="327";"subkey"="106929";"value"="673"};
+{"key"="328";"subkey"="107584";"value"="672"};
+{"key"="329";"subkey"="108241";"value"="671"};
+{"key"="330";"subkey"="108900";"value"="670"};
+{"key"="331";"subkey"="109561";"value"="669"};
+{"key"="332";"subkey"="110224";"value"="668"};
+{"key"="333";"subkey"="110889";"value"="667"};
+{"key"="334";"subkey"="111556";"value"="666"};
+{"key"="335";"subkey"="112225";"value"="665"};
+{"key"="336";"subkey"="112896";"value"="664"};
+{"key"="337";"subkey"="113569";"value"="663"};
+{"key"="338";"subkey"="114244";"value"="662"};
+{"key"="339";"subkey"="114921";"value"="661"};
+{"key"="340";"subkey"="115600";"value"="660"};
+{"key"="341";"subkey"="116281";"value"="659"};
+{"key"="342";"subkey"="116964";"value"="658"};
+{"key"="343";"subkey"="117649";"value"="657"};
+{"key"="344";"subkey"="118336";"value"="656"};
+{"key"="345";"subkey"="119025";"value"="655"};
+{"key"="346";"subkey"="119716";"value"="654"};
+{"key"="347";"subkey"="120409";"value"="653"};
+{"key"="348";"subkey"="121104";"value"="652"};
+{"key"="349";"subkey"="121801";"value"="651"};
+{"key"="350";"subkey"="122500";"value"="650"};
+{"key"="351";"subkey"="123201";"value"="649"};
+{"key"="352";"subkey"="123904";"value"="648"};
+{"key"="353";"subkey"="124609";"value"="647"};
+{"key"="354";"subkey"="125316";"value"="646"};
+{"key"="355";"subkey"="126025";"value"="645"};
+{"key"="356";"subkey"="126736";"value"="644"};
+{"key"="357";"subkey"="127449";"value"="643"};
+{"key"="358";"subkey"="128164";"value"="642"};
+{"key"="359";"subkey"="128881";"value"="641"};
+{"key"="360";"subkey"="129600";"value"="640"};
+{"key"="361";"subkey"="130321";"value"="639"};
+{"key"="362";"subkey"="131044";"value"="638"};
+{"key"="363";"subkey"="131769";"value"="637"};
+{"key"="364";"subkey"="132496";"value"="636"};
+{"key"="365";"subkey"="133225";"value"="635"};
+{"key"="366";"subkey"="133956";"value"="634"};
+{"key"="367";"subkey"="134689";"value"="633"};
+{"key"="368";"subkey"="135424";"value"="632"};
+{"key"="369";"subkey"="136161";"value"="631"};
+{"key"="370";"subkey"="136900";"value"="630"};
+{"key"="371";"subkey"="137641";"value"="629"};
+{"key"="372";"subkey"="138384";"value"="628"};
+{"key"="373";"subkey"="139129";"value"="627"};
+{"key"="374";"subkey"="139876";"value"="626"};
+{"key"="375";"subkey"="140625";"value"="625"};
+{"key"="376";"subkey"="141376";"value"="624"};
+{"key"="377";"subkey"="142129";"value"="623"};
+{"key"="378";"subkey"="142884";"value"="622"};
+{"key"="379";"subkey"="143641";"value"="621"};
+{"key"="380";"subkey"="144400";"value"="620"};
+{"key"="381";"subkey"="145161";"value"="619"};
+{"key"="382";"subkey"="145924";"value"="618"};
+{"key"="383";"subkey"="146689";"value"="617"};
+{"key"="384";"subkey"="147456";"value"="616"};
+{"key"="385";"subkey"="148225";"value"="615"};
+{"key"="386";"subkey"="148996";"value"="614"};
+{"key"="387";"subkey"="149769";"value"="613"};
+{"key"="388";"subkey"="150544";"value"="612"};
+{"key"="389";"subkey"="151321";"value"="611"};
+{"key"="390";"subkey"="152100";"value"="610"};
+{"key"="391";"subkey"="152881";"value"="609"};
+{"key"="392";"subkey"="153664";"value"="608"};
+{"key"="393";"subkey"="154449";"value"="607"};
+{"key"="394";"subkey"="155236";"value"="606"};
+{"key"="395";"subkey"="156025";"value"="605"};
+{"key"="396";"subkey"="156816";"value"="604"};
+{"key"="397";"subkey"="157609";"value"="603"};
+{"key"="398";"subkey"="158404";"value"="602"};
+{"key"="399";"subkey"="159201";"value"="601"};
+{"key"="400";"subkey"="160000";"value"="600"};
+{"key"="401";"subkey"="160801";"value"="599"};
+{"key"="402";"subkey"="161604";"value"="598"};
+{"key"="403";"subkey"="162409";"value"="597"};
+{"key"="404";"subkey"="163216";"value"="596"};
+{"key"="405";"subkey"="164025";"value"="595"};
+{"key"="406";"subkey"="164836";"value"="594"};
+{"key"="407";"subkey"="165649";"value"="593"};
+{"key"="408";"subkey"="166464";"value"="592"};
+{"key"="409";"subkey"="167281";"value"="591"};
+{"key"="410";"subkey"="168100";"value"="590"};
+{"key"="411";"subkey"="168921";"value"="589"};
+{"key"="412";"subkey"="169744";"value"="588"};
+{"key"="413";"subkey"="170569";"value"="587"};
+{"key"="414";"subkey"="171396";"value"="586"};
+{"key"="415";"subkey"="172225";"value"="585"};
+{"key"="416";"subkey"="173056";"value"="584"};
+{"key"="417";"subkey"="173889";"value"="583"};
+{"key"="418";"subkey"="174724";"value"="582"};
+{"key"="419";"subkey"="175561";"value"="581"};
+{"key"="420";"subkey"="176400";"value"="580"};
+{"key"="421";"subkey"="177241";"value"="579"};
+{"key"="422";"subkey"="178084";"value"="578"};
+{"key"="423";"subkey"="178929";"value"="577"};
+{"key"="424";"subkey"="179776";"value"="576"};
+{"key"="425";"subkey"="180625";"value"="575"};
+{"key"="426";"subkey"="181476";"value"="574"};
+{"key"="427";"subkey"="182329";"value"="573"};
+{"key"="428";"subkey"="183184";"value"="572"};
+{"key"="429";"subkey"="184041";"value"="571"};
+{"key"="430";"subkey"="184900";"value"="570"};
+{"key"="431";"subkey"="185761";"value"="569"};
+{"key"="432";"subkey"="186624";"value"="568"};
+{"key"="433";"subkey"="187489";"value"="567"};
+{"key"="434";"subkey"="188356";"value"="566"};
+{"key"="435";"subkey"="189225";"value"="565"};
+{"key"="436";"subkey"="190096";"value"="564"};
+{"key"="437";"subkey"="190969";"value"="563"};
+{"key"="438";"subkey"="191844";"value"="562"};
+{"key"="439";"subkey"="192721";"value"="561"};
+{"key"="440";"subkey"="193600";"value"="560"};
+{"key"="441";"subkey"="194481";"value"="559"};
+{"key"="442";"subkey"="195364";"value"="558"};
+{"key"="443";"subkey"="196249";"value"="557"};
+{"key"="444";"subkey"="197136";"value"="556"};
+{"key"="445";"subkey"="198025";"value"="555"};
+{"key"="446";"subkey"="198916";"value"="554"};
+{"key"="447";"subkey"="199809";"value"="553"};
+{"key"="448";"subkey"="200704";"value"="552"};
+{"key"="449";"subkey"="201601";"value"="551"};
+{"key"="450";"subkey"="202500";"value"="550"};
+{"key"="451";"subkey"="203401";"value"="549"};
+{"key"="452";"subkey"="204304";"value"="548"};
+{"key"="453";"subkey"="205209";"value"="547"};
+{"key"="454";"subkey"="206116";"value"="546"};
+{"key"="455";"subkey"="207025";"value"="545"};
+{"key"="456";"subkey"="207936";"value"="544"};
+{"key"="457";"subkey"="208849";"value"="543"};
+{"key"="458";"subkey"="209764";"value"="542"};
+{"key"="459";"subkey"="210681";"value"="541"};
+{"key"="460";"subkey"="211600";"value"="540"};
+{"key"="461";"subkey"="212521";"value"="539"};
+{"key"="462";"subkey"="213444";"value"="538"};
+{"key"="463";"subkey"="214369";"value"="537"};
+{"key"="464";"subkey"="215296";"value"="536"};
+{"key"="465";"subkey"="216225";"value"="535"};
+{"key"="466";"subkey"="217156";"value"="534"};
+{"key"="467";"subkey"="218089";"value"="533"};
+{"key"="468";"subkey"="219024";"value"="532"};
+{"key"="469";"subkey"="219961";"value"="531"};
+{"key"="470";"subkey"="220900";"value"="530"};
+{"key"="471";"subkey"="221841";"value"="529"};
+{"key"="472";"subkey"="222784";"value"="528"};
+{"key"="473";"subkey"="223729";"value"="527"};
+{"key"="474";"subkey"="224676";"value"="526"};
+{"key"="475";"subkey"="225625";"value"="525"};
+{"key"="476";"subkey"="226576";"value"="524"};
+{"key"="477";"subkey"="227529";"value"="523"};
+{"key"="478";"subkey"="228484";"value"="522"};
+{"key"="479";"subkey"="229441";"value"="521"};
+{"key"="480";"subkey"="230400";"value"="520"};
+{"key"="481";"subkey"="231361";"value"="519"};
+{"key"="482";"subkey"="232324";"value"="518"};
+{"key"="483";"subkey"="233289";"value"="517"};
+{"key"="484";"subkey"="234256";"value"="516"};
+{"key"="485";"subkey"="235225";"value"="515"};
+{"key"="486";"subkey"="236196";"value"="514"};
+{"key"="487";"subkey"="237169";"value"="513"};
+{"key"="488";"subkey"="238144";"value"="512"};
+{"key"="489";"subkey"="239121";"value"="511"};
+{"key"="490";"subkey"="240100";"value"="510"};
+{"key"="491";"subkey"="241081";"value"="509"};
+{"key"="492";"subkey"="242064";"value"="508"};
+{"key"="493";"subkey"="243049";"value"="507"};
+{"key"="494";"subkey"="244036";"value"="506"};
+{"key"="495";"subkey"="245025";"value"="505"};
+{"key"="496";"subkey"="246016";"value"="504"};
+{"key"="497";"subkey"="247009";"value"="503"};
+{"key"="498";"subkey"="248004";"value"="502"};
+{"key"="499";"subkey"="249001";"value"="501"};
+{"key"="500";"subkey"="250000";"value"="500"};
+{"key"="501";"subkey"="251001";"value"="499"};
+{"key"="502";"subkey"="252004";"value"="498"};
+{"key"="503";"subkey"="253009";"value"="497"};
+{"key"="504";"subkey"="254016";"value"="496"};
+{"key"="505";"subkey"="255025";"value"="495"};
+{"key"="506";"subkey"="256036";"value"="494"};
+{"key"="507";"subkey"="257049";"value"="493"};
+{"key"="508";"subkey"="258064";"value"="492"};
+{"key"="509";"subkey"="259081";"value"="491"};
+{"key"="510";"subkey"="260100";"value"="490"};
+{"key"="511";"subkey"="261121";"value"="489"};
+{"key"="512";"subkey"="262144";"value"="488"};
+{"key"="513";"subkey"="263169";"value"="487"};
+{"key"="514";"subkey"="264196";"value"="486"};
+{"key"="515";"subkey"="265225";"value"="485"};
+{"key"="516";"subkey"="266256";"value"="484"};
+{"key"="517";"subkey"="267289";"value"="483"};
+{"key"="518";"subkey"="268324";"value"="482"};
+{"key"="519";"subkey"="269361";"value"="481"};
+{"key"="520";"subkey"="270400";"value"="480"};
+{"key"="521";"subkey"="271441";"value"="479"};
+{"key"="522";"subkey"="272484";"value"="478"};
+{"key"="523";"subkey"="273529";"value"="477"};
+{"key"="524";"subkey"="274576";"value"="476"};
+{"key"="525";"subkey"="275625";"value"="475"};
+{"key"="526";"subkey"="276676";"value"="474"};
+{"key"="527";"subkey"="277729";"value"="473"};
+{"key"="528";"subkey"="278784";"value"="472"};
+{"key"="529";"subkey"="279841";"value"="471"};
+{"key"="530";"subkey"="280900";"value"="470"};
+{"key"="531";"subkey"="281961";"value"="469"};
+{"key"="532";"subkey"="283024";"value"="468"};
+{"key"="533";"subkey"="284089";"value"="467"};
+{"key"="534";"subkey"="285156";"value"="466"};
+{"key"="535";"subkey"="286225";"value"="465"};
+{"key"="536";"subkey"="287296";"value"="464"};
+{"key"="537";"subkey"="288369";"value"="463"};
+{"key"="538";"subkey"="289444";"value"="462"};
+{"key"="539";"subkey"="290521";"value"="461"};
+{"key"="540";"subkey"="291600";"value"="460"};
+{"key"="541";"subkey"="292681";"value"="459"};
+{"key"="542";"subkey"="293764";"value"="458"};
+{"key"="543";"subkey"="294849";"value"="457"};
+{"key"="544";"subkey"="295936";"value"="456"};
+{"key"="545";"subkey"="297025";"value"="455"};
+{"key"="546";"subkey"="298116";"value"="454"};
+{"key"="547";"subkey"="299209";"value"="453"};
+{"key"="548";"subkey"="300304";"value"="452"};
+{"key"="549";"subkey"="301401";"value"="451"};
+{"key"="550";"subkey"="302500";"value"="450"};
+{"key"="551";"subkey"="303601";"value"="449"};
+{"key"="552";"subkey"="304704";"value"="448"};
+{"key"="553";"subkey"="305809";"value"="447"};
+{"key"="554";"subkey"="306916";"value"="446"};
+{"key"="555";"subkey"="308025";"value"="445"};
+{"key"="556";"subkey"="309136";"value"="444"};
+{"key"="557";"subkey"="310249";"value"="443"};
+{"key"="558";"subkey"="311364";"value"="442"};
+{"key"="559";"subkey"="312481";"value"="441"};
+{"key"="560";"subkey"="313600";"value"="440"};
+{"key"="561";"subkey"="314721";"value"="439"};
+{"key"="562";"subkey"="315844";"value"="438"};
+{"key"="563";"subkey"="316969";"value"="437"};
+{"key"="564";"subkey"="318096";"value"="436"};
+{"key"="565";"subkey"="319225";"value"="435"};
+{"key"="566";"subkey"="320356";"value"="434"};
+{"key"="567";"subkey"="321489";"value"="433"};
+{"key"="568";"subkey"="322624";"value"="432"};
+{"key"="569";"subkey"="323761";"value"="431"};
+{"key"="570";"subkey"="324900";"value"="430"};
+{"key"="571";"subkey"="326041";"value"="429"};
+{"key"="572";"subkey"="327184";"value"="428"};
+{"key"="573";"subkey"="328329";"value"="427"};
+{"key"="574";"subkey"="329476";"value"="426"};
+{"key"="575";"subkey"="330625";"value"="425"};
+{"key"="576";"subkey"="331776";"value"="424"};
+{"key"="577";"subkey"="332929";"value"="423"};
+{"key"="578";"subkey"="334084";"value"="422"};
+{"key"="579";"subkey"="335241";"value"="421"};
+{"key"="580";"subkey"="336400";"value"="420"};
+{"key"="581";"subkey"="337561";"value"="419"};
+{"key"="582";"subkey"="338724";"value"="418"};
+{"key"="583";"subkey"="339889";"value"="417"};
+{"key"="584";"subkey"="341056";"value"="416"};
+{"key"="585";"subkey"="342225";"value"="415"};
+{"key"="586";"subkey"="343396";"value"="414"};
+{"key"="587";"subkey"="344569";"value"="413"};
+{"key"="588";"subkey"="345744";"value"="412"};
+{"key"="589";"subkey"="346921";"value"="411"};
+{"key"="590";"subkey"="348100";"value"="410"};
+{"key"="591";"subkey"="349281";"value"="409"};
+{"key"="592";"subkey"="350464";"value"="408"};
+{"key"="593";"subkey"="351649";"value"="407"};
+{"key"="594";"subkey"="352836";"value"="406"};
+{"key"="595";"subkey"="354025";"value"="405"};
+{"key"="596";"subkey"="355216";"value"="404"};
+{"key"="597";"subkey"="356409";"value"="403"};
+{"key"="598";"subkey"="357604";"value"="402"};
+{"key"="599";"subkey"="358801";"value"="401"};
+{"key"="600";"subkey"="360000";"value"="400"};
+{"key"="601";"subkey"="361201";"value"="399"};
+{"key"="602";"subkey"="362404";"value"="398"};
+{"key"="603";"subkey"="363609";"value"="397"};
+{"key"="604";"subkey"="364816";"value"="396"};
+{"key"="605";"subkey"="366025";"value"="395"};
+{"key"="606";"subkey"="367236";"value"="394"};
+{"key"="607";"subkey"="368449";"value"="393"};
+{"key"="608";"subkey"="369664";"value"="392"};
+{"key"="609";"subkey"="370881";"value"="391"};
+{"key"="610";"subkey"="372100";"value"="390"};
+{"key"="611";"subkey"="373321";"value"="389"};
+{"key"="612";"subkey"="374544";"value"="388"};
+{"key"="613";"subkey"="375769";"value"="387"};
+{"key"="614";"subkey"="376996";"value"="386"};
+{"key"="615";"subkey"="378225";"value"="385"};
+{"key"="616";"subkey"="379456";"value"="384"};
+{"key"="617";"subkey"="380689";"value"="383"};
+{"key"="618";"subkey"="381924";"value"="382"};
+{"key"="619";"subkey"="383161";"value"="381"};
+{"key"="620";"subkey"="384400";"value"="380"};
+{"key"="621";"subkey"="385641";"value"="379"};
+{"key"="622";"subkey"="386884";"value"="378"};
+{"key"="623";"subkey"="388129";"value"="377"};
+{"key"="624";"subkey"="389376";"value"="376"};
+{"key"="625";"subkey"="390625";"value"="375"};
+{"key"="626";"subkey"="391876";"value"="374"};
+{"key"="627";"subkey"="393129";"value"="373"};
+{"key"="628";"subkey"="394384";"value"="372"};
+{"key"="629";"subkey"="395641";"value"="371"};
+{"key"="630";"subkey"="396900";"value"="370"};
+{"key"="631";"subkey"="398161";"value"="369"};
+{"key"="632";"subkey"="399424";"value"="368"};
+{"key"="633";"subkey"="400689";"value"="367"};
+{"key"="634";"subkey"="401956";"value"="366"};
+{"key"="635";"subkey"="403225";"value"="365"};
+{"key"="636";"subkey"="404496";"value"="364"};
+{"key"="637";"subkey"="405769";"value"="363"};
+{"key"="638";"subkey"="407044";"value"="362"};
+{"key"="639";"subkey"="408321";"value"="361"};
+{"key"="640";"subkey"="409600";"value"="360"};
+{"key"="641";"subkey"="410881";"value"="359"};
+{"key"="642";"subkey"="412164";"value"="358"};
+{"key"="643";"subkey"="413449";"value"="357"};
+{"key"="644";"subkey"="414736";"value"="356"};
+{"key"="645";"subkey"="416025";"value"="355"};
+{"key"="646";"subkey"="417316";"value"="354"};
+{"key"="647";"subkey"="418609";"value"="353"};
+{"key"="648";"subkey"="419904";"value"="352"};
+{"key"="649";"subkey"="421201";"value"="351"};
+{"key"="650";"subkey"="422500";"value"="350"};
+{"key"="651";"subkey"="423801";"value"="349"};
+{"key"="652";"subkey"="425104";"value"="348"};
+{"key"="653";"subkey"="426409";"value"="347"};
+{"key"="654";"subkey"="427716";"value"="346"};
+{"key"="655";"subkey"="429025";"value"="345"};
+{"key"="656";"subkey"="430336";"value"="344"};
+{"key"="657";"subkey"="431649";"value"="343"};
+{"key"="658";"subkey"="432964";"value"="342"};
+{"key"="659";"subkey"="434281";"value"="341"};
+{"key"="660";"subkey"="435600";"value"="340"};
+{"key"="661";"subkey"="436921";"value"="339"};
+{"key"="662";"subkey"="438244";"value"="338"};
+{"key"="663";"subkey"="439569";"value"="337"};
+{"key"="664";"subkey"="440896";"value"="336"};
+{"key"="665";"subkey"="442225";"value"="335"};
+{"key"="666";"subkey"="443556";"value"="334"};
+{"key"="667";"subkey"="444889";"value"="333"};
+{"key"="668";"subkey"="446224";"value"="332"};
+{"key"="669";"subkey"="447561";"value"="331"};
+{"key"="670";"subkey"="448900";"value"="330"};
+{"key"="671";"subkey"="450241";"value"="329"};
+{"key"="672";"subkey"="451584";"value"="328"};
+{"key"="673";"subkey"="452929";"value"="327"};
+{"key"="674";"subkey"="454276";"value"="326"};
+{"key"="675";"subkey"="455625";"value"="325"};
+{"key"="676";"subkey"="456976";"value"="324"};
+{"key"="677";"subkey"="458329";"value"="323"};
+{"key"="678";"subkey"="459684";"value"="322"};
+{"key"="679";"subkey"="461041";"value"="321"};
+{"key"="680";"subkey"="462400";"value"="320"};
+{"key"="681";"subkey"="463761";"value"="319"};
+{"key"="682";"subkey"="465124";"value"="318"};
+{"key"="683";"subkey"="466489";"value"="317"};
+{"key"="684";"subkey"="467856";"value"="316"};
+{"key"="685";"subkey"="469225";"value"="315"};
+{"key"="686";"subkey"="470596";"value"="314"};
+{"key"="687";"subkey"="471969";"value"="313"};
+{"key"="688";"subkey"="473344";"value"="312"};
+{"key"="689";"subkey"="474721";"value"="311"};
+{"key"="690";"subkey"="476100";"value"="310"};
+{"key"="691";"subkey"="477481";"value"="309"};
+{"key"="692";"subkey"="478864";"value"="308"};
+{"key"="693";"subkey"="480249";"value"="307"};
+{"key"="694";"subkey"="481636";"value"="306"};
+{"key"="695";"subkey"="483025";"value"="305"};
+{"key"="696";"subkey"="484416";"value"="304"};
+{"key"="697";"subkey"="485809";"value"="303"};
+{"key"="698";"subkey"="487204";"value"="302"};
+{"key"="699";"subkey"="488601";"value"="301"};
+{"key"="700";"subkey"="490000";"value"="300"};
+{"key"="701";"subkey"="491401";"value"="299"};
+{"key"="702";"subkey"="492804";"value"="298"};
+{"key"="703";"subkey"="494209";"value"="297"};
+{"key"="704";"subkey"="495616";"value"="296"};
+{"key"="705";"subkey"="497025";"value"="295"};
+{"key"="706";"subkey"="498436";"value"="294"};
+{"key"="707";"subkey"="499849";"value"="293"};
+{"key"="708";"subkey"="501264";"value"="292"};
+{"key"="709";"subkey"="502681";"value"="291"};
+{"key"="710";"subkey"="504100";"value"="290"};
+{"key"="711";"subkey"="505521";"value"="289"};
+{"key"="712";"subkey"="506944";"value"="288"};
+{"key"="713";"subkey"="508369";"value"="287"};
+{"key"="714";"subkey"="509796";"value"="286"};
+{"key"="715";"subkey"="511225";"value"="285"};
+{"key"="716";"subkey"="512656";"value"="284"};
+{"key"="717";"subkey"="514089";"value"="283"};
+{"key"="718";"subkey"="515524";"value"="282"};
+{"key"="719";"subkey"="516961";"value"="281"};
+{"key"="720";"subkey"="518400";"value"="280"};
+{"key"="721";"subkey"="519841";"value"="279"};
+{"key"="722";"subkey"="521284";"value"="278"};
+{"key"="723";"subkey"="522729";"value"="277"};
+{"key"="724";"subkey"="524176";"value"="276"};
+{"key"="725";"subkey"="525625";"value"="275"};
+{"key"="726";"subkey"="527076";"value"="274"};
+{"key"="727";"subkey"="528529";"value"="273"};
+{"key"="728";"subkey"="529984";"value"="272"};
+{"key"="729";"subkey"="531441";"value"="271"};
+{"key"="730";"subkey"="532900";"value"="270"};
+{"key"="731";"subkey"="534361";"value"="269"};
+{"key"="732";"subkey"="535824";"value"="268"};
+{"key"="733";"subkey"="537289";"value"="267"};
+{"key"="734";"subkey"="538756";"value"="266"};
+{"key"="735";"subkey"="540225";"value"="265"};
+{"key"="736";"subkey"="541696";"value"="264"};
+{"key"="737";"subkey"="543169";"value"="263"};
+{"key"="738";"subkey"="544644";"value"="262"};
+{"key"="739";"subkey"="546121";"value"="261"};
+{"key"="740";"subkey"="547600";"value"="260"};
+{"key"="741";"subkey"="549081";"value"="259"};
+{"key"="742";"subkey"="550564";"value"="258"};
+{"key"="743";"subkey"="552049";"value"="257"};
+{"key"="744";"subkey"="553536";"value"="256"};
+{"key"="745";"subkey"="555025";"value"="255"};
+{"key"="746";"subkey"="556516";"value"="254"};
+{"key"="747";"subkey"="558009";"value"="253"};
+{"key"="748";"subkey"="559504";"value"="252"};
+{"key"="749";"subkey"="561001";"value"="251"};
+{"key"="750";"subkey"="562500";"value"="250"};
+{"key"="751";"subkey"="564001";"value"="249"};
+{"key"="752";"subkey"="565504";"value"="248"};
+{"key"="753";"subkey"="567009";"value"="247"};
+{"key"="754";"subkey"="568516";"value"="246"};
+{"key"="755";"subkey"="570025";"value"="245"};
+{"key"="756";"subkey"="571536";"value"="244"};
+{"key"="757";"subkey"="573049";"value"="243"};
+{"key"="758";"subkey"="574564";"value"="242"};
+{"key"="759";"subkey"="576081";"value"="241"};
+{"key"="760";"subkey"="577600";"value"="240"};
+{"key"="761";"subkey"="579121";"value"="239"};
+{"key"="762";"subkey"="580644";"value"="238"};
+{"key"="763";"subkey"="582169";"value"="237"};
+{"key"="764";"subkey"="583696";"value"="236"};
+{"key"="765";"subkey"="585225";"value"="235"};
+{"key"="766";"subkey"="586756";"value"="234"};
+{"key"="767";"subkey"="588289";"value"="233"};
+{"key"="768";"subkey"="589824";"value"="232"};
+{"key"="769";"subkey"="591361";"value"="231"};
+{"key"="770";"subkey"="592900";"value"="230"};
+{"key"="771";"subkey"="594441";"value"="229"};
+{"key"="772";"subkey"="595984";"value"="228"};
+{"key"="773";"subkey"="597529";"value"="227"};
+{"key"="774";"subkey"="599076";"value"="226"};
+{"key"="775";"subkey"="600625";"value"="225"};
+{"key"="776";"subkey"="602176";"value"="224"};
+{"key"="777";"subkey"="603729";"value"="223"};
+{"key"="778";"subkey"="605284";"value"="222"};
+{"key"="779";"subkey"="606841";"value"="221"};
+{"key"="780";"subkey"="608400";"value"="220"};
+{"key"="781";"subkey"="609961";"value"="219"};
+{"key"="782";"subkey"="611524";"value"="218"};
+{"key"="783";"subkey"="613089";"value"="217"};
+{"key"="784";"subkey"="614656";"value"="216"};
+{"key"="785";"subkey"="616225";"value"="215"};
+{"key"="786";"subkey"="617796";"value"="214"};
+{"key"="787";"subkey"="619369";"value"="213"};
+{"key"="788";"subkey"="620944";"value"="212"};
+{"key"="789";"subkey"="622521";"value"="211"};
+{"key"="790";"subkey"="624100";"value"="210"};
+{"key"="791";"subkey"="625681";"value"="209"};
+{"key"="792";"subkey"="627264";"value"="208"};
+{"key"="793";"subkey"="628849";"value"="207"};
+{"key"="794";"subkey"="630436";"value"="206"};
+{"key"="795";"subkey"="632025";"value"="205"};
+{"key"="796";"subkey"="633616";"value"="204"};
+{"key"="797";"subkey"="635209";"value"="203"};
+{"key"="798";"subkey"="636804";"value"="202"};
+{"key"="799";"subkey"="638401";"value"="201"};
+{"key"="800";"subkey"="640000";"value"="200"};
+{"key"="801";"subkey"="641601";"value"="199"};
+{"key"="802";"subkey"="643204";"value"="198"};
+{"key"="803";"subkey"="644809";"value"="197"};
+{"key"="804";"subkey"="646416";"value"="196"};
+{"key"="805";"subkey"="648025";"value"="195"};
+{"key"="806";"subkey"="649636";"value"="194"};
+{"key"="807";"subkey"="651249";"value"="193"};
+{"key"="808";"subkey"="652864";"value"="192"};
+{"key"="809";"subkey"="654481";"value"="191"};
+{"key"="810";"subkey"="656100";"value"="190"};
+{"key"="811";"subkey"="657721";"value"="189"};
+{"key"="812";"subkey"="659344";"value"="188"};
+{"key"="813";"subkey"="660969";"value"="187"};
+{"key"="814";"subkey"="662596";"value"="186"};
+{"key"="815";"subkey"="664225";"value"="185"};
+{"key"="816";"subkey"="665856";"value"="184"};
+{"key"="817";"subkey"="667489";"value"="183"};
+{"key"="818";"subkey"="669124";"value"="182"};
+{"key"="819";"subkey"="670761";"value"="181"};
+{"key"="820";"subkey"="672400";"value"="180"};
+{"key"="821";"subkey"="674041";"value"="179"};
+{"key"="822";"subkey"="675684";"value"="178"};
+{"key"="823";"subkey"="677329";"value"="177"};
+{"key"="824";"subkey"="678976";"value"="176"};
+{"key"="825";"subkey"="680625";"value"="175"};
+{"key"="826";"subkey"="682276";"value"="174"};
+{"key"="827";"subkey"="683929";"value"="173"};
+{"key"="828";"subkey"="685584";"value"="172"};
+{"key"="829";"subkey"="687241";"value"="171"};
+{"key"="830";"subkey"="688900";"value"="170"};
+{"key"="831";"subkey"="690561";"value"="169"};
+{"key"="832";"subkey"="692224";"value"="168"};
+{"key"="833";"subkey"="693889";"value"="167"};
+{"key"="834";"subkey"="695556";"value"="166"};
+{"key"="835";"subkey"="697225";"value"="165"};
+{"key"="836";"subkey"="698896";"value"="164"};
+{"key"="837";"subkey"="700569";"value"="163"};
+{"key"="838";"subkey"="702244";"value"="162"};
+{"key"="839";"subkey"="703921";"value"="161"};
+{"key"="840";"subkey"="705600";"value"="160"};
+{"key"="841";"subkey"="707281";"value"="159"};
+{"key"="842";"subkey"="708964";"value"="158"};
+{"key"="843";"subkey"="710649";"value"="157"};
+{"key"="844";"subkey"="712336";"value"="156"};
+{"key"="845";"subkey"="714025";"value"="155"};
+{"key"="846";"subkey"="715716";"value"="154"};
+{"key"="847";"subkey"="717409";"value"="153"};
+{"key"="848";"subkey"="719104";"value"="152"};
+{"key"="849";"subkey"="720801";"value"="151"};
+{"key"="850";"subkey"="722500";"value"="150"};
+{"key"="851";"subkey"="724201";"value"="149"};
+{"key"="852";"subkey"="725904";"value"="148"};
+{"key"="853";"subkey"="727609";"value"="147"};
+{"key"="854";"subkey"="729316";"value"="146"};
+{"key"="855";"subkey"="731025";"value"="145"};
+{"key"="856";"subkey"="732736";"value"="144"};
+{"key"="857";"subkey"="734449";"value"="143"};
+{"key"="858";"subkey"="736164";"value"="142"};
+{"key"="859";"subkey"="737881";"value"="141"};
+{"key"="860";"subkey"="739600";"value"="140"};
+{"key"="861";"subkey"="741321";"value"="139"};
+{"key"="862";"subkey"="743044";"value"="138"};
+{"key"="863";"subkey"="744769";"value"="137"};
+{"key"="864";"subkey"="746496";"value"="136"};
+{"key"="865";"subkey"="748225";"value"="135"};
+{"key"="866";"subkey"="749956";"value"="134"};
+{"key"="867";"subkey"="751689";"value"="133"};
+{"key"="868";"subkey"="753424";"value"="132"};
+{"key"="869";"subkey"="755161";"value"="131"};
+{"key"="870";"subkey"="756900";"value"="130"};
+{"key"="871";"subkey"="758641";"value"="129"};
+{"key"="872";"subkey"="760384";"value"="128"};
+{"key"="873";"subkey"="762129";"value"="127"};
+{"key"="874";"subkey"="763876";"value"="126"};
+{"key"="875";"subkey"="765625";"value"="125"};
+{"key"="876";"subkey"="767376";"value"="124"};
+{"key"="877";"subkey"="769129";"value"="123"};
+{"key"="878";"subkey"="770884";"value"="122"};
+{"key"="879";"subkey"="772641";"value"="121"};
+{"key"="880";"subkey"="774400";"value"="120"};
+{"key"="881";"subkey"="776161";"value"="119"};
+{"key"="882";"subkey"="777924";"value"="118"};
+{"key"="883";"subkey"="779689";"value"="117"};
+{"key"="884";"subkey"="781456";"value"="116"};
+{"key"="885";"subkey"="783225";"value"="115"};
+{"key"="886";"subkey"="784996";"value"="114"};
+{"key"="887";"subkey"="786769";"value"="113"};
+{"key"="888";"subkey"="788544";"value"="112"};
+{"key"="889";"subkey"="790321";"value"="111"};
+{"key"="890";"subkey"="792100";"value"="110"};
+{"key"="891";"subkey"="793881";"value"="109"};
+{"key"="892";"subkey"="795664";"value"="108"};
+{"key"="893";"subkey"="797449";"value"="107"};
+{"key"="894";"subkey"="799236";"value"="106"};
+{"key"="895";"subkey"="801025";"value"="105"};
+{"key"="896";"subkey"="802816";"value"="104"};
+{"key"="897";"subkey"="804609";"value"="103"};
+{"key"="898";"subkey"="806404";"value"="102"};
+{"key"="899";"subkey"="808201";"value"="101"};
+{"key"="900";"subkey"="810000";"value"="100"};
+{"key"="901";"subkey"="811801";"value"="99"};
+{"key"="902";"subkey"="813604";"value"="98"};
+{"key"="903";"subkey"="815409";"value"="97"};
+{"key"="904";"subkey"="817216";"value"="96"};
+{"key"="905";"subkey"="819025";"value"="95"};
+{"key"="906";"subkey"="820836";"value"="94"};
+{"key"="907";"subkey"="822649";"value"="93"};
+{"key"="908";"subkey"="824464";"value"="92"};
+{"key"="909";"subkey"="826281";"value"="91"};
+{"key"="910";"subkey"="828100";"value"="90"};
+{"key"="911";"subkey"="829921";"value"="89"};
+{"key"="912";"subkey"="831744";"value"="88"};
+{"key"="913";"subkey"="833569";"value"="87"};
+{"key"="914";"subkey"="835396";"value"="86"};
+{"key"="915";"subkey"="837225";"value"="85"};
+{"key"="916";"subkey"="839056";"value"="84"};
+{"key"="917";"subkey"="840889";"value"="83"};
+{"key"="918";"subkey"="842724";"value"="82"};
+{"key"="919";"subkey"="844561";"value"="81"};
+{"key"="920";"subkey"="846400";"value"="80"};
+{"key"="921";"subkey"="848241";"value"="79"};
+{"key"="922";"subkey"="850084";"value"="78"};
+{"key"="923";"subkey"="851929";"value"="77"};
+{"key"="924";"subkey"="853776";"value"="76"};
+{"key"="925";"subkey"="855625";"value"="75"};
+{"key"="926";"subkey"="857476";"value"="74"};
+{"key"="927";"subkey"="859329";"value"="73"};
+{"key"="928";"subkey"="861184";"value"="72"};
+{"key"="929";"subkey"="863041";"value"="71"};
+{"key"="930";"subkey"="864900";"value"="70"};
+{"key"="931";"subkey"="866761";"value"="69"};
+{"key"="932";"subkey"="868624";"value"="68"};
+{"key"="933";"subkey"="870489";"value"="67"};
+{"key"="934";"subkey"="872356";"value"="66"};
+{"key"="935";"subkey"="874225";"value"="65"};
+{"key"="936";"subkey"="876096";"value"="64"};
+{"key"="937";"subkey"="877969";"value"="63"};
+{"key"="938";"subkey"="879844";"value"="62"};
+{"key"="939";"subkey"="881721";"value"="61"};
+{"key"="940";"subkey"="883600";"value"="60"};
+{"key"="941";"subkey"="885481";"value"="59"};
+{"key"="942";"subkey"="887364";"value"="58"};
+{"key"="943";"subkey"="889249";"value"="57"};
+{"key"="944";"subkey"="891136";"value"="56"};
+{"key"="945";"subkey"="893025";"value"="55"};
+{"key"="946";"subkey"="894916";"value"="54"};
+{"key"="947";"subkey"="896809";"value"="53"};
+{"key"="948";"subkey"="898704";"value"="52"};
+{"key"="949";"subkey"="900601";"value"="51"};
+{"key"="950";"subkey"="902500";"value"="50"};
+{"key"="951";"subkey"="904401";"value"="49"};
+{"key"="952";"subkey"="906304";"value"="48"};
+{"key"="953";"subkey"="908209";"value"="47"};
+{"key"="954";"subkey"="910116";"value"="46"};
+{"key"="955";"subkey"="912025";"value"="45"};
+{"key"="956";"subkey"="913936";"value"="44"};
+{"key"="957";"subkey"="915849";"value"="43"};
+{"key"="958";"subkey"="917764";"value"="42"};
+{"key"="959";"subkey"="919681";"value"="41"};
+{"key"="960";"subkey"="921600";"value"="40"};
+{"key"="961";"subkey"="923521";"value"="39"};
+{"key"="962";"subkey"="925444";"value"="38"};
+{"key"="963";"subkey"="927369";"value"="37"};
+{"key"="964";"subkey"="929296";"value"="36"};
+{"key"="965";"subkey"="931225";"value"="35"};
+{"key"="966";"subkey"="933156";"value"="34"};
+{"key"="967";"subkey"="935089";"value"="33"};
+{"key"="968";"subkey"="937024";"value"="32"};
+{"key"="969";"subkey"="938961";"value"="31"};
+{"key"="970";"subkey"="940900";"value"="30"};
+{"key"="971";"subkey"="942841";"value"="29"};
+{"key"="972";"subkey"="944784";"value"="28"};
+{"key"="973";"subkey"="946729";"value"="27"};
+{"key"="974";"subkey"="948676";"value"="26"};
+{"key"="975";"subkey"="950625";"value"="25"};
+{"key"="976";"subkey"="952576";"value"="24"};
+{"key"="977";"subkey"="954529";"value"="23"};
+{"key"="978";"subkey"="956484";"value"="22"};
+{"key"="979";"subkey"="958441";"value"="21"};
+{"key"="980";"subkey"="960400";"value"="20"};
+{"key"="981";"subkey"="962361";"value"="19"};
+{"key"="982";"subkey"="964324";"value"="18"};
+{"key"="983";"subkey"="966289";"value"="17"};
+{"key"="984";"subkey"="968256";"value"="16"};
+{"key"="985";"subkey"="970225";"value"="15"};
+{"key"="986";"subkey"="972196";"value"="14"};
+{"key"="987";"subkey"="974169";"value"="13"};
+{"key"="988";"subkey"="976144";"value"="12"};
+{"key"="989";"subkey"="978121";"value"="11"};
+{"key"="990";"subkey"="980100";"value"="10"};
+{"key"="991";"subkey"="982081";"value"="9"};
+{"key"="992";"subkey"="984064";"value"="8"};
+{"key"="993";"subkey"="986049";"value"="7"};
+{"key"="994";"subkey"="988036";"value"="6"};
+{"key"="995";"subkey"="990025";"value"="5"};
+{"key"="996";"subkey"="992016";"value"="4"};
+{"key"="997";"subkey"="994009";"value"="3"};
+{"key"="998";"subkey"="996004";"value"="2"};
+{"key"="999";"subkey"="998001";"value"="1"};
+{"key"="1000";"subkey"="1000000";"value"="0"};
diff --git a/yql/essentials/tests/sql/suites/join/test_join_2.txt b/yql/essentials/tests/sql/suites/join/test_join_2.txt
new file mode 100644
index 0000000000..2e5076d14c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/test_join_2.txt
@@ -0,0 +1,100 @@
+{"key"="99";"subkey"="2";"value"="x"};
+{"key"="98";"subkey"="8";"value"="xx"};
+{"key"="97";"subkey"="18";"value"="xxx"};
+{"key"="96";"subkey"="32";"value"="xxxx"};
+{"key"="95";"subkey"="50";"value"="xxxxx"};
+{"key"="94";"subkey"="72";"value"="xxxxxx"};
+{"key"="93";"subkey"="98";"value"="xxxxxxx"};
+{"key"="92";"subkey"="128";"value"="xxxxxxxx"};
+{"key"="91";"subkey"="162";"value"="xxxxxxxxx"};
+{"key"="90";"subkey"="200";"value"="xxxxxxxxxx"};
+{"key"="89";"subkey"="242";"value"="xxxxxxxxxxx"};
+{"key"="88";"subkey"="288";"value"="xxxxxxxxxxxx"};
+{"key"="87";"subkey"="338";"value"="xxxxxxxxxxxxx"};
+{"key"="86";"subkey"="392";"value"="xxxxxxxxxxxxxx"};
+{"key"="85";"subkey"="450";"value"="xxxxxxxxxxxxxxx"};
+{"key"="84";"subkey"="512";"value"="xxxxxxxxxxxxxxxx"};
+{"key"="83";"subkey"="578";"value"="xxxxxxxxxxxxxxxxx"};
+{"key"="82";"subkey"="648";"value"="xxxxxxxxxxxxxxxxxx"};
+{"key"="81";"subkey"="722";"value"="xxxxxxxxxxxxxxxxxxx"};
+{"key"="80";"subkey"="800";"value"="xxxxxxxxxxxxxxxxxxxx"};
+{"key"="79";"subkey"="882";"value"="xxxxxxxxxxxxxxxxxxxxx"};
+{"key"="78";"subkey"="968";"value"="xxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="77";"subkey"="1058";"value"="xxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="76";"subkey"="1152";"value"="xxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="75";"subkey"="1250";"value"="xxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="74";"subkey"="1352";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="73";"subkey"="1458";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="72";"subkey"="1568";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="71";"subkey"="1682";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="70";"subkey"="1800";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="69";"subkey"="1922";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="68";"subkey"="2048";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="67";"subkey"="2178";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="66";"subkey"="2312";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="65";"subkey"="2450";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="64";"subkey"="2592";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="63";"subkey"="2738";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="62";"subkey"="2888";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="61";"subkey"="3042";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="60";"subkey"="3200";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="59";"subkey"="3362";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="58";"subkey"="3528";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="57";"subkey"="3698";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="56";"subkey"="3872";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="55";"subkey"="4050";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="54";"subkey"="4232";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="53";"subkey"="4418";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="52";"subkey"="4608";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="51";"subkey"="4802";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="50";"subkey"="5000";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="49";"subkey"="5202";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="48";"subkey"="5408";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="47";"subkey"="5618";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="46";"subkey"="5832";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="45";"subkey"="6050";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="44";"subkey"="6272";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="43";"subkey"="6498";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="42";"subkey"="6728";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="41";"subkey"="6962";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="40";"subkey"="7200";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="39";"subkey"="7442";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="38";"subkey"="7688";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="37";"subkey"="7938";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="36";"subkey"="8192";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="35";"subkey"="8450";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="34";"subkey"="8712";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="33";"subkey"="8978";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="32";"subkey"="9248";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="31";"subkey"="9522";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="30";"subkey"="9800";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="29";"subkey"="10082";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="28";"subkey"="10368";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="27";"subkey"="10658";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="26";"subkey"="10952";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="25";"subkey"="11250";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="24";"subkey"="11552";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="23";"subkey"="11858";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="22";"subkey"="12168";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="21";"subkey"="12482";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="20";"subkey"="12800";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="19";"subkey"="13122";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="18";"subkey"="13448";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="17";"subkey"="13778";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="16";"subkey"="14112";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="15";"subkey"="14450";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="14";"subkey"="14792";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="13";"subkey"="15138";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="12";"subkey"="15488";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="11";"subkey"="15842";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="10";"subkey"="16200";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="9";"subkey"="16562";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="8";"subkey"="16928";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="7";"subkey"="17298";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="6";"subkey"="17672";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="5";"subkey"="18050";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="4";"subkey"="18432";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="3";"subkey"="18818";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="2";"subkey"="19208";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="1";"subkey"="19602";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
+{"key"="0";"subkey"="20000";"value"="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"};
diff --git a/yql/essentials/tests/sql/suites/join/three_equalities-off.cfg b/yql/essentials/tests/sql/suites/join/three_equalities-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/three_equalities-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/three_equalities.cfg b/yql/essentials/tests/sql/suites/join/three_equalities.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/three_equalities.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/three_equalities.sql b/yql/essentials/tests/sql/suites/join/three_equalities.sql
new file mode 100644
index 0000000000..51637f9154
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/three_equalities.sql
@@ -0,0 +1,12 @@
+PRAGMA DisableSimpleColumns;
+USE plato;
+SELECT * FROM
+ Input1 AS A
+JOIN
+ Input2 AS B
+ON
+ A.key == B.key AND
+ (cast(A.subkey AS int) + 1 == cast(B.subkey AS int)) AND
+ A.value == B.value
+ORDER BY A.key
+;
diff --git a/yql/essentials/tests/sql/suites/join/three_equalities_paren-off.cfg b/yql/essentials/tests/sql/suites/join/three_equalities_paren-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/three_equalities_paren-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/three_equalities_paren.cfg b/yql/essentials/tests/sql/suites/join/three_equalities_paren.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/three_equalities_paren.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/three_equalities_paren.sql b/yql/essentials/tests/sql/suites/join/three_equalities_paren.sql
new file mode 100644
index 0000000000..b1be3c32e2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/three_equalities_paren.sql
@@ -0,0 +1,11 @@
+PRAGMA DisableSimpleColumns;
+USE plato;
+SELECT * FROM
+ Input2 AS A
+JOIN
+ Input4 AS B
+ON
+ (A.key == B.key) AND
+ (A.subkey == B.subkey) AND
+ (A.value == B.value)
+;
diff --git a/yql/essentials/tests/sql/suites/join/trivial_view-off.cfg b/yql/essentials/tests/sql/suites/join/trivial_view-off.cfg
new file mode 100644
index 0000000000..43f157699a
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/trivial_view-off.cfg
@@ -0,0 +1,4 @@
+in Input1 view_input.txt
+in Input2 input.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/trivial_view.cfg b/yql/essentials/tests/sql/suites/join/trivial_view.cfg
new file mode 100644
index 0000000000..3f072cc800
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/trivial_view.cfg
@@ -0,0 +1,2 @@
+in Input1 view_input.txt
+in Input2 input.txt
diff --git a/yql/essentials/tests/sql/suites/join/trivial_view.sql b/yql/essentials/tests/sql/suites/join/trivial_view.sql
new file mode 100644
index 0000000000..8534f3a0c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/trivial_view.sql
@@ -0,0 +1,9 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+/* syntax version 1 */
+use plato;
+SELECT a.v, b.value
+FROM `Input1` VIEW `ksv` AS a
+JOIN `Input2` AS b
+ON a.k == b.key
+ORDER BY a.v;
diff --git a/yql/essentials/tests/sql/suites/join/two_aggrs.sql b/yql/essentials/tests/sql/suites/join/two_aggrs.sql
new file mode 100644
index 0000000000..1be595ca17
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/two_aggrs.sql
@@ -0,0 +1,18 @@
+USE plato;
+
+PRAGMA yt.JoinMergeForce = "1";
+pragma yt.JoinMergeTablesLimit="10";
+
+$join =
+ SELECT a.key as key1, a.subkey as subkey1
+ FROM (SELECT * FROM Input8 WHERE subkey != "bar") AS a
+ JOIN (SELECT * FROM Input8 WHERE subkey != "foo") AS b
+ ON a.key = b.key AND a.subkey = b.subkey;
+
+SELECT key1, subkey1, count(*)
+FROM $join
+GROUP COMPACT BY subkey1, key1;
+
+SELECT key1, subkey1
+FROM $join
+GROUP COMPACT BY key1, subkey1;
diff --git a/yql/essentials/tests/sql/suites/join/uniqkeys.txt b/yql/essentials/tests/sql/suites/join/uniqkeys.txt
new file mode 100644
index 0000000000..b214aab0d9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/uniqkeys.txt
@@ -0,0 +1,10 @@
+{"key"="023";"subkey"="3";"value"="aaa"};
+{"key"="037";"subkey"="5";"value"="ddd"};
+{"key"="075";"subkey"="1";"value"="abc"};
+{"key"="150";"subkey"="1";"value"="aaa"};
+{"key"="150";"subkey"="3";"value"="iii"};
+{"key"="150";"subkey"="8";"value"="zzz"};
+{"key"="200";"subkey"="7";"value"="qqq"};
+{"key"="527";"subkey"="4";"value"="bbb"};
+{"key"="761";"subkey"="6";"value"="ccc"};
+{"key"="911";"subkey"="2";"value"="kkk"};
diff --git a/yql/essentials/tests/sql/suites/join/uniqkeys.txt.attr b/yql/essentials/tests/sql/suites/join/uniqkeys.txt.attr
new file mode 100644
index 0000000000..e847d48e3e
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/uniqkeys.txt.attr
@@ -0,0 +1,12 @@
+{"_yql_row_spec"={
+ "Type"=["StructType";[
+ ["key";["DataType";"String"]];
+ ["subkey";["DataType";"String"]];
+ ["value";["DataType";"String"]]
+ ]];
+ "SortDirections"=[1;1;];
+ "SortedBy"=["key";"subkey";];
+ "SortedByTypes"=[["DataType";"String";];["DataType";"String";];];
+ "SortMembers"=["key";"subkey";];
+ "UniqueKeys"=%true
+}}
diff --git a/yql/essentials/tests/sql/suites/join/view_input.txt b/yql/essentials/tests/sql/suites/join/view_input.txt
new file mode 100644
index 0000000000..e1faba7b62
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/view_input.txt
@@ -0,0 +1,3 @@
+{"key"="foo";"subkey"="bar";"value"="jar"};
+{"key"="bar";"subkey"="jar";"value"="foo"};
+{"key"="jar";"subkey"="foo";"value"="baz"};
diff --git a/yql/essentials/tests/sql/suites/join/view_input.txt.attr b/yql/essentials/tests/sql/suites/join/view_input.txt.attr
new file mode 100644
index 0000000000..22c3547210
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/view_input.txt.attr
@@ -0,0 +1,31 @@
+{
+ "_yql_view_ksv"="SELECT key as k, subkey as s, value as v FROM self";
+ "_yql_row_spec" = {
+ "Type" = [
+ "StructType";
+ [
+ [
+ "key";
+ [
+ "DataType";
+ "String"
+ ]
+ ];
+ [
+ "subkey";
+ [
+ "DataType";
+ "String"
+ ]
+ ];
+ [
+ "value";
+ [
+ "DataType";
+ "String"
+ ]
+ ]
+ ]
+ ]
+ }
+}
diff --git a/yql/essentials/tests/sql/suites/join/vk1_sorted.txt b/yql/essentials/tests/sql/suites/join/vk1_sorted.txt
new file mode 100644
index 0000000000..0210602a64
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/vk1_sorted.txt
@@ -0,0 +1,32 @@
+{"v1"="01";"k1"="1";"u1"="01"};
+{"v1"="01";"k1"="2";"u1"="02"};
+
+{"v1"="02";"k1"="1";"u1"="03"};
+{"v1"="02";"k1"="1";"u1"="04"};
+{"v1"="02";"k1"="2";"u1"="05"};
+{"v1"="02";"k1"="2";"u1"="06"};
+
+{"v1"="03";"k1"=#; "u1"="07"};
+{"v1"="03";"k1"="1";"u1"="08"};
+{"v1"="03";"k1"="2";"u1"="09"};
+
+{"v1"="04";"k1"="1";"u1"="10"};
+{"v1"="04";"k1"="2";"u1"="11"};
+
+{"v1"="05";"k1"="1";"u1"="12"};
+{"v1"="05";"k1"="2";"u1"="13"};
+
+{"v1"="06";"k1"="1";"u1"="14"};
+{"v1"="06";"k1"="2";"u1"="15"};
+
+{"v1"="07";"k1"="1";"u1"="16"};
+{"v1"="07";"k1"="2";"u1"="17"};
+
+{"v1"="08";"k1"="1";"u1"="18"};
+{"v1"="08";"k1"="2";"u1"="19"};
+
+{"v1"="09";"k1"="1";"u1"="20"};
+{"v1"="09";"k1"="2";"u1"="21"};
+
+{"v1"="10";"k1"="1";"u1"="22"};
+{"v1"="10";"k1"="2";"u1"="23"};
diff --git a/yql/essentials/tests/sql/suites/join/vk1_sorted.txt.attr b/yql/essentials/tests/sql/suites/join/vk1_sorted.txt.attr
new file mode 100644
index 0000000000..068381b88f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/vk1_sorted.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "v1";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "k1";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u1";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/vk2_sorted.txt b/yql/essentials/tests/sql/suites/join/vk2_sorted.txt
new file mode 100644
index 0000000000..1156f3cbef
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/vk2_sorted.txt
@@ -0,0 +1,22 @@
+{"v2"="02";"k2"="1";"u2"="01"};
+{"v2"="02";"k2"="1";"u2"="02"};
+{"v2"="02";"k2"="2";"u2"="03"};
+{"v2"="02";"k2"="2";"u2"="04"};
+
+{"v2"="03";"k2"="1";"u2"="05"};
+{"v2"="03";"k2"="2";"u2"="06"};
+
+{"v2"="04";"k2"="1";"u2"="07"};
+{"v2"="04";"k2"="2";"u2"="08"};
+
+{"v2"="05";"k2"="1";"u2"="09"};
+{"v2"="05";"k2"="2";"u2"="10"};
+
+{"v2"="06";"k2"="1";"u2"="11"};
+{"v2"="06";"k2"="2";"u2"="12"};
+
+{"v2"="07";"k2"="1";"u2"="13"};
+{"v2"="07";"k2"="2";"u2"="14"};
+
+{"v2"="09";"k2"="1";"u2"="15"};
+{"v2"="09";"k2"="2";"u2"="16"};
diff --git a/yql/essentials/tests/sql/suites/join/vk2_sorted.txt.attr b/yql/essentials/tests/sql/suites/join/vk2_sorted.txt.attr
new file mode 100644
index 0000000000..ff5c200f6b
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/vk2_sorted.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "v2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "k2";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u2";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/vk3_sorted.txt b/yql/essentials/tests/sql/suites/join/vk3_sorted.txt
new file mode 100644
index 0000000000..3b3797f549
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/vk3_sorted.txt
@@ -0,0 +1,8 @@
+{"v3"=#; "k3"="1";"u3"="01"};
+{"v3"=#; "k3"="2";"u3"="02"};
+
+{"v3"="04";"k3"="1";"u3"="03"};
+{"v3"="04";"k3"="2";"u3"="04"};
+
+{"v3"="05";"k3"="1";"u3"="05"};
+{"v3"="05";"k3"="2";"u3"="06"};
diff --git a/yql/essentials/tests/sql/suites/join/vk3_sorted.txt.attr b/yql/essentials/tests/sql/suites/join/vk3_sorted.txt.attr
new file mode 100644
index 0000000000..c399355613
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/vk3_sorted.txt.attr
@@ -0,0 +1,25 @@
+{
+ "schema" = <
+ "strict" = %true;
+ "unique_keys" = %false
+ >
+ [
+ {
+ "name" = "v3";
+ "required" = %false;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "k3";
+ "required" = %true;
+ "sort_order" = "ascending";
+ "type" = "string"
+ };
+ {
+ "name" = "u3";
+ "required" = %true;
+ "type" = "string"
+ }
+ ];
+}
diff --git a/yql/essentials/tests/sql/suites/join/wrong_order_by_col.sqlx b/yql/essentials/tests/sql/suites/join/wrong_order_by_col.sqlx
new file mode 100644
index 0000000000..777ffc883f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/wrong_order_by_col.sqlx
@@ -0,0 +1,16 @@
+USE plato;
+
+$input = (
+ SELECT key, subkey, value FROM Input
+);
+
+--INSERT INTO Output
+SELECT
+ i1.key as kk,
+ i2.value as val
+FROM $input as i1
+FULL JOIN $input as i2
+ON cast(i1.key as uint32) % 10 = cast(i2.subkey as uint32)
+ORDER BY
+ i1.kk, -- invalid column, should be either kk or i1.key
+ i2.val -- invalid column, should be either val or i2.value
diff --git a/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns-off.cfg b/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns.cfg b/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns.sql b/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns.sql
new file mode 100644
index 0000000000..543df58892
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-10654_pullup_with_sys_columns.sql
@@ -0,0 +1,14 @@
+/* postgres can not */
+/* syntax version 1 */
+USE plato;
+PRAGMA DisableSimpleColumns;
+
+$src =
+ select key, subkey || key as subkey, value from Input
+ union all
+ select * from AS_TABLE(ListCreate(Struct<key:String,subkey:String,value:String>));
+
+select a.key, a.subkey, b.value
+from Input as a
+left join $src as b using(key)
+order by a.key;
diff --git a/yql/essentials/tests/sql/suites/join/yql-12022-off.cfg b/yql/essentials/tests/sql/suites/join/yql-12022-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-12022-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-12022.cfg b/yql/essentials/tests/sql/suites/join/yql-12022.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-12022.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-12022.sql b/yql/essentials/tests/sql/suites/join/yql-12022.sql
new file mode 100644
index 0000000000..15766d3004
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-12022.sql
@@ -0,0 +1,13 @@
+/* postgres can not */
+/* syntax version 1 */
+USE plato;
+
+DEFINE SUBQUERY $sub($name) AS
+ SELECT * FROM $name
+END DEFINE;
+
+SELECT a.key
+FROM $sub("Input") AS a
+INNER JOIN Input AS b
+ON a.key = b.key
+WHERE JoinTableRow().`a.subkey` == "wat"
diff --git a/yql/essentials/tests/sql/suites/join/yql-14829_left-off.cfg b/yql/essentials/tests/sql/suites/join/yql-14829_left-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14829_left-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-14829_left.cfg b/yql/essentials/tests/sql/suites/join/yql-14829_left.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14829_left.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-14829_left.sql b/yql/essentials/tests/sql/suites/join/yql-14829_left.sql
new file mode 100644
index 0000000000..8e36a759e2
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14829_left.sql
@@ -0,0 +1,35 @@
+USE plato;
+
+pragma yt.JoinEnableStarJoin="true";
+
+insert into @x
+select Just('xxx') as id
+order by id;
+
+insert into @y
+select Just('yyy') as id
+order by id;
+
+insert into @a
+select Just('aaa') as id
+order by id;
+
+commit;
+
+
+$xy_left = (
+ SELECT
+ x.id AS id
+ FROM
+ ANY @x AS x
+ LEFT JOIN ANY @y AS y
+ ON x.id == y.id
+);
+
+SELECT
+ *
+FROM
+ ANY @a AS a
+ LEFT JOIN ANY $xy_left AS b
+ ON a.id == b.id;
+
diff --git a/yql/essentials/tests/sql/suites/join/yql-14829_leftonly-off.cfg b/yql/essentials/tests/sql/suites/join/yql-14829_leftonly-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14829_leftonly-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-14829_leftonly.cfg b/yql/essentials/tests/sql/suites/join/yql-14829_leftonly.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14829_leftonly.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-14829_leftonly.sql b/yql/essentials/tests/sql/suites/join/yql-14829_leftonly.sql
new file mode 100644
index 0000000000..50ef1bae40
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14829_leftonly.sql
@@ -0,0 +1,35 @@
+USE plato;
+
+pragma yt.JoinEnableStarJoin="true";
+
+insert into @x
+select Just('xxx') as id
+order by id;
+
+insert into @y
+select Just('yyy') as id
+order by id;
+
+insert into @a
+select Just('aaa') as id
+order by id;
+
+commit;
+
+
+$xy_leftonly = (
+ SELECT
+ x.id AS id
+ FROM
+ @x AS x
+ LEFT ONLY JOIN @y AS y
+ ON x.id == y.id
+);
+
+SELECT
+ *
+FROM
+ @a AS a
+ LEFT ONLY JOIN $xy_leftonly AS b
+ ON a.id == b.id;
+
diff --git a/yql/essentials/tests/sql/suites/join/yql-14847-off.cfg b/yql/essentials/tests/sql/suites/join/yql-14847-off.cfg
new file mode 100644
index 0000000000..86539293ac
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14847-off.cfg
@@ -0,0 +1,5 @@
+in Input1 input1.txt
+in Input2 input7.txt
+in Input3 input3.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-14847.cfg b/yql/essentials/tests/sql/suites/join/yql-14847.cfg
new file mode 100644
index 0000000000..5cac58c60c
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14847.cfg
@@ -0,0 +1,3 @@
+in Input1 input1.txt
+in Input2 input7.txt
+in Input3 input3.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-14847.sql b/yql/essentials/tests/sql/suites/join/yql-14847.sql
new file mode 100644
index 0000000000..25d2f0394f
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-14847.sql
@@ -0,0 +1,23 @@
+USE plato;
+
+pragma yt.MapJoinLimit="1M";
+
+$t = (
+SELECT
+ l.key as key,
+ r.subkey as subkey,
+ l.value || r.value as value
+FROM
+ Input1 as l
+CROSS JOIN
+ Input2 as r
+);
+
+SELECT
+ l.*,
+ r.value as rvalue
+FROM
+ $t as l
+LEFT JOIN
+ Input3 as r
+ON l.key = coalesce("" || r.key, "")
diff --git a/yql/essentials/tests/sql/suites/join/yql-16011.cfg b/yql/essentials/tests/sql/suites/join/yql-16011.cfg
new file mode 100644
index 0000000000..bb349dd8ab
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-16011.cfg
@@ -0,0 +1 @@
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/yql-16011.sql b/yql/essentials/tests/sql/suites/join/yql-16011.sql
new file mode 100644
index 0000000000..bb8698027d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-16011.sql
@@ -0,0 +1,27 @@
+USE plato;
+
+PRAGMA AnsiInForEmptyOrNullableItemsCollections = "true";
+PRAGMA yt.MapJoinLimit="1m";
+PRAGMA yt.LookupJoinLimit="64k";
+PRAGMA yt.LookupJoinMaxRows="100";
+
+
+insert into @T1
+select Just('fooo'u) as ID order by ID;
+
+insert into @T2
+select 't' as text, '{}'y as tags, 'foo' as ID
+order by ID;
+
+commit;
+
+
+$lost_ids = SELECT ID FROM @T2 WHERE ID NOT IN (SELECT ID FROM @T1);
+$lost_samples_after_align = SELECT * FROM @T2 WHERE ID IN $lost_ids;
+
+SELECT * FROM $lost_samples_after_align;
+
+SELECT
+ text || 'a' as text,
+ tags,
+FROM $lost_samples_after_align;
diff --git a/yql/essentials/tests/sql/suites/join/yql-19081.cfg b/yql/essentials/tests/sql/suites/join/yql-19081.cfg
new file mode 100644
index 0000000000..aaba13cbfa
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-19081.cfg
@@ -0,0 +1,4 @@
+in Input1 sorted_uniq.txt
+in Input2 sorted_uniq.txt
+in Input3 input1.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/yql-19081.sql b/yql/essentials/tests/sql/suites/join/yql-19081.sql
new file mode 100644
index 0000000000..215ba02fe4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-19081.sql
@@ -0,0 +1,12 @@
+USE plato;
+
+pragma yt.JoinMergeTablesLimit="100";
+pragma yt.MapJoinLimit="10M";
+pragma yt.MaxReplicationFactorToFuseOperations="1";
+
+SELECT
+ a.key, a.subkey, c.value
+FROM Input1 as a
+JOIN /*+ merge() */ Input2 as b ON a.key = b.key AND a.subkey = b.subkey
+JOIN Input3 as c ON b.key = c.key AND b.subkey = c.subkey
+ORDER BY c.value;
diff --git a/yql/essentials/tests/sql/suites/join/yql-4275-off.cfg b/yql/essentials/tests/sql/suites/join/yql-4275-off.cfg
new file mode 100644
index 0000000000..3e2c239448
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-4275-off.cfg
@@ -0,0 +1,3 @@
+in Input yql-4275.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-4275.cfg b/yql/essentials/tests/sql/suites/join/yql-4275.cfg
new file mode 100644
index 0000000000..4461be80f4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-4275.cfg
@@ -0,0 +1 @@
+in Input yql-4275.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-4275.sql b/yql/essentials/tests/sql/suites/join/yql-4275.sql
new file mode 100644
index 0000000000..99096a7bbd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-4275.sql
@@ -0,0 +1,10 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+USE plato;
+
+SELECT
+*
+FROM Input as x1
+JOIN (select key ?? 4 as key from Input) as x2 on x1.key == x2.key
+WHERE x2.key == 4
+;
diff --git a/yql/essentials/tests/sql/suites/join/yql-4275.txt b/yql/essentials/tests/sql/suites/join/yql-4275.txt
new file mode 100644
index 0000000000..172a11b713
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-4275.txt
@@ -0,0 +1,6 @@
+{"key"=#;subkey=".";"value"="E"};
+{"key"=#;subkey=".";"value"="F"};
+{"key"=#;subkey=".";"value"="G"};
+{"key"=1;subkey=".";"value"="A"};
+{"key"=4;subkey=".";"value"="C"};
+{"key"=4;subkey=".";"value"="D"};
diff --git a/yql/essentials/tests/sql/suites/join/yql-4275.txt.attr b/yql/essentials/tests/sql/suites/join/yql-4275.txt.attr
new file mode 100644
index 0000000000..4c1e650192
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-4275.txt.attr
@@ -0,0 +1,40 @@
+{
+ "_yql_row_spec" = {
+ "SortMembers"=["key";"subkey"];"SortedBy"=["key";"subkey"];"SortDirections"=[1;1];"SortedByTypes"=[["OptionalType";["DataType";"Int32"]];["OptionalType";["DataType";"String"]]];
+ "Type" = [
+ "StructType";
+ [
+ [
+ "key";
+ [
+ "OptionalType";
+ [
+ "DataType";
+ "Int32"
+ ]
+ ]
+ ];
+ [
+ "subkey";
+ [
+ "OptionalType";
+ [
+ "DataType";
+ "String"
+ ]
+ ]
+ ];
+ [
+ "value";
+ [
+ "OptionalType";
+ [
+ "DataType";
+ "String"
+ ]
+ ]
+ ]
+ ]
+ ]
+ }
+}
diff --git a/yql/essentials/tests/sql/suites/join/yql-6199-off.cfg b/yql/essentials/tests/sql/suites/join/yql-6199-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-6199-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-6199.cfg b/yql/essentials/tests/sql/suites/join/yql-6199.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-6199.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-6199.sql b/yql/essentials/tests/sql/suites/join/yql-6199.sql
new file mode 100644
index 0000000000..bb2decf34d
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-6199.sql
@@ -0,0 +1,12 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+
+$i = (select 1 as key);
+
+$j1 = (select a2.key,b.key as k from $i as a2 join $i as b on a2.key = b.key);
+
+select a.* from $j1 as a join $i as d on a.k = d.key;
+
+$j2 = (select a.key,b.key as k from $i as a join $i as b on a.key = b.key);
+
+select a.* from $j2 as a join $i as d on a.k = d.key; \ No newline at end of file
diff --git a/yql/essentials/tests/sql/suites/join/yql-6297-off.cfg b/yql/essentials/tests/sql/suites/join/yql-6297-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-6297-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-6297.cfg b/yql/essentials/tests/sql/suites/join/yql-6297.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-6297.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-6297.sql b/yql/essentials/tests/sql/suites/join/yql-6297.sql
new file mode 100644
index 0000000000..1d8bd0c1de
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-6297.sql
@@ -0,0 +1,21 @@
+PRAGMA DisableSimpleColumns;
+/* postgres can not */
+$input = (
+select 2 as id,
+3 as taskId,
+4 as previousId
+union all
+
+select 1 as id,
+null as taskId,
+2 as previousId
+);
+
+SELECT count(*)
+FROM $input AS diff
+INNER JOIN $input AS taskSuite ON diff.previousId = taskSuite.id
+LEFT JOIN $input AS pedestrian ON diff.taskId = pedestrian.id
+WHERE
+diff.id = 1
+;
+
diff --git a/yql/essentials/tests/sql/suites/join/yql-8125-off.cfg b/yql/essentials/tests/sql/suites/join/yql-8125-off.cfg
new file mode 100644
index 0000000000..76a2a2b6a4
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8125-off.cfg
@@ -0,0 +1,3 @@
+in Input input_intersect.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-8125.cfg b/yql/essentials/tests/sql/suites/join/yql-8125.cfg
new file mode 100644
index 0000000000..3df7813790
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8125.cfg
@@ -0,0 +1 @@
+in Input input_intersect.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-8125.sql b/yql/essentials/tests/sql/suites/join/yql-8125.sql
new file mode 100644
index 0000000000..b3d81a5509
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8125.sql
@@ -0,0 +1,29 @@
+use plato;
+
+PRAGMA yt.JoinCollectColumnarStatistics="async";
+
+INSERT INTO @yang_ids
+SELECT
+ *
+ from Input
+ where subkey <= "3"
+ LIMIT 100;
+commit;
+
+INSERT INTO @yang_ids
+ SELECT
+ *
+ from Input as j
+ LEFT ONLY JOIN @yang_ids
+ USING(key);
+commit;
+
+INSERT INTO @yang_ids
+ SELECT
+ *
+ from Input as j
+ LEFT ONLY JOIN @yang_ids
+ USING(key);
+commit;
+
+select * from @yang_ids;
diff --git a/yql/essentials/tests/sql/suites/join/yql-8131-off.cfg b/yql/essentials/tests/sql/suites/join/yql-8131-off.cfg
new file mode 100644
index 0000000000..be399805c7
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8131-off.cfg
@@ -0,0 +1,2 @@
+in Input input_intersect.txt
+providers yt
diff --git a/yql/essentials/tests/sql/suites/join/yql-8131.cfg b/yql/essentials/tests/sql/suites/join/yql-8131.cfg
new file mode 100644
index 0000000000..32d89a04e1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8131.cfg
@@ -0,0 +1,3 @@
+in Input input_intersect.txt
+providers yt
+
diff --git a/yql/essentials/tests/sql/suites/join/yql-8131.sql b/yql/essentials/tests/sql/suites/join/yql-8131.sql
new file mode 100644
index 0000000000..bcdb5aa485
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8131.sql
@@ -0,0 +1,14 @@
+/* kikimr can not */
+use plato;
+
+PRAGMA DisableSimpleColumns;
+PRAGMA yt.JoinCollectColumnarStatistics="async";
+PRAGMA yt.MinTempAvgChunkSize="0";
+PRAGMA yt.MapJoinLimit="1";
+
+SELECT *
+FROM (select distinct key,subkey from Input where cast(key as Int32) > 100 order by key limit 100) as a
+RIGHT JOIN (select key,value from Input where cast(key as Int32) < 500) as b
+USING(key)
+ORDER BY a.key,a.subkey,b.value;
+
diff --git a/yql/essentials/tests/sql/suites/join/yql-8980-off.cfg b/yql/essentials/tests/sql/suites/join/yql-8980-off.cfg
new file mode 100644
index 0000000000..61ca79e527
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8980-off.cfg
@@ -0,0 +1,7 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql-8980.cfg b/yql/essentials/tests/sql/suites/join/yql-8980.cfg
new file mode 100644
index 0000000000..5ffa9b00c0
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8980.cfg
@@ -0,0 +1,5 @@
+in Input input.txt
+in Input1 input1.txt
+in Input2 input2.txt
+in Input3 input3.txt
+in Input4 input4.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql-8980.sql b/yql/essentials/tests/sql/suites/join/yql-8980.sql
new file mode 100644
index 0000000000..e2701ee730
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql-8980.sql
@@ -0,0 +1,15 @@
+USE plato;
+
+$foo = (SELECT key, subkey, value IN ("wat", "bar") AS value FROM Input);
+
+SELECT
+ R0.key, R0.subkey, R0.value,
+ R1.key, R1.subkey, R1.value,
+ R2.key, R2.value
+FROM $foo AS R0
+LEFT JOIN $foo AS R1 ON
+ R0.subkey = R1.key
+LEFT JOIN $foo AS R2 ON
+ R1.subkey = R2.key
+ORDER BY R0.key;
+
diff --git a/yql/essentials/tests/sql/suites/join/yql_465-off.cfg b/yql/essentials/tests/sql/suites/join/yql_465-off.cfg
new file mode 100644
index 0000000000..e6a2551297
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql_465-off.cfg
@@ -0,0 +1,4 @@
+in a input1.txt
+in b input2.txt
+providers dq
+pragma Dq.HashJoinMode='off';
diff --git a/yql/essentials/tests/sql/suites/join/yql_465.cfg b/yql/essentials/tests/sql/suites/join/yql_465.cfg
new file mode 100644
index 0000000000..96c331a7fd
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql_465.cfg
@@ -0,0 +1,2 @@
+in a input1.txt
+in b input2.txt
diff --git a/yql/essentials/tests/sql/suites/join/yql_465.sql b/yql/essentials/tests/sql/suites/join/yql_465.sql
new file mode 100644
index 0000000000..4054dc97c9
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/join/yql_465.sql
@@ -0,0 +1,3 @@
+PRAGMA DisableSimpleColumns;
+use plato;
+select * from (select * from a where a.key > "zzz") as a join b on a.key == b.key;