diff --git a/jeecg-boot/jeecg-boot-base-core/pom.xml b/jeecg-boot/jeecg-boot-base-core/pom.xml index 1f62b586f..9ad9b1ee9 100644 --- a/jeecg-boot/jeecg-boot-base-core/pom.xml +++ b/jeecg-boot/jeecg-boot-base-core/pom.xml @@ -314,5 +314,10 @@ org.jeecgframework.boot jeecg-boot-starter-chatgpt + + + org.jeecgframework + minidao-spring-boot-starter + \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/JSqlParserAllTableManager.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/JSqlParserAllTableManager.java index 1482a0412..ce6eefd26 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/JSqlParserAllTableManager.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/JSqlParserAllTableManager.java @@ -1,255 +1,255 @@ -package org.jeecg.common.util.sqlparse; - -import lombok.extern.slf4j.Slf4j; -import net.sf.jsqlparser.JSQLParserException; -import net.sf.jsqlparser.expression.*; -import net.sf.jsqlparser.parser.CCJSqlParserManager; -import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.schema.Table; -import net.sf.jsqlparser.statement.Statement; -import net.sf.jsqlparser.statement.select.*; -import org.jeecg.common.exception.JeecgBootException; -import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 解析所有表名和字段的类 - */ -@Slf4j -public class JSqlParserAllTableManager { - - private final String sql; - private final Map allTableMap = new HashMap<>(); - /** - * 别名对应实际表名 - */ - private final Map tableAliasMap = new HashMap<>(); - - /** - * 解析后的sql - */ - private String parsedSql = null; - - JSqlParserAllTableManager(String selectSql) { - this.sql = selectSql; - } - - /** - * 开始解析 - * - * @return - * @throws JSQLParserException - */ - public Map parse() throws JSQLParserException { - // 1. 创建解析器 - CCJSqlParserManager mgr = new CCJSqlParserManager(); - // 2. 使用解析器解析sql生成具有层次结构的java类 - Statement stmt = mgr.parse(new StringReader(this.sql)); - if (stmt instanceof Select) { - Select selectStatement = (Select) stmt; - SelectBody selectBody = selectStatement.getSelectBody(); - this.parsedSql = selectBody.toString(); - // 3. 解析select查询sql的信息 - if (selectBody instanceof PlainSelect) { - PlainSelect plainSelect = (PlainSelect) selectBody; - // 4. 合并 fromItems - List fromItems = new ArrayList<>(); - fromItems.add(plainSelect.getFromItem()); - // 4.1 处理join的表 - List joins = plainSelect.getJoins(); - if (joins != null) { - joins.forEach(join -> fromItems.add(join.getRightItem())); - } - // 5. 处理 fromItems - for (FromItem fromItem : fromItems) { - // 5.1 通过表名的方式from - if (fromItem instanceof Table) { - this.addSqlInfoByTable((Table) fromItem); - } - // 5.2 通过子查询的方式from - else if (fromItem instanceof SubSelect) { - this.handleSubSelect((SubSelect) fromItem); - } - } - // 6. 解析 selectFields - List selectItems = plainSelect.getSelectItems(); - for (SelectItem selectItem : selectItems) { - // 6.1 查询的是全部字段 - if (selectItem instanceof AllColumns) { - // 当 selectItem 为 AllColumns 时,fromItem 必定为 Table - String tableName = plainSelect.getFromItem(Table.class).getName(); - // 此处必定不为空,因为在解析 fromItem 时,已经将表名添加到 allTableMap 中 - SelectSqlInfo sqlInfo = this.allTableMap.get(tableName); - assert sqlInfo != null; - // 设置为查询全部字段 - sqlInfo.setSelectAll(true); - sqlInfo.setSelectFields(null); - sqlInfo.setRealSelectFields(null); - } - // 6.2 查询的是带表别名( u.* )的全部字段 - else if (selectItem instanceof AllTableColumns) { - AllTableColumns allTableColumns = (AllTableColumns) selectItem; - String aliasName = allTableColumns.getTable().getName(); - // 通过别名获取表名 - String tableName = this.tableAliasMap.get(aliasName); - if (tableName == null) { - tableName = aliasName; - } - SelectSqlInfo sqlInfo = this.allTableMap.get(tableName); - // 如果此处为空,则说明该字段是通过子查询获取的,所以可以不处理,只有实际表才需要处理 - if (sqlInfo != null) { - // 设置为查询全部字段 - sqlInfo.setSelectAll(true); - sqlInfo.setSelectFields(null); - sqlInfo.setRealSelectFields(null); - } - } - // 6.3 各种字段表达式处理 - else if (selectItem instanceof SelectExpressionItem) { - SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem; - Expression expression = selectExpressionItem.getExpression(); - Alias alias = selectExpressionItem.getAlias(); - this.handleExpression(expression, alias, plainSelect.getFromItem()); - } - } - } else { - log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName()); - throw new JeecgBootException("暂时尚未处理该类型的 SelectBody"); - } - } else { - // 非 select 查询sql,不做处理 - throw new JeecgBootException("非 select 查询sql,不做处理"); - } - return this.allTableMap; - } - - /** - * 处理子查询 - * - * @param subSelect - */ - private void handleSubSelect(SubSelect subSelect) { - try { - String subSelectSql = subSelect.getSelectBody().toString(); - // 递归调用解析 - Map map = JSqlParserUtils.parseAllSelectTable(subSelectSql); - if (map != null) { - this.assignMap(map); - } - } catch (Exception e) { - log.error("解析子查询出错", e); - } - } - - /** - * 处理查询字段表达式 - * - * @param expression - */ - private void handleExpression(Expression expression, Alias alias, FromItem fromItem) { - // 处理函数式字段 CONCAT(name,'(',age,')') - if (expression instanceof Function) { - Function functionExp = (Function) expression; - List expressions = functionExp.getParameters().getExpressions(); - for (Expression expItem : expressions) { - this.handleExpression(expItem, null, fromItem); - } - return; - } - // 处理字段上的子查询 - if (expression instanceof SubSelect) { - this.handleSubSelect((SubSelect) expression); - return; - } - // 不处理字面量 - if (expression instanceof StringValue || - expression instanceof NullValue || - expression instanceof LongValue || - expression instanceof DoubleValue || - expression instanceof HexValue || - expression instanceof DateValue || - expression instanceof TimestampValue || - expression instanceof TimeValue - ) { - return; - } - - // 处理字段 - if (expression instanceof Column) { - Column column = (Column) expression; - // 查询字段名 - String fieldName = column.getColumnName(); - String aliasName = fieldName; - if (alias != null) { - aliasName = alias.getName(); - } - String tableName; - if (column.getTable() != null) { - // 通过列的表名获取 sqlInfo - // 例如 user.name,这里的 tableName 就是 user - tableName = column.getTable().getName(); - // 有可能是别名,需要转换为真实表名 - if (this.tableAliasMap.get(tableName) != null) { - tableName = this.tableAliasMap.get(tableName); - } - } else { - // 当column的table为空时,说明是 fromItem 中的字段 - tableName = ((Table) fromItem).getName(); - } - SelectSqlInfo $sqlInfo = this.allTableMap.get(tableName); - if ($sqlInfo != null) { - $sqlInfo.addSelectField(aliasName, fieldName); - } else { - log.warn("发生意外情况,未找到表名为 {} 的 SelectSqlInfo", tableName); - } - } - } - - /** - * 根据表名添加sqlInfo - * - * @param table - */ - private void addSqlInfoByTable(Table table) { - String tableName = table.getName(); - // 解析 aliasName - if (table.getAlias() != null) { - this.tableAliasMap.put(table.getAlias().getName(), tableName); - } - SelectSqlInfo sqlInfo = new SelectSqlInfo(this.parsedSql); - sqlInfo.setFromTableName(table.getName()); - this.allTableMap.put(sqlInfo.getFromTableName(), sqlInfo); - } - - /** - * 合并map - * - * @param source - */ - private void assignMap(Map source) { - for (Map.Entry entry : source.entrySet()) { - SelectSqlInfo sqlInfo = this.allTableMap.get(entry.getKey()); - if (sqlInfo == null) { - this.allTableMap.put(entry.getKey(), entry.getValue()); - } else { - // 合并 - if (sqlInfo.getSelectFields() == null) { - sqlInfo.setSelectFields(entry.getValue().getSelectFields()); - } else { - sqlInfo.getSelectFields().addAll(entry.getValue().getSelectFields()); - } - if (sqlInfo.getRealSelectFields() == null) { - sqlInfo.setRealSelectFields(entry.getValue().getRealSelectFields()); - } else { - sqlInfo.getRealSelectFields().addAll(entry.getValue().getRealSelectFields()); - } - } - } - } - -} +//package org.jeecg.common.util.sqlparse; +// +//import lombok.extern.slf4j.Slf4j; +//import net.sf.jsqlparser.JSQLParserException; +//import net.sf.jsqlparser.expression.*; +//import net.sf.jsqlparser.parser.CCJSqlParserManager; +//import net.sf.jsqlparser.schema.Column; +//import net.sf.jsqlparser.schema.Table; +//import net.sf.jsqlparser.statement.Statement; +//import net.sf.jsqlparser.statement.select.*; +//import org.jeecg.common.exception.JeecgBootException; +//import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; +// +//import java.io.StringReader; +//import java.util.ArrayList; +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +// +///** +// * 解析所有表名和字段的类 +// */ +//@Slf4j +//public class JSqlParserAllTableManager { +// +// private final String sql; +// private final Map allTableMap = new HashMap<>(); +// /** +// * 别名对应实际表名 +// */ +// private final Map tableAliasMap = new HashMap<>(); +// +// /** +// * 解析后的sql +// */ +// private String parsedSql = null; +// +// JSqlParserAllTableManager(String selectSql) { +// this.sql = selectSql; +// } +// +// /** +// * 开始解析 +// * +// * @return +// * @throws JSQLParserException +// */ +// public Map parse() throws JSQLParserException { +// // 1. 创建解析器 +// CCJSqlParserManager mgr = new CCJSqlParserManager(); +// // 2. 使用解析器解析sql生成具有层次结构的java类 +// Statement stmt = mgr.parse(new StringReader(this.sql)); +// if (stmt instanceof Select) { +// Select selectStatement = (Select) stmt; +// SelectBody selectBody = selectStatement.getSelectBody(); +// this.parsedSql = selectBody.toString(); +// // 3. 解析select查询sql的信息 +// if (selectBody instanceof PlainSelect) { +// PlainSelect plainSelect = (PlainSelect) selectBody; +// // 4. 合并 fromItems +// List fromItems = new ArrayList<>(); +// fromItems.add(plainSelect.getFromItem()); +// // 4.1 处理join的表 +// List joins = plainSelect.getJoins(); +// if (joins != null) { +// joins.forEach(join -> fromItems.add(join.getRightItem())); +// } +// // 5. 处理 fromItems +// for (FromItem fromItem : fromItems) { +// // 5.1 通过表名的方式from +// if (fromItem instanceof Table) { +// this.addSqlInfoByTable((Table) fromItem); +// } +// // 5.2 通过子查询的方式from +// else if (fromItem instanceof SubSelect) { +// this.handleSubSelect((SubSelect) fromItem); +// } +// } +// // 6. 解析 selectFields +// List selectItems = plainSelect.getSelectItems(); +// for (SelectItem selectItem : selectItems) { +// // 6.1 查询的是全部字段 +// if (selectItem instanceof AllColumns) { +// // 当 selectItem 为 AllColumns 时,fromItem 必定为 Table +// String tableName = plainSelect.getFromItem(Table.class).getName(); +// // 此处必定不为空,因为在解析 fromItem 时,已经将表名添加到 allTableMap 中 +// SelectSqlInfo sqlInfo = this.allTableMap.get(tableName); +// assert sqlInfo != null; +// // 设置为查询全部字段 +// sqlInfo.setSelectAll(true); +// sqlInfo.setSelectFields(null); +// sqlInfo.setRealSelectFields(null); +// } +// // 6.2 查询的是带表别名( u.* )的全部字段 +// else if (selectItem instanceof AllTableColumns) { +// AllTableColumns allTableColumns = (AllTableColumns) selectItem; +// String aliasName = allTableColumns.getTable().getName(); +// // 通过别名获取表名 +// String tableName = this.tableAliasMap.get(aliasName); +// if (tableName == null) { +// tableName = aliasName; +// } +// SelectSqlInfo sqlInfo = this.allTableMap.get(tableName); +// // 如果此处为空,则说明该字段是通过子查询获取的,所以可以不处理,只有实际表才需要处理 +// if (sqlInfo != null) { +// // 设置为查询全部字段 +// sqlInfo.setSelectAll(true); +// sqlInfo.setSelectFields(null); +// sqlInfo.setRealSelectFields(null); +// } +// } +// // 6.3 各种字段表达式处理 +// else if (selectItem instanceof SelectExpressionItem) { +// SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem; +// Expression expression = selectExpressionItem.getExpression(); +// Alias alias = selectExpressionItem.getAlias(); +// this.handleExpression(expression, alias, plainSelect.getFromItem()); +// } +// } +// } else { +// log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName()); +// throw new JeecgBootException("暂时尚未处理该类型的 SelectBody"); +// } +// } else { +// // 非 select 查询sql,不做处理 +// throw new JeecgBootException("非 select 查询sql,不做处理"); +// } +// return this.allTableMap; +// } +// +// /** +// * 处理子查询 +// * +// * @param subSelect +// */ +// private void handleSubSelect(SubSelect subSelect) { +// try { +// String subSelectSql = subSelect.getSelectBody().toString(); +// // 递归调用解析 +// Map map = JSqlParserUtils.parseAllSelectTable(subSelectSql); +// if (map != null) { +// this.assignMap(map); +// } +// } catch (Exception e) { +// log.error("解析子查询出错", e); +// } +// } +// +// /** +// * 处理查询字段表达式 +// * +// * @param expression +// */ +// private void handleExpression(Expression expression, Alias alias, FromItem fromItem) { +// // 处理函数式字段 CONCAT(name,'(',age,')') +// if (expression instanceof Function) { +// Function functionExp = (Function) expression; +// List expressions = functionExp.getParameters().getExpressions(); +// for (Expression expItem : expressions) { +// this.handleExpression(expItem, null, fromItem); +// } +// return; +// } +// // 处理字段上的子查询 +// if (expression instanceof SubSelect) { +// this.handleSubSelect((SubSelect) expression); +// return; +// } +// // 不处理字面量 +// if (expression instanceof StringValue || +// expression instanceof NullValue || +// expression instanceof LongValue || +// expression instanceof DoubleValue || +// expression instanceof HexValue || +// expression instanceof DateValue || +// expression instanceof TimestampValue || +// expression instanceof TimeValue +// ) { +// return; +// } +// +// // 处理字段 +// if (expression instanceof Column) { +// Column column = (Column) expression; +// // 查询字段名 +// String fieldName = column.getColumnName(); +// String aliasName = fieldName; +// if (alias != null) { +// aliasName = alias.getName(); +// } +// String tableName; +// if (column.getTable() != null) { +// // 通过列的表名获取 sqlInfo +// // 例如 user.name,这里的 tableName 就是 user +// tableName = column.getTable().getName(); +// // 有可能是别名,需要转换为真实表名 +// if (this.tableAliasMap.get(tableName) != null) { +// tableName = this.tableAliasMap.get(tableName); +// } +// } else { +// // 当column的table为空时,说明是 fromItem 中的字段 +// tableName = ((Table) fromItem).getName(); +// } +// SelectSqlInfo $sqlInfo = this.allTableMap.get(tableName); +// if ($sqlInfo != null) { +// $sqlInfo.addSelectField(aliasName, fieldName); +// } else { +// log.warn("发生意外情况,未找到表名为 {} 的 SelectSqlInfo", tableName); +// } +// } +// } +// +// /** +// * 根据表名添加sqlInfo +// * +// * @param table +// */ +// private void addSqlInfoByTable(Table table) { +// String tableName = table.getName(); +// // 解析 aliasName +// if (table.getAlias() != null) { +// this.tableAliasMap.put(table.getAlias().getName(), tableName); +// } +// SelectSqlInfo sqlInfo = new SelectSqlInfo(this.parsedSql); +// sqlInfo.setFromTableName(table.getName()); +// this.allTableMap.put(sqlInfo.getFromTableName(), sqlInfo); +// } +// +// /** +// * 合并map +// * +// * @param source +// */ +// private void assignMap(Map source) { +// for (Map.Entry entry : source.entrySet()) { +// SelectSqlInfo sqlInfo = this.allTableMap.get(entry.getKey()); +// if (sqlInfo == null) { +// this.allTableMap.put(entry.getKey(), entry.getValue()); +// } else { +// // 合并 +// if (sqlInfo.getSelectFields() == null) { +// sqlInfo.setSelectFields(entry.getValue().getSelectFields()); +// } else { +// sqlInfo.getSelectFields().addAll(entry.getValue().getSelectFields()); +// } +// if (sqlInfo.getRealSelectFields() == null) { +// sqlInfo.setRealSelectFields(entry.getValue().getRealSelectFields()); +// } else { +// sqlInfo.getRealSelectFields().addAll(entry.getValue().getRealSelectFields()); +// } +// } +// } +// } +// +//} diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/JSqlParserUtils.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/JSqlParserUtils.java index 01373e4ff..e8788b718 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/JSqlParserUtils.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/JSqlParserUtils.java @@ -1,190 +1,190 @@ -package org.jeecg.common.util.sqlparse; - -import lombok.extern.slf4j.Slf4j; -import net.sf.jsqlparser.JSQLParserException; -import net.sf.jsqlparser.expression.*; -import net.sf.jsqlparser.parser.CCJSqlParserManager; -import net.sf.jsqlparser.schema.Column; -import net.sf.jsqlparser.schema.Table; -import net.sf.jsqlparser.statement.Statement; -import net.sf.jsqlparser.statement.select.*; -import org.jeecg.common.exception.JeecgBootException; -import org.jeecg.common.util.oConvertUtils; -import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; - -import java.io.StringReader; -import java.util.List; -import java.util.Map; - -@Slf4j -public class JSqlParserUtils { - - /** - * 解析 查询(select)sql的信息, - * 此方法会展开所有子查询到一个map里, - * key只存真实的表名,如果查询的没有真实的表名,则会被忽略。 - * value只存真实的字段名,如果查询的没有真实的字段名,则会被忽略。 - *

- * 例如:SELECT a.*,d.age,(SELECT count(1) FROM sys_depart) AS count FROM (SELECT username AS foo, realname FROM sys_user) a, demo d - * 解析后的结果为:{sys_user=[username, realname], demo=[age], sys_depart=[]} - * - * @param selectSql - * @return - */ - public static Map parseAllSelectTable(String selectSql) throws JSQLParserException { - if (oConvertUtils.isEmpty(selectSql)) { - return null; - } - // log.info("解析查询Sql:{}", selectSql); - JSqlParserAllTableManager allTableManager = new JSqlParserAllTableManager(selectSql); - return allTableManager.parse(); - } - - /** - * 解析 查询(select)sql的信息,子查询嵌套 - * - * @param selectSql - * @return - */ - public static SelectSqlInfo parseSelectSqlInfo(String selectSql) throws JSQLParserException { - if (oConvertUtils.isEmpty(selectSql)) { - return null; - } - // log.info("解析查询Sql:{}", selectSql); - // 使用 JSqlParer 解析sql - // 1、创建解析器 - CCJSqlParserManager mgr = new CCJSqlParserManager(); - // 2、使用解析器解析sql生成具有层次结构的java类 - Statement stmt = mgr.parse(new StringReader(selectSql)); - if (stmt instanceof Select) { - Select selectStatement = (Select) stmt; - // 3、解析select查询sql的信息 - return JSqlParserUtils.parseBySelectBody(selectStatement.getSelectBody()); - } else { - // 非 select 查询sql,不做处理 - throw new JeecgBootException("非 select 查询sql,不做处理"); - } - } - - /** - * 解析 select 查询sql的信息 - * - * @param selectBody - * @return - */ - private static SelectSqlInfo parseBySelectBody(SelectBody selectBody) { - // 判断是否使用了union等操作 - if (selectBody instanceof SetOperationList) { - // 如果使用了union等操作,则只解析第一个查询 - List selectBodyList = ((SetOperationList) selectBody).getSelects(); - return JSqlParserUtils.parseBySelectBody(selectBodyList.get(0)); - } - // 简单的select查询 - if (selectBody instanceof PlainSelect) { - SelectSqlInfo sqlInfo = new SelectSqlInfo(selectBody); - PlainSelect plainSelect = (PlainSelect) selectBody; - FromItem fromItem = plainSelect.getFromItem(); - // 解析 aliasName - if (fromItem.getAlias() != null) { - sqlInfo.setFromTableAliasName(fromItem.getAlias().getName()); - } - // 解析 表名 - if (fromItem instanceof Table) { - // 通过表名的方式from - Table fromTable = (Table) fromItem; - sqlInfo.setFromTableName(fromTable.getName()); - } else if (fromItem instanceof SubSelect) { - // 通过子查询的方式from - SubSelect fromSubSelect = (SubSelect) fromItem; - SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(fromSubSelect.getSelectBody()); - sqlInfo.setFromSubSelect(subSqlInfo); - } - // 解析 selectFields - List selectItems = plainSelect.getSelectItems(); - for (SelectItem selectItem : selectItems) { - if (selectItem instanceof AllColumns || selectItem instanceof AllTableColumns) { - // 全部字段 - sqlInfo.setSelectAll(true); - sqlInfo.setSelectFields(null); - sqlInfo.setRealSelectFields(null); - break; - } else if (selectItem instanceof SelectExpressionItem) { - // 获取单个查询字段名 - SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem; - Expression expression = selectExpressionItem.getExpression(); - Alias alias = selectExpressionItem.getAlias(); - JSqlParserUtils.handleExpression(sqlInfo, expression, alias); - } - } - return sqlInfo; - } else { - log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName()); - throw new JeecgBootException("暂时尚未处理该类型的 SelectBody"); - } - } - - /** - * 处理查询字段表达式 - * - * @param sqlInfo - * @param expression - * @param alias 是否有别名,无传null - */ - private static void handleExpression(SelectSqlInfo sqlInfo, Expression expression, Alias alias) { - // 处理函数式字段 CONCAT(name,'(',age,')') - if (expression instanceof Function) { - JSqlParserUtils.handleFunctionExpression((Function) expression, sqlInfo); - return; - } - // 处理字段上的子查询 - if (expression instanceof SubSelect) { - SubSelect subSelect = (SubSelect) expression; - SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(subSelect.getSelectBody()); - // 注:字段上的子查询,必须只查询一个字段,否则会报错,所以可以放心合并 - sqlInfo.getSelectFields().addAll(subSqlInfo.getSelectFields()); - sqlInfo.getRealSelectFields().addAll(subSqlInfo.getAllRealSelectFields()); - return; - } - // 不处理字面量 - if (expression instanceof StringValue || - expression instanceof NullValue || - expression instanceof LongValue || - expression instanceof DoubleValue || - expression instanceof HexValue || - expression instanceof DateValue || - expression instanceof TimestampValue || - expression instanceof TimeValue - ) { - return; - } - - // 查询字段名 - String selectField = expression.toString(); - // 实际查询字段名 - String realSelectField = selectField; - // 判断是否有别名 - if (alias != null) { - selectField = alias.getName(); - } - // 获取真实字段名 - if (expression instanceof Column) { - Column column = (Column) expression; - realSelectField = column.getColumnName(); - } - sqlInfo.addSelectField(selectField, realSelectField); - } - - /** - * 处理函数式字段 - * - * @param functionExp - * @param sqlInfo - */ - private static void handleFunctionExpression(Function functionExp, SelectSqlInfo sqlInfo) { - List expressions = functionExp.getParameters().getExpressions(); - for (Expression expression : expressions) { - JSqlParserUtils.handleExpression(sqlInfo, expression, null); - } - } - -} +//package org.jeecg.common.util.sqlparse; +// +//import lombok.extern.slf4j.Slf4j; +//import net.sf.jsqlparser.JSQLParserException; +//import net.sf.jsqlparser.expression.*; +//import net.sf.jsqlparser.parser.CCJSqlParserManager; +//import net.sf.jsqlparser.schema.Column; +//import net.sf.jsqlparser.schema.Table; +//import net.sf.jsqlparser.statement.Statement; +//import net.sf.jsqlparser.statement.select.*; +//import org.jeecg.common.exception.JeecgBootException; +//import org.jeecg.common.util.oConvertUtils; +//import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; +// +//import java.io.StringReader; +//import java.util.List; +//import java.util.Map; +// +//@Slf4j +//public class JSqlParserUtils { +// +// /** +// * 解析 查询(select)sql的信息, +// * 此方法会展开所有子查询到一个map里, +// * key只存真实的表名,如果查询的没有真实的表名,则会被忽略。 +// * value只存真实的字段名,如果查询的没有真实的字段名,则会被忽略。 +// *

+// * 例如:SELECT a.*,d.age,(SELECT count(1) FROM sys_depart) AS count FROM (SELECT username AS foo, realname FROM sys_user) a, demo d +// * 解析后的结果为:{sys_user=[username, realname], demo=[age], sys_depart=[]} +// * +// * @param selectSql +// * @return +// */ +// public static Map parseAllSelectTable(String selectSql) throws JSQLParserException { +// if (oConvertUtils.isEmpty(selectSql)) { +// return null; +// } +// // log.info("解析查询Sql:{}", selectSql); +// JSqlParserAllTableManager allTableManager = new JSqlParserAllTableManager(selectSql); +// return allTableManager.parse(); +// } +// +// /** +// * 解析 查询(select)sql的信息,子查询嵌套 +// * +// * @param selectSql +// * @return +// */ +// public static SelectSqlInfo parseSelectSqlInfo(String selectSql) throws JSQLParserException { +// if (oConvertUtils.isEmpty(selectSql)) { +// return null; +// } +// // log.info("解析查询Sql:{}", selectSql); +// // 使用 JSqlParer 解析sql +// // 1、创建解析器 +// CCJSqlParserManager mgr = new CCJSqlParserManager(); +// // 2、使用解析器解析sql生成具有层次结构的java类 +// Statement stmt = mgr.parse(new StringReader(selectSql)); +// if (stmt instanceof Select) { +// Select selectStatement = (Select) stmt; +// // 3、解析select查询sql的信息 +// return JSqlParserUtils.parseBySelectBody(selectStatement.getSelectBody()); +// } else { +// // 非 select 查询sql,不做处理 +// throw new JeecgBootException("非 select 查询sql,不做处理"); +// } +// } +// +// /** +// * 解析 select 查询sql的信息 +// * +// * @param selectBody +// * @return +// */ +// private static SelectSqlInfo parseBySelectBody(SelectBody selectBody) { +// // 判断是否使用了union等操作 +// if (selectBody instanceof SetOperationList) { +// // 如果使用了union等操作,则只解析第一个查询 +// List selectBodyList = ((SetOperationList) selectBody).getSelects(); +// return JSqlParserUtils.parseBySelectBody(selectBodyList.get(0)); +// } +// // 简单的select查询 +// if (selectBody instanceof PlainSelect) { +// SelectSqlInfo sqlInfo = new SelectSqlInfo(selectBody); +// PlainSelect plainSelect = (PlainSelect) selectBody; +// FromItem fromItem = plainSelect.getFromItem(); +// // 解析 aliasName +// if (fromItem.getAlias() != null) { +// sqlInfo.setFromTableAliasName(fromItem.getAlias().getName()); +// } +// // 解析 表名 +// if (fromItem instanceof Table) { +// // 通过表名的方式from +// Table fromTable = (Table) fromItem; +// sqlInfo.setFromTableName(fromTable.getName()); +// } else if (fromItem instanceof SubSelect) { +// // 通过子查询的方式from +// SubSelect fromSubSelect = (SubSelect) fromItem; +// SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(fromSubSelect.getSelectBody()); +// sqlInfo.setFromSubSelect(subSqlInfo); +// } +// // 解析 selectFields +// List selectItems = plainSelect.getSelectItems(); +// for (SelectItem selectItem : selectItems) { +// if (selectItem instanceof AllColumns || selectItem instanceof AllTableColumns) { +// // 全部字段 +// sqlInfo.setSelectAll(true); +// sqlInfo.setSelectFields(null); +// sqlInfo.setRealSelectFields(null); +// break; +// } else if (selectItem instanceof SelectExpressionItem) { +// // 获取单个查询字段名 +// SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem; +// Expression expression = selectExpressionItem.getExpression(); +// Alias alias = selectExpressionItem.getAlias(); +// JSqlParserUtils.handleExpression(sqlInfo, expression, alias); +// } +// } +// return sqlInfo; +// } else { +// log.warn("暂时尚未处理该类型的 SelectBody: {}", selectBody.getClass().getName()); +// throw new JeecgBootException("暂时尚未处理该类型的 SelectBody"); +// } +// } +// +// /** +// * 处理查询字段表达式 +// * +// * @param sqlInfo +// * @param expression +// * @param alias 是否有别名,无传null +// */ +// private static void handleExpression(SelectSqlInfo sqlInfo, Expression expression, Alias alias) { +// // 处理函数式字段 CONCAT(name,'(',age,')') +// if (expression instanceof Function) { +// JSqlParserUtils.handleFunctionExpression((Function) expression, sqlInfo); +// return; +// } +// // 处理字段上的子查询 +// if (expression instanceof SubSelect) { +// SubSelect subSelect = (SubSelect) expression; +// SelectSqlInfo subSqlInfo = JSqlParserUtils.parseBySelectBody(subSelect.getSelectBody()); +// // 注:字段上的子查询,必须只查询一个字段,否则会报错,所以可以放心合并 +// sqlInfo.getSelectFields().addAll(subSqlInfo.getSelectFields()); +// sqlInfo.getRealSelectFields().addAll(subSqlInfo.getAllRealSelectFields()); +// return; +// } +// // 不处理字面量 +// if (expression instanceof StringValue || +// expression instanceof NullValue || +// expression instanceof LongValue || +// expression instanceof DoubleValue || +// expression instanceof HexValue || +// expression instanceof DateValue || +// expression instanceof TimestampValue || +// expression instanceof TimeValue +// ) { +// return; +// } +// +// // 查询字段名 +// String selectField = expression.toString(); +// // 实际查询字段名 +// String realSelectField = selectField; +// // 判断是否有别名 +// if (alias != null) { +// selectField = alias.getName(); +// } +// // 获取真实字段名 +// if (expression instanceof Column) { +// Column column = (Column) expression; +// realSelectField = column.getColumnName(); +// } +// sqlInfo.addSelectField(selectField, realSelectField); +// } +// +// /** +// * 处理函数式字段 +// * +// * @param functionExp +// * @param sqlInfo +// */ +// private static void handleFunctionExpression(Function functionExp, SelectSqlInfo sqlInfo) { +// List expressions = functionExp.getParameters().getExpressions(); +// for (Expression expression : expressions) { +// JSqlParserUtils.handleExpression(sqlInfo, expression, null); +// } +// } +// +//} diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/vo/SelectSqlInfo.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/vo/SelectSqlInfo.java index 1a3d4dd1b..8d0e1325b 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/vo/SelectSqlInfo.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/sqlparse/vo/SelectSqlInfo.java @@ -1,101 +1,101 @@ -package org.jeecg.common.util.sqlparse.vo; - -import lombok.Data; -import net.sf.jsqlparser.statement.select.SelectBody; - -import java.util.HashSet; -import java.util.Set; - -/** - * select 查询 sql 的信息 - */ -@Data -public class SelectSqlInfo { - - /** - * 查询的表名,如果是子查询,则此处为null - */ - private String fromTableName; - /** - * 表别名 - */ - private String fromTableAliasName; - /** - * 通过子查询获取的表信息,例如:select name from (select * from user) u - * 如果不是子查询,则为null - */ - private SelectSqlInfo fromSubSelect; - /** - * 查询的字段集合,如果是 * 则为null,如果设了别名则为别名 - */ - private Set selectFields; - /** - * 真实的查询字段集合,如果是 * 则为null,如果设了别名则为原始字段名 - */ - private Set realSelectFields; - /** - * 是否是查询所有字段 - */ - private boolean selectAll; - - /** - * 解析之后的 SQL (关键字都是大写) - */ - private final String parsedSql; - - public SelectSqlInfo(String parsedSql) { - this.parsedSql = parsedSql; - } - - public SelectSqlInfo(SelectBody selectBody) { - this.parsedSql = selectBody.toString(); - } - - public void addSelectField(String selectField, String realSelectField) { - if (this.selectFields == null) { - this.selectFields = new HashSet<>(); - } - if (this.realSelectFields == null) { - this.realSelectFields = new HashSet<>(); - } - this.selectFields.add(selectField); - this.realSelectFields.add(realSelectField); - } - - /** - * 获取所有字段,包括子查询里的。 - * - * @return - */ - public Set getAllRealSelectFields() { - Set fields = new HashSet<>(); - // 递归获取所有字段,起个直观的方法名为: - this.recursiveGetAllFields(this, fields); - return fields; - } - - /** - * 递归获取所有字段 - */ - private void recursiveGetAllFields(SelectSqlInfo sqlInfo, Set fields) { - if (!sqlInfo.isSelectAll() && sqlInfo.getRealSelectFields() != null) { - fields.addAll(sqlInfo.getRealSelectFields()); - } - if (sqlInfo.getFromSubSelect() != null) { - recursiveGetAllFields(sqlInfo.getFromSubSelect(), fields); - } - } - - @Override - public String toString() { - return "SelectSqlInfo{" + - "fromTableName='" + fromTableName + '\'' + - ", fromSubSelect=" + fromSubSelect + - ", aliasName='" + fromTableAliasName + '\'' + - ", selectFields=" + selectFields + - ", realSelectFields=" + realSelectFields + - ", selectAll=" + selectAll + - "}"; - } - -} +//package org.jeecg.common.util.sqlparse.vo; +// +//import lombok.Data; +//import net.sf.jsqlparser.statement.select.SelectBody; +// +//import java.util.HashSet; +//import java.util.Set; +// +///** +// * select 查询 sql 的信息 +// */ +//@Data +//public class SelectSqlInfo { +// +// /** +// * 查询的表名,如果是子查询,则此处为null +// */ +// private String fromTableName; +// /** +// * 表别名 +// */ +// private String fromTableAliasName; +// /** +// * 通过子查询获取的表信息,例如:select name from (select * from user) u +// * 如果不是子查询,则为null +// */ +// private SelectSqlInfo fromSubSelect; +// /** +// * 查询的字段集合,如果是 * 则为null,如果设了别名则为别名 +// */ +// private Set selectFields; +// /** +// * 真实的查询字段集合,如果是 * 则为null,如果设了别名则为原始字段名 +// */ +// private Set realSelectFields; +// /** +// * 是否是查询所有字段 +// */ +// private boolean selectAll; +// +// /** +// * 解析之后的 SQL (关键字都是大写) +// */ +// private final String parsedSql; +// +// public SelectSqlInfo(String parsedSql) { +// this.parsedSql = parsedSql; +// } +// +// public SelectSqlInfo(SelectBody selectBody) { +// this.parsedSql = selectBody.toString(); +// } +// +// public void addSelectField(String selectField, String realSelectField) { +// if (this.selectFields == null) { +// this.selectFields = new HashSet<>(); +// } +// if (this.realSelectFields == null) { +// this.realSelectFields = new HashSet<>(); +// } +// this.selectFields.add(selectField); +// this.realSelectFields.add(realSelectField); +// } +// +// /** +// * 获取所有字段,包括子查询里的。 +// * +// * @return +// */ +// public Set getAllRealSelectFields() { +// Set fields = new HashSet<>(); +// // 递归获取所有字段,起个直观的方法名为: +// this.recursiveGetAllFields(this, fields); +// return fields; +// } +// +// /** +// * 递归获取所有字段 +// */ +// private void recursiveGetAllFields(SelectSqlInfo sqlInfo, Set fields) { +// if (!sqlInfo.isSelectAll() && sqlInfo.getRealSelectFields() != null) { +// fields.addAll(sqlInfo.getRealSelectFields()); +// } +// if (sqlInfo.getFromSubSelect() != null) { +// recursiveGetAllFields(sqlInfo.getFromSubSelect(), fields); +// } +// } +// +// @Override +// public String toString() { +// return "SelectSqlInfo{" + +// "fromTableName='" + fromTableName + '\'' + +// ", fromSubSelect=" + fromSubSelect + +// ", aliasName='" + fromTableAliasName + '\'' + +// ", selectFields=" + selectFields + +// ", realSelectFields=" + realSelectFields + +// ", selectAll=" + selectAll + +// "}"; +// } +// +//} diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/config/firewall/SqlInjection/impl/DictTableWhiteListHandlerImpl.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/config/firewall/SqlInjection/impl/DictTableWhiteListHandlerImpl.java index 81f74fd9a..f4cf29c68 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/config/firewall/SqlInjection/impl/DictTableWhiteListHandlerImpl.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/config/firewall/SqlInjection/impl/DictTableWhiteListHandlerImpl.java @@ -4,14 +4,14 @@ import lombok.extern.slf4j.Slf4j; import org.jeecg.common.constant.SymbolConstant; import org.jeecg.common.exception.JeecgSqlInjectionException; import org.jeecg.common.util.oConvertUtils; -import org.jeecg.common.util.sqlparse.JSqlParserUtils; -import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo; import org.jeecg.config.JeecgBaseConfig; import org.jeecg.config.firewall.SqlInjection.IDictTableWhiteListHandler; import org.jeecg.config.firewall.interceptor.LowCodeModeInterceptor; import org.jeecg.modules.system.entity.SysTableWhiteList; import org.jeecg.modules.system.security.DictQueryBlackListHandler; import org.jeecg.modules.system.service.ISysTableWhiteListService; +import org.jeecgframework.minidao.sqlparser.impl.vo.SelectSqlInfo; +import org.jeecgframework.minidao.util.MiniDaoUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -65,7 +65,7 @@ public class DictTableWhiteListHandlerImpl implements IDictTableWhiteListHandler public boolean isPassBySql(String sql) { Map parsedMap = null; try { - parsedMap = JSqlParserUtils.parseAllSelectTable(sql); + parsedMap = MiniDaoUtil.parseAllSelectTable(sql); } catch (Exception e) { log.warn("校验sql语句,解析报错:{}", e.getMessage()); } @@ -127,7 +127,7 @@ public class DictTableWhiteListHandlerImpl implements IDictTableWhiteListHandler log.info("字典拼接的查询SQL:{}", sql); try { // 进行SQL解析 - JSqlParserUtils.parseSelectSqlInfo(sql); + MiniDaoUtil.parseSelectSqlInfo(sql); } catch (Exception e) { // 如果SQL解析失败,则通过字段名和表名进行校验 return checkWhiteList(tableName, new HashSet<>(Arrays.asList(fields))); diff --git a/jeecg-boot/pom.xml b/jeecg-boot/pom.xml index 56492188a..8498c278d 100644 --- a/jeecg-boot/pom.xml +++ b/jeecg-boot/pom.xml @@ -40,7 +40,7 @@ 1.5.2 2.4.1 - 2.0.56 + 2.0.57 5.2.6 1.6.0 0.17.0 @@ -56,7 +56,8 @@ 8.1.1.49 - 1.9.5 + 1.9.5.1 + 1.10.7 3.5.3.2 4.1.3 @@ -254,7 +255,7 @@ org.jeecgframework.boot hibernate-re - 3.8.0-GA + 3.8.0.1 @@ -359,7 +360,7 @@ org.jeecgframework weixin4j - 2.0.2 + 2.0.4 commons-beanutils @@ -383,6 +384,22 @@ + + + org.jeecgframework + minidao-spring-boot-starter + ${minidao.version} + + + druid + com.alibaba + + + jsqlparser + com.github.jsqlparser + + + org.jeecgframework.jimureport @@ -418,7 +435,7 @@ org.jeecgframework.jimureport jimureport-nosql-starter - ${jimureport-spring-boot-starter.version} + 1.9.5.2 org.apache.calcite @@ -430,7 +447,7 @@ org.jeecgframework.jimureport jimubi-spring-boot-starter - 1.9.4 + 1.9.5