- 背景
- 源码修改
- CliOptionsParser.java
- CliOptions.java
- SqlClient.java
- SqlClient#executeFile
- 社区现状
背景
目前flink的sql客户端提供了一种交互式的sql查询服务,用户可以使用sql客户端执行一些sql的批任务或者流任务。但是当我想执行一些sql的定时任务时,flink却没有提供一个合适的方式,所以综合考虑了一下,我决定在sql的客户端基础上给加一个 '-filename (-f)' 参数,就像类似'hive -f abc.sql' 一样,可以执行一批sql任务。
源码修改
目前我只是想通过sql客户端执行一些批任务,再加上flink sql 客户端本身的一些设计,所以目前修改后的sql client 执行sql文件的时候支持 SET,DDL,INSERT INTO SELECT ...等语句,其他比如select暂不支持。
修改后执行的方式为:
代码语言:javascript复制/home/flink/bin/sql-client.sh embedded -f flink.sql
CliOptionsParser.java
在这个sql 客户端参数解析类里添加一个选项,用于解析-f参数。
代码语言:javascript复制 public static final Option OPTION_FILENAME = Option
.builder("f")
.required(false)
.longOpt("filename")
.numberOfArgs(1)
.argName("the path of the sql file")
.desc("SQL from files")
.build();
CliOptions.java
在这里添加一个变量filename
代码语言:javascript复制private final String filename;
SqlClient.java
在SqlClient里添加对于-filename的处理
代码语言:javascript复制 if (options.getUpdateStatement() != null){
// execute update statement
final boolean success = cli.submitUpdate(options.getUpdateStatement());
if (!success) {
throw new SqlClientException("Could not submit given SQL update statement to cluster.");
}
} else if (options.getFilename() != null){
final boolean success = cli.executeFile(options.getFilename());
if (!success) {
throw new SqlClientException("Could not submit given SQL file to cluster.");
}
} else {
cli.open();
}
SqlClient#executeFile
添加具体的执行sql文件的方法,sql文件里的所有sql以分号切分,然后分别判断是什么类型,调用不同的方法来执行。
代码语言:javascript复制 public boolean executeFile(String filename){
File file = new File(filename);
if (!file.exists()){
printError("the file do not exist");
return false;
} else {
String statement = null;
try {
statement = FileUtils.readFileToString(file);
} catch (IOException e){
printError("read the sql file error , " e.getMessage());
return false;
}
String[] sqls = statement.split(";");
for (String sql : sqls){
if (sql == null || "".equals(sql.trim())){
continue;
}
final Optional<SqlCommandCall> parsedStatement = parseCommand(sql);
if (parsedStatement.isPresent()){
SqlCommandCall cmdCall = parsedStatement.get();
switch (cmdCall.command) {
case SET:
callSet(cmdCall);
break;
................
case INSERT_INTO:
case INSERT_OVERWRITE:
callInsert(cmdCall);
break;
case CREATE_TABLE:
callDdl(cmdCall.operands[0], CliStrings.MESSAGE_TABLE_CREATED);
break;
.....................
throw new SqlClientException("Unsupported command: " cmdCall.command);
}
}
}
}
return true;
}
完整的代码请参考:
https://github.com/zhangjun0x01/flink/tree/release-1.11.0-sqlclient
社区现状
这个问题目前社区有一个相关的issue,但是不知道为什么迟迟没有更新和发布。 https://issues.apache.org/jira/browse/FLINK-12828
我看了一下这个相关的pr,感觉有些问题,比如sql文件没法支持多个sql,如果复用了原来的CliClient#callCommand方法,有些sql是没法执行的,比如clear、select等等,因为select在flink的客户端是开启了一个新的窗口来显示select的结果,但是我们需要的是执行一个sql文件。
所以我自己基于源码改了一版。