记一次在impala 客户端中 upsert into 语法 被转换成 insert into
问题描述
用户反馈选择的impala数据源 执行的 upsert into 语句在实际执行时被转换成insert into 语句
数据
upsert INTO dw.test
SELECT id
,category
,`type`
,content
,regexp_replace(detail,'\r\n|\r|\n','') AS detail
,status
,gmt_create
,gmt_modify
,CURRENT_TIMESTAMP() AS load_time
FROM ods.test
-- Generation begins
WHERE gmt_create < TO_DATE(NOW())
AND ums_update_time_ > UNIX_TIMESTAMP(DATE_SUB(TO_DATE(NOW()), 4)) * 1000;
成变了
INSERT
INTO
`dw`.`test`
SELECT
`ods`.`id`,
`ods`.`category`,
`ods`.`type`,
`ods`.`content`,
regexp_replace(`ods`.`detail`,
'\\r\\n|\\r|\\n',
'') as `detail`,
`ods`.`status`,
`ods`.`gmt_create`,
`ods`.`gmt_modify`,
NOW() as `load_time`
FROM
`ods`.`test`
WHERE
((`ods`.`gmt_create` < TO_DATE(NOW()))
AND (`ods`.`ums_update_time_` > (UNIX_TIMESTAMP(DATE_SUB(TO_DATE(NOW()),
4)) * 1000)))
结论
JDBC连接添加参数UseNativeQuery=1
启用此选项 (1) 时,驱动程序不会转换应用程序发出的查询,因此使用本机查询。禁用此选项 (0) 时,驱动程序会转换应用程序发出的查询,并将其转换为 Impala SQL 中的等效形式。
分析过程
初步分析可能出现的问题点:
- 环境
- 程序中有拦截处理
- 参数
- 驱动
排查
简单排查
- 问过运维同事都没有做过环境变更
- 查看执行SQL任务的程序没有做过相应的变动
- 询问负责加解密同事也不会对业务执行做拦截逻辑变更
- 检查参考也未做变更
重现
- 刨掉程序单独拿SQL在客户端执行
未重现
刚开始还是以为程序哪里做了拦截处理 调试源码
因为 om.cloudera.impala.jdbc驱动并未开源只能 边看程序边分析
源码分析时重现问题,并做出相应的调整
时序图分析
源码调试分析
- impalajdbc41-2.5.30
try {
if (this.m_settings.m_platformVersionUtils.needsInsertOptimization(this.m_settings.m_serverVersion) && this.m_settings.m_optimizedInsert) {
boolean var3 = false;
boolean var15 = false;
IPTNode var16 = null;
if (var2.toUpperCase().startsWith("INSERT")) {
var3 = true;
DefaultLimitChecker var6 = new DefaultLimitChecker();
var6.initLimitCheckValues(this.getParentStatement().getParentConnection());
var16 = PTParser.parse(var1, var6);
if (null == var16) {
throw SQLEngineExceptionFactory.invalidParseTreeException();
}
LinkedList var7 = new LinkedList();
var7.add(var16);
label91:
while(true) {
while(true) {
if (var7.isEmpty()) {
break label91;
}
IPTNode var8 = (IPTNode)var7.remove();
if (!var8.isTerminalNode()) {
if (var8 instanceof PTNonterminalNode && ((PTNonterminalNode)var8).getNonterminalType() == PTNonterminalType.SELECT_STATEMENT) {
var3 = false;
}
Iterator var9 = ((AbstractPTNonterminalNode)var8).getChildItr();
while(var9.hasNext()) {
IPTNode var10 = (IPTNode)var9.next();
if (null == var10) {
throw SQLEngineExceptionFactory.invalidParseTreeException();
}
var7.add(var10);
}
} else if (var8 instanceof PTDynamicParameterNode) {
var15 = true;
}
}
}
}
if (var3) {
try {
IQueryGenerator var17 = ((HiveJDBCCommonDriver)DSIDriverSingleton.getInstance()).getQueryGenerator();
var17.generate(var16, this.m_settings, (ExecutionContexts)null);
return new HiveJDBCNativeQueryExecutor(this.getLog(), this.m_hiveClient, this.m_statement, var2, var16, this.m_connection, this.m_isDirectExecuteQuery, this.m_requestMap, var15);
} catch (ErrorException var11) {
if (var11 instanceof SQLEngineException) {
var11.loadMessage(SQLEngineGenericContext.getDefaultMsgSource(), this.m_hiveClient.getWarningListener().getLocale());
LogUtilities.logWarning(var11, this.getLog());
}
return this.translateThroughEngine(var2);
}
} else {
return this.translateThroughEngine(var2);
}
} else {
return this.translateThroughEngine(var2);
}
} catch (SQLEngineException var12) {
var12.loadMessage(SQLEngineGenericContext.getDefaultMsgSource(), this.m_hiveClient.getWarningListener().getLocale());
LogUtilities.logWarning(var12, this.getLog());
int var4 = var12.getNativeErrorCode(SQLEngineGenericContext.getDefaultMsgSource(), this.m_hiveClient.getWarningListener().getLocale());
if (12010 == var4 && !this.m_settings.m_platformVersionUtils.supportsNestedDataTypes(this.m_settings.m_serverVersion)) {
ErrorException var5 = HiveJDBCCommonDriver.s_HiveMessages.createGeneralException(HiveJDBCMessageKey.HIVE_QUERY_EXE_ERR.name(), new String[]{var12.getMessage(), "HY000", var2});
throw var5;
} else {
this.m_hiveClient.getWarningListener().postWarning(new Warning(WarningCode.GENERAL_WARNING, 101, HiveJDBCMessageKey.DATABASE_TABLE_GENERAL_ERR.name(), new String[]{var12.getMessage()}));
return new HiveJDBCNativeQueryExecutor(this.getLog(), this.m_hiveClient, this.m_statement, var2, this.m_connection, this.m_isDirectExecuteQuery, this.m_requestMap);
}
} catch (ParsingException var13) {
CoreUtils.postWarning(var13, this.m_hiveClient.getWarningListener(), WarningCode.GENERAL_WARNING, 101, HiveJDBCMessageKey.DATABASE_TABLE_GENERAL_ERR.name());
return new HiveJDBCNativeQueryExecutor(this.getLog(), this.m_hiveClient, this.m_statement, var2, this.m_connection, this.m_isDirectExecuteQuery, this.m_requestMap);
} catch (Exception var14) {
CoreUtils.postWarning(var14, this.m_hiveClient.getWarningListener(), WarningCode.GENERAL_WARNING, 101, HiveJDBCMessageKey.HIVE_TRANSLATION_PREPARE_ERR.name());
return new HiveJDBCNativeQueryExecutor(this.getLog(), this.m_hiveClient, this.m_statement, var2, this.m_connection, this.m_isDirectExecuteQuery, this.m_requestMap);
}
}
}
调整参数后,也会减少一部分元数据处理的这种逻辑