1

h2 v1.3.176 を使用しています。
RECURSIVE クエリを実行するユーザー定義関数があります。

public static ResultSet getChildCategories(Connection connection, long categoryId) throws SQLException {
    String sql = 
            "WITH RECURSIVE r(CATEGORY_ID, PARENT_ID) AS (\n" +
            "    SELECT   CATEGORY_ID\n" +
            "            ,PARENT_ID\n" +
            "    FROM     CATEGORY\n" +
            "    WHERE    CATEGORY_ID = " + categoryId + "\n" +
            "    UNION ALL\n" +
            "    SELECT   CATEGORY.CATEGORY_ID\n" +
            "            ,CATEGORY.PARENT_ID\n" +
            "    FROM     CATEGORY, r\n" +
            "    WHERE    CATEGORY.PARENT_ID = r.CATEGORY_ID\n" +
            ")\n" +
            "SELECT CATEGORY_ID FROM r";
    ResultSet resultSet = connection.createStatement().executeQuery(sql);
    SimpleResultSet rs = new SimpleResultSet();
    rs.addColumn("CATEGORY_ID", Types.INTEGER, 12, 0);
    try {
        while(resultSet.next()) {
            rs.addRow(resultSet.getLong(1));
        }
    } finally {
        resultSet.close();
    }
    return rs;
}

次のSQLでこの関数を登録しました。

create alias GET_CHILD_CATEGORIES for "com.myapp.db.function.Functions.getChildCategories";

私の問題はgetChildCategories、次のクエリを実行すると関数が何度も呼び出されることです。

SELECT DISTINCT  B.BOOK_ID
                ,B.SERIES_ID
                ,B.TITLE
                ,B.ISBN
                ,B.VOLUME
                ,(
                    SELECT  MAX(SAME_SERIES.VOLUME)
                    FROM    BOOK SAME_SERIES
                    WHERE   SAME_SERIES.SERIES_ID = B.SERIES_ID
                    AND     SAME_SERIES.VOLUME IS NOT NULL
                ) AS VOLUME_COUNT
                ,B.PAGE_COUNT
                ,B.FILE_PATH
                ,B.SORTABLE_FILE_NAME
                ,B.SIZE
                ,B.HASH
                ,B.COVER_IMAGE_TYPE
                ,B.COVER_PAGE_NO
                ,B.COVER_LARGE_IMAGE_URL
                ,B.COVER_SMALL_IMAGE_URL
                ,B.COVER_CROP_COORD
                ,B.IS_ENCRYPT
                ,B.PUBLISHER_ID
                ,B.PUBLISHED_DATE
                ,B.CREATION_TIME
                ,B.LAST_MODIFIED_TIME
                ,B.NOTE
                ,B.IS_ISBN_SEARCH
                ,S.CATEGORY_ID
                ,S.TITLE
                ,BA.AUTHOR_ID
                ,BT.TAG_ID
FROM             BOOK AS B
INNER JOIN       SERIES AS S ON S.SERIES_ID = B.SERIES_ID
LEFT OUTER JOIN  BOOK_TAG AS BT ON BT.BOOK_ID = B.BOOK_ID
LEFT OUTER JOIN  BOOK_AUTHOR AS BA ON BA.BOOK_ID = B.BOOK_ID
WHERE 
(
    S.CATEGORY_ID IN (SELECT CATEGORY_ID FROM GET_CHILD_CATEGORIES(106))
    And 
    S.IS_COMPLETION = 1
)
ORDER BY  BA.AUTHOR_ID

なぜ何度もこの関数が呼び出されるのでしょうか?

4

1 に答える 1

1

H2ドキュメントからの抜粋

結果セットを返す関数は、テーブルのように使用できます。ただし、この場合、関数は少なくとも 2 回呼び出されます。1 回目はステートメントを解析して列名を収集するときです (コンパイル時に不明なパラメーターを null に設定します)。次に、ステートメントを実行してデータを取得します (これが結合の場合は複数回)。列リストを取得するためだけに関数が呼び出される場合、関数に渡される接続の URL は jdbc:columnlist:connection です。それ以外の場合、接続の URL は jdbc:default:connection です。

最初の呼び出しは、結果セットの列の型を取得するためだけです。次に、接続 URL が「jdbc:columnlist:connection」であるかどうかを確認する必要があります。true の場合、列リストを含む空の結果セットを返す必要があります。

接続 URL テストは次のとおりです。

connection.getMetaData().getURL().equals("jdbc:columnlist:connection");
于 2014-10-10T07:25:28.490 に答える