fmpp
FMPP是一种使用FreeMarker模板的通用文本文件预处理工具 主要用来 通过 config.fmpp配置文件,xxx.ftl 附加模板和Parser.jj 模板文件 来生成最后的Parser.jj
javaCC
JavaCC本身并不是词法分析器和语法分析器,它是一个生成器!JavaCC通过读取一个后缀为.jj的描述文件中的特定描述, 来生成词法分析器和语法分析器,并且生成的词法分析器和语法分析器使用Java书写的。 用来 通过 Parser.jj来生成 SqlParserImpl等java类.

增加SQL解析
举例:
让calcite可以解析一下语句
String sql = "create function `jessica_udf` AS 'name.jessica.udf.SplitUdtf'";
增加附加模板
需要增加 createFunction.ftl附加模板 用来解析SQL
createFunction.ftl
boolean IfNotExistsOpt() :
{
}
{
<IF> <NOT> <EXISTS> { return true; }
|
{ return false; }
}
SqlCreate SqlCreateFunction(Span s, boolean replace) :
{
final boolean ifNotExists;
final SqlIdentifier functionName;
final SqlNode className;
}
{
<FUNCTION> ifNotExists = IfNotExistsOpt()
functionName = CompoundIdentifier()
<AS> className = StringLiteral() {
return new SqlCreateFunction(s.end(this), replace, ifNotExists,functionName, className);
}
}
增加SqlFunction的SqlNode
public class SqlCreateFunction extends SqlCreate {
// function name
private final SqlIdentifier name;
//function class
private final SqlNode className;
private static final SqlSpecialOperator OPERATOR =
new SqlSpecialOperator("CREATE FUNCTION", SqlKind.CREATE_FUNCTION);
public SqlCreateFunction(SqlParserPos pos,
boolean replace,
boolean ifNotExists,
SqlIdentifier name,
SqlNode className) {
super(OPERATOR, pos, replace, ifNotExists);
this.name = Objects.requireNonNull(name);
this.className = className;
}
//调用 sqlNode.toString方法 可还原sql
@Override public void unparse(SqlWriter writer, int leftPrec,
int rightPrec) {
writer.keyword(getReplace() ? "CREATE OR REPLACE" : "CREATE");
writer.keyword("FUNCTION");
if (ifNotExists) {
writer.keyword("IF NOT EXISTS");
}
name.unparse(writer, 0, 0);
writer.keyword("AS");
className.unparse(writer, 0, 0);
}
@Override
public SqlOperator getOperator() {
return OPERATOR;
}
@Override
public List<SqlNode> getOperandList() {
return Arrays.asList(name,className);
}
}
config.fmpp增加相关配置
在 config.fmpp 配置中 增加 相关的信息
imports: [
"name.jessica.calcite.sql.ddl.SqlCreateFunction"
"org.apache.calcite.sql.SqlCreate"
]
# List of new keywords. Example: "DATABASES", "TABLES". If the keyword is not a reserved
# keyword add it to 'nonReservedKeywords' section.
keywords: [
"IF"
]
implementationFiles: [
"createFunction.ftl"
]
生成SqlParserImpl
final public SqlCreate SqlCreateFunction(Span s, boolean replace) throws ParseException {
final boolean ifNotExists;
final SqlIdentifier functionName;
final SqlNode className;
jj_consume_token(FUNCTION);
ifNotExists = IfNotExistsOpt();
functionName = CompoundIdentifier();
jj_consume_token(AS);
className = StringLiteral();
{if (true) return new SqlCreateFunction(s.end(this), replace, ifNotExists,functionName, className);}
throw new Error("Missing return statement in function");
}
Java单测进行测试
@Test
public void testCreateFunction() throws IOException, SqlParseException {
String sql = "create function `jessica_udf` AS 'name.jessica.udf.SplitUdtf'";
// 解析配置
SqlParser.Config javaConfig = SqlParser.configBuilder().setLex(Lex.JAVA).build();
SqlParser parser = SqlParser.create(sql,javaConfig);
SqlNode createFunctionNode = parser.parseQuery();
System.out.println(createFunctionNode.toSqlString(OracleSqlDialect.DEFAULT));
}
文档信息
- 本文作者:Jessica
- 本文链接:https://jessica0530.github.io/2020/08/18/calcite-3/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)