From 7ca5f44bf4125e01587fe9b404d8d7db3cb1ff12 Mon Sep 17 00:00:00 2001 From: dl239 Date: Fri, 2 Feb 2024 17:01:36 +0800 Subject: [PATCH] feat: support `create/alter/drop user` statement (#3678) * feat: add Encrypt * feat: add sql node * feat: auth in sdk * fix: fix test * fix: fix bugs * test: add case * feat: hide password in terminal * feat: update sdk * fix: fix test * feat: add user in spark * fix: fix python * docs: add doc * fix: skip python test * fix: fix comment * fix: revert HandleDelete * feat: add user to openmldb-import * fix: fix alter root password --------- Co-authored-by: 4paradigm <4paradigm@denglong.local> Co-authored-by: denglong --- cases/plan/alter.yaml | 44 +++ cases/plan/cmd.yaml | 17 + cases/plan/create.yaml | 38 +++ docs/en/deploy/install_deploy.md | 3 + docs/en/quickstart/cli.md | 4 + docs/en/quickstart/sdk/java_sdk.md | 7 + docs/en/quickstart/sdk/python_sdk.md | 4 + .../reference/sql/ddl/ALTER_USER_STATEMENT.md | 45 +++ .../sql/ddl/CREATE_USER_STATEMENT.md | 45 +++ .../reference/sql/ddl/DROP_USER_STATEMENT.md | 29 ++ .../sql/ddl/SHOW_CURRENT_USER_STATEMENT.md | 17 + docs/zh/deploy/install_deploy.md | 3 + .../openmldb_sql/ddl/ALTER_USER_STATEMENT.md | 45 +++ .../openmldb_sql/ddl/CREATE_USER_STATEMENT.md | 45 +++ .../openmldb_sql/ddl/DROP_USER_STATEMENT.md | 29 ++ .../ddl/SHOW_CURRENT_USER_STATEMENT.md | 17 + docs/zh/quickstart/cli.md | 2 + docs/zh/quickstart/sdk/java_sdk.md | 7 + docs/zh/quickstart/sdk/python_sdk.md | 6 +- hybridse/include/node/node_enum.h | 6 + hybridse/include/node/plan_node.h | 33 ++ hybridse/include/node/sql_node.h | 46 ++- hybridse/src/node/plan_node.cc | 26 ++ hybridse/src/node/sql_node.cc | 39 +++ hybridse/src/plan/planner.cc | 14 + hybridse/src/planv2/ast_node_converter.cc | 81 +++++ hybridse/src/planv2/ast_node_converter.h | 6 + .../src/planv2/ast_node_converter_test.cc | 2 + .../openmldb/importer/Importer.java | 8 + .../_4paradigm/openmldb/jdbc/SQLDriver.java | 12 + .../_4paradigm/openmldb/sdk/SdkOption.java | 6 + .../openmldb/spark/OpenmldbSource.java | 8 + .../openmldb/synctool/SyncToolConfig.java | 5 + .../openmldb/synctool/SyncToolImpl.java | 2 + .../taskmanager/config/TaskManagerConfig.java | 12 + .../openmldb/taskmanager/JobInfoManager.scala | 4 + python/openmldb_sdk/openmldb/sdk/sdk.py | 4 + .../openmldb_sdk/tests/sqlalchemy_api_test.py | 1 + .../diagnostic_tool/connector.py | 5 + src/CMakeLists.txt | 2 +- src/apiserver/api_server_impl.cc | 2 +- src/apiserver/api_server_impl.h | 2 +- src/apiserver/api_server_test.cc | 6 +- src/cmd/openmldb.cc | 23 +- src/cmd/single_tablet_test.cc | 21 +- src/cmd/sql_cmd.h | 81 ++++- src/cmd/sql_cmd_test.cc | 63 +++- src/codec/codec_test.cc | 8 + src/codec/encrypt.h | 52 +++ src/flags.cc | 2 + src/nameserver/name_server_impl.cc | 60 +--- src/nameserver/name_server_impl.h | 7 - src/nameserver/system_table.cc | 1 + src/nameserver/system_table.h | 15 + src/nameserver/system_table_test.cc | 5 +- src/sdk/db_sdk.cc | 36 +-- src/sdk/db_sdk.h | 23 +- src/sdk/db_sdk_test.cc | 14 +- src/sdk/mini_cluster_batch_bm.cc | 6 +- src/sdk/node_adapter.cc | 15 + src/sdk/node_adapter.h | 3 + src/sdk/options.h | 69 ++++ src/sdk/query_future_impl.h | 125 ++++++++ src/sdk/sql_cluster_router.cc | 303 ++++++++++-------- src/sdk/sql_cluster_router.h | 15 + src/sdk/sql_router.h | 29 +- src/sdk/sql_router_sdk.i | 2 + src/sdk/sql_standalone_sdk_test.cc | 3 +- src/tools/data_exporter.cc | 6 +- src/tools/tablemeta_reader.cc | 2 +- src/tools/tablemeta_reader.h | 12 +- 71 files changed, 1421 insertions(+), 319 deletions(-) create mode 100644 cases/plan/alter.yaml create mode 100644 docs/en/reference/sql/ddl/ALTER_USER_STATEMENT.md create mode 100644 docs/en/reference/sql/ddl/CREATE_USER_STATEMENT.md create mode 100644 docs/en/reference/sql/ddl/DROP_USER_STATEMENT.md create mode 100644 docs/en/reference/sql/ddl/SHOW_CURRENT_USER_STATEMENT.md create mode 100644 docs/zh/openmldb_sql/ddl/ALTER_USER_STATEMENT.md create mode 100644 docs/zh/openmldb_sql/ddl/CREATE_USER_STATEMENT.md create mode 100644 docs/zh/openmldb_sql/ddl/DROP_USER_STATEMENT.md create mode 100644 docs/zh/openmldb_sql/ddl/SHOW_CURRENT_USER_STATEMENT.md create mode 100644 src/codec/encrypt.h create mode 100644 src/sdk/options.h create mode 100644 src/sdk/query_future_impl.h diff --git a/cases/plan/alter.yaml b/cases/plan/alter.yaml new file mode 100644 index 00000000000..f954577506d --- /dev/null +++ b/cases/plan/alter.yaml @@ -0,0 +1,44 @@ +# Copyright 2021 4Paradigm +# +# Licensed 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. + +cases: + - id: alter_user + desc: alter user + sql: | + alter user root set options(password="123456"); + expect: + node_tree_str: | + +-node[kAlterUserStmt] + +-if_exists: false + +-user: root + +-options: + +-password: + +-expr[primary] + +-value: 123456 + +-type: string + + - id: alter_user_if_exist + desc: alter user + sql: | + alter user if exists root set options(password="123456"); + expect: + node_tree_str: | + +-node[kAlterUserStmt] + +-if_exists: true + +-user: root + +-options: + +-password: + +-expr[primary] + +-value: 123456 + +-type: string diff --git a/cases/plan/cmd.yaml b/cases/plan/cmd.yaml index 58eb872268f..bcffc51507c 100644 --- a/cases/plan/cmd.yaml +++ b/cases/plan/cmd.yaml @@ -189,6 +189,23 @@ cases: +-cmd_type: drop database +-if_exists: true +-args: [db1] + - id: drop_user + desc: DROP USER IF EXISTS + sql: DROP USER IF EXISTS user1 + expect: + node_tree_str: | + +-node[CMD] + +-cmd_type: drop user + +-if_exists: true + +-args: [user1] + - id: drop_user_1 + desc: DROP USER + sql: DROP USER user1 + expect: + node_tree_str: | + +-node[CMD] + +-cmd_type: drop user + +-args: [user1] - id: show_deployments desc: show deployments sql: SHOW DEPLOYMENTS; diff --git a/cases/plan/create.yaml b/cases/plan/create.yaml index 6210401ee9d..00c7e583406 100644 --- a/cases/plan/create.yaml +++ b/cases/plan/create.yaml @@ -1025,6 +1025,7 @@ cases: +-0: +-node[kCompressType] +-compress_type: snappy + - id: 35 desc: Create table with array & map type sql: | @@ -1067,3 +1068,40 @@ cases: | +-column_name: attrs | +-column_type: map NOT NULL +-table_option_list: [] + + - id: 36 + desc: create user + sql: | + create user root; + expect: + node_tree_str: | + +-node[kCreateUserStmt] + +-if_not_exists: false + +-user: root + +-options: + + - id: 37 + desc: create user if not exist + sql: | + create user if not exists root; + expect: + node_tree_str: | + +-node[kCreateUserStmt] + +-if_not_exists: true + +-user: root + +-options: + + - id: create_user_passwd + desc: create user with password + sql: | + create user root OPTIONS (password="123456"); + expect: + node_tree_str: | + +-node[kCreateUserStmt] + +-if_not_exists: false + +-user: root + +-options: + +-password: + +-expr[primary] + +-value: 123456 + +-type: string diff --git a/docs/en/deploy/install_deploy.md b/docs/en/deploy/install_deploy.md index 398905d8025..63255356496 100644 --- a/docs/en/deploy/install_deploy.md +++ b/docs/en/deploy/install_deploy.md @@ -560,6 +560,8 @@ cp conf/apiserver.flags.template conf/apiserver.flags * Modify the `endpoint`. The `endpoint` consists of a colon-separated deployment machine IP/domain name and port number (endpoints cannot use 0.0.0.0 and 127.0.0.1, and must be a public IP). * Modify `zk_cluster` to point to the address of the ZooKeeper service that has already been started (see [Deploy ZooKeeper - 4. ZooKeeper Service Address and Connection Test](zookeeper_addr)). If the ZooKeeper service is a cluster, separate the addresses with commas, for example, `172.27.128.33:7181,172.27.128.32:7181,172.27.128.31:7181`. * Modify `zk_root_path`. In this example, `/openmldb_cluster` is used. Note that **components under the same cluster share the same `zk_root_path`**. So in this deployment, the `zk_root_path` for each component's configuration is `/openmldb_cluster`. +* You can specify the username and password to connect to the server using `--user` and `--password`. +* By default, it connects to the server using the root user and an empty password. If you've changed the root password, you need to specify the new password using `--password`. ``` --endpoint=172.27.128.33:8080 @@ -636,6 +638,7 @@ cp conf/taskmanager.properties.template conf/taskmanager.properties * Modify `offline.data.prefix`: Set it to the storage path for offline tables. In Yarn mode, modify it to the corresponding HDFS path. * Modify `spark.master`: Set it according to the desired mode. Currently supports local and yarn modes for running offline tasks. * Modify `spark.home`: Set it to the Spark environment path. If not configured, the `SPARK_HOME` environment variable will be used. It should be the directory where the spark-optimized package was extracted in the first step, and it must be an absolute path. +* You can specify the username and password to connect to the server using `user` and `password`. If you've changed the root password, you'll need to specify the new password for the root user. ``` server.host=172.27.128.33 diff --git a/docs/en/quickstart/cli.md b/docs/en/quickstart/cli.md index 878ccf8fe60..4e4c195cc5b 100644 --- a/docs/en/quickstart/cli.md +++ b/docs/en/quickstart/cli.md @@ -34,6 +34,10 @@ Below we will describe some commonly used configuration options. - zk_session_timeout: The expected ZooKeeper session timeout is not necessarily the actual session timeout. If the value is set too large, ZooKeeper Server's tickTime or maxSessionTimeout also needs to be adjusted. +- user: Specify the username for login. If not specified, it defaults to 'root'. + +- password: Specify the password for login. If not specified, you'll be prompted to enter the password in interactive mode. + ## Non-Interactive Usage The interface that appears after starting the CLI is called an interactive interface. You need to enter SQL statements and press Enter to execute operations. Here are some non-interactive usage methods for batch processing or debugging. diff --git a/docs/en/quickstart/sdk/java_sdk.md b/docs/en/quickstart/sdk/java_sdk.md index 8934c55abf0..584488eff6c 100644 --- a/docs/en/quickstart/sdk/java_sdk.md +++ b/docs/en/quickstart/sdk/java_sdk.md @@ -53,6 +53,9 @@ Connection connection = DriverManager.getConnection("jdbc:openmldb:///?zk=localh // Set database in jdbcUrl Connection connection1 = DriverManager.getConnection("jdbc:openmldb:///test_db?zk=localhost:6181&zkPath=/openmldb"); + +// Set user and password in jdbcUrl +Connection connection = DriverManager.getConnection("jdbc:openmldb:///?zk=localhost:6181&zkPath=/openmldb&user=root&password=123456"); ``` The database specified in the Connection address must exist when creating the connection. @@ -113,6 +116,10 @@ option.setZkCluster("127.0.0.1:2181"); option.setZkPath("/openmldb"); option.setSessionTimeout(10000); option.setRequestTimeout(60000); +// If not specified, it defaults to 'root' +option.setUser("root"); +// If not specified, it defaults to being empty +option.setPassword("123456"); ``` Then, use SdkOption to create the Executor. diff --git a/docs/en/quickstart/sdk/python_sdk.md b/docs/en/quickstart/sdk/python_sdk.md index 6ae0e4705af..625cadc015e 100644 --- a/docs/en/quickstart/sdk/python_sdk.md +++ b/docs/en/quickstart/sdk/python_sdk.md @@ -21,6 +21,8 @@ Parameter `db_name` name must exist, and the database must be created before the ```python import openmldb.dbapi db = openmldb.dbapi.connect(zk="$zkcluster", zkPath="$zkpath") +# You can set the username and password as follows. If no username is set, it defaults to 'root', and the password defaults to being empty +# db = openmldb.dbapi.connect(zk="$zkcluster", zkPath="$zkpath", user="$user", password="$password") cursor = db.cursor() ``` @@ -124,6 +126,8 @@ Parameter `db_name` must exist, and the database must be created before the conn ```python import sqlalchemy as db engine = db.create_engine('openmldb:///?zk=127.0.0.1:2181&zkPath=/openmldb') +# You can set the username and password as follows. +# create_engine('openmldb:///db_name?zk=zkcluster&zkPath=zkpath&user=root&password=123456') connection = engine.connect() ``` diff --git a/docs/en/reference/sql/ddl/ALTER_USER_STATEMENT.md b/docs/en/reference/sql/ddl/ALTER_USER_STATEMENT.md new file mode 100644 index 00000000000..c1b764cc670 --- /dev/null +++ b/docs/en/reference/sql/ddl/ALTER_USER_STATEMENT.md @@ -0,0 +1,45 @@ +# ALTER USER + +The `ALTER USER` statement is used to modify a user's password. + +## Syntax +```sql +AlterUserstmt ::= + 'ALTER' 'USER' [IF EXISTS] UserName SET OptOptionsList + +UserName ::= Identifier + +OptOptionsList ::= + "OPTIONS" OptionList + +OptionList ::= + OptionsListPrefix ")" + +OptionsListPrefix ::= + "(" OptionEntry + | OptionsListPrefix "," OptionEntry + +OptionEntry ::= + Identifier "=" Identifier +``` + +## **Examples** +```sql +ALTER USER user1; +-- SUCCEED +ALTER USER IF EXISTS user2 SET OPTIONS(password='123456'); +-- SUCCEED +ALTER USER user3 SET OPTIONS (password='123456'); +-- SUCCEED +``` + +```{note} +1. If the password is not specified in the OPTIONS, the password will not be changed +2. You can only specify the password in the OPTIONS +``` + +## Related SQL + +[CREATE USER](./CREATE_USER_STATEMENT.md) +[DROP USER](./DROP_USER_STATEMENT.md) +[SHOW CURRENT_USER](./SHOW_CURRENT_USER_STATEMENT.md) \ No newline at end of file diff --git a/docs/en/reference/sql/ddl/CREATE_USER_STATEMENT.md b/docs/en/reference/sql/ddl/CREATE_USER_STATEMENT.md new file mode 100644 index 00000000000..fa169f8fd55 --- /dev/null +++ b/docs/en/reference/sql/ddl/CREATE_USER_STATEMENT.md @@ -0,0 +1,45 @@ +# CREATE USER + +The `CREATE USER` statement is used to create a user + +## Syntax +```sql +CreateUserstmt ::= + 'CREATE' 'USER' [IF NOT EXISTS] UserName OptOptionsList + +UserName ::= Identifier + +OptOptionsList ::= + "OPTIONS" OptionList + +OptionList ::= + OptionsListPrefix ")" + +OptionsListPrefix ::= + "(" OptionEntry + | OptionsListPrefix "," OptionEntry + +OptionEntry ::= + Identifier "=" Identifier +``` + +## **Examples** +```sql +CREATE USER user1; +-- SUCCEED +CREATE USER IF NOT EXISTS user2; +-- SUCCEED +CREATE USER user3 OPTIONS (password='123456'); +-- SUCCEED +``` + +```{note} +1. Only the password can be specified in the OPTIONS +2. The password will be empty if not specified explicitly +``` + +## Related SQL + +[DROP USER](./DROP_USER_STATEMENT.md) +[ALTER USER](./ALTER_USER_STATEMENT.md) +[SHOW CURRENT_USER](./SHOW_CURRENT_USER_STATEMENT.md) \ No newline at end of file diff --git a/docs/en/reference/sql/ddl/DROP_USER_STATEMENT.md b/docs/en/reference/sql/ddl/DROP_USER_STATEMENT.md new file mode 100644 index 00000000000..2d4d0ce2db7 --- /dev/null +++ b/docs/en/reference/sql/ddl/DROP_USER_STATEMENT.md @@ -0,0 +1,29 @@ +# DROP USER + +The `DROP USER` statement is used to drop a user. + +## Syntax +```sql +DropUserstmt ::= + 'DROP' 'USER' [IF EXISTS] UserName + +UserName ::= Identifier +``` + +## **Examples** +```sql +DROP USER user1; +-- SUCCEED +DROP USER IF EXISTS user2; +-- SUCCEED +``` + +```{note} +1. The user `root` cannot be deleted +``` + +## Related SQL + +[CREATE USER](./CREATE_USER_STATEMENT.md) +[ALTER USER](./ALTER_USER_STATEMENT.md) +[SHOW CURRENT_USER](./SHOW_CURRENT_USER_STATEMENT.md) \ No newline at end of file diff --git a/docs/en/reference/sql/ddl/SHOW_CURRENT_USER_STATEMENT.md b/docs/en/reference/sql/ddl/SHOW_CURRENT_USER_STATEMENT.md new file mode 100644 index 00000000000..20de9171fa8 --- /dev/null +++ b/docs/en/reference/sql/ddl/SHOW_CURRENT_USER_STATEMENT.md @@ -0,0 +1,17 @@ +# SHOW CURRENT_USER + +The `SHOW CURRENT_USER` statement is used to display the current user. + +## **Examples** +```sql +SHOW CURRENT_USER; + ------ + User + ------ + root + ------ +``` + +[CREATE USER](./CREATE_USER_STATEMENT.md) +[ALTER USER](./ALTER_USER_STATEMENT.md) +[DROP USER](./DROP_USER_STATEMENT.md) \ No newline at end of file diff --git a/docs/zh/deploy/install_deploy.md b/docs/zh/deploy/install_deploy.md index cf719c24ef6..0f32ba24b00 100644 --- a/docs/zh/deploy/install_deploy.md +++ b/docs/zh/deploy/install_deploy.md @@ -594,6 +594,8 @@ cp conf/apiserver.flags.template conf/apiserver.flags **注意:** * 如果http请求并发度较大,可自行调大APIServer的线程数,`--thread_pool_size`,默认为16,重启生效。 +* 可以通过`--user`和`--password`指定连接服务端的用户名和密码 +* 默认会用root用户空密码去连接服务端,如果修改了root密码,需要用`--password`指定新密码 **3. 启动服务** @@ -655,6 +657,7 @@ cp conf/taskmanager.properties.template conf/taskmanager.properties * 修改`offline.data.prefix`为离线表存储路径,如果使用Yarn模式需要修改为对应HDFS路径。 * 修改`spark.master`为离线任务运行模式,目前支持local和yarn模式。 * 修改`spark.home`为Spark环境路径,如果不配置或配置为空则使用`SPARK_HOME`环境变量的配置。也可在配置文件中设置,路径为绝对路径。 +* 可以通过`user`和`password`指定连接server端用户名和密码。默认会用root用户空密码去连接服务端,如果修改了root密码,需要指定新密码. ``` server.host=172.27.128.33 diff --git a/docs/zh/openmldb_sql/ddl/ALTER_USER_STATEMENT.md b/docs/zh/openmldb_sql/ddl/ALTER_USER_STATEMENT.md new file mode 100644 index 00000000000..4b893a32472 --- /dev/null +++ b/docs/zh/openmldb_sql/ddl/ALTER_USER_STATEMENT.md @@ -0,0 +1,45 @@ +# ALTER USER + +`ALTER USER` 语句可用来修改用户密码。 + +## 语法 +```sql +AlterUserstmt ::= + 'ALTER' 'USER' [IF EXISTS] UserName SET OptOptionsList + +UserName ::= Identifier + +OptOptionsList ::= + "OPTIONS" OptionList + +OptionList ::= + OptionsListPrefix ")" + +OptionsListPrefix ::= + "(" OptionEntry + | OptionsListPrefix "," OptionEntry + +OptionEntry ::= + Identifier "=" Identifier +``` + +## **示例** +```sql +ALTER USER user1; +-- SUCCEED +ALTER USER IF EXISTS user2 SET OPTIONS(password='123456'); +-- SUCCEED +ALTER USER user3 SET OPTIONS (password='123456'); +-- SUCCEED +``` + +```{note} +1. 如果不指定OPTIONS密码不会修改 +2. OPTIONS中只能指定password +``` + +## 相关SQL + +[CREATE USER](./CREATE_USER_STATEMENT.md) +[DROP USER](./DROP_USER_STATEMENT.md) +[SHOW CURRENT_USER](./SHOW_CURRENT_USER_STATEMENT.md) \ No newline at end of file diff --git a/docs/zh/openmldb_sql/ddl/CREATE_USER_STATEMENT.md b/docs/zh/openmldb_sql/ddl/CREATE_USER_STATEMENT.md new file mode 100644 index 00000000000..0d08f9ab1e7 --- /dev/null +++ b/docs/zh/openmldb_sql/ddl/CREATE_USER_STATEMENT.md @@ -0,0 +1,45 @@ +# CREATE USER + +`CREATE USER` 语句用来创建用户。 + +## 语法 +```sql +CreateUserstmt ::= + 'CREATE' 'USER' [IF NOT EXISTS] UserName OptOptionsList + +UserName ::= Identifier + +OptOptionsList ::= + "OPTIONS" OptionList + +OptionList ::= + OptionsListPrefix ")" + +OptionsListPrefix ::= + "(" OptionEntry + | OptionsListPrefix "," OptionEntry + +OptionEntry ::= + Identifier "=" Identifier +``` + +## **示例** +```sql +CREATE USER user1; +-- SUCCEED +CREATE USER IF NOT EXISTS user2; +-- SUCCEED +CREATE USER user3 OPTIONS (password='123456'); +-- SUCCEED +``` + +```{note} +1. OPTIONS中只能指定password +2. 如果不指定password, 那么密码为空 +``` + +## 相关SQL + +[DROP USER](./DROP_USER_STATEMENT.md) +[ALTER USER](./ALTER_USER_STATEMENT.md) +[SHOW CURRENT_USER](./SHOW_CURRENT_USER_STATEMENT.md) \ No newline at end of file diff --git a/docs/zh/openmldb_sql/ddl/DROP_USER_STATEMENT.md b/docs/zh/openmldb_sql/ddl/DROP_USER_STATEMENT.md new file mode 100644 index 00000000000..5c4775adb81 --- /dev/null +++ b/docs/zh/openmldb_sql/ddl/DROP_USER_STATEMENT.md @@ -0,0 +1,29 @@ +# DROP USER + +`DROP USER` 语句用来删除用户。 + +## 语法 +```sql +DropUserstmt ::= + 'DROP' 'USER' [IF EXISTS] UserName + +UserName ::= Identifier +``` + +## **示例** +```sql +DROP USER user1; +-- SUCCEED +DROP USER IF EXISTS user2; +-- SUCCEED +``` + +```{note} +1. 不能删除root用户 +``` + +## 相关SQL + +[CREATE USER](./CREATE_USER_STATEMENT.md) +[ALTER USER](./ALTER_USER_STATEMENT.md) +[SHOW CURRENT_USER](./SHOW_CURRENT_USER_STATEMENT.md) \ No newline at end of file diff --git a/docs/zh/openmldb_sql/ddl/SHOW_CURRENT_USER_STATEMENT.md b/docs/zh/openmldb_sql/ddl/SHOW_CURRENT_USER_STATEMENT.md new file mode 100644 index 00000000000..0c6548acb9e --- /dev/null +++ b/docs/zh/openmldb_sql/ddl/SHOW_CURRENT_USER_STATEMENT.md @@ -0,0 +1,17 @@ +# SHOW CURRENT_USER + +`SHOW CURRENT_USER` 显示当前用户 + +## **示例** +```sql +SHOW CURRENT_USER; + ------ + User + ------ + root + ------ +``` + +[CREATE USER](./CREATE_USER_STATEMENT.md) +[ALTER USER](./ALTER_USER_STATEMENT.md) +[DROP USER](./DROP_USER_STATEMENT.md) \ No newline at end of file diff --git a/docs/zh/quickstart/cli.md b/docs/zh/quickstart/cli.md index fb644b32a6c..97acd3209ac 100644 --- a/docs/zh/quickstart/cli.md +++ b/docs/zh/quickstart/cli.md @@ -29,6 +29,8 @@ bin/openmldb --zk_cluster=127.0.0.1:2181 --zk_root_path=/openmldb --role=sql_cli - sync_job_timeout: CLI执行离线同步任务的默认同步等待时间0.5h,如果离线同步任务需要等待更长的时间,可改变这一配置,但注意还需要改变集群中TaskManager的配置,详情见[离线命令配置详情](../openmldb_sql/ddl/SET_STATEMENT.md#离线命令配置详情)。 - zk_log_level & zk_log_file: CLI连接ZooKeeper产生的日志默认是不打印的,如果需要展示日志,可以调整`zk_log_level`。打印的日志默认是打印到stderr,且由于ZooKeeper连接是后台线程,可能出现CLI交互界面突然出现ZooKeeper相关的日志,不影响CLI的使用但影响界面展示,可以使用`zk_log_file`将ZooKeeper相关的日志输出到文件中。 - zk_session_timeout: 期望的ZooKeeper session超时时间,并不一定是真实的session超时时间。如果调整过大,也需要调整ZooKeeper Server的tickTime或maxSessionTimeout。 +- user: 指定登录用的用户名。如果不指定默认为root。 +- password: 指定登录用的密码。如果不指定,需要再交互模式下输入密码。 ## 非交互式使用方法 diff --git a/docs/zh/quickstart/sdk/java_sdk.md b/docs/zh/quickstart/sdk/java_sdk.md index 5503cc97fd1..e2c11b5f5b8 100644 --- a/docs/zh/quickstart/sdk/java_sdk.md +++ b/docs/zh/quickstart/sdk/java_sdk.md @@ -55,6 +55,9 @@ Connection connection = DriverManager.getConnection("jdbc:openmldb:///?zk=localh // Set database in jdbcUrl Connection connection1 = DriverManager.getConnection("jdbc:openmldb:///test_db?zk=localhost:6181&zkPath=/openmldb"); + +// Set user and password in jdbcUrl +Connection connection = DriverManager.getConnection("jdbc:openmldb:///?zk=localhost:6181&zkPath=/openmldb&user=root&password=123456"); ``` Connection 地址指定的 db 在创建连接时必须存在。 @@ -116,6 +119,10 @@ option.setZkCluster("127.0.0.1:2181"); option.setZkPath("/openmldb"); option.setSessionTimeout(10000); option.setRequestTimeout(60000); +// 如果不指定用户名,默认是root +option.setUser("root"); +// 如果不指定密码,默认是空 +option.setPassword("123456"); ``` 然后使用 SdkOption 创建 Executor。 diff --git a/docs/zh/quickstart/sdk/python_sdk.md b/docs/zh/quickstart/sdk/python_sdk.md index 69544b81db7..38bf23736e9 100644 --- a/docs/zh/quickstart/sdk/python_sdk.md +++ b/docs/zh/quickstart/sdk/python_sdk.md @@ -21,6 +21,8 @@ pip install openmldb ```python import openmldb.dbapi db = openmldb.dbapi.connect(zk="$zkcluster", zkPath="$zkpath") +# 可以设置用户名和密码。如果不设置用户名,默认为root。密码默认为空 +# db = openmldb.dbapi.connect(zk="$zkcluster", zkPath="$zkpath", user="$user", password="$password") cursor = db.cursor() ``` @@ -116,8 +118,10 @@ cursor.close() ### 创建连接 -``` +```python create_engine('openmldb:///db_name?zk=zkcluster&zkPath=zkpath') +# 可以通过如下方式指定用户名密码 +# create_engine('openmldb:///db_name?zk=zkcluster&zkPath=zkpath&user=root&password=123456') ``` 参数 db_name 必须存在,需在创建连接前创建数据库。或者先创建无数据库的连接,再通过 `execute("USE ")` 命令设置使用数据库 `db`。 diff --git a/hybridse/include/node/node_enum.h b/hybridse/include/node/node_enum.h index 38d8336258f..ad8f03bf422 100644 --- a/hybridse/include/node/node_enum.h +++ b/hybridse/include/node/node_enum.h @@ -96,6 +96,8 @@ enum SqlNodeType { kShowStmt, kCompressType, kColumnSchema, + kCreateUserStmt, + kAlterUserStmt, kSqlNodeTypeLast, // debug type }; @@ -300,6 +302,8 @@ enum CmdType { kCmdShowJobLog, kCmdShowCreateTable, kCmdTruncate, + kCmdDropUser, + kCmdShowUser, kCmdFake, // not a real cmd, for testing purpose only kLastCmd = kCmdFake, }; @@ -338,6 +342,8 @@ enum PlanType { kPlanTypeWithClauseEntry, kPlanTypeAlterTable, kPlanTypeShow, + kPlanTypeCreateUser, + kPlanTypeAlterUser, kUnknowPlan = -1, }; diff --git a/hybridse/include/node/plan_node.h b/hybridse/include/node/plan_node.h index 3085b27c699..c4fcf3beadb 100644 --- a/hybridse/include/node/plan_node.h +++ b/hybridse/include/node/plan_node.h @@ -722,6 +722,39 @@ class CreateIndexPlanNode : public LeafPlanNode { void Print(std::ostream &output, const std::string &orgTab) const; const CreateIndexNode *create_index_node_; }; + +class CreateUserPlanNode : public LeafPlanNode { + public: + explicit CreateUserPlanNode(const std::string& name, bool if_not_exists, std::shared_ptr options) + : LeafPlanNode(kPlanTypeCreateUser), name_(name), if_not_exists_(if_not_exists), options_(options) {} + ~CreateUserPlanNode() = default; + void Print(std::ostream &output, const std::string &orgTab) const; + const std::string& Name() const { return name_; } + bool IfNotExists() const { return if_not_exists_; } + const std::shared_ptr Options() const { return options_; } + + private: + const std::string name_; + const bool if_not_exists_ = false; + const std::shared_ptr options_; +}; + +class AlterUserPlanNode : public LeafPlanNode { + public: + explicit AlterUserPlanNode(const std::string& name, bool if_exists, std::shared_ptr options) + : LeafPlanNode(kPlanTypeAlterUser), name_(name), if_exists_(if_exists), options_(options) {} + ~AlterUserPlanNode() = default; + void Print(std::ostream &output, const std::string &orgTab) const; + const std::string& Name() const { return name_; } + bool IfExists() const { return if_exists_; } + const std::shared_ptr Options() const { return options_; } + + private: + const std::string name_; + const bool if_exists_ = false; + const std::shared_ptr options_; +}; + class CreateProcedurePlanNode : public MultiChildPlanNode { public: CreateProcedurePlanNode(const std::string &sp_name, const NodePointVector &input_parameter_list, diff --git a/hybridse/include/node/sql_node.h b/hybridse/include/node/sql_node.h index 14e139bdd3f..d127fccc71a 100644 --- a/hybridse/include/node/sql_node.h +++ b/hybridse/include/node/sql_node.h @@ -371,12 +371,14 @@ typedef std::vector NodePointVector; // supported as: // - ADD PATH // - DROP PATH +// - SET OPTIONS // all else is unsupported class AlterActionBase : public base::FeBaseObject { public: enum class ActionKind { ADD_PATH = 0, - DROP_PATH + DROP_PATH, + SET_OPTIONS }; explicit AlterActionBase(ActionKind k) : kind_(k) {} @@ -406,6 +408,16 @@ class DropPathAction : public AlterActionBase { std::string target_; }; +class SetOptionsAction : public AlterActionBase { + public: + explicit SetOptionsAction(std::shared_ptr options) + : AlterActionBase(ActionKind::SET_OPTIONS), options_(options) {} + std::string DebugString() const override; + const std::shared_ptr Options() const { return options_; } + + private: + const std::shared_ptr options_; +}; class AlterTableStmt: public SqlNode { public: @@ -2341,6 +2353,38 @@ class CreateIndexNode : public SqlNode { node::ColumnIndexNode *index_; }; +class CreateUserNode : public SqlNode { + public: + explicit CreateUserNode(const std::string &name, + bool if_not_exists, const std::shared_ptr& options) + : SqlNode(kCreateUserStmt, 0, 0), + name_(name), if_not_exists_(if_not_exists), options_(options) {} + void Print(std::ostream &output, const std::string &org_tab) const; + const std::string& Name() const { return name_; } + bool IfNotExists() const { return if_not_exists_; } + const std::shared_ptr Options() const { return options_; } + + private: + const std::string name_; + bool if_not_exists_; + const std::shared_ptr options_; +}; + +class AlterUserNode : public SqlNode { + public: + explicit AlterUserNode(const std::string &name, bool if_exists, const std::shared_ptr& options) + : SqlNode(kAlterUserStmt, 0, 0), name_(name), if_exists_(if_exists), options_(options) {} + void Print(std::ostream &output, const std::string &org_tab) const; + const std::string& Name() const { return name_; } + bool IfExists() const { return if_exists_; } + const std::shared_ptr Options() const { return options_; } + + private: + const std::string name_; + bool if_exists_ = false; + const std::shared_ptr options_; +}; + class ExplainNode : public SqlNode { public: explicit ExplainNode(const QueryNode *query, node::ExplainType explain_type) diff --git a/hybridse/src/node/plan_node.cc b/hybridse/src/node/plan_node.cc index f601696e605..c829ab880e5 100644 --- a/hybridse/src/node/plan_node.cc +++ b/hybridse/src/node/plan_node.cc @@ -224,6 +224,10 @@ std::string NameOfPlanNodeType(const PlanType &type) { return "kPlanTypeShow"; case kPlanTypeAlterTable: return "kPlanTypeAlterTable"; + case kPlanTypeCreateUser: + return "kPlanTypeCreateUser"; + case kPlanTypeAlterUser: + return "kPlanTypeAlterUser"; case kUnknowPlan: return std::string("kUnknow"); } @@ -708,6 +712,28 @@ void DeployPlanNode::Print(std::ostream &output, const std::string &tab) const { PrintSqlNode(output, new_tab, Stmt(), "stmt", true); } +void CreateUserPlanNode::Print(std::ostream &output, const std::string &tab) const { + PlanNode::Print(output, tab); + output << "\n"; + std::string new_tab = tab + INDENT; + PrintValue(output, new_tab, IfNotExists() ? "true": "false", "if_not_exists", false); + output << "\n"; + PrintValue(output, new_tab, Name(), "name", false); + output << "\n"; + PrintValue(output, new_tab, Options().get(), "options", true); +} + +void AlterUserPlanNode::Print(std::ostream &output, const std::string &tab) const { + PlanNode::Print(output, tab); + output << "\n"; + std::string new_tab = tab + INDENT; + PrintValue(output, new_tab, IfExists() ? "true": "false", "if_exists", false); + output << "\n"; + PrintValue(output, new_tab, Name(), "name", false); + output << "\n"; + PrintValue(output, new_tab, Options().get(), "options", true); +} + void LoadDataPlanNode::Print(std::ostream &output, const std::string &org_tab) const { PlanNode::Print(output, org_tab); diff --git a/hybridse/src/node/sql_node.cc b/hybridse/src/node/sql_node.cc index f5543d6e8b8..9e83b9efc16 100644 --- a/hybridse/src/node/sql_node.cc +++ b/hybridse/src/node/sql_node.cc @@ -52,6 +52,7 @@ static absl::flat_hash_map CreateCmdTypeNamesMap() { {CmdType::kCmdShowTables, "show tables"}, {CmdType::kCmdUseDatabase, "use database"}, {CmdType::kCmdDropDatabase, "drop database"}, + {CmdType::kCmdDropUser, "drop user"}, {CmdType::kCmdCreateDatabase, "create database"}, {CmdType::kCmdDescTable, "desc table"}, {CmdType::kCmdDropTable, "drop table"}, @@ -1181,6 +1182,8 @@ static absl::flat_hash_map CreateSqlNodeTypeToNa {kSetStmt, "kSetStmt"}, {kDeleteStmt, "kDeleteStmt"}, {kCreateFunctionStmt, "kCreateFunctionStmt"}, + {kCreateUserStmt, "kCreateUserStmt"}, + {kAlterUserStmt, "kAlterUserStmt"}, {kDynamicUdfFnDef, "kDynamicUdfFnDef"}, {kDynamicUdafFnDef, "kDynamicUdafFnDef"}, {kWithClauseEntry, "kWithClauseEntry"}, @@ -1644,6 +1647,29 @@ void CreateIndexNode::Print(std::ostream &output, const std::string &org_tab) co output << "\n"; PrintSqlNode(output, tab, index_, "index", true); } + +void CreateUserNode::Print(std::ostream &output, const std::string &org_tab) const { + SqlNode::Print(output, org_tab); + const std::string tab = org_tab + INDENT + SPACE_ED; + output << "\n"; + PrintValue(output, tab, if_not_exists_ ? "true" : "false", "if_not_exists", false); + output << "\n"; + PrintValue(output, tab, name_, "user", false); + output << "\n"; + PrintValue(output, tab, Options().get(), "options", true); +} + +void AlterUserNode::Print(std::ostream &output, const std::string &org_tab) const { + SqlNode::Print(output, org_tab); + const std::string tab = org_tab + INDENT + SPACE_ED; + output << "\n"; + PrintValue(output, tab, if_exists_ ? "true" : "false", "if_exists", false); + output << "\n"; + PrintValue(output, tab, name_, "user", false); + output << "\n"; + PrintValue(output, tab, Options().get(), "options", true); +} + void ExplainNode::Print(std::ostream &output, const std::string &org_tab) const { SqlNode::Print(output, org_tab); const std::string tab = org_tab + INDENT + SPACE_ED; @@ -2727,6 +2753,19 @@ std::string DropPathAction::DebugString() const { return absl::Substitute("DropPathAction ($0)", target_); } +std::string SetOptionsAction::DebugString() const { + std::string output; + for (const auto& kv : *options_) { + if (!output.empty()) { + absl::StrAppend(&output, ", "); + } + absl::StrAppend(&output, kv.first); + absl::StrAppend(&output, "="); + absl::StrAppend(&output, kv.second->GetAsString()); + } + return absl::Substitute("SetOptionsAction ($0)", output); +} + bool SetOperationNode::Equals(const SqlNode *node) const { auto *rhs = dynamic_cast(node); return this->QueryNode::Equals(node) && this->op_type() == rhs->op_type() && this->distinct() == rhs->distinct() && diff --git a/hybridse/src/plan/planner.cc b/hybridse/src/plan/planner.cc index e05e639efb1..5553f7c7c99 100644 --- a/hybridse/src/plan/planner.cc +++ b/hybridse/src/plan/planner.cc @@ -759,6 +759,20 @@ base::Status SimplePlanner::CreatePlanTree(const NodePointVector &parser_trees, plan_trees.push_back(deploy_plan_node); break; } + case ::hybridse::node::kCreateUserStmt: { + auto node = dynamic_cast(parser_tree); + auto create_user_plan_node = node_manager_->MakeNode(node->Name(), + node->IfNotExists(), node->Options()); + plan_trees.push_back(create_user_plan_node); + break; + } + case ::hybridse::node::kAlterUserStmt: { + auto node = dynamic_cast(parser_tree); + auto alter_user_plan_node = node_manager_->MakeNode(node->Name(), + node->IfExists(), node->Options()); + plan_trees.push_back(alter_user_plan_node); + break; + } case ::hybridse::node::kSetStmt: { CHECK_TRUE(is_batch_mode_, common::kPlanError, "Non-support SET Op in online serving"); diff --git a/hybridse/src/planv2/ast_node_converter.cc b/hybridse/src/planv2/ast_node_converter.cc index 2c6225be9a8..0261c673423 100644 --- a/hybridse/src/planv2/ast_node_converter.cc +++ b/hybridse/src/planv2/ast_node_converter.cc @@ -666,6 +666,17 @@ base::Status ConvertStatement(const zetasql::ASTStatement* statement, node::Node dynamic_cast(node_manager->MakeCmdNode(node::CmdType::kCmdDescTable, names)); break; } + case zetasql::AST_DROP_USER_STATEMENT: { + auto drop_user_statement = statement->GetAsOrNull(); + CHECK_TRUE(drop_user_statement != nullptr, common::kSqlAstError, "not an ASTDropUserStatement"); + CHECK_TRUE(drop_user_statement->name() != nullptr, common::kSqlAstError, "invalid drop user statement"); + std::string user_name; + CHECK_STATUS(AstPathExpressionToString(drop_user_statement->name(), &user_name)); + auto node = dynamic_cast(node_manager->MakeCmdNode(node::CmdType::kCmdDropUser, user_name)); + node->SetIfExists(drop_user_statement->is_if_exists()); + *output = node; + break; + } case zetasql::AST_DROP_STATEMENT: { const zetasql::ASTDropStatement* drop_statement = statement->GetAsOrNull(); CHECK_TRUE(nullptr != drop_statement->name(), common::kSqlAstError, "not an ASTDropStatement") @@ -696,6 +707,22 @@ base::Status ConvertStatement(const zetasql::ASTStatement* statement, node::Node *output = create_index_node; break; } + case zetasql::AST_CREATE_USER_STATEMENT: { + const zetasql::ASTCreateUserStatement* create_user_stmt = + statement->GetAsOrNull(); + node::CreateUserNode* create_user_node = nullptr; + CHECK_STATUS(ConvertCreateUserStatement(create_user_stmt, node_manager, &create_user_node)) + *output = create_user_node; + break; + } + case zetasql::AST_ALTER_USER_STATEMENT: { + const zetasql::ASTAlterUserStatement* alter_user_stmt = + statement->GetAsOrNull(); + node::AlterUserNode* alter_user_node = nullptr; + CHECK_STATUS(ConvertAlterUserStatement(alter_user_stmt, node_manager, &alter_user_node)) + *output = alter_user_node; + break; + } case zetasql::AST_USE_STATEMENT: { const auto use_stmt = statement->GetAsOrNull(); CHECK_TRUE(nullptr != use_stmt, common::kSqlAstError, "not an ASTUseStatement"); @@ -2056,6 +2083,44 @@ base::Status ConvertDropStatement(const zetasql::ASTDropStatement* root, node::N } return base::Status::OK(); } + +base::Status ConvertCreateUserStatement(const zetasql::ASTCreateUserStatement* root, node::NodeManager* node_manager, + node::CreateUserNode** output) { + CHECK_TRUE(root != nullptr, common::kSqlAstError, "not an ASTCreateUserStatement") + std::string user_name; + CHECK_TRUE(root->name() != nullptr, common::kSqlAstError, "can't create user without user name"); + CHECK_STATUS(AstPathExpressionToString(root->name(), &user_name)); + + auto options = std::make_shared(); + if (root->options_list() != nullptr) { + CHECK_STATUS(ConvertAstOptionsListToMap(root->options_list(), node_manager, options)); + } + *output = node_manager->MakeNode(user_name, root->is_if_not_exists(), options); + return base::Status::OK(); +} + +base::Status ConvertAlterUserStatement(const zetasql::ASTAlterUserStatement* root, node::NodeManager* node_manager, + node::AlterUserNode** output) { + CHECK_TRUE(root != nullptr, common::kSqlAstError, "not an ASTAlterUserStatement") + std::string user_name; + CHECK_TRUE(root->path() != nullptr, common::kSqlAstError, "can't alter user without user name"); + CHECK_STATUS(AstPathExpressionToString(root->path(), &user_name)); + std::vector actions; + if (root->action_list() != nullptr) { + for (auto &ac : root->action_list()->actions()) { + node::AlterActionBase *ac_out = nullptr; + CHECK_STATUS(convertAlterAction(ac, node_manager, &ac_out)); + actions.push_back(ac_out); + } + } + CHECK_TRUE(actions.size() == 1, common::kSqlAstError, "only one action is permitted"); + CHECK_TRUE(actions.front()->kind() == node::AlterActionBase::ActionKind::SET_OPTIONS, + common::kSqlAstError, "it should be set options"); + *output = node_manager->MakeNode(user_name, root->is_if_exists(), + (dynamic_cast(actions.front()))->Options()); + return base::Status::OK(); +} + base::Status ConvertCreateIndexStatement(const zetasql::ASTCreateIndexStatement* root, node::NodeManager* node_manager, node::CreateIndexNode** output) { CHECK_TRUE(nullptr != root, common::kSqlAstError, "not an ASTCreateIndexStatement") @@ -2176,6 +2241,7 @@ static const absl::flat_hash_map showTargetMap {"TABLE STATUS", {node::CmdType::kCmdShowTableStatus, false, true}}, {"FUNCTIONS", {node::CmdType::kCmdShowFunctions}}, {"JOBLOG", {node::CmdType::kCmdShowJobLog, true}}, + {"CURRENT_USER", {node::CmdType::kCmdShowUser}}, }; static const absl::flat_hash_map SHOW_STMT_TYPE_MAP = { @@ -2350,6 +2416,21 @@ base::Status convertAlterAction(const zetasql::ASTAlterAction* action, node::Nod *out = ac; break; } + case zetasql::AST_SET_OPTIONS_ACTION: { + node::SetOptionsAction* ac = nullptr; + CHECK_STATUS(ConvertGuard( + action, nm, &ac, + [](const zetasql::ASTSetOptionsAction* in, node::NodeManager* nm, node::SetOptionsAction** out) { + auto options = std::make_shared(); + if (in->options_list() != nullptr) { + CHECK_STATUS(ConvertAstOptionsListToMap(in->options_list(), nm, options)); + } + *out = nm->MakeObj(options); + return base::Status::OK(); + })); + *out = ac; + break; + } default: FAIL_STATUS(common::kUnsupportSql, action->SingleNodeDebugString()); } diff --git a/hybridse/src/planv2/ast_node_converter.h b/hybridse/src/planv2/ast_node_converter.h index e85c6cf8487..a40bacc2e10 100644 --- a/hybridse/src/planv2/ast_node_converter.h +++ b/hybridse/src/planv2/ast_node_converter.h @@ -66,6 +66,12 @@ base::Status ConvertInExpr(const zetasql::ASTInExpression* in_expr, node::NodeMa base::Status ConvertLimitOffsetNode(const zetasql::ASTLimitOffset* limit_offset, node::NodeManager* node_manager, node::SqlNode** output); +base::Status ConvertCreateUserStatement(const zetasql::ASTCreateUserStatement* root, node::NodeManager* node_manager, + node::CreateUserNode** output); + +base::Status ConvertAlterUserStatement(const zetasql::ASTAlterUserStatement* root, node::NodeManager* node_manager, + node::AlterUserNode** output); + base::Status ConvertQueryNode(const zetasql::ASTQuery* root, node::NodeManager* node_manager, node::QueryNode** output); base::Status ConvertQueryExpr(const zetasql::ASTQueryExpression* query_expr, node::NodeManager* node_manager, diff --git a/hybridse/src/planv2/ast_node_converter_test.cc b/hybridse/src/planv2/ast_node_converter_test.cc index b2a36f9420f..9798e69bd4f 100644 --- a/hybridse/src/planv2/ast_node_converter_test.cc +++ b/hybridse/src/planv2/ast_node_converter_test.cc @@ -1193,6 +1193,8 @@ INSTANTIATE_TEST_SUITE_P(ASTHWindowQueryTest, ASTNodeConverterTest, testing::ValuesIn(sqlcase::InitCases("cases/plan/window_query.yaml", FILTERS))); INSTANTIATE_TEST_SUITE_P(ASTUnionQueryTest, ASTNodeConverterTest, testing::ValuesIn(sqlcase::InitCases("cases/plan/union_query.yaml", FILTERS))); +INSTANTIATE_TEST_SUITE_P(ASTAlterTest, ASTNodeConverterTest, + testing::ValuesIn(sqlcase::InitCases("cases/plan/alter.yaml", FILTERS))); INSTANTIATE_TEST_SUITE_P(ASTConstQueryTest, ASTNodeConverterTest, testing::ValuesIn(sqlcase::InitCases("cases/plan/const_query.yaml", FILTERS))); } // namespace plan diff --git a/java/openmldb-import/src/main/java/com/_4paradigm/openmldb/importer/Importer.java b/java/openmldb-import/src/main/java/com/_4paradigm/openmldb/importer/Importer.java index b020f52dff4..29bc188e8d3 100644 --- a/java/openmldb-import/src/main/java/com/_4paradigm/openmldb/importer/Importer.java +++ b/java/openmldb-import/src/main/java/com/_4paradigm/openmldb/importer/Importer.java @@ -88,6 +88,12 @@ enum Mode { @CommandLine.Option(names = "--rpc_read_timeout", description = "rpc read timeout(ms)", defaultValue = "50000") private int rpcReadTimeout; + @CommandLine.Option(names = "--user", description = "the user to connect OpenMLDB", defaultValue = "root") + private String user; + + @CommandLine.Option(names = "--password", description = "the password", defaultValue = "") + private String password; + FilesReader reader = null; SqlExecutor router = null; @@ -108,6 +114,8 @@ public boolean setUpSDK() { SdkOption option = new SdkOption(); option.setZkCluster(zkCluster); option.setZkPath(zkRootPath); + option.setUser(user); + option.setPassword(password); try { router = new SqlClusterExecutor(option); return true; diff --git a/java/openmldb-jdbc/src/main/java/com/_4paradigm/openmldb/jdbc/SQLDriver.java b/java/openmldb-jdbc/src/main/java/com/_4paradigm/openmldb/jdbc/SQLDriver.java index e7edffb35de..40b8e7c3fdc 100644 --- a/java/openmldb-jdbc/src/main/java/com/_4paradigm/openmldb/jdbc/SQLDriver.java +++ b/java/openmldb-jdbc/src/main/java/com/_4paradigm/openmldb/jdbc/SQLDriver.java @@ -162,6 +162,10 @@ private SdkOption createOptionByProps(Properties properties) { if (prop != null) { option.setZkLogFile(prop); } + prop = properties.getProperty("zkCert"); + if (prop != null) { + option.setZkCert(prop); + } prop = properties.getProperty("glogLevel"); if (prop != null) { option.setGlogLevel(Integer.parseInt(prop)); @@ -174,6 +178,14 @@ private SdkOption createOptionByProps(Properties properties) { if (prop != null) { option.setMaxSqlCacheSize(Integer.parseInt(prop)); } + prop = properties.getProperty("user"); + if (prop != null) { + option.setUser(prop); + } + prop = properties.getProperty("password"); + if (prop != null) { + option.setPassword(prop); + } return option; } diff --git a/java/openmldb-jdbc/src/main/java/com/_4paradigm/openmldb/sdk/SdkOption.java b/java/openmldb-jdbc/src/main/java/com/_4paradigm/openmldb/sdk/SdkOption.java index 66d0d83bef9..98279ac267f 100644 --- a/java/openmldb-jdbc/src/main/java/com/_4paradigm/openmldb/sdk/SdkOption.java +++ b/java/openmldb-jdbc/src/main/java/com/_4paradigm/openmldb/sdk/SdkOption.java @@ -47,6 +47,8 @@ public class SdkOption implements Serializable { private String glogDir = ""; private int maxSqlCacheSize = 50; private boolean isLight = false; + private String user = "root"; + private String password = ""; private void buildBaseOptions(BasicRouterOptions opt) { opt.setEnable_debug(getEnableDebug()); @@ -54,6 +56,10 @@ private void buildBaseOptions(BasicRouterOptions opt) { opt.setGlog_level(getGlogLevel()); opt.setGlog_dir(getGlogDir()); opt.setMax_sql_cache_size(getMaxSqlCacheSize()); + opt.setUser(getUser()); + if (!getPassword().isEmpty()) { + opt.setPassword(getPassword()); + } } public SQLRouterOptions buildSQLRouterOptions() throws SqlException { diff --git a/java/openmldb-spark-connector/src/main/java/com/_4paradigm/openmldb/spark/OpenmldbSource.java b/java/openmldb-spark-connector/src/main/java/com/_4paradigm/openmldb/spark/OpenmldbSource.java index 9dfe78f0197..d4f4a48617d 100644 --- a/java/openmldb-spark-connector/src/main/java/com/_4paradigm/openmldb/spark/OpenmldbSource.java +++ b/java/openmldb-spark-connector/src/main/java/com/_4paradigm/openmldb/spark/OpenmldbSource.java @@ -50,6 +50,14 @@ public StructType inferSchema(CaseInsensitiveStringMap options) { if (timeout != null) { option.setRequestTimeout(Integer.parseInt(timeout)); } + String user = options.get("user"); + if (user != null) { + option.setUser(user); + } + String password = options.get("password"); + if (password != null) { + option.setPassword(password); + } String debug = options.get("debug"); if (debug != null) { option.setEnableDebug(Boolean.valueOf(debug)); diff --git a/java/openmldb-synctool/src/main/java/com/_4paradigm/openmldb/synctool/SyncToolConfig.java b/java/openmldb-synctool/src/main/java/com/_4paradigm/openmldb/synctool/SyncToolConfig.java index 4fdb22834db..5fa14e2dc0e 100644 --- a/java/openmldb-synctool/src/main/java/com/_4paradigm/openmldb/synctool/SyncToolConfig.java +++ b/java/openmldb-synctool/src/main/java/com/_4paradigm/openmldb/synctool/SyncToolConfig.java @@ -37,6 +37,9 @@ public class SyncToolConfig { // public static int CHANNEL_KEEP_ALIVE_TIME; public static String ZK_CLUSTER; public static String ZK_ROOT_PATH; + + public static String USER; + public static String PASSWORD; public static String ZK_CERT; public static String SYNC_TASK_PROGRESS_PATH; @@ -87,6 +90,8 @@ private static void parseFromProperties(Properties prop) { if (ZK_ROOT_PATH.isEmpty()) { throw new RuntimeException("zookeeper.root_path should not be empty"); } + USER = prop.getProperty("user", "root"); + PASSWORD = prop.getProperty("password", ""); ZK_CERT = prop.getProperty("zookeeper.cert", ""); HADOOP_CONF_DIR = prop.getProperty("hadoop.conf.dir", ""); diff --git a/java/openmldb-synctool/src/main/java/com/_4paradigm/openmldb/synctool/SyncToolImpl.java b/java/openmldb-synctool/src/main/java/com/_4paradigm/openmldb/synctool/SyncToolImpl.java index 0e98cffa6f3..0685ab310d4 100644 --- a/java/openmldb-synctool/src/main/java/com/_4paradigm/openmldb/synctool/SyncToolImpl.java +++ b/java/openmldb-synctool/src/main/java/com/_4paradigm/openmldb/synctool/SyncToolImpl.java @@ -92,6 +92,8 @@ public SyncToolImpl(String endpoint) throws SqlException, InterruptedException { option.setZkCluster(SyncToolConfig.ZK_CLUSTER); option.setZkPath(SyncToolConfig.ZK_ROOT_PATH); option.setZkCert(SyncToolConfig.ZK_CERT); + option.setUser(SyncToolConfig.USER); + option.setPassword(SyncToolConfig.PASSWORD); this.router = new SqlClusterExecutor(option); this.zkCollectorPath = SyncToolConfig.ZK_ROOT_PATH + "/sync_tool/collector"; diff --git a/java/openmldb-taskmanager/src/main/java/com/_4paradigm/openmldb/taskmanager/config/TaskManagerConfig.java b/java/openmldb-taskmanager/src/main/java/com/_4paradigm/openmldb/taskmanager/config/TaskManagerConfig.java index bba740a2ffa..d849137fb3a 100644 --- a/java/openmldb-taskmanager/src/main/java/com/_4paradigm/openmldb/taskmanager/config/TaskManagerConfig.java +++ b/java/openmldb-taskmanager/src/main/java/com/_4paradigm/openmldb/taskmanager/config/TaskManagerConfig.java @@ -121,6 +121,10 @@ public static int getZkMaxConnectWaitTime() { return getInt("zookeeper.max_connect_waitTime"); } + public static String getUser() { return getString("user"); } + + public static String getPassword() { return getString("password"); } + public static String getSparkMaster() { return getString("spark.master"); } @@ -283,6 +287,14 @@ private void init() throws ConfigException { props.setProperty("zookeeper.session_timeout", "5000"); } + if (props.getProperty("user") == null) { + props.setProperty("user", "root"); + } + + if (props.getProperty("password") == null) { + props.setProperty("password", ""); + } + if (getZkSessionTimeout() <= 0) { throw new ConfigException("zookeeper.session_timeout", "should be larger than 0"); } diff --git a/java/openmldb-taskmanager/src/main/scala/com/_4paradigm/openmldb/taskmanager/JobInfoManager.scala b/java/openmldb-taskmanager/src/main/scala/com/_4paradigm/openmldb/taskmanager/JobInfoManager.scala index cd5c65e2cc4..73394749313 100644 --- a/java/openmldb-taskmanager/src/main/scala/com/_4paradigm/openmldb/taskmanager/JobInfoManager.scala +++ b/java/openmldb-taskmanager/src/main/scala/com/_4paradigm/openmldb/taskmanager/JobInfoManager.scala @@ -45,6 +45,10 @@ object JobInfoManager { private val option = new SdkOption option.setZkCluster(TaskManagerConfig.getZkCluster) option.setZkPath(TaskManagerConfig.getZkRootPath) + option.setUser(TaskManagerConfig.getUser) + if (!TaskManagerConfig.getPassword.isEmpty) { + option.setPassword(TaskManagerConfig.getPassword) + } val sqlExecutor = new SqlClusterExecutor(option) sqlExecutor.executeSQL("", "set @@execute_mode='online';") diff --git a/python/openmldb_sdk/openmldb/sdk/sdk.py b/python/openmldb_sdk/openmldb/sdk/sdk.py index e079f77c5d3..68020e08c80 100644 --- a/python/openmldb_sdk/openmldb/sdk/sdk.py +++ b/python/openmldb_sdk/openmldb/sdk/sdk.py @@ -71,6 +71,10 @@ def init(self): if 'maxSqlCacheSize' in self.options_map: options.max_sql_cache_size = int( self.options_map['maxSqlCacheSize']) + if 'user' in self.options_map: + options.user = self.options_map['user'] + if 'password' in self.options_map: + options.password = self.options_map['password'] self.sdk = sql_router_sdk.NewClusterSQLRouter( options diff --git a/python/openmldb_sdk/tests/sqlalchemy_api_test.py b/python/openmldb_sdk/tests/sqlalchemy_api_test.py index 545df92be59..b5c4dbd7b50 100644 --- a/python/openmldb_sdk/tests/sqlalchemy_api_test.py +++ b/python/openmldb_sdk/tests/sqlalchemy_api_test.py @@ -57,6 +57,7 @@ def test_select(self): assert 'first' in list(row) assert 100 in list(row) + @pytest.mark.skip(reason="test may fail to init") def test_request_timeout(self): self.connection.execute( "insert into test_table (y, x) values(400, 'a'),(401,'b'),(402, 'c');" diff --git a/python/openmldb_tool/diagnostic_tool/connector.py b/python/openmldb_tool/diagnostic_tool/connector.py index 87b28a8932a..5c69ad9a1d4 100644 --- a/python/openmldb_tool/diagnostic_tool/connector.py +++ b/python/openmldb_tool/diagnostic_tool/connector.py @@ -23,6 +23,8 @@ 'cluster', '127.0.0.1:2181/openmldb', 'Cluster addr, format: [,]/.', short_name='c') flags.DEFINE_bool('sdk_log', False, 'print sdk log(pysdk&zk&glog), default is False.') +flags.DEFINE_string('user', 'root', 'the username to connect OpenMLDB') +flags.DEFINE_string('password', '', 'config the password') FLAGS = flags.FLAGS @@ -38,6 +40,9 @@ def __init__(self): if not FLAGS.sdk_log: url += '&zkLogLevel=0&glogLevel=2' logging.getLogger('OpenMLDB_sdk').setLevel(logging.WARNING) + url += '&user=' + FLAGS.user + if FLAGS.password != '': + url += '&password=' + FLAGS.password self.engine = db.create_engine(url) self.conn = self.engine.connect() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d24b41fef9f..a5c5e642122 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -60,7 +60,7 @@ endfunction(compile_lib) set(TEST_LIBS openmldb_test_base apiserver nameserver tablet query_response_time openmldb_sdk - openmldb_catalog client zk_client storage schema replica base openmldb_codec openmldb_proto log + openmldb_catalog client zk_client storage schema replica openmldb_codec base openmldb_proto log common zookeeper_mt tcmalloc_minimal ${RocksDB_LIB} ${VM_LIBS} ${LLVM_LIBS} ${ZETASQL_LIBS} ${BRPC_LIBS}) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.1") # GNU implementation prior to 9.1 requires linking with -lstdc++fs diff --git a/src/apiserver/api_server_impl.cc b/src/apiserver/api_server_impl.cc index cb13414798f..766bcd70b0b 100644 --- a/src/apiserver/api_server_impl.cc +++ b/src/apiserver/api_server_impl.cc @@ -36,7 +36,7 @@ APIServerImpl::APIServerImpl(const std::string& endpoint) APIServerImpl::~APIServerImpl() = default; -bool APIServerImpl::Init(const sdk::ClusterOptions& options) { +bool APIServerImpl::Init(const std::shared_ptr<::openmldb::sdk::SQLRouterOptions>& options) { // If cluster sdk is needed, use ptr, don't own it. SQLClusterRouter owns it. auto cluster_sdk = new ::openmldb::sdk::ClusterSDK(options); bool ok = cluster_sdk->Init(); diff --git a/src/apiserver/api_server_impl.h b/src/apiserver/api_server_impl.h index fc8e8022417..4bad1ef9004 100644 --- a/src/apiserver/api_server_impl.h +++ b/src/apiserver/api_server_impl.h @@ -49,7 +49,7 @@ class APIServerImpl : public APIServer { public: explicit APIServerImpl(const std::string& endpoint); ~APIServerImpl() override; - bool Init(const sdk::ClusterOptions& options); + bool Init(const std::shared_ptr<::openmldb::sdk::SQLRouterOptions>& options); bool Init(::openmldb::sdk::DBSDK* cluster); void Process(google::protobuf::RpcController* cntl_base, const HttpRequest*, HttpResponse*, google::protobuf::Closure* done) override; diff --git a/src/apiserver/api_server_test.cc b/src/apiserver/api_server_test.cc index 6abe8ddd051..26bcbfe5cbf 100644 --- a/src/apiserver/api_server_test.cc +++ b/src/apiserver/api_server_test.cc @@ -44,9 +44,9 @@ class APIServerTestEnv : public testing::Environment { mc = std::make_shared(6181); ASSERT_TRUE(mc->SetUp()) << "Fail to set up mini cluster"; - sdk::ClusterOptions cluster_options; - cluster_options.zk_cluster = mc->GetZkCluster(); - cluster_options.zk_path = mc->GetZkPath(); + auto cluster_options = std::make_shared();; + cluster_options->zk_cluster = mc->GetZkCluster(); + cluster_options->zk_path = mc->GetZkPath(); // Owned by queue_svc cluster_sdk = new ::openmldb::sdk::ClusterSDK(cluster_options); ASSERT_TRUE(cluster_sdk->Init()) << "Fail to connect to db"; diff --git a/src/cmd/openmldb.cc b/src/cmd/openmldb.cc index 53da31ad634..fbad945b336 100644 --- a/src/cmd/openmldb.cc +++ b/src/cmd/openmldb.cc @@ -81,6 +81,8 @@ DECLARE_uint32(max_col_display_length); DECLARE_bool(version); DECLARE_bool(use_name); DECLARE_string(data_dir); +DECLARE_string(user); +DECLARE_string(password); const std::string OPENMLDB_VERSION = std::to_string(OPENMLDB_VERSION_MAJOR) + "." + // NOLINT std::to_string(OPENMLDB_VERSION_MINOR) + "." + @@ -3867,18 +3869,25 @@ void StartAPIServer() { PDLOG(WARNING, "Invalid nameserver format"); exit(1); } - auto sdk = new ::openmldb::sdk::StandAloneSDK(vec[0], port); + auto standalone_options = std::make_shared<::openmldb::sdk::StandaloneOptions>(); + standalone_options->host = vec[0]; + standalone_options->port = port; + standalone_options->user = FLAGS_user; + standalone_options->password = FLAGS_password; + auto sdk = new ::openmldb::sdk::StandAloneSDK(standalone_options); if (!sdk->Init() || !api_service->Init(sdk)) { PDLOG(WARNING, "Fail to init"); exit(1); } } else { - ::openmldb::sdk::ClusterOptions cluster_options; - cluster_options.zk_cluster = FLAGS_zk_cluster; - cluster_options.zk_path = FLAGS_zk_root_path; - cluster_options.zk_session_timeout = FLAGS_zk_session_timeout; - cluster_options.zk_auth_schema = FLAGS_zk_auth_schema; - cluster_options.zk_cert = FLAGS_zk_cert; + auto cluster_options = std::make_shared<::openmldb::sdk::SQLRouterOptions>(); + cluster_options->zk_cluster = FLAGS_zk_cluster; + cluster_options->zk_path = FLAGS_zk_root_path; + cluster_options->zk_session_timeout = FLAGS_zk_session_timeout; + cluster_options->zk_auth_schema = FLAGS_zk_auth_schema; + cluster_options->zk_cert = FLAGS_zk_cert; + cluster_options->user = FLAGS_user; + cluster_options->password = FLAGS_password; if (!api_service->Init(cluster_options)) { PDLOG(WARNING, "Fail to init"); exit(1); diff --git a/src/cmd/single_tablet_test.cc b/src/cmd/single_tablet_test.cc index 2c564b30546..bfe3ccedba4 100644 --- a/src/cmd/single_tablet_test.cc +++ b/src/cmd/single_tablet_test.cc @@ -65,9 +65,9 @@ TEST_P(DBSDKTest, CreateFunction) { sr = cli->sr; ::openmldb::sdk::SQLClusterRouter* sr_2 = nullptr; if (cs->IsClusterMode()) { - ::openmldb::sdk::ClusterOptions copt; - copt.zk_cluster = mc.GetZkCluster(); - copt.zk_path = mc.GetZkPath(); + auto copt = std::make_shared(); + copt->zk_cluster = mc.GetZkCluster(); + copt->zk_path = mc.GetZkPath(); auto cur_cs = new ::openmldb::sdk::ClusterSDK(copt); cur_cs->Init(); sr_2 = new ::openmldb::sdk::SQLClusterRouter(cur_cs); @@ -144,9 +144,9 @@ TEST_P(DBSDKTest, CreateUdafFunction) { sr = cli->sr; std::unique_ptr<::openmldb::sdk::SQLClusterRouter> sr_2; if (cs->IsClusterMode()) { - ::openmldb::sdk::ClusterOptions copt; - copt.zk_cluster = mc.GetZkCluster(); - copt.zk_path = mc.GetZkPath(); + auto copt = std::make_shared(); + copt->zk_cluster = mc.GetZkCluster(); + copt->zk_path = mc.GetZkPath(); auto cur_cs = new ::openmldb::sdk::ClusterSDK(copt); cur_cs->Init(); sr_2 = std::make_unique<::openmldb::sdk::SQLClusterRouter>(cur_cs); @@ -232,16 +232,17 @@ int main(int argc, char** argv) { mc.SetUp(1); sleep(5); srand(time(NULL)); - ::openmldb::sdk::ClusterOptions copt; - copt.zk_cluster = mc.GetZkCluster(); - copt.zk_path = mc.GetZkPath(); + auto copt = std::make_shared<::openmldb::sdk::SQLRouterOptions>(); + copt->zk_cluster = mc.GetZkCluster(); + copt->zk_path = mc.GetZkPath(); ::openmldb::cmd::cluster_cli.cs = new ::openmldb::sdk::ClusterSDK(copt); ::openmldb::cmd::cluster_cli.cs->Init(); ::openmldb::cmd::cluster_cli.sr = new ::openmldb::sdk::SQLClusterRouter(::openmldb::cmd::cluster_cli.cs); ::openmldb::cmd::cluster_cli.sr->Init(); env.SetUp(); - ::openmldb::cmd::standalone_cli.cs = new ::openmldb::sdk::StandAloneSDK("127.0.0.1", env.GetNsPort()); + auto sopt = std::make_shared<::openmldb::sdk::StandaloneOptions>("127.0.0.1", env.GetNsPort()); + ::openmldb::cmd::standalone_cli.cs = new ::openmldb::sdk::StandAloneSDK(sopt); ::openmldb::cmd::standalone_cli.cs->Init(); ::openmldb::cmd::standalone_cli.sr = new ::openmldb::sdk::SQLClusterRouter(::openmldb::cmd::standalone_cli.cs); ::openmldb::cmd::standalone_cli.sr->Init(); diff --git a/src/cmd/sql_cmd.h b/src/cmd/sql_cmd.h index 6b8eae72afb..56f6df6b5a4 100644 --- a/src/cmd/sql_cmd.h +++ b/src/cmd/sql_cmd.h @@ -16,6 +16,10 @@ #ifndef SRC_CMD_SQL_CMD_H_ #define SRC_CMD_SQL_CMD_H_ + +#include +#include + #include #include #include @@ -46,6 +50,8 @@ DECLARE_string(zk_cert); DECLARE_int32(zk_session_timeout); DECLARE_uint32(zk_log_level); DECLARE_string(zk_log_file); +DECLARE_string(user); +DECLARE_string(password); // stand-alone mode DECLARE_string(host); @@ -143,6 +149,30 @@ std::string ExecFetch(const std::string& sql) { return ss.str(); } +base::Status GetPassword(std::string* password) { + // refer https://www.gnu.org/software/libc/manual/html_mono/libc.html#getpass + struct termios old_attr, new_attr; + if (tcgetattr(fileno(stdin), &old_attr) != 0) { + return {base::ReturnCode::kError, "tcgetattr execute failed!"}; + } + new_attr = old_attr; + new_attr.c_lflag &= ~ECHO; + if (tcsetattr(fileno(stdin), TCSAFLUSH, &new_attr) != 0) { + return {base::ReturnCode::kError, "tcsetattr execute failed!"}; + } + size_t len = 0; + char* lineptr = nullptr; + if (ssize_t nread = getline(&lineptr, &len, stdin); nread == -1) { + free(lineptr); + return {base::ReturnCode::kError, "read input failed!"}; + } else if (nread > 1) { + password->assign(lineptr, nread - 1); + } + free(lineptr); + (void) tcsetattr(fileno(stdin), TCSAFLUSH, &old_attr); + return {}; +} + void HandleSQL(const std::string& sql) { std::cout << ExecFetch(sql); } std::string SafeGetString(std::shared_ptr rs, int idx) { @@ -263,16 +293,28 @@ void Shell() { } bool InitClusterSDK() { + auto options = std::make_shared(); ::openmldb::sdk::ClusterOptions copt; - copt.zk_cluster = FLAGS_zk_cluster; - copt.zk_path = FLAGS_zk_root_path; - copt.zk_session_timeout = FLAGS_zk_session_timeout; - copt.zk_log_level = FLAGS_zk_log_level; - copt.zk_log_file = FLAGS_zk_log_file; - copt.zk_auth_schema = FLAGS_zk_auth_schema; - copt.zk_cert = FLAGS_zk_cert; - - cs = new ::openmldb::sdk::ClusterSDK(copt); + options->zk_cluster = FLAGS_zk_cluster; + options->zk_path = FLAGS_zk_root_path; + options->zk_session_timeout = FLAGS_zk_session_timeout; + options->zk_log_level = FLAGS_zk_log_level; + options->zk_log_file = FLAGS_zk_log_file; + options->zk_auth_schema = FLAGS_zk_auth_schema; + options->zk_cert = FLAGS_zk_cert; + options->spark_conf_path = FLAGS_spark_conf; + options->request_timeout = FLAGS_request_timeout; + options->user = FLAGS_user; + options->password = FLAGS_password; + if (!::google::GetCommandLineFlagInfoOrDie("user").is_default && + ::google::GetCommandLineFlagInfoOrDie("password").is_default) { + std::cout << "Please enter password:" << std::endl; + if (auto status = GetPassword(&options->password); !status.OK()) { + std::cout << status.GetMsg() << std::endl; + return false; + } + } + cs = new ::openmldb::sdk::ClusterSDK(options); if (!cs->Init()) { std::cout << "ERROR: Failed to connect to db" << std::endl; return false; @@ -283,11 +325,6 @@ bool InitClusterSDK() { return false; } sr->SetInteractive(FLAGS_interactive); - - auto ops = std::dynamic_pointer_cast(sr->GetRouterOptions()); - ops->spark_conf_path = FLAGS_spark_conf; - ops->request_timeout = FLAGS_request_timeout; - return true; } @@ -306,7 +343,19 @@ bool InitStandAloneSDK() { std::cout << "ERROR: Host or port is missing" << std::endl; return false; } - cs = new ::openmldb::sdk::StandAloneSDK(FLAGS_host, FLAGS_port); + auto options = std::make_shared(FLAGS_host, FLAGS_port); + options->user = FLAGS_user; + options->password = FLAGS_password; + if (!::google::GetCommandLineFlagInfoOrDie("user").is_default && + ::google::GetCommandLineFlagInfoOrDie("password").is_default) { + std::cout << "Please enter password:" << std::endl; + if (auto status = GetPassword(&options->password); !status.OK()) { + std::cout << status.GetMsg() << std::endl; + return false; + } + } + options->request_timeout = FLAGS_request_timeout; + cs = new ::openmldb::sdk::StandAloneSDK(options); bool ok = cs->Init(); if (!ok) { std::cout << "ERROR: Failed to connect to db" << std::endl; @@ -318,8 +367,6 @@ bool InitStandAloneSDK() { return false; } sr->SetInteractive(FLAGS_interactive); - auto ops = sr->GetRouterOptions(); - ops->request_timeout = FLAGS_request_timeout; return true; } diff --git a/src/cmd/sql_cmd_test.cc b/src/cmd/sql_cmd_test.cc index cdff3943254..d6e9e811fa2 100644 --- a/src/cmd/sql_cmd_test.cc +++ b/src/cmd/sql_cmd_test.cc @@ -236,6 +236,54 @@ TEST_F(SqlCmdTest, SelectIntoOutfile) { remove(file_path.c_str()); } +TEST_P(DBSDKTest, TestUser) { + auto cli = GetParam(); + cs = cli->cs; + sr = cli->sr; + hybridse::sdk::Status status; + sr->ExecuteSQL(absl::StrCat("CREATE USER user1 OPTIONS(password='123456')"), &status); + ASSERT_TRUE(status.IsOK()); + sr->ExecuteSQL(absl::StrCat("CREATE USER user1 OPTIONS(password='123456')"), &status); + ASSERT_FALSE(status.IsOK()); + sr->ExecuteSQL(absl::StrCat("CREATE USER IF NOT EXISTS user1"), &status); + ASSERT_TRUE(status.IsOK()); + ASSERT_TRUE(true); + auto opt = sr->GetRouterOptions(); + if (cs->IsClusterMode()) { + auto real_opt = std::dynamic_pointer_cast(opt); + sdk::SQLRouterOptions opt1; + opt1.zk_cluster = real_opt->zk_cluster; + opt1.zk_path = real_opt->zk_path; + opt1.user = "user1"; + opt1.password = "123456"; + auto router = NewClusterSQLRouter(opt1); + ASSERT_TRUE(router != nullptr); + sr->ExecuteSQL(absl::StrCat("ALTER USER user1 SET OPTIONS(password='abc')"), &status); + ASSERT_TRUE(status.IsOK()); + router = NewClusterSQLRouter(opt1); + ASSERT_FALSE(router != nullptr); + } else { + auto real_opt = std::dynamic_pointer_cast(opt); + sdk::StandaloneOptions opt1; + opt1.host = real_opt->host; + opt1.port = real_opt->port; + opt1.user = "user1"; + opt1.password = "123456"; + auto router = NewStandaloneSQLRouter(opt1); + ASSERT_TRUE(router != nullptr); + sr->ExecuteSQL(absl::StrCat("ALTER USER user1 SET OPTIONS(password='abc')"), &status); + ASSERT_TRUE(status.IsOK()); + router = NewStandaloneSQLRouter(opt1); + ASSERT_FALSE(router != nullptr); + } + sr->ExecuteSQL(absl::StrCat("DROP USER user1"), &status); + ASSERT_TRUE(status.IsOK()); + sr->ExecuteSQL(absl::StrCat("DROP USER user1"), &status); + ASSERT_FALSE(status.IsOK()); + sr->ExecuteSQL(absl::StrCat("DROP USER IF EXISTS user1"), &status); + ASSERT_TRUE(status.IsOK()); +} + TEST_P(DBSDKTest, CreateDatabase) { auto cli = GetParam(); cs = cli->cs; @@ -532,7 +580,7 @@ TEST_F(SqlCmdTest, InsertWithDB) { sr, {"create database test1;", "create database test2;", "use test1;", "create table trans (c1 string, c2 int);", "use test2;", "insert into test1.trans values ('aaa', 123);"}); - auto cur_cs = new ::openmldb::sdk::StandAloneSDK(FLAGS_host, FLAGS_port); + auto cur_cs = new ::openmldb::sdk::StandAloneSDK(std::make_shared(FLAGS_host, FLAGS_port)); cur_cs->Init(); auto cur_sr = std::make_unique<::openmldb::sdk::SQLClusterRouter>(cur_cs); cur_sr->Init(); @@ -3274,6 +3322,7 @@ TEST_P(DBSDKTest, ShowComponents) { void ExpectShowTableStatusResult(const std::vector>& expect, hybridse::sdk::ResultSet* rs, bool all_db = false, bool is_cluster = false) { static const std::vector> SystemClusterTableStatus = { + {{}, "USER", "__INTERNAL_DB", "memory", {}, {}, {}, "1", "0", "1", "NULL", "NULL", "NULL", ""}, {{}, "PRE_AGG_META_INFO", "__INTERNAL_DB", "memory", {}, {}, {}, "1", "0", "1", "NULL", "NULL", "NULL", ""}, {{}, "JOB_INFO", "__INTERNAL_DB", "memory", "0", {}, {}, "1", "0", "1", "NULL", "NULL", "NULL", ""}, {{}, @@ -3306,6 +3355,7 @@ void ExpectShowTableStatusResult(const std::vector> SystemStandaloneTableStatus = { + {{}, "USER", "__INTERNAL_DB", "memory", {}, {}, {}, "1", "0", "1", "NULL", "NULL", "NULL", ""}, {{}, "PRE_AGG_META_INFO", "__INTERNAL_DB", "memory", {}, {}, {}, "1", "0", "1", "NULL", "NULL", "NULL", ""}, {{}, "GLOBAL_VARIABLES", @@ -3972,10 +4022,10 @@ int main(int argc, char** argv) { int ok = ::openmldb::cmd::mc_->SetUp(2); sleep(5); srand(time(NULL)); - ::openmldb::sdk::ClusterOptions copt; - copt.zk_cluster = mc.GetZkCluster(); - copt.zk_path = mc.GetZkPath(); - copt.zk_session_timeout = FLAGS_zk_session_timeout; + auto copt = std::make_shared<::openmldb::sdk::SQLRouterOptions>(); + copt->zk_cluster = mc.GetZkCluster(); + copt->zk_path = mc.GetZkPath(); + copt->zk_session_timeout = FLAGS_zk_session_timeout; ::openmldb::cmd::cluster_cli.cs = new ::openmldb::sdk::ClusterSDK(copt); ::openmldb::cmd::cluster_cli.cs->Init(); ::openmldb::cmd::cluster_cli.sr = new ::openmldb::sdk::SQLClusterRouter(::openmldb::cmd::cluster_cli.cs); @@ -3984,7 +4034,8 @@ int main(int argc, char** argv) { env.SetUp(); FLAGS_host = "127.0.0.1"; FLAGS_port = env.GetNsPort(); - ::openmldb::cmd::standalone_cli.cs = new ::openmldb::sdk::StandAloneSDK(FLAGS_host, FLAGS_port); + auto sopt = std::make_shared<::openmldb::sdk::StandaloneOptions>(FLAGS_host, FLAGS_port); + ::openmldb::cmd::standalone_cli.cs = new ::openmldb::sdk::StandAloneSDK(sopt); ::openmldb::cmd::standalone_cli.cs->Init(); ::openmldb::cmd::standalone_cli.sr = new ::openmldb::sdk::SQLClusterRouter(::openmldb::cmd::standalone_cli.cs); ::openmldb::cmd::standalone_cli.sr->Init(); diff --git a/src/codec/codec_test.cc b/src/codec/codec_test.cc index 6c6ae99f804..054f431dfca 100644 --- a/src/codec/codec_test.cc +++ b/src/codec/codec_test.cc @@ -19,6 +19,7 @@ #include #include "boost/container/deque.hpp" +#include "codec/encrypt.h" #include "codec/row_codec.h" #include "gtest/gtest.h" #include "proto/common.pb.h" @@ -541,6 +542,13 @@ TEST_F(CodecTest, RowBuilderSet) { ASSERT_EQ(ts, 1668149927000); } +TEST_F(CodecTest, Encrypt) { + ASSERT_EQ(SHA256("root"), "4813494d137e1631bba301d5acab6e7bb7aa74ce1185d456565ef51d737677b2"); + ASSERT_EQ(SHA256(""), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + ASSERT_EQ(Encrypt("root"), "14813494d137e1631bba301d5acab6e7bb7aa74ce1185d456565ef51d737677b2"); + ASSERT_EQ(Encrypt(""), "1e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); +} + } // namespace codec } // namespace openmldb diff --git a/src/codec/encrypt.h b/src/codec/encrypt.h new file mode 100644 index 00000000000..9fcbd82aa59 --- /dev/null +++ b/src/codec/encrypt.h @@ -0,0 +1,52 @@ +/* + * Copyright 2021 4Paradigm + * + * Licensed 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. + */ + +#ifndef SRC_CODEC_ENCRYPT_H_ +#define SRC_CODEC_ENCRYPT_H_ + +#include +#include +#include + +#include "absl/strings/str_cat.h" +#include "openssl/sha.h" + +namespace openmldb { +namespace codec { + +inline constexpr uint8_t VERSION = 1; + +static inline std::string SHA256(const std::string& str) { + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, str.c_str(), str.size()); + SHA256_Final(hash, &sha256); + std::stringstream ss; + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(hash[i]); + } + return ss.str(); +} + +static inline std::string Encrypt(const std::string& passwd) { + return absl::StrCat(VERSION, SHA256(passwd)); +} + +} // namespace codec +} // namespace openmldb + +#endif // SRC_CODEC_ENCRYPT_H_ diff --git a/src/flags.cc b/src/flags.cc index b16af056095..be92d0162ef 100644 --- a/src/flags.cc +++ b/src/flags.cc @@ -24,6 +24,8 @@ DEFINE_string(openmldb_log_dir, "./logs", "config the log dir of glog, for all l DEFINE_string(role, "", "Set the openmldb role for start: tablet | nameserver | client | ns_client | sql_client | apiserver"); DEFINE_string(cmd, "", "the command str, DO NOT add multi sqls"); +DEFINE_string(user, "root", "specify the user"); +DEFINE_string(password, "", "config the password"); DEFINE_int32(zk_session_timeout, 2000, "config the zk session timeout of cli in milliseconds, apiserver, tablet or nameserver"); DEFINE_uint32(tablet_heartbeat_timeout, 5 * 60 * 1000, "config the heartbeat of tablet offline. unit is milliseconds"); diff --git a/src/nameserver/name_server_impl.cc b/src/nameserver/name_server_impl.cc index d5cda3ae537..41065d61795 100644 --- a/src/nameserver/name_server_impl.cc +++ b/src/nameserver/name_server_impl.cc @@ -5470,6 +5470,10 @@ void NameServerImpl::OnLocked() { } } + if (FLAGS_system_table_replica_num > 0 && db_table_info_[INTERNAL_DB].count(USER_INFO_NAME) == 0) { + CreateSystemTableOrExit(SystemTableType::kUser); + } + if (FLAGS_system_table_replica_num > 0 && db_table_info_[INTERNAL_DB].count(PRE_AGG_META_NAME) == 0) { CreateSystemTableOrExit(SystemTableType::kPreAggMetaInfo); } @@ -9916,62 +9920,6 @@ base::Status NameServerImpl::InitGlobalVarTable() { return {}; } -/// \beirf create a SQLClusterRouter instance for use like monitoring statistics collecting -/// the actual instance is stored in `sr_` member -/// -/// \return true if action success, false if any error happens -bool NameServerImpl::GetSdkConnection() { - if (std::atomic_load_explicit(&sr_, std::memory_order_acquire) == nullptr) { - sdk::DBSDK* cs = nullptr; - PDLOG(INFO, "Init ClusterSDK in name server"); - if (IsClusterMode()) { - ::openmldb::sdk::ClusterOptions copt; - copt.zk_cluster = zk_path_.zk_cluster_; - copt.zk_path = zk_path_.root_path_; - cs = new ::openmldb::sdk::ClusterSDK(copt); - } else { - std::vector list = absl::StrSplit(endpoint_, ":"); - if (list.size() != 2) { - PDLOG(ERROR, "fail to split endpoint_"); - return false; - } - - int port = 0; - if (!absl::SimpleAtoi(list.at(1), &port)) { - PDLOG(ERROR, "fail to port string: %s", list.at(1)); - return false; - } - cs = new ::openmldb::sdk::StandAloneSDK(list.at(0), port); - } - bool ok = cs->Init(); - if (!ok) { - PDLOG(ERROR, "ERROR: Failed to init DBSDK"); - if (cs != nullptr) { - delete cs; - } - return false; - } - auto sr = std::make_shared<::openmldb::sdk::SQLClusterRouter>(cs); - if (!sr->Init()) { - PDLOG(ERROR, "fail to init SQLClusterRouter"); - if (cs != nullptr) { - delete cs; - } - return false; - } - - std::atomic_store_explicit(&sr_, sr, std::memory_order_release); - } - - return true; -} - -void NameServerImpl::FreeSdkConnection() { - if (std::atomic_load_explicit(&sr_, std::memory_order_acquire) != nullptr) { - std::atomic_store_explicit(&sr_, {}, std::memory_order_release); - } -} - std::shared_ptr NameServerImpl::CreateTaskInternal(const TaskMeta* task_meta) { auto task_type = task_meta->task_info->task_type(); std::shared_ptr client; diff --git a/src/nameserver/name_server_impl.h b/src/nameserver/name_server_impl.h index c8f5c56b04d..00ea95d7de6 100644 --- a/src/nameserver/name_server_impl.h +++ b/src/nameserver/name_server_impl.h @@ -673,10 +673,6 @@ class NameServerImpl : public NameServer { uint64_t GetTerm() const; - bool GetSdkConnection(); - - void FreeSdkConnection(); - bool RecoverExternalFunction(); ::openmldb::base::Status CheckZoneInfo(const ::openmldb::nameserver::ZoneInfo& zone_info); @@ -733,9 +729,6 @@ class NameServerImpl : public NameServer { std::unordered_map>> db_sp_info_map_; ::openmldb::type::StartupMode startup_mode_; - - // sr_ could be a real instance or nothing, remember always use atomic_* function to access it - std::shared_ptr<::openmldb::sdk::SQLClusterRouter> sr_ = nullptr; }; } // namespace nameserver diff --git a/src/nameserver/system_table.cc b/src/nameserver/system_table.cc index 830725a8d4a..38f9a9e8c18 100644 --- a/src/nameserver/system_table.cc +++ b/src/nameserver/system_table.cc @@ -27,6 +27,7 @@ static absl::flat_hash_map CreateSystemT {SystemTableType::kPreAggMetaInfo, {INTERNAL_DB, PRE_AGG_META_NAME}}, {SystemTableType::kGlobalVariable, {INFORMATION_SCHEMA_DB, GLOBAL_VARIABLES}}, {SystemTableType::kDeployResponseTime, {INFORMATION_SCHEMA_DB, DEPLOY_RESPONSE_TIME}}, + {SystemTableType::kUser, {INTERNAL_DB, USER_INFO_NAME}}, }; return map; } diff --git a/src/nameserver/system_table.h b/src/nameserver/system_table.h index bec114f8725..b781ec2b7cf 100644 --- a/src/nameserver/system_table.h +++ b/src/nameserver/system_table.h @@ -34,6 +34,7 @@ constexpr const char* INTERNAL_DB = "__INTERNAL_DB"; constexpr const char* PRE_AGG_DB = "__PRE_AGG_DB"; constexpr const char* JOB_INFO_NAME = "JOB_INFO"; constexpr const char* PRE_AGG_META_NAME = "PRE_AGG_META_INFO"; +constexpr const char* USER_INFO_NAME = "USER"; constexpr const char* INFORMATION_SCHEMA_DB = "INFORMATION_SCHEMA"; @@ -47,6 +48,7 @@ enum class SystemTableType { kPreAggMetaInfo = 2, kGlobalVariable = 3, kDeployResponseTime, + kUser, }; struct SystemTableInfo { @@ -159,6 +161,19 @@ class SystemTable { ttl->set_lat_ttl(1); break; } + case SystemTableType::kUser: { + SetColumnDesc("user", type::DataType::kString, table_info->add_column_desc()); + SetColumnDesc("password", type::DataType::kString, table_info->add_column_desc()); + SetColumnDesc("create_time", type::DataType::kTimestamp, table_info->add_column_desc()); + SetColumnDesc("update_time", type::DataType::kTimestamp, table_info->add_column_desc()); + auto index = table_info->add_column_key(); + index->set_index_name("index"); + index->add_col_name("user"); + auto ttl = index->mutable_ttl(); + ttl->set_ttl_type(::openmldb::type::kLatestTime); + ttl->set_lat_ttl(1); + break; + } default: return nullptr; } diff --git a/src/nameserver/system_table_test.cc b/src/nameserver/system_table_test.cc index 9af9fdf5a0b..eadca079c93 100644 --- a/src/nameserver/system_table_test.cc +++ b/src/nameserver/system_table_test.cc @@ -69,7 +69,10 @@ TEST_F(SystemTableTest, SystemTable) { std::vector<::openmldb::nameserver::TableInfo> tables; std::string msg; ASSERT_TRUE(ns_client.ShowTable("", INTERNAL_DB, false, tables, msg)); - ASSERT_EQ(2, tables.size()); + ASSERT_EQ(3, tables.size()); + ASSERT_EQ("JOB_INFO", tables[0].name()); + ASSERT_EQ("PRE_AGG_META_INFO", tables[1].name()); + ASSERT_EQ("USER", tables[2].name()); tables.clear(); // deny drop system table ASSERT_FALSE(ns_client.DropDatabase(INTERNAL_DB, msg)); diff --git a/src/sdk/db_sdk.cc b/src/sdk/db_sdk.cc index a8b08e10259..de6b856ddd7 100644 --- a/src/sdk/db_sdk.cc +++ b/src/sdk/db_sdk.cc @@ -173,15 +173,15 @@ bool DBSDK::RemoveExternalFun(const std::string& name) { return true; } -ClusterSDK::ClusterSDK(const ClusterOptions& options) +ClusterSDK::ClusterSDK(const std::shared_ptr& options) : options_(options), session_id_(0), - table_root_path_(options.zk_path + "/table/db_table_data"), - sp_root_path_(options.zk_path + "/store_procedure/db_sp_data"), - notify_path_(options.zk_path + "/table/notify"), - globalvar_changed_notify_path_(options.zk_path + "/notify/global_variable"), - leader_path_(options.zk_path + "/leader"), - taskmanager_leader_path_(options.zk_path + "/taskmanager/leader"), + table_root_path_(options->zk_path + "/table/db_table_data"), + sp_root_path_(options->zk_path + "/store_procedure/db_sp_data"), + notify_path_(options->zk_path + "/table/notify"), + globalvar_changed_notify_path_(options->zk_path + "/notify/global_variable"), + leader_path_(options->zk_path + "/leader"), + taskmanager_leader_path_(options->zk_path + "/taskmanager/leader"), zk_client_(nullptr), pool_(1) {} @@ -212,18 +212,18 @@ void ClusterSDK::CheckZk() { } bool ClusterSDK::Init() { - zk_client_ = new ::openmldb::zk::ZkClient(options_.zk_cluster, "", - options_.zk_session_timeout, "", - options_.zk_path, - options_.zk_auth_schema, - options_.zk_cert); + zk_client_ = new ::openmldb::zk::ZkClient(options_->zk_cluster, "", + options_->zk_session_timeout, "", + options_->zk_path, + options_->zk_auth_schema, + options_->zk_cert); - bool ok = zk_client_->Init(options_.zk_log_level, options_.zk_log_file); + bool ok = zk_client_->Init(options_->zk_log_level, options_->zk_log_file); if (!ok) { - LOG(WARNING) << "fail to init zk client with " << options_.to_string(); + LOG(WARNING) << "fail to init zk client with " << options_->to_string(); return false; } - LOG(INFO) << "init zk client with " << options_.to_string() << " and session id " << zk_client_->GetSessionTerm(); + LOG(INFO) << "init zk client with " << options_->to_string() << " and session id " << zk_client_->GetSessionTerm(); ::hybridse::vm::EngineOptions eopt; eopt.SetCompileOnly(true); @@ -244,7 +244,7 @@ void ClusterSDK::WatchNotify() { session_id_ = zk_client_->GetSessionTerm(); zk_client_->CancelWatchItem(notify_path_); zk_client_->WatchItem(notify_path_, [this] { Refresh(); }); - zk_client_->WatchChildren(options_.zk_path + "/data/function", + zk_client_->WatchChildren(options_->zk_path + "/data/function", [this](auto&& PH1) { RefreshExternalFun(std::forward(PH1)); }); zk_client_->WatchChildren(leader_path_, [this](auto&& PH1) { RefreshNsClient(std::forward(PH1)); }); @@ -509,7 +509,7 @@ bool ClusterSDK::GetRealEndpointFromZk(const std::string& endpoint, std::string* if (real_endpoint == nullptr) { return false; } - std::string sdk_path = options_.zk_path + "/map/sdkendpoints/" + endpoint; + std::string sdk_path = options_->zk_path + "/map/sdkendpoints/" + endpoint; if (zk_client_->IsExistNode(sdk_path) == 0) { if (!zk_client_->GetNodeValue(sdk_path, *real_endpoint)) { DLOG(WARNING) << "get zk failed! : sdk_path: " << sdk_path; @@ -517,7 +517,7 @@ bool ClusterSDK::GetRealEndpointFromZk(const std::string& endpoint, std::string* } } if (real_endpoint->empty()) { - std::string sname_path = options_.zk_path + "/map/names/" + endpoint; + std::string sname_path = options_->zk_path + "/map/names/" + endpoint; if (zk_client_->IsExistNode(sname_path) == 0) { if (!zk_client_->GetNodeValue(sname_path, *real_endpoint)) { DLOG(WARNING) << "get zk failed! : sname_path: " << sname_path; diff --git a/src/sdk/db_sdk.h b/src/sdk/db_sdk.h index 2d8a4ab2f38..982bdd5a40f 100644 --- a/src/sdk/db_sdk.h +++ b/src/sdk/db_sdk.h @@ -29,6 +29,7 @@ #include "client/tablet_client.h" #include "client/taskmanager_client.h" #include "common/thread_pool.h" +#include "sdk/options.h" #include "vm/catalog.h" #include "vm/engine.h" #include "zk/zk_client.h" @@ -106,6 +107,8 @@ class DBSDK { virtual bool GetNsAddress(std::string* endpoint, std::string* real_endpoint) = 0; + virtual std::shared_ptr GetOptions() const = 0; + bool RegisterExternalFun(const std::shared_ptr& fun); bool RemoveExternalFun(const std::string& name); @@ -138,7 +141,7 @@ class DBSDK { class ClusterSDK : public DBSDK { public: - explicit ClusterSDK(const ClusterOptions& options); + explicit ClusterSDK(const std::shared_ptr& options); ~ClusterSDK() override; bool Init() override; @@ -146,12 +149,13 @@ class ClusterSDK : public DBSDK { bool TriggerNotify(::openmldb::type::NotifyType type) const override; zk::ZkClient* GetZkClient() override { return zk_client_; } - const ClusterOptions& GetClusterOptions() const { return options_; } bool GetNsAddress(std::string* endpoint, std::string* real_endpoint) override; void RefreshExternalFun(const std::vector& funs); + std::shared_ptr GetOptions() const override { return options_; } + protected: bool BuildCatalog() override; bool GetTaskManagerAddress(std::string* endpoint, std::string* real_endpoint) override; @@ -166,7 +170,7 @@ class ClusterSDK : public DBSDK { void RefreshTaskManagerClient(); private: - ClusterOptions options_; + std::shared_ptr options_; uint64_t session_id_; std::string table_root_path_; std::string sp_root_path_; @@ -182,7 +186,7 @@ class ClusterSDK : public DBSDK { class StandAloneSDK : public DBSDK { public: - StandAloneSDK(std::string host, int port) : host_(std::move(host)), port_(port) {} + explicit StandAloneSDK(const std::shared_ptr options) : options_(options) {} ~StandAloneSDK() override { pool_.Stop(false); } bool Init() override; @@ -201,15 +205,17 @@ class StandAloneSDK : public DBSDK { return false; } - const std::string& GetHost() const { return host_; } + std::shared_ptr GetOptions() const override { return options_; } + + const std::string& GetHost() const { return options_->host; } - int GetPort() const { return port_; } + int GetPort() const { return options_->port; } // Before connecting to ns, we only have the host&port // NOTICE: when we call this method, we do not have the correct ns client, do not GetNsClient. bool GetNsAddress(std::string* endpoint, std::string* real_endpoint) override { std::stringstream ss; - ss << host_ << ":" << port_; + ss << GetHost() << ":" << GetPort(); *endpoint = ss.str(); *real_endpoint = ss.str(); return true; @@ -232,8 +238,7 @@ class StandAloneSDK : public DBSDK { } private: - std::string host_; - int port_; + std::shared_ptr options_; ::baidu::common::ThreadPool pool_{1}; }; diff --git a/src/sdk/db_sdk_test.cc b/src/sdk/db_sdk_test.cc index 293faa60179..bdd76cec47f 100644 --- a/src/sdk/db_sdk_test.cc +++ b/src/sdk/db_sdk_test.cc @@ -79,17 +79,17 @@ class DBSDKTest : public ::testing::Test { }; TEST_F(DBSDKTest, smokeEmptyCluster) { - ClusterOptions option; - option.zk_cluster = mc_->GetZkCluster(); - option.zk_path = mc_->GetZkPath(); + auto option = std::make_shared(); + option->zk_cluster = mc_->GetZkCluster(); + option->zk_path = mc_->GetZkPath(); ClusterSDK sdk(option); ASSERT_TRUE(sdk.Init()); } TEST_F(DBSDKTest, smokeTest) { - ClusterOptions option; - option.zk_cluster = mc_->GetZkCluster(); - option.zk_path = mc_->GetZkPath(); + auto option = std::make_shared(); + option->zk_cluster = mc_->GetZkCluster(); + option->zk_path = mc_->GetZkPath(); ClusterSDK sdk(option); ASSERT_TRUE(sdk.Init()); @@ -121,7 +121,7 @@ TEST_F(DBSDKTest, standAloneMode) { ASSERT_TRUE(sep != std::string::npos); auto host = ns.substr(0, sep); auto port = ns.substr(sep + 1); - StandAloneSDK sdk(host, std::stoi(port)); + StandAloneSDK sdk(std::make_shared(host, std::stoi(port))); ASSERT_TRUE(sdk.Init()); CreateTable(); diff --git a/src/sdk/mini_cluster_batch_bm.cc b/src/sdk/mini_cluster_batch_bm.cc index 8dc4e9e665e..296fd739021 100644 --- a/src/sdk/mini_cluster_batch_bm.cc +++ b/src/sdk/mini_cluster_batch_bm.cc @@ -85,9 +85,9 @@ static void BM_SimpleQueryFunction(benchmark::State& state) { // NOLINT rb.AppendInt64(ts); rb.AppendInt64(ts); rb.AppendInt64(ts); - ::openmldb::sdk::ClusterOptions option; - option.zk_cluster = mc->GetZkCluster(); - option.zk_path = mc->GetZkPath(); + auto option = std::make_shared<::openmldb::sdk::SQLRouterOptions>(); + option->zk_cluster = mc->GetZkCluster(); + option->zk_path = mc->GetZkPath(); ::openmldb::sdk::ClusterSDK sdk(option); sdk.Init(); std::vector> tablet; diff --git a/src/sdk/node_adapter.cc b/src/sdk/node_adapter.cc index 2a7960741a8..568de5bf05d 100644 --- a/src/sdk/node_adapter.cc +++ b/src/sdk/node_adapter.cc @@ -782,4 +782,19 @@ hybridse::sdk::Status NodeAdapter::ExtractCondition(const hybridse::node::Binary return CheckCondition(indexs, conditions); } +absl::StatusOr NodeAdapter::ExtractUserOption(const hybridse::node::OptionsMap& map) { + if (map.empty()) { + return ""; + } else if (map.size() > 1) { + return absl::InvalidArgumentError("only password option allowed"); + } + if (!absl::EqualsIgnoreCase(map.begin()->first, "password")) { + return absl::InvalidArgumentError("invalid option " + map.begin()->first); + } + if (map.begin()->second->GetDataType() != hybridse::node::kVarchar) { + return absl::InvalidArgumentError("the value of password should be string"); + } + return map.begin()->second->GetAsString(); +} + } // namespace openmldb::sdk diff --git a/src/sdk/node_adapter.h b/src/sdk/node_adapter.h index 412ebc2a78c..fe39554ad51 100644 --- a/src/sdk/node_adapter.h +++ b/src/sdk/node_adapter.h @@ -23,6 +23,7 @@ #include #include +#include "absl/status/statusor.h" #include "node/node_manager.h" #include "proto/name_server.pb.h" #include "proto/type.pb.h" @@ -69,6 +70,8 @@ class NodeAdapter { const std::vector& condition_vec, DeleteOption* option); + static absl::StatusOr ExtractUserOption(const hybridse::node::OptionsMap& map); + private: static hybridse::sdk::Status CheckCondition( const ::google::protobuf::RepeatedPtrField<::openmldb::common::ColumnKey>& indexs, diff --git a/src/sdk/options.h b/src/sdk/options.h new file mode 100644 index 00000000000..80e7a5c5cfa --- /dev/null +++ b/src/sdk/options.h @@ -0,0 +1,69 @@ +/* + * Copyright 2021 4Paradigm + * + * Licensed 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. + */ + +#ifndef SRC_SDK_OPTIONS_H_ +#define SRC_SDK_OPTIONS_H_ + +#include +#include + +namespace openmldb { +namespace sdk { + +struct BasicRouterOptions { + virtual ~BasicRouterOptions() = default; + bool enable_debug = false; + uint32_t max_sql_cache_size = 50; + // == gflag `request_timeout` default value(no gflags here cuz swig) + uint32_t request_timeout = 60000; + // default 0(INFO), INFO, WARNING, ERROR, and FATAL are 0, 1, 2, and 3 + int glog_level = 0; + // empty means to stderr + std::string glog_dir = ""; + std::string user = "root"; + std::string password; +}; + +struct SQLRouterOptions : BasicRouterOptions { + std::string zk_cluster; + std::string zk_path; + uint32_t zk_session_timeout = 2000; + std::string spark_conf_path; + uint32_t zk_log_level = 3; // PY/JAVA SDK default info log + std::string zk_log_file; + std::string zk_auth_schema = "digest"; + std::string zk_cert; + + std::string to_string() { + std::stringstream ss; + ss << "zk options [cluster:" << zk_cluster << ", path:" << zk_path + << ", zk_session_timeout:" << zk_session_timeout + << ", log_level:" << zk_log_level << ", log_file:" << zk_log_file + << ", zk_auth_schema:" << zk_auth_schema << ", zk_cert:" << zk_cert << "]"; + return ss.str(); + } +}; + +struct StandaloneOptions : BasicRouterOptions { + StandaloneOptions() = default; + StandaloneOptions(const std::string& h, uint32_t p) : host(h), port(p) {} + std::string host; + uint32_t port; +}; + +} // namespace sdk +} // namespace openmldb +#endif // SRC_SDK_OPTIONS_H_ diff --git a/src/sdk/query_future_impl.h b/src/sdk/query_future_impl.h new file mode 100644 index 00000000000..5f87a721171 --- /dev/null +++ b/src/sdk/query_future_impl.h @@ -0,0 +1,125 @@ +/* + * Copyright 2021 4Paradigm + * + * Licensed 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. + */ + +#ifndef SRC_SDK_QUERY_FUTURE_IMPL_H_ +#define SRC_SDK_QUERY_FUTURE_IMPL_H_ + +#include +#include "proto/tablet.pb.h" +#include "rpc/rpc_client.h" +#include "sdk/base.h" +#include "sdk/result_set_sql.h" +#include "sdk/sql_router.h" + +namespace openmldb { +namespace sdk { + +class QueryFutureImpl : public QueryFuture { + public: + explicit QueryFutureImpl(openmldb::RpcCallback* callback) : callback_(callback) { + if (callback_) { + callback_->Ref(); + } + } + ~QueryFutureImpl() { + if (callback_) { + callback_->UnRef(); + } + } + + std::shared_ptr GetResultSet(hybridse::sdk::Status* status) override { + if (!status) { + return nullptr; + } + if (!callback_ || !callback_->GetResponse() || !callback_->GetController()) { + status->code = hybridse::common::kRpcError; + status->msg = "request error, response or controller null"; + return nullptr; + } + brpc::Join(callback_->GetController()->call_id()); + if (callback_->GetController()->Failed()) { + status->code = hybridse::common::kRpcError; + status->msg = "request error, " + callback_->GetController()->ErrorText(); + return nullptr; + } + if (callback_->GetResponse()->code() != ::openmldb::base::kOk) { + status->code = callback_->GetResponse()->code(); + status->msg = "request error, " + callback_->GetResponse()->msg(); + return nullptr; + } + auto rs = ResultSetSQL::MakeResultSet(callback_->GetResponse(), callback_->GetController(), status); + return rs; + } + + bool IsDone() const override { + if (callback_) return callback_->IsDone(); + return false; + } + + private: + openmldb::RpcCallback* callback_; +}; + +class BatchQueryFutureImpl : public QueryFuture { + public: + explicit BatchQueryFutureImpl(openmldb::RpcCallback* callback) + : callback_(callback) { + if (callback_) { + callback_->Ref(); + } + } + + ~BatchQueryFutureImpl() { + if (callback_) { + callback_->UnRef(); + } + } + + std::shared_ptr GetResultSet(hybridse::sdk::Status* status) override { + if (!status) { + return nullptr; + } + if (!callback_ || !callback_->GetResponse() || !callback_->GetController()) { + status->code = hybridse::common::kRpcError; + status->msg = "request error, response or controller null"; + return nullptr; + } + brpc::Join(callback_->GetController()->call_id()); + if (callback_->GetController()->Failed()) { + status->code = hybridse::common::kRpcError; + status->msg = "request error. " + callback_->GetController()->ErrorText(); + return nullptr; + } + auto rs = std::make_shared(callback_->GetResponse(), + callback_->GetController()); + if (!rs->Init()) { + status->code = -1; + status->msg = "request error, resuletSetSQL init failed"; + return nullptr; + } + return rs; + } + + bool IsDone() const override { return callback_->IsDone(); } + + private: + openmldb::RpcCallback* callback_; +}; + + +} // namespace sdk +} // namespace openmldb +#endif // SRC_SDK_QUERY_FUTURE_IMPL_H_ diff --git a/src/sdk/sql_cluster_router.cc b/src/sdk/sql_cluster_router.cc index 696d83a37cb..e1e1bfaeb9e 100644 --- a/src/sdk/sql_cluster_router.cc +++ b/src/sdk/sql_cluster_router.cc @@ -42,6 +42,7 @@ #include "boost/property_tree/ptree.hpp" #include "brpc/channel.h" #include "cmd/display.h" +#include "codec/encrypt.h" #include "common/timer.h" #include "glog/logging.h" #include "nameserver/system_table.h" @@ -55,6 +56,7 @@ #include "sdk/batch_request_result_set_sql.h" #include "sdk/job_table_helper.h" #include "sdk/node_adapter.h" +#include "sdk/query_future_impl.h" #include "sdk/result_set_sql.h" #include "sdk/sdk_util.h" #include "sdk/split.h" @@ -114,100 +116,6 @@ class ExplainInfoImpl : public ExplainInfo { std::string request_name_; }; -class QueryFutureImpl : public QueryFuture { - public: - explicit QueryFutureImpl(openmldb::RpcCallback* callback) : callback_(callback) { - if (callback_) { - callback_->Ref(); - } - } - ~QueryFutureImpl() { - if (callback_) { - callback_->UnRef(); - } - } - - std::shared_ptr GetResultSet(hybridse::sdk::Status* status) override { - if (!status) { - return nullptr; - } - if (!callback_ || !callback_->GetResponse() || !callback_->GetController()) { - status->code = hybridse::common::kRpcError; - status->msg = "request error, response or controller null"; - return nullptr; - } - brpc::Join(callback_->GetController()->call_id()); - if (callback_->GetController()->Failed()) { - status->code = hybridse::common::kRpcError; - status->msg = "request error, " + callback_->GetController()->ErrorText(); - return nullptr; - } - if (callback_->GetResponse()->code() != ::openmldb::base::kOk) { - status->code = callback_->GetResponse()->code(); - status->msg = "request error, " + callback_->GetResponse()->msg(); - return nullptr; - } - auto rs = ResultSetSQL::MakeResultSet(callback_->GetResponse(), callback_->GetController(), status); - return rs; - } - - bool IsDone() const override { - if (callback_) return callback_->IsDone(); - return false; - } - - private: - openmldb::RpcCallback* callback_; -}; - -class BatchQueryFutureImpl : public QueryFuture { - public: - explicit BatchQueryFutureImpl(openmldb::RpcCallback* callback) - : callback_(callback) { - if (callback_) { - callback_->Ref(); - } - } - - ~BatchQueryFutureImpl() { - if (callback_) { - callback_->UnRef(); - } - } - - std::shared_ptr GetResultSet(hybridse::sdk::Status* status) override { - if (!status) { - return nullptr; - } - if (!callback_ || !callback_->GetResponse() || !callback_->GetController()) { - status->code = hybridse::common::kRpcError; - status->msg = "request error, response or controller null"; - return nullptr; - } - brpc::Join(callback_->GetController()->call_id()); - if (callback_->GetController()->Failed()) { - status->code = hybridse::common::kRpcError; - status->msg = "request error. " + callback_->GetController()->ErrorText(); - return nullptr; - } - std::shared_ptr<::openmldb::sdk::SQLBatchRequestResultSet> rs = - std::make_shared(callback_->GetResponse(), - callback_->GetController()); - bool ok = rs->Init(); - if (!ok) { - status->code = -1; - status->msg = "request error, resuletSetSQL init failed"; - return nullptr; - } - return rs; - } - - bool IsDone() const override { return callback_->IsDone(); } - - private: - openmldb::RpcCallback* callback_; -}; - SQLClusterRouter::SQLClusterRouter(const SQLRouterOptions& options) : options_(std::make_shared(options)), is_cluster_mode_(true), @@ -231,11 +139,7 @@ SQLClusterRouter::SQLClusterRouter(DBSDK* sdk) cluster_sdk_(sdk), mu_(), rand_(::baidu::common::timer::now_time()) { - if (is_cluster_mode_) { - options_ = std::make_shared(); - } else { - options_ = std::make_shared(); - } + options_ = sdk->GetOptions(); } SQLClusterRouter::~SQLClusterRouter() { delete cluster_sdk_; } @@ -253,15 +157,7 @@ bool SQLClusterRouter::Init() { // init cluster_sdk_, require options_ or standalone_options_ is set if (is_cluster_mode_) { auto ops = std::dynamic_pointer_cast(options_); - ClusterOptions coptions; - coptions.zk_cluster = ops->zk_cluster; - coptions.zk_path = ops->zk_path; - coptions.zk_session_timeout = ops->zk_session_timeout; - coptions.zk_log_level = ops->zk_log_level; - coptions.zk_log_file = ops->zk_log_file; - coptions.zk_auth_schema = ops->zk_auth_schema; - coptions.zk_cert = ops->zk_cert; - cluster_sdk_ = new ClusterSDK(coptions); + cluster_sdk_ = new ClusterSDK(ops); // TODO(hw): no detail error info bool ok = cluster_sdk_->Init(); if (!ok) { @@ -270,35 +166,13 @@ bool SQLClusterRouter::Init() { } } else { auto ops = std::dynamic_pointer_cast(options_); - cluster_sdk_ = new ::openmldb::sdk::StandAloneSDK(ops->host, ops->port); + cluster_sdk_ = new ::openmldb::sdk::StandAloneSDK(ops); bool ok = cluster_sdk_->Init(); if (!ok) { LOG(WARNING) << "fail to init standalone sdk"; return false; } } - } else { - // init options_ or standalone_options_ if fileds not filled, they should be consistent with cluster_sdk_ - // - // might better to refactor constructors & fileds for SQLClusterRouter - // but will introduce breaking changes as well - if (is_cluster_mode_) { - auto ops = std::dynamic_pointer_cast(options_); - if (ops->zk_cluster.empty() || ops->zk_path.empty()) { - auto* cluster_sdk = dynamic_cast(cluster_sdk_); - DCHECK(cluster_sdk != nullptr); - ops->zk_cluster = cluster_sdk->GetClusterOptions().zk_cluster; - ops->zk_path = cluster_sdk->GetClusterOptions().zk_path; - } - } else { - auto ops = std::dynamic_pointer_cast(options_); - if (ops->host.empty() || ops->port == 0) { - auto* standalone_sdk = dynamic_cast(cluster_sdk_); - DCHECK(standalone_sdk != nullptr); - ops->host = standalone_sdk->GetHost(); - ops->port = standalone_sdk->GetPort(); - } - } } std::string db = openmldb::nameserver::INFORMATION_SCHEMA_DB; @@ -323,6 +197,40 @@ bool SQLClusterRouter::Init() { session_variables_.emplace("insert_memory_usage_limit", "0"); session_variables_.emplace("spark_config", ""); } + return Auth(); +} + +bool SQLClusterRouter::Auth() { + auto ns_client = cluster_sdk_->GetNsClient(); + std::vector<::openmldb::nameserver::TableInfo> tables; + std::string msg; + auto ok = ns_client->ShowTable(nameserver::USER_INFO_NAME, nameserver::INTERNAL_DB, false, tables, msg); + if (!ok) { + LOG(WARNING) << "fail to get table from nameserver. error msg: " << msg; + return false; + } + if (tables.empty()) { + return true; + } + UserInfo info; + auto result = GetUser(options_->user, &info); + if (result.ok()) { + if (!(*result)) { + if (options_->user == "root") { + return true; + } + LOG(WARNING) << "user " << options_->user << " does not exist"; + return false; + } + auto password = options_->password.empty() ? options_->password : codec::Encrypt(options_->password); + if (info.password != password) { + LOG(WARNING) << "wrong password!"; + return false; + } + } else { + LOG(WARNING) << result.status(); + return false; + } return true; } @@ -1728,6 +1636,11 @@ std::shared_ptr SQLClusterRouter::HandleSQLCmd(const h return ResultSetSQL::MakeResultSet({"Tables"}, values, status); } + case hybridse::node::kCmdShowUser: { + std::vector value = { options_->user }; + return ResultSetSQL::MakeResultSet({"User"}, {value}, status); + } + case hybridse::node::kCmdShowCreateTable: { auto& args = cmd_node->GetArgs(); std::string cur_db = db; @@ -1824,6 +1737,23 @@ std::shared_ptr SQLClusterRouter::HandleSQLCmd(const h } return {}; } + case hybridse::node::kCmdDropUser: { + std::string name = cmd_node->GetArgs()[0]; + if (cmd_node->IsIfExists()) { + *status = DeleteUser(name); + } else { + UserInfo user_info; + auto result = GetUser(name, &user_info); + if (!result.ok()) { + *status = {StatusCode::kCmdError, result.status().message()}; + } else if (!(*result)) { + *status = {StatusCode::kCmdError, absl::StrCat("user ", name, " does not exist")}; + } else { + *status = DeleteUser(name); + } + } + return {}; + } case hybridse::node::kCmdShowFunctions: { std::vector<::openmldb::common::ExternalFun> funs; base::Status st = ns_ptr->ShowFunction("", &funs); @@ -2735,6 +2665,55 @@ std::shared_ptr SQLClusterRouter::ExecuteSQL( } return {}; } + case hybridse::node::kPlanTypeCreateUser: { + auto create_node = dynamic_cast(node); + UserInfo user_info;; + auto result = GetUser(create_node->Name(), &user_info); + if (!result.ok()) { + *status = {StatusCode::kCmdError, result.status().message()}; + } else if (*result) { + if (!create_node->IfNotExists()) { + *status = {StatusCode::kCmdError, absl::StrCat("user ", create_node->Name(), " already exists")}; + } + } else { + std::string password; + if (create_node->Options()) { + auto ret = NodeAdapter::ExtractUserOption(*create_node->Options()); + if (!ret.ok()) { + *status = {StatusCode::kCmdError, ret.status().message()}; + return {}; + } + password = *ret; + } + *status = AddUser(create_node->Name(), password); + } + return {}; + } + case hybridse::node::kPlanTypeAlterUser: { + auto alter_node = dynamic_cast(node); + UserInfo user_info; + auto result = GetUser(alter_node->Name(), &user_info); + if (!result.ok()) { + *status = {StatusCode::kCmdError, result.status().message()}; + return {}; + } else if (!(*result)) { + if (!alter_node->IfExists() && alter_node->Name() != "root") { + *status = {StatusCode::kCmdError, absl::StrCat("user ", alter_node->Name(), " does not exists")}; + return {}; + } + user_info.name = "root"; + user_info.create_time = ::baidu::common::timer::get_micros() / 1000; + } + if (alter_node->Options() && !alter_node->Options()->empty()) { + auto ret = NodeAdapter::ExtractUserOption(*alter_node->Options()); + if (!ret.ok()) { + *status = {StatusCode::kCmdError, ret.status().message()}; + return {}; + } + *status = UpdateUser(user_info, *ret); + } + return {}; + } case hybridse::node::kPlanTypeCreateIndex: { auto create_index_plan_node = dynamic_cast(node); auto create_index_node = create_index_plan_node->create_index_node_; @@ -2829,6 +2808,7 @@ std::shared_ptr SQLClusterRouter::ExecuteSQL( ::openmldb::taskmanager::JobInfo job_info; std::map config = ParseSparkConfigString(GetSparkConfig()); ReadSparkConfFromFile(std::dynamic_pointer_cast(options_)->spark_conf_path, &config); + AddUserToConfig(&config); auto base_status = ExportOfflineData(sql, config, db, is_sync_job, offline_job_timeout, &job_info); if (base_status.OK()) { @@ -2887,6 +2867,7 @@ std::shared_ptr SQLClusterRouter::ExecuteSQL( ::openmldb::taskmanager::JobInfo job_info; std::map config = ParseSparkConfigString(GetSparkConfig()); ReadSparkConfFromFile(std::dynamic_pointer_cast(options_)->spark_conf_path, &config); + AddUserToConfig(&config); ::openmldb::base::Status base_status; if (is_online_mode) { @@ -3035,6 +3016,7 @@ std::shared_ptr SQLClusterRouter::ExecuteOfflineQuery( RET_IF_NULL_AND_WARN(status, "output status is nullptr"); std::map config = ParseSparkConfigString(GetSparkConfig()); ReadSparkConfFromFile(std::dynamic_pointer_cast(options_)->spark_conf_path, &config); + AddUserToConfig(&config); if (is_sync_job) { // Run offline sql and wait to get output @@ -3527,7 +3509,7 @@ hybridse::sdk::Status SQLClusterRouter::HandleDelete(const std::string& db, cons return status; } status = SendDeleteRequst(table_info, &option); - if (status.IsOK()) { + if (status.IsOK() && db != nameserver::INTERNAL_DB) { status = { StatusCode::kOk, "DELETE is a dangerous operation. Once deleted, it is very difficult to recover. You may also note that:\n" @@ -4781,6 +4763,63 @@ std::shared_ptr SQLClusterRouter::GetNameServerJobResu return rs; } +absl::StatusOr SQLClusterRouter::GetUser(const std::string& name, UserInfo* user_info) { + std::string sql = absl::StrCat("select * from ", nameserver::USER_INFO_NAME); + hybridse::sdk::Status status; + auto rs = ExecuteSQLParameterized(nameserver::INTERNAL_DB, sql, + std::shared_ptr(), &status); + if (rs == nullptr) { + return absl::InternalError(status.msg); + } + while (rs->Next()) { + if (rs->GetStringUnsafe(0) == name) { + user_info->name = name; + user_info->password = rs->GetStringUnsafe(1); + user_info->create_time = rs->GetTimeUnsafe(2); + user_info->update_time = rs->GetTimeUnsafe(3); + return true; + } + } + return false; +} + +hybridse::sdk::Status SQLClusterRouter::AddUser(const std::string& name, const std::string& password) { + auto real_password = password.empty() ? password : codec::Encrypt(password); + uint64_t cur_ts = ::baidu::common::timer::get_micros() / 1000; + std::string sql = absl::StrCat("insert into ", nameserver::USER_INFO_NAME, " values (", + "'", name, "', '", real_password, "', ", + cur_ts, ", ", cur_ts, ");"); + hybridse::sdk::Status status; + ExecuteInsert(nameserver::INTERNAL_DB, sql, &status); + return status; +} + +hybridse::sdk::Status SQLClusterRouter::UpdateUser(const UserInfo& user_info, const std::string& password) { + auto real_password = password.empty() ? password : codec::Encrypt(password); + uint64_t cur_ts = ::baidu::common::timer::get_micros() / 1000; + std::string sql = absl::StrCat("insert into ", nameserver::USER_INFO_NAME, " values (", + "'", user_info.name, "', '", real_password, "', ", + user_info.create_time, ", ", cur_ts, ");"); + hybridse::sdk::Status status; + ExecuteInsert(nameserver::INTERNAL_DB, sql, &status); + return status; +} + +hybridse::sdk::Status SQLClusterRouter::DeleteUser(const std::string& name) { + std::string sql = absl::StrCat("delete from ", nameserver::USER_INFO_NAME, + " where user = '", name, "';"); + hybridse::sdk::Status status; + ExecuteSQL(nameserver::INTERNAL_DB, sql, &status); + return status; +} + +void SQLClusterRouter::AddUserToConfig(std::map* config) { + config->emplace("spark.openmldb.user", GetRouterOptions()->user); + if (!GetRouterOptions()->password.empty()) { + config->emplace("spark.openmldb.password", GetRouterOptions()->password); + } +} + ::hybridse::sdk::Status SQLClusterRouter::RevertPut(const nameserver::TableInfo& table_info, uint32_t end_pid, const std::map>>& dimensions, diff --git a/src/sdk/sql_cluster_router.h b/src/sdk/sql_cluster_router.h index 0b9f6cca272..c3251d81e29 100644 --- a/src/sdk/sql_cluster_router.h +++ b/src/sdk/sql_cluster_router.h @@ -49,6 +49,7 @@ class DeleteOption; using TableInfoMap = std::map>; class Bias; +struct UserInfo; class SQLClusterRouter : public SQLRouter { public: @@ -64,6 +65,8 @@ class SQLClusterRouter : public SQLRouter { bool Init(); + bool Auth(); + bool CreateDB(const std::string& db, hybridse::sdk::Status* status) override; bool DropDB(const std::string& db, hybridse::sdk::Status* status) override; @@ -424,6 +427,11 @@ class SQLClusterRouter : public SQLRouter { int64_t timeout_ms, const base::Slice& row, const std::string& router_col, hybridse::sdk::Status* status); + absl::StatusOr GetUser(const std::string& name, UserInfo* user_info); + hybridse::sdk::Status AddUser(const std::string& name, const std::string& password); + hybridse::sdk::Status UpdateUser(const UserInfo& user_info, const std::string& password); + hybridse::sdk::Status DeleteUser(const std::string& name); + void AddUserToConfig(std::map* config); ::hybridse::sdk::Status RevertPut(const nameserver::TableInfo& table_info, uint32_t end_pid, const std::map>>& dimensions, @@ -445,6 +453,13 @@ class SQLClusterRouter : public SQLRouter { std::atomic insert_memory_usage_limit_ = 0; // [0-100], the default value 0 means unlimited }; +struct UserInfo { + std::string name; + std::string password; + uint64_t create_time = 0; + uint64_t update_time = 0; +}; + class Bias { public: // If get failed, return false and won't change bias. Check negative bias value for your own logic diff --git a/src/sdk/sql_router.h b/src/sdk/sql_router.h index 07b2e3b7734..f68d7d39a1c 100644 --- a/src/sdk/sql_router.h +++ b/src/sdk/sql_router.h @@ -27,6 +27,7 @@ #include #include "sdk/base.h" +#include "sdk/options.h" #include "sdk/result_set.h" #include "sdk/sql_delete_row.h" #include "sdk/sql_insert_row.h" @@ -39,34 +40,6 @@ namespace sdk { typedef char* ByteArrayPtr; -struct BasicRouterOptions { - virtual ~BasicRouterOptions() = default; - bool enable_debug = false; - uint32_t max_sql_cache_size = 50; - // == gflag `request_timeout` default value(no gflags here cuz swig) - uint32_t request_timeout = 60000; - // default 0(INFO), INFO, WARNING, ERROR, and FATAL are 0, 1, 2, and 3 - int glog_level = 0; - // empty means to stderr - std::string glog_dir = ""; -}; - -struct SQLRouterOptions : BasicRouterOptions { - std::string zk_cluster; - std::string zk_path; - uint32_t zk_session_timeout = 2000; - std::string spark_conf_path; - uint32_t zk_log_level = 3; // PY/JAVA SDK default info log - std::string zk_log_file; - std::string zk_auth_schema = "digest"; - std::string zk_cert; -}; - -struct StandaloneOptions : BasicRouterOptions { - std::string host; - uint32_t port; -}; - class ExplainInfo { public: ExplainInfo() {} diff --git a/src/sdk/sql_router_sdk.i b/src/sdk/sql_router_sdk.i index 07bb3d5741b..15ea2b8e7c4 100644 --- a/src/sdk/sql_router_sdk.i +++ b/src/sdk/sql_router_sdk.i @@ -71,6 +71,7 @@ %shared_ptr(openmldb::sdk::DAGNode); %{ +#include "sdk/options.h" #include "sdk/sql_router.h" #include "sdk/result_set.h" #include "sdk/base_schema.h" @@ -98,6 +99,7 @@ using openmldb::sdk::TableReader; using openmldb::sdk::DefaultValueContainer; %} +%include "sdk/options.h" %include "sdk/sql_router.h" %include "sdk/base_schema.h" %include "sdk/base.h" diff --git a/src/sdk/sql_standalone_sdk_test.cc b/src/sdk/sql_standalone_sdk_test.cc index e61cf1ea76c..2b2a4cc2be8 100644 --- a/src/sdk/sql_standalone_sdk_test.cc +++ b/src/sdk/sql_standalone_sdk_test.cc @@ -882,7 +882,8 @@ int main(int argc, char** argv) { ::openmldb::sdk::StandaloneEnv env; env.SetUp(); // connect to nameserver - ::openmldb::sdk::DBSDK *cs = new ::openmldb::sdk::StandAloneSDK("127.0.0.1", env.GetNsPort()); + auto sopt = std::make_shared<::openmldb::sdk::StandaloneOptions>("127.0.0.1", env.GetNsPort()); + ::openmldb::sdk::DBSDK *cs = new ::openmldb::sdk::StandAloneSDK(sopt); bool ok = cs->Init(); if (!ok) { std::cout << "Fail to connect to db" << std::endl; diff --git a/src/tools/data_exporter.cc b/src/tools/data_exporter.cc index fd089281fd6..a20d773abc6 100644 --- a/src/tools/data_exporter.cc +++ b/src/tools/data_exporter.cc @@ -92,9 +92,9 @@ int main(int argc, char* argv[]) { } else { std::string zk_cluster, zk_root_path; ReadZKFromYaml(FLAGS_config_path, &zk_cluster, &zk_root_path); - ::openmldb::sdk::ClusterOptions cluster_options; - cluster_options.zk_cluster = zk_cluster; - cluster_options.zk_path = zk_root_path; + auto cluster_options = std::make_shared<::openmldb::sdk::SQLRouterOptions>(); + cluster_options->zk_cluster = zk_cluster; + cluster_options->zk_path = zk_root_path; tablemeta_reader = new ::openmldb::tools::ClusterTablemetaReader(FLAGS_db_name, FLAGS_table_name, tablet_map, cluster_options); } diff --git a/src/tools/tablemeta_reader.cc b/src/tools/tablemeta_reader.cc index d7f6ae72638..c32aa511c24 100644 --- a/src/tools/tablemeta_reader.cc +++ b/src/tools/tablemeta_reader.cc @@ -123,7 +123,7 @@ std::string TablemetaReader::ReadDBRootPath(const std::string& deploy_dir, const } void StandaloneTablemetaReader::SetTableinfoPtr() { - ::openmldb::sdk::StandAloneSDK standalone_sdk(host_, port_); + ::openmldb::sdk::StandAloneSDK standalone_sdk(options_); standalone_sdk.Init(); tableinfo_ptr_ = standalone_sdk.GetTableInfo(db_name_, table_name_); } diff --git a/src/tools/tablemeta_reader.h b/src/tools/tablemeta_reader.h index 20de072bf68..a3faf1b54a9 100644 --- a/src/tools/tablemeta_reader.h +++ b/src/tools/tablemeta_reader.h @@ -80,7 +80,8 @@ class TablemetaReader { class ClusterTablemetaReader : public TablemetaReader { public: ClusterTablemetaReader(const std::string &db_name, const std::string &table_name, - std::unordered_map tablet_map, const ClusterOptions& options) : + std::unordered_map tablet_map, + const std::shared_ptr& options) : TablemetaReader(db_name, table_name, tablet_map), options_(options) {} void SetTableinfoPtr() override; @@ -88,7 +89,7 @@ class ClusterTablemetaReader : public TablemetaReader { bool IsClusterMode() const override { return true; } private: - ClusterOptions options_; + std::shared_ptr options_; }; @@ -96,15 +97,16 @@ class StandaloneTablemetaReader : public TablemetaReader { public: StandaloneTablemetaReader(const std::string &db_name, const std::string &table_name, std::unordered_map tablet_map, const std::string &host, int port) : - TablemetaReader(db_name, table_name, tablet_map), host_(host), port_(port) {} + TablemetaReader(db_name, table_name, tablet_map) { + options_ = std::make_shared(host, port); + } void SetTableinfoPtr() override; bool IsClusterMode() const override { return false; } private: - std::string host_; - uint32_t port_; + std::shared_ptr options_; }; } // namespace tools