flink教程-基于flink 1.11 使 sql客户端支持执行sql文件

背景

目前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暂不支持。

修改后执行的方式为:

/home/flink/bin/sql-client.sh embedded -f flink.sql

CliOptionsParser.java

在这个sql 客户端参数解析类里添加一个选项,用于解析-f参数。

	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

private final String filename;

SqlClient.java

在SqlClient里添加对于-filename的处理

		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以分号切分,然后分别判断是什么类型,调用不同的方法来执行。

	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文件。

所以我自己基于源码改了一版。

更多精彩信息,欢迎关注我的公众号【大数据技术与应用实战】
image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值