This is an automated email from the ASF dual-hosted git repository.
jiangtian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 5cc46a9 [IOTDB-96]Refactor author query (#179)
5cc46a9 is described below
commit 5cc46a97e48468cc905bb29bfee1a0d3fdbff622
Author: Jiang Tian <[email protected]>
AuthorDate: Fri May 31 10:12:25 2019 +0800
[IOTDB-96]Refactor author query (#179)
* use a more elegant way to return results of Authorization queries like
'LIST USERS'
* fix tests
* improve client display
* fix a test in windows
* fix client display
---
.../apache/iotdb/cli/client/AbstractClient.java | 4 +
.../apache/iotdb/db/auth/entity/PathPrivilege.java | 1 -
.../org/apache/iotdb/db/conf/IoTDBConstant.java | 4 +
.../db/qp/executor/IQueryProcessExecutor.java | 3 +-
.../iotdb/db/qp/executor/OverflowQPExecutor.java | 263 ++++++++-----
.../iotdb/db/qp/executor/QueryProcessExecutor.java | 17 +-
.../apache/iotdb/db/qp/physical/PhysicalPlan.java | 4 +
.../iotdb/db/qp/physical/sys/AuthorPlan.java | 6 +
.../apache/iotdb/db/query/dataset/AuthDataSet.java | 53 +++
.../org/apache/iotdb/db/service/TSServiceImpl.java | 195 ++++++----
.../iotdb/db/integration/IoTDBAuthorizationIT.java | 416 +++++++++++----------
.../apache/iotdb/db/qp/utils/MemIntQpExecutor.java | 6 +
.../org/apache/iotdb/jdbc/IoTDBQueryResultSet.java | 9 +
.../java/org/apache/iotdb/jdbc/IoTDBStatement.java | 9 +-
service-rpc/src/main/thrift/rpc.thrift | 1 +
15 files changed, 616 insertions(+), 375 deletions(-)
diff --git
a/iotdb-cli/src/main/java/org/apache/iotdb/cli/client/AbstractClient.java
b/iotdb-cli/src/main/java/org/apache/iotdb/cli/client/AbstractClient.java
index e4c4137..586a5d9 100644
--- a/iotdb-cli/src/main/java/org/apache/iotdb/cli/client/AbstractClient.java
+++ b/iotdb-cli/src/main/java/org/apache/iotdb/cli/client/AbstractClient.java
@@ -42,6 +42,7 @@ import org.apache.iotdb.cli.tool.ImportCsv;
import org.apache.iotdb.jdbc.IoTDBConnection;
import org.apache.iotdb.jdbc.IoTDBDatabaseMetadata;
import org.apache.iotdb.jdbc.IoTDBMetadataResultSet;
+import org.apache.iotdb.jdbc.IoTDBQueryResultSet;
import org.apache.iotdb.jdbc.IoTDBSQLException;
import org.apache.iotdb.service.rpc.thrift.ServerProperties;
import org.apache.thrift.TException;
@@ -188,6 +189,9 @@ public abstract class AbstractClient {
if (!isShow && resultSetMetaData.getColumnTypeName(0) != null) {
printTimestamp =
!res.getMetaData().getColumnTypeName(0).equalsIgnoreCase(NEED_NOT_TO_PRINT_TIMESTAMP);
}
+ if (res instanceof IoTDBQueryResultSet) {
+ printTimestamp = printTimestamp && ((IoTDBQueryResultSet)
res).isIgnoreTimeStamp();
+ }
// Output values
while (res.next()) {
diff --git
a/iotdb/src/main/java/org/apache/iotdb/db/auth/entity/PathPrivilege.java
b/iotdb/src/main/java/org/apache/iotdb/db/auth/entity/PathPrivilege.java
index 11579fe..4339cc1 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/auth/entity/PathPrivilege.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/auth/entity/PathPrivilege.java
@@ -101,7 +101,6 @@ public class PathPrivilege {
for (Integer privilegeId : privileges) {
builder.append(" ").append(PrivilegeType.values()[privilegeId]);
}
- builder.append("\n");
return builder.toString();
}
}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
b/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
index 48e927f..e2775cd 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
@@ -59,4 +59,8 @@ public class IoTDBConstant {
// for cluster, set read consistency level
public static final String SET_READ_CONSISTENCY_LEVEL_PATTERN =
"set\\s+read.*level.*";
+
+ public static final String ROLE = "Role";
+ public static final String USER = "User";
+ public static final String PRIVILEGE = "Privilege";
}
diff --git
a/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/IQueryProcessExecutor.java
b/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/IQueryProcessExecutor.java
index 920aeef..6377f44 100644
---
a/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/IQueryProcessExecutor.java
+++
b/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/IQueryProcessExecutor.java
@@ -25,7 +25,6 @@ import org.apache.iotdb.db.exception.FileNodeManagerException;
import org.apache.iotdb.db.exception.PathErrorException;
import org.apache.iotdb.db.exception.ProcessorException;
import org.apache.iotdb.db.qp.physical.PhysicalPlan;
-import org.apache.iotdb.db.qp.physical.crud.QueryPlan;
import org.apache.iotdb.db.query.context.QueryContext;
import org.apache.iotdb.db.query.fill.IFill;
import
org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException;
@@ -51,7 +50,7 @@ public interface IQueryProcessExecutor {
* @param queryPlan QueryPlan
* @return QueryDataSet
*/
- QueryDataSet processQuery(QueryPlan queryPlan, QueryContext context)
+ QueryDataSet processQuery(PhysicalPlan queryPlan, QueryContext context)
throws IOException, FileNodeManagerException, PathErrorException,
QueryFilterOptimizationException, ProcessorException;
diff --git
a/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/OverflowQPExecutor.java
b/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/OverflowQPExecutor.java
index 9ca337e..e772bf5 100644
---
a/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/OverflowQPExecutor.java
+++
b/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/OverflowQPExecutor.java
@@ -18,6 +18,10 @@
*/
package org.apache.iotdb.db.qp.executor;
+import static org.apache.iotdb.db.conf.IoTDBConstant.PRIVILEGE;
+import static org.apache.iotdb.db.conf.IoTDBConstant.ROLE;
+import static org.apache.iotdb.db.conf.IoTDBConstant.USER;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
@@ -41,6 +45,7 @@ import org.apache.iotdb.db.metadata.MNode;
import org.apache.iotdb.db.monitor.MonitorConstants;
import org.apache.iotdb.db.qp.constant.SQLConstant;
import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
+import org.apache.iotdb.db.qp.logical.sys.AuthorOperator.AuthorType;
import org.apache.iotdb.db.qp.logical.sys.MetadataOperator;
import org.apache.iotdb.db.qp.logical.sys.PropertyOperator;
import org.apache.iotdb.db.qp.physical.PhysicalPlan;
@@ -52,6 +57,7 @@ import org.apache.iotdb.db.qp.physical.sys.LoadDataPlan;
import org.apache.iotdb.db.qp.physical.sys.MetadataPlan;
import org.apache.iotdb.db.qp.physical.sys.PropertyPlan;
import org.apache.iotdb.db.query.context.QueryContext;
+import org.apache.iotdb.db.query.dataset.AuthDataSet;
import org.apache.iotdb.db.query.executor.EngineQueryRouter;
import org.apache.iotdb.db.query.fill.IFill;
import org.apache.iotdb.db.utils.AuthUtils;
@@ -60,9 +66,12 @@ import
org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.read.common.Field;
import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
import org.apache.iotdb.tsfile.read.expression.IExpression;
import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
+import org.apache.iotdb.tsfile.utils.Binary;
import org.apache.iotdb.tsfile.utils.Pair;
import org.apache.iotdb.tsfile.write.record.TSRecord;
import org.apache.iotdb.tsfile.write.record.datapoint.DataPoint;
@@ -132,14 +141,16 @@ public class OverflowQPExecutor extends
QueryProcessExecutor {
case GRANT_USER_ROLE:
case MODIFY_PASSWORD:
case DELETE_USER:
+ AuthorPlan author = (AuthorPlan) plan;
+ return operateAuthor(author);
case LIST_ROLE:
case LIST_USER:
case LIST_ROLE_PRIVILEGE:
case LIST_ROLE_USERS:
case LIST_USER_PRIVILEGE:
case LIST_USER_ROLES:
- AuthorPlan author = (AuthorPlan) plan;
- return operateAuthor(author);
+ throw new ProcessorException(String.format("Author query %s is now
allowed"
+ + " in processNonQuery", plan.getOperatorType()));
case LOADDATA:
LoadDataPlan loadData = (LoadDataPlan) plan;
LoadDataUtils load = new LoadDataUtils();
@@ -312,15 +323,12 @@ public class OverflowQPExecutor extends
QueryProcessExecutor {
String newPassword = author.getNewPassword();
Set<Integer> permissions = author.getPermissions();
Path nodeName = author.getNodeName();
- IAuthorizer authorizer = null;
+ IAuthorizer authorizer;
try {
authorizer = LocalFileAuthorizer.getInstance();
} catch (AuthException e) {
throw new ProcessorException(e);
}
- StringBuilder msg;
- List<String> roleList;
- List<String> userList;
try {
switch (authorType) {
case UPDATE_USER:
@@ -394,94 +402,6 @@ public class OverflowQPExecutor extends
QueryProcessExecutor {
throw new ProcessorException("User " + userName + " does not have
role " + roleName);
}
return true;
- case LIST_ROLE:
- roleList = authorizer.listAllRoles();
- msg = new StringBuilder("Roles are : [ \n");
- for (String role : roleList) {
- msg.append(role).append("\n");
- }
- msg.append("]");
- // TODO : use a more elegant way to pass message.
- throw new ProcessorException(msg.toString());
- case LIST_USER:
- userList = authorizer.listAllUsers();
- msg = new StringBuilder("Users are : [ \n");
- for (String user : userList) {
- msg.append(user).append("\n");
- }
- msg.append("]");
- throw new ProcessorException(msg.toString());
- case LIST_ROLE_USERS:
- Role role = authorizer.getRole(roleName);
- if (role == null) {
- throw new ProcessorException("No such role : " + roleName);
- }
- userList = authorizer.listAllUsers();
- msg = new StringBuilder("Users are : [ \n");
- for (String userN : userList) {
- User userObj = authorizer.getUser(userN);
- if (userObj != null && userObj.hasRole(roleName)) {
- msg.append(userN).append("\n");
- }
- }
- msg.append("]");
- throw new ProcessorException(msg.toString());
- case LIST_USER_ROLES:
- msg = new StringBuilder("Roles are : [ \n");
- User user = authorizer.getUser(userName);
- if (user != null) {
- for (String roleN : user.getRoleList()) {
- msg.append(roleN).append("\n");
- }
- } else {
- throw new ProcessorException("No such user : " + userName);
- }
- msg.append("]");
- throw new ProcessorException(msg.toString());
- case LIST_ROLE_PRIVILEGE:
- msg = new StringBuilder("Privileges are : [ \n");
- role = authorizer.getRole(roleName);
- if (role != null) {
- for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
- if (nodeName == null || AuthUtils
- .pathBelongsTo(nodeName.getFullPath(),
pathPrivilege.getPath())) {
- msg.append(pathPrivilege.toString());
- }
- }
- } else {
- throw new ProcessorException("No such role : " + roleName);
- }
- msg.append("]");
- throw new ProcessorException(msg.toString());
- case LIST_USER_PRIVILEGE:
- user = authorizer.getUser(userName);
- if (user == null) {
- throw new ProcessorException("No such user : " + userName);
- }
- msg = new StringBuilder("Privileges are : [ \n");
- msg.append("From itself : {\n");
- for (PathPrivilege pathPrivilege : user.getPrivilegeList()) {
- if (nodeName == null || AuthUtils
- .pathBelongsTo(nodeName.getFullPath(),
pathPrivilege.getPath())) {
- msg.append(pathPrivilege.toString());
- }
- }
- msg.append("}\n");
- for (String roleN : user.getRoleList()) {
- role = authorizer.getRole(roleN);
- if (role != null) {
- msg.append("From role ").append(roleN).append(" : {\n");
- for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
- if (nodeName == null
- || AuthUtils.pathBelongsTo(nodeName.getFullPath(),
pathPrivilege.getPath())) {
- msg.append(pathPrivilege.toString());
- }
- }
- msg.append("}\n");
- }
- }
- msg.append("]");
- throw new ProcessorException(msg.toString());
default:
throw new ProcessorException("Unsupported operation " + authorType);
}
@@ -679,4 +599,159 @@ public class OverflowQPExecutor extends
QueryProcessExecutor {
}
return true;
}
+
+ @Override
+ protected QueryDataSet processAuthorQuery(AuthorPlan plan, QueryContext
context)
+ throws ProcessorException {
+ AuthorType authorType = plan.getAuthorType();
+ String userName = plan.getUserName();
+ String roleName = plan.getRoleName();
+ Path nodeName = plan.getNodeName();
+ IAuthorizer authorizer;
+ try {
+ authorizer = LocalFileAuthorizer.getInstance();
+ } catch (AuthException e) {
+ throw new ProcessorException(e);
+ }
+ List<Path> headerList = new ArrayList<>();
+ List<TSDataType> typeList = new ArrayList<>();
+ List<String> roleList;
+ List<String> userList;
+ AuthDataSet dataSet;
+ int index = 0;
+ try {
+ switch (authorType) {
+ case LIST_ROLE:
+ headerList.add(new Path(ROLE));
+ typeList.add(TSDataType.TEXT);
+ dataSet = new AuthDataSet(headerList, typeList);
+ roleList = authorizer.listAllRoles();
+ for (String role : roleList) {
+ RowRecord record = new RowRecord(index++);
+ Field field = new Field(TSDataType.TEXT);
+ field.setBinaryV(new Binary(role));
+ record.addField(field);
+ dataSet.putRecord(record);
+ }
+ break;
+ case LIST_USER:
+ userList = authorizer.listAllUsers();
+ headerList.add(new Path(USER));
+ typeList.add(TSDataType.TEXT);
+ dataSet = new AuthDataSet(headerList, typeList);
+ for (String user : userList) {
+ RowRecord record = new RowRecord(index++);
+ Field field = new Field(TSDataType.TEXT);
+ field.setBinaryV(new Binary(user));
+ record.addField(field);
+ dataSet.putRecord(record);
+ }
+ break;
+ case LIST_ROLE_USERS:
+ Role role = authorizer.getRole(roleName);
+ if (role == null) {
+ throw new ProcessorException("No such role : " + roleName);
+ }
+ headerList.add(new Path(USER));
+ typeList.add(TSDataType.TEXT);
+ dataSet = new AuthDataSet(headerList, typeList);
+ userList = authorizer.listAllUsers();
+ for (String userN : userList) {
+ User userObj = authorizer.getUser(userN);
+ if (userObj != null && userObj.hasRole(roleName)) {
+ RowRecord record = new RowRecord(index++);
+ Field field = new Field(TSDataType.TEXT);
+ field.setBinaryV(new Binary(userN));
+ record.addField(field);
+ dataSet.putRecord(record);
+ }
+ }
+ break;
+ case LIST_USER_ROLES:
+ User user = authorizer.getUser(userName);
+ if (user != null) {
+ headerList.add(new Path(ROLE));
+ typeList.add(TSDataType.TEXT);
+ dataSet = new AuthDataSet(headerList, typeList);
+ for (String roleN : user.getRoleList()) {
+ RowRecord record = new RowRecord(index++);
+ Field field = new Field(TSDataType.TEXT);
+ field.setBinaryV(new Binary(roleN));
+ record.addField(field);
+ dataSet.putRecord(record);
+ }
+ } else {
+ throw new ProcessorException("No such user : " + userName);
+ }
+ break;
+ case LIST_ROLE_PRIVILEGE:
+ role = authorizer.getRole(roleName);
+ if (role != null) {
+ headerList.add(new Path(PRIVILEGE));
+ typeList.add(TSDataType.TEXT);
+ dataSet = new AuthDataSet(headerList, typeList);
+ for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
+ if (nodeName == null || AuthUtils
+ .pathBelongsTo(nodeName.getFullPath(),
pathPrivilege.getPath())) {
+ RowRecord record = new RowRecord(index++);
+ Field field = new Field(TSDataType.TEXT);
+ field.setBinaryV(new Binary(pathPrivilege.toString()));
+ record.addField(field);
+ dataSet.putRecord(record);
+ }
+ }
+ } else {
+ throw new ProcessorException("No such role : " + roleName);
+ }
+ break;
+ case LIST_USER_PRIVILEGE:
+ user = authorizer.getUser(userName);
+ if (user == null) {
+ throw new ProcessorException("No such user : " + userName);
+ }
+ headerList.add(new Path(ROLE));
+ headerList.add(new Path(PRIVILEGE));
+ typeList.add(TSDataType.TEXT);
+ typeList.add(TSDataType.TEXT);
+ dataSet = new AuthDataSet(headerList, typeList);
+ for (PathPrivilege pathPrivilege : user.getPrivilegeList()) {
+ if (nodeName == null || AuthUtils
+ .pathBelongsTo(nodeName.getFullPath(),
pathPrivilege.getPath())) {
+ RowRecord record = new RowRecord(index++);
+ Field roleF = new Field(TSDataType.TEXT);
+ roleF.setBinaryV(new Binary(""));
+ record.addField(roleF);
+ Field privilegeF = new Field(TSDataType.TEXT);
+ privilegeF.setBinaryV(new Binary(pathPrivilege.toString()));
+ record.addField(privilegeF);
+ dataSet.putRecord(record);
+ }
+ }
+ for (String roleN : user.getRoleList()) {
+ role = authorizer.getRole(roleN);
+ if (role != null) {
+ for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
+ if (nodeName == null
+ || AuthUtils.pathBelongsTo(nodeName.getFullPath(),
pathPrivilege.getPath())) {
+ RowRecord record = new RowRecord(index++);
+ Field roleF = new Field(TSDataType.TEXT);
+ roleF.setBinaryV(new Binary(roleN));
+ record.addField(roleF);
+ Field privilegeF = new Field(TSDataType.TEXT);
+ privilegeF.setBinaryV(new Binary(pathPrivilege.toString()));
+ record.addField(privilegeF);
+ dataSet.putRecord(record);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ throw new ProcessorException("Unsupported operation " + authorType);
+ }
+ } catch (AuthException e) {
+ throw new ProcessorException(e.getMessage());
+ }
+ return dataSet;
+ }
}
diff --git
a/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/QueryProcessExecutor.java
b/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/QueryProcessExecutor.java
index 17768aa..94939e9 100644
---
a/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/QueryProcessExecutor.java
+++
b/iotdb/src/main/java/org/apache/iotdb/db/qp/executor/QueryProcessExecutor.java
@@ -32,6 +32,7 @@ import org.apache.iotdb.db.qp.physical.crud.AggregationPlan;
import org.apache.iotdb.db.qp.physical.crud.FillQueryPlan;
import org.apache.iotdb.db.qp.physical.crud.GroupByPlan;
import org.apache.iotdb.db.qp.physical.crud.QueryPlan;
+import org.apache.iotdb.db.qp.physical.sys.AuthorPlan;
import org.apache.iotdb.db.query.context.QueryContext;
import org.apache.iotdb.db.query.executor.EngineQueryRouter;
import org.apache.iotdb.db.query.executor.IEngineQueryRouter;
@@ -46,10 +47,24 @@ public abstract class QueryProcessExecutor implements
IQueryProcessExecutor {
protected IEngineQueryRouter queryRouter = new EngineQueryRouter();
@Override
- public QueryDataSet processQuery(QueryPlan queryPlan, QueryContext context)
+ public QueryDataSet processQuery(PhysicalPlan queryPlan, QueryContext
context)
throws IOException, FileNodeManagerException, PathErrorException,
QueryFilterOptimizationException, ProcessorException {
+ if (queryPlan instanceof QueryPlan) {
+ return processDataQuery((QueryPlan) queryPlan, context);
+ } else if (queryPlan instanceof AuthorPlan) {
+ return processAuthorQuery((AuthorPlan) queryPlan, context);
+ } else {
+ throw new ProcessorException(String.format("Unrecognized query plan %s",
queryPlan));
+ }
+ }
+
+ protected abstract QueryDataSet processAuthorQuery(AuthorPlan plan,
QueryContext context)
+ throws ProcessorException;
+
+ private QueryDataSet processDataQuery(QueryPlan queryPlan, QueryContext
context)
+ throws FileNodeManagerException, QueryFilterOptimizationException,
PathErrorException, ProcessorException, IOException {
QueryExpression queryExpression =
QueryExpression.create().setSelectSeries(queryPlan.getPaths())
.setExpression(queryPlan.getExpression());
if (queryPlan instanceof GroupByPlan) {
diff --git
a/iotdb/src/main/java/org/apache/iotdb/db/qp/physical/PhysicalPlan.java
b/iotdb/src/main/java/org/apache/iotdb/db/qp/physical/PhysicalPlan.java
index d2f7bb9..07d1e75 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/qp/physical/PhysicalPlan.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/qp/physical/PhysicalPlan.java
@@ -75,4 +75,8 @@ public abstract class PhysicalPlan implements Serializable {
public void setProposer(String proposer) {
this.proposer = proposer;
}
+
+ public void setQuery(boolean query) {
+ isQuery = query;
+ }
}
diff --git
a/iotdb/src/main/java/org/apache/iotdb/db/qp/physical/sys/AuthorPlan.java
b/iotdb/src/main/java/org/apache/iotdb/db/qp/physical/sys/AuthorPlan.java
index 3ec812c..339f1e0 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/qp/physical/sys/AuthorPlan.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/qp/physical/sys/AuthorPlan.java
@@ -99,21 +99,27 @@ public class AuthorPlan extends PhysicalPlan {
this.setOperatorType(Operator.OperatorType.REVOKE_USER_ROLE);
break;
case LIST_USER_PRIVILEGE:
+ this.setQuery(true);
this.setOperatorType(Operator.OperatorType.LIST_USER_PRIVILEGE);
break;
case LIST_ROLE_PRIVILEGE:
+ this.setQuery(true);
this.setOperatorType(Operator.OperatorType.LIST_ROLE_PRIVILEGE);
break;
case LIST_USER_ROLES:
+ this.setQuery(true);
this.setOperatorType(Operator.OperatorType.LIST_USER_ROLES);
break;
case LIST_ROLE_USERS:
+ this.setQuery(true);
this.setOperatorType(Operator.OperatorType.LIST_ROLE_USERS);
break;
case LIST_USER:
+ this.setQuery(true);
this.setOperatorType(Operator.OperatorType.LIST_USER);
break;
case LIST_ROLE:
+ this.setQuery(true);
this.setOperatorType(Operator.OperatorType.LIST_ROLE);
break;
default:
diff --git
a/iotdb/src/main/java/org/apache/iotdb/db/query/dataset/AuthDataSet.java
b/iotdb/src/main/java/org/apache/iotdb/db/query/dataset/AuthDataSet.java
new file mode 100644
index 0000000..1846f12
--- /dev/null
+++ b/iotdb/src/main/java/org/apache/iotdb/db/query/dataset/AuthDataSet.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.query.dataset;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
+
+public class AuthDataSet extends QueryDataSet {
+
+ List<RowRecord> records = new ArrayList<>();
+ int index = 0;
+
+ public AuthDataSet(List<Path> paths,
+ List<TSDataType> dataTypes) {
+ super(paths, dataTypes);
+ }
+
+ @Override
+ public boolean hasNext() throws IOException {
+ return index < records.size();
+ }
+
+ @Override
+ public RowRecord next() throws IOException {
+ return records.get(index++);
+ }
+
+ public void putRecord(RowRecord newRecord) {
+ records.add(newRecord);
+ }
+}
diff --git a/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
b/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
index 592b009..4b3d62e 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
@@ -18,6 +18,10 @@
*/
package org.apache.iotdb.db.service;
+import static org.apache.iotdb.db.conf.IoTDBConstant.PRIVILEGE;
+import static org.apache.iotdb.db.conf.IoTDBConstant.ROLE;
+import static org.apache.iotdb.db.conf.IoTDBConstant.USER;
+
import java.io.IOException;
import java.nio.ByteBuffer;
import java.sql.Statement;
@@ -563,80 +567,12 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
PhysicalPlan plan = processor.parseSQLToPhysicalPlan(statement,
zoneIds.get());
plan.setProposer(username.get());
- List<Path> paths;
- paths = plan.getPaths();
-
- // check seriesPath exists
- if (paths.isEmpty()) {
- return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
"Timeseries does not exist.");
- }
-
- // check file level set
-
- try {
- checkFileLevelSet(paths);
- } catch (PathErrorException e) {
- LOGGER.error("meet error while checking file level.", e);
- return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
e.getMessage());
- }
-
- // check permissions
- if (!checkAuthorization(paths, plan)) {
- return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
- "No permissions for this query.");
- }
-
- TSExecuteStatementResp resp =
getTSExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS, "");
+ TSExecuteStatementResp resp;
List<String> columns = new ArrayList<>();
- // Restore column header of aggregate to func(column_name), only
- // support single aggregate function for now
- if (plan instanceof QueryPlan) {
- switch (plan.getOperatorType()) {
- case QUERY:
- case FILL:
- for (Path p : paths) {
- columns.add(p.getFullPath());
- }
- break;
- case AGGREGATION:
- case GROUPBY:
- List<String> aggregations = plan.getAggregations();
- if (aggregations.size() != paths.size()) {
- for (int i = 1; i < paths.size(); i++) {
- aggregations.add(aggregations.get(0));
- }
- }
- for (int i = 0; i < paths.size(); i++) {
- columns.add(aggregations.get(i) + "(" +
paths.get(i).getFullPath() + ")");
- }
- break;
- default:
- throw new TException("unsupported query type: " +
plan.getOperatorType());
- }
+ if (!(plan instanceof AuthorPlan)) {
+ resp = executeDataQuery(plan, columns);
} else {
- Operator.OperatorType type = plan.getOperatorType();
- switch (type) {
- case QUERY:
- case FILL:
- for (Path p : paths) {
- columns.add(p.getFullPath());
- }
- break;
- case AGGREGATION:
- case GROUPBY:
- List<String> aggregations = plan.getAggregations();
- if (aggregations.size() != paths.size()) {
- for (int i = 1; i < paths.size(); i++) {
- aggregations.add(aggregations.get(0));
- }
- }
- for (int i = 0; i < paths.size(); i++) {
- columns.add(aggregations.get(i) + "(" +
paths.get(i).getFullPath() + ")");
- }
- break;
- default:
- throw new TException("not support " + type + " in new read
process");
- }
+ resp = executeAuthQuery(plan, columns);
}
resp.setOperationType(plan.getOperatorType().toString());
@@ -655,6 +591,116 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
}
}
+ private TSExecuteStatementResp executeAuthQuery(PhysicalPlan plan,
List<String> columns) {
+ TSExecuteStatementResp resp =
getTSExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS, "");
+ resp.ignoreTimeStamp = true;
+ AuthorPlan authorPlan = (AuthorPlan) plan;
+ switch (authorPlan.getAuthorType()) {
+ case LIST_ROLE:
+ columns.add(ROLE);
+ break;
+ case LIST_USER:
+ columns.add(USER);
+ break;
+ case LIST_ROLE_USERS:
+ columns.add(USER);
+ break;
+ case LIST_USER_ROLES:
+ columns.add(ROLE);
+ break;
+ case LIST_ROLE_PRIVILEGE:
+ columns.add(PRIVILEGE);
+ break;
+ case LIST_USER_PRIVILEGE:
+ columns.add(ROLE);
+ columns.add(PRIVILEGE);
+ break;
+ default:
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
String.format("%s is not an "
+ + "auth query", authorPlan.getAuthorType()));
+ }
+ return resp;
+ }
+
+ private TSExecuteStatementResp executeDataQuery(PhysicalPlan plan,
List<String> columns)
+ throws AuthException, TException {
+ List<Path> paths;
+ paths = plan.getPaths();
+
+ // check seriesPath exists
+ if (paths.isEmpty()) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, "Timeseries
does not exist.");
+ }
+
+ // check file level set
+
+ try {
+ checkFileLevelSet(paths);
+ } catch (PathErrorException e) {
+ LOGGER.error("meet error while checking file level.", e);
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
e.getMessage());
+ }
+
+ // check permissions
+ if (!checkAuthorization(paths, plan)) {
+ return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS,
+ "No permissions for this query.");
+ }
+
+ TSExecuteStatementResp resp =
getTSExecuteStatementResp(TS_StatusCode.SUCCESS_STATUS, "");
+ // Restore column header of aggregate to func(column_name), only
+ // support single aggregate function for now
+ if (plan instanceof QueryPlan) {
+ switch (plan.getOperatorType()) {
+ case QUERY:
+ case FILL:
+ for (Path p : paths) {
+ columns.add(p.getFullPath());
+ }
+ break;
+ case AGGREGATION:
+ case GROUPBY:
+ List<String> aggregations = plan.getAggregations();
+ if (aggregations.size() != paths.size()) {
+ for (int i = 1; i < paths.size(); i++) {
+ aggregations.add(aggregations.get(0));
+ }
+ }
+ for (int i = 0; i < paths.size(); i++) {
+ columns.add(aggregations.get(i) + "(" + paths.get(i).getFullPath()
+ ")");
+ }
+ break;
+ default:
+ throw new TException("unsupported query type: " +
plan.getOperatorType());
+ }
+ } else {
+ Operator.OperatorType type = plan.getOperatorType();
+ switch (type) {
+ case QUERY:
+ case FILL:
+ for (Path p : paths) {
+ columns.add(p.getFullPath());
+ }
+ break;
+ case AGGREGATION:
+ case GROUPBY:
+ List<String> aggregations = plan.getAggregations();
+ if (aggregations.size() != paths.size()) {
+ for (int i = 1; i < paths.size(); i++) {
+ aggregations.add(aggregations.get(0));
+ }
+ }
+ for (int i = 0; i < paths.size(); i++) {
+ columns.add(aggregations.get(i) + "(" + paths.get(i).getFullPath()
+ ")");
+ }
+ break;
+ default:
+ throw new TException("not support " + type + " in new read process");
+ }
+ }
+ return resp;
+ }
+
protected void checkFileLevelSet(List<Path> paths) throws PathErrorException
{
MManager.getInstance().checkFileLevel(paths);
}
@@ -700,13 +746,15 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
PhysicalPlan physicalPlan = queryStatus.get().get(statement);
processor.getExecutor().setFetchSize(fetchSize);
+ QueryDataSet queryDataSet;
QueryContext context = new
QueryContext(QueryResourceManager.getInstance().assignJobId());
initContextMap();
contextMapLocal.get().put(req.queryId, context);
- QueryDataSet queryDataSet =
processor.getExecutor().processQuery((QueryPlan) physicalPlan,
+ queryDataSet = processor.getExecutor().processQuery(physicalPlan,
context);
+
queryRet.get().put(statement, queryDataSet);
return queryDataSet;
}
@@ -898,5 +946,6 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
properties.getSupportedTimeAggregationOperations().add(IoTDBConstant.MIN_TIME);
return properties;
}
+
}
diff --git
a/iotdb/src/test/java/org/apache/iotdb/db/integration/IoTDBAuthorizationIT.java
b/iotdb/src/test/java/org/apache/iotdb/db/integration/IoTDBAuthorizationIT.java
index 4484bc7..d9385ff 100644
---
a/iotdb/src/test/java/org/apache/iotdb/db/integration/IoTDBAuthorizationIT.java
+++
b/iotdb/src/test/java/org/apache/iotdb/db/integration/IoTDBAuthorizationIT.java
@@ -23,6 +23,8 @@ import static org.junit.Assert.assertTrue;
import java.sql.Connection;
import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.iotdb.db.service.IoTDB;
@@ -654,37 +656,43 @@ public class IoTDBAuthorizationIT {
Statement adminStmt = adminCon.createStatement();
try {
- adminStmt.execute("LIST USER");
- } catch (SQLException e) {
- assertEquals("Users are : [ \n" + "root\n" + "]", e.getMessage());
- }
+ ResultSet resultSet = adminStmt.executeQuery("LIST USER");
+ String ans = String.format("0,root,\n");
+ validateResultSet(resultSet, ans);
- for (int i = 0; i < 10; i++) {
- adminStmt.execute("CREATE USER user" + i + " password" + i);
- }
- try {
- adminStmt.execute("LIST USER");
- } catch (SQLException e) {
- assertEquals(
- "Users are : [ \n" + "root\n" + "user0\n" + "user1\n" + "user2\n" +
"user3\n" + "user4\n"
- + "user5\n" + "user6\n" + "user7\n" + "user8\n" + "user9\n" +
"]", e.getMessage());
- }
-
- for (int i = 0; i < 10; i++) {
- if (i % 2 == 0) {
- adminStmt.execute("DROP USER user" + i);
+ for (int i = 0; i < 10; i++) {
+ adminStmt.execute("CREATE USER user" + i + " password" + i);
}
+ resultSet = adminStmt.executeQuery("LIST USER");
+ ans = "0,root,\n"
+ + "1,user0,\n"
+ + "2,user1,\n"
+ + "3,user2,\n"
+ + "4,user3,\n"
+ + "5,user4,\n"
+ + "6,user5,\n"
+ + "7,user6,\n"
+ + "8,user7,\n"
+ + "9,user8,\n"
+ + "10,user9,\n";
+ validateResultSet(resultSet, ans);
+
+ for (int i = 0; i < 10; i++) {
+ if (i % 2 == 0) {
+ adminStmt.execute("DROP USER user" + i);
+ }
+ }
+ resultSet = adminStmt.executeQuery("LIST USER");
+ ans = "0,root,\n"
+ + "1,user1,\n"
+ + "2,user3,\n"
+ + "3,user5,\n"
+ + "4,user7,\n"
+ + "5,user9,\n";
+ validateResultSet(resultSet, ans);
+ } finally {
+ adminCon.close();
}
- try {
- adminStmt.execute("LIST USER");
- } catch (SQLException e) {
- assertEquals(
- "Users are : [ \n" + "root\n" + "user1\n" + "user3\n" + "user5\n" +
"user7\n" + "user9\n"
- + "]",
- e.getMessage());
- }
-
- adminCon.close();
}
@Test
@@ -695,36 +703,43 @@ public class IoTDBAuthorizationIT {
Statement adminStmt = adminCon.createStatement();
try {
- adminStmt.execute("LIST ROLE");
- } catch (SQLException e) {
- assertEquals("Roles are : [ \n" + "]", e.getMessage());
- }
+ ResultSet resultSet = adminStmt.executeQuery("LIST ROLE");
+ String ans = "";
+ validateResultSet(resultSet, ans);
- for (int i = 0; i < 10; i++) {
- adminStmt.execute("CREATE ROLE role" + i);
- }
- try {
- adminStmt.execute("LIST ROLE");
- } catch (SQLException e) {
- assertEquals(
- "Roles are : [ \n" + "role0\n" + "role1\n" + "role2\n" + "role3\n" +
"role4\n" + "role5\n"
- + "role6\n" + "role7\n" + "role8\n" + "role9\n" + "]",
e.getMessage());
- }
+ for (int i = 0; i < 10; i++) {
+ adminStmt.execute("CREATE ROLE role" + i);
+ }
- for (int i = 0; i < 10; i++) {
- if (i % 2 == 0) {
- adminStmt.execute("DROP ROLE role" + i);
+ resultSet = adminStmt.executeQuery("LIST ROLE");
+ ans = "0,role0,\n"
+ + "1,role1,\n"
+ + "2,role2,\n"
+ + "3,role3,\n"
+ + "4,role4,\n"
+ + "5,role5,\n"
+ + "6,role6,\n"
+ + "7,role7,\n"
+ + "8,role8,\n"
+ + "9,role9,\n";
+ validateResultSet(resultSet, ans);
+
+ for (int i = 0; i < 10; i++) {
+ if (i % 2 == 0) {
+ adminStmt.execute("DROP ROLE role" + i);
+ }
}
- }
- try {
- adminStmt.execute("LIST ROLE");
- } catch (SQLException e) {
- assertEquals(
- "Roles are : [ \n" + "role1\n" + "role3\n" + "role5\n" + "role7\n" +
"role9\n" + "]",
- e.getMessage());
- }
+ resultSet = adminStmt.executeQuery("LIST ROLE");
+ ans = "0,role1,\n"
+ + "1,role3,\n"
+ + "2,role5,\n"
+ + "3,role7,\n"
+ + "4,role9,\n";
+ validateResultSet(resultSet, ans);
- adminCon.close();
+ } finally {
+ adminCon.close();
+ }
}
@Test
@@ -734,56 +749,44 @@ public class IoTDBAuthorizationIT {
.getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root",
"root");
Statement adminStmt = adminCon.createStatement();
- adminStmt.execute("CREATE USER user1 password1");
- adminStmt.execute("GRANT USER user1 PRIVILEGES 'READ_TIMESERIES' ON
root.a.b");
- adminStmt.execute("CREATE ROLE role1");
- adminStmt.execute(
- "GRANT ROLE role1 PRIVILEGES
'READ_TIMESERIES','INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.a.b.c");
- adminStmt.execute(
- "GRANT ROLE role1 PRIVILEGES
'READ_TIMESERIES','INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.d.b.c");
- adminStmt.execute("GRANT role1 TO user1");
-
- try {
- adminStmt.execute("LIST USER PRIVILEGES user1");
- } catch (SQLException e) {
- assertEquals(
- "Privileges are : [ \n" + "From itself : {\n" + "root.a.b :
READ_TIMESERIES\n" + "}\n"
- + "From role role1 : {\n"
- + "root.a.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES\n"
- + "root.d.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES\n" + "}\n" + "]",
- e.getMessage());
- }
-
- try {
- adminStmt.execute("LIST PRIVILEGES USER user1 ON root.a.b.c");
- } catch (SQLException e) {
- assertEquals(
- "Privileges are : [ \n" + "From itself : {\n" + "root.a.b :
READ_TIMESERIES\n" + "}\n"
- + "From role role1 : {\n"
- + "root.a.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES\n" + "}\n" + "]",
- e.getMessage());
- }
-
- adminStmt.execute("REVOKE role1 from user1");
- try {
- adminStmt.execute("LIST USER PRIVILEGES user1");
- } catch (SQLException e) {
- assertEquals(
- "Privileges are : [ \n" + "From itself : {\n" + "root.a.b :
READ_TIMESERIES\n" + "}\n"
- + "]",
- e.getMessage());
- }
-
try {
- adminStmt.execute("LIST PRIVILEGES USER user1 ON root.a.b.c");
- } catch (SQLException e) {
- assertEquals(
- "Privileges are : [ \n" + "From itself : {\n" + "root.a.b :
READ_TIMESERIES\n" + "}\n"
- + "]",
- e.getMessage());
+ adminStmt.execute("CREATE USER user1 password1");
+ adminStmt.execute("GRANT USER user1 PRIVILEGES 'READ_TIMESERIES' ON
root.a.b");
+ adminStmt.execute("CREATE ROLE role1");
+ adminStmt.execute(
+ "GRANT ROLE role1 PRIVILEGES
'READ_TIMESERIES','INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.a.b.c");
+ adminStmt.execute(
+ "GRANT ROLE role1 PRIVILEGES
'READ_TIMESERIES','INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.d.b.c");
+ adminStmt.execute("GRANT role1 TO user1");
+
+ ResultSet resultSet = adminStmt.executeQuery("LIST USER PRIVILEGES
user1");
+ String ans = "0,,root.a.b : READ_TIMESERIES"
+ + ",\n"
+ + "1,role1,root.a.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES"
+ + ",\n"
+ + "2,role1,root.d.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES"
+ + ",\n";
+ validateResultSet(resultSet, ans);
+
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES USER user1 ON
root.a.b.c");
+ ans = "0,,root.a.b : READ_TIMESERIES"
+ + ",\n"
+ + "1,role1,root.a.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES"
+ + ",\n";
+ validateResultSet(resultSet, ans);
+
+ adminStmt.execute("REVOKE role1 from user1");
+
+ resultSet = adminStmt.executeQuery("LIST USER PRIVILEGES user1");
+ ans = "0,,root.a.b : READ_TIMESERIES,\n";
+ validateResultSet(resultSet, ans);
+
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES USER user1 ON
root.a.b.c");
+ ans = "0,,root.a.b : READ_TIMESERIES,\n";
+ validateResultSet(resultSet, ans);
+ } finally {
+ adminCon.close();
}
-
- adminCon.close();
}
@Test
@@ -793,50 +796,36 @@ public class IoTDBAuthorizationIT {
.getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root",
"root");
Statement adminStmt = adminCon.createStatement();
- adminStmt.execute("CREATE ROLE role1");
- adminStmt.execute(
- "GRANT ROLE role1 PRIVILEGES
'READ_TIMESERIES','INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.a.b.c");
- adminStmt.execute(
- "GRANT ROLE role1 PRIVILEGES
'READ_TIMESERIES','INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.d.b.c");
-
try {
- adminStmt.execute("LIST ROLE PRIVILEGES role1");
- } catch (SQLException e) {
- assertEquals(
- "Privileges are : [ \n"
- + "root.a.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES\n"
- + "root.d.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES\n" + "]",
- e.getMessage());
- }
+ adminStmt.execute("CREATE ROLE role1");
+ adminStmt.execute(
+ "GRANT ROLE role1 PRIVILEGES
'READ_TIMESERIES','INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.a.b.c");
+ adminStmt.execute(
+ "GRANT ROLE role1 PRIVILEGES
'READ_TIMESERIES','INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.d.b.c");
- try {
- adminStmt.execute("LIST PRIVILEGES ROLE role1 ON root.a.b.c");
- } catch (SQLException e) {
- assertEquals("Privileges are : [ \n"
- + "root.a.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES\n"
- + "]", e.getMessage());
- }
+ ResultSet resultSet = adminStmt.executeQuery("LIST ROLE PRIVILEGES
role1");
+ String ans = "0,root.a.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES,\n"
+ + "1,root.d.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES,\n";
+ validateResultSet(resultSet, ans);
- adminStmt.execute(
- "REVOKE ROLE role1 PRIVILEGES 'INSERT_TIMESERIES','DELETE_TIMESERIES'
ON root.a.b.c");
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES ROLE role1 ON
root.a.b.c");
+ ans = "0,root.a.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES,\n";
+ validateResultSet(resultSet, ans);
- try {
- adminStmt.execute("LIST ROLE PRIVILEGES role1");
- } catch (SQLException e) {
- assertEquals(
- "Privileges are : [ \n" + "root.a.b.c : READ_TIMESERIES\n"
- + "root.d.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES\n" + "]",
- e.getMessage());
- }
+ adminStmt.execute(
+ "REVOKE ROLE role1 PRIVILEGES
'INSERT_TIMESERIES','DELETE_TIMESERIES' ON root.a.b.c");
- try {
- adminStmt.execute("LIST PRIVILEGES ROLE role1 ON root.a.b.c");
- } catch (SQLException e) {
- assertEquals("Privileges are : [ \n" + "root.a.b.c : READ_TIMESERIES\n"
+ "]",
- e.getMessage());
- }
+ resultSet = adminStmt.executeQuery("LIST ROLE PRIVILEGES role1");
+ ans = "0,root.a.b.c : READ_TIMESERIES,\n"
+ + "1,root.d.b.c : INSERT_TIMESERIES READ_TIMESERIES
DELETE_TIMESERIES,\n";
+ validateResultSet(resultSet, ans);
- adminCon.close();
+ resultSet = adminStmt.executeQuery("LIST PRIVILEGES ROLE role1 ON
root.a.b.c");
+ ans = "0,root.a.b.c : READ_TIMESERIES,\n";
+ validateResultSet(resultSet, ans);
+ } finally {
+ adminCon.close();
+ }
}
@Test
@@ -846,39 +835,40 @@ public class IoTDBAuthorizationIT {
.getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root",
"root");
Statement adminStmt = adminCon.createStatement();
- adminStmt.execute("CREATE USER chenduxiu orange");
+ try {
+ adminStmt.execute("CREATE USER chenduxiu orange");
- adminStmt.execute("CREATE ROLE xijing");
- adminStmt.execute("CREATE ROLE dalao");
- adminStmt.execute("CREATE ROLE shenshi");
- adminStmt.execute("CREATE ROLE zhazha");
- adminStmt.execute("CREATE ROLE hakase");
+ adminStmt.execute("CREATE ROLE xijing");
+ adminStmt.execute("CREATE ROLE dalao");
+ adminStmt.execute("CREATE ROLE shenshi");
+ adminStmt.execute("CREATE ROLE zhazha");
+ adminStmt.execute("CREATE ROLE hakase");
- adminStmt.execute("GRANT xijing TO chenduxiu");
- adminStmt.execute("GRANT dalao TO chenduxiu");
- adminStmt.execute("GRANT shenshi TO chenduxiu");
- adminStmt.execute("GRANT zhazha TO chenduxiu");
- adminStmt.execute("GRANT hakase TO chenduxiu");
+ adminStmt.execute("GRANT xijing TO chenduxiu");
+ adminStmt.execute("GRANT dalao TO chenduxiu");
+ adminStmt.execute("GRANT shenshi TO chenduxiu");
+ adminStmt.execute("GRANT zhazha TO chenduxiu");
+ adminStmt.execute("GRANT hakase TO chenduxiu");
- try {
- adminStmt.execute("LIST ALL ROLE OF USER chenduxiu");
- } catch (SQLException e) {
- assertEquals(
- "Roles are : [ \n" + "xijing\n" + "dalao\n" + "shenshi\n" +
"zhazha\n" + "hakase\n" + "]",
- e.getMessage());
- }
+ ResultSet resultSet = adminStmt.executeQuery("LIST ALL ROLE OF USER
chenduxiu");
+ String ans = "0,xijing,\n"
+ + "1,dalao,\n"
+ + "2,shenshi,\n"
+ + "3,zhazha,\n"
+ + "4,hakase,\n";
+ validateResultSet(resultSet, ans);
- adminStmt.execute("REVOKE dalao FROM chenduxiu");
- adminStmt.execute("REVOKE hakase FROM chenduxiu");
+ adminStmt.execute("REVOKE dalao FROM chenduxiu");
+ adminStmt.execute("REVOKE hakase FROM chenduxiu");
- try {
- adminStmt.execute("LIST ALL ROLE OF USER chenduxiu");
- } catch (SQLException e) {
- assertEquals("Roles are : [ \n" + "xijing\n" + "shenshi\n" + "zhazha\n"
+ "]",
- e.getMessage());
+ resultSet = adminStmt.executeQuery("LIST ALL ROLE OF USER chenduxiu");
+ ans = "0,xijing,\n"
+ + "1,shenshi,\n"
+ + "2,zhazha,\n";
+ validateResultSet(resultSet, ans);
+ } finally {
+ adminCon.close();
}
-
- adminCon.close();
}
@Test
@@ -888,46 +878,68 @@ public class IoTDBAuthorizationIT {
.getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root",
"root");
Statement adminStmt = adminCon.createStatement();
- adminStmt.execute("CREATE ROLE dalao");
- adminStmt.execute("CREATE ROLE zhazha");
-
- String[] members = {"HighFly", "SunComparison", "Persistence",
"GoodWoods", "HealthHonor",
- "GoldLuck",
- "DoubleLight", "Eastwards", "ScentEffusion", "Smart", "East",
"DailySecurity", "Moon",
- "RayBud",
- "RiverSky"};
-
- for (int i = 0; i < members.length - 1; i++) {
- adminStmt.execute("CREATE USER " + members[i] + " 666666");
- adminStmt.execute("GRANT dalao TO " + members[i]);
- }
- adminStmt.execute("CREATE USER RiverSky 2333333");
- adminStmt.execute("GRANT zhazha TO RiverSky");
-
try {
- adminStmt.execute("LIST ALL USER OF ROLE dalao");
- } catch (SQLException e) {
- assertEquals(
- "Users are : [ \n" + "DailySecurity\n" + "DoubleLight\n" + "East\n"
+ "Eastwards\n"
- + "GoldLuck\n" + "GoodWoods\n" + "HealthHonor\n" + "HighFly\n" +
"Moon\n"
- + "Persistence\n"
- + "RayBud\n" + "ScentEffusion\n" + "Smart\n" + "SunComparison\n"
+ "]",
- e.getMessage());
- }
+ adminStmt.execute("CREATE ROLE dalao");
+ adminStmt.execute("CREATE ROLE zhazha");
- try {
- adminStmt.execute("LIST ALL USER OF ROLE zhazha");
- } catch (SQLException e) {
- assertEquals("Users are : [ \n" + "RiverSky\n" + "]", e.getMessage());
+ String[] members = {"HighFly", "SunComparison", "Persistence",
"GoodWoods", "HealthHonor",
+ "GoldLuck",
+ "DoubleLight", "Eastwards", "ScentEffusion", "Smart", "East",
"DailySecurity", "Moon",
+ "RayBud",
+ "RiverSky"};
+
+ for (int i = 0; i < members.length - 1; i++) {
+ adminStmt.execute("CREATE USER " + members[i] + " 666666");
+ adminStmt.execute("GRANT dalao TO " + members[i]);
+ }
+ adminStmt.execute("CREATE USER RiverSky 2333333");
+ adminStmt.execute("GRANT zhazha TO RiverSky");
+
+ ResultSet resultSet = adminStmt.executeQuery("LIST ALL USER OF ROLE
dalao");
+ String ans = "0,DailySecurity,\n"
+ + "1,DoubleLight,\n"
+ + "2,East,\n"
+ + "3,Eastwards,\n"
+ + "4,GoldLuck,\n"
+ + "5,GoodWoods,\n"
+ + "6,HealthHonor,\n"
+ + "7,HighFly,\n"
+ + "8,Moon,\n"
+ + "9,Persistence,\n"
+ + "10,RayBud,\n"
+ + "11,ScentEffusion,\n"
+ + "12,Smart,\n"
+ + "13,SunComparison,\n";
+ validateResultSet(resultSet, ans);
+
+ resultSet = adminStmt.executeQuery("LIST ALL USER OF ROLE zhazha");
+ ans = "0,RiverSky,\n";
+ validateResultSet(resultSet, ans);
+
+ adminStmt.execute("REVOKE zhazha from RiverSky");
+ resultSet = adminStmt.executeQuery("LIST ALL USER OF ROLE zhazha");
+ ans = "";
+ validateResultSet(resultSet, ans);
+
+ } finally {
+ adminCon.close();
}
+ }
- adminStmt.execute("REVOKE zhazha from RiverSky");
+ private void validateResultSet(ResultSet set, String ans) throws
SQLException {
try {
- adminStmt.execute("LIST ALL USER OF ROLE zhazha");
- } catch (SQLException e) {
- assertEquals("Users are : [ \n" + "]", e.getMessage());
+ StringBuilder builder = new StringBuilder();
+ ResultSetMetaData metaData = set.getMetaData();
+ int colNum = metaData.getColumnCount();
+ while (set.next()) {
+ for (int i = 1; i <= colNum; i++) {
+ builder.append(set.getString(i)).append(",");
+ }
+ builder.append("\n");
+ }
+ assertEquals(ans, builder.toString());
+ } finally {
+ set.close();
}
-
- adminCon.close();
}
}
diff --git
a/iotdb/src/test/java/org/apache/iotdb/db/qp/utils/MemIntQpExecutor.java
b/iotdb/src/test/java/org/apache/iotdb/db/qp/utils/MemIntQpExecutor.java
index 71df644..7afced3 100644
--- a/iotdb/src/test/java/org/apache/iotdb/db/qp/utils/MemIntQpExecutor.java
+++ b/iotdb/src/test/java/org/apache/iotdb/db/qp/utils/MemIntQpExecutor.java
@@ -36,6 +36,7 @@ import org.apache.iotdb.db.qp.physical.PhysicalPlan;
import org.apache.iotdb.db.qp.physical.crud.DeletePlan;
import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
import org.apache.iotdb.db.qp.physical.crud.UpdatePlan;
+import org.apache.iotdb.db.qp.physical.sys.AuthorPlan;
import org.apache.iotdb.db.query.context.QueryContext;
import org.apache.iotdb.db.query.executor.EngineQueryRouter;
import org.apache.iotdb.db.query.fill.IFill;
@@ -206,6 +207,11 @@ public class MemIntQpExecutor extends QueryProcessExecutor
{
return 0;
}
+ @Override
+ protected QueryDataSet processAuthorQuery(AuthorPlan plan, QueryContext
context) {
+ return null;
+ }
+
private class TestSeries {
public TreeMap<Long, Integer> data = new TreeMap<>();
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBQueryResultSet.java
b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBQueryResultSet.java
index c9b2b2c..58ed56e 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBQueryResultSet.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBQueryResultSet.java
@@ -87,6 +87,7 @@ public class IoTDBQueryResultSet implements ResultSet {
// 0 means it is not constrained in sql, or the offset position has been
reached
private int rowsOffset = 0;
private long queryId;
+ private boolean ignoreTimeStamp = false;
/*
* Combine maxRows and the LIMIT constraints. maxRowsOrRowsLimit = 0 means
that neither maxRows
@@ -1245,4 +1246,12 @@ public class IoTDBQueryResultSet implements ResultSet {
}
return null;
}
+
+ public boolean isIgnoreTimeStamp() {
+ return ignoreTimeStamp;
+ }
+
+ public void setIgnoreTimeStamp(boolean ignoreTimeStamp) {
+ this.ignoreTimeStamp = ignoreTimeStamp;
+ }
}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
index fe56bbc..3c4e298 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
@@ -252,9 +252,12 @@ public class IoTDBStatement implements Statement {
operationHandle = execResp.getOperationHandle();
Utils.verifySuccess(execResp.getStatus());
if (execResp.getOperationHandle().hasResultSet) {
- resultSet = new IoTDBQueryResultSet(this, execResp.getColumns(),
client,
+ IoTDBQueryResultSet resSet = new IoTDBQueryResultSet(this,
+ execResp.getColumns(), client,
operationHandle, sql, execResp.getOperationType(),
getColumnsType(execResp.getColumns()), queryId.getAndIncrement());
+ resSet.setIgnoreTimeStamp(execResp.ignoreTimeStamp);
+ this.resultSet = resSet;
return true;
}
return false;
@@ -348,9 +351,11 @@ public class IoTDBStatement implements Statement {
TSExecuteStatementResp execResp = client.executeQueryStatement(execReq);
operationHandle = execResp.getOperationHandle();
Utils.verifySuccess(execResp.getStatus());
- resultSet = new IoTDBQueryResultSet(this, execResp.getColumns(), client,
+ IoTDBQueryResultSet resSet = new IoTDBQueryResultSet(this,
execResp.getColumns(), client,
operationHandle, sql, execResp.getOperationType(),
getColumnsType(execResp.getColumns()),
queryId.getAndIncrement());
+ resSet.setIgnoreTimeStamp(execResp.ignoreTimeStamp);
+ this.resultSet = resSet;
return resultSet;
}
diff --git a/service-rpc/src/main/thrift/rpc.thrift
b/service-rpc/src/main/thrift/rpc.thrift
index de18cfe..6e857e8 100644
--- a/service-rpc/src/main/thrift/rpc.thrift
+++ b/service-rpc/src/main/thrift/rpc.thrift
@@ -73,6 +73,7 @@ struct TSExecuteStatementResp {
// Column names in select statement of SQL
3: optional list<string> columns
4: optional string operationType
+ 5: optional bool ignoreTimeStamp
}
enum TSProtocolVersion {