joins = plainSelect.getJoins();
+ if (CollectionUtils.isNotEmpty(joins)) {
+ processJoins(joins);
+ }
+ }
+
+ /**
+ * 处理where条件内的子查询
+ *
+ * 支持如下:
+ * 1. in
+ * 2. =
+ * 3. >
+ * 4. <
+ * 5. >=
+ * 6. <=
+ * 7. <>
+ * 8. EXISTS
+ * 9. NOT EXISTS
+ *
+ * 前提条件:
+ * 1. 子查询必须放在小括号中
+ * 2. 子查询一般放在比较操作符的右边
+ *
+ * @param where where 条件
+ */
+ protected void processWhereSubSelect(Expression where) {
+ if (where == null) {
+ return;
+ }
+ if (where instanceof FromItem) {
+ processFromItem((FromItem) where);
+ return;
+ }
+ if (where.toString().indexOf("SELECT") > 0) {
+ // 有子查询
+ if (where instanceof BinaryExpression) {
+ // 比较符号 , and , or , 等等
+ BinaryExpression expression = (BinaryExpression) where;
+ processWhereSubSelect(expression.getLeftExpression());
+ processWhereSubSelect(expression.getRightExpression());
+ } else if (where instanceof InExpression) {
+ // in
+ InExpression expression = (InExpression) where;
+ ItemsList itemsList = expression.getRightItemsList();
+ if (itemsList instanceof SubSelect) {
+ processSelectBody(((SubSelect) itemsList).getSelectBody());
+ }
+ } else if (where instanceof ExistsExpression) {
+ // exists
+ ExistsExpression expression = (ExistsExpression) where;
+ processWhereSubSelect(expression.getRightExpression());
+ } else if (where instanceof NotExpression) {
+ // not exists
+ NotExpression expression = (NotExpression) where;
+ processWhereSubSelect(expression.getExpression());
+ } else if (where instanceof Parenthesis) {
+ Parenthesis expression = (Parenthesis) where;
+ processWhereSubSelect(expression.getExpression());
+ }
+ }
+ }
+
+ protected void processSelectItem(SelectItem selectItem) {
+ if (selectItem instanceof SelectExpressionItem) {
+ SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
+ if (selectExpressionItem.getExpression() instanceof SubSelect) {
+ processSelectBody(((SubSelect) selectExpressionItem.getExpression()).getSelectBody());
+ } else if (selectExpressionItem.getExpression() instanceof Function) {
+ processFunction((Function) selectExpressionItem.getExpression());
+ }
+ }
+ }
+
+ /**
+ * 处理函数
+ *
支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)
+ *
fixed gitee pulls/141
+ *
+ * @param function
+ */
+ protected void processFunction(Function function) {
+ ExpressionList parameters = function.getParameters();
+ if (parameters != null) {
+ parameters.getExpressions().forEach(expression -> {
+ if (expression instanceof SubSelect) {
+ processSelectBody(((SubSelect) expression).getSelectBody());
+ } else if (expression instanceof Function) {
+ processFunction((Function) expression);
+ }
+ });
+ }
+ }
+
+ /**
+ * 处理子查询等
+ */
+ protected void processFromItem(FromItem fromItem) {
+ if (fromItem instanceof SubJoin) {
+ SubJoin subJoin = (SubJoin) fromItem;
+ if (subJoin.getJoinList() != null) {
+ processJoins(subJoin.getJoinList());
+ }
+ if (subJoin.getLeft() != null) {
+ processFromItem(subJoin.getLeft());
+ }
+ } else if (fromItem instanceof SubSelect) {
+ SubSelect subSelect = (SubSelect) fromItem;
+ if (subSelect.getSelectBody() != null) {
+ processSelectBody(subSelect.getSelectBody());
+ }
+ } else if (fromItem instanceof ValuesList) {
+ logger.debug("Perform a subquery, if you do not give us feedback");
+ } else if (fromItem instanceof LateralSubSelect) {
+ LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem;
+ if (lateralSubSelect.getSubSelect() != null) {
+ SubSelect subSelect = lateralSubSelect.getSubSelect();
+ if (subSelect.getSelectBody() != null) {
+ processSelectBody(subSelect.getSelectBody());
+ }
+ }
+ }
+ }
+
+ /**
+ * 处理 joins
+ *
+ * @param joins join 集合
+ */
+ private void processJoins(List joins) {
+ //对于 on 表达式写在最后的 join,需要记录下前面多个 on 的表名
+ Deque tables = new LinkedList<>();
+ for (Join join : joins) {
+ // 处理 on 表达式
+ FromItem fromItem = join.getRightItem();
+ if (fromItem instanceof Table) {
+ Table fromTable = (Table) fromItem;
+ // 获取 join 尾缀的 on 表达式列表
+ Collection originOnExpressions = join.getOnExpressions();
+ // 正常 join on 表达式只有一个,立刻处理
+ if (originOnExpressions.size() == 1) {
+ processJoin(join);
+ continue;
+ }
+ // 当前表是否忽略
+ boolean needIgnore = ignoreTable(fromTable.getName());
+ // 表名压栈,忽略的表压入 null,以便后续不处理
+ tables.push(needIgnore ? null : fromTable);
+ // 尾缀多个 on 表达式的时候统一处理
+ if (originOnExpressions.size() > 1) {
+ Collection onExpressions = new LinkedList<>();
+ for (Expression originOnExpression : originOnExpressions) {
+ Table currentTable = tables.poll();
+ if (currentTable == null) {
+ onExpressions.add(originOnExpression);
+ } else {
+ onExpressions.add(builderExpression(originOnExpression, currentTable));
+ }
+ }
+ join.setOnExpressions(onExpressions);
+ }
+ } else {
+ // 处理右边连接的子表达式
+ processFromItem(fromItem);
+ }
+ }
+ }
+
+ /**
+ * 处理联接语句
+ */
+ protected void processJoin(Join join) {
+ if (join.getRightItem() instanceof Table) {
+ Table fromTable = (Table) join.getRightItem();
+ if (ignoreTable(fromTable.getName())) {
+ // 过滤退出执行
+ return;
+ }
+ // 走到这里说明 on 表达式肯定只有一个
+ Collection originOnExpressions = join.getOnExpressions();
+ List onExpressions = new LinkedList<>();
+ onExpressions.add(builderExpression(originOnExpressions.iterator().next(), fromTable));
+ join.setOnExpressions(onExpressions);
+ }
+ }
+
+ /**
+ * 处理条件
+ */
+ protected Expression builderExpression(Expression currentExpression, Table table) {
+ EqualsTo equalsTo = new EqualsTo();
+ equalsTo.setLeftExpression(this.getAliasColumn(table));
+ equalsTo.setRightExpression(getTenantId());
+ if (currentExpression == null) {
+ return equalsTo;
+ }
+ if (currentExpression instanceof OrExpression) {
+ return new AndExpression(new Parenthesis(currentExpression), equalsTo);
+ } else {
+ return new AndExpression(currentExpression, equalsTo);
+ }
+ }
+
+ /**
+ * 租户字段别名设置
+ * tenantId 或 tableAlias.tenantId
+ *
+ * @param table 表对象
+ * @return 字段
+ */
+ protected Column getAliasColumn(Table table) {
+ StringBuilder column = new StringBuilder();
+ if (table.getAlias() != null) {
+ column.append(table.getAlias().getName()).append(StringPool.DOT);
+ }
+ column.append(getTenantIdColumn());
+ return new Column(column.toString());
+ }
+
+// @Override
+// public void setProperties(Properties properties) {
+// PropertyMapper.newInstance(properties).whenNotBlank("tenantLineHandler",
+// ClassUtils::newInstance, this::setTenantLineHandler);
+// }
+
+ // TODO 芋艿:未实现
+
+ private boolean ignoreTable(String tableName) {
+ return false;
+ }
+
+ private String getTenantIdColumn() {
+ return "dept_id";
+ }
+
+ private Expression getTenantId() {
+ return new LongValue(1L);
+ }
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datascope/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datascope/core/package-info.java
new file mode 100644
index 000000000..9881cc057
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datascope/core/package-info.java
@@ -0,0 +1 @@
+package cn.iocoder.yudao.framework.datascope.core;
diff --git a/yudao-framework/yudao-spring-boot-starter-datascope/src/main/java/cn/iocoder/yudao/framework/datascope/package-info.java b/yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datascope/package-info.java
similarity index 100%
rename from yudao-framework/yudao-spring-boot-starter-datascope/src/main/java/cn/iocoder/yudao/framework/datascope/package-info.java
rename to yudao-framework/yudao-spring-boot-starter-data-permission/src/main/java/cn/iocoder/yudao/framework/datascope/package-info.java
diff --git a/yudao-framework/yudao-spring-boot-starter-data-permission/src/test/java/cn/iocoder/yudao/framework/datascope/core/interceptor/DataPermissionInterceptorTest.java b/yudao-framework/yudao-spring-boot-starter-data-permission/src/test/java/cn/iocoder/yudao/framework/datascope/core/interceptor/DataPermissionInterceptorTest.java
new file mode 100644
index 000000000..19fdbf013
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-data-permission/src/test/java/cn/iocoder/yudao/framework/datascope/core/interceptor/DataPermissionInterceptorTest.java
@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.framework.datascope.core.interceptor;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DataPermissionInterceptorTest {
+
+ private final DataPermissionInterceptor interceptor = new DataPermissionInterceptor();
+
+ @Test
+ void selectSingle() {
+ // 单表
+ assertSql("select * from entity where id = ?",
+ "SELECT * FROM entity WHERE id = ? AND tenant_id = 1");
+
+ assertSql("select * from entity where id = ? or name = ?",
+ "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1");
+
+ assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)",
+ "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1");
+
+ /* not */
+ assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)",
+ "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND tenant_id = 1");
+ }
+
+ private void assertSql(String sql, String targetSql) {
+ assertThat(interceptor.parserSingle(sql, null)).isEqualTo(targetSql);
+ }
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
index 4335577d7..88d6e86ab 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -33,7 +33,7 @@ public interface BaseMapperX extends BaseMapper {
}
default Integer selectCount(String field, Object value) {
- return selectCount(new QueryWrapper().eq(field, value));
+ return selectCount(new QueryWrapper().eq(field, value)).intValue();
}
default List selectList() {