Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect row numbers in recursive queries #3483

Open
marschall opened this issue Apr 14, 2022 · 6 comments
Open

Incorrect row numbers in recursive queries #3483

marschall opened this issue Apr 14, 2022 · 6 comments
Assignees
Labels
WITH clause Related to the WITH clause implementation.

Comments

@marschall
Copy link
Contributor

We are using the following recursive CTE to fetch multiple sequence values in one database round trip

WITH RECURSIVE t(n, level_num) AS (
  SELECT NEXT VALUE FOR demo_squence AS n, 1 AS level_num
    UNION ALL
  SELECT NEXT VALUE FOR demo_squence AS n, level_num + 1 AS level_num
    FROM t
   WHERE level_num < ?)
SELECT n
  FROM t

With 1.4.200 this used to generate [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] but starting with 2.0.202 it generates [1, 2, 2, 2, 2, 2, 2, 2, 2, 2]. It is still broken with 2.1.212.

Full code example

public class RecursiveCteTest {

  private static final String CREATE_SEQUENCE = "CREATE SEQUENCE demo_squence "
                                                + " CACHE 10 "
                                                + " NO CYCLE ";
  
  private static final String SELECT_SEQUENCE_VALUES = 
        " WITH RECURSIVE t(n, level_num) AS ( "
      + "   SELECT NEXT VALUE FOR demo_squence AS n, 1 AS level_num "
      + "     UNION ALL "
      + "   SELECT NEXT VALUE FOR demo_squence AS n, level_num + 1 AS level_num "
      + "     FROM t "
      + "    WHERE level_num < ?) "
      + " SELECT n"
      + "   FROM t ";

  public static void main(String[] args) throws SQLException {
    try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:")) {
      try (Statement statement = connection.createStatement()) {
        statement.execute(CREATE_SEQUENCE);
      }
      List<Integer> sequenceValues = new ArrayList<>(10); 
      try (PreparedStatement selectSequenceValues = connection.prepareStatement(SELECT_SEQUENCE_VALUES)) {
        selectSequenceValues.setInt(1, 10);
        try (ResultSet resultSet = selectSequenceValues.executeQuery()) {
          while (resultSet.next()) {
            sequenceValues.add(resultSet.getInt(1));
          }
        }
      }
      System.out.println(sequenceValues);
    }
  }

}
@marschall marschall changed the title Sequence Value no longer incremented in recursive CTE Sequence value no longer incremented in recursive CTE Apr 14, 2022
@katzyn
Copy link
Contributor

katzyn commented Apr 15, 2022

Recursive CTEs are experimental in H2 and may have any issues.

I think this query worked in H2 only due to buggy implementation of sequence value expressions in old versions of H2. New versions properly return the same value within a processed row as required by the SQL Standard in Regular and some other compatibility modes. H2 incorrectly determines all additional rows from recursive query as the same row, that's why you see only two different values, first one is produced by a first part of union, and all remaining rows are produced by its second part. Combination of two different unrelated bugs led to correct results, but when first bug was resolved the second bug was revealed.

Actually this query is overcomplicated, you can use something like

SELECT NEXT VALUE FOR sequenceName FROM SYSTEM_RANGE(1, 10);

But if you need to use standard syntax only, you can move sequence value expression outside of recursive part as a workaround:

WITH RECURSIVE T(N) AS (
  SELECT 1
  UNION ALL
  SELECT N + 1 FROM T WHERE N < 10
)
SELECT NEXT VALUE FOR sequenceName FROM T;

@katzyn katzyn changed the title Sequence value no longer incremented in recursive CTE Incorrect row numbers in recursive queries Apr 15, 2022
@marschall
Copy link
Contributor Author

Thank you for pointing out the alternatives. That solves our issue.

@manticore-projects manticore-projects added the WITH clause Related to the WITH clause implementation. label Jan 23, 2024
@manticore-projects manticore-projects self-assigned this Feb 13, 2024
@manticore-projects
Copy link
Contributor

@marschall

Please retry with latest GIT 4497462. It should be fixed now. Please close when confirmed.

@katzyn
Copy link
Contributor

katzyn commented Feb 13, 2024

This minor bug is still here.

@marschall
Copy link
Contributor Author

I'm trying to retry. I'll first have to fix an issue that Hibernate does not run with -SNAPSHOT versions of H2.

@marschall
Copy link
Contributor Author

@manticore-projects I built H2 from source with a modified Hibernate version, as @katzyn said, 4497462 does not fix the issue and the issue is still present

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WITH clause Related to the WITH clause implementation.
Projects
None yet
Development

No branches or pull requests

3 participants