mysql 修改或破解jOOQ生成的DDL的方法有哪些?

gmxoilav  于 2023-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(125)

我正在广泛地使用jOOQ的模式导出特性。不幸的是,在某些情况下,jOOQ为数据库对象生成不正确或不准确的DDL。除了对生成的DDL字符串使用replace/regex命令之外,还有什么标准方法可以稍微修改生成的DDL吗?
让我们看一个例子。
1.创建表(禁用NO_ZERO_DATE模式):

set sql_mode='';
create table test_date_types_table (
  timestamp_column_nullable timestamp null,
  timestamp_column_not_null timestamp not null,
  timestamp_column_default timestamp
);

1.运行以下Java代码为表生成DDL:

Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:6000/sakila", "root", "admin");
        Configuration configuration = new DefaultConfiguration().set(conn).set(SQLDialect.MYSQL.family());
        Meta currentMeta = using(configuration).meta();

        Query[] queries = currentMeta
                .filterSchemas(v -> v.getName().equalsIgnoreCase("sakila"))
                .ddl()
                .queries();

        for (Query query : queries) {
            System.out.println(query);
        }

1.因此,我从jOOQ收到了以下DDL:

create table `sakila`.`test_date_types_table` (
  `timestamp_column_nullable` timestamp,
  `timestamp_column_not_null` timestamp not null default null,
  `timestamp_column_default` timestamp not null default null
)
  1. DDL不起作用,因为我们有not null列,默认值为null
Invalid default value for 'timestamp_column_not_null'

1.我们的可空列timestamp_column_default不再是可空的
1.我相信有效的DDL脚本应该看起来像我们的源DDL:

create table `sakila`.`test_date_types_table` (
  `timestamp_column_nullable` timestamp,
  `timestamp_column_not_null` timestamp not null,
  `timestamp_column_default` timestamp
)

我如何在不改变jOOQ核心的情况下解决这个问题和类似的问题?

ffx8fchx

ffx8fchx1#

修补jOOQ表达式树的非正则表达式方法是使用实验性的(从jOOQ 3.18开始)query object model API,例如来自ExecuteListener。您可以对整个查询进行模式匹配,直到找到要替换的正确位置,或者使用内置的query object model replacement API。这允许在呈现查询之前 * 替换查询部分。
使用替换API的一个简单示例如下:

System.out.println(ctx
    .parser()
    .parseQuery("create table t (i int not null)")
    .$replace(q -> {
        if (q instanceof QOM.CreateTable ct) {
            UnmodifiableCollection<? extends TableElement> te1 = 
                ct.$tableElements();
            UnmodifiableCollection<? extends TableElement> te2 = 
                (UnmodifiableCollection<? extends TableElement>)
                te1.$replace(x -> x instanceof Field<?> f 
                      && !f.getDataType().nullable()
                    ? DSL.field(
                          f.getQualifiedName(), 
                          f.getDataType().nullable(true)
                      )
                    : x
                );

            if (te1 != te2)
                return ct.$tableElements(te2);
        }
        return q;
    })
);

它将替换CREATE TABLE语句上的 allNOT NULL约束,结果是:

create table T (
  I int
)

另一种更复杂的方法是使用VisitListener,它允许在将QueryPart类型呈现为输出SQL时替换它们。

相关问题