jOOQ 覆盖特定方言的类型长度

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

我想创建一个

DataType
,其行为类似于
SQLDataType.VARCHAR
,除了在 sql server 上它的长度是指定长度的三倍,这可能吗?

以下代码应在 MySQL 上创建

varchar(15)
,但在 SQL Server 上创建
varchar(45)

create.createTable("table")
      .column("col1", myVarchar.length(15))
      .execute();

我认为这会起作用,如果

construct()
方法和大
DefaultDataType
构造函数不是包私有的:

myVarchar = new DefaultDataType<>(null, String.class, "varchar(l)");
new DefaultDataType<>(SQLDialect.MYSQL, myVarchar, "varchar", "char");
new SqlServerCharType(myVarchar);

private class SqlServerCharType extends DefaultDataType<String> {
    public SqlServerCharType(DataType<String> baseType) {
        super(SQLDialect.SQLSERVER, baseType, "varchar", "varchar(max)");
    }

    DefaultDataType<String> construct(Integer newPrecision, Integer newScale, Integer newLength, Nullability newNullability, boolean newReadonly, Generator<?, ?, String> newGeneratedAlwaysAs, QOM.GenerationOption newGenerationOption, QOM.GenerationLocation newGenerationLocation, Collation newCollation, CharacterSet newCharacterSet, boolean newIdentity, Field<String> newDefaultValue) {
        return new DefaultDataType(this, newPrecision, newScale, newLength * 3, newNullability, newReadonly, newGeneratedAlwaysAs, newGenerationOption, newGenerationLocation, newCollation, newCharacterSet, newIdentity, newDefaultValue);
    }
}

是否可以用

Binding
来做到这一点?我唯一的选择是等到建立连接、了解方言后再做这样的事情吗?

create.createTable("table")
      .column("col1", multiply(create, SQLDataType.VARCHAR(15))
      .execute();
...
private <T> DataType<T> multiply(Scope scope, DataType<T> type) {
    if (scope.dialect().family().equals(SQLDialect.SQLSERVER) && type.isString()) {
        return type.length(type.length() * 3);
    }
    return type;
}
java jooq
1个回答
0
投票

如果您的条件匹配,您可以实现一个

ExecuteListener
来替换任何
QOM.CreateTable
查询,如果您的条件匹配,例如:

ExecuteListener.onRenderStart(ctx -> {
    if (ctx.family() == SQLSERVER
        && ctx.query() instanceof QOM.CreateTable ct
    ) {
        if (ct.$tableElements().stream().anyMatch(e ->
            e instanceof Field<?> f && f.getDataType().isString()
        )) {
            ctx.query(ct.$tableElements(ct.$tableElements()
                .stream()
                .map(e -> {
                    if (e instanceof Field<?> f && f.getDataType().isString())
                        return DSL.field(
                            f.getQualifiedName(),
                            f.getDataType().length(f.getDataType().length() * 3)
                        );
                    else
                        return e;
                })
                .toList()
            ));
        }
    }
});

现在,这将适用于 jOOQ 的任何地方,包括例如解析器:

configuration.set(l);
configuration.dsl()
             .parser()
             .parseQuery("create table t (i int, j varchar(10))")
             .execute();

您可以在日志中看到:

Executing query          : create table t (i int, j varchar(30))
© www.soinside.com 2019 - 2024. All rights reserved.