|
127 | 127 | import static org.hamcrest.CoreMatchers.is; |
128 | 128 | import static org.hamcrest.CoreMatchers.notNullValue; |
129 | 129 | import static org.hamcrest.MatcherAssert.assertThat; |
| 130 | +import static org.hamcrest.Matchers.containsString; |
130 | 131 | import static org.hamcrest.Matchers.hasToString; |
| 132 | +import static org.hamcrest.Matchers.not; |
131 | 133 | import static org.junit.jupiter.api.Assertions.assertFalse; |
132 | 134 | import static org.junit.jupiter.api.Assertions.assertTrue; |
133 | 135 |
|
@@ -11887,6 +11889,109 @@ public Sql schema(CalciteAssert.SchemaSpec schemaSpec) { |
11887 | 11889 | sql(sql).schema(CalciteAssert.SchemaSpec.JDBC_SCOTT).ok(expected); |
11888 | 11890 | } |
11889 | 11891 |
|
| 11892 | + /** Test case for |
| 11893 | + * <a href="https://issues.apache.org/jira/browse/CALCITE-7439">[CALCITE-7439] |
| 11894 | + * RelToSqlConverter emits ambiguous GROUP BY after LEFT JOIN USING with |
| 11895 | + * semi-join rewrite.</a>. */ |
| 11896 | + @Test void testPostgresqlRoundTripDistinctLeftJoinInSubqueryWithSemiJoinRules() { |
| 11897 | + final String query = "WITH product_keys AS (\n" |
| 11898 | + + " SELECT p.\"product_id\",\n" |
| 11899 | + + " (SELECT MAX(p3.\"product_id\")\n" |
| 11900 | + + " FROM \"foodmart\".\"product\" p3\n" |
| 11901 | + + " WHERE p3.\"product_id\" = p.\"product_id\") AS \"mx\"\n" |
| 11902 | + + " FROM \"foodmart\".\"product\" p\n" |
| 11903 | + + ")\n" |
| 11904 | + + "SELECT DISTINCT pk.\"product_id\"\n" |
| 11905 | + + "FROM product_keys pk\n" |
| 11906 | + + "LEFT JOIN \"foodmart\".\"product\" p2 USING (\"product_id\")\n" |
| 11907 | + + "WHERE pk.\"product_id\" IN (\n" |
| 11908 | + + " SELECT p4.\"product_id\"\n" |
| 11909 | + + " FROM \"foodmart\".\"product\" p4\n" |
| 11910 | + + ")"; |
| 11911 | + |
| 11912 | + final RuleSet rules = |
| 11913 | + RuleSets.ofList(CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE, |
| 11914 | + CoreRules.FILTER_SUB_QUERY_TO_CORRELATE, |
| 11915 | + CoreRules.JOIN_SUB_QUERY_TO_CORRELATE, |
| 11916 | + CoreRules.PROJECT_SUB_QUERY_TO_MARK_CORRELATE, |
| 11917 | + CoreRules.FILTER_SUB_QUERY_TO_MARK_CORRELATE, |
| 11918 | + CoreRules.MARK_TO_SEMI_OR_ANTI_JOIN_RULE, |
| 11919 | + CoreRules.PROJECT_TO_SEMI_JOIN); |
| 11920 | + |
| 11921 | + final String generated = sql(query).withPostgresql().optimize(rules, null).exec(); |
| 11922 | + assertThat(generated, containsString("GROUP BY \"t2\".\"product_id\"")); |
| 11923 | + } |
| 11924 | + |
| 11925 | + /** Test case for |
| 11926 | + * <a href="https://issues.apache.org/jira/browse/CALCITE-7439">[CALCITE-7439] |
| 11927 | + * RelToSqlConverter should not emit ambiguous GROUP BY after RIGHT JOIN USING |
| 11928 | + * with semi-join rewrite.</a>. */ |
| 11929 | + @Test void testPostgresqlRoundTripDistinctRightJoinInSubqueryWithSemiJoinRules() { |
| 11930 | + final String query = "WITH product_keys AS (\n" |
| 11931 | + + " SELECT p.\"product_id\",\n" |
| 11932 | + + " (SELECT MAX(p3.\"product_id\")\n" |
| 11933 | + + " FROM \"foodmart\".\"product\" p3\n" |
| 11934 | + + " WHERE p3.\"product_id\" = p.\"product_id\") AS \"mx\"\n" |
| 11935 | + + " FROM \"foodmart\".\"product\" p\n" |
| 11936 | + + ")\n" |
| 11937 | + + "SELECT DISTINCT pk.\"product_id\"\n" |
| 11938 | + + "FROM product_keys pk\n" |
| 11939 | + + "RIGHT JOIN \"foodmart\".\"product\" p2 USING (\"product_id\")\n" |
| 11940 | + + "WHERE pk.\"product_id\" IN (\n" |
| 11941 | + + " SELECT p4.\"product_id\"\n" |
| 11942 | + + " FROM \"foodmart\".\"product\" p4\n" |
| 11943 | + + ")"; |
| 11944 | + |
| 11945 | + final RuleSet rules = |
| 11946 | + RuleSets.ofList(CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE, |
| 11947 | + CoreRules.FILTER_SUB_QUERY_TO_CORRELATE, |
| 11948 | + CoreRules.JOIN_SUB_QUERY_TO_CORRELATE, |
| 11949 | + CoreRules.PROJECT_SUB_QUERY_TO_MARK_CORRELATE, |
| 11950 | + CoreRules.FILTER_SUB_QUERY_TO_MARK_CORRELATE, |
| 11951 | + CoreRules.MARK_TO_SEMI_OR_ANTI_JOIN_RULE, |
| 11952 | + CoreRules.PROJECT_TO_SEMI_JOIN); |
| 11953 | + |
| 11954 | + final String generated = sql(query).withPostgresql().optimize(rules, null).exec(); |
| 11955 | + assertThat(generated, containsString("GROUP BY ")); |
| 11956 | + assertThat(generated, containsString(".\"product_id\"")); |
| 11957 | + assertThat(generated, not(containsString("GROUP BY \"product_id\""))); |
| 11958 | + } |
| 11959 | + |
| 11960 | + /** Test case for |
| 11961 | + * <a href="https://issues.apache.org/jira/browse/CALCITE-7439">[CALCITE-7439] |
| 11962 | + * RelToSqlConverter should not emit ambiguous GROUP BY after FULL JOIN USING |
| 11963 | + * with semi-join rewrite.</a>. */ |
| 11964 | + @Test void testPostgresqlRoundTripDistinctFullJoinInSubqueryWithSemiJoinRules() { |
| 11965 | + final String query = "WITH product_keys AS (\n" |
| 11966 | + + " SELECT p.\"product_id\",\n" |
| 11967 | + + " (SELECT MAX(p3.\"product_id\")\n" |
| 11968 | + + " FROM \"foodmart\".\"product\" p3\n" |
| 11969 | + + " WHERE p3.\"product_id\" = p.\"product_id\") AS \"mx\"\n" |
| 11970 | + + " FROM \"foodmart\".\"product\" p\n" |
| 11971 | + + ")\n" |
| 11972 | + + "SELECT DISTINCT pk.\"product_id\"\n" |
| 11973 | + + "FROM product_keys pk\n" |
| 11974 | + + "FULL JOIN \"foodmart\".\"product\" p2 USING (\"product_id\")\n" |
| 11975 | + + "WHERE pk.\"product_id\" IN (\n" |
| 11976 | + + " SELECT p4.\"product_id\"\n" |
| 11977 | + + " FROM \"foodmart\".\"product\" p4\n" |
| 11978 | + + ")"; |
| 11979 | + |
| 11980 | + final RuleSet rules = |
| 11981 | + RuleSets.ofList(CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE, |
| 11982 | + CoreRules.FILTER_SUB_QUERY_TO_CORRELATE, |
| 11983 | + CoreRules.JOIN_SUB_QUERY_TO_CORRELATE, |
| 11984 | + CoreRules.PROJECT_SUB_QUERY_TO_MARK_CORRELATE, |
| 11985 | + CoreRules.FILTER_SUB_QUERY_TO_MARK_CORRELATE, |
| 11986 | + CoreRules.MARK_TO_SEMI_OR_ANTI_JOIN_RULE, |
| 11987 | + CoreRules.PROJECT_TO_SEMI_JOIN); |
| 11988 | + |
| 11989 | + final String generated = sql(query).withPostgresql().optimize(rules, null).exec(); |
| 11990 | + assertThat(generated, containsString("GROUP BY ")); |
| 11991 | + assertThat(generated, containsString(".\"product_id\"")); |
| 11992 | + assertThat(generated, not(containsString("GROUP BY \"product_id\""))); |
| 11993 | + } |
| 11994 | + |
11890 | 11995 | @Test void testNotBetween() { |
11891 | 11996 | Sql f = fixture().withConvertletTable(new SqlRexConvertletTable() { |
11892 | 11997 | @Override public @Nullable SqlRexConvertlet get(SqlCall call) { |
|
0 commit comments