【spark】sparkJDBC自定义方言(以vertica为例)

背景

sparkJDBC在写入时提供了overwrite模式。当写入数据之前,会将之前的表drop掉,然后根据DataFrame类型推断生成Create语句新建一张表。

在某些小众的数据库,spark内部没有提供对应的方言。这是spark会使用一个NoopCommon的默认方言,这时候很容易推断错误。

案例

以vertica为例,在DataFrame中包含String类型时,如下:

1
2
3
4
5
6
root
 |-- time: timestamp (nullable = true)
 |-- AMP: double (nullable = true)
 |-- NOZP: integer (nullable = true)
 |-- value: integer (nullable = true)
 |-- reason: string (nullable = true)

这时在直接用jdbc写入时会报

1
java.sql.SQLSyntaxErrorException: [Vertica][VJDBC](5108) ERROR: Type "TEXT" does not exist

因此需要注册一个vertica方言,将String类型转为一个合适varchar类型。如下

1
2
3
4
5
6
7
8
9
10
object VerticaDialect extends JdbcDialect {
  override def canHandle(url: String): Boolean = {
    url.toLowerCase(Locale.ROOT).startsWith("jdbc:vertica")
  }
 
  override def getJDBCType(dt: DataType): Option[JdbcType] = dt match {
    case StringType => Some(JdbcType("LONG VARCHAR", Types.LONGVARCHAR))
    case _ => None
  }
}

因为String是无界的,所以转为long varchar最为保险。这里只需要转String类型即可,因为在JdbcUtils里面

1
2
3
4
private def getJdbcType(dt: DataType, dialect: JdbcDialect): JdbcType = {
    dialect.getJDBCType(dt).orElse(getCommonJDBCType(dt)).getOrElse(
      throw new IllegalArgumentException(s"Can't get JDBC type for ${dt.catalogString}"))
  }

sparkJDBC会优先找注册的方言,然后还会在CommonJDBCType中找一次。所以其他通用的类型不需要在方言中重复指定。

最后在driver中注册方言

1
JdbcDialects.registerDialect(VerticaDialect)

  

 

posted @   周周周文阳  阅读(898)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示