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... operands) {
      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了,后续我们的升级迭代也是比较方法的

参考资料

https://github.com/dremio/dremio-oss

原文地址:https://www.cnblogs.com/rongfengliang/p/15484913.html