diff --git a/pom.xml b/pom.xml
index d393b98fd5b..8bf3160209f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,6 +14,8 @@
UTF-8
1.8
2.6.0
+ 2.14.1
+ 10.12.1.1
@@ -37,6 +39,19 @@
${hadoop.version}
+
+ jline
+ jline
+ ${jline.version}
+
+
+
+ org.apache.derby
+ derby
+ ${derby.version}
+
+
+
diff --git a/src/main/java/cn/edu/thu/tsfiledb/auth/TestAu.java b/src/main/java/cn/edu/thu/tsfiledb/auth/TestAu.java
new file mode 100644
index 00000000000..4991cf8cf3a
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/auth/TestAu.java
@@ -0,0 +1,31 @@
+package cn.edu.thu.tsfiledb.auth;
+
+import cn.edu.thu.tsfiledb.auth.dao.Authorizer;
+import cn.edu.thu.tsfiledb.auth.dao.DBdao;
+import cn.edu.thu.tsfiledb.auth.model.User;
+
+public class TestAu {
+
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+
+ // 启动server的时候需要open db
+ DBdao dBdao = new DBdao();
+ dBdao.open();
+ System.out.println("start server.....");
+ // 操作数据库信息
+ User user = new User("test", "test");
+
+ try {
+ Authorizer.createUser(user.getUserName(), user.getPassWord());
+ Authorizer.deleteUser(user.getUserName());
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ // 关闭server的时候需要 close db
+ System.out.println("close the server...");
+ dBdao.close();
+ }
+
+}
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..0485e0076a7
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDao.java
@@ -0,0 +1,285 @@
+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..269db10d890
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/AuthDaoWrap.java
@@ -0,0 +1,355 @@
+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.AuthException;
+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 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..c689512a613
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/RoleDao.java
@@ -0,0 +1,103 @@
+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..83bba202225
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/RolePermissionDao.java
@@ -0,0 +1,99 @@
+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..8a2011eeeeb
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserDao.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.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..21b35bb9fef
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserPermissionDao.java
@@ -0,0 +1,99 @@
+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..69fc1f04992
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/auth/dao/UserRoleRelDao.java
@@ -0,0 +1,117 @@
+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/jdbc/Client.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/Client.java
new file mode 100644
index 00000000000..b0eba015ebe
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/Client.java
@@ -0,0 +1,229 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLTimeoutException;
+import java.sql.Statement;
+
+import jline.console.ConsoleReader;
+
+public class Client {
+
+ private static final int MAX_PRINT_ROW_COUNT = 1000;
+
+ public static void main(String[] args) throws ClassNotFoundException, SQLException {
+ // TODO Auto-generated method stub
+ Class.forName("com.corp.tsfile.jdbc.TsfileDriver");
+ Connection connection = null;
+ ConsoleReader reader = null;
+ String s;
+ boolean printToConsole = true;
+
+ try {
+ reader = new ConsoleReader();
+ String[] argsName = new String[] { "-host", "-port", "-u", "-print" };
+ String[] argv = new String[argsName.length];
+
+ if (args.length < 3) {
+ System.out.println("Useage : login -host -port -u");
+ System.out.println("e.g. : login -host127.0.0.1 -port6667 -u");
+ return;
+ }
+
+ for (int i = 0; i < args.length; i++) {
+ String v = args[i].trim();
+ for (int j = 0; j < argsName.length; j++) {
+ if (v.startsWith(argsName[j])) {
+ argv[j] = v.substring(argsName[j].length()).trim();
+ }
+ }
+ }
+
+ if (argv[3] != null && !argv[3].equals("")) {
+ if (argv[3].toLowerCase().equals("true") || argv[3].toLowerCase().equals("false")) {
+ printToConsole = Boolean.valueOf(argv[3]);
+ } else {
+ System.out.println("-print args error.");
+ return;
+ }
+ }
+ String password = reader.readLine("Password: ", ' ');
+ try {
+ connection = DriverManager.getConnection("jdbc:tsfile://" + argv[0] + ":" + argv[1] + "/x", argv[2],
+ password);
+ } catch (SQLTimeoutException e){
+ System.out.println("Connect Timeout: " + e.getMessage());
+ return;
+ } catch (SQLException e) {
+ System.out.println(e.getMessage());
+ return;
+ }
+
+ } catch (IOException e) {
+ System.out.println("Console Input Error:" + e.getMessage());
+ } catch (Exception e){
+ System.out.println("Unknown Error: " + e.getMessage());
+ }
+
+ System.out.println(" _______________________________.___.__ \n"
+ + " \\__ ___/ _____/\\_ _____/| | | ____ \n"
+ + " | | \\_____ \\ | __) | | | _/ __ \\ \n"
+ + " | | / \\ | \\ | | |_\\ ___/ \n"
+ + " |____| /_______ / \\___ / |___|____/\\___ > version 0.0.1\n"
+ + " \\/ \\/ \\/ \n");
+ // Login in and create connection first
+
+ System.out.println("login successfully");
+ // connection =
+ // DriverManager.getConnection("jdbc:tsfile://127.0.0.1:6667/x",
+ // "User", "HAHAH");
+
+ try {
+ while (true) {
+ s = reader.readLine("[TSFile: ] > ");
+ if (s.toLowerCase().trim().equals("quit")) {
+ System.out.println(">> TSFile Quit");
+ break;
+ }
+ if (s.toLowerCase().trim().equals("show metadata")){
+ System.out.println(connection.getMetaData());
+ continue;
+ }
+ String[] cmds = s.split(";");
+ for (int i = 0; i < cmds.length; i++) {
+ String cmd = cmds[i];
+ if (cmd != null && !cmd.trim().equals("")) {
+ Statement statement = connection.createStatement();
+ statement.setFetchSize(500000);
+ try {
+ boolean hasResultSet = statement.execute(cmd.trim());
+ if (hasResultSet) {
+ ResultSet resultSet = statement.getResultSet();
+ output(resultSet, printToConsole);
+ }
+ statement.close();
+ System.out.println("Execute successfully.");
+ } catch (TsfileSQLException e) {
+ System.out.println("statement error: " + e.getMessage());
+ } catch (Exception e){
+ System.out.println("Connection error. " + e.getMessage());
+ }
+
+ }
+ }
+ }
+ connection.close();
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ public static void output(ResultSet res, boolean printToConsole) {
+ try {
+ File file = new File("src/main/resources/output/queryRes.csv");
+ if (!file.exists()) {
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+ file.createNewFile();
+ }
+ FileWriter fw = new FileWriter(file);
+// BufferedWriter bw = new BufferedWriter(fw);
+ int cnt = 0;
+ int colCount = res.getMetaData().getColumnCount();
+ // //Output Labels
+ String format = "|%15s|";
+ String blockLine = "";
+ if (printToConsole) {
+ // System.out.printf("+---------------+");
+ // for(int i = 0 ; i < res.mapRet.keySet().size(); i++){
+ // System.out.printf("---------------+");
+ // }
+ // System.out.printf("\n");
+ //
+ // System.out.printf("|%15s|","Timestamp");
+ // for(String name : res.mapRet.keySet()){
+ // System.out.printf("%15s|", name.split(",")[1]);
+ // }
+ // System.out.printf("\n");
+ //
+
+ int maxv = 15;
+ for (int i = 0; i < colCount; i++) {
+ int len = res.getMetaData().getColumnLabel(i).length();
+ maxv = maxv < len ? len : maxv;
+ }
+
+ for (int i = 0; i < maxv; i++) {
+ blockLine += "-";
+ }
+ System.out.printf("+" + blockLine + "+");
+ for (int i = 0; i < colCount - 1; i++) {
+ System.out.printf(blockLine + "+");
+ }
+ System.out.printf("\n");
+
+ format = "%" + maxv + "s|";
+ System.out.printf("|" + format, "Timestamp");
+ for (int i = 0; i < colCount - 1; i++) {
+ System.out.printf(format, res.getMetaData().getColumnLabel(i + 1));
+ }
+ System.out.printf("\n");
+
+ System.out.printf("+" + blockLine + "+");
+ for (int i = 0; i < colCount - 1; i++) {
+ System.out.printf(blockLine + "+");
+ }
+ System.out.printf("\n");
+ }
+
+ // Output values
+ while (res.next()) {
+ StringBuilder line = new StringBuilder();
+ line.append(String.valueOf(res.getString(0)));
+
+ if (printToConsole && cnt < MAX_PRINT_ROW_COUNT) {
+ System.out.printf("|" + format, String.valueOf(res.getString(0)));
+ }
+
+ for (int i = 1; i < colCount; i++) {
+ line.append(",");
+ line.append(res.getString(i));
+ if (printToConsole && cnt < MAX_PRINT_ROW_COUNT) {
+ System.out.printf(format, String.valueOf(res.getString(i)));
+ }
+ }
+
+ if (printToConsole && cnt < MAX_PRINT_ROW_COUNT) {
+ System.out.printf("\n");
+ }
+
+// bw.write(line.toString());
+// bw.newLine();
+ cnt++;
+
+ if (!printToConsole && cnt % 10000 == 0) {
+ System.out.println(cnt);
+ }
+ }
+
+ if (printToConsole) {
+ System.out.printf("+" + blockLine + "+");
+ for (int i = 0; i < colCount - 1; i++) {
+ System.out.printf(blockLine + "+");
+ }
+ System.out.printf("\n");
+ }
+
+// bw.close();
+ System.out.println("Result size : " + cnt);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/Demo.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/Demo.java
new file mode 100644
index 00000000000..df99b5f63eb
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/Demo.java
@@ -0,0 +1,41 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class Demo {
+
+ public static void main(String[] args) throws SQLException, ClassNotFoundException {
+ Class.forName("com.corp.tsfile.jdbc.TsfileDriver");
+ Connection connection = DriverManager.getConnection("jdbc:tsfile://127.0.0.1:6667/", "root", "root");
+// Statement statement = connection.createStatement();
+// statement.addBatch("123");
+// statement.addBatch("321");
+// int[] resultSet = statement.executeBatch();
+// System.out.println(resultSet.length);
+// statement.clearBatch();
+// connection.close();
+//
+// Connection connection = DriverManager.getConnection("jdbc:tsfile://192.168.130.15:6667/","root","root");
+ DatabaseMetaData databaseMetaData = connection.getMetaData();
+ System.out.println("show metadata");
+ System.out.println(databaseMetaData);
+ // get all columns
+ ResultSet resultSet = databaseMetaData.getColumns(null, null, "car", null);
+ while(resultSet.next()){
+ System.out.println(String.format("column %s, type %s", resultSet.getString("COLUMN_NAME"), resultSet.getString("COLUMN_TYPE")));
+ }
+ // get all delta object
+ resultSet = databaseMetaData.getColumns(null, null, null, "car");
+ while(resultSet.next()){
+ System.out.println(String.format("delta object %s", resultSet.getString("DELTA_OBJECT")));
+ }
+ connection.close();
+
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/Generator.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/Generator.java
new file mode 100644
index 00000000000..9db6346512c
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/Generator.java
@@ -0,0 +1,137 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.lang.management.ManagementFactory;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import com.sun.management.OperatingSystemMXBean;
+
+import cn.edu.thu.tsfile.file.metadata.enums.TSDataType;
+import cn.edu.thu.tsfile.file.metadata.enums.TSEncoding;
+
+@SuppressWarnings("restriction")
+public class Generator {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Generator.class);
+
+ private String deviceName;
+ private OperatingSystemMXBean osmb;
+
+ private final String createTimeSeriesTemplate = "create timeseries root.%s.laptop.%s with datatype=%s,encoding=%s";
+ private final String insertDataTemplate = "insert into root.%s.laptop.%s values(%s,%s)";
+ private final String queryDataTemplate = "select laptop.* from root.%s where time < %s";
+ private final String setFileLevelTemplate = "set storage group to root.%s.laptop";
+
+ private final long SLEEP_INTERVAL = 5000;
+
+// private final String JDBC_SERVER_URL = "jdbc:tsfile://127.0.0.1:6667/x";
+ private final String JDBC_SERVER_URL = "jdbc:tsfile://192.168.130.15:6667/x";
+
+
+ public Generator(String deviceName) {
+ this.deviceName = deviceName;
+ this.osmb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
+
+ }
+
+ public void start() throws ClassNotFoundException, SQLException {
+ Class.forName("com.corp.tsfile.jdbc.TsfileDriver");
+ createTimeSeriesMetadata();
+ while (true) {
+ try {
+ insertData();
+ Thread.sleep(SLEEP_INTERVAL);
+ } catch (SQLException e) {
+ LOGGER.error("tsfile-jdbc Generator: insertData failed because ", e);
+ } catch (InterruptedException e) {
+ LOGGER.error("tsfile-jdbc Generator: thread sleep failed because ", e);
+ }
+ }
+ }
+
+ public void test() throws SQLException, ClassNotFoundException {
+ Class.forName("com.corp.tsfile.jdbc.TsfileDriver");
+ Connection connection = DriverManager.getConnection(JDBC_SERVER_URL, "root", "root");
+ Statement statement = connection.createStatement();
+ ResultSet res = statement.executeQuery(String.format(queryDataTemplate, deviceName, getCurretnTimestamp()));
+ Client.output(res, true);
+ connection.close();
+ }
+
+ private void createTimeSeriesMetadata() throws SQLException {
+ List sqls = new ArrayList<>();
+ sqls.add(String.format(createTimeSeriesTemplate, deviceName, "cpu", TSDataType.FLOAT.toString(),
+ TSEncoding.RLE.toString()));
+ sqls.add(String.format(createTimeSeriesTemplate, deviceName, "memory", TSDataType.INT64.toString(),
+ TSEncoding.RLE.toString()));
+ sqls.add(String.format(setFileLevelTemplate, deviceName));
+ executeSQL(sqls);
+ }
+
+ private void insertData() throws SQLException {
+ List sqls = new ArrayList<>();
+ String timestamp = String.valueOf(getCurretnTimestamp());
+ sqls.add(String.format(insertDataTemplate, deviceName, "cpu", timestamp, getCpuRatio()));
+ sqls.add(String.format(insertDataTemplate, deviceName, "memory", timestamp, getFreePhysicalMemorySize()));
+ executeSQL(sqls);
+ }
+
+ private void executeSQL(List sqls) throws SQLException {
+ Connection connection = null;
+ try {
+ connection = DriverManager.getConnection(JDBC_SERVER_URL, "root", "root");
+ Statement statement = connection.createStatement();
+ for (String sql : sqls) {
+ try {
+ statement.execute(sql);
+ } catch (Exception e) {
+ LOGGER.error("tsfile-jdbc Generator: execute {} failed!", sql, e);
+ continue;
+ }
+ LOGGER.info("tsfile-jdbc Generator: execute {} successfully!", sql);
+ }
+ } catch (SQLException e) {
+ LOGGER.error("tsfile-jdbc Generator: fail to execute {} because ", sqls, e);
+ } finally {
+ if (connection != null) {
+ connection.close();
+ connection = null;
+ }
+ }
+ }
+
+ public String getCpuRatio() {
+ double cpuRatio = osmb.getSystemCpuLoad() * 100;
+ if (cpuRatio < 0 || cpuRatio > 100) {
+ return "0";
+ }
+ return String.format("%.2f", cpuRatio);
+ }
+
+ private String getFreePhysicalMemorySize() {
+ long sizeFree = osmb.getFreePhysicalMemorySize();
+ return sizeFree > 0 ? String.valueOf(sizeFree) : "0";
+ }
+
+ private String getCurretnTimestamp() {
+ return String.valueOf(System.currentTimeMillis());
+ }
+
+ public static void main(String[] args) throws ClassNotFoundException, SQLException, InterruptedException {
+ Generator demo = new Generator("caogaofei_pc");
+ // insert data
+ demo.start();
+
+ // query data
+// demo.test();
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConfig.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConfig.java
new file mode 100644
index 00000000000..6e05fc4cd83
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConfig.java
@@ -0,0 +1,31 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+public class TsfileConfig {
+ /**
+ * The required prefix for the connection URL.
+ */
+ public static final String TSFILE_URL_PREFIX = "jdbc:tsfile://";
+
+ public static final String TSFILE_DEFAULT_HOST = "localhost";
+ /**
+ * If host is provided, without a port.
+ */
+ public static final int TSFILE_DEFAULT_PORT = 8888;
+
+ /**
+ * tsfile's default series name
+ */
+ public static final String DEFAULT_SERIES_NAME = "default";
+
+ public static final String URI_JDBC_PREFIX = "jdbc:";
+
+ public static final String URI_TSFILE_PREFIX = "tsfile:";
+
+ public static final int DEFAULT_FETCH_SIZE = 1000;
+
+ public static final String AUTH_USER = "user";
+ public static final String DEFAULT_USER = "user";
+
+ public static final String AUTH_PASSWORD = "password";
+ public static final String DEFALUT_PASSWORD = "password";
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConnection.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConnection.java
new file mode 100644
index 00000000000..98bf78d325c
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConnection.java
@@ -0,0 +1,454 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+import org.apache.thrift.TException;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransport;
+import org.apache.thrift.transport.TTransportException;
+
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSIService;
+import cn.edu.thu.tsfiledb.metadata.ColumnSchema;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseSessionReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSFetchMetadataReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSFetchMetadataResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSOpenSessionReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSOpenSessionResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSProtocolVersion;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TS_SessionHandle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class TsfileConnection implements Connection {
+ private static final Logger LOGGER = LoggerFactory.getLogger(TsfileConnection.class);
+ private TsfileConnectionParams params;
+ private boolean isClosed = true;
+ private SQLWarning warningChain = null;
+ private TTransport transport;
+ private TSIService.Iface client = null;
+ private TS_SessionHandle sessionHandle = null;
+ private final List supportedProtocols = new LinkedList();
+ // private int loginTimeout = 0;
+ private TSProtocolVersion protocol;
+
+ public TsfileConnection(String url, Properties info) throws SQLException, TTransportException {
+ if (url == null) {
+ throw new TsfileURLException("Input url cannot be null");
+ }
+ params = Utils.parseURL(url, info);
+
+ supportedProtocols.add(TSProtocolVersion.TSFILE_SERVICE_PROTOCOL_V1);
+
+ openTransport();
+
+ client = new TSIService.Client(new TBinaryProtocol(transport));
+ // open client session
+ openSession();
+
+ // Wrap the client with a thread-safe proxy to serialize the RPC calls
+ client = newSynchronizedClient(client);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public T unwrap(Class arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void abort(Executor arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ warningChain = null;
+ }
+
+ @Override
+ public void close() throws SQLException {
+ if (isClosed)
+ return;
+ TSCloseSessionReq req = new TSCloseSessionReq(sessionHandle);
+ try {
+ client.CloseSession(req);
+ } catch (TException e) {
+ throw new SQLException("Error occurs when closing session at server", e);
+ } finally {
+ isClosed = true;
+ if (transport != null)
+ transport.close();
+ }
+ }
+
+ @Override
+ public void commit() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Array createArrayOf(String arg0, Object[] arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Blob createBlob() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Clob createClob() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public NClob createNClob() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public SQLXML createSQLXML() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Statement createStatement() throws SQLException {
+ if (isClosed) {
+ throw new SQLException("Cannot create statement because connection is closed");
+ }
+ return new TsfileStatement(this, client, sessionHandle);
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
+ throw new SQLException(String.format("Statement with resultset concurrency %d is not supported", resultSetConcurrency));
+ }
+ if (resultSetType == ResultSet.TYPE_SCROLL_SENSITIVE) {
+ throw new SQLException(String.format("Statement with resultset type %d is not supported", resultSetType));
+ }
+ return new TsfileStatement(this, client, sessionHandle);
+ }
+
+ @Override
+ public Statement createStatement(int arg0, int arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Struct createStruct(String arg0, Object[] arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean getAutoCommit() throws SQLException {
+ return false;
+ }
+
+ @Override
+ public String getCatalog() throws SQLException {
+ return "no cata log";
+ }
+
+ @Override
+ public Properties getClientInfo() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getClientInfo(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public DatabaseMetaData getMetaData() throws SQLException {
+ if (isClosed) {
+ throw new SQLException("Cannot create statement because connection is closed");
+ }
+ try {
+ TSFetchMetadataResp resp = client.FetchMetadata(new TSFetchMetadataReq());
+ Utils.verifySuccess(resp.getStatus());
+ Map> seriesMap = Utils.convertAllSchema(resp.getSeriesMap());
+ Map> deltaObjectMap = resp.getDeltaObjectMap();
+ String metadataInJson = resp.getMetadataInJson();
+ return new TsfileDatabaseMetadata(this, seriesMap, deltaObjectMap, metadataInJson);
+ } catch (TException e) {
+ throw new SQLException("Fail to connect to server when fetching metadata because "+e.getMessage());
+ } catch (Exception e){
+ throw new SQLException("Error occurs when fetching metaData because " + e.getMessage());
+ }
+ }
+
+ @Override
+ public int getNetworkTimeout() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getSchema() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getTransactionIsolation() throws SQLException {
+ return Connection.TRANSACTION_NONE;
+ }
+
+ @Override
+ public Map> getTypeMap() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ return warningChain;
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ return isClosed;
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean isValid(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String nativeSQL(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String arg0, int arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public CallableStatement prepareCall(String arg0, int arg1, int arg2, int arg3) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void releaseSavepoint(Savepoint arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void rollback() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void rollback(Savepoint arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setAutoCommit(boolean arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setCatalog(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setClientInfo(Properties arg0) throws SQLClientInfoException {
+ throw new SQLClientInfoException("Method not supported", null);
+ }
+
+ @Override
+ public void setClientInfo(String arg0, String arg1) throws SQLClientInfoException {
+ throw new SQLClientInfoException("Method not supported", null);
+ }
+
+ @Override
+ public void setHoldability(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setNetworkTimeout(Executor arg0, int arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setReadOnly(boolean arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Savepoint setSavepoint() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Savepoint setSavepoint(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setSchema(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setTransactionIsolation(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setTypeMap(Map> arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ private void openTransport() throws TTransportException {
+ transport = new TSocket(params.getHost(), params.getPort());
+ if (!transport.isOpen()) {
+ transport.open();
+ LOGGER.debug("Connect to host {} port {}",params.getHost(),params.getPort());
+ }
+ }
+
+ private void openSession() throws SQLException {
+ TSOpenSessionReq openReq = new TSOpenSessionReq(TSProtocolVersion.TSFILE_SERVICE_PROTOCOL_V1);
+
+ openReq.setUsername(params.getUsername());
+ openReq.setPassword(params.getPassword());
+
+ try {
+ TSOpenSessionResp openResp = client.OpenSession(openReq);
+
+ // validate connection
+ Utils.verifySuccess(openResp.getStatus());
+ if (!supportedProtocols.contains(openResp.getServerProtocolVersion())) {
+ throw new TException("Unsupported tsfile protocol");
+ }
+ setProtocol(openResp.getServerProtocolVersion());
+ sessionHandle = openResp.getSessionHandle();
+ } catch (TException e) {
+ throw new SQLException(String.format("Can not establish connection with %s. because %s",
+ params.getJdbcUriString()), e.getMessage());
+ }
+ isClosed = false;
+ }
+
+ public static TSIService.Iface newSynchronizedClient(TSIService.Iface client) {
+ return (TSIService.Iface) Proxy.newProxyInstance(TsfileConnection.class.getClassLoader(),
+ new Class[] { TSIService.Iface.class }, new SynchronizedHandler(client));
+ }
+
+ public TSProtocolVersion getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(TSProtocolVersion protocol) {
+ this.protocol = protocol;
+ }
+
+ private static class SynchronizedHandler implements InvocationHandler {
+ private final TSIService.Iface client;
+
+ SynchronizedHandler(TSIService.Iface client) {
+ this.client = client;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ try {
+ synchronized (client) {
+ return method.invoke(client, args);
+ }
+ } catch (InvocationTargetException e) {
+ // all IFace APIs throw TException
+ if (e.getTargetException() instanceof TException) {
+ throw (TException) e.getTargetException();
+ } else {
+ // should not happen
+ throw new TException("Error in calling method " + method.getName(), e.getTargetException());
+ }
+ } catch (Exception e) {
+ throw new TException("Error in calling method " + method.getName(), e);
+ }
+ }
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConnectionParams.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConnectionParams.java
new file mode 100644
index 00000000000..dd1e8f6453a
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileConnectionParams.java
@@ -0,0 +1,59 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+public class TsfileConnectionParams {
+ private String host = TsfileConfig.TSFILE_DEFAULT_HOST;
+ private int port = TsfileConfig.TSFILE_DEFAULT_PORT;
+ private String jdbcUriString;
+ private String seriesName = TsfileConfig.DEFAULT_SERIES_NAME;
+ private String username = TsfileConfig.DEFAULT_USER;
+ private String password = TsfileConfig.DEFALUT_PASSWORD;
+ private String dbName;
+
+ public TsfileConnectionParams(String url){
+ this.jdbcUriString = url;
+ }
+
+ public String getHost() {
+ return host;
+ }
+ public void setHost(String host) {
+ this.host = host;
+ }
+ public int getPort() {
+ return port;
+ }
+ public void setPort(int port) {
+ this.port = port;
+ }
+ public String getJdbcUriString() {
+ return jdbcUriString;
+ }
+ public void setJdbcUriString(String jdbcUriString) {
+ this.jdbcUriString = jdbcUriString;
+ }
+ public String getSeriesName() {
+ return seriesName;
+ }
+ public void setSeriesName(String seriesName) {
+ this.seriesName = seriesName;
+ }
+ public String getUsername() {
+ return username;
+ }
+ public void setUsername(String username) {
+ this.username = username;
+ }
+ public String getPassword() {
+ return password;
+ }
+ public void setPassword(String password) {
+ this.password = password;
+ }
+ public String getDbName() {
+ return dbName;
+ }
+ public void setDbName(String dbName) {
+ this.dbName = dbName;
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileDatabaseMetadata.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileDatabaseMetadata.java
new file mode 100644
index 00000000000..544620c2cf7
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileDatabaseMetadata.java
@@ -0,0 +1,1117 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.RowIdLifetime;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+
+import cn.edu.thu.tsfiledb.metadata.ColumnSchema;
+
+
+public class TsfileDatabaseMetadata implements DatabaseMetaData {
+
+ private TsfileConnection connection;
+ private Map> seriesMap;
+ private Map> deltaObjectMap;
+ private String metadataInJson;
+
+ public TsfileDatabaseMetadata(TsfileConnection connection, Map> seriesMap, Map> deltaObjectMap, String metadataInJson) {
+ this.connection = connection;
+ this.seriesMap = seriesMap;
+ this.deltaObjectMap = deltaObjectMap;
+ this.metadataInJson = metadataInJson;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public T unwrap(Class iface) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean allProceduresAreCallable() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean allTablesAreSelectable() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean deletesAreDetected(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean generatedKeyAlwaysReturned() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getAttributes(String arg0, String arg1, String arg2, String arg3) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getBestRowIdentifier(String arg0, String arg1, String arg2, int arg3, boolean arg4)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getCatalogSeparator() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getCatalogTerm() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getCatalogs() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getClientInfoProperties() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getColumnPrivileges(String arg0, String arg1, String arg2, String arg3) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getColumns(String catalog, String schemaPattern, String columnPattern, String deltaObjectPattern) throws SQLException {
+ if(deltaObjectPattern != null){
+ if(deltaObjectMap == null){
+ throw new SQLException("No delta object metadata");
+ }
+ List deltaObjectList = deltaObjectMap.get(deltaObjectPattern);
+ if(deltaObjectList == null){
+ throw new SQLException(String.format("Cannot find delta object %s", deltaObjectPattern));
+ }
+ return new TsfileMetadataResultSet(null, deltaObjectList);
+ }
+
+ if(columnPattern != null){
+ if(seriesMap == null){
+ throw new SQLException("No schema for TsfileDatabaseMetadata");
+ }
+ List columnSchemas = seriesMap.get(columnPattern);
+
+ if(columnSchemas == null){
+ throw new SQLException(String.format("Cannot find table %s",columnPattern));
+ }
+
+ return new TsfileMetadataResultSet(columnSchemas, null);
+ }
+
+ return null;
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ return connection;
+ }
+
+ @Override
+ public ResultSet getCrossReference(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getDatabaseMajorVersion() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getDatabaseMinorVersion() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getDatabaseProductName() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getDatabaseProductVersion() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getDefaultTransactionIsolation() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getDriverMajorVersion() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getDriverMinorVersion() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getDriverName() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getDriverVersion() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getExportedKeys(String arg0, String arg1, String arg2) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getExtraNameCharacters() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getFunctionColumns(String arg0, String arg1, String arg2, String arg3) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getFunctions(String arg0, String arg1, String arg2) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getIdentifierQuoteString() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getImportedKeys(String arg0, String arg1, String arg2) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getIndexInfo(String arg0, String arg1, String arg2, boolean arg3, boolean arg4)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getJDBCMajorVersion() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getJDBCMinorVersion() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxBinaryLiteralLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxCatalogNameLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxCharLiteralLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxColumnNameLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxColumnsInGroupBy() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxColumnsInIndex() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxColumnsInOrderBy() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxColumnsInSelect() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxColumnsInTable() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxConnections() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxCursorNameLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxIndexLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxProcedureNameLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxRowSize() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxSchemaNameLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxStatementLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxStatements() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxTableNameLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxTablesInSelect() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMaxUserNameLength() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getNumericFunctions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getPrimaryKeys(String arg0, String arg1, String arg2) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getProcedureColumns(String arg0, String arg1, String arg2, String arg3) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getProcedureTerm() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getProcedures(String arg0, String arg1, String arg2) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern,
+ String columnNamePattern) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getResultSetHoldability() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public RowIdLifetime getRowIdLifetime() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getSQLKeywords() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getSQLStateType() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getSchemaTerm() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getSchemas() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getSearchStringEscape() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getStringFunctions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getSystemFunctions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getTableTypes() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getTimeDateFunctions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getTypeInfo() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getURL() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getUserName() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean insertsAreDetected(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean isCatalogAtStart() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean locatorsUpdateCopy() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean nullPlusNonNullIsNull() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean nullsAreSortedAtEnd() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean nullsAreSortedAtStart() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean nullsAreSortedHigh() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean nullsAreSortedLow() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean othersDeletesAreVisible(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean othersInsertsAreVisible(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean othersUpdatesAreVisible(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean ownDeletesAreVisible(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean ownInsertsAreVisible(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean ownUpdatesAreVisible(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean storesLowerCaseIdentifiers() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean storesMixedCaseIdentifiers() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean storesUpperCaseIdentifiers() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsANSI92EntryLevelSQL() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsANSI92FullSQL() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsANSI92IntermediateSQL() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsAlterTableWithAddColumn() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsAlterTableWithDropColumn() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsBatchUpdates() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsCatalogsInDataManipulation() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsCatalogsInProcedureCalls() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsCatalogsInTableDefinitions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsColumnAliasing() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsConvert() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsConvert(int fromType, int toType) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsCoreSQLGrammar() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsCorrelatedSubqueries() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsDifferentTableCorrelationNames() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsExpressionsInOrderBy() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsExtendedSQLGrammar() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsFullOuterJoins() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsGetGeneratedKeys() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsGroupBy() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsGroupByBeyondSelect() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsGroupByUnrelated() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsIntegrityEnhancementFacility() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsLikeEscapeClause() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsLimitedOuterJoins() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsMinimumSQLGrammar() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsMixedCaseIdentifiers() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsMultipleOpenResults() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsMultipleResultSets() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsMultipleTransactions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsNamedParameters() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsNonNullableColumns() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsOrderByUnrelated() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsOuterJoins() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsPositionedDelete() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsPositionedUpdate() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsResultSetHoldability(int holdability) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsResultSetType(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSavepoints() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSchemasInDataManipulation() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSchemasInIndexDefinitions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSchemasInProcedureCalls() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSchemasInTableDefinitions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSelectForUpdate() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsStatementPooling() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsStoredProcedures() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSubqueriesInComparisons() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSubqueriesInExists() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSubqueriesInIns() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsSubqueriesInQuantifieds() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsTableCorrelationNames() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsTransactions() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsUnion() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean supportsUnionAll() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean updatesAreDetected(int type) throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean usesLocalFilePerTable() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean usesLocalFiles() throws SQLException {
+ // TODO Auto-generated method stub
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String toString(){
+ return metadataInJson;
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileDriver.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileDriver.java
new file mode 100644
index 00000000000..4efa6fc81db
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileDriver.java
@@ -0,0 +1,77 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+import org.apache.thrift.transport.TTransportException;
+
+
+public class TsfileDriver implements Driver {
+ private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(TsfileDriver.class);
+
+ static {
+ try {
+ java.sql.DriverManager.registerDriver(new TsfileDriver());
+ } catch (SQLException e) {
+ LOGGER.error("Error occurs when resgistering tsfile driver",e);
+ }
+ }
+
+ /**
+ * Is this driver JDBC compliant?
+ */
+ private static final boolean TSFILE_JDBC_COMPLIANT = false;
+
+ public TsfileDriver() {
+
+ }
+
+ @Override
+ public boolean acceptsURL(String url) throws SQLException {
+ return Pattern.matches(TsfileConfig.TSFILE_URL_PREFIX+".*", url);
+ }
+
+ @Override
+ public Connection connect(String url, Properties info) throws SQLException {
+ try {
+ return acceptsURL(url) ? new TsfileConnection(url, info) : null;
+ } catch (TTransportException e) {
+ throw new SQLException("Connection Error, Please check whether the network is avalible or the server has started. " + e.getMessage());
+ }
+ }
+
+ @Override
+ public int getMajorVersion() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getMinorVersion() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ throw new SQLFeatureNotSupportedException("Method not supported");
+ }
+
+ @Override
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean jdbcCompliant() {
+ return TSFILE_JDBC_COMPLIANT;
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileMetadataResultSet.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileMetadataResultSet.java
new file mode 100644
index 00000000000..d5ba3b0d681
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileMetadataResultSet.java
@@ -0,0 +1,257 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.sql.Time;
+import java.util.Iterator;
+import java.util.List;
+
+import cn.edu.thu.tsfiledb.metadata.ColumnSchema;
+
+
+
+public class TsfileMetadataResultSet extends TsfileQueryResultSet {
+
+ private Iterator> columnItr;
+ private ColumnSchema currentColumn;
+ private String currentDeltaObject;
+ private MetadataType type;
+
+ public TsfileMetadataResultSet(List columnSchemas, List deltaObjectList) {
+ if (columnSchemas != null) {
+ columnItr = columnSchemas.iterator();
+ type = MetadataType.COLUMN;
+ } else if (deltaObjectList != null) {
+ columnItr = deltaObjectList.iterator();
+ type = MetadataType.DELTA_OBJECT;
+ }
+ }
+
+ @Override
+ public void close() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int findColumn(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean getBoolean(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean getBoolean(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public byte getByte(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public byte getByte(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public byte[] getBytes(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public byte[] getBytes(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getConcurrency() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Date getDate(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Date getDate(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public double getDouble(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public double getDouble(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getFetchDirection() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public float getFloat(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public float getFloat(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getInt(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getInt(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public long getLong(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public long getLong(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public ResultSetMetaData getMetaData() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean next() throws SQLException {
+ boolean hasNext = columnItr.hasNext();
+ switch (type) {
+ case COLUMN:
+ if (hasNext) {
+ currentColumn = (ColumnSchema)columnItr.next();
+ }
+ return hasNext;
+ case DELTA_OBJECT:
+ if (hasNext) {
+ currentDeltaObject = (String)columnItr.next();
+ }
+ return hasNext;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ public Object getObject(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Object getObject(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public short getShort(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public short getShort(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Statement getStatement() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getString(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getString(String columnName) throws SQLException {
+ switch (columnName) {
+ case "COLUMN_NAME":
+ return currentColumn.name;
+ case "COLUMN_TYPE":
+ return currentColumn.dataType.toString();
+ case "DELTA_OBJECT":
+ return currentDeltaObject;
+ default:
+ break;
+ }
+ return null;
+ }
+
+ @Override
+ public Time getTime(int columnIndex) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Time getTime(String columnName) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getType() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean wasNull() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ private enum MetadataType{
+ DELTA_OBJECT, COLUMN;
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileQueryResultSet.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileQueryResultSet.java
new file mode 100644
index 00000000000..324df33788c
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileQueryResultSet.java
@@ -0,0 +1,1119 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.thrift.TException;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseOperationReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseOperationResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSFetchResultsReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSFetchResultsResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSIService;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSOperationHandle;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TS_SessionHandle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet;
+import cn.edu.thu.tsfile.timeseries.read.readSupport.RowRecord;
+
+
+
+public class TsfileQueryResultSet implements ResultSet {
+ private static final Logger LOGGER = LoggerFactory.getLogger(TsfileQueryResultSet.class);
+
+ private Statement statement = null;
+ private String sql;
+ private SQLWarning warningChain = null;
+ private boolean wasNull = false;
+ private boolean isClosed = false;
+ private TSIService.Iface client = null;
+// private TS_SessionHandle sessionHandle = null;
+ private TSOperationHandle operationHandle = null;
+ private Map columnInfo;
+ private RowRecord record;
+ private Iterator recordItr;
+ private int rowsFetched = 0;
+ private int maxRows;
+ private int fetchSize;
+ boolean emptyResultSet = false;
+
+ public TsfileQueryResultSet(){
+
+ }
+
+ public TsfileQueryResultSet(Statement statement,List columnName,
+ TSIService.Iface client, TS_SessionHandle sessionHandle ,
+ TSOperationHandle operationHandle, String sql) throws SQLException {
+ this.statement = statement;
+ this.sql = sql;
+ this.columnInfo = new HashMap<>();
+ this.client = client;
+ this.operationHandle = operationHandle;
+// this.sessionHandle = sessionHandle;
+ columnInfo.put("Timestamp", 0);
+ int index = 1;
+ for(String name : columnName){
+ columnInfo.put(name, index++);
+ }
+ this.maxRows = statement.getMaxRows();
+ this.fetchSize = statement.getFetchSize();
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public T unwrap(Class iface) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean absolute(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void afterLast() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void beforeFirst() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void cancelRowUpdates() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ warningChain = null;
+ }
+
+ @Override
+ public void close() throws SQLException {
+ if(isClosed) return;
+// if (this.statement != null && (this.statement instanceof TsfileStatement)) {
+// TsfileStatement s = (TsfileStatement) this.statement;
+// s.closeClientOperation();
+// } else{
+ closeOperationHandle();
+// }
+ client = null;
+// sessionHandle = null;
+ isClosed = true;
+ }
+
+ private void closeOperationHandle() throws SQLException{
+ try {
+ if (operationHandle != null) {
+ TSCloseOperationReq closeReq = new TSCloseOperationReq(operationHandle);
+ TSCloseOperationResp closeResp = client.CloseOperation(closeReq);
+ Utils.verifySuccess(closeResp.getStatus());
+ }
+ } catch (SQLException e) {
+ throw new SQLException("Error occurs for close opeation in server side becasuse "+e.getMessage());
+ } catch (TException e) {
+ throw new SQLException("Error occurs when connecting to server for close operation, becasue: "+e.getMessage());
+ }
+ }
+
+ @Override
+ public void deleteRow() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int findColumn(String columnName) throws SQLException {
+ Integer column = columnInfo.get(columnName);
+ if(column == null){
+ throw new SQLException(String.format("Column %s does not exist", columnName));
+ }
+ return column;
+ }
+
+ @Override
+ public boolean first() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Array getArray(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Array getArray(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public InputStream getAsciiStream(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public InputStream getAsciiStream(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ return new BigDecimal(getValue(columnIndex));
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(String columnName) throws SQLException {
+ return getBigDecimal(findColumn(columnName));
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
+ MathContext mc = new MathContext(scale);
+ return getBigDecimal(columnIndex).round(mc);
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
+ return getBigDecimal(findColumn(columnName),scale);
+ }
+
+ @Override
+ public InputStream getBinaryStream(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public InputStream getBinaryStream(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Blob getBlob(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Blob getBlob(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean getBoolean(int columnIndex) throws SQLException {
+ String b = getValue(columnIndex);
+ if(b.trim().equalsIgnoreCase("0")) return false;
+ if(b.trim().equalsIgnoreCase("1")) return true;
+ return Boolean.parseBoolean(getValue(columnIndex));
+ }
+
+ @Override
+ public boolean getBoolean(String columnName) throws SQLException {
+ return getBoolean(findColumn(columnName));
+ }
+
+ @Override
+ public byte getByte(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public byte getByte(String columnName) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public byte[] getBytes(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public byte[] getBytes(String columnName) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Reader getCharacterStream(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Reader getCharacterStream(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Clob getClob(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Clob getClob(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getConcurrency() throws SQLException {
+ return ResultSet.CONCUR_READ_ONLY;
+ }
+
+ @Override
+ public String getCursorName() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Date getDate(int columnIndex) throws SQLException {
+ return new Date(getLong(columnIndex));
+ }
+
+ @Override
+ public Date getDate(String columnName) throws SQLException {
+ return getDate(findColumn(columnName));
+ }
+
+ @Override
+ public Date getDate(int arg0, Calendar arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Date getDate(String arg0, Calendar arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public double getDouble(int columnIndex) throws SQLException {
+ return Double.parseDouble(getValue(columnIndex));
+ }
+
+ @Override
+ public double getDouble(String columnName) throws SQLException {
+ return getDouble(findColumn(columnName));
+ }
+
+ @Override
+ public int getFetchDirection() throws SQLException {
+ return ResultSet.FETCH_FORWARD;
+ }
+
+ @Override
+ public int getFetchSize() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public float getFloat(int columnIndex) throws SQLException {
+ return Float.parseFloat(getValue(columnIndex));
+ }
+
+ @Override
+ public float getFloat(String columnName) throws SQLException {
+ return getFloat(findColumn(columnName));
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getInt(int columnIndex) throws SQLException {
+ return Integer.parseInt(getValue(columnIndex));
+ }
+
+ @Override
+ public int getInt(String columnName) throws SQLException {
+ return getInt(findColumn(columnName));
+ }
+
+ @Override
+ public long getLong(int columnIndex) throws SQLException {
+ return Long.parseLong(getValue(columnIndex));
+ }
+
+ @Override
+ public long getLong(String columnName) throws SQLException {
+ return getLong(findColumn(columnName));
+ }
+
+ @Override
+ public ResultSetMetaData getMetaData() throws SQLException {
+ return new TsfileResultMetadata(columnInfo);
+ }
+
+ @Override
+ public Reader getNCharacterStream(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Reader getNCharacterStream(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public NClob getNClob(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public NClob getNClob(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getNString(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public String getNString(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Object getObject(int columnIndex) throws SQLException {
+ return getValue(columnIndex);
+ }
+
+ @Override
+ public Object getObject(String columnName) throws SQLException {
+ return getObject(findColumn(columnName));
+ }
+
+ @Override
+ public Object getObject(int arg0, Map> arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Object getObject(String arg0, Map> arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public T getObject(int arg0, Class arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public T getObject(String arg0, Class arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Ref getRef(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Ref getRef(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getRow() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public RowId getRowId(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public RowId getRowId(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public SQLXML getSQLXML(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public SQLXML getSQLXML(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public short getShort(int columnIndex) throws SQLException {
+ return Short.parseShort(getValue(columnIndex));
+ }
+
+ @Override
+ public short getShort(String columnName) throws SQLException {
+ return getShort(findColumn(columnName));
+ }
+
+ @Override
+ public Statement getStatement() throws SQLException {
+ return this.statement;
+ }
+
+ @Override
+ public String getString(int columnIndex) throws SQLException {
+ return getValue(columnIndex);
+ }
+
+ @Override
+ public String getString(String columnName) throws SQLException {
+ return getString(findColumn(columnName));
+ }
+
+ @Override
+ public Time getTime(int columnIndex) throws SQLException {
+ return new Time(getLong(columnIndex));
+ }
+
+ @Override
+ public Time getTime(String columnName) throws SQLException {
+ return getTime(findColumn(columnName));
+ }
+
+ @Override
+ public Time getTime(int arg0, Calendar arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Time getTime(String arg0, Calendar arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Timestamp getTimestamp(int columnIndex) throws SQLException {
+ return new Timestamp(getLong(columnIndex));
+ }
+
+ @Override
+ public Timestamp getTimestamp(String columnName) throws SQLException {
+ return getTimestamp(findColumn(columnName));
+ }
+
+ @Override
+ public Timestamp getTimestamp(int arg0, Calendar arg1) throws SQLException {
+ throw new SQLException("Method not supported"); }
+
+ @Override
+ public Timestamp getTimestamp(String arg0, Calendar arg1) throws SQLException {
+ throw new SQLException("Method not supported"); }
+
+ @Override
+ public int getType() throws SQLException {
+ return ResultSet.TYPE_FORWARD_ONLY;
+ }
+
+ @Override
+ public URL getURL(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public URL getURL(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public InputStream getUnicodeStream(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public InputStream getUnicodeStream(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ return warningChain;
+ }
+
+ @Override
+ public void insertRow() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean isAfterLast() throws SQLException {
+ throw new SQLException("Method not supported"); }
+
+ @Override
+ public boolean isBeforeFirst() throws SQLException {
+ throw new SQLException("Method not supported"); }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ return isClosed;
+ }
+
+ @Override
+ public boolean isFirst() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean isLast() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean last() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void moveToCurrentRow() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void moveToInsertRow() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean next() throws SQLException {
+ if(maxRows > 0 && rowsFetched >= maxRows){
+ if(LOGGER.isInfoEnabled()) LOGGER.info("tsfile-jdbc TsfileResultSet: reach max rows {}", maxRows);
+ return false;
+ }
+
+ if((recordItr == null || !recordItr.hasNext()) && !emptyResultSet){
+ TSFetchResultsReq req = new TSFetchResultsReq(sql,fetchSize);
+ try {
+ TSFetchResultsResp resp = client.FetchResults(req);
+ Utils.verifySuccess(resp.status);
+ if(!resp.hasResultSet){
+ emptyResultSet = true;
+ }else{
+ QueryDataSet queryDataSet = Utils.convertQueryDataSet(resp.getQueryDataSet());
+ List records = new ArrayList<>();
+ while(queryDataSet.hasNextRecord()){
+ records.add(queryDataSet.getNextRecord());
+ }
+
+ recordItr = records.iterator();
+ }
+ } catch (TException e) {
+ throw new SQLException("Cannot fetch result from server, because "+e.getMessage());
+ }
+ }
+
+ if(emptyResultSet){
+ return false;
+ }
+ record = recordItr.next();
+ rowsFetched++;
+ return true;
+ }
+
+ @Override
+ public boolean previous() throws SQLException {
+ throw new SQLException("Method not supported"); }
+
+ @Override
+ public void refreshRow() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean relative(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean rowDeleted() throws SQLException {
+ throw new SQLException("Method not supported"); }
+
+ @Override
+ public boolean rowInserted() throws SQLException {
+ throw new SQLException("Method not supported"); }
+
+ @Override
+ public boolean rowUpdated() throws SQLException {
+ throw new SQLException("Method not supported"); }
+
+ @Override
+ public void setFetchDirection(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setFetchSize(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateArray(int arg0, Array arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateArray(String arg0, Array arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateAsciiStream(int arg0, InputStream arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateAsciiStream(String arg0, InputStream arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateAsciiStream(int arg0, InputStream arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateAsciiStream(String arg0, InputStream arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateAsciiStream(int arg0, InputStream arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateAsciiStream(String arg0, InputStream arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBigDecimal(int arg0, BigDecimal arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBigDecimal(String arg0, BigDecimal arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBinaryStream(int arg0, InputStream arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBinaryStream(String arg0, InputStream arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBinaryStream(int arg0, InputStream arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBinaryStream(String arg0, InputStream arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBinaryStream(int arg0, InputStream arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBinaryStream(String arg0, InputStream arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBlob(int arg0, Blob arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBlob(String arg0, Blob arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBlob(int arg0, InputStream arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBlob(String arg0, InputStream arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBlob(int arg0, InputStream arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBlob(String arg0, InputStream arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBoolean(int arg0, boolean arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBoolean(String arg0, boolean arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateByte(int arg0, byte arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateByte(String arg0, byte arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBytes(int arg0, byte[] arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateBytes(String arg0, byte[] arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateCharacterStream(int arg0, Reader arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateCharacterStream(String arg0, Reader arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateCharacterStream(int arg0, Reader arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateCharacterStream(String arg0, Reader arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateCharacterStream(int arg0, Reader arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateCharacterStream(String arg0, Reader arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateClob(int arg0, Clob arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateClob(String arg0, Clob arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateClob(int arg0, Reader arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateClob(String arg0, Reader arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateClob(int arg0, Reader arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+
+ }
+
+ @Override
+ public void updateClob(String arg0, Reader arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateDate(int arg0, Date arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateDate(String arg0, Date arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateDouble(int arg0, double arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateDouble(String arg0, double arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateFloat(int arg0, float arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateFloat(String arg0, float arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateInt(int arg0, int arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateInt(String arg0, int arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateLong(int arg0, long arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateLong(String arg0, long arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNCharacterStream(int arg0, Reader arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNCharacterStream(String arg0, Reader arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNCharacterStream(int arg0, Reader arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNCharacterStream(String arg0, Reader arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNClob(int arg0, NClob arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNClob(String arg0, NClob arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNClob(int arg0, Reader arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNClob(String arg0, Reader arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNClob(int arg0, Reader arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNClob(String arg0, Reader arg1, long arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNString(int arg0, String arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNString(String arg0, String arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNull(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateNull(String arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateObject(int arg0, Object arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateObject(String arg0, Object arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateObject(int arg0, Object arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateObject(String arg0, Object arg1, int arg2) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateRef(int arg0, Ref arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateRef(String arg0, Ref arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateRow() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateRowId(int arg0, RowId arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateRowId(String arg0, RowId arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateSQLXML(int arg0, SQLXML arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateSQLXML(String arg0, SQLXML arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateShort(int arg0, short arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateShort(String arg0, short arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateString(int arg0, String arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateString(String arg0, String arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateTime(int arg0, Time arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateTime(String arg0, Time arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateTimestamp(int arg0, Timestamp arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void updateTimestamp(String arg0, Timestamp arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean wasNull() throws SQLException {
+ return wasNull;
+ }
+
+ private void checkRecord() throws SQLException{
+ if(record == null){
+ throw new SQLException("No record remains");
+ }
+ }
+
+ private String getValue(int columnIndex) throws SQLException{
+ checkRecord();
+ if(columnIndex == 0){
+ return String.valueOf(record.getTime());
+ }
+ int len = record.fields.size();
+ if(columnIndex > len || len == 0){
+ throw new SQLException(String.format("columnIndex %d out of range %d",columnIndex,len));
+ }
+ return record.fields.get(columnIndex-1).getStringValue();
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileResultMetadata.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileResultMetadata.java
new file mode 100644
index 00000000000..a5e72d15b95
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileResultMetadata.java
@@ -0,0 +1,169 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.Map;
+
+public class TsfileResultMetadata implements ResultSetMetaData {
+ private Map columnInfo;
+
+ public TsfileResultMetadata(Map columnInfo) {
+ this.columnInfo = columnInfo;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public T unwrap(Class arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getCatalogName(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getColumnClassName(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getColumnCount() throws SQLException {
+ if (columnInfo == null || columnInfo.keySet() == null || columnInfo.keySet().size() == 0) {
+ throw new SQLException("No column exists");
+ }
+ return columnInfo.keySet().size();
+ }
+
+ @Override
+ public int getColumnDisplaySize(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getColumnLabel(int column) throws SQLException {
+ if (columnInfo == null || columnInfo.keySet() == null || columnInfo.keySet().size() == 0) {
+ throw new SQLException("No column exists");
+ }
+
+ for (Map.Entry entry : columnInfo.entrySet()) {
+ if (entry.getValue().equals(column)) {
+ return String.format(entry.getKey());
+ }
+ }
+ throw new SQLException(String.format("column %d does not exist", column));
+ }
+
+ @Override
+ public String getColumnName(int column) throws SQLException {
+ if (columnInfo == null || columnInfo.keySet() == null || columnInfo.keySet().size() == 0) {
+ throw new SQLException("tNo column exists");
+ }
+ for (Map.Entry entry : columnInfo.entrySet()) {
+ if (entry.getValue().equals(column)) {
+ return entry.getKey();
+ }
+ }
+ throw new SQLException(String.format("column %d does not exist", column));
+ }
+
+ @Override
+ public int getColumnType(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getColumnTypeName(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getPrecision(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public int getScale(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public String getSchemaName(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getTableName(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isAutoIncrement(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isCaseSensitive(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isCurrency(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isDefinitelyWritable(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public int isNullable(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public boolean isReadOnly(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isSearchable(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isSigned(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isWritable(int arg0) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileSQLException.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileSQLException.java
new file mode 100644
index 00000000000..394234c409c
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileSQLException.java
@@ -0,0 +1,24 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.sql.SQLException;
+
+public class TsfileSQLException extends SQLException{
+ private String errorMessage;
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3306001287342258977L;
+
+ public TsfileSQLException(String reason){
+ super(reason);
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileStatement.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileStatement.java
new file mode 100644
index 00000000000..99ba7c158ce
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileStatement.java
@@ -0,0 +1,411 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.thrift.TException;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCancelOperationReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCancelOperationResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseOperationReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseOperationResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSExecuteBatchStatementReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSExecuteBatchStatementResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSExecuteStatementReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSExecuteStatementResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSIService;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSOperationHandle;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TS_SessionHandle;
+
+public class TsfileStatement implements Statement {
+
+ private ResultSet resultSet = null;
+ private final TsfileConnection connection;
+ private int fetchSize = TsfileConfig.DEFAULT_FETCH_SIZE;
+ private int queryTimeout = 10;
+ private TSIService.Iface client = null;
+ private TS_SessionHandle sessionHandle = null;
+ private TSOperationHandle operationHandle = null;
+ private List batchSQLList;
+
+ /**
+ * Keep state so we can fail certain calls made after close().
+ */
+ private boolean isClosed = false;
+
+ /**
+ * Keep state so we can fail certain calls made after cancel().
+ */
+ private boolean isCancelled = false;
+
+ /**
+ * Sets the limit for the maximum number of rows that any ResultSet object
+ * produced by this Statement can contain to the given number. If the limit
+ * is exceeded, the excess rows are silently dropped. The value must be >=
+ * 0, and 0 means there is not limit.
+ */
+ private int maxRows = 0;
+
+ /**
+ * Add SQLWarnings to the warningChain if needed.
+ */
+ private SQLWarning warningChain = null;
+
+ public TsfileStatement(TsfileConnection connection, TSIService.Iface client, TS_SessionHandle sessionHandle,
+ int fetchSize) {
+ this.connection = connection;
+ this.client = client;
+ this.sessionHandle = sessionHandle;
+ this.fetchSize = fetchSize;
+ this.batchSQLList = new ArrayList<>();
+ }
+
+ public TsfileStatement(TsfileConnection connection, TSIService.Iface client, TS_SessionHandle sessionHandle){
+ this(connection, client, sessionHandle, TsfileConfig.DEFAULT_FETCH_SIZE);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ return false;
+ }
+
+ @Override
+ public T unwrap(Class iface) throws SQLException {
+ throw new SQLException("Cannot unwrap to " + iface);
+ }
+
+ @Override
+ public void addBatch(String sql) throws SQLException {
+ if(batchSQLList == null){
+ batchSQLList = new ArrayList<>();
+ }
+ batchSQLList.add(sql);
+ }
+
+ @Override
+ public void cancel() throws SQLException {
+ checkConnection("cancle");
+ if(isCancelled) return;
+ try {
+ if (operationHandle != null) {
+ TSCancelOperationReq closeReq = new TSCancelOperationReq(operationHandle);
+ TSCancelOperationResp closeResp = client.CancelOperation(closeReq);
+ Utils.verifySuccess(closeResp.getStatus());
+ }
+ } catch (Exception e) {
+ throw new SQLException("Error occurs when cancling statement because "+e.getMessage());
+ }
+ isCancelled = true;
+ }
+
+ @Override
+ public void clearBatch() throws SQLException {
+ if(batchSQLList == null){
+ batchSQLList = new ArrayList<>();
+ }
+ batchSQLList.clear();
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ warningChain = null;
+ }
+
+ public void closeClientOperation() throws SQLException{
+ try {
+ if (operationHandle != null) {
+ TSCloseOperationReq closeReq = new TSCloseOperationReq(operationHandle);
+ TSCloseOperationResp closeResp = client.CloseOperation(closeReq);
+ Utils.verifySuccess(closeResp.getStatus());
+ }
+ } catch (Exception e) {
+ throw new SQLException("Error occurs when closing statement because "+e.getMessage());
+ }
+ }
+
+ @Override
+ public void close() throws SQLException {
+ if(isClosed) return;
+
+// if(resultSet != null){
+// resultSet.close();
+// resultSet = null;
+// }else{
+ closeClientOperation();
+// }
+ client = null;
+ isClosed = true;
+ }
+
+ @Override
+ public void closeOnCompletion() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean execute(String sql) throws SQLException {
+ checkConnection("execute");
+ try {
+ isCancelled = false;
+ TSExecuteStatementReq execReq = new TSExecuteStatementReq(sessionHandle, sql);
+ TSExecuteStatementResp execResp = client.ExecuteStatement(execReq);
+ operationHandle = execResp.getOperationHandle();
+ Utils.verifySuccess(execResp.getStatus());
+ if(execResp.getOperationHandle().hasResultSet){
+ resultSet = new TsfileQueryResultSet(this, execResp.getColumns(), client, sessionHandle,operationHandle, sql);
+ return true;
+ }
+ return false;
+ } catch (TException e) {
+ throw new TsfileSQLException(String.format("Fail to execute %s when connecting to server because %s", sql, e.getMessage()));
+ }
+ }
+
+ @Override
+ public boolean execute(String arg0, int arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean execute(String arg0, int[] arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public boolean execute(String arg0, String[] arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int[] executeBatch() throws SQLException {
+ checkConnection("executeBatch");
+ try {
+ isCancelled = false;
+ TSExecuteBatchStatementReq execReq = new TSExecuteBatchStatementReq(sessionHandle, batchSQLList);
+ TSExecuteBatchStatementResp execResp = client.ExecuteBatchStatement(execReq);
+ Utils.verifySuccess(execResp.getStatus());
+ if (execResp.getResult() == null){
+ return new int[0];
+ }
+ else{
+ List result = execResp.getResult();
+ int len = result.size();
+ int[] updateArray = new int[len];
+ for(int i = 0; i < len; i++){
+ updateArray[i] = result.get(i);
+ }
+ return updateArray;
+ }
+
+ } catch (TException e) {
+ throw new TsfileSQLException(String.format("Fail to execute sqls in batch when connecting to server because %s",e.getMessage()));
+ }
+
+ }
+
+ @Override
+ public ResultSet executeQuery(String sql) throws SQLException {
+ checkConnection("execute");
+ try {
+ isCancelled = false;
+ TSExecuteStatementReq execReq = new TSExecuteStatementReq(sessionHandle, sql);
+ TSExecuteStatementResp execResp = client.ExecuteQueryStatement(execReq);
+ operationHandle = execResp.getOperationHandle();
+ Utils.verifySuccess(execResp.getStatus());
+ resultSet = new TsfileQueryResultSet(this,execResp.getColumns(), client,sessionHandle,operationHandle, sql);
+ } catch (TException e) {
+ throw new TsfileSQLException(String.format("Fail to execute query sql %s when connecting to server because %s",sql,e.getMessage()));
+ }
+ return resultSet;
+ }
+
+ @Override
+ public int executeUpdate(String sql) throws SQLException {
+ try {
+ TSExecuteStatementReq execReq = new TSExecuteStatementReq(sessionHandle, sql);
+ TSExecuteStatementResp execResp = client.ExecuteUpdateStatement(execReq);
+ operationHandle = execResp.getOperationHandle();
+ Utils.verifySuccess(execResp.getStatus());
+ } catch (TException e) {
+ throw new TsfileSQLException(String.format("Fail to execute update sql %s when connecting to server because %s",sql,e.getMessage()));
+ }
+ return 0;
+ }
+
+ @Override
+ public int executeUpdate(String arg0, int arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int executeUpdate(String arg0, int[] arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int executeUpdate(String arg0, String[] arg1) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ return connection;
+ }
+
+ @Override
+ public int getFetchDirection() throws SQLException {
+ checkConnection("getFetchDirection");
+ return ResultSet.FETCH_FORWARD;
+ }
+
+ @Override
+ public int getFetchSize() throws SQLException {
+ checkConnection("getFetchSize");
+ return fetchSize;
+ }
+
+ @Override
+ public ResultSet getGeneratedKeys() throws SQLException {
+ throw new SQLFeatureNotSupportedException("Method not supported");
+ }
+
+ @Override
+ public int getMaxFieldSize() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getMaxRows() throws SQLException {
+ checkConnection("getMaxRows");
+ return maxRows;
+ }
+
+ @Override
+ public boolean getMoreResults() throws SQLException {
+ return false;
+ }
+
+ @Override
+ public boolean getMoreResults(int arg0) throws SQLException {
+ throw new SQLFeatureNotSupportedException("Method not supported");
+ }
+
+ @Override
+ public int getQueryTimeout() throws SQLException {
+ return this.queryTimeout;
+ }
+
+ @Override
+ public ResultSet getResultSet() throws SQLException {
+ checkConnection("getResultSet");
+ return resultSet;
+ }
+
+ @Override
+ public int getResultSetConcurrency() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getResultSetHoldability() throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public int getResultSetType() throws SQLException {
+ checkConnection("getResultSetType");
+ return ResultSet.TYPE_FORWARD_ONLY;
+ }
+
+ @Override
+ public int getUpdateCount() throws SQLException {
+ return 0;
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ return warningChain;
+ }
+
+ @Override
+ public boolean isCloseOnCompletion() throws SQLException {
+ return false;
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ return isClosed;
+ }
+
+ @Override
+ public boolean isPoolable() throws SQLException {
+ return false;
+ }
+
+ @Override
+ public void setCursorName(String arg0) throws SQLException {
+ throw new SQLFeatureNotSupportedException("Method not supported");
+ }
+
+ @Override
+ public void setEscapeProcessing(boolean enable) throws SQLException {
+ throw new SQLFeatureNotSupportedException("Method not supported");
+ }
+
+ @Override
+ public void setFetchDirection(int direction) throws SQLException {
+ checkConnection("setFetchDirection");
+ if (direction != ResultSet.FETCH_FORWARD) {
+ throw new SQLException(String.format("direction %d is not supported!", direction));
+ }
+ }
+
+ @Override
+ public void setFetchSize(int fetchSize) throws SQLException {
+ checkConnection("setFetchSize");
+ if (fetchSize < 0) {
+ throw new SQLException(String.format("fetchSize %d must be >= 0!", fetchSize));
+ }
+ this.fetchSize = fetchSize == 0 ? TsfileConfig.DEFAULT_FETCH_SIZE : fetchSize;
+ }
+
+ @Override
+ public void setMaxFieldSize(int arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setMaxRows(int num) throws SQLException {
+ checkConnection("setMaxRows");
+ if (num < 0) {
+ throw new SQLException(String.format("maxRows %d must be >= 0!", num));
+ }
+ this.maxRows = num;
+ }
+
+ @Override
+ public void setPoolable(boolean arg0) throws SQLException {
+ throw new SQLException("Method not supported");
+ }
+
+ @Override
+ public void setQueryTimeout(int seconds) throws SQLException {
+ checkConnection("setQueryTimeout");
+ if (seconds <= 0) {
+ throw new SQLException(String.format("queryTimeout %d must be >= 0!", seconds));
+ }
+ this.queryTimeout = seconds;
+ }
+
+ private void checkConnection(String action) throws SQLException {
+ if (isClosed) {
+ throw new SQLException(String.format("Cannot %s after statement has been closed!", action));
+ }
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileURLException.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileURLException.java
new file mode 100644
index 00000000000..1faa75bc05d
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/TsfileURLException.java
@@ -0,0 +1,15 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.sql.SQLException;
+
+public class TsfileURLException extends SQLException{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5071922897222027267L;
+
+ public TsfileURLException(String reason){
+ super(reason);
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/jdbc/Utils.java b/src/main/java/cn/edu/thu/tsfiledb/jdbc/Utils.java
new file mode 100644
index 00000000000..fcd7a9a56ac
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/jdbc/Utils.java
@@ -0,0 +1,162 @@
+package cn.edu.thu.tsfiledb.jdbc;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import cn.edu.thu.tsfile.common.utils.Binary;
+import cn.edu.thu.tsfile.file.metadata.enums.TSDataType;
+import cn.edu.thu.tsfile.file.metadata.enums.TSEncoding;
+import cn.edu.thu.tsfile.timeseries.read.query.DynamicOneColumnData;
+import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet;
+import cn.edu.thu.tsfiledb.metadata.ColumnSchema;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSColumnSchema;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSDynamicOneColumnData;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSQueryDataSet;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TS_Status;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TS_StatusCode;
+
+
+
+
+public class Utils {
+
+ /**
+ * Parse JDBC connection URL The only supported format of the URL is:
+ * jdbc:tsfile://localhost:8888/seriesName
+ *
+ * @param url
+ * @return
+ * @throws TsfileURLException
+ */
+ public static TsfileConnectionParams parseURL(String url, Properties info) throws TsfileURLException {
+ TsfileConnectionParams params = new TsfileConnectionParams(url);
+ if(url.trim().equalsIgnoreCase(TsfileConfig.TSFILE_URL_PREFIX)){
+ return params;
+ }
+
+ Pattern pattern = Pattern.compile("([^;]*):([^;]*)/");
+ Matcher matcher = pattern.matcher(url.substring(TsfileConfig.TSFILE_URL_PREFIX.length()));
+ boolean isUrlLegal = false;
+ while(matcher.find()){
+ params.setHost(matcher.group(1));
+ params.setPort(Integer.parseInt((matcher.group(2))));
+ isUrlLegal = true;
+ }
+ if(!isUrlLegal){
+ throw new TsfileURLException("Error url format, url should be jdbc:tsfile://ip:port/");
+ }
+
+ if(info.containsKey(TsfileConfig.AUTH_USER)){
+ params.setUsername(info.getProperty(TsfileConfig.AUTH_USER));
+ }
+ if(info.containsKey(TsfileConfig.AUTH_PASSWORD)){
+ params.setPassword(info.getProperty(TsfileConfig.AUTH_PASSWORD));
+ }
+
+ return params;
+ }
+
+ public static void verifySuccess(TS_Status status) throws TsfileSQLException{
+ if(status.getStatusCode() != TS_StatusCode.SUCCESS_STATUS){
+ throw new TsfileSQLException(status.errorMessage);
+ }
+ }
+
+ public static Map> convertAllSchema(Map> tsAllSchema){
+ if(tsAllSchema == null){
+ return null;
+ }
+ Map> allSchema = new HashMap<>();
+ for(Map.Entry> entry : tsAllSchema.entrySet()){
+ List columnSchemas = new ArrayList<>();
+ for(TSColumnSchema columnSchema : entry.getValue()){
+ columnSchemas.add(convertColumnSchema(columnSchema));
+ }
+ allSchema.put(entry.getKey(), columnSchemas);
+ }
+ return allSchema;
+ }
+
+ public static ColumnSchema convertColumnSchema(TSColumnSchema tsSchema){
+ if(tsSchema == null){
+ return null;
+ }
+ TSDataType dataType = tsSchema.dataType == null ? null : TSDataType.valueOf(tsSchema.dataType);
+ TSEncoding encoding = tsSchema.encoding == null ? null : TSEncoding.valueOf(tsSchema.encoding);
+ ColumnSchema ColumnSchema = new ColumnSchema(tsSchema.name, dataType, encoding);
+ ColumnSchema.setArgsMap(tsSchema.getOtherArgs());
+ return ColumnSchema;
+ }
+
+ public static QueryDataSet convertQueryDataSet(TSQueryDataSet tsQueryDataSet){
+ QueryDataSet queryDataSet = new QueryDataSet();
+ List keys = tsQueryDataSet.getKeys();
+ List values = tsQueryDataSet.getValues();
+
+ LinkedHashMap ret = new LinkedHashMap<>();
+ int length = keys.size();
+ for(int i = 0; i < length;i++){
+ ret.put(keys.get(i), convertDynamicOneColumnData(values.get(i)));
+ }
+ queryDataSet.mapRet = ret;
+ return queryDataSet;
+ }
+
+ public static DynamicOneColumnData convertDynamicOneColumnData(TSDynamicOneColumnData tsDynamicOneColumnData){
+ TSDataType dataType = TSDataType.valueOf(tsDynamicOneColumnData.getDataType());
+ DynamicOneColumnData dynamicOneColumnData = new DynamicOneColumnData(dataType,true);
+ dynamicOneColumnData.setDeltaObjectType(tsDynamicOneColumnData.getDeviceType());
+
+ for(long time : tsDynamicOneColumnData.getTimeRet()){
+ dynamicOneColumnData.putTime(time);
+ }
+
+ switch (dataType) {
+ case BOOLEAN:
+ List booleans = tsDynamicOneColumnData.getBoolList();
+ for(Boolean b: booleans){
+ dynamicOneColumnData.putBoolean(b);
+ }
+ break;
+ case INT32:
+ List integers = tsDynamicOneColumnData.getI32List();
+ for(Integer i: integers){
+ dynamicOneColumnData.putInt(i);
+ }
+ break;
+ case INT64:
+ List longs = tsDynamicOneColumnData.getI64List();
+ for(Long l: longs){
+ dynamicOneColumnData.putLong(l);
+ }
+ break;
+ case FLOAT:
+ List floats = tsDynamicOneColumnData.getFloatList();
+ for(double f: floats){
+ dynamicOneColumnData.putFloat((float)f);
+ }
+ break;
+ case DOUBLE:
+ List doubles = tsDynamicOneColumnData.getDoubleList();
+ for(double d: doubles){
+ dynamicOneColumnData.putDouble(d);
+ }
+ break;
+ case BYTE_ARRAY:
+ List binaries = tsDynamicOneColumnData.getBinaryList();
+ for(Byte b: binaries){
+ dynamicOneColumnData.putBinary(new Binary(b.toString()));
+ }
+ break;
+ default:
+ break;
+ }
+ return dynamicOneColumnData;
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/AuthorityChecker.java b/src/main/java/cn/edu/thu/tsfiledb/service/AuthorityChecker.java
new file mode 100644
index 00000000000..fc98be7bd8e
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/AuthorityChecker.java
@@ -0,0 +1,102 @@
+package cn.edu.thu.tsfiledb.service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import cn.edu.thu.tsfile.timeseries.read.qp.Path;
+import cn.edu.thu.tsfiledb.auth.dao.Authorizer;
+import cn.edu.thu.tsfiledb.auth.model.Permission;
+
+public class AuthorityChecker {
+
+ public static final String SUPER_USER = "root";
+ private static final Logger logger = LoggerFactory.getLogger(AuthorityChecker.class);
+
+ public static boolean check(String username, List paths, OperatorType type){
+ if(SUPER_USER.equals(username)){
+ return true;
+ }
+ int permission = translateToPermissionId(type);
+ if(permission == -1){
+ logger.error("OperateType not found. {}", type);
+ return false;
+ }
+ for(int i = 0 ; i < paths.size() ; i ++){
+ if(!checkOnePath(username, paths.get(i), permission)){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static List getAllParentPath(Path path){
+ List parentPaths = new ArrayList();
+ String fullPath = path.getFullPath();
+ String[] nodes = fullPath.split("\\.");
+
+ for(int i = 0 ; i < nodes.length ; i++){
+ StringBuilder sb = new StringBuilder();
+ for(int j = 0 ; j <= i ; j++){
+ sb.append(nodes[j]);
+ if(j < i){
+ sb.append(".");
+ }
+ }
+ parentPaths.add(sb.toString());
+ }
+ return parentPaths;
+ }
+
+ public static boolean checkOnePath(String username, Path path, int permission){
+ List parentPaths = getAllParentPath(path);
+ for(int i = 0 ; i < parentPaths.size(); i ++){
+ if(Authorizer.checkUserPermission(username, parentPaths.get(i), permission)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static int translateToPermissionId(OperatorType type){
+ switch(type){
+ case METADATA:
+ return Permission.CREATE;
+ case QUERY:
+ case SELECT:
+ case FILTER:
+ case GROUPBY:
+ case SEQTABLESCAN:
+ case TABLESCAN:
+ return Permission.READ;
+ case DELETE:
+ return Permission.DELETE;
+ case INSERT:
+ case LOADDATA:
+ return Permission.INSERT;
+ case UPDATE:
+ return Permission.MODIFY;
+ case AUTHOR:
+ case BASIC_FUNC:
+ case FILEREAD:
+ case FROM:
+ case FUNC:
+ case HASHTABLESCAN:
+ case JOIN:
+ case LIMIT:
+ case MERGEJOIN:
+ case NULL:
+ case ORDERBY:
+ case PROPERTY:
+ case ROOT:
+ case UNION:
+
+ return -1;
+ default:
+ return -1;
+ }
+
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/Daemon.java b/src/main/java/cn/edu/thu/tsfiledb/service/Daemon.java
new file mode 100644
index 00000000000..ff011e5e75f
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/Daemon.java
@@ -0,0 +1,54 @@
+package cn.edu.thu.tsfiledb.service;
+
+import java.io.IOException;
+
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TBinaryProtocol.Factory;
+import org.apache.thrift.server.TServer;
+import org.apache.thrift.server.TThreadPoolServer;
+import org.apache.thrift.transport.TServerSocket;
+import org.apache.thrift.transport.TTransportException;
+
+import cn.edu.thu.tsfiledb.auth.dao.DBdao;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSIService;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSIService.Processor;
+
+
+public class Daemon {
+
+ public static void main(String[] args) {
+ //init Derby Database
+ DBdao dBdao = new DBdao();
+ dBdao.open();
+
+ startRPC();
+ }
+
+ public static TServer startRPC() {
+ try {
+ // 设置服务器端口
+ TServerSocket serverTransport = new TServerSocket(JDBCServerConfig.PORT);
+ // 设置二进制协议工厂
+ Factory protocolFactory = new TBinaryProtocol.Factory();
+ //处理器关联业务实现
+ Processor processor = new TSIService.Processor(new TSServiceImpl());
+ // 2. 使用线程池服务模型
+ TThreadPoolServer.Args poolArgs = new TThreadPoolServer.Args(serverTransport);
+ poolArgs.processor(processor);
+ poolArgs.protocolFactory(protocolFactory);
+ TServer poolServer = new TThreadPoolServer(poolArgs);
+ poolServer.serve();
+
+ } catch (TTransportException e) {
+
+ e.printStackTrace();
+
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServer.java b/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServer.java
new file mode 100644
index 00000000000..8be12c24c9a
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServer.java
@@ -0,0 +1,155 @@
+package cn.edu.thu.tsfiledb.service;
+
+import java.io.IOException;
+
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TBinaryProtocol.Factory;
+import org.apache.thrift.server.TServer;
+import org.apache.thrift.server.TThreadPoolServer;
+import org.apache.thrift.transport.TServerSocket;
+import org.apache.thrift.transport.TTransportException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import cn.edu.thu.tsfiledb.auth.dao.DBdao;
+import cn.edu.thu.tsfiledb.engine.exception.FileNodeManagerException;
+import cn.edu.thu.tsfiledb.engine.exception.LRUManagerException;
+import cn.edu.thu.tsfiledb.engine.filenode.FileNodeManager;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSIService;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSIService.Processor;
+
+
+
+public class JDBCServer implements JDBCServerMBean {
+ private static final Logger LOGGER = LoggerFactory.getLogger(JDBCServer.class);
+ private DBdao dBdao;
+ private Thread jdbcServerThread;
+ private boolean isStart;
+
+ private Factory protocolFactory;
+ private Processor processor;
+ private TServerSocket serverTransport;
+ private TThreadPoolServer.Args poolArgs;
+ private TServer poolServer;
+
+ private boolean isMerging;
+
+ public JDBCServer() throws TTransportException {
+ isStart = false;
+ isMerging = false;
+ }
+
+ @Override
+ public synchronized void startServer() {
+ if(isStart){
+ LOGGER.info("tsfile-service JDBCServer: jdbc server has been already running now");
+ return;
+ }
+ LOGGER.info("tsfile-service JDBCServer: starting jdbc server...");
+ dBdao = new DBdao();
+ dBdao.open();
+
+ try {
+ jdbcServerThread = new Thread(new JDBCServerThread());
+ } catch (IOException e) {
+ LOGGER.error("Server start Error. {}", e.getMessage());
+ e.printStackTrace();
+ return;
+ }
+ jdbcServerThread.start();
+
+ LOGGER.info("tsfile-service JDBCServer: start jdbc server successfully");
+ isStart = true;
+
+ }
+
+ @Override
+ public synchronized void restartServer() {
+ stopServer();
+ startServer();
+ }
+
+ @Override
+ public synchronized void stopServer() {
+ if(!isStart){
+ LOGGER.info("tsfile-service JDBCServer: jdbc server isn't running now");
+ return;
+ }
+
+ LOGGER.info("tsfile-service JDBCServer: closing jdbc server...");
+
+ if(dBdao != null){
+ dBdao.close();
+ dBdao = null;
+ }
+
+ LOGGER.info("tsfile-service JDBCServer: flush data in memory to disk");
+ try {
+ FileNodeManager.getInstance().close();
+ } catch (LRUManagerException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ close();
+ LOGGER.info("tsfile-service JDBCServer: close jdbc server successfully");
+ }
+
+ private void close(){
+ if(poolServer != null){
+ poolServer.stop();
+ poolServer = null;
+ }
+
+ if(serverTransport != null){
+ serverTransport.close();
+ serverTransport = null;
+ }
+ isStart = false;
+ }
+
+ class JDBCServerThread implements Runnable{
+
+ public JDBCServerThread() throws IOException{
+ protocolFactory = new TBinaryProtocol.Factory();
+ processor = new TSIService.Processor(new TSServiceImpl());
+ }
+
+ @Override
+ public void run() {
+ try {
+ serverTransport = new TServerSocket(JDBCServerConfig.PORT);
+ poolArgs = new TThreadPoolServer.Args(serverTransport);
+ poolArgs.processor(processor);
+ poolArgs.protocolFactory(protocolFactory);
+ poolServer = new TThreadPoolServer(poolArgs);
+ // poolServer.serve(); will block next statement to execute
+ poolServer.serve();
+ } catch (TTransportException e) {
+ LOGGER.error("tsfile-service JDBCServer: failed to start jdbc server, because ", e);
+ } catch (Exception e) {
+ LOGGER.error("tsfile-service JDBCServer: jdbc server exit, because ", e);
+ } finally {
+ close();
+ LOGGER.info("tsfile-service JDBCServer: close TThreadPoolServer and TServerSocket");
+ }
+ }
+ }
+
+ public static void main(String[] args) throws TTransportException, InterruptedException{
+ JDBCServer server = new JDBCServer();
+ server.startServer();
+ }
+
+ @Override
+ public synchronized void mergeAll() {
+ LOGGER.info("tsfile-service JDBCServer : start merging..");
+ try {
+ FileNodeManager.getInstance().mergeAll();
+ } catch (FileNodeManagerException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ LOGGER.info("tsfile-service JDBCServer : Done.");
+ }
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServerConfig.java b/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServerConfig.java
new file mode 100644
index 00000000000..5eb340c982c
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServerConfig.java
@@ -0,0 +1,16 @@
+package cn.edu.thu.tsfiledb.service;
+
+public class JDBCServerConfig {
+ public static final int PORT = 6667;
+
+// public static final String TSFILE_DATA_PATH = "writeV2Huge.out";
+
+ public static final String overflowErrOutput = "overflowErrOutput";
+ public static final String overflowOutput = "overflowOutput";
+
+ public static final String JMX_IP = "0.0.0.0";
+ public static final int JMX_PORT = 31999;
+ public static final String JMX_USER = "saf";
+ public static final String JMX_PASS = "pass";
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServerMBean.java b/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServerMBean.java
new file mode 100644
index 00000000000..d5f6447b010
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/JDBCServerMBean.java
@@ -0,0 +1,9 @@
+package cn.edu.thu.tsfiledb.service;
+
+
+public interface JDBCServerMBean {
+ public void startServer();
+ public void restartServer();
+ public void stopServer();
+ public void mergeAll();
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/JMXManager.java b/src/main/java/cn/edu/thu/tsfiledb/service/JMXManager.java
new file mode 100644
index 00000000000..643cb677545
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/JMXManager.java
@@ -0,0 +1,115 @@
+package cn.edu.thu.tsfiledb.service;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.server.RMISocketFactory;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXPrincipal;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.security.auth.Subject;
+
+import org.apache.thrift.transport.TTransportException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.core.joran.spi.JoranException;
+import cn.edu.thu.tsfile.common.constant.SystemConstant;
+
+public class JMXManager {
+
+ static{
+ try {
+ String home = System.getProperty(SystemConstant.TSFILE_HOME);
+ if(home != null && !home.equals("")){
+ LogBackConfigLoader.load(home + File.separator + "conf" + File.separator + "logback.xml");
+ }
+ } catch (IOException | JoranException e) {
+ System.out.println("Load configuration file error");
+ e.printStackTrace();
+ }
+ }
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JMXManager.class);
+
+ private JMXConnectorServer connector;
+ private Map jmxEnvironment;
+
+ public JMXManager() {
+ jmxEnvironment = new HashMap();
+ }
+
+ public void serice() throws IOException, TTransportException, MalformedObjectNameException,
+ InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ String addr = String.format("service:jmx:rmi://%s:%d/jndi/rmi://%s:%d/jmxrmi", JDBCServerConfig.JMX_IP,
+ JDBCServerConfig.JMX_PORT, JDBCServerConfig.JMX_IP, JDBCServerConfig.JMX_PORT);
+ JMXServiceURL address = new JMXServiceURL(addr);
+
+ RMISocketFactory rmiFactory = RMISocketFactory.getDefaultSocketFactory();
+ LocateRegistry.createRegistry(JDBCServerConfig.JMX_PORT, null, rmiFactory);
+
+ jmxEnvironment.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, rmiFactory);
+
+ // for auth
+ JMXAuthenticator auth = createJMXAuthenticator();
+ jmxEnvironment.put(JMXConnectorServer.AUTHENTICATOR, auth);
+
+ connector = JMXConnectorServerFactory.newJMXConnectorServer(address, jmxEnvironment,
+ ManagementFactory.getPlatformMBeanServer());
+ JDBCServerMBean mbean = new JDBCServer();
+ mbean.startServer();
+ ObjectName mBeanName = new ObjectName("JDBCServerDomain", "type", "JDBCServer");
+ mbs.registerMBean(mbean, mBeanName);
+ connector.start();
+ LOGGER.info("tsfile-service JMXManager: start JMX manager...");
+ }
+
+ public void close() throws IOException {
+ connector.stop();
+ LOGGER.info("tsfile-service JMXManager: close JMX manager...");
+ }
+
+ private JMXAuthenticator createJMXAuthenticator() {
+ return new JMXAuthenticator() {
+ public Subject authenticate(Object credentials) {
+ String[] sCredentials = (String[]) credentials;
+ if (null == sCredentials || sCredentials.length != 2) {
+ LOGGER.error("tsfile-service JMXManager: auth info in wrong format!");
+ throw new SecurityException("Authentication failed!");
+ }
+ String userName = sCredentials[0];
+ String pValue = sCredentials[1];
+ if (JDBCServerConfig.JMX_USER.equals(userName) && JDBCServerConfig.JMX_PASS.equals(pValue)) {
+ Set principals = new HashSet();
+ principals.add(new JMXPrincipal(userName));
+ return new Subject(true, principals, Collections.EMPTY_SET, Collections.EMPTY_SET);
+ }
+ LOGGER.error("tsfile-service JMXManager: Authentication failed!");
+ throw new SecurityException("Authentication failed!");
+ }
+ };
+ }
+
+ public static void main(String[] args) throws MalformedObjectNameException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, TTransportException, IOException {
+ JMXManager manager = new JMXManager();
+ manager.serice();
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/LogBackConfigLoader.java b/src/main/java/cn/edu/thu/tsfiledb/service/LogBackConfigLoader.java
new file mode 100644
index 00000000000..04b089be268
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/LogBackConfigLoader.java
@@ -0,0 +1,46 @@
+package cn.edu.thu.tsfiledb.service;
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+import java.io.File;
+import java.io.IOException;
+
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
+
+/**
+ * Simple Utility class for loading an external config file for logback
+ * @author daniel
+ */
+public class LogBackConfigLoader {
+
+ public static void load (String externalConfigFileLocation) throws IOException, JoranException{
+ LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+ File externalConfigFile = new File(externalConfigFileLocation);
+ if(!externalConfigFile.exists()){
+ throw new IOException("Logback External Config File Parameter does not reference a file that exists");
+ }else{
+ if(!externalConfigFile.isFile()){
+ throw new IOException("Logback External Config File Parameter exists, but does not reference a file");
+ }else{
+ if(!externalConfigFile.canRead()){
+ throw new IOException("Logback External Config File exists and is a file, but cannot be read.");
+ }else{
+ JoranConfigurator configurator = new JoranConfigurator();
+ configurator.setContext(lc);
+ lc.reset();
+ configurator.doConfigure(externalConfigFileLocation);
+ StatusPrinter.printInCaseOfErrorsOrWarnings(lc);
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/TSServiceImpl.java b/src/main/java/cn/edu/thu/tsfiledb/service/TSServiceImpl.java
new file mode 100644
index 00000000000..8b8d1af9754
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/TSServiceImpl.java
@@ -0,0 +1,662 @@
+package cn.edu.thu.tsfiledb.service;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.thrift.TException;
+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.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.engine.filenode.FileNodeManager;
+import cn.edu.thu.tsfiledb.exception.NotConsistentException;
+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.metadata.Metadata;
+import cn.edu.thu.tsfiledb.query.aggregation.AggreFuncFactory;
+import cn.edu.thu.tsfiledb.query.aggregation.AggregateFunction;
+import cn.edu.thu.tsfiledb.query.engine.OverflowQueryEngine;
+import cn.edu.thu.tsfiledb.query.management.ReadLockManager;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCancelOperationReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCancelOperationResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseOperationReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseOperationResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseSessionReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSCloseSessionResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSColumnSchema;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSExecuteBatchStatementReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSExecuteBatchStatementResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSExecuteStatementReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSExecuteStatementResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSFetchMetadataReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSFetchMetadataResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSFetchResultsReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSFetchResultsResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSHandleIdentifier;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSOpenSessionReq;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSOpenSessionResp;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSOperationHandle;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSProtocolVersion;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSQueryDataSet;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TS_SessionHandle;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TS_Status;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TS_StatusCode;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSIService;;
+
+public class TSServiceImpl implements TSIService.Iface {
+
+ private WriteLogManager writeLogManager;
+ private OverflowQPExecutor exec = new OverflowQPExecutor();
+ // Record the username for every rpc connection. Username.get() is null if
+ // login is failed.
+ private ThreadLocal username = new ThreadLocal<>();
+ private ThreadLocal> queryStatus = new ThreadLocal<>();
+ private ThreadLocal>> queryRet = new ThreadLocal<>();
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(TSServiceImpl.class);
+
+ public TSServiceImpl() throws IOException {
+ LOGGER.info("start check write log...");
+ writeLogManager = WriteLogManager.getInstance();
+ long cnt = 0l;
+ PhysicalPlan plan;
+ while ((plan = writeLogManager.getPhysicalPlan()) != null) {
+ try {
+ plan.processNonQuery(exec);
+ cnt++;
+ } catch (ProcessorException e) {
+ e.printStackTrace();
+ throw new IOException("Error in recovery from write log");
+ }
+ }
+ LOGGER.info("Done. Recover operation count {}", cnt);
+ }
+
+ @Override
+ public TSOpenSessionResp OpenSession(TSOpenSessionReq req) throws TException {
+
+ if (LOGGER.isInfoEnabled())
+ LOGGER.info("tsfile-server TSServiceImpl: receive open session from username {}", req.getUsername());
+
+ boolean status = false;
+ try {
+ status = Authorizer.login(req.getUsername(), req.getPassword());
+ } catch (AuthException e) {
+ status = false;
+ }
+ // boolean status = true;
+ TS_Status ts_status;
+ if (status) {
+ ts_status = new TS_Status(TS_StatusCode.SUCCESS_STATUS);
+ ts_status.setErrorMessage("login successfully.");
+ username.set(req.getUsername());
+ initForOneSession();
+ } else {
+ ts_status = new TS_Status(TS_StatusCode.ERROR_STATUS);
+ ts_status.setErrorMessage("login failed. Username or password is wrong.");
+ }
+ TSOpenSessionResp resp = new TSOpenSessionResp(ts_status, TSProtocolVersion.TSFILE_SERVICE_PROTOCOL_V1);
+ resp.setSessionHandle(new TS_SessionHandle(new TSHandleIdentifier(ByteBuffer.wrap(req.getUsername().getBytes()),
+ ByteBuffer.wrap((req.getPassword().getBytes())))));
+ if (LOGGER.isInfoEnabled())
+ LOGGER.info("tsfile-server TSServiceImpl: Login status: {}. User : {}", ts_status.getErrorMessage(),
+ req.getUsername());
+
+ return resp;
+ }
+
+ private void initForOneSession() {
+ queryStatus.set(new HashMap());
+ queryRet.set(new HashMap>());
+ }
+
+ @Override
+ public TSCloseSessionResp CloseSession(TSCloseSessionReq req) throws TException {
+ if (LOGGER.isInfoEnabled())
+ LOGGER.info("tsfile-server TSServiceImpl: receive close session");
+ TS_Status ts_status;
+ if (username.get() == null) {
+ ts_status = new TS_Status(TS_StatusCode.ERROR_STATUS);
+ ts_status.setErrorMessage("Has not logged in");
+ } else {
+ ts_status = new TS_Status(TS_StatusCode.SUCCESS_STATUS);
+ username.remove();
+ }
+ return new TSCloseSessionResp(ts_status);
+ }
+
+ @Override
+ // TODO: 这个方法啥意思?
+ public TSCancelOperationResp CancelOperation(TSCancelOperationReq req) throws TException {
+ if (LOGGER.isInfoEnabled())
+ LOGGER.info("tsfile-server TSServiceImpl: receive cancle operation");
+ return new TSCancelOperationResp(new TS_Status(TS_StatusCode.SUCCESS_STATUS));
+ }
+
+ @Override
+ public TSCloseOperationResp CloseOperation(TSCloseOperationReq req) throws TException {
+ if (LOGGER.isInfoEnabled())
+ LOGGER.info("tsfile-server TSServiceImpl: receive statement close operation");
+ try {
+ ReadLockManager.getInstance().unlockForOneRequest();
+ clearAllStatusForCurrentRequest();
+ } catch (NotConsistentException e) {
+ LOGGER.warn("Warning in closeOperation : {}", e.getMessage());
+ // e.printStackTrace();
+ } catch (ProcessorException e) {
+ // TODO Auto-generated catch block
+ LOGGER.error("Error in closeOperation : {}", e.getMessage());
+ e.printStackTrace();
+ }
+ return new TSCloseOperationResp(new TS_Status(TS_StatusCode.SUCCESS_STATUS));
+ }
+
+ public void clearAllStatusForCurrentRequest() {
+ this.queryRet.get().clear();
+ this.queryStatus.get().clear();
+ // Clear all parameters in last request.
+ exec.clearParamter();
+ }
+
+ @Override
+ public TSFetchMetadataResp FetchMetadata(TSFetchMetadataReq req) throws TException {
+ LOGGER.info("tsfile-server FetchMetadata: Receive fetch metadata operation");
+ TS_Status status;
+ if (!checkLogin()) {
+ LOGGER.info("tsfile-server ExecuteStatement: Not login.");
+ status = new TS_Status(TS_StatusCode.ERROR_STATUS);
+ status.setErrorMessage("Not login");
+ return new TSFetchMetadataResp(status);
+ }
+ TSFetchMetadataResp resp = new TSFetchMetadataResp();
+ try {
+ Metadata metadata = MManager.getInstance().getMetadata();
+ String metadataInJson = MManager.getInstance().getMetadataInString();
+ Map> seriesMap = metadata.getSeriesMap();
+ Map> tsSeriesMap = Utils.convertAllSchema(seriesMap);
+ resp.setSeriesMap(tsSeriesMap);
+ resp.setDeltaObjectMap(metadata.getDeltaObjectMap());
+ resp.setMetadataInJson(metadataInJson);
+ status = new TS_Status(TS_StatusCode.SUCCESS_STATUS);
+ resp.setStatus(status);
+ } catch (PathErrorException e) {
+ LOGGER.error("tsfile-server FetchMetadata: failed to get all schema", e);
+ status = new TS_Status(TS_StatusCode.ERROR_STATUS);
+ status.setErrorMessage(e.getMessage());
+ resp.setStatus(status);
+ resp.setSeriesMap(null);
+ resp.setDeltaObjectMap(null);
+ resp.setMetadataInJson(null);
+ } catch (Exception e) {
+ LOGGER.error("tsfile-server FetchMetadata: failed to get all schema with unknown reason", e);
+ status = new TS_Status(TS_StatusCode.ERROR_STATUS);
+ status.setErrorMessage(e.getMessage());
+ resp.setStatus(status);
+ resp.setSeriesMap(null);
+ resp.setDeltaObjectMap(null);
+ resp.setMetadataInJson(null);
+ }
+ return resp;
+ }
+
+ /**
+ * Judge whether the statement is ADMIN COMMOND and if true, execute it.
+ *
+ * @param statement
+ * @return true if the statement is ADMIN COMMOND
+ * @throws IOException
+ */
+ public boolean execAdminCommond(String statement) throws IOException {
+ if (!username.get().equals("root")) {
+ return false;
+ }
+ if (statement == null) {
+ return false;
+ }
+ statement = statement.toLowerCase();
+ switch (statement) {
+ case "close":
+ FileNodeManager.getInstance().closeAll();
+ writeLogManager.overflowFlush();
+ writeLogManager.bufferFlush();
+ // MManager.getInstance().flushObjectToFile();
+ return true;
+ case "merge":
+ FileNodeManager.getInstance().mergeAll();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 用来测试的函数,仅供测试,后面要删除
+ *
+ * @param req
+ * @return
+ * @throws TException
+ */
+ public TSExecuteStatementResp testExecute(TSExecuteStatementReq req) {
+ TSExecuteStatementResp resp = getTSExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS, "");
+ String sql = req.statement;
+ String[] params = sql.substring(5).split(" ");
+ List columns = new ArrayList<>();
+ columns.add(params[0] + "(" + params[1] + ")");
+ TSHandleIdentifier operationId = new TSHandleIdentifier(ByteBuffer.wrap(username.get().getBytes()),
+ ByteBuffer.wrap(("PASS".getBytes())));
+ TSOperationHandle operationHandle = null;
+ resp.setColumns(columns);
+ operationHandle = new TSOperationHandle(operationId, true);
+ resp.setOperationHandle(operationHandle);
+ recordANewQuery(sql, null);
+ return resp;
+ }
+
+ @Override
+ public TSExecuteBatchStatementResp ExecuteBatchStatement(TSExecuteBatchStatementReq req) throws TException {
+ try {
+ LOGGER.info("tsfile-server ExecuteBatchStatement: Receive execute batch sql operation");
+ if (!checkLogin()) {
+ LOGGER.info("tsfile-server ExecuteBatchStatement: Not login.");
+ return getTSBathcExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Not login", null);
+ }
+ List statements = req.getStatements();
+ List result = new ArrayList<>();
+
+ TSqlParserV2 parser = new TSqlParserV2();
+ ArrayList opList = new ArrayList<>();
+ for (String statement : statements) {
+ RootOperator root = parser.parseSQLToOperator(statement);
+ if (root.isQuery()) {
+ return getTSBathcExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
+ "statement is query :" + statement, result);
+ }
+ opList.add(root);
+ }
+ for (RootOperator op: opList) {
+ ExecuteUpdateStatement(op);
+ }
+ // TODO Auto-generated method stub
+
+ return getTSBathcExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS, "Execute statements successfully",
+ result);
+ } catch (Exception e) {
+ LOGGER.error("tsfile-server ExecuteBatchStatement: error occurs when executing statements", e);
+ return getTSBathcExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage(), null);
+ }
+
+ }
+
+ @Override
+ public TSExecuteStatementResp ExecuteStatement(TSExecuteStatementReq req) throws TException {
+ try {
+ // 测试代码
+ String sql = req.getStatement();
+ if (sql != null && sql.startsWith("test:")) {
+ return testExecute(req);
+ }
+ // 测试代码(结束)
+
+ LOGGER.info("tsfile-server ExecuteStatement: Receive execute sql operation,statement {}", req.statement);
+ if (!checkLogin()) {
+ LOGGER.info("tsfile-server ExecuteStatement: Not login.");
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Not login");
+ }
+ String statement = req.getStatement();
+
+ try {
+ if (execAdminCommond(statement)) {
+ return getTSExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS, "ADMIN_COMMOND_SUCCESS");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Server Internal Error");
+ }
+
+ TSqlParserV2 parser = new TSqlParserV2();
+ RootOperator root;
+ try {
+ root = parser.parseSQLToOperator(statement);
+ } catch (IllegalASTFormatException e) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
+ "Statement is not right:" + e.getMessage());
+ } catch (NullPointerException e) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Statement is not allowed");
+ }
+ if (root.isQuery()) {
+ return ExecuteQueryStatement(req);
+ } else {
+ return ExecuteUpdateStatement(root);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ }
+ }
+
+ @Override
+ public TSExecuteStatementResp ExecuteQueryStatement(TSExecuteStatementReq req) throws TException {
+
+ try {
+ LOGGER.info("tsfile-server ExecuteQueryStatement: receive query sql operation,statement {}", req.statement);
+ if (!checkLogin()) {
+ LOGGER.info("tsfile-server ExecuteQueryStatement: Not login.");
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Not login");
+ }
+
+ String statement = req.getStatement();
+ TSqlParserV2 parser = new TSqlParserV2();
+ RootOperator root = parser.parseSQLToOperator(statement);
+
+ List paths = null;
+ // paths = ((SFWOperator) root).getSelSeriesPaths(exec);
+ PhysicalPlan plan = parser.parseSQLToPhysicalPlan(statement, exec);
+ paths = plan.getInvolvedSeriesPaths();
+
+ // check whether current statement is a query statement
+ if (!root.isQuery()) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Statement Error: Not a query statement");
+ }
+
+ // check path exists
+ if (paths.size() == 0) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Selected columns do NOT EXIST.");
+ }
+
+ // check file level set
+ try {
+ MManager.getInstance().checkFileLevel(paths);
+ } catch (PathErrorException e) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ }
+
+ // check permissions
+ if (!checkAuthorization(paths, root.getType())) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "No permissions for this query.");
+ }
+
+ TSExecuteStatementResp resp = getTSExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS, "");
+ List columns = new ArrayList<>();
+ for (Path p : paths) {
+ columns.add(p.getFullPath());
+ }
+ TSHandleIdentifier operationId = new TSHandleIdentifier(ByteBuffer.wrap(username.get().getBytes()),
+ ByteBuffer.wrap(("PASS".getBytes())));
+ TSOperationHandle operationHandle = null;
+ resp.setColumns(columns);
+ operationHandle = new TSOperationHandle(operationId, true);
+ resp.setOperationHandle(operationHandle);
+
+ recordANewQuery(statement, root);
+
+ LOGGER.info("ExecuteQueryStatement: finish query statement {}", statement);
+ return resp;
+ } catch (Exception e) {
+ LOGGER.error("Server internal error: {}", e.getMessage());
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ }
+ }
+
+ public TSFetchResultsResp testFetchResults(TSFetchResultsReq req) {
+ String sql = req.statement;
+ if (!queryStatus.get().containsKey(sql)) {
+ TSFetchResultsResp resp = getTSFetchResultsResp(TS_StatusCode.SUCCESS_STATUS,
+ "FetchResult successfully. Has more result: " + false);
+ resp.setHasResultSet(false);
+ return resp;
+ }
+ String[] params = sql.substring(5).split(" ");
+ TSDataType dataType;
+ try {
+ dataType = MManager.getInstance().getSeriesType(params[1]);
+ AggregateFunction aggrFunc = AggreFuncFactory.getAggrFuncByName(params[0], dataType);
+ Path p = new Path(params[1]);
+ QueryDataSet queryDataSet = new OverflowQueryEngine().aggregate(p, aggrFunc, null, null, null);
+ TSQueryDataSet tsQueryDataSet = Utils.convertQueryDataSet(queryDataSet);
+
+ TSFetchResultsResp resp = getTSFetchResultsResp(TS_StatusCode.SUCCESS_STATUS,
+ "FetchResult successfully. Has more result: " + false);
+ resp.setHasResultSet(true);
+ resp.setQueryDataSet(tsQueryDataSet);
+ queryStatus.get().remove(sql);
+ return resp;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ }
+
+ @Override
+ public TSFetchResultsResp FetchResults(TSFetchResultsReq req) throws TException {
+ // 测试代码
+ if (req.statement.startsWith("test:")) {
+ return testFetchResults(req);
+ }
+ // 测试代码(结束)
+ try {
+ if (!checkLogin()) {
+ return getTSFetchResultsResp(TS_StatusCode.ERROR_STATUS, "Not login.");
+ }
+ String statement = req.getStatement();
+ LOGGER.info("tsfile-server TSServiceImpl: receive fetch result sql operation,statement {}", statement);
+
+ if (!queryStatus.get().containsKey(statement)) {
+ return getTSFetchResultsResp(TS_StatusCode.ERROR_STATUS, "Has not executed statement");
+ }
+
+ int fetchSize = req.getFetch_size();
+ Iterator queryDataSetIterator;
+ if (!queryRet.get().containsKey(statement)) {
+ TSqlParserV2 parser = new TSqlParserV2();
+ RootOperator operator = queryStatus.get().get(statement);
+ exec.setFetchSize(fetchSize);
+ queryDataSetIterator = parser.query(operator, exec);
+ queryRet.get().put(statement, queryDataSetIterator);
+ } else {
+ queryDataSetIterator = queryRet.get().get(statement);
+ }
+
+ boolean hasResultSet = false;
+ // TODO: 需要和徐毅确认res是否可以这么用
+ QueryDataSet res = new QueryDataSet();
+ if (queryDataSetIterator.hasNext()) {
+ res = queryDataSetIterator.next();
+ hasResultSet = true;
+ } else {
+ hasResultSet = false;
+ queryRet.get().remove(statement);
+ }
+ TSQueryDataSet tsQueryDataSet = Utils.convertQueryDataSet(res);
+
+ TSFetchResultsResp resp = getTSFetchResultsResp(TS_StatusCode.SUCCESS_STATUS,
+ "FetchResult successfully. Has more result: " + hasResultSet);
+ resp.setHasResultSet(hasResultSet);
+ resp.setQueryDataSet(tsQueryDataSet);
+ return resp;
+ } catch (Exception e) {
+ LOGGER.error("Server Internal Error: {}", e.getMessage());
+ e.printStackTrace();
+ return getTSFetchResultsResp(TS_StatusCode.ERROR_STATUS, "Server Internal Error");
+ }
+
+ }
+
+ @Override
+ public TSExecuteStatementResp ExecuteUpdateStatement(TSExecuteStatementReq req) throws TException {
+ try {
+ if (!checkLogin()) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Not login");
+ }
+ String statement = req.getStatement();
+ return ExecuteUpdateStatement(statement);
+ } catch (ProcessorException e) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOGGER.error(e.getMessage());
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ }
+ }
+
+ private TSExecuteStatementResp ExecuteUpdateStatement(RootOperator root) throws TException {
+ try {
+ LOGGER.debug("ExecuteUpdateStatement: receive statement {}", root);
+ PhysicalPlan plan = root.transformToPhysicalPlan(exec);
+ List paths = plan.getInvolvedSeriesPaths();
+
+ if (!checkAuthorization(paths, root.getType())) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "No permissions for this operation");
+ }
+ // TODO 是否要添加执行的信息而不是仅仅返回正确或者错误
+ boolean execRet;
+ try {
+ execRet = plan.processNonQuery(exec);
+ } catch (ProcessorException e) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ }
+ if (execRet && needToBeWritenToLog(plan)) {
+ writeLogManager.write(plan);
+ }
+ TS_StatusCode statusCode = execRet ? TS_StatusCode.SUCCESS_STATUS : TS_StatusCode.ERROR_STATUS;
+ String msg = execRet ? "Execute successfully" : "Execute statement error.";
+ TSExecuteStatementResp resp = getTSExecuteStatementResp(statusCode, msg);
+ TSHandleIdentifier operationId = new TSHandleIdentifier(ByteBuffer.wrap(username.get().getBytes()),
+ ByteBuffer.wrap(("PASS".getBytes())));
+ TSOperationHandle operationHandle = null;
+ operationHandle = new TSOperationHandle(operationId, false);
+ resp.setOperationHandle(operationHandle);
+ return resp;
+ } catch (QueryProcessorException e) {
+ LOGGER.error(e.getMessage());
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ } catch (IOException e) {
+ LOGGER.error("Write preLog error", e);
+ return getTSExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS, "Write log error");
+ }
+ }
+
+ private TSExecuteStatementResp ExecuteUpdateStatement(String statement)
+ throws TException, QueryProcessorException, IOException, ProcessorException {
+
+ LOGGER.info("ExecuteUpdateStatement: receive statement {}", statement);
+ TSqlParserV2 parser = new TSqlParserV2();
+ RootOperator root;
+
+ try {
+ root = parser.parseSQLToOperator(statement);
+ } catch (QueryProcessorException e) {
+ e.printStackTrace();
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ }
+ if (root.isQuery()) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Statement is a query statement.");
+ }
+
+ // 如果操作是增删改
+ PhysicalPlan plan = parser.parseSQLToPhysicalPlan(statement, exec);
+ List paths = plan.getInvolvedSeriesPaths();
+
+ if (!checkAuthorization(paths, root.getType())) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "No permissions for this operation");
+ }
+
+ // TODO 是否要添加执行的信息而不是仅仅返回正确或者错误
+ boolean execRet;
+ try {
+ execRet = parser.nonQuery(root, exec);
+ } catch (ProcessorException e) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+ }
+ if (execRet && needToBeWritenToLog(plan)) {
+ writeLogManager.write(plan);
+ }
+ TS_StatusCode statusCode = execRet ? TS_StatusCode.SUCCESS_STATUS : TS_StatusCode.ERROR_STATUS;
+ String msg = execRet ? "Execute successfully" : "Execute statement error.";
+ TSExecuteStatementResp resp = getTSExecuteStatementResp(statusCode, msg);
+ TSHandleIdentifier operationId = new TSHandleIdentifier(ByteBuffer.wrap(username.get().getBytes()),
+ ByteBuffer.wrap(("PASS".getBytes())));
+ TSOperationHandle operationHandle = null;
+ operationHandle = new TSOperationHandle(operationId, false);
+ resp.setOperationHandle(operationHandle);
+ return resp;
+ }
+
+ private boolean needToBeWritenToLog(PhysicalPlan plan) {
+ if (plan.getOperatorType() == OperatorType.INSERT) {
+ return true;
+ }
+ if (plan.getOperatorType() == OperatorType.UPDATE) {
+ return true;
+ }
+ if (plan.getOperatorType() == OperatorType.DELETE) {
+ return true;
+ }
+ return false;
+ }
+
+ private void recordANewQuery(String statement, RootOperator op) {
+ queryStatus.get().put(statement, op);
+ // refresh current queryRet for statement
+ if (queryRet.get().containsKey(statement)) {
+ queryRet.get().remove(statement);
+ }
+ }
+
+ /**
+ * Check whether current user has logined.
+ *
+ * @return true: If logined; false: If not logined
+ */
+ private boolean checkLogin() {
+ if (username.get() == null) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean checkAuthorization(List paths, OperatorType type) {
+ return AuthorityChecker.check(username.get(), paths, type);
+ }
+
+ private TSExecuteStatementResp getTSExecuteStatementResp(TS_StatusCode code, String msg) {
+ TSExecuteStatementResp resp = new TSExecuteStatementResp();
+ TS_Status ts_status = new TS_Status(code);
+ ts_status.setErrorMessage(msg);
+ resp.setStatus(ts_status);
+ TSHandleIdentifier operationId = new TSHandleIdentifier(ByteBuffer.wrap(username.get().getBytes()),
+ ByteBuffer.wrap(("PASS".getBytes())));
+ TSOperationHandle operationHandle = new TSOperationHandle(operationId, false);
+ resp.setOperationHandle(operationHandle);
+ return resp;
+ }
+
+ private TSExecuteBatchStatementResp getTSBathcExecuteStatementResp(TS_StatusCode code, String msg,
+ List result) {
+ TSExecuteBatchStatementResp resp = new TSExecuteBatchStatementResp();
+ TS_Status ts_status = new TS_Status(code);
+ ts_status.setErrorMessage(msg);
+ resp.setStatus(ts_status);
+ resp.setResult(result);
+ return resp;
+ }
+
+ private TSFetchResultsResp getTSFetchResultsResp(TS_StatusCode code, String msg) {
+ TSFetchResultsResp resp = new TSFetchResultsResp();
+ TS_Status ts_status = new TS_Status(code);
+ ts_status.setErrorMessage(msg);
+ resp.setStatus(ts_status);
+ return resp;
+ }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/Utils.java b/src/main/java/cn/edu/thu/tsfiledb/service/Utils.java
new file mode 100644
index 00000000000..f7ab5e04f90
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/Utils.java
@@ -0,0 +1,129 @@
+package cn.edu.thu.tsfiledb.service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import cn.edu.thu.tsfile.timeseries.read.query.DynamicOneColumnData;
+import cn.edu.thu.tsfile.timeseries.read.query.QueryDataSet;
+import cn.edu.thu.tsfiledb.metadata.ColumnSchema;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSColumnSchema;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSDynamicOneColumnData;
+import cn.edu.thu.tsfiledb.service.rpc.thrift.TSQueryDataSet;
+
+public class Utils {
+ public static Map> convertAllSchema(Map> allSchema){
+ if(allSchema == null){
+ return null;
+ }
+ Map> tsAllSchema = new HashMap<>();
+ for(Map.Entry> entry : allSchema.entrySet()){
+ List tsColumnSchemas = new ArrayList<>();
+ for(ColumnSchema columnSchema : entry.getValue()){
+ tsColumnSchemas.add(convertColumnSchema(columnSchema));
+ }
+ tsAllSchema.put(entry.getKey(), tsColumnSchemas);
+ }
+ return tsAllSchema;
+ }
+
+ public static TSColumnSchema convertColumnSchema(ColumnSchema schema){
+ if(schema == null){
+ return null;
+ }
+ TSColumnSchema tsColumnSchema = new TSColumnSchema();
+ tsColumnSchema.setName(schema.name);
+ tsColumnSchema.setDataType(schema.dataType == null ? null : schema.dataType.toString());
+ tsColumnSchema.setEncoding(schema.encoding == null ? null : schema.encoding.toString());
+ tsColumnSchema.setOtherArgs(schema.getArgsMap() == null ? null : schema.getArgsMap());
+ return tsColumnSchema;
+ }
+
+
+ public static TSQueryDataSet convertQueryDataSet(QueryDataSet queryDataSet){
+ List keys = new ArrayList<>();
+ List values = new ArrayList<>();
+ for(Map.Entry entry: queryDataSet.mapRet.entrySet()){
+ keys.add(entry.getKey());
+ values.add(convertDynamicOneColumnData(entry.getValue()));
+ }
+ TSQueryDataSet tsQueryDataSet = new TSQueryDataSet(keys,values);
+ return tsQueryDataSet;
+ }
+
+
+ public static TSDynamicOneColumnData convertDynamicOneColumnData(DynamicOneColumnData dynamicOneColumnData){
+ List timeRetList = new ArrayList();
+ for(int i = 0 ; i < dynamicOneColumnData.timeLength; i ++){
+ timeRetList.add(dynamicOneColumnData.getTime(i));
+ }
+ TSDynamicOneColumnData tsDynamicOneColumnData = new TSDynamicOneColumnData(dynamicOneColumnData.getDeltaObjectType(), dynamicOneColumnData.dataType.toString(), dynamicOneColumnData.length, timeRetList);
+
+ switch (dynamicOneColumnData.dataType) {
+ case BOOLEAN:
+ List boolList = new ArrayList<>();
+ for(int i = 0 ; i < dynamicOneColumnData.length; i ++){
+ boolList.add(dynamicOneColumnData.getBoolean(i));
+ }
+ tsDynamicOneColumnData.setBoolList(boolList);
+ break;
+ case INT32:
+ List intList = new ArrayList<>();
+ for(int i = 0 ; i < dynamicOneColumnData.length; i ++){
+ intList.add(dynamicOneColumnData.getInt(i));
+ }
+ tsDynamicOneColumnData.setI32List(intList);
+ break;
+ case INT64:
+ List longList = new ArrayList<>();
+ for(int i = 0 ; i < dynamicOneColumnData.length; i ++){
+ longList.add(dynamicOneColumnData.getLong(i));
+ }
+ tsDynamicOneColumnData.setI64List(longList);
+ break;
+ case FLOAT:
+ List floatList = new ArrayList<>();
+ for(int i = 0 ; i < dynamicOneColumnData.length; i ++){
+ floatList.add((double) dynamicOneColumnData.getFloat(i));
+ }
+ tsDynamicOneColumnData.setFloatList(floatList);
+ break;
+ case DOUBLE:
+ List doubleList = new ArrayList<>();
+ for(int i = 0 ; i < dynamicOneColumnData.length; i ++){
+ doubleList.add(dynamicOneColumnData.getDouble(i));
+ }
+ tsDynamicOneColumnData.setDoubleList(doubleList);
+ break;
+ case BYTE_ARRAY:
+ List byteList = new ArrayList<>();
+ for(int i = 0 ; i < dynamicOneColumnData.length; i ++){
+ byteList.add(Byte.valueOf(dynamicOneColumnData.getStringValue(i)));
+ }
+ tsDynamicOneColumnData.setBinaryList(byteList);
+ break;
+ default:
+ break;
+ }
+
+ return tsDynamicOneColumnData;
+ }
+
+// public static TSJDBCRecord convertRecord(TSRecord record){
+// TSJDBCRecord tsJDBCRecord = new TSJDBCRecord();
+// tsJDBCRecord.setDeviceId(record.getRowKey());
+// tsJDBCRecord.setTimeValue(new TSTimeValue(record.getTime().getTime()));
+// tsJDBCRecord.setDeviceType(record.getDeviceType());
+// List dataPoints = new ArrayList<>();
+// for(DataPoint point : record.getTuple()){
+// String valueStr = point.getValue() == null ? "null" : point.getValue();
+// TSDataPoint tsDataPoint = new TSDataPoint(point.getType().toString(),point.getSeriesName(),point.getDeviceId(),valueStr);
+// tsDataPoint.setGroupId(point.getGroupId());
+// dataPoints.add(tsDataPoint);
+// }
+// tsJDBCRecord.setDataList(dataPoints);
+// return tsJDBCRecord;
+// }
+
+}
diff --git a/src/main/java/cn/edu/thu/tsfiledb/service/rpc/thrift/TSCancelOperationReq.java b/src/main/java/cn/edu/thu/tsfiledb/service/rpc/thrift/TSCancelOperationReq.java
new file mode 100644
index 00000000000..7bfe06b620d
--- /dev/null
+++ b/src/main/java/cn/edu/thu/tsfiledb/service/rpc/thrift/TSCancelOperationReq.java
@@ -0,0 +1,393 @@
+/**
+ * Autogenerated by Thrift Compiler (0.9.2)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ * @generated
+ */
+package cn.edu.thu.tsfiledb.service.rpc.thrift;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import javax.annotation.Generated;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-5-10")
+public class TSCancelOperationReq implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("TSCancelOperationReq");
+
+ private static final org.apache.thrift.protocol.TField OPERATION_HANDLE_FIELD_DESC = new org.apache.thrift.protocol.TField("operationHandle", org.apache.thrift.protocol.TType.STRUCT, (short)1);
+
+ private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new TSCancelOperationReqStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new TSCancelOperationReqTupleSchemeFactory());
+ }
+
+ public TSOperationHandle operationHandle; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ OPERATION_HANDLE((short)1, "operationHandle");
+
+ private static final Map byName = new HashMap();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // OPERATION_HANDLE
+ return OPERATION_HANDLE;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.OPERATION_HANDLE, new org.apache.thrift.meta_data.FieldMetaData("operationHandle", org.apache.thrift.TFieldRequirementType.REQUIRED,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT , "TSOperationHandle")));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(TSCancelOperationReq.class, metaDataMap);
+ }
+
+ public TSCancelOperationReq() {
+ }
+
+ public TSCancelOperationReq(
+ TSOperationHandle operationHandle)
+ {
+ this();
+ this.operationHandle = operationHandle;
+ }
+
+ /**
+ * Performs a deep copy on other.
+ */
+ public TSCancelOperationReq(TSCancelOperationReq other) {
+ if (other.isSetOperationHandle()) {
+ this.operationHandle = other.operationHandle;
+ }
+ }
+
+ public TSCancelOperationReq deepCopy() {
+ return new TSCancelOperationReq(this);
+ }
+
+ @Override
+ public void clear() {
+ this.operationHandle = null;
+ }
+
+ public TSOperationHandle getOperationHandle() {
+ return this.operationHandle;
+ }
+
+ public TSCancelOperationReq setOperationHandle(TSOperationHandle operationHandle) {
+ this.operationHandle = operationHandle;
+ return this;
+ }
+
+ public void unsetOperationHandle() {
+ this.operationHandle = null;
+ }
+
+ /** Returns true if field operationHandle is set (has been assigned a value) and false otherwise */
+ public boolean isSetOperationHandle() {
+ return this.operationHandle != null;
+ }
+
+ public void setOperationHandleIsSet(boolean value) {
+ if (!value) {
+ this.operationHandle = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case OPERATION_HANDLE:
+ if (value == null) {
+ unsetOperationHandle();
+ } else {
+ setOperationHandle((TSOperationHandle)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case OPERATION_HANDLE:
+ return getOperationHandle();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case OPERATION_HANDLE:
+ return isSetOperationHandle();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof TSCancelOperationReq)
+ return this.equals((TSCancelOperationReq)that);
+ return false;
+ }
+
+ public boolean equals(TSCancelOperationReq that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_operationHandle = true && this.isSetOperationHandle();
+ boolean that_present_operationHandle = true && that.isSetOperationHandle();
+ if (this_present_operationHandle || that_present_operationHandle) {
+ if (!(this_present_operationHandle && that_present_operationHandle))
+ return false;
+ if (!this.operationHandle.equals(that.operationHandle))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ List