H2 User defined aggregate function, ListAgg, can't use DISTINCT or TRIM() on the first parameter

戏子无情 提交于 2021-02-07 20:35:53

问题


So I have a DB2 production database in which I need to use the available function ListAgg. I would like my unit test, which is using H2, to correctly test this functionality. Unfortunately H2 does not support ListAgg directly. I can, however, create a user defined aggregate function...

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.h2.api.AggregateFunction;

import com.google.common.base.Joiner;

public class ListAgg implements AggregateFunction
{

private List<String> values = new ArrayList<String>();
private String delimiter = ",";

@Override
public void init(Connection conn) throws SQLException
{
}

@Override
public int getType(int[] inputTypes) throws SQLException
{
    if (inputTypes.length != 2) {
        throw new java.sql.SQLException("The aggregate function ListAgg must have 2 arguments.");
    }
    return java.sql.Types.VARCHAR;
}

@Override
public void add(Object sqlValues) throws SQLException
{
    Object[] objects = (Object[]) sqlValues;
    this.delimiter = (String) objects[1];
    String value = (String) objects[0];
    values.add(value);
}

@Override
public Object getResult() throws SQLException
{
    return Joiner.on(delimiter).join(values);
}

}

Which I have done. This works just fine for

ListAgg(columnName, ',')

But fails for

ListAgg(DISTINCT TRIM(columnName), ',')

What am I missing?

EDIT: I get the following error message:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback;
bad SQL grammar [select ..., LISTAGG(DISTINCT TRIM(columnName), ',') as 
columnName_LIST, from ... group by ...]; nested exception is 
org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "SELECT ... "; 
expected "NOT, EXISTS, INTERSECTS, SELECT, FROM"; SQL statement:
select ... from ... group by ... [42001-174]    
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231) 
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)

EDIT2:

Does COUNT() also implement AggregateFunction or is it using something else internally? Because H2 is able to handle COUNT(DISTINCT columnName)


回答1:


I don't think H2 allows you to use the DISTINCT keyword on your custom aggregate functions. But you can easily define your own "distinct" version of ListAgg:

public class DistinctListAgg implements AggregateFunction {
    private Set<String> values = new LinkedHashSet<String>();
    // The rest is the same
}


来源:https://stackoverflow.com/questions/33047121/h2-user-defined-aggregate-function-listagg-cant-use-distinct-or-trim-on-the

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!