SQL 解析器更改 table 名称
SQL parser to alter table name
我有一个 SQL 查询:
select
t1.name, t2.address
from
Table1 t1
inner join
Table2 t2 on t1.id = t2.id;
和一张地图:
Map<String,String> map = new HashMap<String,String>();
map.put("testTable", "hive.DB1");
map.put("testTable", "mongo.DB2");
我只想使用此地图将上述查询转换为:
select
t1.name, t2.address
from
hive.DB1.`Table1` t1
inner join
mongo.DB2.`Table2` t2 on t1.id = t2.id;
哪个开源 SQL 解析器适合此目的。
您真的需要 SQL 解析器吗?
为什么不直接使用 sed 呢?
例如一个 table :
sed -e "s/Table1/hive.DB1.TABLE1/g" C:\test.sql > C:\new.sql
我用了JSqlParser.
我从 SQL 查询中提取了 table 个名字:
Statement statement = CCJSqlParserUtil.parse("select t1.name, t2.address from Table1 t1 inner join Table2 t2 on t1.id = t2.id;");
Select selectStatement = (Select) statement;
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
List<String> tableList = tablesNamesFinder.getTableList(selectStatement);
然后我根据地图修改了Table个名字
需要一个解析器来仅更改 "from" 部分的 table 引用。某些数据库不接受表达式中的完全限定名称。
此代码使用 JSqlParser 0.9.5-SNAPSHOT 并打印出修改后的 SQL:
public class SimpleTableReplacer {
public static void main(String args[]) throws JSQLParserException {
String sql = "select t1.name, t2.address from Table1 t1 inner join Table2 t2 on t1.id = t2.id";
Select select = (Select)CCJSqlParserUtil.parse(sql);
//Replace Table1 with hive.DB1.Table1 and Table2 with mongo.DB2.Table2
StringBuilder buffer = new StringBuilder();
ExpressionDeParser expressionDeParser = new ExpressionDeParser();
SelectDeParser deparser = new SelectDeParser(expressionDeParser,buffer ) {
@Override
public void visit(Table tableName) {
switch (tableName.getName()) {
case "Table1": getBuffer().append("hive.DB1.Table1").append(' ').append(tableName.getAlias().getName());break;
case "Table2": getBuffer().append("mongo.DB2.Table2").append(' ').append(tableName.getAlias().getName());break;
default:
super.visit(tableName);
}
}
};
expressionDeParser.setSelectVisitor(deparser);
expressionDeParser.setBuffer(buffer);
select.getSelectBody().accept(deparser);
//End of value modification
System.out.println(buffer.toString());
}
}
结果:SELECT t1.name, t2.address FROM hive.DB1.Table1 t1 INNER JOIN mongo.DB2.Table2 t2 ON t1.id = t2.id
。
您当然可以使用此代码修改 class 层次结构本身,这意味着更改 Table - 对象名称。
此外,您可以使用 JSqlParser 的一项新功能为 SQL 的某些部分提供 AST 节点。您可以在 SQL 中提取 table 名称的确切位置,并在那里替换文本。这可以这样编码:
SimpleNode node = (SimpleNode) CCJSqlParserUtil.parseAST(sql);
node.childrenAccept(new CCJSqlParserDefaultVisitor() {
@Override
public Object visit(SimpleNode node, Object data) {
if (node.getId() == CCJSqlParserTreeConstants.JJTTABLE) {
System.out.println("table name '" + node.jjtGetValue() + "' found at " + node.jjtGetFirstToken().beginColumn + "-" + node.jjtGetLastToken().endColumn);
}
return super.visit(node, data);
}
}, null);
如果您只需要从 SQL 中提取 table 个名称并执行一些逻辑,则需要超轻、超快的库来完成此操作
只需在您的 pom 中添加以下内容
<dependency>
<groupId>com.github.mnadeem</groupId>
<artifactId>sql-table-name-parser</artifactId>
<version>0.0.1</version>
</dependency>
并使用以下指令
new TableNameParser(sql).tables()
有关详细信息,请参阅 project
免责声明:我是所有者
我有一个 SQL 查询:
select
t1.name, t2.address
from
Table1 t1
inner join
Table2 t2 on t1.id = t2.id;
和一张地图:
Map<String,String> map = new HashMap<String,String>();
map.put("testTable", "hive.DB1");
map.put("testTable", "mongo.DB2");
我只想使用此地图将上述查询转换为:
select
t1.name, t2.address
from
hive.DB1.`Table1` t1
inner join
mongo.DB2.`Table2` t2 on t1.id = t2.id;
哪个开源 SQL 解析器适合此目的。
您真的需要 SQL 解析器吗? 为什么不直接使用 sed 呢?
例如一个 table :
sed -e "s/Table1/hive.DB1.TABLE1/g" C:\test.sql > C:\new.sql
我用了JSqlParser.
我从 SQL 查询中提取了 table 个名字:
Statement statement = CCJSqlParserUtil.parse("select t1.name, t2.address from Table1 t1 inner join Table2 t2 on t1.id = t2.id;");
Select selectStatement = (Select) statement;
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
List<String> tableList = tablesNamesFinder.getTableList(selectStatement);
然后我根据地图修改了Table个名字
需要一个解析器来仅更改 "from" 部分的 table 引用。某些数据库不接受表达式中的完全限定名称。
此代码使用 JSqlParser 0.9.5-SNAPSHOT 并打印出修改后的 SQL:
public class SimpleTableReplacer {
public static void main(String args[]) throws JSQLParserException {
String sql = "select t1.name, t2.address from Table1 t1 inner join Table2 t2 on t1.id = t2.id";
Select select = (Select)CCJSqlParserUtil.parse(sql);
//Replace Table1 with hive.DB1.Table1 and Table2 with mongo.DB2.Table2
StringBuilder buffer = new StringBuilder();
ExpressionDeParser expressionDeParser = new ExpressionDeParser();
SelectDeParser deparser = new SelectDeParser(expressionDeParser,buffer ) {
@Override
public void visit(Table tableName) {
switch (tableName.getName()) {
case "Table1": getBuffer().append("hive.DB1.Table1").append(' ').append(tableName.getAlias().getName());break;
case "Table2": getBuffer().append("mongo.DB2.Table2").append(' ').append(tableName.getAlias().getName());break;
default:
super.visit(tableName);
}
}
};
expressionDeParser.setSelectVisitor(deparser);
expressionDeParser.setBuffer(buffer);
select.getSelectBody().accept(deparser);
//End of value modification
System.out.println(buffer.toString());
}
}
结果:SELECT t1.name, t2.address FROM hive.DB1.Table1 t1 INNER JOIN mongo.DB2.Table2 t2 ON t1.id = t2.id
。
您当然可以使用此代码修改 class 层次结构本身,这意味着更改 Table - 对象名称。
此外,您可以使用 JSqlParser 的一项新功能为 SQL 的某些部分提供 AST 节点。您可以在 SQL 中提取 table 名称的确切位置,并在那里替换文本。这可以这样编码:
SimpleNode node = (SimpleNode) CCJSqlParserUtil.parseAST(sql);
node.childrenAccept(new CCJSqlParserDefaultVisitor() {
@Override
public Object visit(SimpleNode node, Object data) {
if (node.getId() == CCJSqlParserTreeConstants.JJTTABLE) {
System.out.println("table name '" + node.jjtGetValue() + "' found at " + node.jjtGetFirstToken().beginColumn + "-" + node.jjtGetLastToken().endColumn);
}
return super.visit(node, data);
}
}, null);
如果您只需要从 SQL 中提取 table 个名称并执行一些逻辑,则需要超轻、超快的库来完成此操作
只需在您的 pom 中添加以下内容
<dependency>
<groupId>com.github.mnadeem</groupId>
<artifactId>sql-table-name-parser</artifactId>
<version>0.0.1</version>
</dependency>
并使用以下指令
new TableNameParser(sql).tables()
有关详细信息,请参阅 project
免责声明:我是所有者