我正在尝试使用Spark JDBC从SAS IOM中读取。问题是SAS JDBC驱动程序有点奇怪,因此我需要创建自己的方言:
object SasDialect extends JdbcDialect {
override def canHandle(url: String): Boolean = url.startsWith("jdbc:sasiom")
override def quoteIdentifier(colName: String): String = "\"" + colName + "\"n"
}
但是,这还不够。 SAS区分了列标签(=可读名称)和列名称(=在SQL查询中使用的名称),但是似乎spark在表发现中使用了column标签而不是名称,请参见下面的JdbcUtils摘录: / p>
while (i < ncols) {
val columnName = rsmd.getColumnLabel(i + 1)
这会导致SQL错误,因为它尝试在生成的SQL代码中使用人类可读的列名。
要使SAS IOM JDBC正常工作,它必须是getColumnName而不是getColumnLabel。有方言可以指定此方法吗?除了包装整个com.sas.rio.MVADriver和resultsetmeta
之外,我真的找不到一种方法可以解决这个问题坦率
答案 0 :(得分:1)
在此期间,我发现了如何做到这一点,因此仅发布以供参考。诀窍是注册自己的方言,如下所示。
此外,SAS用空格填充所有varchar列,因此我修剪了所有字符串列。
def getSasTable(sparkSession: org.apache.spark.sql.SparkSession, tablename: String): org.apache.spark.sql.DataFrame = {
val host : String = "dwhid94.msnet.railb.be";
val port : String = "48593";
val props = new java.util.Properties();
props.put("user", CredentialsStore.getUsername("sas"))
props.put("password", CredentialsStore.getPassword("sas"))
props.setProperty("driver", "com.sas.rio.MVADriver")
val sasconurl : String = String.format("jdbc:sasiom://%s:%s", host, port);
object SasDialect extends JdbcDialect {
override def canHandle(url: String): Boolean = url.startsWith("jdbc:sasiom")
override def quoteIdentifier(colName: String): String = "\"" + colName + "\"n"
}
JdbcDialects.registerDialect(SasDialect)
val df = sparkSession.read
.option("url", sasconurl)
.option("driver", "com.sas.rio.MVADriver")
.option("dbtable", tablename)
.option("user",CredentialsStore.getUsername("sas"))
.option("password",CredentialsStore.getPassword("sas"))
.option("fetchsize",100)
.format("jdbc")
.load()
val strippedDf = sparkSession.createDataFrame(df.rdd.map(r => Row(r.toSeq.map(x => x match {case s: String => s.trim; case _ => x}): _*)), df.schema);
return strippedDf;
}