创建适用于 H2 中的字符串和数字的别名

问题描述 投票:0回答:1

我想为 H2 中的 IF 函数创建一个别名,以实现 MySQL 兼容性,如 此处要求Vituels 答案解释了如何使用 CREATE ALIAS 来做到这一点:

CREATE ALIAS IF NOT EXISTS `IF` AS $$
    String ifFunction(boolean condition, String exp1, String exp2){
        if(condition) {
            return exp1;
        } else {
            return exp2;
        }
    }
$$;

如果您将别名与字符串参数一起使用,则此方法有效,但不适用于数字。如果我在别名定义中使用

Integer
而不是
String
,则相反。使用
Object
不适用于这两种类型。

有没有办法编写

ifFunction
以便它适用于任意数据类型?

这个类似问题的答案指出,如果多个方法具有不同数量的参数,则可以将多个方法绑定到别名。这对我不起作用,因为我需要相同数量的参数,但对于多种数据类型。

database h2
1个回答
0
投票

在H2中,函数有固定的返回类型,如果你想要动态返回类型,你可以使用Aggregate,就像这样:

import org.h2.api.Aggregate;

import java.lang.reflect.Array;
import java.sql.Connection;
import java.sql.SQLException;

public class IfFunction implements Aggregate {

    boolean isTrue;
    Object exp1;
    Object exp2;

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

    @Override
    public int getInternalType(int[] ints) {
        if (ints[1] <= 0) {
            if (ints[2] <= 0) {
                return 1;
            }
            return ints[2];
        }
        return ints[1];
    }

    @Override
    public void add(Object o) throws SQLException {
        if (o != null && o.getClass().isArray()) {
            isTrue = (boolean) Array.get(o, 0);
            exp1 = Array.get(o, 1);
            exp2 = Array.get(o, 2);
        } else {
            throw new SQLException("o is not an array");
        }
    }

    @Override
    public Object getResult() throws SQLException {
        return isTrue ? exp1 : exp2;
    }
}
@Test
public void testIf() {
    String ifFunction = "CREATE AGGREGATE `IF` FOR \"" + IfFunction.class.getName() + "\"";
    em.createNativeQuery(ifFunction).executeUpdate();

    assertEquals("a", em.createNativeQuery("select IF(1=1, 'a', 'b')").getResultList().get(0));
    assertEquals("b", em.createNativeQuery("select IF(1=2, 'a', 'b')").getResultList().get(0));
    assertEquals(1, em.createNativeQuery("select IF(1=1, 1, 2)").getResultList().get(0));
    assertEquals(2, em.createNativeQuery("select IF(1=2, 1, 2)").getResultList().get(0));
    assertEquals(1, em.createNativeQuery("select IF(1=1, 1, null)").getResultList().get(0));
    assertEquals(2, em.createNativeQuery("select IF(1=2, null, 2)").getResultList().get(0));
    assertNull(em.createNativeQuery("select IF(1=1, null, null)").getResultList().get(0));
}
© www.soinside.com 2019 - 2024. All rights reserved.