java使用jsqlparser实现自定义转换

article/2025/10/5 4:40:57

jsqlparser描述:

JSqlParser 解析 SQL 语句并将其转换为 Java 类的层次结构。基本上的sql关键字和函数都可以被jsqlparser解析成对象层层包装。

实现的功能:

基础sql查询,条件查询,字段和表得别名,排序,分组,聚合,case when,基本上都是有得。

我的使用场景:

将一个表和字段不是数据库直接查询的表字段,进行通过jsqlparser来转换成elasticsearch中存储的表和字段进行到openlokeng中进行查询

界面输入:

在这里插入图片描述

openlookeng 执行:

在这里插入图片描述

举例:

首先在页面输入:SELECT t1.公司名称 from gxb.新规则表5 t1
然后通过解析后:SELECT eas_file_197_1_1_1_1_1_2.column2 FROM eas_file_197_1_1_1_1_1_2

解析对象:

在这里插入图片描述
在这里插入图片描述

自定义函数:

在这里插入图片描述

实际使用:

@Injectprivate Metadata metadata;@Injectprivate DataManager dataManager;@Injectprivate TimeSource timeSource;@Injectprivate Logger log;@Injectprivate DataServiceConfig dataServiceConfig;@Injectprivate CustomConfig customConfig;private static final String CLASSIFY_NAME = "classifyName";private static final String TABLE_NAME = "tableName";private static final String TABLE_ALIAS = "tableAlias";private static final String STATUS = "status";private static final String SUCCESS = "success";private static final String FAILED = "failed";@Overridepublic Object execute(String sql, UserExt userExt, Page page){if(Objects.isNull(page)) page = new Page();long startTime = timeSource.currentTimeMillis();String operateResult = "执行成功";Map<String, Object> resultObj = new HashMap<>();List<HashMap<String, Object>> jsonArray = new ArrayList<>();try {Statements stmts = parseStatements(sql);Page finalPage = page;stmts.getStatements().forEach(stmt -> {if (stmt instanceof Select) {executeSelect(stmt,finalPage,jsonArray);}});resultObj.put("data", jsonArray);resultObj.put(STATUS, SUCCESS);} catch (JSQLParserException e) {operateResult = "执行失败,输入SQL语法错误";resultObj.put(STATUS, FAILED);throw new SQLParserException("输入SQL语法错误",e);}catch (Exception e){operateResult = "执行失败,接口处理异常";resultObj.put(STATUS, FAILED);throw new SQLParserException("接口处理异常",e);}finally {saveOperateHistory(sql, userExt, startTime, operateResult);}return resultObj;}/*** 具体执行 select 解析后返回 jsonArray 对象* @param stmt* @param finalPage* @param jsonArray*/private void executeSelect(Statement stmt, Page finalPage, List<HashMap<String, Object>> jsonArray) {Map<String, Object> tempMap = parseSelectSql((Select) stmt, finalPage);String paramSql = formatSql((String) tempMap.get("sql"));List<SqlStatementEasTableVo> tables = (List<SqlStatementEasTableVo>) tempMap.get("tables");Map<String, String> config = getDataServiceConfig(tables.get(0));String database = config.get("database");String schemaName = config.get("schema");log.info("数据服务入参:");log.info("sql: {}", paramSql);log.info("database: {} | schemaName: {}", database, schemaName);if(Objects.isNull(database) || Objects.isNull(schemaName) ){throw new SQLParserException("database 或 schema 为空 ");}Page resultPage = (Page) tempMap.get("page");RunQueryResponse response = invokeDataService(database, schemaName, paramSql);if(resultPage.isSelectAll()){resultPage.setTotalCount(response.getTotal().longValue());resultPage.setPageCount(getPageCount(response.getTotal().longValue(), finalPage.getPageSize()));}resultPage.setList(response.getResult());HashMap<String, Object> objHashMap = new HashMap<>();tempMap.put("page", resultPage);objHashMap.put("metas", tempMap);jsonArray.add(objHashMap);}private Map<String, String> getDataServiceConfig(SqlStatementEasTableVo entity) {EasTable easTable = getEasTable(entity.getClassifyName(), entity.getName());Map<String,String> resultMap = new HashMap<>();if(Objects.nonNull(easTable)){String database = Objects.isNull(easTable.getDatabase()) ? "" : easTable.getDatabase().getAlias();String schema = easTable.getSchema().getSchema().getName();resultMap.put("database", database);resultMap.put("schema", schema);}return resultMap;}private List<EasColumn> parseSelectItem(PlainSelect selectBody, List<Map<String, String>> tableItems) {List<EasColumn> resultColumn = new ArrayList<>();selectBody.getSelectItems().forEach(s -> s.accept(new SelectItemVisitorAdapter() {@Overridepublic void visit(AllColumns columns) {Map<String, String> tableMap = Objects.nonNull(tableItems.get(0)) ? tableItems.get(0) : new HashMap<>();EasTable easTable = getEasTable(tableMap.get(CLASSIFY_NAME), tableMap.get(TABLE_NAME));if (Objects.isNull(easTable)) return;List<SelectItem> list = new ArrayList<>();easTable.getColumn().forEach(c -> {Column column = initColumn(easTable.getTable().getName(), c.getColumn().getName());SelectExpressionItem selectExpressionItem = new SelectExpressionItem(column);list.add(selectExpressionItem);resultColumn.add(c);});selectBody.setSelectItems(list);}@Overridepublic void visit(AllTableColumns columns) {String name = columns.getTable().getName();Map<String, String> tableMap = tableItems.stream().filter(t -> StringUtils.equals(name, t.get(TABLE_ALIAS))).findFirst().orElse(new HashMap<>());EasTable easTable = getEasTable(tableMap.get(CLASSIFY_NAME), tableMap.get(TABLE_NAME));if (Objects.isNull(easTable)) return;List<SelectItem> list = new ArrayList<>();easTable.getColumn().forEach(c -> {Column column = initColumn(easTable.getTable().getName(), c.getColumn().getName());SelectExpressionItem selectExpressionItem = new SelectExpressionItem(column);list.add(selectExpressionItem);resultColumn.add(c);});selectBody.setSelectItems(list);}@Overridepublic void visit(SelectExpressionItem item) {//如果是条件查询的case,否则默认为字段switch (item.getExpression().getClass().getName()){case "net.sf.jsqlparser.expression.CaseExpression":caseExpression(item,tableItems,resultColumn);break;case "net.sf.jsqlparser.expression.Function":functionExpression(item,tableItems,resultColumn);break;default:basicExpression(item,tableItems,resultColumn);break;}}}));return resultColumn;}/*** 带有条件的 查询字段的进行拼接转换* @param item* @param tableItems* @param resultColumn*/private void caseExpression(SelectExpressionItem item,List<Map<String, String>> tableItems,List<EasColumn> resultColumn) {Column switchExpression = ((CaseExpression) item.getExpression()).getSwitchExpression(Column.class);EasColumn easColumn;//这里要处理 ,分情况, 如果是 没有switch 的时候if(Objects.isNull(switchExpression)){easColumn =noHaveSwitchExpression(item,tableItems);}else{easColumn =haveSwitchExpression(item,tableItems,switchExpression);}if (Objects.isNull(easColumn)) return ;//这里构造一个新的自定义的别名 column 给前端,为了展示EasColumn newEasColumn=customAlias(item,easColumn.getColumn().getName(),DimensionType.BUSINESS);resultColumn.add(newEasColumn);}/*** 没有switchExpression 表示*  case when  列名=值 then  ''*/private EasColumn noHaveSwitchExpression(SelectExpressionItem item, List<Map<String, String>> tableItems) {List<WhenClause> whenClauseList=new ArrayList<>();EasColumn easColumn = null;for (WhenClause i : ((CaseExpression) item.getExpression()).getWhenClauses()) {Column left = ((EqualsTo) i.getWhenExpression()).getLeftExpression(Column.class);Map<String, String> leftTableMap = tableItems.stream().filter(t -> StringUtils.equals(left.getTable().getName(), t.get(TABLE_ALIAS))).findFirst().orElse(new HashMap<>());//大于0 表示 匹配到别名 t1, 否则就用默认的 文件夹.表名.列名EasTable easTable;if(leftTableMap.size()>0){//  on  左边  转换的表名easTable = getEasTable(leftTableMap.get(CLASSIFY_NAME), leftTableMap.get(TABLE_NAME));}else{easTable = getEasTable(left.getTable().getSchemaName(), left.getTable().getName());}if (Objects.isNull(easTable)) return null;EasColumn leftColumn = easTable.getColumn().stream().filter(c -> StringUtils.equals(left.getColumnName(), c.getName())).findFirst().orElse(null);if (Objects.isNull(leftColumn)) return null;EasTable finalEasTable1 = easTable;WhenClause whenClause= i;BinaryExpression onExpression = new EqualsTo();onExpression.setLeftExpression(new Column(new Table(finalEasTable1.getTable().getName()),leftColumn.getColumn().getName()));onExpression.setRightExpression(((EqualsTo) i.getWhenExpression()).getRightExpression());whenClause.setWhenExpression(onExpression);whenClauseList.add(whenClause);//替换原有的case when 中文表名 -> case when es表名((CaseExpression) item.getExpression()).setWhenClauses(whenClauseList);easColumn = easTable.getColumn().stream().filter(c -> StringUtils.equals(left.getColumnName(), c.getName())).findFirst().orElse(null);if (Objects.isNull(easColumn)) return null;}return easColumn;}/*** 有switchExpression 表示*  case 列名  when 值 then  ''*/private EasColumn haveSwitchExpression(SelectExpressionItem item, List<Map<String, String>> tableItems, Column switchExpression) {Map<String,Object> map= Collections.unmodifiableMap(getNewColumn(tableItems, switchExpression));//重新赋值给 函数表达式EasColumn easColumn=(EasColumn)map.get("easColumn");EasTable easTable=(EasTable)map.get("easTable");//将获取转化后的表.列,重新赋值给 switchExpression对象EasTable finalEasTable = easTable;item.getExpression().accept(new ExpressionVisitorAdapter(){@Overridepublic void visit(CaseExpression caseExpression) {caseExpression.setSwitchExpression(initColumn(finalEasTable.getTable().getName(), easColumn.getColumn().getName()));}});return easColumn;}/*** 带有条件的 查询字段的进行拼接转换* @param item* @param tableItems* @param resultColumn*/private void functionExpression(SelectExpressionItem item,List<Map<String, String>> tableItems,List<EasColumn> resultColumn) {List<Expression> expressions=new ArrayList<>();ExpressionList functionExpressions= ((net.sf.jsqlparser.expression.Function)item.getExpression()).getParameters();if(Objects.nonNull(functionExpressions)){//这里表示的 是 count + 具体字段List<Expression>  expressionList= functionExpressions.getExpressions();expressionList.forEach(expression -> {//判断是否是自定义日期函数if(((net.sf.jsqlparser.expression.Function)item.getExpression()).getMultipartName().get(0).equals(customConfig.getDoTimeFunction())){functionItem(expression,tableItems,expressions,item,resultColumn,expressionList.get(1));}else{functionItem(expression,tableItems,expressions,item,resultColumn,null);}});}else{//这里表示 的是 count (*)//这里构造一个新的自定义的别名 column 给前端,为了展示EasColumn newEasColumn=customAlias(item,item.getAlias().getName(),DimensionType.BUSINESS);resultColumn.add(newEasColumn);}}/*** 函数 count + 具体字段*/private void functionItem(Expression expression, List<Map<String, String>> tableItems, List<Expression> expressions, SelectExpressionItem item, List<EasColumn> resultColumn,Expression value) {if(expression instanceof Column){Column functionExpression = (Column) expression;item.getExpression().accept(new ExpressionVisitorAdapter(){@Overridepublic void visit(ExpressionList expression) {Map<String,Object> map= Collections.unmodifiableMap(getNewColumn(tableItems, functionExpression));Column newColumn=(Column) map.get("newColumn");EasColumn easColumn =(EasColumn) map.get("easColumn");//重新赋值给 函数表达式expressions.add(newColumn);expression.setExpressions(expressions);//这里构造一个新的自定义的别名 column 给前端,为了展示EasColumn newEasColumn=customAlias(item,easColumn.getColumn().getName(),easColumn.getDimensionType());resultColumn.add(newEasColumn);net.sf.jsqlparser.expression.Function function=((net.sf.jsqlparser.expression.Function)item.getExpression());List<String> customerFunctionNames=function.getMultipartName();//这里要判断下自定义时间函数for(String customerFunctionName:customerFunctionNames) {if (Objects.nonNull(customerFunctionName) &&customerFunctionName.equals(customConfig.getDoTimeFunction())&& Objects.nonNull(value)) {net.sf.jsqlparser.expression.Function expressFunction = ((net.sf.jsqlparser.expression.Function) item.getExpression());expressFunction.setName("from_unixtime");ExpressionList list= customTimeFunction(value, expression);expressFunction.setParameters(list);}}}});}}/*** 自定义时间段分组函数*/private ExpressionList customTimeFunction(Expression value, ExpressionList expression) {//from_unixtime((to_unixtime(eas_file_493_2.column0) / 60 ) * 60)//1.上面已经拼好 eas_file_493_2.column0//2.然后拼 to_unixtime(eas_file_493_2.column0)ExpressionList list=new ExpressionList();//to_unixtimenet.sf.jsqlparser.expression.Function newFunction=new net.sf.jsqlparser.expression.Function();newFunction.setName("to_unixtime");newFunction.setParameters(expression);//3.再拼  to_unixtime(eas_file_493_2.column0) / 60Division division=new Division();division.setLeftExpression(newFunction);division.setRightExpression(value);//((to_unixtime(eas_file_493_2.column0) / 60 )ExpressionList expressionList1=new ExpressionList();expressionList1.addExpressions(division);net.sf.jsqlparser.expression.Function newFunction2=new net.sf.jsqlparser.expression.Function();newFunction2.setName("");newFunction2.setParameters(expressionList1);//4.最后拼  (to_unixtime(eas_file_493_2.column0) / 60 ) * 60Multiplication multiplication2=new Multiplication();multiplication2.setLeftExpression(newFunction2);multiplication2.setRightExpression(value);list.addExpressions(multiplication2);return list;}/*** 根据 是否有别名,执行对应的操作。*/private  void basicExpression( SelectExpressionItem item,List<Map<String, String>> tableItems,List<EasColumn>  resultColumn){Column expression = item.getExpression(Column.class);Map<String,Object> map= Collections.unmodifiableMap(getNewColumn(tableItems, expression));//重新赋值给 函数表达式EasColumn easColumn=(EasColumn)map.get("easColumn");EasTable easTable=(EasTable)map.get("easTable");//这里构造一个新的自定义的别名 column 给前端,为了展示EasColumn newEasColumn=customAlias(item,easColumn.getColumn().getName(),easColumn.getDimensionType());resultColumn.add(newEasColumn);item.setExpression(initColumn(easTable.getTable().getName(), easColumn.getColumn().getName()));}/*** 自定义字段别名, COLUMN AS ""* @param item* @param easColumnName* @param dimensionType* @return*/private static EasColumn customAlias (SelectExpressionItem item,String easColumnName,DimensionType dimensionType){//这里构造一个新的自定义的别名 column 给前端,为了展示EasColumn newEasColumn=new EasColumn();String tempName;if(item.getAlias() ==null ){tempName=easColumnName;}else{tempName=item.getAlias().getName().replace("\"", "");}newEasColumn.setOriginalName(tempName);newEasColumn.setName(tempName);newEasColumn.setDimensionType(dimensionType);cn.com.dataocean.metadata.entity.Column column=new cn.com.dataocean.metadata.entity.Column();column.setName(tempName);newEasColumn.setColumn(column);return newEasColumn;}private Column initColumn(String tableName, String columnName ){Table table = new Table(tableName);return new Column(table, columnName);}/*** 分组 group by 处理* @param selectBody* @param tableItems*/private void parseGroupBy(PlainSelect selectBody, List<Map<String, String>> tableItems) {if (Objects.nonNull(selectBody.getGroupBy())) {List<Expression> expressions=new ArrayList<>();ExpressionList groupByList=selectBody.getGroupBy().getGroupByExpressionList();groupByList.getExpressions().forEach(expression -> groupByList.accept(new ExpressionVisitorAdapter(){@Overridepublic void visit(ExpressionList express) {groupBy(expression,tableItems,expressions,express);}}));}}/*** 区别 是否有自定义时间段 函数,否则为普通group by*/private void groupBy(Expression expression, List<Map<String, String>> tableItems, List<Expression> expressions, ExpressionList express){//这里要判断下自定义时间函数if((expression instanceof Column)){Column group = (Column) expression;Map<String,Object> map= Collections.unmodifiableMap(getNewColumn(tableItems, group));//重新赋值给 函数表达式expressions.add((Column) map.get("newColumn"));express.setExpressions(expressions);}else{net.sf.jsqlparser.expression.Function function= (net.sf.jsqlparser.expression.Function) expression;Expression value=function.getParameters().getExpressions().get(1);function.getParameters().getExpressions().forEach(expression1 -> {if(!(expression1 instanceof Column)){return ;}Column functionExpression = (Column) expression1;expression.accept(new ExpressionVisitorAdapter(){@Overridepublic void visit(ExpressionList expression) {Map<String,Object> map= Collections.unmodifiableMap(getNewColumn(tableItems, functionExpression));//重新赋值给 函数表达式expressions.add((Column) map.get("newColumn"));expression.setExpressions(expressions);//自定义函数 重新赋值List<String> customerFunctionNames=function.getMultipartName();//这里要判断下自定义时间函数for(String customerFunctionName:customerFunctionNames) {if (Objects.nonNull(customerFunctionName) && customerFunctionName.equals(customConfig.getDoTimeFunction()) && Objects.nonNull(value)) {function.setName("from_unixtime");ExpressionList expressionList=customTimeFunction(value, expression);function.setParameters(expressionList);}}}});});}}/*** 获取重新拼接的 table 和 column* @param tableItems* @param functionExpression* @return*/private Map<String,Object> getNewColumn(List<Map<String, String>> tableItems, Column functionExpression) {Map<String, String> tableMap = tableItems.stream().filter(t -> StringUtils.equals(functionExpression.getTable().getName(), t.get(TABLE_ALIAS))).findFirst().orElse(new HashMap<>());EasTable easTable;//大于0 表示 匹配到别名 t1, 否则就用默认的 文件夹.表名.列名if(tableMap.size()>0){easTable = getEasTable(tableMap.get(CLASSIFY_NAME), tableMap.get(TABLE_NAME));}else{easTable = getEasTable(functionExpression.getTable().getSchemaName(), functionExpression.getTable().getName());}if (Objects.isNull(easTable)) return null;EasColumn easColumn = easTable.getColumn().stream().filter(c -> StringUtils.equals(functionExpression.getColumnName(), c.getName())).findFirst().orElse(null);if (Objects.isNull(easColumn)) return null;Column newColumn=initColumn(easTable.getTable().getName(), easColumn.getColumn().getName());Map<String,Object> map=new HashMap();map.put("easTable",easTable);map.put("easColumn",easColumn);map.put("newColumn",newColumn);return map;}private void parseHaving(PlainSelect selectBody, List<Map<String, String>> tableItems) {if (Objects.nonNull(selectBody.getHaving())) {selectBody.getHaving().accept(new ExpressionVisitorAdapter(){@Overridepublic void visit(ExpressionList expression) {List<Expression> expressions=new ArrayList<>();List<Expression> columnList=expression.getExpressions();columnList.forEach(tempColumn->{Column having = (Column) tempColumn;Map<String,Object> map= getNewColumn(tableItems,having);//重新赋值给 函数表达式EasColumn easColumn=(EasColumn)map.get("easColumn");EasTable easTable=(EasTable)map.get("easTable");Column newColumn=initColumn(easTable.getTable().getName(), easColumn.getColumn().getName());//重新赋值给 函数表达式expressions.add(newColumn);expression.setExpressions(expressions);});}});}}private Page parseLimit(PlainSelect selectBody, Page page) {Page resultPage = new Page();long limit = page.getPageSize();long offset = (page.getCurrentPage()-1)*limit < 0 ? 0 : (page.getCurrentPage()-1)*limit;if (Objects.isNull(selectBody.getLimit())) {resultPage.setSelectAll(true);}else{long total = selectBody.getLimit().getRowCount(LongValue.class).getValue(); //sql语句中的limit参数resultPage.setSelectAll(false);resultPage.setTotalCount(total);resultPage.setPageCount(getPageCount(total,limit));if(total < offset){limit = 0;}else if(total-offset < limit){limit = total-offset;}}selectBody.setLimit(new Limit().withRowCount(new LongValue(limit)));selectBody.setOffset(new Offset().withOffset(offset));resultPage.setCurrentPage(page.getCurrentPage());resultPage.setLimit(limit);resultPage.setOffset(offset);return resultPage;}private void parseWhere(PlainSelect selectBody,List<Map<String, String>> tableMap) {if (Objects.nonNull(selectBody.getWhere())) {selectBody.getWhere().accept(new ExpressionVisitorAdapter() {@Overridepublic void visit(Column column) {EasTable easTable;//大于0 表示 匹配到别名 t1, 否则就用默认的 文件夹.表名.列名if(!tableMap.isEmpty()){easTable = getEasTable(tableMap.get(0).get(CLASSIFY_NAME), tableMap.get(0).get(TABLE_NAME));}else{easTable = getEasTable(column.getTable().getSchemaName(), column.getTable().getName());}if (Objects.isNull(easTable)) return;EasColumn easColumn = easTable.getColumn().stream().filter(c -> StringUtils.equals(column.getColumnName(), c.getName())).findFirst().orElse(null);if (Objects.isNull(easColumn)) return;column.setColumnName(easColumn.getColumn().getName());Table table = new Table(easTable.getTable().getName());column.setTable(table);}});}}private Map<String, String> parseFromItem(PlainSelect selectBody) {Map<String, String> fromItemMap = new HashMap<>();selectBody.getFromItem().accept(new FromItemVisitorAdapter() {@Overridepublic void visit(Table table) {fromItemMap.put(CLASSIFY_NAME, table.getSchemaName());fromItemMap.put(TABLE_NAME, table.getName());fromItemMap.put(TABLE_ALIAS, Objects.nonNull(table.getAlias()) ? table.getAlias().getName() : null);EasTable easTable = getEasTable(table.getSchemaName(), table.getName());if (Objects.isNull(easTable)) return;table.setName(easTable.getTable().getName());table.setAlias(null);table.setSchemaName(null);}});return fromItemMap;}/*** 解析连表查询的表** @param selectBody* @return*/private List<Map<String, String>> parseJoinItem(PlainSelect selectBody, List<Map<String, String>> tableItems) {if (Objects.nonNull(selectBody.getJoins())) {selectBody.getJoins().forEach(j -> {Table rightItem = j.getRightItem(Table.class);Map<String, String> joinItemMap = new HashMap<>();if (rightItem instanceof Table) {rightItem.accept(new FromItemVisitorAdapter() {@Overridepublic void visit(Table table) {joinItemMap.put(CLASSIFY_NAME, table.getSchemaName());joinItemMap.put(TABLE_NAME, table.getName());joinItemMap.put(TABLE_ALIAS, Objects.nonNull(table.getAlias()) ? table.getAlias().getName() : null);}});tableItems.add(joinItemMap);}EasTable easTable = getEasTable(rightItem.getSchemaName(), rightItem.getName());j.setRightItem(new Table(easTable.getTable().getName()));Expression onColumn= j.getOnExpression();if(onColumn!=null){//拼接join 后 的on 条件j.setOnExpression(getNewOnExpression(onColumn,tableItems));}});}return tableItems;}private BinaryExpression getNewOnExpression(Expression onColumn,List<Map<String, String>> tableItems) {Column left=((EqualsTo) onColumn).getLeftExpression(Column.class);Column right=((EqualsTo) onColumn).getRightExpression(Column.class);BinaryExpression onExpression = new EqualsTo();Map<String, String> leftTableMap = tableItems.stream().filter(t -> StringUtils.equals(left.getTable().getName(), t.get(TABLE_ALIAS))).findFirst().orElse(new HashMap<>());Map<String, String> rightTableMap = tableItems.stream().filter(t -> StringUtils.equals(right.getTable().getName(), t.get(TABLE_ALIAS))).findFirst().orElse(new HashMap<>());EasTable leftEasTable ;EasTable rightEasTable;//大于0 表示 匹配到别名 t1, 否则就用默认的 文件夹.表名.列名if(leftTableMap.size()>0 && rightTableMap.size()>0){//  on  左边  =  右边leftEasTable = getEasTable(leftTableMap.get(CLASSIFY_NAME), leftTableMap.get(TABLE_NAME));rightEasTable = getEasTable(rightTableMap.get(CLASSIFY_NAME), rightTableMap.get(TABLE_NAME));}else{rightEasTable = getEasTable(right.getTable().getSchemaName(), right.getTable().getName());leftEasTable = getEasTable(left.getTable().getSchemaName(), left.getTable().getName());}if (Objects.isNull(leftEasTable)) return null;EasColumn leftColumn = leftEasTable.getColumn().stream().filter(c -> StringUtils.equals(left.getColumnName(), c.getName())).findFirst().orElse(null);if (Objects.isNull(leftColumn)) return null;if (Objects.isNull(rightEasTable)) return null;EasColumn rightColumn = rightEasTable.getColumn().stream().filter(c -> StringUtils.equals(right.getColumnName(), c.getName())).findFirst().orElse(null);if (Objects.isNull(rightColumn)) return null;onExpression.setLeftExpression(new Column(new Table(leftEasTable.getTable().getName()),leftColumn.getColumn().getName()));onExpression.setRightExpression(new Column(new Table(rightEasTable.getTable().getName()),rightColumn.getColumn().getName()));return onExpression;}/*** 排序* @param selectBody* @param tableItems*/private void parseOrderBy(PlainSelect selectBody, List<Map<String, String>> tableItems) {if (Objects.nonNull(selectBody.getOrderByElements())) {selectBody.getOrderByElements().forEach(item->{List<Expression> expressions=new ArrayList<>();if(item.getExpression() instanceof Column) {orderByItem(item,tableItems);}else{ExpressionList functionExpressions = ((net.sf.jsqlparser.expression.Function) item.getExpression()).getParameters();List<Expression> expressionList = functionExpressions.getExpressions();expressionList.forEach(expression ->orderByFunction(expression,item,tableItems,expressions));}});}}/*** 根据原字段排序* @param item* @param tableItems*/private void orderByItem(OrderByElement item, List<Map<String, String>> tableItems) {Column expression = item.getExpression(Column.class);Map<String,Object> map= Collections.unmodifiableMap(getNewColumn(tableItems, expression));//重新赋值给 函数表达式EasColumn easColumn=(EasColumn)map.get("easColumn");EasTable easTable=(EasTable)map.get("easTable");item.setExpression(initColumn(easTable.getTable().getName(), easColumn.getColumn().getName()));}/*** 根据 聚合字段排序* @param expression* @param item* @param tableItems* @param expressions*/private void orderByFunction(Expression expression, OrderByElement item, List<Map<String, String>> tableItems, List<Expression> expressions) {Column functionExpression = (Column) expression;item.getExpression().accept(new ExpressionVisitorAdapter() {@Overridepublic void visit(ExpressionList expression) {Map<String,Object> map= Collections.unmodifiableMap(getNewColumn(tableItems, functionExpression));//重新赋值给 函数表达式EasColumn easColumn=(EasColumn)map.get("easColumn");EasTable easTable=(EasTable)map.get("easTable");Column newColumn=initColumn(easTable.getTable().getName(), easColumn.getColumn().getName());//重新赋值给 函数表达式expressions.add(newColumn);expression.setExpressions(expressions);}});}public EasTable getEasTable(String classifyName, String tableName) {return dataManager.load(EasTable.class).query("select e from eas$EasTable e " +"where e.name = :name " +"and e.classify.classifyName = :classify").parameter("name", tableName).parameter("classify", classifyName).view("easTable-view-sqlAssociate").optional().orElse(null);}/*** 解析select sql语句** @param stmt* @return*/public Map<String, Object> parseSelectSql(Select stmt, Page page) {Map<String, Object> map = new HashMap<>();PlainSelect selectBody = (PlainSelect) stmt.getSelectBody();List<Map<String, String>> tableItems = new ArrayList<>();tableItems.add(parseFromItem(selectBody));tableItems.addAll(parseJoinItem(selectBody,tableItems));List<EasTable> resultTables = new ArrayList<>();tableItems.forEach(t -> {EasTable easTable = getEasTable(t.get(CLASSIFY_NAME), t.get(TABLE_NAME));resultTables.add(easTable);resultTables.stream().filter(distinctByKey(BaseUuidEntity::getId));});List<EasColumn> resultColumn = parseSelectItem(selectBody, tableItems);parseWhere(selectBody,tableItems);parseGroupBy(selectBody,tableItems);parseHaving(selectBody,tableItems);parseOrderBy(selectBody,tableItems);Page resultPage = parseLimit(selectBody,page);map.put("sql", stmt.toString());map.put("column", simplifyEasColumn(resultColumn));map.put("tables", translateToTableVo(resultTables));map.put("id", UUID.randomUUID());map.put("page",resultPage);return map;}private List<EasColumn> simplifyEasColumn(List<EasColumn> columns){columns.forEach(c -> c.setTable(null));return columns;}private List<SqlStatementEasTableVo> translateToTableVo(List<EasTable> resultTables) {List<SqlStatementEasTableVo> resultTableVos = new ArrayList<>();resultTables.forEach(t -> {if(Objects.nonNull(t)){SqlStatementEasTableVo sqlStatementEasTableVo = new SqlStatementEasTableVo();sqlStatementEasTableVo.setId(t.getId());sqlStatementEasTableVo.setName(t.getName());sqlStatementEasTableVo.setDescription(t.getDescription());sqlStatementEasTableVo.setVersion(t.getVersion());sqlStatementEasTableVo.setClassifyId(Objects.isNull(t.getClassify()) ? null : t.getClassify().getId());sqlStatementEasTableVo.setClassifyName(Objects.isNull(t.getClassify()) ? null : t.getClassify().getClassifyName());sqlStatementEasTableVo.setDatabaseId(Objects.isNull(t.getDatabase()) ? null : t.getDatabase().getId());resultTableVos.add(sqlStatementEasTableVo);}});return resultTableVos;}/*** 使用jsqlparser把SQL解析成对象** @param sql* @return* @throws JSQLParserException*/public Statements parseStatements(String sql) throws JSQLParserException {return CCJSqlParserUtil.parseStatements(sql);}private RunQueryResponse invokeDataService(String database, String schema, String paramSql) {return QueryRunner.newInstance().url(dataServiceConfig.getDataServiceUrl()).database(database).schema(schema).statement(paramSql).run();}/*** 保存SQL执行历史** @param sql* @param userExt* @param startTime* @return*/public EasSqlStatementOperateHistory saveOperateHistory(String sql, UserExt userExt, long startTime, String operateResult) {long endTime = timeSource.currentTimeMillis();String elapsedTime = endTime - startTime + "";EasSqlStatementOperateHistory easSqlStatementOperateHistory = metadata.create(EasSqlStatementOperateHistory.class);easSqlStatementOperateHistory.setOperator(userExt);easSqlStatementOperateHistory.setSqlStatement(sql);easSqlStatementOperateHistory.setElapsedTime(elapsedTime);easSqlStatementOperateHistory.setOperateResult(operateResult);easSqlStatementOperateHistory.setOperateTime(timeSource.currentTimestamp());dataManager.commit(easSqlStatementOperateHistory);return easSqlStatementOperateHistory;}/*** 获取SQL查询联想内容** @return*/@Overridepublic String getAssociateContent() {long startTime = timeSource.currentTimeMillis();List<EasTable> easTables = dataManager.load(EasTable.class).query("select e from eas$EasTable e where e.tableType = :type1 or e.tableType = :type2 and e.classify.id is not null ").view("easTable-view-sqlAssociate")
//                .parameter("type1",TableType.DATAFRAME.getId())
//                .parameter("type2",TableType.ESDATAFRAME.getId()).parameter("type1","工作表").parameter("type2","ES工作表").list();long time2 = timeSource.currentTimeMillis();log.info("查询easTable耗时:{} ms",time2-startTime);JSONObject resultJson = new JSONObject();easTables.forEach(easTable -> {List<EasColumn> easColumns = dataManager.load(EasColumn.class).query("select e from eas$EasColumn e where e.table.id = :table").parameter("table",easTable.getId()).list();String classifyName = easTable.getClassify().getClassifyName();String name = easTable.getName();Object[] objects = easColumns.stream().map(EasColumn::getName).toArray();resultJson.put(classifyName + "." + name, objects);});long time3 = timeSource.currentTimeMillis();log.info("查询column及拼接耗时:{} ms", time3-time2);return resultJson.toJSONString();}public long getPageCount(Long total, Long pageSize){return (total+pageSize-1)/pageSize;}private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {Map<Object, Boolean> seen = new ConcurrentHashMap<>();return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;}/*** 当前数据服务对SQL格式有着很严格的要求,SQL语句最后必须为空格,且不能带分号* 这里做一些特殊转换* @param sql* @return*/private String formatSql(String sql){sql = sql.trim();if(sql.endsWith(";")){sql = sql.substring(0,sql.length()-1);}return sql.trim()+" ";}}

http://chatgpt.dhexx.cn/article/PgEqRtN2.shtml

相关文章

JSQLParser碰到的问题

JSQLParser是github上一个开源的项目&#xff0c;专门解析SQL&#xff0c;可以轻松地得到一条SQL的列、表、条件等对象&#xff0c; P.S. https://github.com/JSQLParser/JSqlParser 最近在做一个功能开发的时候&#xff0c;被他困扰了下&#xff0c;从需求来讲&#xff0c;就是…

JSqlParser-SQL解析处理

一、介绍 JSqlParse是一款很精简的sql解析工具&#xff0c;将sql语句转成Java对象。 官网&#xff1a;JSqlParser - Home 用法&#xff1a;可以用于数据权限处理&#xff0c;拦截sql解析改写sql等等。 二、版本 <dependency><groupId>com.github.jsqlparser&l…

JSQLParser 解析复杂SQL 2.0

前言 这段时间&#xff0c;为了开发数据中台项目&#xff0c;我去研究学习了JSQLParser&#xff08;Java中解析SQL语句的工具&#xff09;&#xff0c;并且结合网上资料&#xff0c;写了一个初步的SQL解析工具类... 正文 时隔三天&#xff0c;我又回来了&#xff0c; 因为之前J…

JSqlParser入门系列(1)-JSqlParser简介及入门案例

简介 JSqlParser是一个SQL语句解析器。它将SQL转换为Java类的可遍历层次结构。 支持Oracle&#xff0c;SqlServer&#xff0c;MySQL&#xff0c;PostgreSQL等常用数据库。但各种数据库系统的SQL语法都在动态变化&#xff0c;可以解析某些&#xff08;不是全部&#xff09;。 …

JSqlParser

JSqlParser 关于SqlParser引言&#xff1a; Java 生态中较为流行的 SQL Parser 有以下几种&#xff1a; fdb-sql-parser 是 FoundationDB 在被 Apple 收购前开源的 SQL Parser&#xff08;不支持很复杂的SQL&#xff09;&#xff0c;目前已无人维护。jsqlparser 是基于 Java…

Sql解析转换之JSqlParse完整介绍

1、 jsqlparse介绍 JSqlParse是一款很精简的sql解析工具&#xff0c;它可以将常用的sql文本解析成具有层级结构的“语法树”&#xff0c;我们可以针对解析后的“树节点&#xff08;也即官网里说的有层次结构的java类&#xff09;”进行处理进而生成符合我们要求的sql形式。 官…

相机内参模型Kannala-Brandt/fisheye/pinhole+equi详解

文章目录 1. 论文总述2. pinholeradtan无法建模鱼眼相机3. 内参模型3.1 Radially Symmetric Model3.2 Full Model3.3 affine transformation3.4 Backward Model 4. 标定4.1 ORIFL190-3 lens 可以被标定 5. 内参结果验证参考文献 本博客主要从fisheye论文角度&#xff0c;详细介…

python-opencv实现pinhole相机图像转fisheye相机图像

根据鱼眼相机公式rff*θ&#xff0c;其中θatan(rc/f)&#xff0c;即可实现从pinhole相机模型到fisheye相机模型的像素映射。可自行设置焦距&#xff0c;我使用如下代码完成了将cityscape数据集转换为鱼眼视角。 import numpy as np import cv2 import osclass ConvertFisheye…

jiraconfluencefisheye用户同步

分别安装好jira和confluence&#xff0c;fisheye之后&#xff0c;先在jira中将confluence和fisheye的应用程序连接配置好。如下 配置好后&#xff0c;在jira中的用户服务器中可以已经允许对应的程序使用jira的用户了。 此时&#xff0c;分别去confluence或者fisheye的user-d…

Atlassian家族 JIRA Confluence Fisheye 在 Linux (CentOS 7.6 )安装部署教程

安装包 atlassian-agent-v1.2.2.tar.gz # 破解工具atlassian-fisheye-4.8.3.zipatlassian-confluence-7.4.1-lts-x64.binatlassian-jira-software-8.5.5-lts-x64.bin 部署环境 Linux版本&#xff1a;CentOS 7.6VMware 16Confluence 6.3.1Jira 8.5.5MySQL 5.6JDK 1.8…

【图像】【OpenCV鱼眼矫正】二、fisheye::initUndistortRectifyMap()源码分析

目录 一、fisheye::initUndistortRectifyMap() 之 功能介绍二、fisheye::initUndistortRectifyMap() 之 源码分析1. 源码分析2. 更进一步3. 如何由 (j, i) 算出 (u, v) &#xff1f; 一、fisheye::initUndistortRectifyMap() 之 功能介绍 在上一篇文章的第 2. 部分中&#xff…

Monocular Fisheye Camera Depth Estimation Using Sparse LiDAR Supervision

Paper name Monocular Fisheye Camera Depth Estimation Using Sparse LiDAR Supervision Paper Reading Note URL: https://arxiv.org/pdf/1803.06192.pdf TL;DR 2018 年 ITSC 文章&#xff0c;出自于德国 Valeo 自动驾驶公司&#xff0c;提出了单目鱼眼深度估计的有监督…

Linux环境fisheye+crucible安装与破解

由于最新的版本中fisheye和crucible已经集成在一起了&#xff0c;故只需要下载一个包就可以了。 需要的软件及版本情况如下&#xff1a; fisheye4.8.7&#xff1b;&#xff08;安装包&#xff09; atlassian-agent-v1.2.3&#xff1b;&#xff08;破解工具&#xff09; mysql-c…

相机模型-鱼眼模型(fisheye camera model)

鱼眼相机模型 &#xff08;fisheye camera model&#xff09; 模型介绍等距投影等立体角投影正交投影体视投影线性投影 Kannala-Brandt 模型去畸变过程投影过程反投影过程 雅可比计算 之前总结了一下针孔相机的模型&#xff0c;然后得到了比较积极的回复&#xff08;其实是我到…

opencv fisheye calibration(鱼眼相机校正)

文章目录 fisheye_calibration小孔成像模型&#xff08;理想相机成像模型&#xff09;fisheye model 相机模型内参校正的原理calibration过程对这个过程简单分析参考文章 fisheye_calibration 小孔成像模型&#xff08;理想相机成像模型&#xff09; 请参考下面的文章 理想相…

【论文】RAPiD: Rotation-Aware People Detection in Overhead Fisheye Images

RAPiD: Rotation-Aware People Detection in Overhead Fisheye Images 在这项工作中&#xff0c;我们开发了一种端到端的旋转感知的人检测方法&#xff0c;称为RAPID&#xff0c;它使用任意方向的包围盒来检测人。我们的完全卷积神经网络使用周期损失函数直接回归每个包围盒的…

fisheye calib视野调整

1. 畸变模型采用 K np.array([[6.2597563231075685e02, 0., 1.1601088601848592e03],[0., 6.2525998102575511e02, 1.1634786618991664e03],[0., 0., 1.]]) 2. 直接使用 initUndistortRectifyMap和remap时注意调节视野的大小&#xff0c;为了方便得到想要的大小需要借助 es…

初识FishEye

一、简介 这几个月一直都在整白盒测试&#xff0c;虽然断断续续&#xff0c;但是也确实学习了不少东西&#xff0c;长了不少见识。今天就要给大家隆重介绍一款非常棒的工具——FishEye&#xff01; FishEye能够为你打开代码库&#xff0c;并帮助你分析代码&#xff0c;一句话概…

FishEye简介

前言 在项目开发过程中&#xff0c;随着开发的进行&#xff0c;将有大量的代码编写提交到代码仓库&#xff0c;如何能全面准确的了解源代码的变化&#xff0c;提交的频率&#xff0c;代码量的趋势&#xff0c;发现代码的缺陷&#xff0c;将是控制源代码质量的重要指标&#xff…