public QueryObjectBundle rewriteQuery(@Language("SQL") String query, QueryConfiguration queryConfiguration, ClusterType clusterType)
    {
        return rewriteQuery(query, queryConfiguration, clusterType, false);
    }
@Test
    public void testRewriteFunctionCalls()
    {
        VerifierConfig verifierConfig = new VerifierConfig().setFunctionSubstitutes(
                "/approx_distinct(x)/count(x)/," +
                        "/approx_percentile(x,array[0.9])/repeat(avg(x),cast(cardinality(array[0.9]) as integer))/," +
                        "/approx_percentile(x,_)/avg(x)/," +
                        "/arbitrary(x)/min(x)/," +
                        "/array_agg(x)/if(typeof(arbitrary(x))='integer', array_sort(array_agg(x)), array_agg(x))/," +
                        "/current_timestamp/timestamp '2023-01-01 00:00:00 UTC'/," +
                        "/first_value(x)/if(min(x) is not null, min(x), max(x))/," +
                        "/max_by(x,_)/max(x)/," +
                        "/map_agg(x,y)/transform_values(multimap_agg(x,y),(k,v)->array_max(v))/," +
                        "/min_by(x,_)/min(x)/," +
                        "/now()/date_trunc('day',now())/," +
                        "/rand()/1/," +
                        "/row_number() over (partition by x order by y)/row_number() over (partition by y)/");
        QueryRewriter queryRewriter = getQueryRewriter(new QueryRewriteConfig(), verifierConfig);

        // Test rewriting nested function calls.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    TRIM(ARBITRARY(b))\n" +
                                "FROM test_table",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    TRIM(MIN(b))\n" +
                        "FROM test_table");

        // Test rewriting with nested function calls.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    MAP_AGG(a,b)\n" +
                                "FROM test_table",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    TRANSFORM_VALUES(MULTIMAP_AGG(a,b),(k,v)->ARRAY_MAX(v))\n" +
                        "FROM test_table");

        // Test rewriting with literal.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT RAND()",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT 1");

        // Test rewriting with if expression.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    ARRAY_AGG(DISTINCT a)\n" +
                                "FROM test_table",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    IF(TYPEOF(ARBITRARY(DISTINCT a))='integer', ARRAY_SORT(ARRAY_AGG(DISTINCT a)), ARRAY_AGG(DISTINCT a))\n" +
                        "FROM test_table");

        // Test rewriting CurrentTime function.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    TO_UNIXTIME(CURRENT_TIMESTAMP)\n" +
                                "FROM test_table",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    TO_UNIXTIME(TIMESTAMP '2023-01-01 00:00:00 UTC')\n" +
                        "FROM test_table");

        // Test rewriting NOW function.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    TO_UNIXTIME(NOW())\n" +
                                "FROM test_table",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    TO_UNIXTIME(DATE_TRUNC('day',NOW()))\n" +
                        "FROM test_table");

        // Test rewriting columns in Join.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT *\n" +
                                "FROM test_table x\n" +
                                "JOIN (\n" +
                                "    SELECT\n" +
                                "        b,\n" +
                                "        APPROX_PERCENTILE(a, 0.5) AS a\n" +
                                "    FROM test_table\n" +
                                "    GROUP BY\n" +
                                "        1\n" +
                                ") y\n" +
                                "    ON (x.b = y.b)",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT *\n" +
                        "FROM test_table x\n" +
                        "JOIN (\n" +
                        "    SELECT\n" +
                        "        b,\n" +
                        "        AVG(a) AS a\n" +
                        "    FROM test_table\n" +
                        "    GROUP BY\n" +
                        "        1\n" +
                        ") y\n" +
                        "    ON (x.b = y.b)");

        // Test rewriting columns in SubqueryExpression.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT a, b\n" +
                                "FROM test_table\n" +
                                "WHERE a IN (\n" +
                                "    SELECT\n" +
                                "        ARBITRARY(a)\n" +
                                "    FROM test_table\n" +
                                ")",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT a, b\n" +
                        "FROM test_table\n" +
                        "WHERE a IN (\n" +
                        "    SELECT\n" +
                        "        MIN(a)\n" +
                        "    FROM test_table\n" +
                        ")");

        // Test rewriting columns in TableSubquery.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT num\n" +
                                "FROM (\n" +
                                "    SELECT\n" +
                                "        APPROX_DISTINCT(b) AS num\n" +
                                "    FROM test_table\n" +
                                ") x",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT num\n" +
                        "FROM (\n" +
                        "    SELECT\n" +
                        "        COUNT(b) AS num\n" +
                        "    FROM test_table\n" +
                        ") x");

        // Test rewriting columns in With.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "WITH x AS (\n" +
                                "    SELECT\n" +
                                "        MAX_BY(a, b) AS a\n" +
                                "    FROM test_table\n" +
                                ")\n" +
                                "SELECT\n" +
                                "    a\n" +
                                "FROM x", CONFIGURATION, CONTROL).getQuery(),
                "WITH x AS (\n" +
                        "    SELECT\n" +
                        "        MAX(a) AS a\n" +
                        "    FROM test_table\n" +
                        ")\n" +
                        "SELECT\n" +
                        "    a\n" +
                        "FROM x");

        // Test rewriting columns in Union.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    ARBITRARY(a)\n" +
                                "FROM (\n" +
                                "    SELECT \n" +
                                "       MIN_BY(a, b) AS a\n" +
                                "    FROM test_table\n" +
                                "\n" +
                                "    UNION ALL\n" +
                                "\n" +
                                "    SELECT \n" +
                                "       MIN_BY(a, b) AS a\n" +
                                "    FROM test_table\n" +
                                ") x",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    MIN(a)\n" +
                        "FROM (\n" +
                        "    SELECT \n" +
                        "       MIN(a) AS a\n" +
                        "    FROM test_table\n" +
                        "\n" +
                        "    UNION ALL\n" +
                        "\n" +
                        "    SELECT \n" +
                        "       MIN(a) AS a\n" +
                        "    FROM test_table\n" +
                        ") x");

        // Test rewriting window functions with partition and order derived from the original.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    FIRST_VALUE(a) OVER (\n" +
                                "        PARTITION BY b\n" +
                                "    )\n" +
                                "FROM test_table",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    IF(\n" +
                        "        MIN(a) OVER (\n" +
                        "            PARTITION BY\n" +
                        "                b\n" +
                        "        ) IS NOT NULL,\n" +
                        "        MIN(a) OVER (\n" +
                        "            PARTITION BY\n" +
                        "                b\n" +
                        "        ),\n" +
                        "        MAX(a) OVER (\n" +
                        "            PARTITION BY\n" +
                        "                b\n" +
                        "        )\n" +
                        "    )\n" +
                        "FROM test_table");

        // Test rewriting window functions with partition and order resolving.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    ROW_NUMBER() OVER (\n" +
                                "        PARTITION BY a\n" +
                                "        ORDER BY b DESC\n" +
                                "    )\n" +
                                "FROM test_table",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    ROW_NUMBER() OVER (\n" +
                        "        PARTITION BY b\n" +
                        "        ORDER BY b DESC\n" +
                        "    )\n" +
                        "FROM test_table");

        // Test mapping of multiple substitutions with match precedence and matching of literal arguments.
        assertCreateTableAs(
                queryRewriter.rewriteQuery(
                        "SELECT\n" +
                                "    APPROX_PERCENTILE(a, 0.95),\n" +
                                "    APPROX_PERCENTILE(a, ARRAY[0.5, 0.9])\n" +
                                "FROM test_table",
                        CONFIGURATION, CONTROL).getQuery(),
                "SELECT\n" +
                        "    AVG(a),\n" +
                        "    REPEAT(AVG(a), CAST(CARDINALITY(ARRAY[0.5, 0.9]) AS INTEGER))\n" +
                        "FROM test_table");
    }