From 235715502278c0e6769f4de278598902b17d1754 Mon Sep 17 00:00:00 2001 From: xingtanzjr Date: Wed, 10 May 2017 18:14:40 +0800 Subject: [PATCH] add QP --- pom.xml | 6 + .../cn/edu/thu/tsfiledb/auth/dao/AuthDao.java | 284 ++++++++++++++ .../thu/tsfiledb/auth/dao/AuthDaoWrap.java | 350 ++++++++++++++++++ .../edu/thu/tsfiledb/auth/dao/Authorizer.java | 238 ++++++++++++ .../cn/edu/thu/tsfiledb/auth/dao/DBdao.java | 178 +++++++++ .../edu/thu/tsfiledb/auth/dao/InitTable.java | 37 ++ .../cn/edu/thu/tsfiledb/auth/dao/RoleDao.java | 102 +++++ .../tsfiledb/auth/dao/RolePermissionDao.java | 98 +++++ .../cn/edu/thu/tsfiledb/auth/dao/UserDao.java | 115 ++++++ .../tsfiledb/auth/dao/UserPermissionDao.java | 98 +++++ .../thu/tsfiledb/auth/dao/UserRoleRelDao.java | 116 ++++++ .../tsfiledb/auth/model/AuthException.java | 28 ++ .../thu/tsfiledb/auth/model/DBContext.java | 16 + .../thu/tsfiledb/auth/model/Permission.java | 15 + .../cn/edu/thu/tsfiledb/auth/model/Role.java | 57 +++ .../tsfiledb/auth/model/RolePermission.java | 96 +++++ .../cn/edu/thu/tsfiledb/auth/model/User.java | 109 ++++++ .../tsfiledb/auth/model/UserPermission.java | 98 +++++ .../thu/tsfiledb/auth/model/UserRoleRel.java | 65 ++++ .../engine/exception/LRUManagerException.java | 4 +- .../engine/filenode/FileNodeProcessor.java | 8 +- .../engine/filenode/OverflowQueryEngine.java | 17 - .../thu/tsfiledb/qp/constant/SQLConstant.java | 155 ++++++++ .../qp/exception/ErrorQueryOpException.java | 21 ++ .../exception/IllegalASTFormatException.java | 10 + .../qp/exception/QueryProcessorException.java | 17 + .../qp/exception/TSTransformException.java | 20 + .../operator/BasicOperatorException.java | 20 + .../operator/DeleteOperatorException.java | 20 + .../operator/FilterOperatorException.java | 20 + .../operator/InsertOperatorException.java | 20 + .../logical/operator/ParseLeafException.java | 10 + .../logical/operator/ParseTimeException.java | 10 + .../operator/QpSelectFromException.java | 12 + .../logical/operator/QpWhereException.java | 12 + .../operator/QueryOperatorException.java | 20 + .../operator/SeriesNotExistException.java | 10 + .../logical/operator/SetClauseException.java | 12 + .../operator/UpdateOperatorException.java | 20 + .../logical/operator/ValueParseException.java | 12 + .../optimize/DNFOptimizeException.java | 12 + .../optimize/LogicalOptimizeException.java | 13 + .../optimize/MergeFilterException.java | 12 + .../logical/optimize/PathConcatException.java | 12 + .../logical/optimize/RemoveNotException.java | 16 + .../physical/plan/NamespacePlanException.java | 20 + .../physical/plan/PhysicalPlanException.java | 13 + .../tsfiledb/qp/exec/BasicOperatorType.java | 86 +++++ .../edu/thu/tsfiledb/qp/exec/FilterType.java | 32 ++ .../qp/exec/QueryProcessExecutor.java | 238 ++++++++++++ .../qp/exec/impl/OverflowQPExecutor.java | 162 ++++++++ .../qp/logical/operator/Operator.java | 51 +++ .../qp/logical/operator/RootOperator.java | 29 ++ .../operator/author/AuthorOperator.java | 95 +++++ .../operator/crud/BasicFunctionOperator.java | 166 +++++++++ .../logical/operator/crud/DeleteOperator.java | 84 +++++ .../logical/operator/crud/FilterOperator.java | 262 +++++++++++++ .../logical/operator/crud/FromOperator.java | 60 +++ .../operator/crud/FunctionOperator.java | 54 +++ .../operator/crud/GroupByOperator.java | 19 + .../logical/operator/crud/InsertOperator.java | 56 +++ .../operator/crud/MultiInsertOperator.java | 67 ++++ .../logical/operator/crud/QueryOperator.java | 137 +++++++ .../qp/logical/operator/crud/SFWOperator.java | 101 +++++ .../logical/operator/crud/SelectOperator.java | 49 +++ .../logical/operator/crud/UpdateOperator.java | 119 ++++++ .../operator/load/LoadDataOperator.java | 40 ++ .../operator/metadata/MetadataOperator.java | 76 ++++ .../operator/metadata/PropertyOperator.java | 57 +++ .../logical/operator/sys/FlushOperator.java | 21 ++ .../logical/operator/sys/MergeOperator.java | 21 ++ .../optimizer/ConcatPathOptimizer.java | 138 +++++++ .../logical/optimizer/ILogicalOptimizer.java | 21 ++ .../optimizer/NoneLogicalOptimizer.java | 18 + .../optimizer/filter/DNFFilterOptimizer.java | 145 ++++++++ .../optimizer/filter/IFilterOptimizer.java | 16 + .../filter/MergeSingleFilterOptimizer.java | 134 +++++++ .../optimizer/filter/RemoveNotOptimizer.java | 91 +++++ .../optimizer/IPhysicalOptimizer.java | 15 + .../optimizer/NonePhycicalOptimizer.java | 20 + .../optimizer/UnionTableOptimizer.java | 107 ++++++ .../tsfiledb/qp/physical/plan/AuthorPlan.java | 140 +++++++ .../tsfiledb/qp/physical/plan/DeletePlan.java | 59 +++ .../tsfiledb/qp/physical/plan/InsertPlan.java | 81 ++++ .../qp/physical/plan/LoadDataPlan.java | 40 ++ .../qp/physical/plan/MultiInsertPlan.java | 99 +++++ .../qp/physical/plan/PhysicalPlan.java | 63 ++++ .../tsfiledb/qp/physical/plan/UpdatePlan.java | 80 ++++ .../physical/plan/metadata/MetadataPlan.java | 132 +++++++ .../physical/plan/metadata/PropertyPlan.java | 94 +++++ .../plan/query/MergeQuerySetIterator.java | 119 ++++++ .../plan/query/MergeQuerySetPlan.java | 88 +++++ .../plan/query/OutputQueryDataSet.java | 57 +++ .../physical/plan/query/SeriesSelectPlan.java | 341 +++++++++++++++++ .../thu/tsfiledb/utils/FileSchemaUtil.java | 47 +++ .../edu/thu/tsfiledb/utils/LoadDataUtils.java | 209 +++++++++++ 96 files changed, 7071 insertions(+), 19 deletions(-) create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDao.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDaoWrap.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/Authorizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/DBdao.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/InitTable.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/RoleDao.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/RolePermissionDao.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserDao.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserPermissionDao.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserRoleRelDao.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/model/AuthException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/model/DBContext.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/model/Permission.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/model/Role.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/model/RolePermission.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/model/User.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/model/UserPermission.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/auth/model/UserRoleRel.java delete mode 100644 src/main/java/cn/edu/thu/tsfiledb/engine/filenode/OverflowQueryEngine.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/constant/SQLConstant.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/ErrorQueryOpException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/IllegalASTFormatException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/QueryProcessorException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/TSTransformException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/BasicOperatorException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/DeleteOperatorException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/FilterOperatorException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/InsertOperatorException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ParseLeafException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ParseTimeException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QpSelectFromException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QpWhereException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QueryOperatorException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/SeriesNotExistException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/SetClauseException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/UpdateOperatorException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ValueParseException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/DNFOptimizeException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/LogicalOptimizeException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/MergeFilterException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/PathConcatException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/RemoveNotException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/physical/plan/NamespacePlanException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exception/physical/plan/PhysicalPlanException.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exec/BasicOperatorType.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exec/FilterType.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exec/QueryProcessExecutor.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/exec/impl/OverflowQPExecutor.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/Operator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/RootOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/author/AuthorOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/BasicFunctionOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/DeleteOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FilterOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FromOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FunctionOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/GroupByOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/InsertOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/MultiInsertOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/QueryOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/SFWOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/SelectOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/UpdateOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/load/LoadDataOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/metadata/MetadataOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/metadata/PropertyOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/sys/FlushOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/sys/MergeOperator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/ConcatPathOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/ILogicalOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/NoneLogicalOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/DNFFilterOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/IFilterOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/MergeSingleFilterOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/RemoveNotOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/IPhysicalOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/NonePhycicalOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/UnionTableOptimizer.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/AuthorPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/DeletePlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/InsertPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/LoadDataPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/MultiInsertPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/PhysicalPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/UpdatePlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/metadata/MetadataPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/metadata/PropertyPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/MergeQuerySetIterator.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/MergeQuerySetPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/OutputQueryDataSet.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/SeriesSelectPlan.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/utils/FileSchemaUtil.java create mode 100644 src/main/java/cn/edu/thu/tsfiledb/utils/LoadDataUtils.java diff --git a/pom.xml b/pom.xml index d393b98fd5b..8157f5d07e5 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,12 @@ ${hadoop.version} + + org.apache.derby + derby + 10.12.1.1 + + diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDao.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDao.java new file mode 100644 index 00000000000..1dd0eb2a4f3 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDao.java @@ -0,0 +1,284 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import cn.edu.thu.tsfiledb.auth.model.Role; +import cn.edu.thu.tsfiledb.auth.model.RolePermission; +import cn.edu.thu.tsfiledb.auth.model.User; +import cn.edu.thu.tsfiledb.auth.model.UserPermission; +import cn.edu.thu.tsfiledb.auth.model.UserRoleRel; + +/** + * @author liukun + * + */ +public class AuthDao { + + /** + * if the user don't exist in the db, return true else return false + * + * @param statement + * @param user + * @return + */ + public boolean addUser(Statement statement, User user) { + UserDao dao = new UserDao(); + boolean state = false; + // Check the user exist or not + if (dao.getUser(statement, user.getUserName()) == null) { + dao.createUser(statement, user); + state = true; + } + return state; + } + + /** + * if the role isn't exist in the db, will return true else return false + * + * @param statement + * @param role + * @return + */ + public boolean addRole(Statement statement, Role role) { + RoleDao dao = new RoleDao(); + boolean state = false; + // check the user exist or not + if (dao.getRole(statement, role.getRoleName()) == null) { + dao.createRole(statement, role); + state = true; + } + return state; + } + + /** + * the user and role is exist, the relation is not exist, will return true + * else return false + * + * @param statement + * @param userName + * @param roleName + * @return + */ + public boolean addUserRoleRel(Statement statement, String userName, String roleName) { + UserDao userDao = new UserDao(); + RoleDao roleDao = new RoleDao(); + UserRoleRelDao userRoleRelDao = new UserRoleRelDao(); + int userId; + int roleId; + User user = null; + Role role = null; + boolean state = false; + if ((user = userDao.getUser(statement, userName)) != null) { + if ((role = roleDao.getRole(statement, roleName)) != null) { + userId = user.getId(); + roleId = role.getId(); + UserRoleRel userRoleRel = new UserRoleRel(userId, roleId); + + if (userRoleRelDao.getUserRoleRel(statement, userRoleRel) == null) { + state = true; + userRoleRelDao.createUserRoleRel(statement, userRoleRel); + } + } + } + return state; + } + + public boolean addUserPermission(Statement statement, String userName, String nodeName, int permissionId) { + UserDao userDao = new UserDao(); + UserPermissionDao userPermissionDao = new UserPermissionDao(); + boolean state = false; + User user = null; + if ((user = userDao.getUser(statement, userName)) != null) { + int userId = user.getId(); + UserPermission userPermission = new UserPermission(userId, nodeName, permissionId); + if (userPermissionDao.getUserPermission(statement, userPermission) == null) { + state = true; + userPermissionDao.createUserPermission(statement, userPermission); + } + } + return state; + } + + public boolean addRolePermission(Statement statement, String roleName, String nodeName, int permissionId) { + RoleDao roleDao = new RoleDao(); + RolePermissionDao rolePermissionDao = new RolePermissionDao(); + boolean state = false; + Role role = null; + if ((role = roleDao.getRole(statement, roleName)) != null) { + int roleId = role.getId(); + RolePermission rolePermission = new RolePermission(roleId, nodeName, permissionId); + if (rolePermissionDao.getRolePermission(statement, rolePermission) == null) { + state = true; + rolePermissionDao.createRolePermission(statement, rolePermission); + } + } + return state; + } + + public boolean deleteUser(Statement statement, String userName) { + UserDao userDao = new UserDao(); + boolean state = false; + if (userDao.deleteUser(statement, userName) > 0) { + state = true; + } + return state; + } + + public boolean deleteRole(Statement statement, String roleName) { + RoleDao roleDao = new RoleDao(); + boolean state = false; + if (roleDao.deleteRole(statement, roleName) > 0) { + state = true; + } + return state; + } + + public boolean deleteUserRoleRel(Statement statement, String userName, String roleName) { + UserRoleRelDao userRoleRelDao = new UserRoleRelDao(); + UserDao userDao = new UserDao(); + RoleDao roleDao = new RoleDao(); + int userId; + int roleId; + User user = null; + Role role = null; + boolean state = false; + + if ((user = userDao.getUser(statement, userName)) != null + && (role = roleDao.getRole(statement, roleName)) != null) { + userId = user.getId(); + roleId = role.getId(); + UserRoleRel userRoleRel = new UserRoleRel(userId, roleId); + if (userRoleRelDao.deleteUserRoleRel(statement, userRoleRel) > 0) { + state = true; + } + } + return state; + } + + public boolean deleteUserPermission(Statement statement, String userName, String nodeName, int permissionId) { + UserDao userDao = new UserDao(); + UserPermissionDao userPermissionDao = new UserPermissionDao(); + int userId; + User user = null; + boolean state = false; + if ((user = userDao.getUser(statement, userName)) != null) { + userId = user.getId(); + UserPermission userPermission = new UserPermission(userId, nodeName, permissionId); + if (userPermissionDao.deleteUserPermission(statement, userPermission) > 0) { + state = true; + } + } + return state; + } + + public boolean deleteRolePermission(Statement statement, String roleName, String nodeName, int permissionId) { + RoleDao roleDao = new RoleDao(); + RolePermissionDao rolePermissionDao = new RolePermissionDao(); + Role role = null; + int roleId; + boolean state = false; + if ((role = roleDao.getRole(statement, roleName)) != null) { + roleId = role.getId(); + RolePermission rolePermission = new RolePermission(roleId, nodeName, permissionId); + if (rolePermissionDao.deleteRolePermission(statement, rolePermission) > 0) { + state = true; + } + } + return state; + } + + // 如果username或者nodename不存在怎么办? + public List getUsers(Statement statement) { + UserDao userDao = new UserDao(); + List users = userDao.getUsers(statement); + return users; + } + + public List getRoles(Statement statement) { + RoleDao roleDao = new RoleDao(); + List roles = roleDao.getRoles(statement); + return roles; + } + + public List getAllUserRoleRel(Statement statement) { + UserRoleRelDao userRoleRelDao = new UserRoleRelDao(); + List userRoleRels = userRoleRelDao.getUserRoleRels(statement); + return userRoleRels; + } + + /* + * 返回值的问题 + */ + public List getRolesByUser(Statement statement, String userName) { + UserDao userDao = new UserDao(); + UserRoleRelDao userRoleRelDao = new UserRoleRelDao(); + RoleDao roleDao = new RoleDao(); + // 当 user不存在的情况下是返回 size = 0,还是 null + ArrayList roles = new ArrayList<>(); + User user = userDao.getUser(statement, userName); + if (user != null) { + int userId = user.getId(); + List userRoleRels = userRoleRelDao.getUserRoleRelByUser(statement, userId); + for (UserRoleRel userRoleRel : userRoleRels) { + int roleId = userRoleRel.getRoleId(); + Role role = roleDao.getRole(statement, roleId); + roles.add(role); + } + } + return roles; + } + + /* + * 返回值的问题 + */ + public List getUserPermission(Statement statement, String userName, String nodeName) { + UserDao userDao = new UserDao(); + UserPermissionDao userPermissionDao = new UserPermissionDao(); + List userPermissions = new ArrayList<>(); + // 当user 不存在的时候 是返回size = 0,还是null + User user = userDao.getUser(statement, userName); + if (user != null) { + userPermissions = userPermissionDao.getUserPermissionByUserAndNodeName(statement, user.getId(), nodeName); + } + // 返回值可能是null还是 没有结果 size = 0; + return userPermissions; + } + + public List getRolePermission(Statement statement, String roleName, String nodeName) { + RoleDao roleDao = new RoleDao(); + RolePermissionDao rolePermissionDao = new RolePermissionDao(); + List rolePermissions = new ArrayList<>(); + Role role = roleDao.getRole(statement, roleName); + if (role != null) { + rolePermissions = rolePermissionDao.getRolePermissionByRoleAndNodeName(statement, role.getId(), nodeName); + } + return rolePermissions; + } + + /* + * All user's permission: userPermission and rolePermission + */ + public Set getAllUserPermission(Statement statement, String userName, String nodeName) { + // permission set + Set permissionSet = new HashSet<>(); + // userpermission + List userPermissions = getUserPermission(statement, userName, nodeName); + for (UserPermission userPermission : userPermissions) { + permissionSet.add(userPermission.getPermissionId()); + } + // rolepermission + List roles = getRolesByUser(statement, userName); + for (Role role : roles) { + List rolePermissions = getRolePermission(statement, role.getRoleName(), nodeName); + // operation add the permission into the set + for (RolePermission rolePermission : rolePermissions) { + permissionSet.add(rolePermission.getPermissionId()); + } + } + return permissionSet; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDaoWrap.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDaoWrap.java new file mode 100644 index 00000000000..a7ea64342db --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDaoWrap.java @@ -0,0 +1,350 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import cn.edu.thu.tsfiledb.auth.model.*; + +/** + * @author liukun + */ +public class AuthDaoWrap { + + // Must init the DBdao before use this class + private Statement statement = DBdao.getStatement(); + + + public boolean addUser(User user) { + UserDao dao = new UserDao(); + boolean state = false; + // Check the user exist or not + if (dao.getUser(statement, user.getUserName()) == null) { + dao.createUser(statement, user); + state = true; + } + return state; + } + + + public boolean addRole(Role role) { + RoleDao dao = new RoleDao(); + boolean state = false; + // check the user exist or not + if (dao.getRole(statement, role.getRoleName()) == null) { + dao.createRole(statement, role); + state = true; + } + return state; + } + + + public boolean addUserRoleRel(String userName, String roleName) throws AuthException { + UserDao userDao = new UserDao(); + RoleDao roleDao = new RoleDao(); + UserRoleRelDao userRoleRelDao = new UserRoleRelDao(); + int userId; + int roleId; + User user = null; + Role role = null; + boolean state = false; + if ((user = userDao.getUser(statement, userName)) != null) { + if ((role = roleDao.getRole(statement, roleName)) != null) { + userId = user.getId(); + roleId = role.getId(); + UserRoleRel userRoleRel = new UserRoleRel(userId, roleId); + + if (userRoleRelDao.getUserRoleRel(statement, userRoleRel) == null) { + state = true; + userRoleRelDao.createUserRoleRel(statement, userRoleRel); + } else { + throw new AuthException(String.format("The user of %s already has the role of %s", userName, role.getRoleName())); + } + } else { + throw new AuthException("The role is not exist"); + } + } else { + throw new AuthException("The user is not exist"); + } + return state; + } + + public boolean addUserPermission(String userName, String nodeName, int permissionId) throws AuthException { + UserDao userDao = new UserDao(); + UserPermissionDao userPermissionDao = new UserPermissionDao(); + boolean state = false; + User user = null; + if ((user = userDao.getUser(statement, userName)) != null) { + int userId = user.getId(); + UserPermission userPermission = new UserPermission(userId, nodeName, permissionId); + if (userPermissionDao.getUserPermission(statement, userPermission) == null) { + state = true; + userPermissionDao.createUserPermission(statement, userPermission); + } else { + throw new AuthException("The permission is exist"); + } + } else { + throw new AuthException("The user is not exist"); + } + return state; + } + + public boolean addRolePermission(String roleName, String nodeName, int permissionId) throws AuthException { + RoleDao roleDao = new RoleDao(); + RolePermissionDao rolePermissionDao = new RolePermissionDao(); + boolean state = false; + Role role = null; + if ((role = roleDao.getRole(statement, roleName)) != null) { + int roleId = role.getId(); + RolePermission rolePermission = new RolePermission(roleId, nodeName, permissionId); + if (rolePermissionDao.getRolePermission(statement, rolePermission) == null) { + state = true; + rolePermissionDao.createRolePermission(statement, rolePermission); + } else { + throw new AuthException("The permission is exist"); + } + } else { + throw new AuthException("The role is not exist"); + } + return state; + } + + public boolean deleteUser(String userName) { + UserDao userDao = new UserDao(); + boolean state = false; + if (userDao.deleteUser(statement, userName) > 0) { + state = true; + } + return state; + } + + public boolean deleteRole(String roleName) { + RoleDao roleDao = new RoleDao(); + boolean state = false; + if (roleDao.deleteRole(statement, roleName) > 0) { + state = true; + } + return state; + } + + public boolean deleteUserRoleRel(String userName, String roleName) throws AuthException { + UserRoleRelDao userRoleRelDao = new UserRoleRelDao(); + UserDao userDao = new UserDao(); + RoleDao roleDao = new RoleDao(); + int userId; + int roleId; + User user = null; + Role role = null; + boolean state = false; + + if ((user = userDao.getUser(statement, userName)) != null) { + if ((role = roleDao.getRole(statement, roleName)) != null) { + userId = user.getId(); + roleId = role.getId(); + UserRoleRel userRoleRel = new UserRoleRel(userId, roleId); + if (userRoleRelDao.deleteUserRoleRel(statement, userRoleRel) > 0) { + state = true; + } else { + throw new AuthException(String.format("The user of %s does not have the role of %s"), userName, role.getRoleName()); + } + } else { + throw new AuthException("The role is not exist"); + } + } else { + throw new AuthException("The user is not exist"); + } + return state; + } + + public boolean deleteUserPermission(String userName, String nodeName, int permissionId) throws AuthException { + UserDao userDao = new UserDao(); + UserPermissionDao userPermissionDao = new UserPermissionDao(); + int userId; + User user = null; + boolean state = false; + if ((user = userDao.getUser(statement, userName)) != null) { + userId = user.getId(); + UserPermission userPermission = new UserPermission(userId, nodeName, permissionId); + if (userPermissionDao.deleteUserPermission(statement, userPermission) > 0) { + state = true; + } else { + throw new AuthException("The permission is not exist"); + } + } else { + throw new AuthException("The user is not exist"); + } + return state; + } + + public boolean deleteRolePermission(String roleName, String nodeName, int permissionId) throws AuthException { + RoleDao roleDao = new RoleDao(); + RolePermissionDao rolePermissionDao = new RolePermissionDao(); + Role role = null; + int roleId; + boolean state = false; + if ((role = roleDao.getRole(statement, roleName)) != null) { + roleId = role.getId(); + RolePermission rolePermission = new RolePermission(roleId, nodeName, permissionId); + if (rolePermissionDao.deleteRolePermission(statement, rolePermission) > 0) { + state = true; + } else { + throw new AuthException("The permission is not exist"); + } + } else { + throw new AuthException("The role is not exist"); + } + return state; + } + + public User getUser(String userName, String password) { + UserDao userDao = new UserDao(); + User user = null; + user = userDao.getUser(statement, userName, password); + return user; + } + + public User getUser(String userName) { + UserDao userDao = new UserDao(); + User user = null; + user = userDao.getUser(statement, userName); + return user; + } + + // 如果username或者nodename不存在怎么办? + public List getUsers() { + UserDao userDao = new UserDao(); + List users = userDao.getUsers(statement); + return users; + } + + public List getRoles() { + RoleDao roleDao = new RoleDao(); + List roles = roleDao.getRoles(statement); + return roles; + } + + public List getAllUserRoleRel() { + UserRoleRelDao userRoleRelDao = new UserRoleRelDao(); + List userRoleRels = userRoleRelDao.getUserRoleRels(statement); + return userRoleRels; + } + + /* + * 返回值的问题 + */ + public List getRolesByUser(String userName) { + UserDao userDao = new UserDao(); + UserRoleRelDao userRoleRelDao = new UserRoleRelDao(); + RoleDao roleDao = new RoleDao(); + // 当 user不存在的情况下是返回 size = 0,还是 null + ArrayList roles = new ArrayList<>(); + User user = userDao.getUser(statement, userName); + if (user != null) { + int userId = user.getId(); + List userRoleRels = userRoleRelDao.getUserRoleRelByUser(statement, userId); + for (UserRoleRel userRoleRel : userRoleRels) { + int roleId = userRoleRel.getRoleId(); + Role role = roleDao.getRole(statement, roleId); + roles.add(role); + } + } + return roles; + } + + public UserPermission getUserPermission(String userName, String nodeName, int permissionId) { + UserPermission userPermission = null; + UserDao userDao = new UserDao(); + User user = userDao.getUser(statement, userName); + if (user != null) { + int userId = user.getId(); + userPermission = new UserPermission(userId, nodeName, permissionId); + UserPermissionDao userPermissionDao = new UserPermissionDao(); + // userPermission will be null + userPermission = userPermissionDao.getUserPermission(statement, userPermission); + } + return userPermission; + } + + /* + * 返回值的问题 + */ + public List getUserPermissions(String userName, String nodeName) throws AuthException { + UserDao userDao = new UserDao(); + UserPermissionDao userPermissionDao = new UserPermissionDao(); + List userPermissions = new ArrayList<>(); + // 当user 不存在的时候 是返回size = 0,还是null + User user = userDao.getUser(statement, userName); + if (user != null) { + userPermissions = userPermissionDao.getUserPermissionByUserAndNodeName(statement, user.getId(), nodeName); + } else { + throw new AuthException("The user is not exist"); + } + // 返回值可能是null还是 没有结果 size = 0; + return userPermissions; + } + + public List getRolePermissions(String roleName, String nodeName) { + RoleDao roleDao = new RoleDao(); + RolePermissionDao rolePermissionDao = new RolePermissionDao(); + List rolePermissions = new ArrayList<>(); + Role role = roleDao.getRole(statement, roleName); + if (role != null) { + rolePermissions = rolePermissionDao.getRolePermissionByRoleAndNodeName(statement, role.getId(), nodeName); + } + return rolePermissions; + } + + /* + * All user's permission: userPermission and rolePermission + */ + public Set getAllUserPermissions(String userName, String nodeName) throws AuthException { + // permission set + Set permissionSet = new HashSet<>(); + // userpermission + List userPermissions = getUserPermissions(userName, nodeName); + for (UserPermission userPermission : userPermissions) { + permissionSet.add(userPermission.getPermissionId()); + } + // rolepermission + List roles = getRolesByUser(userName); + for (Role role : roles) { + List rolePermissions = getRolePermissions(role.getRoleName(), nodeName); + // operation add the permission into the set + for (RolePermission rolePermission : rolePermissions) { + permissionSet.add(rolePermission.getPermissionId()); + } + } + return permissionSet; + } + + public boolean updateUserPassword(String userName, String newPassword) { + boolean state = false; + UserDao userDao = new UserDao(); + int change = userDao.updateUserPassword(statement, userName, newPassword); + if (change > 0) { + state = true; + } + return state; + } + + public boolean checkUserPermission(String userName, String nodeName, int permissionId) { + boolean state = false; + UserPermission userPermission = this.getUserPermission(userName, nodeName, permissionId); + if (userPermission != null) { + state = true; + } + return state; + } + + // add the method without the authdao + public boolean checkUser(String userName, String password) { + boolean state = false; + User user = this.getUser(userName, password); + if (user != null) { + state = true; + } + return state; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/Authorizer.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/Authorizer.java new file mode 100644 index 00000000000..65bdcc9fa13 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/Authorizer.java @@ -0,0 +1,238 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.util.Set; + +import cn.edu.thu.tsfiledb.auth.model.AuthException; +import cn.edu.thu.tsfiledb.auth.model.Role; +import cn.edu.thu.tsfiledb.auth.model.User; + +/** + * @author liukun + */ +public class Authorizer { + + private static AuthDaoWrap authDaoWrap = new AuthDaoWrap(); + + /** + * Check the information for login + * + * @param username + * @param password + * @return + * @throws AuthException + */ + public static synchronized boolean login(String username, String password) throws AuthException { + + boolean state = false; + state = authDaoWrap.checkUser(username, password); + if (state == false) { + throw new AuthException("The username or the password is not correct"); + } + return state; + } + + /** + * Add user + * + * @param username is not null or empty + * @param password is not null or empty + * @return true: add user successfully, false: add user unsuccessfully + * @throws AuthException + */ + public static boolean createUser(String username, String password) throws AuthException { + boolean state = false; + User user = new User(username, password); + if (username == null || password == null || "".equals(username) || "".equals(password)) { + throw new AuthException("Username or password can't be empty"); + } + state = authDaoWrap.addUser(user); + if (state == false) { + throw new AuthException("The user is exist"); + } + return state; + } + + /** + * Delete user + * + * @param username + * @return true: delete user successfully, false: delete user unsuccessfully + * @throws AuthException + */ + public static boolean deleteUser(String username) throws AuthException { + boolean state = false; + state = authDaoWrap.deleteUser(username); + if (state == false) { + throw new AuthException("The user is not exist"); + } + return state; + } + + /** + * Add permission to user + * + * @param username + * @param nodeName + * @param permissionId + * @return true: add permission successfully, false: add permission unsuccessfully + * @throws AuthException + */ + public static boolean addPmsToUser(String username, String nodeName, int permissionId) throws AuthException { + boolean state = false; + state = authDaoWrap.addUserPermission(username, nodeName, permissionId); + return state; + } + + /** + * Delete permission from user + * + * @param userName + * @param nodeName + * @param permissionId + * @return true: delete permission from user successfully, false: delete permission from user unsuccessfully + * @throws AuthException + */ + public static boolean removePmsFromUser(String userName, String nodeName, int permissionId) throws AuthException { + boolean state = false; + state = authDaoWrap.deleteUserPermission(userName, nodeName, permissionId); + return state; + } + + /** + * Add role + * + * @param roleName + * @return true: add role successfully, false: add role unsuccessfully + * @throws Exception + */ + public static boolean createRole(String roleName) throws AuthException { + boolean state = false; + Role role = new Role(roleName); + state = authDaoWrap.addRole(role); + if (state == false) { + throw new AuthException("The role is exist"); + } + return state; + } + + /** + * Delete role + * + * @param roleName + * @return true: delete role successfully, false: delete role unsuccessfully + * @throws Exception + */ + public static boolean deleteRole(String roleName) throws AuthException { + boolean state = false; + state = authDaoWrap.deleteRole(roleName); + if (state == false) { + throw new AuthException("The role is not exist"); + } + return state; + } + + /** + * Add permission to role + * + * @param roleName + * @param nodeName + * @param permissionId + * @return true: add permission to role successfully, false: add permission to role unsuccessfully + * @throws AuthException + */ + public static boolean addPmsToRole(String roleName, String nodeName, int permissionId) throws AuthException { + boolean state = false; + state = authDaoWrap.addRolePermission(roleName, nodeName, permissionId); + return state; + } + + /** + * Delete permission from role + * + * @param roleName + * @param nodeName + * @param permissionId + * @return true: delete permission from role successfully, false: delete permission from role unsuccessfully + * @throws AuthException + */ + public static boolean removePmsFromRole(String roleName, String nodeName, int permissionId) throws AuthException { + boolean state = false; + state = authDaoWrap.deleteRolePermission(roleName, nodeName, permissionId); + return state; + } + + /** + * Add role to user + * + * @param roleName + * @param username + * @return true: add role to user successfully, false: add role to user unsuccessfully + * @throws AuthException + */ + public static boolean grantRoleToUser(String roleName, String username) throws AuthException { + boolean state = false; + state = authDaoWrap.addUserRoleRel(username, roleName); + return state; + } + + /** + * Delete role from user + * + * @param roleName + * @param username + * @return true: delete role from user successfully, false: delete role from user unsuccessfully + * @throws AuthException + */ + public static boolean revokeRoleFromUser(String roleName, String username) throws AuthException { + boolean state = false; + state = authDaoWrap.deleteUserRoleRel(username, roleName); + return state; + } + + /** + * Get the all permission of the user + * + * @param username + * @param nodeName + * @return + * @throws AuthException + */ + public static Set getPermission(String username, String nodeName) throws AuthException { + Set permissionSets = null; + permissionSets = authDaoWrap.getAllUserPermissions(username, nodeName); + return permissionSets; + } + + /** + * Modify the password + * + * @param username + * @param oldPassword + * @param newPassword + * @return true: update the password successfully, false: update the password unsuccessfully + * @throws AuthException + */ + public static boolean updateUserPassword(String username, String newPassword) throws AuthException { + boolean state = false; + state = authDaoWrap.updateUserPassword(username, newPassword); + if (state == false) { + throw new AuthException("The username or the password is not correct"); + } + return state; + } + + /** + * Check the permission belong to the user + * + * @param username + * @param nodeName + * @param permissionId + * @return true: the user has this permission, false: the user does not have the permission + */ + public static boolean checkUserPermission(String username, String nodeName, int permissionId) { + boolean state = false; + state = authDaoWrap.checkUserPermission(username, nodeName, permissionId); + return state; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/DBdao.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/DBdao.java new file mode 100644 index 00000000000..e2425ae7662 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/DBdao.java @@ -0,0 +1,178 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.io.File; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import cn.edu.thu.tsfile.common.conf.TSFileDescriptor; + + +/** + * @author liukun + * + */ +public class DBdao { + + private String derbyEmbeddedDriver = "org.apache.derby.jdbc.EmbeddedDriver"; + private String protocal = "jdbc:derby:"; + private String DBName; + private String createOrNot = ";create=true"; + private String shutdown = ";shutdown=True"; + + private static Connection connection = null; + private static Statement statement = null; + private PreparedStatement preparedStatement = null; + + /** + * @param dBName + */ + public DBdao(String dBName) { + String path = TSFileDescriptor.getInstance().getConfig().derbyHome + File.separator + dBName; + DBName = path; + } + + public DBdao() { + this("derby-tsfile-db"); + } + + private void initDriver() { + try { + Class.forName(derbyEmbeddedDriver).newInstance(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + private void connection() { + String url = protocal + DBName + createOrNot; + try { + connection = DriverManager.getConnection(url); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void closeConnection() { + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } else { + try { + throw new Exception("The connection is null"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void statement() { + try { + statement = connection.createStatement(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void closeStatement() { + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } else { + try { + throw new Exception("The statement is null"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private boolean checkTableExist() { + boolean state = false; + + try { + DatabaseMetaData metaData = connection.getMetaData(); + ResultSet resultSet; + resultSet = metaData.getTables(null, "APP", "USERTABLE", null); + if (resultSet.next()) { + state = true; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + // create table; + public boolean createOriTable() { + boolean state = false; + try { + statement.executeUpdate(InitTable.createTableSql); + statement.executeUpdate(InitTable.createRoleTableSql); + statement.executeUpdate(InitTable.createUserRoleRelTableSql); + statement.executeUpdate(InitTable.creteUserPermissionTableSql); + statement.executeUpdate(InitTable.createRolePermissionTableSql); + statement.executeUpdate(InitTable.insertIntoUserToTableSql); + state = true; + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public void getPreparedStatement() { + try { + preparedStatement = connection.prepareStatement("test"); + + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void closePreparedStatement() { + + } + + public void open() { + initDriver(); + connection(); + statement(); + if (!checkTableExist()) { + // + createOriTable(); + } + } + + public void close() { + closeStatement(); + closeConnection(); +// try { +// DriverManager.getConnection(protocal + shutdown); +// } catch (SQLException e) { +// e.printStackTrace(); +// } + } + + public static Statement getStatement() { + return statement; + } + + public static Connection getConnection() { + return connection; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/InitTable.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/InitTable.java new file mode 100644 index 00000000000..7fb3cf08b84 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/InitTable.java @@ -0,0 +1,37 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +/** + * @author liukun + * + */ +public class InitTable { + + public static String createTableSql = "create table userTable(" + + "id INT generated always as identity(start with 1,increment by 1) not null primary key," + + "userName VARCHAR(20) not null unique," + "password VARCHAR(20) not null," + + "locked CHAR(1) check (locked='t' or locked='f')," + "validTime VARCHAR(20))"; + + public static String createRoleTableSql = "create table roleTable(" + + "id INT generated always as identity(start with 1, increment by 1) not null primary key," + + "roleName VARCHAR(20) not null unique)"; + + public static String createUserRoleRelTableSql = "create table userRoleRelTable(" + + "id INT generated always as identity(start with 1, increment by 1) ," + "userId INT," + "roleId INT," + + "constraint pk_userrolerel primary key (userId,roleId)," + + "foreign key (userId) references usertable(id) on delete cascade," + + "foreign key (roleId) references roletable(id) on delete cascade)"; + + public static String creteUserPermissionTableSql = "create table userPermissionTable(" + + "id INT generated always as identity(start with 1,increment by 1) ," + "userId INT not null," + + "nodeName VARCHAR(20) not null," + "permissionId INT not null," + + "constraint pk_userpermission primary key (userId,nodeName,permissionId)," + + "foreign key (userId) references usertable(id) on delete cascade)"; + + public static String createRolePermissionTableSql = "create table rolePermissionTable(" + + "id INT generated always as identity(start with 1, increment by 1)," + "roleId INT not null," + + "nodeName VARCHAR(20) not null," + "permissionId INT not null," + + "constraint pk_rolepermission primary key (roleId,nodeName,permissionId)," + + "foreign key (roleId) references roleTable(id) on delete cascade)"; + + public static String insertIntoUserToTableSql = "insert into usertable (username,password) values('root','root')"; +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/RoleDao.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/RoleDao.java new file mode 100644 index 00000000000..7bd91dd5ca2 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/RoleDao.java @@ -0,0 +1,102 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfiledb.auth.model.DBContext; +import cn.edu.thu.tsfiledb.auth.model.Role; + +/** + * @author liukun + * + */ +public class RoleDao { + + public List getRoles(Statement statement) { + ArrayList arrayList = new ArrayList<>(); + String sql = "select * from " + DBContext.roleTable; + + try { + ResultSet resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + Role role = new Role(); + int id = resultSet.getInt(1); + String roleName = resultSet.getString(2); + role.setId(id); + role.setRoleName(roleName); + arrayList.add(role); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return arrayList; + } + + public Role getRole(Statement statement, String roleName) { + String sql = "select * from " + DBContext.roleTable + " where roleName=" + "'" + roleName + "'"; + Role role = null; + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + int id = resultSet.getInt(1); + String name = resultSet.getString(2); + role = new Role(id, name); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + return role; + } + + public Role getRole(Statement statement, int roleId) { + String sql = "select * from " + DBContext.roleTable + " where id=" + roleId; + Role role = null; + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + if (resultSet.next()) { + role = new Role(roleId, resultSet.getString(2)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + return role; + } + + public int deleteRole(Statement statement, String roleName) { + String sql = "delete from " + DBContext.roleTable + " where roleName=" + "'" + roleName + "'"; + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public int createRole(Statement statement, Role role) { + String sql = "insert into " + DBContext.roleTable + " (" + "roleName" + ")" + " values('" + role.getRoleName() + + "')"; + + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public int updateRole(Statement statement) { + String sql = "update " + DBContext.roleTable + " set "; + int state = 0; + + return state; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/RolePermissionDao.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/RolePermissionDao.java new file mode 100644 index 00000000000..22e59496bfb --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/RolePermissionDao.java @@ -0,0 +1,98 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfiledb.auth.model.DBContext; +import cn.edu.thu.tsfiledb.auth.model.RolePermission; + +/** + * @author liukun + * + */ +public class RolePermissionDao { + + public int createRolePermission(Statement statement, RolePermission rolePermission) { + String sql = "insert into " + DBContext.rolePermission + " (roleId,nodeName,permissionId) values" + "(" + + rolePermission.getRoleId() + ",'" + rolePermission.getNodeName() + "'," + + rolePermission.getPermissionId() + ")"; + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public int deleteRolePermission(Statement statement, RolePermission rolePermission) { + String sql = "delete from " + DBContext.rolePermission + " where roleId=" + rolePermission.getRoleId() + " and " + + "nodeName=" + "'" + rolePermission.getNodeName() + "'" + " and " + "permissionId=" + + rolePermission.getPermissionId(); + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public RolePermission getRolePermission(Statement statement, RolePermission rolePermission) { + String sql = "select * from " + DBContext.rolePermission + " where roleId=" + rolePermission.getRoleId() + + " and nodeName='" + rolePermission.getNodeName() + "' and permissionId=" + + rolePermission.getPermissionId(); + RolePermission permission = null; + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + if (resultSet.next()) { + permission = new RolePermission(resultSet.getInt(1), resultSet.getInt(2), resultSet.getString(3), + resultSet.getInt(4)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + return permission; + } + + public List getRolePermissions(Statement statement) { + String sql = "select * from " + DBContext.rolePermission; + List rolePermissions = new ArrayList<>(); + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + RolePermission rolePermission = new RolePermission(resultSet.getInt(1), resultSet.getInt(2), + resultSet.getString(3), resultSet.getInt(4)); + rolePermissions.add(rolePermission); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return rolePermissions; + } + + public List getRolePermissionByRoleAndNodeName(Statement statement, int roleId, String nodeName) { + String sql = "select * from " + DBContext.rolePermission + " where roleId=" + roleId + " and nodeName='" + + nodeName + "'"; + List rolePermissions = new ArrayList<>(); + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + RolePermission rolePermission = new RolePermission(resultSet.getInt(1), resultSet.getInt(2), + resultSet.getString(3), resultSet.getInt(4)); + rolePermissions.add(rolePermission); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return rolePermissions; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserDao.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserDao.java new file mode 100644 index 00000000000..d82e274366e --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserDao.java @@ -0,0 +1,115 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfiledb.auth.model.DBContext; +import cn.edu.thu.tsfiledb.auth.model.User; + +/** + * @author liukun + * + */ +public class UserDao { + + public int createUser(Statement statement, User user) { + + String sql = "insert into " + DBContext.userTable + " (userName,passWord) " + " values ('" + user.getUserName() + + "','" + user.getPassWord() + "')"; + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public int deleteUser(Statement statement, String userName) { + String sql = "delete from " + DBContext.userTable + " where userName=" + "'" + userName + "'"; + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public int updateUserPassword(Statement statement, String userName, String newPassword) { + String sql = "update " + DBContext.userTable + " set password='" + newPassword + "'" + " where username='" + + userName + "'"; + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public List getUsers(Statement statement) { + String sql = "select * from " + DBContext.userTable; + ArrayList arrayList = new ArrayList<>(); + + try { + ResultSet resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + int id = resultSet.getInt(1); + String userName = resultSet.getString(2); + String passWord = resultSet.getString(3); + boolean isLock = resultSet.getBoolean(4); + String validTime = resultSet.getString(5); + User user = new User(id, userName, passWord, isLock, validTime); + arrayList.add(user); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return arrayList; + } + + public User getUser(Statement statement, String userName) { + String sql = "select * from " + DBContext.userTable + " where userName=" + "'" + userName + "'"; + User user = null; + + try { + ResultSet resultSet = statement.executeQuery(sql); + if (resultSet.next()) { + int id = resultSet.getInt(1); + String name = userName; + String passWord = resultSet.getString(3); + boolean isLock = resultSet.getBoolean(4); + String validTime = resultSet.getString(5); + user = new User(id, name, passWord, isLock, validTime); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return user; + + } + + public User getUser(Statement statement, String userName, String password) { + User user = null; + String sql = "select * from " + DBContext.userTable + " where username='" + userName + "'" + " and password='" + + password + "'"; + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + if (resultSet.next()) { + user = new User(); + user.setId(resultSet.getInt(1)); + user.setUserName(resultSet.getString(2)); + user.setPassWord(resultSet.getString(3)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return user; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserPermissionDao.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserPermissionDao.java new file mode 100644 index 00000000000..c221e06d047 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserPermissionDao.java @@ -0,0 +1,98 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfiledb.auth.model.DBContext; +import cn.edu.thu.tsfiledb.auth.model.UserPermission; + +/** + * @author liukun + * + */ +public class UserPermissionDao { + + public int createUserPermission(Statement statement, UserPermission userPermission) { + String sql = "insert into " + DBContext.userPermission + " (userId,nodeName,permissionId)" + " values(" + + userPermission.getUserId() + ",'" + userPermission.getNodeName() + "'," + + userPermission.getPermissionId() + ")"; + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public int deleteUserPermission(Statement statement, UserPermission userPermission) { + String sql = "delete from " + DBContext.userPermission + " where userId=" + userPermission.getUserId() + " and " + + "nodeName=" + "'" + userPermission.getNodeName() + "'" + " and " + "permissionId=" + + userPermission.getPermissionId(); + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public UserPermission getUserPermission(Statement statement, UserPermission userPermission) { + String sql = "select * from " + DBContext.userPermission + " where userId=" + userPermission.getUserId() + + " and " + "nodeName=" + "'" + userPermission.getNodeName() + "'" + " and " + "permissionId=" + + userPermission.getPermissionId(); + UserPermission permission = null; + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + if (resultSet.next()) { + permission = new UserPermission(resultSet.getInt(1), resultSet.getInt(2), resultSet.getString(3), + resultSet.getInt(4)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return permission; + } + + // + public ArrayList getUserPermissionByUserAndNodeName(Statement statement, int userId, + String nodeName) { + ArrayList userPermissions = new ArrayList<>(); + String sql = "select * from " + DBContext.userPermission + " where userId=" + userId + " and " + "nodeName=" + + "'" + nodeName + "'"; + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + UserPermission userPermission = new UserPermission(resultSet.getInt(1), resultSet.getInt(2), + resultSet.getString(3), resultSet.getInt(4)); + userPermissions.add(userPermission); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return userPermissions; + } + + public List getUserPermissions(Statement statement) { + ArrayList userPermissions = new ArrayList<>(); + String sql = "select * from " + DBContext.userPermission; + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + UserPermission userPermission = new UserPermission(resultSet.getInt(1), resultSet.getInt(2), + resultSet.getString(3), resultSet.getInt(4)); + userPermissions.add(userPermission); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return userPermissions; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserRoleRelDao.java b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserRoleRelDao.java new file mode 100644 index 00000000000..c74f60eb5a2 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserRoleRelDao.java @@ -0,0 +1,116 @@ +package cn.edu.thu.tsfiledb.auth.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfiledb.auth.model.DBContext; +import cn.edu.thu.tsfiledb.auth.model.UserRoleRel; + +/** + * @author liukun + * + */ +public class UserRoleRelDao { + + public List getUserRoleRels(Statement statement) { + String sql = "select * from " + DBContext.userRoleRel; + ArrayList arrayList = new ArrayList<>(); + + try { + ResultSet resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + + int id = resultSet.getInt(1); + int userId = resultSet.getInt(2); + int roleId = resultSet.getInt(3); + UserRoleRel rel = new UserRoleRel(id, userId, roleId); + arrayList.add(rel); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + return arrayList; + } + + public UserRoleRel getUserRoleRel(Statement statement, UserRoleRel rel) { + String sql = "select * from " + DBContext.userRoleRel + " where userId=" + rel.getUserId() + " and roleId=" + + rel.getRoleId(); + UserRoleRel userRoleRel = null; + ResultSet resultSet; + try { + resultSet = statement.executeQuery(sql); + if (resultSet.next()) { + userRoleRel = new UserRoleRel(resultSet.getInt(1), resultSet.getInt(2), resultSet.getInt(3)); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return userRoleRel; + + } + + public List getUserRoleRelByUser(Statement statement, int userId) { + String sql = "select * from " + DBContext.userRoleRel + " where userId = " + userId; + ArrayList arrayList = new ArrayList<>(); + try { + ResultSet resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + int id = resultSet.getInt(1); + int roleId = resultSet.getInt(3); + UserRoleRel rel = new UserRoleRel(id, userId, roleId); + arrayList.add(rel); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return arrayList; + } + + public List getUserRoleRelByRole(Statement statement, int roleId) { + String sql = "select * from " + DBContext.userRoleRel + " where roleId=" + roleId; + ArrayList arrayList = new ArrayList<>(); + try { + ResultSet resultSet = statement.executeQuery(sql); + while (resultSet.next()) { + int id = resultSet.getInt(1); + int userId = resultSet.getInt(2); + UserRoleRel rel = new UserRoleRel(id, userId, roleId); + arrayList.add(rel); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return arrayList; + } + + public int createUserRoleRel(Statement statement, UserRoleRel rel) { + String sql = "insert into " + DBContext.userRoleRel + " (userId,roleId) values" + "(" + rel.getUserId() + "," + + rel.getRoleId() + ")"; + int state = 0; + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + return state; + } + + public int deleteUserRoleRel(Statement statement, UserRoleRel rel) { + String sql = "delete from " + DBContext.userRoleRel + " where userId=" + rel.getUserId() + " and roleId=" + + rel.getRoleId(); + int state = 0; + + try { + state = statement.executeUpdate(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + + return state; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/model/AuthException.java b/src/main/java/cn/edu/thu/tsfiledb/auth/model/AuthException.java new file mode 100644 index 00000000000..ba2493b4c18 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/model/AuthException.java @@ -0,0 +1,28 @@ +package cn.edu.thu.tsfiledb.auth.model; + +/** + * The exception for authority model + * Created by liukun on 17/1/4. + */ +public class AuthException extends Exception { + public AuthException(String format, String userName, String roleName) { + super(); + } + + public AuthException(String message) { + super(message); + } + + public AuthException(String message, Throwable cause) { + super(message, cause); + } + + public AuthException(Throwable cause) { + super(cause); + } + + protected AuthException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/model/DBContext.java b/src/main/java/cn/edu/thu/tsfiledb/auth/model/DBContext.java new file mode 100644 index 00000000000..fda7be9ec0f --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/model/DBContext.java @@ -0,0 +1,16 @@ +package cn.edu.thu.tsfiledb.auth.model; + +/** + * The + * @author liukun + * + */ +public class DBContext { + + public static final String userTable = "userTable"; + public static final String roleTable = "roleTable"; + public static final String userRoleRel = "userRoleRelTable"; + public static final String userPermission = "userPermissionTable"; + public static final String rolePermission = "rolePermissionTable"; + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/model/Permission.java b/src/main/java/cn/edu/thu/tsfiledb/auth/model/Permission.java new file mode 100644 index 00000000000..8b10d83faaf --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/model/Permission.java @@ -0,0 +1,15 @@ +package cn.edu.thu.tsfiledb.auth.model; + +/** + * @author liukun + * + */ +public class Permission { + + public static final int CREATE = 0; + public static final int INSERT = 1; + public static final int MODIFY = 2; + public static final int READ = 3; + public static final int DELETE = 4; + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/model/Role.java b/src/main/java/cn/edu/thu/tsfiledb/auth/model/Role.java new file mode 100644 index 00000000000..ca94c37edc8 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/model/Role.java @@ -0,0 +1,57 @@ +package cn.edu.thu.tsfiledb.auth.model; + +/** + * @author liukun + * + */ +public class Role { + + private int id; + private String roleName; + /** + * @param id + * @param roleName + */ + public Role(int id, String roleName) { + this.id = id; + this.roleName = roleName; + } + + public Role(String roleName) { + this.roleName = roleName; + } + + public Role(){ + + } + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return the roleName + */ + public String getRoleName() { + return roleName; + } + + /** + * @param roleName the roleName to set + */ + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/model/RolePermission.java b/src/main/java/cn/edu/thu/tsfiledb/auth/model/RolePermission.java new file mode 100644 index 00000000000..216b943d314 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/model/RolePermission.java @@ -0,0 +1,96 @@ +package cn.edu.thu.tsfiledb.auth.model; + +/** + * @author liukun + * + */ +public class RolePermission { + + private int id; + private int roleId; + private String nodeName; + private int permissionId; + + /** + * @param id + * @param roleId + * @param permissionId + */ + public RolePermission(int id, int roleId, String nodeName, int permissionId) { + this.id = id; + this.roleId = roleId; + this.nodeName = nodeName; + this.permissionId = permissionId; + } + + public RolePermission(int roleId, String nodeName, int permissionId) { + this.roleId = roleId; + this.nodeName = nodeName; + this.permissionId = permissionId; + } + + public RolePermission() { + + } + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @param id + * the id to set + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return the nodeName + */ + public String getNodeName() { + return nodeName; + } + + /** + * @param nodeName + * the nodeName to set + */ + public void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + /** + * @return the roleId + */ + public int getRoleId() { + return roleId; + } + + /** + * @param roleId + * the roleId to set + */ + public void setRoleId(int roleId) { + this.roleId = roleId; + } + + /** + * @return the permissionId + */ + public int getPermissionId() { + return permissionId; + } + + /** + * @param permissionId + * the permissionId to set + */ + public void setPermissionId(int permissionId) { + this.permissionId = permissionId; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/model/User.java b/src/main/java/cn/edu/thu/tsfiledb/auth/model/User.java new file mode 100644 index 00000000000..2e5c98863c3 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/model/User.java @@ -0,0 +1,109 @@ +package cn.edu.thu.tsfiledb.auth.model; + +/** + * @author liukun + * + */ +public class User { + + private int id; + private String userName; + private String passWord; + private boolean locked;//true - t false - f + private String validTime; + /** + * @param id + * @param userName + * @param passWord + * @param isLock + * @param validTime + */ + public User(int id, String userName, String passWord, boolean isLock, String validTime) { + this.id = id; + this.userName = userName; + this.passWord = passWord; + this.locked = isLock; + this.validTime = validTime; + } + + public User(){ + + } + + public User(String userName, String passWord) { + this.userName = userName; + this.passWord = passWord; + } + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return the userName + */ + public String getUserName() { + return userName; + } + + /** + * @param userName the userName to set + */ + public void setUserName(String userName) { + this.userName = userName; + } + + /** + * @return the passWord + */ + public String getPassWord() { + return passWord; + } + + /** + * @param passWord the passWord to set + */ + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + /** + * @return the isLock + */ + public boolean isLock() { + return locked; + } + + /** + * @param isLock the isLock to set + */ + public void setLock(boolean isLock) { + this.locked = isLock; + } + + /** + * @return the validTime + */ + public String getValidTime() { + return validTime; + } + + /** + * @param validTime the validTime to set + */ + public void setValidTime(String validTime) { + this.validTime = validTime; + } + + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/model/UserPermission.java b/src/main/java/cn/edu/thu/tsfiledb/auth/model/UserPermission.java new file mode 100644 index 00000000000..29f9c6d3e4e --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/model/UserPermission.java @@ -0,0 +1,98 @@ +package cn.edu.thu.tsfiledb.auth.model; + +/** + * @author liukun + * + */ +public class UserPermission { + + private int id; + private int userId; + private String nodeName; + private int permissionId;// 权限的值必须是permission中的,在数据库中使用check方法来指定 + + /** + * @param id + * @param userId + * @param nodeName + * @param permissionId + */ + public UserPermission(int id, int userId, String nodeName, int permissionId) { + this.id = id; + this.userId = userId; + this.nodeName = nodeName; + this.permissionId = permissionId; + } + + public UserPermission() { + + } + + public UserPermission(int userId, String nodeName, int permissionId) { + this.userId = userId; + this.nodeName = nodeName; + this.permissionId = permissionId; + } + + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @param id + * the id to set + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return the userId + */ + public int getUserId() { + return userId; + } + + /** + * @param userId + * the userId to set + */ + public void setUserId(int userId) { + this.userId = userId; + } + + /** + * @return the nodeName + */ + public String getNodeName() { + return nodeName; + } + + /** + * @param nodeName + * the nodeName to set + */ + public void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + /** + * @return the permissionId + */ + public int getPermissionId() { + return permissionId; + } + + /** + * @param permissionId + * the permissionId to set + */ + public void setPermissionId(int permissionId) { + this.permissionId = permissionId; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/model/UserRoleRel.java b/src/main/java/cn/edu/thu/tsfiledb/auth/model/UserRoleRel.java new file mode 100644 index 00000000000..952ecccc7a2 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/auth/model/UserRoleRel.java @@ -0,0 +1,65 @@ +package cn.edu.thu.tsfiledb.auth.model; + +/** + * @author liukun + * + */ +public class UserRoleRel { + private int id; + private int userId; + private int roleId; + /** + * @param id + * @param userId + * @param roleId + */ + public UserRoleRel(int id, int userId, int roleId) { + this.id = id; + this.userId = userId; + this.roleId = roleId; + } + public UserRoleRel(int userId,int roleId){ + this.userId = userId; + this.roleId = roleId; + } + public UserRoleRel() { + + } + /** + * @return the id + */ + public int getId() { + return id; + } + /** + * @param id the id to set + */ + public void setId(int id) { + this.id = id; + } + /** + * @return the userId + */ + public int getUserId() { + return userId; + } + /** + * @param userId the userId to set + */ + public void setUserId(int userId) { + this.userId = userId; + } + /** + * @return the roleId + */ + public int getRoleId() { + return roleId; + } + /** + * @param roleId the roleId to set + */ + public void setRoleId(int roleId) { + this.roleId = roleId; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/engine/exception/LRUManagerException.java b/src/main/java/cn/edu/thu/tsfiledb/engine/exception/LRUManagerException.java index d2ee6bc914f..fd450987202 100644 --- a/src/main/java/cn/edu/thu/tsfiledb/engine/exception/LRUManagerException.java +++ b/src/main/java/cn/edu/thu/tsfiledb/engine/exception/LRUManagerException.java @@ -1,6 +1,8 @@ package cn.edu.thu.tsfiledb.engine.exception; -public class LRUManagerException extends Exception { +import cn.edu.thu.tsfile.common.exception.ProcessorException; + +public class LRUManagerException extends ProcessorException { private static final long serialVersionUID = 3426203851432238314L; diff --git a/src/main/java/cn/edu/thu/tsfiledb/engine/filenode/FileNodeProcessor.java b/src/main/java/cn/edu/thu/tsfiledb/engine/filenode/FileNodeProcessor.java index ffc2be8d2c7..124175f1e8d 100644 --- a/src/main/java/cn/edu/thu/tsfiledb/engine/filenode/FileNodeProcessor.java +++ b/src/main/java/cn/edu/thu/tsfiledb/engine/filenode/FileNodeProcessor.java @@ -51,6 +51,7 @@ import cn.edu.thu.tsfiledb.engine.overflow.io.OverflowProcessor; import cn.edu.thu.tsfiledb.exception.PathErrorException; import cn.edu.thu.tsfiledb.metadata.ColumnSchema; import cn.edu.thu.tsfiledb.metadata.MManager; +import cn.edu.thu.tsfiledb.query.engine.OverflowQueryEngine; public class FileNodeProcessor extends LRUProcessor { @@ -791,7 +792,12 @@ public class FileNodeProcessor extends LRUProcessor { long endTime = -1; OverflowQueryEngine queryEngine = new OverflowQueryEngine(); - data = queryEngine.query(pathList, timeFilter, null, null, null, TsFileConf.defaultFetchSize); + try { + data = queryEngine.query(pathList, timeFilter, null, null, null, TsFileConf.defaultFetchSize); + } catch (ProcessorException e1) { + e1.printStackTrace(); + throw new IOException("Exception when merge"); + } if (!data.hasNextRecord()) { // No record in this query LOGGER.info("Merge query: namespace {}, time filter {}, no query data", nameSpacePath, timeFilter); diff --git a/src/main/java/cn/edu/thu/tsfiledb/engine/filenode/OverflowQueryEngine.java b/src/main/java/cn/edu/thu/tsfiledb/engine/filenode/OverflowQueryEngine.java deleted file mode 100644 index dd211056b9c..00000000000 --- a/src/main/java/cn/edu/thu/tsfiledb/engine/filenode/OverflowQueryEngine.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.edu.thu.tsfiledb.engine.filenode; - -import java.util.List; - -import cn.edu.thu.tsfile.timeseries.filter.definition.FilterExpression; -import cn.edu.thu.tsfile.timeseries.read.qp.Path; -import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet; - -public class OverflowQueryEngine { - - public QueryDataSet query(List pathList, FilterExpression timeFilter, Object object, Object object2, - Object object3, int defaultFetchSize) { - - return null; - } - -} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/constant/SQLConstant.java b/src/main/java/cn/edu/thu/tsfiledb/qp/constant/SQLConstant.java new file mode 100644 index 00000000000..71736a33e93 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/constant/SQLConstant.java @@ -0,0 +1,155 @@ +package cn.edu.thu.tsfiledb.qp.constant; + +import java.util.HashMap; +import java.util.Map; + +import cn.edu.thu.tsfile.timeseries.read.qp.Path; + + + +/** + * this class contains several constants used in SQL. + * + * @author kangrong + * + */ +public class SQLConstant { + public static final String MREGE_EXTENSION = "merge"; + public static final String ERR_EXTENSION = "err"; + public static final String PATH_SEPARATOR = "."; + public static final String PATH_SEPARATER_NO_REGEX = "\\."; + + public static final String DEFAULT_DELTA_OBJECT_TYPE = "defalut_delta_object_type"; + + public static final String RESERVED_TIME = "time"; + public static final String RESERVED_FREQ = "freq"; + public static final String RESERVED_DELTA_OBJECT = "delta_object"; + public static final String IS_AGGREGATION = "IS_AGGREGATION"; + + public static final String lineFeedSignal = "\n"; + public static final String ROOT = "root"; + public static final String METADATA_PARAM_EQUAL = "="; + + public static final int KW_AND = 1; + public static final int KW_OR = 2; + public static final int KW_NOT = 3; + + public static final int EQUAL = 11; + public static final int NOTEQUAL = 12; + public static final int LESSTHANOREQUALTO = 13; + public static final int LESSTHAN = 14; + public static final int GREATERTHANOREQUALTO = 15; + public static final int GREATERTHAN = 16; + public static final int EQUAL_NS = 17; + + public static final int TOK_SELECT = 21; + public static final int TOK_FROM = 22; + public static final int TOK_WHERE = 23; + public static final int TOK_INSERT = 24; + public static final int TOK_DELETE = 25; + public static final int TOK_UPDATE = 26; + public static final int TOK_QUERY = 27; + public static final int TOK_MULTIINSERT = 28; + // public static final int TOK_VIRTUAL_TABLE = 30; + // public static final int TOK_TABNAME = 31; + // public static final int TOK_TABREF = 32; + + public static final int TOK_AUTHOR_CREATE = 41; + public static final int TOK_AUTHOR_DROP = 42; + public static final int TOK_AUTHOR_GRANT = 43; + public static final int TOK_AUTHOR_REVOKE = 44; + /** + * 这是是刘昆修改的,为了update user的密码 + */ + public static final int TOK_AUTHOR_UPDATE_USER = 46; + + public static final int TOK_DATALOAD = 45; + + public static final int TOK_METADATA_CREATE = 51; + public static final int TOK_METADATA_DELETE = 52; + public static final int TOK_METADATA_SET_FILE_LEVEL = 53; + public static final int TOK_PORPERTY_CREATE = 54; + public static final int TOK_PORPERTY_ADD_LABEL = 55; + public static final int TOK_PORPERTY_DELETE_LABEL = 56; + public static final int TOK_PORPERTY_LINK = 57; + public static final int TOK_PORPERTY_UNLINK = 58; + + + + public static Map tokenSymbol = new HashMap(); + public static Map tokenNames = new HashMap(); + public static Map reverseWords = new HashMap(); + + static { + tokenSymbol.put(KW_AND, "&"); + tokenSymbol.put(KW_OR, "|"); + tokenSymbol.put(KW_NOT, "!"); + tokenSymbol.put(EQUAL, "="); + tokenSymbol.put(NOTEQUAL, "<>"); + tokenSymbol.put(EQUAL_NS, "<=>"); + tokenSymbol.put(LESSTHANOREQUALTO, "<="); + tokenSymbol.put(LESSTHAN, "<"); + tokenSymbol.put(GREATERTHANOREQUALTO, ">="); + tokenSymbol.put(GREATERTHAN, ">"); + } + + static { + tokenNames.put(KW_AND, "and"); + tokenNames.put(KW_OR, "or"); + tokenNames.put(KW_NOT, "not"); + tokenNames.put(EQUAL, "equal"); + tokenNames.put(NOTEQUAL, "not_equal"); + tokenNames.put(EQUAL_NS, "equal_ns"); + tokenNames.put(LESSTHANOREQUALTO, "lessthan_or_equalto"); + tokenNames.put(LESSTHAN, "lessthan"); + tokenNames.put(GREATERTHANOREQUALTO, "greaterthan_or_equalto"); + tokenNames.put(GREATERTHAN, "greaterthan"); + + tokenNames.put(TOK_SELECT, "TOK_SELECT"); + tokenNames.put(TOK_FROM, "TOK_FROM"); + tokenNames.put(TOK_WHERE, "TOK_WHERE"); + tokenNames.put(TOK_INSERT, "TOK_INSERT"); + tokenNames.put(TOK_DELETE, "TOK_DELETE"); + tokenNames.put(TOK_UPDATE, "TOK_UPDATE"); + tokenNames.put(TOK_QUERY, "TOK_QUERY"); + tokenNames.put(TOK_MULTIINSERT, "TOK_MULTIINSERT"); + + tokenNames.put(TOK_AUTHOR_CREATE, "TOK_AUTHOR_CREATE"); + tokenNames.put(TOK_AUTHOR_DROP, "TOK_AUTHOR_DROP"); + tokenNames.put(TOK_AUTHOR_GRANT, "TOK_AUTHOR_GRANT"); + tokenNames.put(TOK_AUTHOR_REVOKE, "TOK_AUTHOR_REVOKE"); + /** + * 这是是刘昆修改的,为了update user的密码 + */ + tokenNames.put(TOK_AUTHOR_UPDATE_USER, "TOK_AUTHOR_UPDATE_USER"); + tokenNames.put(TOK_DATALOAD, "TOK_DATALOAD"); + + tokenNames.put(TOK_METADATA_CREATE, "TOK_METADATA_CREATE"); + tokenNames.put(TOK_METADATA_DELETE, "TOK_METADATA_DELETE"); + tokenNames.put(TOK_METADATA_SET_FILE_LEVEL, "TOK_METADATA_SET_FILE_LEVEL"); + tokenNames.put(TOK_PORPERTY_CREATE, "TOK_PORPERTY_CREATE"); + tokenNames.put(TOK_PORPERTY_ADD_LABEL, "TOK_PORPERTY_ADD_LABEL"); + tokenNames.put(TOK_PORPERTY_DELETE_LABEL, "TOK_PORPERTY_DELETE_LABEL"); + tokenNames.put(TOK_PORPERTY_LINK, "TOK_PORPERTY_LINK"); + tokenNames.put(TOK_PORPERTY_UNLINK, "TOK_PORPERTY_UNLINK"); + + } + + static { + reverseWords.put(KW_AND, KW_OR); + reverseWords.put(KW_OR, KW_AND); + reverseWords.put(EQUAL, NOTEQUAL); + reverseWords.put(NOTEQUAL, EQUAL); + reverseWords.put(LESSTHAN, GREATERTHANOREQUALTO); + reverseWords.put(GREATERTHANOREQUALTO, LESSTHAN); + reverseWords.put(LESSTHANOREQUALTO, GREATERTHAN); + reverseWords.put(GREATERTHAN, LESSTHANOREQUALTO); + } + + public static boolean isReservedPath(Path pathStr) { + return pathStr.equals(SQLConstant.RESERVED_TIME) + || pathStr.equals(SQLConstant.RESERVED_FREQ) + || pathStr.equals(SQLConstant.RESERVED_DELTA_OBJECT); + + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/ErrorQueryOpException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/ErrorQueryOpException.java new file mode 100644 index 00000000000..969e975bba2 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/ErrorQueryOpException.java @@ -0,0 +1,21 @@ +package cn.edu.thu.tsfiledb.qp.exception; + +/** + * This exception is for calling error method in {@linkplain com.corp.tsfile.sql.exec.TSqlParserV2 + * TSqlParserV2}.
+ * Throw this exception if user call {@code nonQuery} method from a {@code QUERY operator}, or call + * {@code getIndex getIndex} method from a {@code NonQUERY operator}, like AUTHOR, LOADDATA, + * UPDATE,INSERT, DELETE + * + * @author kangrong + * + */ +public class ErrorQueryOpException extends QueryProcessorException { + + private static final long serialVersionUID = -262405196554416563L; + + public ErrorQueryOpException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/IllegalASTFormatException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/IllegalASTFormatException.java new file mode 100644 index 00000000000..9134c1fea98 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/IllegalASTFormatException.java @@ -0,0 +1,10 @@ +package cn.edu.thu.tsfiledb.qp.exception; + +public class IllegalASTFormatException extends QueryProcessorException { + private static final long serialVersionUID = -8987915911329315588L; + + public IllegalASTFormatException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/QueryProcessorException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/QueryProcessorException.java new file mode 100644 index 00000000000..02bfd5bdc64 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/QueryProcessorException.java @@ -0,0 +1,17 @@ +package cn.edu.thu.tsfiledb.qp.exception; + +public class QueryProcessorException extends Exception { + private static final long serialVersionUID = -8987915921329335088L; + + protected String errMsg; + public QueryProcessorException(String msg) { + super(msg); + this.errMsg = msg; + } + + @Override + public String getMessage() { + return errMsg; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/TSTransformException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/TSTransformException.java new file mode 100644 index 00000000000..80029d5c131 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/TSTransformException.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.exception; + +/** + * This exception is threw while meeting error in transforming a logical operator to a physical + * plan. + * + * @author kangrong + * + */ +public class TSTransformException extends QueryProcessorException { + /** + * + */ + private static final long serialVersionUID = 7573857366601268706L; + + public TSTransformException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/BasicOperatorException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/BasicOperatorException.java new file mode 100644 index 00000000000..f83ba254d89 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/BasicOperatorException.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +/** + * This exception is threw whiling meeting error in + * {@linkplain cn.edu.thu.tsfiledb.qp.logical.operator.crud.BasicFunctionOperator BasicFunctionOperator} + * + * @author kangrong + * + */ +public class BasicOperatorException extends QueryProcessorException { + + private static final long serialVersionUID = -2163809754074237707L; + + public BasicOperatorException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/DeleteOperatorException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/DeleteOperatorException.java new file mode 100644 index 00000000000..68a999fb661 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/DeleteOperatorException.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +/** + * This exception is threw whiling meeting error in + * {@linkplain cn.edu.thu.tsfiledb.qp.logical.operator.crud.DeleteOperator DeleteOperator} + * + * @author kangrong + * + */ +public class DeleteOperatorException extends QueryProcessorException { + + private static final long serialVersionUID = 5532624124231495807L; + + public DeleteOperatorException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/FilterOperatorException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/FilterOperatorException.java new file mode 100644 index 00000000000..eb3c058e565 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/FilterOperatorException.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +/** + * This exception is threw whiling meeting error in + * {@linkplain cn.edu.thu.tsfiledb.qp.logical.operator.crud.FilterOperator FilterOperator} + * + * @author kangrong + * + */ +public class FilterOperatorException extends QueryProcessorException { + + private static final long serialVersionUID = 167597682291449523L; + + public FilterOperatorException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/InsertOperatorException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/InsertOperatorException.java new file mode 100644 index 00000000000..bbbed759524 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/InsertOperatorException.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +/** + * This exception is threw whiling meeting error in + * {@linkplain cn.edu.thu.tsfiledb.qp.logical.operator.crud.InsertOperator InsertOperator} + * + * @author kangrong + * + */ +public class InsertOperatorException extends QueryProcessorException { + + private static final long serialVersionUID = -6280121806646850135L; + + public InsertOperatorException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ParseLeafException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ParseLeafException.java new file mode 100644 index 00000000000..68e82be6137 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ParseLeafException.java @@ -0,0 +1,10 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +public class ParseLeafException extends QpWhereException { + private static final long serialVersionUID = -8987115911329315088L; + + public ParseLeafException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ParseTimeException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ParseTimeException.java new file mode 100644 index 00000000000..886f1559314 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ParseTimeException.java @@ -0,0 +1,10 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +public class ParseTimeException extends QpWhereException { + private static final long serialVersionUID = -5838261873402031565L; + + public ParseTimeException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QpSelectFromException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QpSelectFromException.java new file mode 100644 index 00000000000..afbf45ff3c7 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QpSelectFromException.java @@ -0,0 +1,12 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +public class QpSelectFromException extends QueryProcessorException { + private static final long serialVersionUID = -8987543591129315588L; + + public QpSelectFromException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QpWhereException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QpWhereException.java new file mode 100644 index 00000000000..29c184e73cf --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QpWhereException.java @@ -0,0 +1,12 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +public class QpWhereException extends QueryProcessorException { + private static final long serialVersionUID = -8987915911329315088L; + + public QpWhereException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QueryOperatorException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QueryOperatorException.java new file mode 100644 index 00000000000..5a2e443e4cd --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/QueryOperatorException.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +/** + * This exception is threw whiling meeting error in + * {@linkplain cn.edu.thu.tsfiledb.qp.logical.operator.crud.QueryOperator QueryOperator} + * + * @author kangrong + * + */ +public class QueryOperatorException extends QueryProcessorException { + + private static final long serialVersionUID = 4466703029858082216L; + + public QueryOperatorException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/SeriesNotExistException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/SeriesNotExistException.java new file mode 100644 index 00000000000..c3a92572006 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/SeriesNotExistException.java @@ -0,0 +1,10 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +public class SeriesNotExistException extends QpSelectFromException { + private static final long serialVersionUID = -5838261873402011565L; + + public SeriesNotExistException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/SetClauseException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/SetClauseException.java new file mode 100644 index 00000000000..94800dc0c76 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/SetClauseException.java @@ -0,0 +1,12 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +public class SetClauseException extends QueryProcessorException { + private static final long serialVersionUID = -8987915921329315088L; + + public SetClauseException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/UpdateOperatorException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/UpdateOperatorException.java new file mode 100644 index 00000000000..24f14e18278 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/UpdateOperatorException.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +/** + * This exception is threw whiling meeting error in + * {@linkplain cn.edu.thu.tsfiledb.qp.logical.operator.crud.UpdateOperator UpdateOperator} + * + * @author kangrong + * + */ +public class UpdateOperatorException extends QueryProcessorException { + + private static final long serialVersionUID = -797390809639488007L; + + public UpdateOperatorException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ValueParseException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ValueParseException.java new file mode 100644 index 00000000000..43dfd15870c --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/operator/ValueParseException.java @@ -0,0 +1,12 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +public class ValueParseException extends QueryProcessorException { + private static final long serialVersionUID = -8987281211329315088L; + + public ValueParseException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/DNFOptimizeException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/DNFOptimizeException.java new file mode 100644 index 00000000000..e45199d6317 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/DNFOptimizeException.java @@ -0,0 +1,12 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.optimize; + + +public class DNFOptimizeException extends LogicalOptimizeException { + + private static final long serialVersionUID = 807384397361662482L; + + public DNFOptimizeException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/LogicalOptimizeException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/LogicalOptimizeException.java new file mode 100644 index 00000000000..ed4dcf9ef9a --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/LogicalOptimizeException.java @@ -0,0 +1,13 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.optimize; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +public class LogicalOptimizeException extends QueryProcessorException { + + private static final long serialVersionUID = -7098092782689670064L; + + public LogicalOptimizeException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/MergeFilterException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/MergeFilterException.java new file mode 100644 index 00000000000..d33ab88311b --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/MergeFilterException.java @@ -0,0 +1,12 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.optimize; + + +public class MergeFilterException extends LogicalOptimizeException { + + private static final long serialVersionUID = 8581594261924961899L; + + public MergeFilterException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/PathConcatException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/PathConcatException.java new file mode 100644 index 00000000000..4d22dd6d157 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/PathConcatException.java @@ -0,0 +1,12 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.optimize; + + +public class PathConcatException extends LogicalOptimizeException { + + private static final long serialVersionUID = 1789858025764650098L; + + public PathConcatException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/RemoveNotException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/RemoveNotException.java new file mode 100644 index 00000000000..0e209799ed7 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/logical/optimize/RemoveNotException.java @@ -0,0 +1,16 @@ +package cn.edu.thu.tsfiledb.qp.exception.logical.optimize; + + +public class RemoveNotException extends LogicalOptimizeException { + + + /** + * + */ + private static final long serialVersionUID = -772591029262375715L; + + public RemoveNotException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/physical/plan/NamespacePlanException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/physical/plan/NamespacePlanException.java new file mode 100644 index 00000000000..7cce91e4884 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/physical/plan/NamespacePlanException.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.exception.physical.plan; + +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; + +public class NamespacePlanException extends PhysicalPlanException { + + private static final long serialVersionUID = -2069701664732857589L; + + public NamespacePlanException(String msg){ + super(msg); + } + public NamespacePlanException(String msg, Exception exception) { + super(msg); + StringContainer sc = new StringContainer(","); + sc.addTail("error message:", msg, "meet other exceptions:"); + sc.addTail("exception type", exception.getClass().toString(), "exception message", + exception.getMessage()); + errMsg = sc.toString(); + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exception/physical/plan/PhysicalPlanException.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/physical/plan/PhysicalPlanException.java new file mode 100644 index 00000000000..58c1fa68033 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exception/physical/plan/PhysicalPlanException.java @@ -0,0 +1,13 @@ +package cn.edu.thu.tsfiledb.qp.exception.physical.plan; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; + +public class PhysicalPlanException extends QueryProcessorException { + + private static final long serialVersionUID = 2730849997674197054L; + + public PhysicalPlanException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exec/BasicOperatorType.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exec/BasicOperatorType.java new file mode 100644 index 00000000000..8d6e5d9214c --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exec/BasicOperatorType.java @@ -0,0 +1,86 @@ +package cn.edu.thu.tsfiledb.qp.exec; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.timeseries.filter.definition.FilterFactory; +import cn.edu.thu.tsfile.timeseries.filter.definition.SingleSeriesFilterExpression; +import cn.edu.thu.tsfile.timeseries.filter.definition.filterseries.FilterSeries; +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.BasicOperatorException; + +/** + * all basic operator in filter + * + * @author kangrong + * + */ +public enum BasicOperatorType { + EQ { + @Override + public , C extends FilterSeries> SingleSeriesFilterExpression getSingleSeriesFilterExpression( + C column, T value) { + return FilterFactory.eq(column, value); + } + }, + LTEQ { + @Override + public , C extends FilterSeries> SingleSeriesFilterExpression getSingleSeriesFilterExpression( + C column, T value) { + return FilterFactory.ltEq(column, value, true); + } + }, + LT { + @Override + public , C extends FilterSeries> SingleSeriesFilterExpression getSingleSeriesFilterExpression( + C column, T value) { + return FilterFactory.ltEq(column, value, false); + } + }, + GTEQ { + @Override + public , C extends FilterSeries> SingleSeriesFilterExpression getSingleSeriesFilterExpression( + C column, T value) { + return FilterFactory.gtEq(column, value, true); + } + }, + GT { + @Override + public , C extends FilterSeries> SingleSeriesFilterExpression getSingleSeriesFilterExpression( + C column, T value) { + return FilterFactory.gtEq(column, value, false); + } + }, + NOTEQUAL { + @Override + public , C extends FilterSeries> SingleSeriesFilterExpression getSingleSeriesFilterExpression( + C column, T value) { + return FilterFactory.noteq(column, value); + } + }; + private static Logger LOG = LoggerFactory.getLogger(BasicOperatorType.class); + + public static BasicOperatorType getBasicOpBySymbol(int tokenIntType) + throws BasicOperatorException { + switch (tokenIntType) { + case SQLConstant.EQUAL: + return EQ; + case SQLConstant.LESSTHANOREQUALTO: + return LTEQ; + case SQLConstant.LESSTHAN: + return LT; + case SQLConstant.GREATERTHANOREQUALTO: + return GTEQ; + case SQLConstant.GREATERTHAN: + return GT; + case SQLConstant.NOTEQUAL: + return NOTEQUAL; + default: + throw new BasicOperatorException("unsupported type:{}" + + SQLConstant.tokenNames.get(tokenIntType)); + } + } + + public abstract , C extends FilterSeries> SingleSeriesFilterExpression getSingleSeriesFilterExpression( + C column, T value); +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exec/FilterType.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exec/FilterType.java new file mode 100644 index 00000000000..806fa0c6e6d --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exec/FilterType.java @@ -0,0 +1,32 @@ +package cn.edu.thu.tsfiledb.qp.exec; + +/** + * condition has three type:time, freq(frequency) and ordinary value. + * + * @author kangrong + * + */ +public enum FilterType { + TIME(0), FREQ(1), VALUE(2); + private int typeCode; + + private FilterType(int i) { + typeCode = i; + } + + public int getTypeCode() { + return typeCode; + } + + public static FilterType valueOfStr(String v) { + v = v.toLowerCase(); + switch (v) { + case "time": + return TIME; + case "freq": + return FREQ; + default: + return VALUE; + } + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exec/QueryProcessExecutor.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exec/QueryProcessExecutor.java new file mode 100644 index 00000000000..54afdba8a40 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exec/QueryProcessExecutor.java @@ -0,0 +1,238 @@ +package cn.edu.thu.tsfiledb.qp.exec; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.derby.iapi.error.PublicAPI; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.file.metadata.enums.TSDataType; +import cn.edu.thu.tsfile.timeseries.filter.definition.FilterExpression; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet; +import cn.edu.thu.tsfiledb.auth.dao.Authorizer; +import cn.edu.thu.tsfiledb.auth.model.AuthException; +import cn.edu.thu.tsfiledb.exception.PathErrorException; +import cn.edu.thu.tsfiledb.metadata.MManager; +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + + +public abstract class QueryProcessExecutor { + protected final boolean isSingleFile; + /** + * parameters allows to set and get user-defined parameters. + */ + protected ThreadLocal> parameters = new ThreadLocal>(); + protected int fetchSize = 100; + + public QueryProcessExecutor(boolean isSingleFile) { + this.isSingleFile = isSingleFile; + } + + protected abstract TSDataType getNonReseveredSeriesType(Path fullPath); + + protected abstract boolean judgeNonReservedPathExists(Path fullPath); + + public boolean isSingleFile() { + return isSingleFile; + } + + public TSDataType getSeriesType(Path fullPath) { + if (fullPath.equals(SQLConstant.RESERVED_TIME)) + return TSDataType.INT64; + if (fullPath.equals(SQLConstant.RESERVED_FREQ)) + return TSDataType.FLOAT; + if (fullPath.equals(SQLConstant.RESERVED_DELTA_OBJECT)) + return TSDataType.BYTE_ARRAY; + return getNonReseveredSeriesType(fullPath); + } + + public boolean judgePathExists(Path pathStr) { + if (SQLConstant.isReservedPath(pathStr)) + return true; + else + return judgeNonReservedPathExists(pathStr); + } + + public void setFetchSize(int fetchSize) { + this.fetchSize = fetchSize; + } + + /** + * in getIndex command, fetchSize must be specified at first. + * + * @return + */ + public int getFetchSize() { + return fetchSize; + } + + /** + * + * @param paths + * @param timeFilter + * @param freqFilter + * @param valueFilter + * @param fetchSize + * @param lastData + * @return + */ + public abstract QueryDataSet query(List paths, FilterExpression timeFilter, + FilterExpression freqFilter, FilterExpression valueFilter, int fetchSize, + QueryDataSet lastData) throws ProcessorException; + + /** + * execute update command and return whether the operator is successful. + * + * @param path : update series path + * @param startTime + * @param endTime + * @param value - in type of string + * @return - whether the operator is successful. + */ + public abstract boolean update(Path path, long startTime, long endTime, String value) throws ProcessorException; + + /** + * execute delete command and return whether the operator is successful. + * + * @param path : delete series path + * @param deleteTime + * @return - whether the operator is successful. + */ + public abstract boolean delete(Path path, long deleteTime) throws ProcessorException; + + /** + * execute insert command and return whether the operator is successful. + * + * @param path + * @param insertTime - it's time point but not a range + * @param value + * @return - Operate Type. + */ + public abstract int insert(Path path, long insertTime, String value) throws ProcessorException; + + public abstract int multiInsert(String deltaObject, long insertTime, + List measurementList, List insertValues) throws ProcessorException; + + public MManager getMManager() { + return MManager.getInstance(); + } + + public void addParameter(String key, Object value) { + if(parameters.get() == null){ + parameters.set(new HashMap()); + } + parameters.get().put(key, value); + } + + public Object getParameter(String key) { + return parameters.get().get(key); + } + + public void clearParamter(){ + if(parameters.get() != null){ + parameters.get().clear(); + } + } + /* + * 刘昆修改,添加修改用户密码功能 + */ + public boolean updateUser(String username,String newPassword) throws AuthException{ + return Authorizer.updateUserPassword(username, newPassword); + } + + public boolean createUser(String username, String password) throws AuthException { + return Authorizer.createUser(username, password); + } + + /** + * 异常可能:用户不存在,权限编号不对等 + */ + public boolean addPmsToUser(String userName, String nodeName, int permissionId) + throws AuthException { + return Authorizer.addPmsToUser(userName, nodeName, permissionId); + } + + /** + * 异常可能:用户不存在;用户不具有该权限 + */ + public boolean removePmsFromUser(String userName, String nodeName, int permissionId) + throws AuthException { + return Authorizer.removePmsFromUser(userName, nodeName, permissionId); + } + + + /** + * 异常可能:用户不存在 + */ + public boolean deleteUser(String userName) throws AuthException { + return Authorizer.deleteUser(userName); + } + + + /** + * 异常可能:角色已经存在 + */ + public boolean createRole(String roleName) throws AuthException { + return Authorizer.createRole(roleName); + } + + /** + * 异常可能:角色不存在,或者权限ID不对 + */ + public boolean addPmsToRole(String roleName, String nodeName, int permissionId) + throws AuthException { + return Authorizer.addPmsToRole(roleName, nodeName, permissionId); + } + + /** + * 异常可能:角色不存在;权限ID不对;角色本来不拥有该权限 + */ + public boolean removePmsFromRole(String roleName, String nodeName, int permissionId) + throws AuthException { + return Authorizer.removePmsFromRole(roleName, nodeName, permissionId); + } + + /** + * 异常可能:角色不存在 + */ + public boolean deleteRole(String roleName) throws AuthException { + return Authorizer.deleteRole(roleName); + } + + /** + * 异常可能:用户不存在;角色不存在;该用户已经拥有该该角色 + */ + public boolean grantRoleToUser(String roleName, String username) throws AuthException { + return Authorizer.grantRoleToUser(roleName, username); + } + + /** + * 异常可能:用户不存在;角色不存在;该用户没有该角色 + */ + public boolean revokeRoleFromUser(String roleName, String username) throws AuthException { + return Authorizer.revokeRoleFromUser(roleName, username); + } + + /** + * 异常可能:用户不存在 + */ + public Set getPermissions(String username, String nodeName) throws AuthException { + return Authorizer.getPermission(username, nodeName); + } + + public PhysicalPlan queryPhysicalOptimize(PhysicalPlan plan) { + return plan; + } + + public PhysicalPlan nonQueryPhysicalOptimize(PhysicalPlan plan) { + return plan; + } + + public List getAllPaths(String fullPath) throws PathErrorException { + return getMManager().getPaths(fullPath); + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/exec/impl/OverflowQPExecutor.java b/src/main/java/cn/edu/thu/tsfiledb/qp/exec/impl/OverflowQPExecutor.java new file mode 100644 index 00000000000..73ef75a07e7 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/exec/impl/OverflowQPExecutor.java @@ -0,0 +1,162 @@ +package cn.edu.thu.tsfiledb.qp.exec.impl; + + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.file.metadata.enums.TSDataType; +import cn.edu.thu.tsfile.timeseries.filter.definition.FilterExpression; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet; +import cn.edu.thu.tsfile.timeseries.write.record.DataPoint; +import cn.edu.thu.tsfile.timeseries.write.record.TSRecord; +import cn.edu.thu.tsfiledb.engine.filenode.FileNodeManager; +import cn.edu.thu.tsfiledb.exception.PathErrorException; +import cn.edu.thu.tsfiledb.metadata.MManager; +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.query.engine.OverflowQueryEngine; + +public class OverflowQPExecutor extends QueryProcessExecutor { + + static final Logger logger = LoggerFactory.getLogger(OverflowQPExecutor.class); + private OverflowQueryEngine queryEngine; + private FileNodeManager fileNodeManager; + + public OverflowQPExecutor() { + super(false); + queryEngine = new OverflowQueryEngine(); + fileNodeManager = FileNodeManager.getInstance(); + } + + @Override + protected TSDataType getNonReseveredSeriesType(Path path) { + try { + return MManager.getInstance().getSeriesType(path.getFullPath()); + } catch (PathErrorException e) { + logger.error("path error in getSeriesType. Path: " + path.getFullPath() + "ErrorMsg: " + e.getMessage()); + } + return null; + } + + @Override + protected boolean judgeNonReservedPathExists(Path path) { + return MManager.getInstance().pathExist(path.getFullPath()); + } + + @Override + public QueryDataSet query(List paths, FilterExpression timeFilter, FilterExpression freqFilter, + FilterExpression valueFilter, int fetchSize, QueryDataSet lastData) throws ProcessorException { + QueryDataSet ret; + try { + if (parameters.get() != null && parameters.get().containsKey(SQLConstant.IS_AGGREGATION)) { + if (lastData != null) { + lastData.clear(); + return lastData; + } + String aggrFuncName = (String) parameters.get().get(SQLConstant.IS_AGGREGATION); + ret = queryEngine.aggregate(paths.get(0), aggrFuncName, timeFilter, freqFilter, valueFilter); + } else { + ret = queryEngine.query(paths, timeFilter, freqFilter, valueFilter, lastData, fetchSize); + } + + return ret; + } catch (Exception e) { + logger.error("Error in query", e); + e.printStackTrace(); + return null; + } + } + + @Override + public boolean update(Path path, long startTime, long endTime, String value) throws ProcessorException { + String device = path.getDeltaObjectToString(); + String sensor = path.getMeasurementToString(); + + try { + TSDataType type = queryEngine.getDataTypeByDeviceAndSensor(device, sensor); + fileNodeManager.update(device, sensor, startTime, endTime, type, value); + return true; + } catch (PathErrorException e) { + throw new ProcessorException("Error in update: " + e.getMessage()); + } + } + + @Override + public boolean delete(Path path, long timestamp) throws ProcessorException { + // TODO Auto-generated method stub + String device = path.getDeltaObjectToString(); + String sensor = path.getMeasurementToString(); + try { + TSDataType type = queryEngine.getDataTypeByDeviceAndSensor(device, sensor); + fileNodeManager.delete(device, sensor, timestamp, type); + return true; + } catch (PathErrorException e) { + throw new ProcessorException("Error in delete: " + e.getMessage()); + } + } + + @Override + // return 0: failed, 1: Overflow, 2:Bufferwrite + public int insert(Path path, long timestamp, String value) throws ProcessorException { + String device = path.getDeltaObjectToString(); + String sensor = path.getMeasurementToString(); + + try { + TSDataType type = queryEngine.getDataTypeByDeviceAndSensor(device, sensor); + TSRecord tsRecord = new TSRecord(timestamp, device); + DataPoint dataPoint = DataPoint.getDataPoint(type, sensor, value); + tsRecord.addTuple(dataPoint); + return fileNodeManager.insert(tsRecord); + + } catch (PathErrorException e) { + throw new ProcessorException("Error in insert: " + e.getMessage()); + } + } + + @Override + public int multiInsert(String deltaObject, long insertTime, List measurementList, List insertValues) + throws ProcessorException { + try { + MManager mManager = MManager.getInstance(); + TSRecord tsRecord = new TSRecord(insertTime, deltaObject); + + for (int i = 0 ; i < measurementList.size() ; i ++) { + StringBuilder sb = new StringBuilder(); + sb.append(deltaObject); + sb.append("."); + sb.append(measurementList.get(i)); + String p = sb.toString(); + if(!mManager.pathExist(p)){ + throw new ProcessorException("Path not exists:" + p); + } + TSDataType dataType = mManager.getSeriesType(p); + DataPoint dataPoint = DataPoint.getDataPoint(dataType, measurementList.get(i), insertValues.get(i)); + tsRecord.addTuple(dataPoint); + } + return fileNodeManager.insert(tsRecord); + + } catch (PathErrorException e) { + throw new ProcessorException("Path error:" + e.getMessage()); + } + } + +} + + + + + + + + + + + + + + + diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/Operator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/Operator.java new file mode 100644 index 00000000000..7477d5a8e5b --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/Operator.java @@ -0,0 +1,51 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator; + +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; + +/** + * This class is a superclass of all operator. + * + * @author kangrong + */ +public abstract class Operator { + protected int tokenIntType; + protected String tokenName; + + protected OperatorType operatorType = OperatorType.NULL; + + public Operator(int tokenIntType) { + this.tokenIntType = tokenIntType; + this.tokenName = SQLConstant.tokenNames.get(tokenIntType); + } + + public OperatorType getType() { + return operatorType; + } + + public boolean isQuery() { + return operatorType == OperatorType.QUERY; + } + + public int getTokenIntType() { + return tokenIntType; + } + + public String getTokenName() { + return tokenName; + } + + @Override + public String toString() { + return tokenName; + } + + public enum OperatorType { + ROOT, JOIN, UNION, FILTER, GROUPBY, ORDERBY, LIMIT, SELECT, SEQTABLESCAN, HASHTABLESCAN, MERGEJOIN, FILEREAD, NULL, TABLESCAN, + UPDATE, MULTIINSERT, INSERT, DELETE, BASIC_FUNC, QUERY, AUTHOR, FROM, FUNC, LOADDATA, METADATA, PROPERTY + , OVERFLOWFLUSHSTART, // 25 + // ordinal() + OVERFLOWFLUSHEND, // 26 + BUFFERFLUSHSTART, // 27 + BUFFERFLUSHEND; // 28 + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/RootOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/RootOperator.java new file mode 100644 index 00000000000..c0186df08c6 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/RootOperator.java @@ -0,0 +1,29 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.SFWOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * RootOperator indicates the operator that could be executed as a entire command. RootOperator + * consists of SFWOperator, like INSERT/UPDATE/DELETE, and AuthorOperator. + * + * @author kangrong + */ +public abstract class RootOperator extends Operator { + + + public RootOperator(int tokenIntType) { + super(tokenIntType); + } + + /** + * transform this root operator tree to a physical plan tree.Node that, before this method + * called, the where filter has been dealt with + * {@linkplain cn.edu.thu.tsfiledb.qp.logical.optimizer.filter.MergeSingleFilterOptimizer} + */ + public abstract PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException; + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/author/AuthorOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/author/AuthorOperator.java new file mode 100644 index 00000000000..a463b2ff524 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/author/AuthorOperator.java @@ -0,0 +1,95 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.author; + +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.RootOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.SFWOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.AuthorPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * this class maintains information in Author statement, including CREATE, DROP, GRANT and REVOKE + * + * @author kangrong + * + */ +public class AuthorOperator extends RootOperator { + + public AuthorOperator(int tokenIntType, AuthorType type) { + super(tokenIntType); + authorType = type; + operatorType = OperatorType.AUTHOR; + } + + private final AuthorType authorType; + private String userName; + private String roleName; + private String password; + //被刘昆修改,填写新的密码内容 + private String newPassword; + private String[] privilegeList; + private Path nodeName; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public String getPassWord() { + return password; + } + + public void setPassWord(String password) { + this.password = password; + } + + public String getNewPassword() { + return newPassword; + } + + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } + + public String[] getPrivilegeList() { + return privilegeList; + } + + public void setPrivilegeList(String[] authorizationList) { + this.privilegeList = authorizationList; + } + + public Path getNodeName() { + return nodeName; + } + + public void setNodeNameList(String[] nodeNameList) { + StringContainer sc = new StringContainer(SQLConstant.PATH_SEPARATOR); + sc.addTail(nodeNameList); + this.nodeName = new Path(sc); + } + + public enum AuthorType { + CREATE_USER, CREATE_ROLE, DROP_USER, DROP_ROLE, GRANT_ROLE, GRANT_USER, GRANT_ROLE_TO_USER, REVOKE_USER, REVOKE_ROLE, REVOKE_ROLE_FROM_USER,UPDATE_USER + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + return new AuthorPlan(authorType, userName, roleName, password, newPassword, privilegeList, nodeName); + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/BasicFunctionOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/BasicFunctionOperator.java new file mode 100644 index 00000000000..be63cf19879 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/BasicFunctionOperator.java @@ -0,0 +1,166 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.utils.Pair; +import cn.edu.thu.tsfile.file.metadata.enums.TSDataType; +import cn.edu.thu.tsfile.timeseries.filter.definition.FilterFactory; +import cn.edu.thu.tsfile.timeseries.filter.definition.SingleSeriesFilterExpression; +import cn.edu.thu.tsfile.timeseries.filter.definition.filterseries.FilterSeriesType; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.BasicOperatorException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.QpSelectFromException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.QpWhereException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.SeriesNotExistException; +import cn.edu.thu.tsfiledb.qp.exec.BasicOperatorType; +import cn.edu.thu.tsfiledb.qp.exec.FilterType; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; + +/** + * basic operator include < > >= <= !=. + * + * @author kangrong + * + */ + +public class BasicFunctionOperator extends FunctionOperator { + Logger LOG = LoggerFactory.getLogger(BasicFunctionOperator.class); + + private BasicOperatorType funcToken; + private final FilterType filterType; + + protected Path seriesPath; + protected String seriesValue; + + public String getSeriesPath() { + return seriesPath.toString(); + } + + public String getSeriesValue() { + return seriesValue; + } + + public BasicFunctionOperator(int tokenIntType, Path path, String value) + throws BasicOperatorException { + super(tokenIntType); + operatorType = OperatorType.BASIC_FUNC; + funcToken = BasicOperatorType.getBasicOpBySymbol(tokenIntType); + this.seriesPath = this.singlePath = path; + this.seriesValue = value; + filterType = FilterType.valueOfStr(seriesPath.getFullPath()); + + } + + public void setReversedTokenIntType() throws BasicOperatorException { + int intType = SQLConstant.reverseWords.get(tokenIntType); + setTokenIntType(intType); + funcToken = BasicOperatorType.getBasicOpBySymbol(intType); + } + + @Override + public Path getSinglePath() { + return singlePath; + } + + @Override + public void addHeadDeltaObjectPath(String deltaObject) { + seriesPath.addHeadPath(deltaObject); + } + + // @Override + // public Pair, FilterOperator> splitFilOpWithDNF( + // Set reservedWords){ + // Map ret = new HashMap(); + // if(reservedWords.contains(seriesPath.toString())){ + // ret.put(seriesPath.toString(), this); + // return new Pair, FilterOperator>(ret, null); + // } + // else { + // return new Pair, FilterOperator>(ret, this); + // } + // } + + @Override + protected Pair transformToSingleFilter(QueryProcessExecutor exec) + throws QpSelectFromException, QpWhereException { + TSDataType type = exec.getSeriesType(seriesPath); + if (type == null) { + throw new SeriesNotExistException("given path:{" + seriesPath.getFullPath() + + "} don't exist in metadata"); + } + SingleSeriesFilterExpression ret = null; + switch (type) { + case INT32: + ret = + funcToken.getSingleSeriesFilterExpression( + FilterFactory.intFilterSeries(seriesPath.getDeltaObjectToString(), + seriesPath.getMeasurementToString(), FilterSeriesType.VALUE_FILTER), + Integer.valueOf(seriesValue)); + break; + case INT64: + ret = + funcToken.getSingleSeriesFilterExpression( + FilterFactory.longFilterSeries(seriesPath.getDeltaObjectToString(), + seriesPath.getMeasurementToString(), FilterSeriesType.VALUE_FILTER), + Long.valueOf(seriesValue)); + break; + case BOOLEAN: + ret = + funcToken.getSingleSeriesFilterExpression( + FilterFactory.booleanFilterSeries(seriesPath.getDeltaObjectToString(), + seriesPath.getMeasurementToString(), FilterSeriesType.VALUE_FILTER), + Boolean.valueOf(seriesValue)); + break; + case FLOAT: + ret = + funcToken.getSingleSeriesFilterExpression( + FilterFactory.floatFilterSeries(seriesPath.getDeltaObjectToString(), + seriesPath.getMeasurementToString(), FilterSeriesType.VALUE_FILTER), + Float.valueOf(seriesValue)); + break; + case DOUBLE: + ret = + funcToken.getSingleSeriesFilterExpression( + FilterFactory.doubleFilterSeries(seriesPath.getDeltaObjectToString(), + seriesPath.getMeasurementToString(), FilterSeriesType.VALUE_FILTER), + Double.valueOf(seriesValue)); + break; + default: + throw new QpWhereException("unsupported data type:" + type); + } + return new Pair(ret, seriesPath.getFullPath()); + } + + @Override + public String showTree(int spaceNum) { + StringContainer sc = new StringContainer(); + for (int i = 0; i < spaceNum; i++) { + sc.addTail(" "); + } + sc.addTail(seriesPath.toString(), this.tokenSymbol, seriesValue, ", single\n"); + return sc.toString(); + } + + @Override + public BasicFunctionOperator clone() { + BasicFunctionOperator ret; + try { + ret = new BasicFunctionOperator(this.tokenIntType, seriesPath.clone(), seriesValue); + } catch (BasicOperatorException e) { + LOG.error("error clone:{}",e.getMessage()); + return null; + } + ret.tokenSymbol=tokenSymbol; + ret.isLeaf = isLeaf; + ret.isSingle = isSingle; + return ret; + } + + @Override + public String toString() { + return "["+seriesPath.getFullPath()+tokenSymbol+seriesValue+"]"; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/DeleteOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/DeleteOperator.java new file mode 100644 index 00000000000..ecd575171e3 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/DeleteOperator.java @@ -0,0 +1,84 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.LESSTHAN; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.LESSTHANOREQUALTO; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.ParseTimeException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.QpSelectFromException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.physical.plan.DeletePlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * this class extends {@code RootOperator} and process delete statement + * + * @author kangrong + * + */ +public class DeleteOperator extends SFWOperator { + private static Logger LOG = LoggerFactory.getLogger(DeleteOperator.class); + + public DeleteOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.DELETE; + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + DeletePlan delPlan = new DeletePlan(); + // thansform where condition to Filter class + // for update, delete and insert, all where clause has just condition about time + parseDeleteTimeFilter(delPlan); + // parse path + List paths = getSelSeriesPaths(conf); + if (paths.size() != 1) { + throw new QpSelectFromException( + "for delete command, cannot specified more than one path:" + paths); + } + delPlan.setPath(paths.get(0)); + return delPlan; + } + + /** + * for delete command, time should have start and end time range. + * + * @param delPlan + */ + private void parseDeleteTimeFilter(DeletePlan delPlan) throws ParseTimeException { + if (!(filterOperator.isLeaf)) { + // LOG.error("for delete command, where clause must be like : time < XXXX"); + throw new ParseTimeException( + "for delete command, where clause must be like : time < XXX"); + } + + if (filterOperator.getTokenIntType() != LESSTHAN + && filterOperator.getTokenIntType() != LESSTHANOREQUALTO) { + // LOG.error( + // "for delete command, time filter must be less than or less than or equal to, this:{}", + // filterOperator.getTokenIntType()); + // return false; + throw new ParseTimeException( + "for delete command, time filter must be less than or less than or equal to, this:" + + filterOperator.getTokenIntType()); + } + long delTime = Long.valueOf(((BasicFunctionOperator) filterOperator).getSeriesValue()); + + if (delTime < 0) { + // LOG.error("delete Time:{}, time filter error", delTime); + // return false; + throw new ParseTimeException("delete Time:" + delTime + ", time filter error"); + } + delPlan.setDeleteTime(delTime); + } + + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FilterOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FilterOperator.java new file mode 100644 index 00000000000..03c46ed9496 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FilterOperator.java @@ -0,0 +1,262 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_AND; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_OR; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.utils.Pair; +import cn.edu.thu.tsfile.timeseries.filter.definition.FilterExpression; +import cn.edu.thu.tsfile.timeseries.filter.definition.FilterFactory; +import cn.edu.thu.tsfile.timeseries.filter.definition.SingleSeriesFilterExpression; +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.FilterOperatorException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator; + +/** + * This class is for filter operator and implements + * {@link cn.edu.thu.tsfiledb.qp.logical.operator.Operator} .
+ * it may consist of more than two child FilterOperator, but if it's not leaf operator, the relation + * is same among all of its children.(AND or OR). It's identified by tokenType. + * + * @author kangrong + * + */ +public class FilterOperator extends Operator implements Comparable { + Logger LOG = LoggerFactory.getLogger(FilterOperator.class); + // it is the symbol of token. e.g. AND is & and OR is | + protected String tokenSymbol; + + protected List childOperators; + // leaf filter operator means it doesn't have left and right child filterOperator. Leaf filter + // should set FunctionOperator. + protected boolean isLeaf = false; + // isSingle being true means all recursive children of this filter belong to one series path. + protected boolean isSingle = false; + // if isSingle = false, singlePath must be null + protected Path singlePath = null; + + public void addHeadDeltaObjectPath(String deltaObject) { + for (FilterOperator child : childOperators) { + child.addHeadDeltaObjectPath(deltaObject); + } + if(isSingle) + this.singlePath.addHeadPath(deltaObject); + } + + public FilterOperator(int tokenType) { + super(tokenType); + operatorType = OperatorType.FILTER; + childOperators = new ArrayList(); + this.tokenIntType = tokenType; + isLeaf = false; + tokenSymbol = SQLConstant.tokenSymbol.get(tokenType); + } + + public void setTokenIntType(int intType) { + this.tokenIntType = intType; + this.tokenName = SQLConstant.tokenNames.get(tokenIntType); + this.tokenSymbol = SQLConstant.tokenSymbol.get(tokenIntType); + } + + public FilterOperator(int tokenType, boolean isSingle) { + this(tokenType); + this.isSingle = isSingle; + } + + public int getTokenIntType() { + return tokenIntType; + } + + public List getChildren() { + return childOperators; + } + + public void setChildrenList(List children) { + this.childOperators = children; + } + + public void setIsSingle(boolean b) { + this.isSingle = b; + } + + /** + * if this node's singlePath is set, this.isLeaf will be set true in same time + * + * @param p + */ + public void setSinglePath(Path p) { + this.singlePath = p; + } + + public Path getSinglePath() { + return singlePath; + } + + public boolean addChildOPerator(FilterOperator op) { + childOperators.add((FilterOperator) op); + return true; + } + + + /** + * For a filter operator, if isSingle, call transformToSingleFilter.
+ * FilterOperator cannot be leaf. + * + * @return + * @throws QueryProcessorException + */ + public FilterExpression transformToFilter(QueryProcessExecutor conf) + throws QueryProcessorException { + if (isSingle) { + Pair ret = transformToSingleFilter(conf); + return ret.left; + } else { + if (childOperators.isEmpty()) { + throw new FilterOperatorException("this filter is not leaf, but it's empty:" + + tokenIntType); + } + FilterExpression retFilter = childOperators.get(0).transformToFilter(conf); + FilterExpression cross; + for (int i = 1; i < childOperators.size(); i++) { + cross = childOperators.get(i).transformToFilter(conf); + switch (tokenIntType) { + case KW_AND: + retFilter = FilterFactory.and(retFilter, cross); + break; + case KW_OR: + retFilter = FilterFactory.or(retFilter, cross); + break; + default: + throw new FilterOperatorException("unknown binary tokenIntType:" + + tokenIntType + ",maybe it means " + + SQLConstant.tokenNames.get(tokenIntType)); + } + } + return retFilter; + } + } + + /** + * it will be used in BasicFunction Operator + * + * @param exec + * @return - pair.left:SingleSeriesFilterExpression constructed by its one child; - pair.right: Path + * represented by this child. + * @throws QueryProcessorException + */ + protected Pair transformToSingleFilter(QueryProcessExecutor exec) + throws QueryProcessorException { + if (childOperators.isEmpty()) { + throw new FilterOperatorException( + ("transformToSingleFilter: this filter is not leaf, but it's empty:{}" + tokenIntType)); + } + Pair single = + childOperators.get(0).transformToSingleFilter(exec); + SingleSeriesFilterExpression retFilter = single.left; + String childSeriesStr = single.right; + // + for (int i = 1; i < childOperators.size(); i++) { + single = childOperators.get(i).transformToSingleFilter(exec); + if (!childSeriesStr.equals(single.right)) + throw new FilterOperatorException( + ("transformToSingleFilter: paths among children are not inconsistent: one is:" + + childSeriesStr + ",another is:" + single.right)); + switch (tokenIntType) { + case KW_AND: + retFilter = (SingleSeriesFilterExpression) FilterFactory.and(retFilter, single.left); + break; + case KW_OR: + retFilter = (SingleSeriesFilterExpression) FilterFactory.or(retFilter, single.left); + break; + default: + throw new FilterOperatorException("unknown binary tokenIntType:" + + tokenIntType + ",maybe it means " + + SQLConstant.tokenNames.get(tokenIntType)); + } + } + return new Pair(retFilter, childSeriesStr); + } + + /** + * if this is null, ordered to later + */ + @Override + public int compareTo(FilterOperator fil) { + if (singlePath == null && fil.singlePath == null) { + return 0; + } + if (singlePath == null) { + return 1; + } + if (fil.singlePath == null) { + return -1; + } + return fil.singlePath.toString().compareTo(singlePath.toString()); + } + + public boolean isLeaf() { + return isLeaf; + } + + public boolean isSingle() { + return isSingle; + } + + public String showTree() { + return showTree(0); + } + + public String showTree(int spaceNum) { + StringContainer sc = new StringContainer(); + for (int i = 0; i < spaceNum; i++) { + sc.addTail(" "); + } + sc.addTail(this.tokenName); + if (isSingle) { + sc.addTail("[single:", getSinglePath().toString(), "]"); + } + sc.addTail("\n"); + for (FilterOperator filter : childOperators) { + sc.addTail(filter.showTree(spaceNum + 1)); + } + return sc.toString(); + } + + @Override + public String toString() { + StringContainer sc = new StringContainer(); + sc.addTail("[", this.tokenName); + if (isSingle) { + sc.addTail("[single:", getSinglePath().toString(), "]"); + } + sc.addTail(" "); + for (FilterOperator filter : childOperators) { + sc.addTail(filter.toString()); + } + sc.addTail("]"); + return sc.toString(); + } + + @Override + public FilterOperator clone() { + FilterOperator ret = new FilterOperator(this.tokenIntType); + ret.tokenSymbol=tokenSymbol; + ret.isLeaf = isLeaf; + ret.isSingle = isSingle; + if(singlePath != null) + ret.singlePath = singlePath.clone(); + for (FilterOperator filterOperator : this.childOperators) { + ret.addChildOPerator(filterOperator.clone()); + } + return ret; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FromOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FromOperator.java new file mode 100644 index 00000000000..e6657dbc1fd --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FromOperator.java @@ -0,0 +1,60 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.utils.Pair; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.QpSelectFromException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator; + + +/** + * this class maintains information from {@code FROM} clause + * + * @author kangrong + * + */ +public class FromOperator extends Operator { + Logger LOG = LoggerFactory.getLogger(FromOperator.class); + private List prefixList; + + public FromOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.FROM; + prefixList = new ArrayList(); + } + + public void addPrefixTablePath(Path prefixPath) throws QpSelectFromException { +// if(!prefixPath.startWith(SQLConstant.ROOT)) +// throw new QpSelectFromException("given select clause path doesn't start with ROOT!"); + prefixList.add(prefixPath); + } + + // public void addPrefixTablePath(String[] prefixPath) { + // addPrefixTablePath(new StringContainer(prefixPath, SQLConstant.PATH_SEPARATER)); + // } + + public List getPrefixPaths() { + return prefixList; + } + + /** + * {@code Pair} + * + * @return not be null, just empty list + */ + public List> getPathsAndAlias() { + // TODO up to now(2016-11-14), we don't involve alias, thus set alias to null + List> ret = new ArrayList>(); + for (Path path: prefixList) { + ret.add(new Pair(path, null)); + } + return ret; + } + + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FunctionOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FunctionOperator.java new file mode 100644 index 00000000000..29469536633 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/FunctionOperator.java @@ -0,0 +1,54 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.utils.Pair; +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; + +/** + * This class presents series condition which is general(e.g. numerical comparison) or defined by + * user. Function is used for bottom operator.
+ * FunctionOperator has a {@code seriesPath}, and other filter condition. + * + * @author kangrong + * + */ + +public class FunctionOperator extends FilterOperator { + Logger LOG = LoggerFactory.getLogger(FunctionOperator.class); + + public FunctionOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.FUNC; + isLeaf = true; + isSingle = true; + } + + @Override + public boolean addChildOPerator(FilterOperator op) { + LOG.error("cannot add child to leaf FilterOperator, now it's FunctionOperator"); + return false; + } + + + /** + * For function Operator, it just return itself expression and its path. + * + * @param reserveWordsMap + * @return {@code } + */ + public Pair getFilterToStr() { + throw new UnsupportedOperationException(); + } + + /** + * return seriesPath + * + * @return + */ + public String getSeriesPath() { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/GroupByOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/GroupByOperator.java new file mode 100644 index 00000000000..b0b4ef34943 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/GroupByOperator.java @@ -0,0 +1,19 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator; + +/** + * This class is used for GROUP clause(not used up to now). + * + * @since 2016-09-27 16:03:45 + * @author kangrong + * + */ +public class GroupByOperator extends Operator { + + public GroupByOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.GROUPBY; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/InsertOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/InsertOperator.java new file mode 100644 index 00000000000..d70c5b3722c --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/InsertOperator.java @@ -0,0 +1,56 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exception.TSTransformException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.physical.plan.InsertPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * this class extends {@code RootOperator} and process insert statement + * + * @author kangrong + * + */ +public class InsertOperator extends SFWOperator { + private static final Logger LOG = LoggerFactory.getLogger(InsertOperator.class); + private long insertTime; + private String insertValue; + + public InsertOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.INSERT; + } + + + public void setInsertValue(String value) { + insertValue = value; + } + + public void setInsertTime(long time) { + insertTime = Long.valueOf(time); + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + InsertPlan insertPlan = new InsertPlan(); + insertPlan.setTime(insertTime); + // parse value + insertPlan.setValue(insertValue); + // parse path + List paths = getSelSeriesPaths(conf); + if (paths.size() != 1) { + throw new TSTransformException("for insert command, cannot specified more than one path:{}"+ paths); + } + insertPlan.setPath(paths.get(0)); + return insertPlan; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/MultiInsertOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/MultiInsertOperator.java new file mode 100644 index 00000000000..8997598498e --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/MultiInsertOperator.java @@ -0,0 +1,67 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exception.TSTransformException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.physical.plan.InsertPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.MultiInsertPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * this class extends {@code RootOperator} and process insert statement + * + * @author kangrong + * + */ +public class MultiInsertOperator extends SFWOperator { + private static final Logger LOG = LoggerFactory.getLogger(MultiInsertOperator.class); + private long insertTime; + private List measurementList; + private List insertValue; + + + public MultiInsertOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.MULTIINSERT; + } + + public void setInsertTime(long time) { + insertTime = Long.valueOf(time); + } + + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + List paths = getSelSeriesPaths(conf); + if(paths.size() != 1){ + throw new TSTransformException("for MultiInsert command, cannot specified more than one path:{}"+ paths); + } + Path deltaObject = paths.get(0); + MultiInsertPlan multiInsertPlan = new MultiInsertPlan(deltaObject.getFullPath(), insertTime, measurementList, insertValue); + return multiInsertPlan; + } + + public List getMeasurementList() { + return measurementList; + } + + public void setMeasurementList(List measurementList) { + this.measurementList = measurementList; + } + + public List getInsertValue() { + return insertValue; + } + + public void setInsertValue(List insertValue) { + this.insertValue = insertValue; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/QueryOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/QueryOperator.java new file mode 100644 index 00000000000..29962f7a3ec --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/QueryOperator.java @@ -0,0 +1,137 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_AND; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_OR; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.QueryOperatorException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.query.MergeQuerySetPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.query.SeriesSelectPlan; + + +/** + * this class extends {@code RootOperator} and process getIndex statement + * + * @author kangrong + * + */ +public class QueryOperator extends SFWOperator { + private static final Logger LOG = LoggerFactory.getLogger(QueryOperator.class); + + public QueryOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.QUERY; + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + List paths = getSelSeriesPaths(conf); + String aggregation = selectOperator.getAggregation(); + if(aggregation != null) + conf.addParameter(SQLConstant.IS_AGGREGATION, aggregation); + ArrayList subPlans = new ArrayList(); + if (filterOperator == null) { + subPlans.add(new SeriesSelectPlan(paths, null, null, null, conf)); + } + else{ + List parts = splitFilter(); + for (FilterOperator filterOperator : parts) { + SeriesSelectPlan plan = constructSelectPlan(filterOperator, paths, conf); + if (plan != null) + subPlans.add(plan); + } + } + return new MergeQuerySetPlan(subPlans); + } + + private SeriesSelectPlan constructSelectPlan(FilterOperator filterOperator, List paths, + QueryProcessExecutor conf) throws QueryProcessorException { + FilterOperator timeFilter = null; + FilterOperator freqFilter = null; + FilterOperator valueFilter = null; + FilterOperator deltaObjectFilterOperator = null; + List singleFilterList; + if (filterOperator.isSingle) { + singleFilterList = new ArrayList(); + singleFilterList.add(filterOperator); + } else if (filterOperator.getTokenIntType() == KW_AND) { + // now it has been dealt with merge optimizer, thus all nodes with same path have been + // merged to one node + singleFilterList = filterOperator.childOperators; + } else { + throw new QueryOperatorException( + "for one tasks, filter cannot be OR if it's not single"); + } + List valueList = new ArrayList(); + Map deltaMeasurementMap = new HashMap(); + for (FilterOperator child : singleFilterList) { + if (!child.isSingle) { + throw new QueryOperatorException( + "in format:[(a) and () and ()] or [] or [], a is not single! a:" + child); + } + switch (child.singlePath.toString()) { + case SQLConstant.RESERVED_TIME: + if (timeFilter != null) { + throw new QueryOperatorException( + "time filter has been specified more than once"); + } + timeFilter = child; + break; + case SQLConstant.RESERVED_FREQ: + if (freqFilter != null) { + throw new QueryOperatorException( + "freq filter has been specified more than once"); + } + freqFilter = child; + break; + case SQLConstant.RESERVED_DELTA_OBJECT: + if (deltaObjectFilterOperator != null) { + throw new QueryOperatorException( + "delta object filter has been specified more than once"); + } + deltaObjectFilterOperator = child; + break; + default: + valueList.add(child); + break; + } + } + if (valueList.size() == 1) { + valueFilter = valueList.get(0); + } else if (valueList.size() > 1) { + valueFilter = new FilterOperator(KW_AND, false); + valueFilter.childOperators = valueList; + } + + return new SeriesSelectPlan(paths, deltaObjectFilterOperator, timeFilter, freqFilter, valueFilter, conf); + } + + /** + * split filter operator to a list of filter with relation of "or" each other. + * + * @return + */ + private List splitFilter() { + List ret = new ArrayList(); + if (filterOperator.isSingle || filterOperator.getTokenIntType() != KW_OR) { + // single or leaf(BasicFunction) + ret.add(filterOperator); + return ret; + } + // a list of partion linked with or + return filterOperator.childOperators; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/SFWOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/SFWOperator.java new file mode 100644 index 00000000000..9c4f613fcd5 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/SFWOperator.java @@ -0,0 +1,101 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.QpSelectFromException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.RootOperator; + +/** + * SFWOperator includes four subclass: INSERT,DELETE,UPDATE,QUERY. All of these four statements has + * three partition: select clause, from clause and filter clause(where clause). + * + * @author kangrong + * + */ +public abstract class SFWOperator extends RootOperator { + private static final Logger LOG = LoggerFactory.getLogger(SFWOperator.class); + + protected SelectOperator selectOperator; + protected FromOperator fromOperator; + protected FilterOperator filterOperator; + + public SFWOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.ROOT; + } + + // /** + // * transform this root operator tree to a physical plan tree.Node that, before this method + // * called, the where filter has been dealt with + // * {@linkplain com.corp.tsfile.qp.logical.optimizer.filter.MergeSingleFilterOptimizer} + // * + // */ + // public abstract PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + // throws QueryProcessorException; + + public void setSelectOperator(SelectOperator sel) { + this.selectOperator = sel; + } + + public void setFromOperator(FromOperator from) { + this.fromOperator = from; + } + + public FromOperator getFrom() { + return fromOperator; + } + + public SelectOperator getSelect() { + return selectOperator; + } + + public void setFilterOperator(FilterOperator filter) { + this.filterOperator = filter; + } + + public FilterOperator getFilter() { + return filterOperator; + } + + /** + * get information from SelectOperator and FromOperator and generate all table paths. Note + * that, if there are some path doesn't exist in metadata tree or file metadata, this method + * just log error records and omit them. Nevertheless, if all of paths doesn't exist, it + * will throw Exception. + * + * @return - a list of path + * @throws QpSelectFromException + */ + public List getSelSeriesPaths(QueryProcessExecutor qpConfig) throws QpSelectFromException { + List prefixPaths = null; + if (fromOperator != null) { + prefixPaths = fromOperator.getPrefixPaths(); + // check legality of from clauses + if (!qpConfig.isSingleFile()) { + for (Path path : prefixPaths) { + if (!path.startWith(SQLConstant.ROOT)) + throw new QpSelectFromException( + "given select clause path doesn't start with ROOT!" + path); + } + } + } + // after ConcatPathOptimizer, paths in FROM clause are just used to check legality for delta + // system + List suffixPaths = null; + if (selectOperator != null) + suffixPaths = selectOperator.getSuffixPaths(); + if ((suffixPaths == null || suffixPaths.isEmpty())) { + // Log.error("from clause and select clause cannot be both empty!"); + throw new QpSelectFromException("select clause cannot be empty!"); + } + else + return suffixPaths; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/SelectOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/SelectOperator.java new file mode 100644 index 00000000000..ead0fd472f3 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/SelectOperator.java @@ -0,0 +1,49 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator; + +/** + * this class maintains information from select clause + * + * @author kangrong + * + */ +public final class SelectOperator extends Operator { + private List suffixList; + private String aggregation; + public SelectOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.SELECT; + suffixList = new ArrayList<>(); + } + + public void addSuffixTablePath(Path suffixPath) { + suffixList.add(suffixPath); + } + + public void addSuffixTablePath(Path suffixPath, String aggregation) { + suffixList.add(suffixPath); + this.aggregation = aggregation; + } + + public String getAggregation(){ + return this.aggregation; + } + + public void setSuffixPathList(List suffixPaths) { + suffixList = suffixPaths; + } + +// public void addSuffixTablePath(String[] suffixPath) { +// addSuffixTablePath(new StringContainer(suffixPath, SQLConstant.PATH_SEPARATER)); +// } + + public List getSuffixPaths() { + return suffixList; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/UpdateOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/UpdateOperator.java new file mode 100644 index 00000000000..fc9d719d2e1 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/crud/UpdateOperator.java @@ -0,0 +1,119 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.crud; + +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.GREATERTHAN; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.GREATERTHANOREQUALTO; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.LESSTHAN; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.LESSTHANOREQUALTO; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.RESERVED_TIME; + +import java.util.List; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.BasicOperatorException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.ParseTimeException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.QpSelectFromException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.UpdatePlan; + +/** + * this class extends {@code RootOperator} and process update statement + * + * @author kangrong + * + */ +public final class UpdateOperator extends SFWOperator { + private String value; + + public UpdateOperator(int tokenIntType) { + super(tokenIntType); + operatorType = OperatorType.UPDATE; + } + + public void setUpdateValue(String value) throws BasicOperatorException { + this.value = value; + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + UpdatePlan upPlan = new UpdatePlan(); + // thansform where condition to Filter class + // for update, delete and insert, all where clause has just condition about time + parseUpdateTimeFilter(upPlan); + // parse value + upPlan.setValue(value); + // parse path + List paths = getSelSeriesPaths(conf); + if (paths.size() != 1) { + throw new QpSelectFromException("update command, must have and only have one path:" + + paths); + // LOG.error("for update command, cannot specified more than one path:{}", paths); + } + upPlan.setPath(paths.get(0)); + return upPlan; + } + + /** + * for udpate command, time should have start and end time range. + * + * @param upPlan + */ + private void parseUpdateTimeFilter(UpdatePlan upPlan) throws ParseTimeException { + if (!filterOperator.isSingle || !filterOperator.getSinglePath().equals(RESERVED_TIME)) { + throw new ParseTimeException( + "for update command, it has non-time condition in where clause"); + } + if (filterOperator.childOperators.size() != 2) + throw new ParseTimeException( + "for update command, time must have left and right boundaries"); + FilterOperator leftOp = filterOperator.childOperators.get(0); + FilterOperator rightOp = filterOperator.childOperators.get(1); + if (!leftOp.isLeaf || !rightOp.isLeaf) + throw new ParseTimeException("illegal time condition:" + filterOperator.showTree()); + long startTime = -1; + long endTime = -1; + // left time border + + if (leftOp.getTokenIntType() == LESSTHAN || leftOp.getTokenIntType() == LESSTHANOREQUALTO) { + endTime = Long.valueOf(((BasicFunctionOperator) leftOp).getSeriesValue()); + } else if (leftOp.getTokenIntType() == GREATERTHAN + || leftOp.getTokenIntType() == GREATERTHANOREQUALTO) { + startTime = Long.valueOf(((BasicFunctionOperator) leftOp).getSeriesValue()); + } + if(leftOp.getTokenIntType() == LESSTHAN){ + endTime --; + } + if(leftOp.getTokenIntType() == GREATERTHAN && startTime < Long.MAX_VALUE){ + startTime ++; + } + // right time border + if (rightOp.getTokenIntType() == LESSTHAN || rightOp.getTokenIntType() == LESSTHANOREQUALTO) { + endTime = Long.valueOf(((BasicFunctionOperator) rightOp).getSeriesValue()); + } else if (rightOp.getTokenIntType() == GREATERTHAN + || rightOp.getTokenIntType() == GREATERTHANOREQUALTO) { + startTime = Long.valueOf(((BasicFunctionOperator) rightOp).getSeriesValue()); + } + if(rightOp.getTokenIntType() == LESSTHAN){ + endTime --; + } + if(rightOp.getTokenIntType() == GREATERTHAN && startTime < Long.MAX_VALUE){ + startTime ++; + } + + if (startTime < 0 || endTime < 0) { + // LOG.error("startTime:{},endTime:{}, one of them is illegal", startTime, endTime); + throw new ParseTimeException("startTime:" + startTime + ",endTime:" + endTime + + ", one of them is illegal"); + } + if (startTime > endTime) { + // LOG.error("startTime:{},endTime:{}, start time cannot be greater than end time", + // startTime, endTime); + throw new ParseTimeException("startTime:" + startTime + ",endTime:" + endTime + + ", start time cannot be greater than end time"); + } + upPlan.setStartTime(startTime); + upPlan.setEndTime(endTime); + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/load/LoadDataOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/load/LoadDataOperator.java new file mode 100644 index 00000000000..606d653854c --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/load/LoadDataOperator.java @@ -0,0 +1,40 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.load; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.RootOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.SFWOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.LoadDataPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * this class maintains information in Author statement, including CREATE, DROP, GRANT and REVOKE + * + * @author kangrong + * + */ +public class LoadDataOperator extends RootOperator { + private final String inputFilePath; + private final String measureType; + + public LoadDataOperator(int tokenIntType, String inputFilePath, String measureType) { + super(tokenIntType); + operatorType = OperatorType.LOADDATA; + this.inputFilePath = inputFilePath; + this.measureType = measureType; + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + return new LoadDataPlan(inputFilePath, measureType); + } + + public String getInputFilePath() { + return inputFilePath; + } + + public String getMeasureType() { + return measureType; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/metadata/MetadataOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/metadata/MetadataOperator.java new file mode 100644 index 00000000000..a6c0b0d76b9 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/metadata/MetadataOperator.java @@ -0,0 +1,76 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.metadata; + +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.RootOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.metadata.MetadataPlan; + +/** + * this class maintains information in Metadata.namespace statement + * + * @author kangrong + * + */ +public class MetadataOperator extends RootOperator { + + public MetadataOperator(int tokenIntType, NamespaceType type) { + super(tokenIntType); + namespaceType = type; + operatorType = OperatorType.METADATA; + } + + private final NamespaceType namespaceType; + private Path path; + private String dataType; + private String encoding; + private String[] encodingArgs; + + + public Path getPath() { + return path; + } + + public void setPath(Path path) { + this.path = path; + } + + public String getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = dataType; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public String[] getEncodingArgs() { + return encodingArgs; + } + + public void setEncodingArgs(String[] encodingArgs) { + this.encodingArgs = encodingArgs; + } + + public NamespaceType getNamespaceType() { + return namespaceType; + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + return new MetadataPlan(namespaceType, path, dataType, encoding, encodingArgs); + } + + public static enum NamespaceType { + ADD_PATH, DELETE_PATH, SET_FILE_LEVEL + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/metadata/PropertyOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/metadata/PropertyOperator.java new file mode 100644 index 00000000000..54ebcd24208 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/metadata/PropertyOperator.java @@ -0,0 +1,57 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.metadata; + +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.RootOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.metadata.PropertyPlan; + +/** + * this class maintains information in Metadata.namespace statement + * + * @author kangrong + * + */ +public class PropertyOperator extends RootOperator { + + public PropertyOperator(int tokenIntType, PropertyType type) { + super(tokenIntType); + propertyType = type; + operatorType = OperatorType.PROPERTY; + } + + private final PropertyType propertyType; + private Path propertyPath; + private Path metadataPath; + + public Path getPropertyPath() { + return propertyPath; + } + + public void setPropertyPath(Path propertyPath) { + this.propertyPath = propertyPath; + } + + public Path getMetadataPath() { + return metadataPath; + } + + public void setMetadataPath(Path metadataPath) { + this.metadataPath = metadataPath; + } + + public PropertyType getPropertyType() { + return propertyType; + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) + throws QueryProcessorException { + return new PropertyPlan(propertyType, propertyPath, metadataPath); + } + + public static enum PropertyType { + ADD_TREE, ADD_PROPERTY_LABEL, DELETE_PROPERTY_LABEL, ADD_PROPERTY_TO_METADATA,DEL_PROPERTY_FROM_METADATA + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/sys/FlushOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/sys/FlushOperator.java new file mode 100644 index 00000000000..36874062878 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/sys/FlushOperator.java @@ -0,0 +1,21 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.sys; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.RootOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.SFWOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +public class FlushOperator extends RootOperator{ + + public FlushOperator(int tokenIntType) { + super(tokenIntType); + // TODO Auto-generated constructor stub + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) throws QueryProcessorException { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/sys/MergeOperator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/sys/MergeOperator.java new file mode 100644 index 00000000000..a47b3591d09 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/operator/sys/MergeOperator.java @@ -0,0 +1,21 @@ +package cn.edu.thu.tsfiledb.qp.logical.operator.sys; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.RootOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.SFWOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +public class MergeOperator extends RootOperator{ + + public MergeOperator(int tokenIntType) { + super(tokenIntType); + // TODO Auto-generated constructor stub + } + + @Override + public PhysicalPlan transformToPhysicalPlan(QueryProcessExecutor conf) throws QueryProcessorException { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/ConcatPathOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/ConcatPathOptimizer.java new file mode 100644 index 00000000000..970c47b073b --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/ConcatPathOptimizer.java @@ -0,0 +1,138 @@ +package cn.edu.thu.tsfiledb.qp.logical.optimizer; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.utils.Pair; +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.logical.optimize.PathConcatException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.BasicFunctionOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.FilterOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.FromOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.SFWOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.SelectOperator; + + + +/** + * This class deals with delta object in union table + * + * @author kangrong + * + */ +public class ConcatPathOptimizer implements ILogicalOptimizer { + private static final Logger LOG = LoggerFactory.getLogger(ConcatPathOptimizer.class); + + @Override + public Operator transform(Operator context) throws PathConcatException { + if (!(context instanceof SFWOperator)) { + LOG.warn("given operator isn't SFWOperator, cannot concat path"); + return context; + } + SFWOperator sfwOperator = (SFWOperator) context; + FromOperator from = sfwOperator.getFrom(); + List> prefixPathPairs; + if (from == null || (prefixPathPairs = from.getPathsAndAlias()).isEmpty()) { + LOG.warn("given SFWOperator doesn't have prefix paths, cannot concat path"); + return context; + } + SelectOperator select = sfwOperator.getSelect(); + List suffixPaths; + if (select == null || (suffixPaths = select.getSuffixPaths()).isEmpty()) { + LOG.warn("given SFWOperator doesn't have suffix paths, cannot concat path"); + return context; + } + // concat select paths + suffixPaths = concatSelect(prefixPathPairs, suffixPaths); + select.setSuffixPathList(suffixPaths); + // concat filter + FilterOperator filter = sfwOperator.getFilter(); + if (filter == null) + return context; + concatFilter(prefixPathPairs, filter); + // sfwOperator.setFilterOperator(filter); + return sfwOperator; + } + + + private List concatSelect(List> fromPaths, List selectPaths) + throws PathConcatException { + if (fromPaths.size() == 1) { + Pair fromPair = fromPaths.get(0); + for (Path path : selectPaths) { + if (path.startWith(fromPair.right)) { + // replace alias to namespace path starting with ROOT + path.replace(fromPair.right, fromPair.left); + } else if (!path.startWith(fromPair.left)) { + // add prefix root path + path.addHeadPath(fromPair.left); + } + } + } else { + for (Path selectPath : selectPaths) { + boolean legal = false; + for (Pair fromPair : fromPaths) { + if (selectPath.startWith(fromPair.right)) { + // replace alias to namespace path starting with ROOT + selectPath.replace(fromPair.right, fromPair.left); + legal = true; + break; + } else if (selectPath.startWith(fromPair.left)) { + // do nothing, mark legal + legal = true; + break; + } + } + if (!legal) { + throw new PathConcatException("select path is illegal:" + selectPath); + } + } + } + return selectPaths; + } + + private void concatFilter(List> fromPaths, FilterOperator filter) + throws PathConcatException { + if (!filter.isLeaf()) { + for (FilterOperator child : filter.getChildren()) + concatFilter(fromPaths, child); + return; + } + BasicFunctionOperator basic = (BasicFunctionOperator) filter; + Path selectPath = basic.getSinglePath(); + if (SQLConstant.isReservedPath(selectPath)) + return; + if (fromPaths.size() == 1) { + Pair fromPair = fromPaths.get(0); + if (selectPath.startWith(fromPair.right)) { + // replace alias to namespace path starting with ROOT + selectPath.replace(fromPair.right, fromPair.left); + } else if (!selectPath.startWith(fromPair.left)) { + // add prefix root path + selectPath.addHeadPath(fromPair.left); + } + + } else { + boolean legal = false; + for (Pair fromPair : fromPaths) { + if (selectPath.startWith(fromPair.right)) { + // replace alias to namespace path starting with ROOT + selectPath.replace(fromPair.right, fromPair.left); + legal = true; + break; + } else if (selectPath.startWith(fromPair.left)) { + // do nothing, mark legal + legal = true; + break; + } + } + if (!legal) { + throw new PathConcatException("select path is illegal:" + selectPath); + } + } + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/ILogicalOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/ILogicalOptimizer.java new file mode 100644 index 00000000000..f2cf0ff0077 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/ILogicalOptimizer.java @@ -0,0 +1,21 @@ +package cn.edu.thu.tsfiledb.qp.logical.optimizer; + +import cn.edu.thu.tsfiledb.qp.exception.logical.optimize.LogicalOptimizeException; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator; + + +/** + * provide a context, transform it for optimization. + * + * @author kangrong + * + */ +public interface ILogicalOptimizer { + /** + * input a TSPlanContext and + * + * @param context + * @return + */ + public Operator transform(Operator context) throws LogicalOptimizeException; +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/NoneLogicalOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/NoneLogicalOptimizer.java new file mode 100644 index 00000000000..09d9211ce66 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/NoneLogicalOptimizer.java @@ -0,0 +1,18 @@ +package cn.edu.thu.tsfiledb.qp.logical.optimizer; + +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator; + +/** + * This class do nothing for an input TSPlanContext. + * + * @author kangrong + * + */ +public class NoneLogicalOptimizer implements ILogicalOptimizer { + + @Override + public Operator transform(Operator context) { + return context; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/DNFFilterOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/DNFFilterOptimizer.java new file mode 100644 index 00000000000..21fbcd0dc9c --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/DNFFilterOptimizer.java @@ -0,0 +1,145 @@ +package cn.edu.thu.tsfiledb.qp.logical.optimizer.filter; + +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_AND; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_OR; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfiledb.qp.exception.logical.optimize.DNFOptimizeException; +import cn.edu.thu.tsfiledb.qp.exception.logical.optimize.LogicalOptimizeException; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.FilterOperator; + +public class DNFFilterOptimizer implements IFilterOptimizer { + private static final Logger LOG = LoggerFactory.getLogger(DNFFilterOptimizer.class); + + + /** + * get DNF(disjunctive normal form) for this filter operator tree. Before getDNF, this op tree + * must be binary, in another word, each non-leaf node has exactly two children. + * + * @return + * @throws LogicalOptimizeException + */ + @Override + public FilterOperator optimize(FilterOperator filter) throws LogicalOptimizeException { + return getDNF(filter); + } + + private FilterOperator getDNF(FilterOperator filter) throws DNFOptimizeException { + if (filter.isLeaf()) + return filter; + List childOperators = filter.getChildren(); + if (childOperators.size() != 2) { + throw new DNFOptimizeException("node :" + filter.getTokenName() + " has " + + childOperators.size() + " childrean"); + + } + FilterOperator left = getDNF(childOperators.get(0)); + FilterOperator right = getDNF(childOperators.get(1)); + List newChildrenList = new ArrayList(); + switch (filter.getTokenIntType()) { + case KW_OR: + addChildOpInOr(left, newChildrenList); + addChildOpInOr(right, newChildrenList); + break; + case KW_AND: + if (left.getTokenIntType() != KW_OR && right.getTokenIntType() != KW_OR) { + addChildOpInAnd(left, newChildrenList); + addChildOpInAnd(right, newChildrenList); + } else { + List leftAndChildren = getAndChild(left); + List rightAndChildren = getAndChild(right); + for (FilterOperator laChild : leftAndChildren) { + for (FilterOperator raChild : rightAndChildren) { + FilterOperator r = mergeToConjunction(laChild.clone(), raChild.clone()); + newChildrenList.add(r); + } + } + filter.setTokenIntType(KW_OR); + } + break; + default: + throw new DNFOptimizeException("get DNF failed, this tokenType is:" + + filter.getTokenIntType()); + } + filter.setChildrenList(newChildrenList); + return filter; + } + + /** + * used by getDNF. merge two conjunction filter operators into a conjunction.
+ * conjunction operator consists of {@code FunctionOperator} and inner operator which token is + * KW_AND.
+ * e.g. (a and b) merge (c) is (a and b and c) + * + * @param b + * @return + * @throws DNFOptimizeException + */ + private FilterOperator mergeToConjunction(FilterOperator a, FilterOperator b) + throws DNFOptimizeException { + List retChildrenList = new ArrayList(); + addChildOpInAnd(a, retChildrenList); + addChildOpInAnd(b, retChildrenList); + FilterOperator ret = new FilterOperator(KW_AND, false); + ret.setChildrenList(retChildrenList); + return ret; + } + + /** + * used by getDNF. get conjunction node.
+ * If child is basic function or AND node, return a list just containing this.
+ * If this child is OR, return children of OR. + * + * @param child + * @return + */ + private List getAndChild(FilterOperator child) { + switch (child.getTokenIntType()) { + case KW_OR: + return child.getChildren(); + default: + // other token type means leaf node or and + List ret = new ArrayList(); + ret.add(child); + return ret; + } + } + + /** + * used by getDNF + * + * @param child + * @param newChildrenList + * @throws LogicalOptimizeException + */ + private void addChildOpInAnd(FilterOperator child, List newChildrenList) + throws DNFOptimizeException { + if (child.isLeaf()) + newChildrenList.add(child); + else if (child.getTokenIntType() == KW_AND) + newChildrenList.addAll(child.getChildren()); + else { + throw new DNFOptimizeException( + "add all children of an OR operator to newChildrenList in AND"); + } + } + + /** + * used by getDNF + * + * @param child + * @param newChildrenList + */ + private void addChildOpInOr(FilterOperator child, List newChildrenList) { + if (child.isLeaf() || child.getTokenIntType() == KW_AND) + newChildrenList.add(child); + else + newChildrenList.addAll(child.getChildren()); + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/IFilterOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/IFilterOptimizer.java new file mode 100644 index 00000000000..be06c08c9cd --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/IFilterOptimizer.java @@ -0,0 +1,16 @@ +package cn.edu.thu.tsfiledb.qp.logical.optimizer.filter; + +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.FilterOperator; + + + +/** + * provide a filter operator, optimize it. + * + * @author kangrong + * + */ +public interface IFilterOptimizer { + public FilterOperator optimize(FilterOperator filter) throws QueryProcessorException; +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/MergeSingleFilterOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/MergeSingleFilterOptimizer.java new file mode 100644 index 00000000000..00d12db8c08 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/MergeSingleFilterOptimizer.java @@ -0,0 +1,134 @@ +package cn.edu.thu.tsfiledb.qp.logical.optimizer.filter; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfiledb.qp.exception.logical.optimize.MergeFilterException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.FilterOperator; + +public class MergeSingleFilterOptimizer implements IFilterOptimizer { + Logger LOG = LoggerFactory.getLogger(MergeSingleFilterOptimizer.class); + + @Override + public FilterOperator optimize(FilterOperator filter) { + try { + mergeSamePathFilter(filter); + } catch (MergeFilterException e) { + LOG.error(e.getMessage()); + e.printStackTrace(); + } + return filter; + } + + /** + * + * merge and extract node with same Path recursively.
+ * If a node has more than two children and some children has same paths, remove them from this + * node and merge them to a new single node, then add the new node to this children list.
+ * if all recursive children of this node have same path, set this node to single node, and + * return the same path, otherwise, throw exception; + * + * @param children - children is not empty. + * + * @return - if all recursive children of this node have same path, set this node to single + * node, and return the same path, otherwise, throw exception; + */ + public Path mergeSamePathFilter(FilterOperator src) throws MergeFilterException { + if (src.isLeaf()) + return src.getSinglePath(); + List children = src.getChildren(); + if (children.isEmpty()) { + throw new MergeFilterException("this inner filter has no children!"); + } + if (children.size() == 1) { + throw new MergeFilterException("this inner filter has just one child!"); + } + Path childPath = mergeSamePathFilter(children.get(0)); + Path tempPath; + for (int i = 1; i < children.size(); i++) { + tempPath = mergeSamePathFilter(children.get(i)); + // if one of children differs with others or is not single node(path = null), src's path + // is null + if (tempPath != null && !tempPath.equals(childPath)) + childPath = null; + } + if (childPath != null) { + src.setIsSingle(true); + src.setSinglePath(childPath.clone()); + return childPath; + } + // extract same node + Collections.sort(children); + List ret = new ArrayList(); + + List tempExtrNode = null; + int i; + for (i = 0; i < children.size(); i++) { + tempPath = children.get(i).getSinglePath(); + // sorted by path, all "null" paths are at last + if (tempPath == null) { + // childPath = null; + break; + } + if (childPath == null) { + // first child to be add + childPath = tempPath; + tempExtrNode = new ArrayList(); + tempExtrNode.add(children.get(i)); + } else if (childPath.equals(tempPath)) { + // successive next single child with same path,merge it with previous children + tempExtrNode.add(children.get(i)); + } else { + // not more same, add exist nodes in tempExtrNode into a new node + // prevent make a node which has only one child. + if (tempExtrNode.size() == 1) { + ret.add(tempExtrNode.get(0)); + // use exist Object directly for efficiency + tempExtrNode.set(0, children.get(i)); + childPath = tempPath; + } else { + // add a new inner node + FilterOperator newFil = new FilterOperator(src.getTokenIntType(), true); + newFil.setSinglePath(childPath.clone()); + newFil.setChildrenList(tempExtrNode); + ret.add(newFil); + tempExtrNode = new ArrayList(); + tempExtrNode.add(children.get(i)); + childPath = tempPath; + } + } + } + // the last several children before null has not been added to ret list. + if (childPath != null) { + if (tempExtrNode.size() == 1) { + ret.add(tempExtrNode.get(0)); + } else { + // add a new inner node + FilterOperator newFil = new FilterOperator(src.getTokenIntType(), true); + newFil.setSinglePath(childPath.clone()); + newFil.setChildrenList(tempExtrNode); + ret.add(newFil); + } + } + // add last null children + for (; i < children.size(); i++) { + ret.add(children.get(i)); + } + if (ret.size() == 1) { + // all children have same path, which means this src node is a single node + src.setIsSingle(true); + src.setSinglePath(childPath.clone()); + src.setChildrenList(ret.get(0).getChildren()); + return childPath; + } else { + src.setIsSingle(false); + src.setChildrenList(ret); + return null; + } + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/RemoveNotOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/RemoveNotOptimizer.java new file mode 100644 index 00000000000..2adcacf76e7 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/logical/optimizer/filter/RemoveNotOptimizer.java @@ -0,0 +1,91 @@ +package cn.edu.thu.tsfiledb.qp.logical.optimizer.filter; + +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_AND; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_NOT; +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.KW_OR; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfiledb.qp.exception.logical.operator.BasicOperatorException; +import cn.edu.thu.tsfiledb.qp.exception.logical.optimize.LogicalOptimizeException; +import cn.edu.thu.tsfiledb.qp.exception.logical.optimize.RemoveNotException; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.BasicFunctionOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.FilterOperator; + +public class RemoveNotOptimizer implements IFilterOptimizer { + private static final Logger LOG = LoggerFactory.getLogger(RemoveNotOptimizer.class); + + + /** + * get DNF(disjunctive normal form) for this filter operator tree. Before getDNF, this op tree + * must be binary, in another word, each non-leaf node has exactly two children. + * + * @return + * @throws LogicalOptimizeException + */ + @Override + public FilterOperator optimize(FilterOperator filter) throws LogicalOptimizeException { + return removeNot(filter); + } + + private FilterOperator removeNot(FilterOperator filter) throws RemoveNotException { + if (filter.isLeaf()) + return filter; + int tokenInt = filter.getTokenIntType(); + switch (tokenInt) { + case KW_AND: + case KW_OR: + // replace children in-place for efficiency + List children = filter.getChildren(); + children.set(0, removeNot(children.get(0))); + children.set(1, removeNot(children.get(1))); + return filter; + case KW_NOT: + return reverseFilter(filter.getChildren().get(0)); + default: + throw new RemoveNotException("Unknown token in removeNot: " + tokenInt + "," + + SQLConstant.tokenNames.get(tokenInt)); + } + } + + /** + * reverse given filter to reversed expression + * + * @param filter + * @return + * @throws QueryProcessorException + */ + private FilterOperator reverseFilter(FilterOperator filter) throws RemoveNotException { + int tokenInt = filter.getTokenIntType(); + if (filter.isLeaf()) { + try { + ((BasicFunctionOperator) filter).setReversedTokenIntType(); + } catch (BasicOperatorException e) { + throw new RemoveNotException( + "convert BasicFuntion to reserved meet failed: previous token:" + tokenInt + + "tokenName:" + SQLConstant.tokenNames.get(tokenInt)); + } + return filter; + } + switch (tokenInt) { + case KW_AND: + case KW_OR: + List children = filter.getChildren(); + children.set(0, reverseFilter(children.get(0))); + children.set(1, reverseFilter(children.get(1))); + filter.setTokenIntType(SQLConstant.reverseWords.get(tokenInt)); + return filter; + case KW_NOT: + return removeNot(filter.getChildren().get(0)); + default: + throw new RemoveNotException("Unknown token in reverseFilter: " + tokenInt + "," + + SQLConstant.tokenNames.get(tokenInt)); + } + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/IPhysicalOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/IPhysicalOptimizer.java new file mode 100644 index 00000000000..c11db9023b3 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/IPhysicalOptimizer.java @@ -0,0 +1,15 @@ +package cn.edu.thu.tsfiledb.qp.physical.optimizer; + +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + + +/** + * this class is used for optimizing operator tree in physical layer. + * + * @author kangrong + * + */ +public interface IPhysicalOptimizer { + public PhysicalPlan transform(PhysicalPlan context, QueryProcessExecutor conf); +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/NonePhycicalOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/NonePhycicalOptimizer.java new file mode 100644 index 00000000000..dce85781000 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/NonePhycicalOptimizer.java @@ -0,0 +1,20 @@ +package cn.edu.thu.tsfiledb.qp.physical.optimizer; + +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + + + +/** + * This class do nothing for an input TSPlanContext. + * + * @author kangrong + * + */ +public class NonePhycicalOptimizer implements IPhysicalOptimizer { + + @Override + public PhysicalPlan transform(PhysicalPlan context, QueryProcessExecutor conf) { + return context; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/UnionTableOptimizer.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/UnionTableOptimizer.java new file mode 100644 index 00000000000..ce2ff0bcbdd --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/optimizer/UnionTableOptimizer.java @@ -0,0 +1,107 @@ +package cn.edu.thu.tsfiledb.qp.physical.optimizer; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.constant.QueryConstant; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.constant.SQLConstant; +import cn.edu.thu.tsfiledb.qp.exception.logical.optimize.MergeFilterException; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.BasicFunctionOperator; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.FilterOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.query.MergeQuerySetPlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.query.SeriesSelectPlan; + + + +/** + * This class deals with delta object in union table + * + * @author kangrong + * + */ +public class UnionTableOptimizer implements IPhysicalOptimizer { + private static final Logger LOG = LoggerFactory.getLogger(UnionTableOptimizer.class); + private MergeQuerySetPlan plan; + + @Override + public PhysicalPlan transform(PhysicalPlan plan, QueryProcessExecutor conf) { + MergeQuerySetPlan mergePlan = (MergeQuerySetPlan) plan; + ArrayList alldeltaObjects = (ArrayList)conf.getParameter(QueryConstant.ALL_DEVICES); + + for (SeriesSelectPlan seriesPlan : mergePlan.getSelectPlans()) { + List newPlans = new ArrayList<>(); + Set selectDeltaObjects = mergeDeltaObject(seriesPlan.getDeltaObjectFilterOperator()); + + ArrayList actualDeltaObjects = new ArrayList<>(); + //if select deltaObject, then match with measurement + if(selectDeltaObjects != null && selectDeltaObjects.size() >= 1) { + actualDeltaObjects.addAll(selectDeltaObjects); + } else { + actualDeltaObjects.addAll(alldeltaObjects); + } + + FilterOperator timeFilter = seriesPlan.getTimeFilterOperator(); + FilterOperator freqFilter = seriesPlan.getFreqFilterOperator(); + FilterOperator valueFilter = seriesPlan.getValueFilterOperator(); + List paths = seriesPlan.getPaths(); + + for(String deltaObject: actualDeltaObjects) { + List newPaths = new ArrayList<>(); + for(Path path: paths) { + Path newPath = new Path(deltaObject + "." + path.getFullPath()); + newPaths.add(newPath); + } + SeriesSelectPlan newSeriesPlan; + if(valueFilter == null) { + newSeriesPlan = new SeriesSelectPlan(newPaths, timeFilter, freqFilter, null,conf); + } else { + FilterOperator newValueFilter = valueFilter.clone(); + newValueFilter.addHeadDeltaObjectPath(deltaObject); + newSeriesPlan = new SeriesSelectPlan(newPaths, timeFilter, freqFilter, newValueFilter,conf); + } + newPlans.add(newSeriesPlan); + } + mergePlan.setSelectPlans(newPlans); + } + return mergePlan; + } + + public Set mergeDeltaObject(FilterOperator deltaFilterOperator) { + if (deltaFilterOperator == null) { + System.out.println("deltaFilterOperator is null"); + return null; + } + if (deltaFilterOperator.isLeaf()) { + Set r = new HashSet(); + r.add(((BasicFunctionOperator)deltaFilterOperator).getSeriesValue()); + return r; + } + List children = deltaFilterOperator.getChildren(); + if (children.isEmpty()) { + return new HashSet(); + } + Set ret = mergeDeltaObject(children.get(0)); + for (int i = 1; i < children.size(); i++) { + Set temp = mergeDeltaObject(children.get(i)); + switch (deltaFilterOperator.getTokenIntType()) { + case SQLConstant.KW_AND: + ret.retainAll(temp); + break; + case SQLConstant.KW_OR: + ret.addAll(temp); + break; + default: + throw new UnsupportedOperationException("given error token type:"+deltaFilterOperator.getTokenIntType()); + } + } + return ret; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/AuthorPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/AuthorPlan.java new file mode 100644 index 00000000000..bb6d549327d --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/AuthorPlan.java @@ -0,0 +1,140 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfiledb.auth.model.AuthException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; +import cn.edu.thu.tsfiledb.qp.logical.operator.author.AuthorOperator.AuthorType; + +/** + * given a author related plan and construct a {@code AuthorPlan} + * + * @author kangrong、whw + * + */ +public class AuthorPlan extends PhysicalPlan { + private final AuthorType authorType; + private String userName; + private String roleName; + private String password; + /* + * 刘昆修改的添加new password + */ + private String newPassword; + private String[] authorizationList; + private Path nodeName; + + public AuthorPlan(AuthorType authorType, String userName, String roleName, String password, String newPassword, + String[] authorizationList, Path nodeName) { + super(false, OperatorType.AUTHOR); + this.authorType = authorType; + this.userName = userName; + this.roleName = roleName; + this.password = password; + this.newPassword = newPassword; + this.authorizationList = authorizationList; + this.nodeName = nodeName; + } + + public boolean processNonQuery(QueryProcessExecutor config) throws ProcessorException{ + try { + boolean flag = true; + Set permissions; + switch (authorType) { + /* + * 刘昆修改添加一个物理修改密码的操作 + * + */ + case UPDATE_USER: + return config.updateUser(userName, newPassword); + case CREATE_USER: + return config.createUser(userName, password); + case CREATE_ROLE: + return config.createRole(roleName); + case DROP_USER: + return config.deleteUser(userName); + case DROP_ROLE: + return config.deleteRole(roleName); + case GRANT_ROLE: + permissions = pmsToInt(authorizationList); + for (int i : permissions) { + if (!config.addPmsToRole(roleName, nodeName.getFullPath(), i)) + flag = false; + } + return flag; + case GRANT_USER: + permissions = pmsToInt(authorizationList); + for (int i : permissions) { + if (!config.addPmsToUser(userName, nodeName.getFullPath(), i)) + flag = false; + } + return flag; + case GRANT_ROLE_TO_USER: + return config.grantRoleToUser(roleName, userName); + case REVOKE_USER: + permissions = pmsToInt(authorizationList); + for (int i : permissions) { + if (!config.removePmsFromUser(userName, nodeName.getFullPath(), i)) + flag = false; + } + return flag; + case REVOKE_ROLE: + permissions = pmsToInt(authorizationList); + for (int i : permissions) { + if (!config.removePmsFromRole(roleName, nodeName.getFullPath(), i)) + flag = false; + } + return flag; + case REVOKE_ROLE_FROM_USER: + return config.revokeRoleFromUser(roleName, userName); + default: + break; + + } + } catch (AuthException e) { + throw new ProcessorException(e.getMessage()); + } + return false; + } + + Set pmsToInt(String[] authorizationList) { + Set result = new HashSet(); + for (String s : authorizationList) { + s = s.toUpperCase(); + switch (s) { + case "CREATE": + result.add(0); + break; + case "INSERT": + result.add(1); + break; + case "MODIFY": + result.add(2); + break; + case "READ": + result.add(3); + break; + case "DELETE": + result.add(4); + break; + default: + break; + } + } + return result; + } + + @Override + public List getInvolvedSeriesPaths() { + List ret = new ArrayList(); + if (nodeName != null) + ret.add(nodeName); + return ret; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/DeletePlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/DeletePlan.java new file mode 100644 index 00000000000..fc2d3981a77 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/DeletePlan.java @@ -0,0 +1,59 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan; + +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; + +/** + * given a delete plan and construct a {@code DeletePlan} + * + * @author kangrong + * + */ +public class DeletePlan extends PhysicalPlan { + private long deleteTime; + private Path path; + + public DeletePlan() { + super(false, OperatorType.DELETE); + } + + public DeletePlan(long deleteTime, Path path) { + super(false, OperatorType.DELETE); + this.setDeleteTime(deleteTime); + this.setPath(path); + } + @Override + public boolean processNonQuery(QueryProcessExecutor exec) throws ProcessorException { + return exec.delete(path, deleteTime); + } + + public long getDeleteTime() { + return deleteTime; + } + + public void setDeleteTime(long delTime) { + this.deleteTime = delTime; + } + + public Path getPath() { + return path; + } + + public void setPath(Path path) { + this.path = path; + } + + @Override + public List getInvolvedSeriesPaths() { + List ret = new ArrayList(); + if (path != null) + ret.add(path); + return ret; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/InsertPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/InsertPlan.java new file mode 100644 index 00000000000..b7d0a38e097 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/InsertPlan.java @@ -0,0 +1,81 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan; + +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; + +/** + * given a insert plan and construct a {@code InsertPlan} + * + * @author kangrong + * + */ +public class InsertPlan extends PhysicalPlan { + private long insertTime; + private String value; + private Path path; + //insertType : 1表示插入到Bufferwrite,2表示插入到Overflow + private int insertType; + + public InsertPlan() { + super(false, OperatorType.INSERT); + } + + public InsertPlan(int insertType, long insertTime, String value, Path path) { + super(false, OperatorType.INSERT); + this.insertType = insertType; + this.insertTime = insertTime; + this.value = value; + this.path = path; + } + + @Override + public boolean processNonQuery(QueryProcessExecutor exec) throws ProcessorException{ + insertType = exec.insert(path, insertTime, value); + return true; + } + + public long getTime() { + return insertTime; + } + + public void setTime(long time) { + this.insertTime = time; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Path getPath() { + return path; + } + + public void setPath(Path path) { + this.path = path; + } + + @Override + public List getInvolvedSeriesPaths() { + List ret = new ArrayList(); + if (path != null) + ret.add(path); + return ret; + } + + public int getInsertType() { + return insertType; + } + + public void setInsertType(int insertType) { + this.insertType = insertType; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/LoadDataPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/LoadDataPlan.java new file mode 100644 index 00000000000..5679a396b2c --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/LoadDataPlan.java @@ -0,0 +1,40 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan; + +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; +import cn.edu.thu.tsfiledb.utils.LoadDataUtils; + +/** + * given a author related plan and construct a {@code AuthorPlan} + * + * @author kangrong + * + */ +public class LoadDataPlan extends PhysicalPlan { + private final String inputFilePath; + private final String measureType; + + public LoadDataPlan(String inputFilePath, String measureType) { + super(false, OperatorType.LOADDATA); + this.inputFilePath = inputFilePath; + this.measureType = measureType; + } + + public boolean processNonQuery(QueryProcessExecutor config) { + LoadDataUtils load = new LoadDataUtils(); + load.loadLocalDataMultiPass(inputFilePath, measureType, config.getMManager()); + return true; + } + + @Override + public List getInvolvedSeriesPaths() { + List ret = new ArrayList(); + if (measureType != null) + ret.add(new Path(measureType)); + return ret; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/MultiInsertPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/MultiInsertPlan.java new file mode 100644 index 00000000000..969c3186992 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/MultiInsertPlan.java @@ -0,0 +1,99 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan; + +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; + +/** + * given a insert plan and construct a {@code InsertPlan} + * + * @author kangrong + * + */ +public class MultiInsertPlan extends PhysicalPlan { + private String deltaObject; + private List measurementList; + private List insertValues; + private long insertTime; + + + //insertType : 1表示插入到Bufferwrite,2表示插入到Overflow + private int insertType; + + public MultiInsertPlan() { + super(false, OperatorType.MULTIINSERT); + } + + public MultiInsertPlan(String deltaObject, long insertTime, List measurementList, List insertValues) { + super(false, OperatorType.MULTIINSERT); + this.insertTime = insertTime; + this.deltaObject = deltaObject; + this.measurementList = measurementList; + this.insertValues = insertValues; + } + + @Override + public boolean processNonQuery(QueryProcessExecutor exec) throws ProcessorException{ + insertType = exec.multiInsert(deltaObject, insertTime, measurementList, insertValues); + return true; + } + + public long getTime() { + return insertTime; + } + + public void setTime(long time) { + this.insertTime = time; + } + + @Override + public List getInvolvedSeriesPaths() { + List ret = new ArrayList<>(); + + for(String m : measurementList){ + StringBuilder sb = new StringBuilder(); + sb.append(deltaObject); + sb.append("."); + sb.append(m); + Path p = new Path(sb.toString()); + ret.add(p); + } + return ret; + } + + public int getInsertType() { + return insertType; + } + + public void setInsertType(int insertType) { + this.insertType = insertType; + } + + public String getDeltaObject() { + return this.deltaObject; + } + + public void setDeltaObject(String deltaObject) { + this.deltaObject = deltaObject; + } + + public List getMeasurementList() { + return this.measurementList; + } + + public void setMeasurementList(List measurementList) { + this.measurementList = measurementList; + } + + public List getInsertValues() { + return this.insertValues; + } + + public void setInsertValues(List insertValues) { + this.insertValues = insertValues; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/PhysicalPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/PhysicalPlan.java new file mode 100644 index 00000000000..b4c7f898e23 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/PhysicalPlan.java @@ -0,0 +1,63 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan; + +import java.util.Iterator; +import java.util.List; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet; +import cn.edu.thu.tsfiledb.qp.exception.physical.plan.PhysicalPlanException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; + +/** + * This class is a abstract class for all type of PhysicalPlan. PhysicalPlan is a binary tree and is + * processed along preorder traversal. + * + * @author kangrong + * + */ +public abstract class PhysicalPlan { + private boolean isQuery; + private OperatorType operatorType; + + protected PhysicalPlan(boolean isQuery, OperatorType operatorType) { + this.isQuery = isQuery; + this.operatorType = operatorType; + } + + /** + * input a getIndex processing config and process the getIndex + * + * @param config + * @return + */ + public Iterator processQuery(QueryProcessExecutor config) { + throw new UnsupportedOperationException(); + } + + /** + * input a getIndex processing config and process insert/update/delete + * + * @param config + * @return + * @throws PhysicalPlanException + */ + public boolean processNonQuery(QueryProcessExecutor config) throws ProcessorException { + throw new UnsupportedOperationException(); + } + + public String printQueryPlan() { + return ""; + } + + public abstract List getInvolvedSeriesPaths(); + + public boolean isQuery(){ + return isQuery; + } + + public OperatorType getOperatorType() { + return operatorType; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/UpdatePlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/UpdatePlan.java new file mode 100644 index 00000000000..b6d40c0d627 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/UpdatePlan.java @@ -0,0 +1,80 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan; + +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; + + +/** + * given a update plan and construct a {@code UpdatePlan} + * + * @author kangrong + * + */ +public class UpdatePlan extends PhysicalPlan { + private long startTime; + private long endTime; + private String value; + private Path path; + + public UpdatePlan() { + super(false, OperatorType.UPDATE); + } + + public UpdatePlan(long startTime, long endTime, String value, Path path) { + super(false, OperatorType.UPDATE); + this.setStartTime(startTime); + this.setEndTime(endTime); + this.setValue(value); + this.setPath(path); + } + + @Override + public boolean processNonQuery(QueryProcessExecutor exec) throws ProcessorException { + return exec.update(path, startTime, endTime, value); + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Path getPath() { + return path; + } + + public void setPath(Path path) { + this.path = path; + } + + @Override + public List getInvolvedSeriesPaths() { + List ret = new ArrayList(); + if (path != null) + ret.add(path); + return ret; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/metadata/MetadataPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/metadata/MetadataPlan.java new file mode 100644 index 00000000000..7725b6a44b4 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/metadata/MetadataPlan.java @@ -0,0 +1,132 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan.metadata; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfiledb.exception.ArgsErrorException; +import cn.edu.thu.tsfiledb.exception.PathErrorException; +import cn.edu.thu.tsfiledb.metadata.MManager; +import cn.edu.thu.tsfiledb.qp.exception.physical.plan.NamespacePlanException; +import cn.edu.thu.tsfiledb.qp.exception.physical.plan.PhysicalPlanException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; +import cn.edu.thu.tsfiledb.qp.logical.operator.metadata.MetadataOperator.NamespaceType; +import cn.edu.thu.tsfiledb.qp.physical.plan.DeletePlan; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * given a author related plan and construct a {@code AuthorPlan} + * + * @author kangrong + * + */ +public class MetadataPlan extends PhysicalPlan { + private static final Logger logger = LoggerFactory.getLogger(MetadataPlan.class); + private final NamespaceType namespaceType; + private Path path; + private String dataType; + private String encoding; + private String[] encodingArgs; + + public Path getPath() { + return path; + } + + public void setPath(Path path) { + this.path = path; + } + + public String getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = dataType; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public String[] getEncodingArgs() { + return encodingArgs; + } + + public void setEncodingArgs(String[] encodingArgs) { + this.encodingArgs = encodingArgs; + } + + public NamespaceType getNamespaceType() { + return namespaceType; + } + + public MetadataPlan(NamespaceType namespaceType, Path path, String dataType, String encoding, + String[] encodingArgs) { + super(false, OperatorType.METADATA); + this.namespaceType = namespaceType; + this.path = path; + this.dataType = dataType; + this.encoding = encoding; + this.encodingArgs = encodingArgs; + } + + public boolean processNonQuery(QueryProcessExecutor config) throws ProcessorException { + MManager mManager = config.getMManager(); + try { + switch (namespaceType) { + case ADD_PATH: + mManager.addAPathToMTree(path.getFullPath(), dataType, encoding, encodingArgs); + break; + case DELETE_PATH: + try { + // First delete all data interactive + deleteAllData(config); + // Then delete the metadata + mManager.deletePathFromMTree(path.getFullPath()); + } catch (Exception e) { + return true; + } + break; + case SET_FILE_LEVEL: + mManager.setStorageLevelToMTree(path.getFullPath()); + break; + default: + throw new ProcessorException("unkown namespace type:" + namespaceType); + } + } catch (PathErrorException | IOException | ArgsErrorException e) { + throw new ProcessorException("meet err in " + namespaceType + " . " + e.getMessage()); + } + return true; + } + + private void deleteAllData(QueryProcessExecutor config) throws PathErrorException, ProcessorException { + MManager mManager = config.getMManager(); + ArrayList pathList = mManager.getPaths(path.getFullPath()); + for (String p : pathList) { + if(mManager.pathExist(p)){ + DeletePlan deletePlan = new DeletePlan(); + deletePlan.setPath(new Path(p)); + deletePlan.setDeleteTime(Long.MAX_VALUE); + deletePlan.processNonQuery(config); + } + } + } + + @Override + public List getInvolvedSeriesPaths() { + List ret = new ArrayList(); + if (path != null) + ret.add(path); + return ret; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/metadata/PropertyPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/metadata/PropertyPlan.java new file mode 100644 index 00000000000..9b202ff467a --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/metadata/PropertyPlan.java @@ -0,0 +1,94 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan.metadata; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfiledb.exception.ArgsErrorException; +import cn.edu.thu.tsfiledb.exception.PathErrorException; +import cn.edu.thu.tsfiledb.metadata.MManager; +import cn.edu.thu.tsfiledb.qp.exception.physical.plan.NamespacePlanException; +import cn.edu.thu.tsfiledb.qp.exception.physical.plan.PhysicalPlanException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; +import cn.edu.thu.tsfiledb.qp.logical.operator.metadata.PropertyOperator.PropertyType; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * given a author related plan and construct a {@code AuthorPlan} + * + * @author kangrong + * + */ +public class PropertyPlan extends PhysicalPlan { + private final PropertyType propertyType; + private Path propertyPath; + private Path metadataPath; + + public Path getPropertyPath() { + return propertyPath; + } + + public void setPropertyPath(Path propertyPath) { + this.propertyPath = propertyPath; + } + + public Path getMetadataPath() { + return metadataPath; + } + + public void setMetadataPath(Path metadataPath) { + this.metadataPath = metadataPath; + } + + public PropertyType getPropertyType() { + return propertyType; + } + + + public PropertyPlan(PropertyType propertyType, Path propertyPath, Path metadataPath) { + super(false, OperatorType.PROPERTY); + this.propertyType = propertyType; + this.propertyPath = propertyPath; + this.metadataPath = metadataPath; + } + + public boolean processNonQuery(QueryProcessExecutor config) throws ProcessorException { + MManager mManager = config.getMManager(); + try { + switch (propertyType) { + case ADD_TREE: + mManager.addAPTree(propertyPath.getFullPath()); + break; + case ADD_PROPERTY_LABEL: + mManager.addAPathToPTree(propertyPath.getFullPath()); + break; + case DELETE_PROPERTY_LABEL: + mManager.deletePathFromPTree(propertyPath.getFullPath()); + break; + case ADD_PROPERTY_TO_METADATA: + mManager.linkMNodeToPTree(propertyPath.getFullPath(), metadataPath.getFullPath()); + break; + case DEL_PROPERTY_FROM_METADATA: + mManager.unlinkMNodeFromPTree(propertyPath.getFullPath(), metadataPath.getFullPath()); + break; + default: + throw new ProcessorException("unkown namespace type:" + propertyType); + } + } catch (PathErrorException | IOException | ArgsErrorException e) { + throw new ProcessorException("meet err in " + propertyType +" . "+ e.getMessage()); + } + return true; + } + @Override + public List getInvolvedSeriesPaths() { + List ret = new ArrayList(); + if (metadataPath != null) + ret.add(metadataPath); + if (propertyPath != null) + ret.add(propertyPath); + return ret; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/MergeQuerySetIterator.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/MergeQuerySetIterator.java new file mode 100644 index 00000000000..2fc73faa05f --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/MergeQuerySetIterator.java @@ -0,0 +1,119 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan.query; + +import java.util.Iterator; +import java.util.List; + +import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet; +import cn.edu.thu.tsfile.timeseries.read.readSupport.RowRecord; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; + +/** + * This class implements the interface {@code Iterator}. It is the result of + * {@code MergeQuerySetPlan}(for multi-pass getIndex). {@code MergeQuerySetPlan} provides it with a + * list of {@code SeriesSelectPlan}.
+ * This class merge row record data set from a list of {@code Iterator} provided by + * {@code SeriesSelectPlan} according to the time ascending, using minimum heap + * + * @author kangrong + * + */ +public class MergeQuerySetIterator implements Iterator { + private final int mergeFetchSize; + // private RowRecord[] records; + private Iterator[] recordIters; + private Node[] records; + // it's actually number of series iterators which has next record; + private int heapSize; + private long lastRowTime = -1; + + public MergeQuerySetIterator(List selectPlans, int mergeFetchSize, + QueryProcessExecutor conf) { + this.mergeFetchSize = mergeFetchSize; + heapSize = selectPlans.size(); + records = new Node[heapSize + 1]; + recordIters = SeriesSelectPlan.getRecordIteratorArray(selectPlans, conf); + initIters(); + } + + private void initIters() { + int index = 1; + int tempSize = heapSize; + for (int i = 0; i < tempSize; i++) { + if (!recordIters[i].hasNext()) { + heapSize--; + } else { + // add first value in all iterators to build minimum heap. + records[index++] = new Node(recordIters[i].next(), recordIters[i]); + } + } + // build minimum Heap + for (int i = heapSize / 2; i >= 1; i--) + minHeapify(i); + } + + @Override + public boolean hasNext() { + return heapSize > 0; + } + + @Override + public QueryDataSet next() { + QueryDataSet ret = new QueryDataSet(); + int i = 0; + while (i < mergeFetchSize && heapSize > 0) { + Node minNode = records[1]; + if (minNode.r.timestamp != lastRowTime) { + lastRowTime = minNode.r.timestamp; + i++; + ret.putARowRecord(minNode.r); + } + if (minNode.iter.hasNext()) { + records[1].r = records[1].iter.next(); + } else { + records[1] = records[heapSize]; + heapSize -= 1; + } + minHeapify(1); + } + return ret; + } + + public void minHeapify(int i) { + int left = 2 * i; + int right = 2 * i + 1; + int min = i; + + if (left <= heapSize && records[left].lessThan(records[i])) + min = left; + if (right <= heapSize && records[right].lessThan(records[min])) + min = right; + + if (min != i) { + Node tmp = records[i]; + records[i] = records[min]; + records[min] = tmp; + minHeapify(min); + } + } + + private class Node { + public RowRecord r; + public Iterator iter; + + public Node(RowRecord r, Iterator iter) { + this.r = r; + this.iter = iter; + } + + public boolean lessThan(Node o) { + if (r == null || o.r == null) + System.err.println("asdasdas"); + return r.timestamp < o.r.timestamp; + } + + @Override + public String toString() { + return r.toString(); + } + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/MergeQuerySetPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/MergeQuerySetPlan.java new file mode 100644 index 00000000000..bd4fc918895 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/MergeQuerySetPlan.java @@ -0,0 +1,88 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan.query; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet; +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * {@code MergeQuerySetPlan} is used in multi-pass getIndex plan. Multi-pass means it's a disjunction + * among a list of single getIndex. {@code MergeQuerySetPlan} return a {@code Iterator} + * provided by {@code SeriesSelectPlan} for one-pass getIndex, or a {@code MergeQuerySetIterator} for + * multi-pass getIndex. + * + * @see cn.edu.thu.tsfiledb.qp.physical.plan.query.SeriesSelectPlan + * @author kangrong + * + */ +public class MergeQuerySetPlan extends PhysicalPlan { + private static Logger LOG = LoggerFactory.getLogger(MergeQuerySetPlan.class); + protected List selectPlans; + + public List getSelectPlans() { + return selectPlans; + } + + public MergeQuerySetPlan(ArrayList selectPlans) { + super(true, OperatorType.QUERY); + if (selectPlans == null || selectPlans.isEmpty()) { + LOG.error("cannot input an null or empty plan list into QuerySetMergePlan! "); + } + this.selectPlans = selectPlans; + } + + public void setSelectPlans(List selectPlans) { + this.selectPlans = selectPlans; + } + + @Override + public Iterator processQuery(QueryProcessExecutor conf) { + if (selectPlans.size() == 1) + // return new SingleQuerySetIterator(conf, selectPlans[0]); + return selectPlans.get(0).processQuery(conf); + else + return new MergeQuerySetIterator(selectPlans, conf.getFetchSize(), conf); + } + + @Override + public String printQueryPlan() { + // LOG.info("show getIndex plan:"); + StringContainer sc = new StringContainer("\n"); + for (int i = 0; i < selectPlans.size(); i++) { + sc.addTail("showing series plan:" + i); + sc.addTail(selectPlans.get(i).printQueryPlan()); + } + return sc.toString(); + } + + @Override + public List getInvolvedSeriesPaths() { + if(selectPlans == null || selectPlans.size() == 0) + return new ArrayList(); + else{ + List ret = new ArrayList<>(); + LinkedHashMap pathMap = new LinkedHashMap<>(); + for (SeriesSelectPlan series : selectPlans) { + for(Path p : series.getInvolvedSeriesPaths()){ + if(!pathMap.containsKey(p)){ + pathMap.put(p, 1); + ret.add(p); + } + } + } + return ret; + } + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/OutputQueryDataSet.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/OutputQueryDataSet.java new file mode 100644 index 00000000000..4bb329d7f50 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/OutputQueryDataSet.java @@ -0,0 +1,57 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan.query; + +import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet; +import cn.edu.thu.tsfile.timeseries.read.readSupport.RowRecord; + +/** + * This class extends {@link cn.edu.thu.tsfiledb.read.query.QueryDataSet}.
+ * This getIndex data set is used for getIndex processing. getIndex processing merges a list of QueryDataSet + * and construct a new OutputQueryDataSet by adding {@code RowRecord}. This class provides two + * methods for caller {@code getNextRecord} and {@code hasNextRecord} just same as + * {@code QueryDataSet}. + * + * @author kangrong + * + */ +public class OutputQueryDataSet extends QueryDataSet { + protected final int fetchSize; + protected RowRecord[] data; + protected int size; + protected int index; + + public OutputQueryDataSet(int fetchSize) { + this.fetchSize = fetchSize; + data = new RowRecord[fetchSize]; + size = 0; + index = 0; + } + + /** + * put a rowRecord into this DataSet. + * + * @param r - rowRecord to be added. + * @return if amount of exist record equals to fetchSize, return false, otherwise return true. + * + */ + public boolean addRowRecord(RowRecord r) { + if (size < fetchSize) { + data[size++] = r; + return true; + } else + return false; + } + + /** + * For efficiency, this method don't check index boundary. caller should check index boundary by + * {@code hasNextRecord} before calling this method. + */ + @Override + public RowRecord getNextRecord() { + return data[index++]; + } + + @Override + public boolean hasNextRecord() { + return index < size; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/SeriesSelectPlan.java b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/SeriesSelectPlan.java new file mode 100644 index 00000000000..27acd5b7b49 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/qp/physical/plan/query/SeriesSelectPlan.java @@ -0,0 +1,341 @@ +package cn.edu.thu.tsfiledb.qp.physical.plan.query; + +import static cn.edu.thu.tsfiledb.qp.constant.SQLConstant.lineFeedSignal; + +import java.util.*; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.timeseries.filter.definition.FilterExpression; +import cn.edu.thu.tsfile.timeseries.filter.definition.FilterFactory; +import cn.edu.thu.tsfile.timeseries.filter.definition.SingleSeriesFilterExpression; +import cn.edu.thu.tsfile.timeseries.filter.definition.filterseries.FilterSeries; +import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet; +import cn.edu.thu.tsfile.timeseries.read.readSupport.RowRecord; +import cn.edu.thu.tsfile.timeseries.utils.StringContainer; +import cn.edu.thu.tsfiledb.exception.PathErrorException; +import cn.edu.thu.tsfiledb.qp.exception.QueryProcessorException; +import cn.edu.thu.tsfile.timeseries.read.qp.Path; +import cn.edu.thu.tsfiledb.qp.exec.QueryProcessExecutor; +import cn.edu.thu.tsfiledb.qp.logical.operator.Operator.OperatorType; +import cn.edu.thu.tsfiledb.qp.logical.operator.crud.FilterOperator; +import cn.edu.thu.tsfiledb.qp.physical.plan.PhysicalPlan; + +/** + * This class is constructed with a single getIndex plan. Single getIndex means it could be processed by + * reading API by one pass directly.
+ * Up to now, Single Query what {@code reading API} supports means it's a conjunction among time + * filter, frequency filter and value filter.
+ * This class provide two public function. If the whole getIndex plan has exactly one single getIndex, + * {@code SeriesSelectPlan} return a {@code Iterator} directly. Otherwise + * {@code SeriesSelectPlan} is regard as a portion of {@code MergeQuerySetPlan}. This class provide + * a {@code Iterator}in the latter case. + * + * @author kangrong + * + */ +public class SeriesSelectPlan extends PhysicalPlan { + private static final Logger LOG = LoggerFactory.getLogger(SeriesSelectPlan.class); + private List paths; + private FilterOperator deltaObjectFilterOperator; + + public FilterOperator getDeltaObjectFilterOperator() { + return deltaObjectFilterOperator; + } + + public void setDeltaObjectFilterOperator(FilterOperator deltaObjectFilterOperator) { + this.deltaObjectFilterOperator = deltaObjectFilterOperator; + } + + private FilterOperator timeFilterOperator; + private FilterOperator freqFilterOperator; + private FilterOperator valueFilterOperator; + + public List getPaths() { + return paths; + } + + public FilterOperator getTimeFilterOperator() { + return timeFilterOperator; + } + + public FilterOperator getFreqFilterOperator() { + return freqFilterOperator; + } + + public FilterOperator getValueFilterOperator() { + return valueFilterOperator; + } + + public SeriesSelectPlan(List paths, FilterOperator timeFilter, FilterOperator freqFilter, + FilterOperator valueFilter, QueryProcessExecutor conf) { + this(paths, null, timeFilter, freqFilter, valueFilter, conf); + } + + public SeriesSelectPlan(List paths, FilterOperator deltaObjectFilterOperator, + FilterOperator timeFilter, FilterOperator freqFilter, FilterOperator valueFilter, QueryProcessExecutor conf) { + super(true, OperatorType.QUERY); + this.paths = paths; + this.deltaObjectFilterOperator = deltaObjectFilterOperator; + this.timeFilterOperator = timeFilter; + this.freqFilterOperator = freqFilter; + this.valueFilterOperator = valueFilter; + removeStarsInPath(conf); + LOG.info(Arrays.toString(paths.toArray())); + removeNotExistsPaths(conf); + LOG.info(Arrays.toString(paths.toArray())); + } + + @Override + public Iterator processQuery(QueryProcessExecutor conf) { + FilterExpression[] exprs; + try { + exprs = transformFilterOpToExpression(conf); + } catch (QueryProcessorException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + return new QueryDataSetIterator(paths, conf.getFetchSize(), conf, exprs[0], exprs[1], + exprs[2]); + } + + private void removeStarsInPath(QueryProcessExecutor conf) { + LinkedHashMap pathMap = new LinkedHashMap<>(); + for (Path path : paths) { + List all = null; + try { + all = conf.getAllPaths(path.getFullPath()); + for(String subp : all){ + if(!pathMap.containsKey(subp)){ + pathMap.put(subp, 1); + } + } + } catch (PathErrorException e) { + LOG.error("path error:" + e.getMessage()); + continue; + } + } + paths = new ArrayList(); + for (String pathStr : pathMap.keySet()) { + paths.add(new Path(pathStr)); + } + } + + private void removeNotExistsPaths(QueryProcessExecutor conf) { + List existsPaths = new ArrayList(); + List notExistsPaths = new ArrayList(); + for (Path path : paths) { + if (conf.judgePathExists(path)) + existsPaths.add(path); + else + notExistsPaths.add(path); + } + if (!notExistsPaths.isEmpty()) { + LOG.warn("following paths don't exist:{}", notExistsPaths.toString()); + } + this.paths = existsPaths; + + } + + private FilterExpression[] transformFilterOpToExpression(QueryProcessExecutor conf) + throws QueryProcessorException { + FilterExpression timeFilter = + timeFilterOperator == null ? null : timeFilterOperator.transformToFilter(conf); + FilterExpression freqFilter = + freqFilterOperator == null ? null : freqFilterOperator.transformToFilter(conf); + FilterExpression valueFilter = + valueFilterOperator == null ? null : valueFilterOperator.transformToFilter(conf); + // TODO maybe it's a temporary solution. Up to now, if a crossSensorFilter is needed, just + // construct it with two same children via CSAnd(valueFilter, valueFilter) + if (valueFilter instanceof SingleSeriesFilterExpression) { + if (paths.size() == 1) { + FilterSeries series = ((SingleSeriesFilterExpression) valueFilter).getFilterSeries(); + Path path = paths.get(0); + if (!series.getDeltaObjectUID().equals(path.getDeltaObjectToString()) + || !series.getMeasurementUID().equals(path.getMeasurementToString())) { + valueFilter = FilterFactory.and(valueFilter, valueFilter); + } + } else + valueFilter = FilterFactory.and(valueFilter, valueFilter); + } + return new FilterExpression[] {timeFilter, freqFilter, valueFilter}; + } + + + /** + * provide {@code Iterator} for + * {@link cn.edu.thu.tsfiledb.qp.physical.plan.query.MergeQuerySetIterator} which has more than one + * {@code SeriesSelectPlan} to merge + * + * @param conf + * @return + */ + private Iterator getRecordIterator(QueryProcessExecutor conf) { + FilterExpression[] exprs = null; + try { + exprs = transformFilterOpToExpression(conf); + } catch (QueryProcessorException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + return new RowRecordIterator(conf.getFetchSize(), conf, exprs[0], exprs[1], exprs[2]); + } + + /** + * provide {@code Iterator} for + * {@link com.corp.tsfile.qp.physical.plan.MergeQuerySetIterator} which has exactly one + * {@code SeriesSelectPlan}. + * + * @param conf + * @return + */ + // public Iterator getQueryDataSetIterator(QueryProcessExecutor conf) { + // return new QueryDataSetIterator(conf.getFetchSize(), conf); + // } + + /** + * only used by + * + * @param plans + * @param conf + * @return + */ + public static Iterator[] getRecordIteratorArray(List plans, + QueryProcessExecutor conf) { + Iterator[] ret = new RowRecordIterator[plans.size()]; + for (int i = 0; i < plans.size(); i++) { + ret[i] = plans.get(i).getRecordIterator(conf); + } + return ret; + } + + public class RowRecordIterator implements Iterator { + private boolean noNext = false; + private final int fetchSize; + private final QueryProcessExecutor conf; + private QueryDataSet data = null; + private FilterExpression timeFilter; + private FilterExpression freqFilter; + private FilterExpression valueFilter; + + public RowRecordIterator(int fetchSize, QueryProcessExecutor conf, + FilterExpression timeFilter, FilterExpression freqFilter, + FilterExpression valueFilter) { + this.fetchSize = fetchSize; + this.conf = conf; + this.timeFilter = timeFilter; + this.freqFilter = freqFilter; + this.valueFilter = valueFilter; + } + + @Override + public boolean hasNext(){ + if (noNext) + return false; + if (data == null || !data.hasNextRecord()) + try { + data = conf.query(paths, timeFilter, freqFilter, valueFilter, fetchSize, data); + } catch (ProcessorException e) { + throw new RuntimeException(e.getMessage()); + } + if (data.hasNextRecord()) + return true; + else { + noNext = true; + return false; + } + } + + @Override + public RowRecord next() { + return data.getNextRecord(); + } + + } + + private class QueryDataSetIterator implements Iterator { + private boolean noNext = false; + private final int fetchSize; + private final QueryProcessExecutor conf; + private QueryDataSet data = null; + private QueryDataSet usedData = null; + private FilterExpression timeFilter; + private FilterExpression freqFilter; + private FilterExpression valueFilter; + private List paths; + + public QueryDataSetIterator(List paths, int fetchSize, QueryProcessExecutor conf, + FilterExpression timeFilter, FilterExpression freqFilter, + FilterExpression valueFilter) { + this.paths = paths; + this.fetchSize = fetchSize; + this.conf = conf; + this.timeFilter = timeFilter; + this.freqFilter = freqFilter; + this.valueFilter = valueFilter; + + } + + @Override + public boolean hasNext() { + if (usedData != null) { + usedData.clear(); + } + if (noNext) + return false; + if (data == null || !data.hasNextRecord()) + try { + data = conf.query(paths, timeFilter, freqFilter, valueFilter, fetchSize, usedData); + } catch (ProcessorException e) { + throw new RuntimeException(e.getMessage()); + } + if (data == null) { + LOG.error( + "data is null! parameters: paths:{},timeFilter:{}, freqFilter:{}, valueFilter:{}, fetchSize:{}, usedData:{}", + paths, timeFilter, freqFilter, valueFilter, fetchSize, usedData); + throw new RuntimeException("data is null! parameters: paths:"); + } + if (data.hasNextRecord()) + return true; + else { + noNext = true; + return false; + } + } + + @Override + public QueryDataSet next() { + usedData = data; + data = null; + return usedData; + } + } + + + @Override + public String printQueryPlan() { + StringContainer sc = new StringContainer(); + String preSpace = " "; + sc.addTail(preSpace, "series getIndex plan:", lineFeedSignal); + sc.addTail(preSpace, "paths: ").addTail(paths.toString(), lineFeedSignal); + sc.addTail(preSpace, timeFilterOperator == null ? "null" : timeFilterOperator.toString(), + lineFeedSignal); + sc.addTail(preSpace, freqFilterOperator == null ? "null" : freqFilterOperator.toString(), + lineFeedSignal); + sc.addTail(preSpace, valueFilterOperator == null ? "null" : valueFilterOperator.toString(), + lineFeedSignal); + return sc.toString(); + } + + @Override + public List getInvolvedSeriesPaths() { + if (paths == null) + return new ArrayList(); + else + return paths; + } +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/utils/FileSchemaUtil.java b/src/main/java/cn/edu/thu/tsfiledb/utils/FileSchemaUtil.java new file mode 100644 index 00000000000..01a855c1bb8 --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/utils/FileSchemaUtil.java @@ -0,0 +1,47 @@ +package cn.edu.thu.tsfiledb.utils; + +import java.util.List; +import java.util.Map.Entry; + +import org.json.JSONArray; +import org.json.JSONObject; + +import cn.edu.thu.tsfile.common.constant.JsonFormatConstant; +import cn.edu.thu.tsfile.timeseries.write.exception.InvalidJsonSchemaException; +import cn.edu.thu.tsfile.timeseries.write.schema.FileSchema; +import cn.edu.thu.tsfiledb.metadata.ColumnSchema; + +public class FileSchemaUtil { + + public static FileSchema getFileSchemaFromColumnSchema(List schemaList, String measureType) { + JSONObject jsonSchema = new JSONObject(); + JSONArray rowGroupArray = new JSONArray(); + + for (ColumnSchema col : schemaList) { + JSONObject s1 = new JSONObject(); + s1.put(JsonFormatConstant.MEASUREMENT_UID, col.name); + s1.put(JsonFormatConstant.DATA_TYPE, col.dataType.toString()); + s1.put(JsonFormatConstant.MEASUREMENT_ENCODING, col.encoding.toString()); + for (Entry entry : col.getArgsMap().entrySet()) { + if (JsonFormatConstant.ENUM_VALUES.equals(entry.getKey())) { + String[] valueArray = entry.getValue().split(","); + s1.put(JsonFormatConstant.ENUM_VALUES, new JSONArray(valueArray)); + } else + s1.put(entry.getKey(), entry.getValue().toString()); + } + rowGroupArray.put(s1); + } + + jsonSchema.put(JsonFormatConstant.DELTA_TYPE, measureType); + jsonSchema.put(JsonFormatConstant.JSON_SCHEMA, rowGroupArray); + FileSchema fileSchema = null; + try { + fileSchema = new FileSchema(jsonSchema); + } catch (InvalidJsonSchemaException e) { + //This exception won't occur + e.printStackTrace(); + } + return fileSchema; + } + +} diff --git a/src/main/java/cn/edu/thu/tsfiledb/utils/LoadDataUtils.java b/src/main/java/cn/edu/thu/tsfiledb/utils/LoadDataUtils.java new file mode 100644 index 00000000000..63b743ed47f --- /dev/null +++ b/src/main/java/cn/edu/thu/tsfiledb/utils/LoadDataUtils.java @@ -0,0 +1,209 @@ +package cn.edu.thu.tsfiledb.utils; + +import org.apache.derby.tools.sysinfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cn.edu.thu.tsfile.common.conf.TSFileConfig; +import cn.edu.thu.tsfile.common.conf.TSFileDescriptor; +import cn.edu.thu.tsfile.common.exception.ProcessorException; +import cn.edu.thu.tsfile.timeseries.utils.FileUtils; +import cn.edu.thu.tsfile.timeseries.utils.RecordUtils; +import cn.edu.thu.tsfile.timeseries.write.record.TSRecord; +import cn.edu.thu.tsfile.timeseries.write.schema.FileSchema; +import cn.edu.thu.tsfiledb.engine.filenode.FileNodeManager; +import cn.edu.thu.tsfiledb.exception.PathErrorException; +import cn.edu.thu.tsfiledb.metadata.ColumnSchema; +import cn.edu.thu.tsfiledb.metadata.MManager; + +import java.io.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author kangrong + */ +public class LoadDataUtils { + private static Logger LOG = LoggerFactory.getLogger(LoadDataUtils.class); + private BufferedReader inputCsvFileReader; + private BufferedWriter extraDataFileWriter; + private FileSchema fileSchema; + private Set writeInstanceMap; + private MManager mManager; + private int writeInstanceThreshold; + private boolean hasExtra = false; + private String measureType; + private long totalPointCount = 0; + private FileNodeManager fileNodeManager; + private TSFileConfig conf = TSFileDescriptor.getInstance().getConfig(); + + public LoadDataUtils() { + writeInstanceMap = new HashSet<>(); + fileNodeManager = FileNodeManager.getInstance(); + writeInstanceThreshold = conf.writeInstanceThreshold; + } + + /** + * @param inputCsvDataPath - path + * @return - return extra data file in this circle as input csv path in next circle + */ + private String loadLocalDataOnePass(String inputCsvDataPath) { + hasExtra = false; + // prepare file for extra data + String extraDataFilePath = prepareFilePathAddOne(inputCsvDataPath); + File extraDataFile = new File(extraDataFilePath); + try { + this.extraDataFileWriter = new BufferedWriter(new FileWriter(extraDataFile)); + } catch (IOException e) { + LOG.error("create"); + e.printStackTrace(); + close(); + return null; + } + // prepare input csv data file. + try { + this.inputCsvFileReader = new BufferedReader(new FileReader(inputCsvDataPath)); + } catch (FileNotFoundException e1) { + LOG.error("inputCsvDataPath:{} not found!", inputCsvDataPath); + close(); + return null; + } + // load data for each line + long lineCount = 0; + long startTime = System.currentTimeMillis(); + long temp = System.currentTimeMillis(); + String line; + try { + while ((line = inputCsvFileReader.readLine()) != null) { + if (lineCount % 1000000 == 0) { + long endTime = System.currentTimeMillis(); + LOG.info("write line:{}, use time:{}", lineCount, + (endTime - temp)); + temp = System.currentTimeMillis(); + LOG.info("load data points:{}, load data speed:{}w point/s", + totalPointCount, FileUtils.format(((float) totalPointCount / 10) / (endTime - startTime), 2)); + } + loadOneRecordLine(line); + lineCount++; + } + } catch (IOException e1) { + LOG.error("read line from inputCsvFileReader failed:{}", inputCsvDataPath); + extraDataFilePath = null; + } finally { + LOG.info("write line:{}", lineCount); + close(); + closeWriteInstance(); + } + return extraDataFilePath; + } + + @SuppressWarnings("finally") + private void loadOneRecordLine(String line) { + TSRecord record = RecordUtils.parseSimpleTupleRecord(line, this.fileSchema); + totalPointCount += record.dataPointList.size(); + String nsPath = null; + try { + nsPath = mManager.getFileNameByPath(record.deltaObjectId); + } catch (PathErrorException e) { + LOG.error("given path not found.{}", e.getMessage()); + } + if (!writeInstanceMap.contains(nsPath)) { + if (writeInstanceMap.size() < writeInstanceThreshold) { + writeInstanceMap.add(nsPath); + } else { + hasExtra = true; + try { + extraDataFileWriter.write(line); + extraDataFileWriter.newLine(); + } catch (IOException e) { + LOG.error("record the extra data into extraFile failed, record:{}", line); + } + } + } + // appeared before, insert directly + try { + fileNodeManager.insert(record); + } catch (ProcessorException e) { + LOG.error("write record failed: {}", e.getMessage()); + } + } + + private String prepareFilePathAddOne(String srcFilePath) { + String extraExt = "deltaTempExt"; + int srcEnd = srcFilePath.indexOf(extraExt); + if (srcEnd != -1) + srcFilePath = srcFilePath.substring(0, srcEnd); + File file; + int ext = 0; + String tempFile = srcFilePath; + while (true) { + file = new File(tempFile); + if (file.exists()) + tempFile = srcFilePath + extraExt + (ext++); + else + break; + } + return tempFile; + } + + + private void close() { + try { + if (inputCsvFileReader != null) + inputCsvFileReader.close(); + if (extraDataFileWriter != null) + extraDataFileWriter.close(); + } catch (IOException e) { + LOG.error("close inputCsvFileReader and extraDataFileWriter failed"); + } + } + + private void closeWriteInstance() { + //TODO for data load, don't close the write processor +// for (Entry entry : writeInstanceMap.entrySet()) { +// entry.getValue().close(); +// LOG.info("closed write instance:{}", entry.getKey()); +// } + writeInstanceMap.clear(); + } + + + public void loadLocalDataMultiPass(String inputCsvDataPath, String measureType, + MManager mManager) { + LOG.info("start loading data..."); + long start = System.currentTimeMillis(); + System.out.println("asdaasd"); + System.out.println("asdaasd"); + System.out.println("asdaasd"); + System.out.println("asdaasd"); + long startTime = System.currentTimeMillis(); + this.mManager = mManager; + // get measurement schema + try { + ArrayList meaSchema = mManager.getSchemaForOneType(measureType); + this.measureType = measureType; + fileSchema = FileSchemaUtil.getFileSchemaFromColumnSchema(meaSchema, measureType); + } catch (PathErrorException e) { + LOG.error("the path of input measurement schema meet error!"); + e.printStackTrace(); + close(); + return; + } + String extraPath = inputCsvDataPath; + List extraPaths = new ArrayList<>(); + do { + LOG.info("cycle: write csv file: {}", extraPath); + extraPath = loadLocalDataOnePass(extraPath); + extraPaths.add(extraPath); + } while (hasExtra); + for (String ext : extraPaths) { + LOG.info("delete old file:{}", ext); + new File(ext).delete(); + } + long endTime = System.currentTimeMillis(); + LOG.info("load data successfully! total data points:{}, load data speed:{}w point/s", + totalPointCount, FileUtils.format(((float) totalPointCount / 10) / (endTime - startTime), 2)); + } +}