SQLDelight MySQL方言能否绕过语法检查支持未识别表达式?
SQLDelight MySQL方言绕过JSON函数语法检查的实现方案
针对你需要执行带JSON_OBJECT的迁移语句、不需要结果映射回Kotlin层的场景,不需要扩展方言实现,也不用在Kotlin层做数据转换,直接用以下两种方案即可:
- 使用驱动原生执行API透传SQL
SQLDelight底层驱动提供了跳过编译期语法解析的原始语句执行接口,整段SQL会直接下发给MySQL执行,完全不会触发SQLDelight的方言语法校验。因为你的迁移语句不需要返回结果集映射,这个方案实现成本最低。
参考实现代码:
注意:MySQL原生不支持driver.execute( identifier = null, sql = "INSERT IGNORE INTO new_table SELECT id, a, b, JSON_OBJECT('c', c, 'd', JSON_OBJECT(...)) FROM old_table WHERE id = ?", parameterCount = 1 ) { bindLong(0, targetRecordId) // 按占位符顺序绑定参数,索引从0开始 }INSERT OR IGNORE语法,需要替换为INSERT IGNORE,否则语句下发到MySQL后会报语法错误。 - 在.sq文件中标记跳过语句校验
如果你想保留SQLDelight自动生成参数绑定代码的能力,可以在.sq文件中对应语句前加校验跳过注释,SQLDelight生成代码时不会校验该语句的语法合法性,但依然会正常生成带参数绑定的调用方法:
编写完成后正常编译项目,就可以像调用其他SQLDelight生成的方法一样调用-- @sqldelight:skip-validation migrateOldToNew: INSERT IGNORE INTO new_table SELECT id, a, b, JSON_OBJECT('c', c, 'd', JSON_OBJECT(...)) FROM old_table WHERE id = ?;migrateOldToNew(id)方法执行迁移。
不建议选择Kotlin层查询旧表、转换后写入新表的方案:一方面迁移效率远低于单条SQL执行,数据量较大时会产生不必要的内存和网络IO开销;另一方面Kotlin层手动组装JSON很容易出现特殊字符转义、null值处理不一致的问题,稳定性不如MySQL原生JSON函数。
内容的提问来源于stack exchange,提问作者Merlin Ran
相关产品推荐
相关产品推荐

