dremio 实现类似官方create user sql 处理的思路
主要说明思路,后边有时间了会进行开发的说明
官方特性说明
sabot/kernel/src/main/java/com/dremio/exec/planner/sql/parser/SqlCreateUser.java
public class SqlCreateUser extends SqlCall implements SimpleDirectHandler.Creator {
private final SqlIdentifier username;
private final SqlNode password;
public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("CREATE", SqlKind.OTHER) {
@Override
public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNode
Preconditions.checkArgument(operands.length == 1, "SqlCreateUser.createCall() has to get at least 1 operands!");
if (operands.length == 2){
return new SqlCreateUser(
pos,
(SqlIdentifier) operands[0],
(SqlNode) operands[1]
);
}
return new SqlCreateUser(
pos,
(SqlIdentifier) operands[0]
);
}
};
public SqlCreateUser(SqlParserPos pos, SqlIdentifier username) {
super(pos);
this.username = username;
this.password = null;
}
public SqlCreateUser(SqlParserPos pos, SqlIdentifier username, SqlNode password) {
super(pos);
this.username = username;
this.password = password;
}
@Override
public SimpleDirectHandler toDirectHandler(QueryContext context) {
try {
// 此处是创建用户的核心
final Class<?> cl = Class.forName("com.dremio.exec.planner.sql.handlers.UserCreateHandler");
final Constructor<?> ctor = cl.getConstructor(QueryContext.class);
return (SimpleDirectHandler) ctor.newInstance(context);
} catch (ClassNotFoundException e) {
// Assume failure to find class means that we aren't running Enterprise Edition
throw UserException.unsupportedError(e)
.message("CREATE USER action is only supported in Enterprise Edition.")
.buildSilently();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw Throwables.propagate(e);
}
}
从上边可以看出官方的就是一个class 文件。。。。
handler 开发说明
- 方法签名
public abstract class SimpleDirectHandler implements SqlDirectHandler<SimpleCommandResult> {
@Override
public Class<SimpleCommandResult> getResultType() {
return SimpleCommandResult.class;
}
public interface Creator {
SimpleDirectHandler toDirectHandler(QueryContext context);
}
}
- 参考实现
sabot/kernel/src/main/java/com/dremio/exec/planner/sql/handlers/direct/UseSchemaHandler.java
dremio 内部的一个
public class UseSchemaHandler extends SimpleDirectHandler {
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(UseSchemaHandler.class);
private final UserSession session;
private final Catalog catalog;
public UseSchemaHandler(UserSession session, Catalog catalog) {
this.session = session;
this.catalog = catalog;
}
@Override
public List<SimpleCommandResult> toResult(String sql, SqlNode sqlNode) throws Exception {
final SqlUseSchema useSchema = SqlNodeUtil.unwrap(sqlNode, SqlUseSchema.class);
// first we try locally.
NamespaceKey orig = new NamespaceKey(useSchema.getSchema());
NamespaceKey defaultPath = catalog.resolveToDefault(orig);
NamespaceKey compoundPath = orig.size() == 1 && orig.getRoot().contains(".") ? new NamespaceKey(SqlUtils.parseSchemaPath(orig.getRoot())) : null;
if(defaultPath != null && catalog.containerExists(defaultPath)) {
session.setDefaultSchemaPath(defaultPath.getPathComponents());
} else if (catalog.containerExists(orig)) {
session.setDefaultSchemaPath(orig.getPathComponents());
} else if(compoundPath != null && catalog.containerExists(compoundPath)) {
// kept to support old compound use statements.
session.setDefaultSchemaPath(compoundPath.getPathComponents());
} else {
throw UserException.validationError().message("Schema [%s] is not valid with respect to either root schema or current default schema.", orig).build(logger);
}
return Collections.singletonList(SimpleCommandResult.successful("Default schema changed to [%s]", session.getDefaultSchemaPath()));
}
}
自己实现
思路就是参考以上的,只是用户管理我们需要集成官方的UserService ,参考地址,具体官方默认实现是SimpleUserService
services/users/src/main/java/com/dremio/service/users/UserService.java
services/users/src/main/java/com/dremio/service/users/SimpleUserService.java
说明
以上只是一个简单的思路,实现起来也不是很难,实际上dremio好多企业特性也是基于次方法解决的
从源码上我们也可以猜测官方企业版本主要也是多了一些jar吧,所以官方还是比较务实的,好多特性也是提供给了
社区的,只是部分企业特性独立开了jar了,后续我们的升级迭代也是比较方便的