diff --git a/.github/actions/test_stateful_sharing/action.yml b/.github/actions/test_stateful_sharing/action.yml deleted file mode 100644 index 1334f3f0aee8..000000000000 --- a/.github/actions/test_stateful_sharing/action.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: "Test Stateful Sharing" -description: "Running stateful with sharing in standalone mode" -inputs: - target: - description: "" - required: true - default: "x86_64-unknown-linux-gnu" -runs: - using: "composite" - steps: - - uses: ./.github/actions/setup_bendsql - - name: Download artifact - uses: ./.github/actions/artifact_download - with: - sha: ${{ github.sha }} - target: ${{ inputs.target }} - artifacts: open-sharing,meta,query - - - name: Minio Setup for (ubuntu-latest only) - shell: bash - run: | - docker run -d --network host --name minio \ - -e "MINIO_ACCESS_KEY=minioadmin" \ - -e "MINIO_SECRET_KEY=minioadmin" \ - -e "MINIO_ADDRESS=:9900" \ - -v /tmp/data:/data \ - -v /tmp/config:/root/.minio \ - minio/minio server /data - - export AWS_ACCESS_KEY_ID=minioadmin - export AWS_SECRET_ACCESS_KEY=minioadmin - export AWS_EC2_METADATA_DISABLED=true - - aws --endpoint-url http://127.0.0.1:9900/ s3 mb s3://testbucket - aws --endpoint-url http://127.0.0.1:9900/ s3 cp tests/data s3://testbucket/admin/data --recursive --no-progress - aws --endpoint-url http://127.0.0.1:9900/ s3 cp tests/data/ontime_200.csv s3://testbucket/admin/data/ontime_200_v1.csv --no-progress - aws --endpoint-url http://127.0.0.1:9900/ s3 cp tests/data/ontime_200.parquet s3://testbucket/admin/data/ontime_200_v1.parquet --no-progress - aws --endpoint-url http://127.0.0.1:9900/ s3 cp tests/data/iceberg s3://testbucket --recursive --no-progress - - - name: Run Stateful Share database Tests with Standalone mode - shell: bash - run: | - ./scripts/ci/ci-run-sharding-tests.sh diff --git a/.github/workflows/reuse.linux.yml b/.github/workflows/reuse.linux.yml index c9b84e3b60e8..c6be36fb22b4 100644 --- a/.github/workflows/reuse.linux.yml +++ b/.github/workflows/reuse.linux.yml @@ -181,20 +181,6 @@ jobs: with: name: test-stateful-standalone-linux - test_stateful_sharing: - runs-on: [self-hosted, X64, Linux, 4c8g, "${{ inputs.runner_provider }}"] - needs: [build, check] - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/test_stateful_sharing - if: env.BUILD_PROFILE == 'debug' - timeout-minutes: 10 - - name: Upload failure - if: failure() - uses: ./.github/actions/artifact_failure - with: - name: test-stateful-sharing-linux - test_stateful_cluster: runs-on: [self-hosted, X64, Linux, 4c8g, "${{ inputs.runner_provider }}"] needs: [build, check] diff --git a/Cargo.lock b/Cargo.lock index 6d5365021dbf..1924221315b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3496,7 +3496,6 @@ dependencies = [ "databend-common-meta-stoerr", "databend-common-meta-types", "databend-common-proto-conv", - "enumflags2", "futures", "log", "logcall", @@ -3955,13 +3954,9 @@ dependencies = [ "async-backtrace", "bytes", "databend-common-auth", - "databend-common-base", "databend-common-config", "databend-common-exception", - "databend-common-meta-api", "databend-common-meta-app", - "databend-common-storage", - "databend-common-users", "http 1.1.0", "log", "moka", @@ -4385,23 +4380,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "databend-common-storages-share" -version = "0.1.0" -dependencies = [ - "async-backtrace", - "chrono", - "databend-common-exception", - "databend-common-meta-app", - "databend-storages-common-table-meta", - "enumflags2", - "goldenfile", - "opendal", - "serde", - "serde_json", - "tempfile", -] - [[package]] name = "databend-common-storages-stage" version = "0.1.0" @@ -4886,7 +4864,6 @@ dependencies = [ "databend-common-pipeline-transforms", "databend-common-script", "databend-common-settings", - "databend-common-sharing", "databend-common-sql", "databend-common-storage", "databend-common-storages-delta", @@ -4898,7 +4875,6 @@ dependencies = [ "databend-common-storages-null", "databend-common-storages-parquet", "databend-common-storages-result-cache", - "databend-common-storages-share", "databend-common-storages-stage", "databend-common-storages-stream", "databend-common-storages-system", @@ -4994,8 +4970,7 @@ name = "databend-sharing-endpoint" version = "0.1.0" dependencies = [ "async-backtrace", - "base64 0.22.0", - "bytes", + "base64 0.21.7", "chrono", "clap 4.5.1", "databend-common-base", @@ -5003,15 +4978,12 @@ dependencies = [ "databend-common-exception", "databend-common-meta-app", "databend-common-storage", - "databend-common-storages-share", "enumflags2", "http 1.1.0", "opendal", "poem", "serde", - "serde_json", "serfig", - "time", "uuid", ] diff --git a/Cargo.toml b/Cargo.toml index 75d9598af70a..0a58dd324ff8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,6 @@ members = [ "src/query/storages/memory", "src/query/storages/null", "src/query/storages/random", - "src/query/storages/share", "src/query/storages/stage", "src/query/storages/stream", "src/query/storages/system", diff --git a/src/meta/api/Cargo.toml b/src/meta/api/Cargo.toml index 71ff64b3c597..4ee85113e8f3 100644 --- a/src/meta/api/Cargo.toml +++ b/src/meta/api/Cargo.toml @@ -26,7 +26,6 @@ anyhow = { workspace = true } async-backtrace = { workspace = true } async-trait = { workspace = true } chrono = { workspace = true } -enumflags2 = { workspace = true } futures = { workspace = true } log = { workspace = true } logcall = { workspace = true } diff --git a/src/meta/api/src/kv_pb_api/mod.rs b/src/meta/api/src/kv_pb_api/mod.rs index 98e92736fa5c..89de49056108 100644 --- a/src/meta/api/src/kv_pb_api/mod.rs +++ b/src/meta/api/src/kv_pb_api/mod.rs @@ -46,6 +46,23 @@ use crate::kv_pb_api::errors::PbApiWriteError; /// This trait provides a way to access a kv store with `kvapi::Key` type key and protobuf encoded value. pub trait KVPbApi: KVApi { + /// Update a protobuf encoded value by kvapi::Key. + /// + /// Equivalent to `update_pb(UpsertPB::update(key,value))` + /// but returns the transition before and after executing the operation. + fn update_pb( + &self, + key: K, + value: K::ValueType, + ) -> impl Future, Self::Error>> + Send + where + K: kvapi::Key + Send + 'static, + K::ValueType: FromToProto + Send, + Self::Error: From>, + { + async move { self.upsert_pb(&UpsertPB::update(key, value)).await } + } + /// Update or insert a protobuf encoded value by kvapi::Key. /// /// The key will be converted to string and the value is encoded by `FromToProto`. diff --git a/src/meta/api/src/lib.rs b/src/meta/api/src/lib.rs index 1a4d58b720f8..ffd6d8b109f1 100644 --- a/src/meta/api/src/lib.rs +++ b/src/meta/api/src/lib.rs @@ -30,9 +30,6 @@ mod schema_api; mod schema_api_impl; mod schema_api_test_suite; mod sequence_api; -mod share_api; -mod share_api_impl; -mod share_api_test_suite; pub(crate) mod testing; pub mod txn_backoff; pub(crate) mod util; @@ -44,31 +41,17 @@ pub use background_api::BackgroundApi; pub use background_api_test_suite::BackgroundApiTestSuite; pub use data_mask_api::DatamaskApi; pub use schema_api::SchemaApi; -pub(crate) use schema_api_impl::get_db_or_err; pub use schema_api_test_suite::SchemaApiTestSuite; pub use sequence_api::SequenceApi; -pub use share_api::ShareApi; -pub use share_api_test_suite::ShareApiTestSuite; pub use util::assert_table_exist; -pub use util::convert_share_meta_to_spec; pub use util::db_has_to_exist; pub use util::deserialize_struct; pub use util::deserialize_u64; pub use util::fetch_id; -pub use util::get_object_shared_by_share_ids; pub use util::get_pb_value; -pub use util::get_share_account_meta_or_err; -pub use util::get_share_database_id_and_privilege; -pub use util::get_share_id_to_name_or_err; -pub use util::get_share_meta_by_id_or_err; -pub use util::get_share_or_err; -pub use util::get_share_table_info; pub use util::get_u64_value; -pub use util::is_all_db_data_removed; -pub use util::is_db_need_to_be_remove; pub use util::list_keys; pub use util::list_u64_value; -pub use util::remove_db_from_share; pub use util::send_txn; pub use util::serialize_struct; pub use util::serialize_u64; diff --git a/src/meta/api/src/schema_api.rs b/src/meta/api/src/schema_api.rs index 9f76755e72a7..e52ee864d87d 100644 --- a/src/meta/api/src/schema_api.rs +++ b/src/meta/api/src/schema_api.rs @@ -29,6 +29,7 @@ use databend_common_meta_app::schema::CreateTableReply; use databend_common_meta_app::schema::CreateTableReq; use databend_common_meta_app::schema::CreateVirtualColumnReply; use databend_common_meta_app::schema::CreateVirtualColumnReq; +use databend_common_meta_app::schema::DatabaseIdIdent; use databend_common_meta_app::schema::DatabaseInfo; use databend_common_meta_app::schema::DeleteLockRevReq; use databend_common_meta_app::schema::DropCatalogReply; @@ -95,6 +96,7 @@ use databend_common_meta_app::schema::UpdateVirtualColumnReq; use databend_common_meta_app::schema::UpsertTableOptionReply; use databend_common_meta_app::schema::UpsertTableOptionReq; use databend_common_meta_app::schema::VirtualColumnMeta; +use databend_common_meta_app::tenant::Tenant; use databend_common_meta_types::MetaError; use databend_common_meta_types::MetaId; use databend_common_meta_types::SeqV; @@ -212,15 +214,17 @@ pub trait SchemaApi: Send + Sync { async fn mget_table_names_by_ids( &self, + tenant: &Tenant, table_ids: &[MetaId], ) -> Result>, KVAppError>; async fn mget_database_names_by_ids( &self, + tenant: &Tenant, db_ids: &[MetaId], ) -> Result>, KVAppError>; - async fn get_db_name_by_id(&self, db_id: MetaId) -> Result; + async fn get_db_name_by_id(&self, db_id: DatabaseIdIdent) -> Result; async fn get_table_copied_file_info( &self, diff --git a/src/meta/api/src/schema_api_impl.rs b/src/meta/api/src/schema_api_impl.rs index e6549617e1e1..874fa681d466 100644 --- a/src/meta/api/src/schema_api_impl.rs +++ b/src/meta/api/src/schema_api_impl.rs @@ -57,8 +57,6 @@ use databend_common_meta_app::app_error::UnknownTable; use databend_common_meta_app::app_error::UnknownTableId; use databend_common_meta_app::app_error::ViewAlreadyExists; use databend_common_meta_app::app_error::VirtualColumnAlreadyExists; -use databend_common_meta_app::app_error::WrongShare; -use databend_common_meta_app::app_error::WrongShareObject; use databend_common_meta_app::data_mask::MaskPolicyTableIdListIdent; use databend_common_meta_app::data_mask::MaskpolicyTableIdList; use databend_common_meta_app::id_generator::IdGenerator; @@ -85,9 +83,9 @@ use databend_common_meta_app::schema::CreateTableReq; use databend_common_meta_app::schema::CreateVirtualColumnReply; use databend_common_meta_app::schema::CreateVirtualColumnReq; use databend_common_meta_app::schema::DBIdTableName; -use databend_common_meta_app::schema::DatabaseId; use databend_common_meta_app::schema::DatabaseIdHistoryIdent; -use databend_common_meta_app::schema::DatabaseIdToName; +use databend_common_meta_app::schema::DatabaseIdIdent; +use databend_common_meta_app::schema::DatabaseIdToNameIdent; use databend_common_meta_app::schema::DatabaseIdent; use databend_common_meta_app::schema::DatabaseInfo; use databend_common_meta_app::schema::DatabaseInfoFilter; @@ -179,10 +177,6 @@ use databend_common_meta_app::schema::UpsertTableOptionReply; use databend_common_meta_app::schema::UpsertTableOptionReq; use databend_common_meta_app::schema::VirtualColumnIdent; use databend_common_meta_app::schema::VirtualColumnMeta; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::ShareGrantObject; -use databend_common_meta_app::share::ShareSpec; -use databend_common_meta_app::share::ShareTableInfoMap; use databend_common_meta_app::tenant::Tenant; use databend_common_meta_app::KeyWithTenant; use databend_common_meta_kvapi::kvapi; @@ -214,22 +208,15 @@ use minitrace::func_name; use ConditionResult::Eq; use crate::assert_table_exist; -use crate::convert_share_meta_to_spec; use crate::db_has_to_exist; use crate::deserialize_struct; use crate::fetch_id; use crate::get_pb_value; -use crate::get_share_id_to_name_or_err; -use crate::get_share_meta_by_id_or_err; -use crate::get_share_or_err; -use crate::get_share_table_info; use crate::get_u64_value; -use crate::is_db_need_to_be_remove; use crate::kv_app_error::KVAppError; use crate::kv_pb_api::KVPbApi; use crate::list_keys; use crate::list_u64_value; -use crate::remove_db_from_share; use crate::send_txn; use crate::serialize_struct; use crate::serialize_u64; @@ -245,12 +232,9 @@ use crate::util::deserialize_struct_get_response; use crate::util::deserialize_u64; use crate::util::get_index_metas_by_ids; use crate::util::get_table_by_id_or_err; -use crate::util::get_table_names_by_ids; use crate::util::get_virtual_column_by_id_or_err; -use crate::util::list_tables_from_share_db; use crate::util::list_tables_from_unshare_db; use crate::util::mget_pb_values; -use crate::util::remove_table_from_share; use crate::SchemaApi; use crate::DEFAULT_MGET_SIZE; @@ -268,6 +252,7 @@ impl + ?Sized> SchemaApi for KV { ) -> Result { debug!(req :? =(&req); "SchemaApi: {}", func_name!()); + let tenant = req.name_ident.tenant().clone(); let name_key = &req.name_ident; if req.meta.drop_on.is_some() { @@ -287,7 +272,7 @@ impl + ?Sized> SchemaApi for KV { let mut condition = vec![]; let mut if_then = vec![]; - let spec_vec = if db_id_seq > 0 { + if db_id_seq > 0 { match req.create_option { CreateOption::Create => { return Err(KVAppError::AppError(AppError::DatabaseAlreadyExists( @@ -298,10 +283,7 @@ impl + ?Sized> SchemaApi for KV { ))); } CreateOption::CreateIfNotExists => { - return Ok(CreateDatabaseReply { - db_id, - spec_vec: None, - }); + return Ok(CreateDatabaseReply { db_id }); } CreateOption::CreateOrReplace => { drop_database_meta( @@ -315,8 +297,6 @@ impl + ?Sized> SchemaApi for KV { .await? } } - } else { - None }; // get db id list from _fd_db_id_list/db_id @@ -341,8 +321,8 @@ impl + ?Sized> SchemaApi for KV { // share_id -> share_meta let db_id = fetch_id(self, IdGenerator::database_id()).await?; - let id_key = DatabaseId { db_id }; - let id_to_name_key = DatabaseIdToName { db_id }; + let db_id_ident = DatabaseIdIdent::new(&tenant, db_id); + let id_to_name_key = DatabaseIdToNameIdent::new(&tenant, db_id); debug!(db_id = db_id, name_key :? =(name_key); "new database id"); @@ -357,7 +337,7 @@ impl + ?Sized> SchemaApi for KV { ]); if_then.extend(vec![ txn_op_put(name_key, serialize_u64(db_id)?), // (tenant, db_name) -> db_id - txn_op_put(&id_key, serialize_struct(&req.meta)?), // (db_id) -> db_meta + txn_op_put(&db_id_ident, serialize_struct(&req.meta)?), // (db_id) -> db_meta txn_op_put(&dbid_idlist, serialize_struct(&db_id_list)?), /* _fd_db_id_list// -> db_id_list */ txn_op_put(&id_to_name_key, serialize_struct(&DatabaseNameIdentRaw::from(name_key))?), /* __fd_database_id_to_name/ -> (tenant,db_name) */ ]); @@ -372,13 +352,13 @@ impl + ?Sized> SchemaApi for KV { debug!( name :? =(name_key), - id :? =(&id_key), + id :? =(&db_id_ident), succ = succ; "create_database" ); if succ { - return Ok(CreateDatabaseReply { db_id, spec_vec }); + return Ok(CreateDatabaseReply { db_id }); } } } @@ -398,7 +378,7 @@ impl + ?Sized> SchemaApi for KV { let mut condition = vec![]; let mut if_then = vec![]; - let spec_vec = drop_database_meta( + drop_database_meta( self, tenant_dbname, req.if_exists, @@ -422,7 +402,7 @@ impl + ?Sized> SchemaApi for KV { ); if succ { - return Ok(DropDatabaseReply { spec_vec }); + return Ok(DropDatabaseReply {}); } } } @@ -435,6 +415,7 @@ impl + ?Sized> SchemaApi for KV { ) -> Result { debug!(req :? =(&req); "SchemaApi: {}", func_name!()); + let tenant = req.name_ident.tenant().clone(); let name_key = &req.name_ident; let mut trials = txn_backoff(None, func_name!()); @@ -486,9 +467,9 @@ impl + ?Sized> SchemaApi for KV { })?; // get db_meta of the last db id - let dbid = DatabaseId { db_id }; + let db_id_ident = DatabaseIdIdent::new(&tenant, db_id); let (db_meta_seq, db_meta): (_, Option) = - get_pb_value(self, &dbid).await?; + get_pb_value(self, &db_id_ident).await?; debug!(db_id = db_id, name_key :? =(name_key); "undrop_database"); @@ -507,11 +488,11 @@ impl + ?Sized> SchemaApi for KV { condition: vec![ txn_cond_seq(name_key, Eq, 0), txn_cond_seq(&dbid_idlist, Eq, db_id_list_seq), - txn_cond_seq(&dbid, Eq, db_meta_seq), + txn_cond_seq(&db_id_ident, Eq, db_meta_seq), ], if_then: vec![ txn_op_put(name_key, serialize_u64(db_id)?), // (tenant, db_name) -> db_id - txn_op_put(&dbid, serialize_struct(&db_meta)?), // (db_id) -> db_meta + txn_op_put(&db_id_ident, serialize_struct(&db_meta)?), // (db_id) -> db_meta ], else_then: vec![], }; @@ -539,6 +520,7 @@ impl + ?Sized> SchemaApi for KV { ) -> Result { debug!(req :? =(&req); "SchemaApi: {}", func_name!()); + let tenant = req.name_ident.tenant().clone(); let tenant_dbname = &req.name_ident; let tenant_newdbname = DatabaseNameIdent::new(tenant_dbname.tenant(), &req.new_db_name); @@ -567,7 +549,7 @@ impl + ?Sized> SchemaApi for KV { db_has_to_not_exist(db_id_seq, &tenant_newdbname, "rename_database")?; // get db id -> name - let db_id_key = DatabaseIdToName { db_id: old_db_id }; + let db_id_key = DatabaseIdToNameIdent::new(&tenant, old_db_id); let (db_name_seq, _): (_, Option) = get_pb_value(self, &db_id_key).await?; @@ -703,6 +685,8 @@ impl + ?Sized> SchemaApi for KV { ) -> Result>, KVAppError> { debug!(req :? =(&req); "SchemaApi: {}", func_name!()); + let tenant = req.tenant.clone(); + // List tables by tenant, db_id, table_name. let dbid_tbname_idlist = DatabaseIdHistoryIdent::new(&req.tenant, "dummy"); let dir_name = DirName::new(dbid_tbname_idlist); @@ -736,8 +720,9 @@ impl + ?Sized> SchemaApi for KV { let inner_keys: Vec = db_id_list .id_list .iter() - .map(|db_id| DatabaseId { db_id: *db_id }.to_string_key()) + .map(|db_id| DatabaseIdIdent::new(&tenant, *db_id).to_string_key()) .collect(); + let mut db_id_list_iter = db_id_list.id_list.into_iter(); for c in inner_keys.chunks(DEFAULT_MGET_SIZE) { let db_meta_seq_meta_vec: Vec<(u64, Option)> = @@ -806,9 +791,7 @@ impl + ?Sized> SchemaApi for KV { "get db history db:{:?}, db_id:{:?} has no DbIdListKey", db_info.name_ident, db_info.ident.db_id ); - db_id_list.push(DatabaseId { - db_id: db_info.ident.db_id, - }); + db_id_list.push(DatabaseIdIdent::new(&tenant, db_info.ident.db_id)); add_dbinfo_map.insert(db_info.ident.db_id, db_info); } } @@ -822,7 +805,7 @@ impl + ?Sized> SchemaApi for KV { mget_pb_values(self, c).await?; for (db_meta_seq, db_meta) in db_meta_seq_meta_vec { - let db_id = db_id_list_iter.next().unwrap().db_id; + let db_id = db_id_list_iter.next().unwrap().database_id(); if db_meta_seq == 0 || db_meta.is_none() { error!("get_database_history cannot find {:?} db_meta", db_id); continue; @@ -854,6 +837,8 @@ impl + ?Sized> SchemaApi for KV { ) -> Result>, KVAppError> { debug!(req :? =(&req); "SchemaApi: {}", func_name!()); + let tenant = req.tenant.clone(); + // Using a empty db to to list all let name_key = DatabaseNameIdent::new(req.tenant(), ""); @@ -864,7 +849,7 @@ impl + ?Sized> SchemaApi for KV { let mut kv_keys = Vec::with_capacity(db_ids.len()); for db_id in db_ids.iter() { - let k = DatabaseId { db_id: *db_id }.to_string_key(); + let k = DatabaseIdIdent::new(&tenant, *db_id).to_string_key(); kv_keys.push(k); } @@ -1508,6 +1493,7 @@ impl + ?Sized> SchemaApi for KV { debug!(req :? =(&req); "SchemaApi: {}", func_name!()); + let tenant = req.name_ident.tenant.clone(); let tenant_dbname_tbname = &req.name_ident; let tenant_dbname = req.name_ident.db_name_ident(); @@ -1526,7 +1512,7 @@ impl + ?Sized> SchemaApi for KV { }; // fixed - let key_dbid = DatabaseId { db_id: db_id.data }; + let db_id_ident = DatabaseIdIdent::new(&tenant, db_id.data); // fixed let key_dbid_tbname = DBIdTableName { @@ -1542,7 +1528,7 @@ impl + ?Sized> SchemaApi for KV { // The keys of values to re-fetch for every retry in this txn. let keys = vec![ - key_dbid.to_string_key(), + db_id_ident.to_string_key(), key_dbid_tbname.to_string_key(), key_table_id_list.to_string_key(), ]; @@ -1573,8 +1559,8 @@ impl + ?Sized> SchemaApi for KV { let db_meta = { let d = data.remove(0); - let (k, v) = deserialize_struct_get_response::(d)?; - assert_eq!(key_dbid, k); + let (k, v) = deserialize_struct_get_response::(d)?; + assert_eq!(db_id_ident.database_id(), k.database_id()); v.ok_or_else(|| { AppError::UnknownDatabaseId(UnknownDatabaseId::new( @@ -1595,7 +1581,7 @@ impl + ?Sized> SchemaApi for KV { let mut condition = vec![]; let mut if_then = vec![]; - let opt = { + let dbid_tbname_seq = { let d = data.remove(0); let (k, v) = deserialize_id_get_response::(d)?; assert_eq!(key_dbid_tbname, k); @@ -1611,9 +1597,8 @@ impl + ?Sized> SchemaApi for KV { return Ok(CreateTableReply { table_id: *id.data, table_id_seq: None, - db_id: db_id.data, + database_id_ident: db_id_ident.clone(), new_table: false, - spec_vec: None, }); } CreateOption::CreateOrReplace => { @@ -1622,7 +1607,7 @@ impl + ?Sized> SchemaApi for KV { // need to combine with drop_table_txn operations, just return // the sequence number associated with the value part of // the key-value pair (key_dbid_tbname, table_id). - (None, id.seq) + id.seq } else { construct_drop_table_txn_operations( self, @@ -1640,7 +1625,7 @@ impl + ?Sized> SchemaApi for KV { } } } else { - (None, 0) + 0 } }; @@ -1675,12 +1660,11 @@ impl + ?Sized> SchemaApi for KV { { // append new table_id into list tb_id_list.data.append(table_id); - let dbid_tbname_seq = opt.1; condition.extend(vec![ // db has not to change, i.e., no new table is created. // Renaming db is OK and does not affect the seq of db_meta. - txn_cond_seq(&key_dbid, Eq, db_meta.seq), + txn_cond_seq(&db_id_ident, Eq, db_meta.seq), // no other table with the same name is inserted. txn_cond_seq(&key_dbid_tbname, Eq, dbid_tbname_seq), // no other table id with the same name is append. @@ -1688,16 +1672,16 @@ impl + ?Sized> SchemaApi for KV { ]); if_then.extend( vec![ - // Changing a table in a db has to update the seq of db_meta, - // to block the batch-delete-tables when deleting a db. - txn_op_put(&key_dbid, serialize_struct(&db_meta.data)?), /* (db_id) -> db_meta */ + // Changing a table in a db has to update the seq of db_meta, + // to block the batch-delete-tables when deleting a db. + txn_op_put(&db_id_ident, serialize_struct(&db_meta.data)?), /* (db_id) -> db_meta */ txn_op_put( key_table_id, serialize_struct(&req.table_meta)?, ), /* (tenant, db_id, tb_id) -> tb_meta */ txn_op_put(&key_table_id_list, serialize_struct(&tb_id_list.data)?), /* _fd_table_id_list/db_id/table_name -> tb_id_list */ - // This record does not need to assert `table_id_to_name_key == 0`, - // Because this is a reverse index for db_id/table_name -> table_id, and it is unique. + // This record does not need to assert `table_id_to_name_key == 0`, + // Because this is a reverse index for db_id/table_name -> table_id, and it is unique. txn_op_put(&key_table_id_to_name, serialize_struct(&key_dbid_tbname)?), /* __fd_table_id_to_name/db_id/table_name -> DBIdTableName */ ]); @@ -1745,13 +1729,8 @@ impl + ?Sized> SchemaApi for KV { return Ok(CreateTableReply { table_id, table_id_seq, - db_id: db_id.data, + database_id_ident: db_id_ident.clone(), new_table: dbid_tbname_seq == 0, - spec_vec: if let Some((spec_vec, mut_share_table_info)) = opt.0 { - Some((spec_vec, mut_share_table_info)) - } else { - None - }, }); } else { // re-run txn with re-fetched data @@ -1783,6 +1762,7 @@ impl + ?Sized> SchemaApi for KV { async fn rename_table(&self, req: RenameTableReq) -> Result { debug!(req :? =(&req); "SchemaApi: {}", func_name!()); + let tenant = &req.name_ident.tenant.clone(); let tenant_dbname_tbname = &req.name_ident; let tenant_dbname = tenant_dbname_tbname.db_name_ident(); let tenant_newdbname_newtbname = TableNameIdent { @@ -1916,8 +1896,12 @@ impl + ?Sized> SchemaApi for KV { let condition = vec![ // db has not to change, i.e., no new table is created. // Renaming db is OK and does not affect the seq of db_meta. - txn_cond_seq(&DatabaseId { db_id }, Eq, db_meta_seq), - txn_cond_seq(&DatabaseId { db_id: new_db_id }, Eq, new_db_meta_seq), + txn_cond_seq(&DatabaseIdIdent::new(tenant, db_id), Eq, db_meta_seq), + txn_cond_seq( + &DatabaseIdIdent::new(tenant, new_db_id), + Eq, + new_db_meta_seq, + ), // table_name->table_id does not change. // Updating the table meta is ok. txn_cond_seq(&dbid_tbname, Eq, tb_id_seq), @@ -1933,7 +1917,10 @@ impl + ?Sized> SchemaApi for KV { txn_op_put(&newdbid_newtbname, serialize_u64(table_id)?), /* (db_id, new_tb_name) -> tb_id */ // Changing a table in a db has to update the seq of db_meta, // to block the batch-delete-tables when deleting a db. - txn_op_put(&DatabaseId { db_id }, serialize_struct(&db_meta)?), /* (db_id) -> db_meta */ + txn_op_put( + &DatabaseIdIdent::new(tenant, db_id), + serialize_struct(&db_meta)?, + ), // (db_id) -> db_meta txn_op_put(&dbid_tbname_idlist, serialize_struct(&tb_id_list)?), /* _fd_table_id_list/db_id/old_table_name -> tb_id_list */ txn_op_put(&new_dbid_tbname_idlist, serialize_struct(&new_tb_id_list)?), /* _fd_table_id_list/db_id/new_table_name -> tb_id_list */ txn_op_put(&table_id_to_name_key, serialize_struct(&db_id_table_name)?), /* __fd_table_id_to_name/db_id/table_name -> DBIdTableName */ @@ -1942,7 +1929,7 @@ impl + ?Sized> SchemaApi for KV { if db_id != new_db_id { then_ops.push( txn_op_put( - &DatabaseId { db_id: new_db_id }, + &DatabaseIdIdent::new(tenant, new_db_id), serialize_struct(&new_db_meta)?, ), // (db_id) -> db_meta ); @@ -1995,29 +1982,18 @@ impl + ?Sized> SchemaApi for KV { } }; - let table_id = match db_meta.from_share { - Some(ref share_name_ident_raw) => { - let share_ident = share_name_ident_raw.clone().to_tident(()); - get_table_id_from_share_by_name( - self, - &share_ident, - &tenant_dbname_tbname.table_name, - ) - .await? - } - None => { - // Get table by tenant,db_id, table_name to assert presence. + let table_id = { + // Get table by tenant,db_id, table_name to assert presence. - let dbid_tbname = DBIdTableName { - db_id, - table_name: tenant_dbname_tbname.table_name.clone(), - }; + let dbid_tbname = DBIdTableName { + db_id, + table_name: tenant_dbname_tbname.table_name.clone(), + }; - let (tb_id_seq, table_id) = get_u64_value(self, &dbid_tbname).await?; - assert_table_exist(tb_id_seq, tenant_dbname_tbname, "get_table")?; + let (tb_id_seq, table_id) = get_u64_value(self, &dbid_tbname).await?; + assert_table_exist(tb_id_seq, tenant_dbname_tbname, "get_table")?; - table_id - } + table_id }; let tbid = TableId { table_id }; @@ -2213,20 +2189,14 @@ impl + ?Sized> SchemaApi for KV { ) .await; - let (_db_id_seq, db_id, _db_meta_seq, db_meta) = match res { + let (_db_id_seq, db_id, _db_meta_seq, _db_meta) = match res { Ok(x) => x, Err(e) => { return Err(e); } }; - let tb_infos = match db_meta.from_share { - None => list_tables_from_unshare_db(self, db_id, tenant_dbname).await?, - Some(share) => { - let share_ident = share.to_tident(()); - list_tables_from_share_db(self, share_ident, tenant_dbname).await? - } - }; + let tb_infos = list_tables_from_unshare_db(self, db_id, tenant_dbname).await?; Ok(tb_infos) } @@ -2249,8 +2219,11 @@ impl + ?Sized> SchemaApi for KV { #[minitrace::trace] async fn mget_table_names_by_ids( &self, + tenant: &Tenant, table_ids: &[MetaId], ) -> Result>, KVAppError> { + let _ = tenant; + debug!(req :? =(&table_ids); "SchemaApi: {}", func_name!()); let mut id_name_kv_keys = Vec::with_capacity(table_ids.len()); @@ -2290,19 +2263,19 @@ impl + ?Sized> SchemaApi for KV { #[logcall::logcall("debug")] #[minitrace::trace] - async fn get_db_name_by_id(&self, db_id: u64) -> Result { - debug!(req :? =(&db_id); "SchemaApi: {}", func_name!()); + async fn get_db_name_by_id(&self, db_id_ident: DatabaseIdIdent) -> Result { + debug!(req :? =(&db_id_ident); "SchemaApi: {}", func_name!()); - let db_id_to_name_key = DatabaseIdToName { db_id }; + let db_id_to_name_ident = DatabaseIdToNameIdent::new_from(db_id_ident.clone()); let (meta_seq, db_name): (_, Option) = - get_pb_value(self, &db_id_to_name_key).await?; + get_pb_value(self, &db_id_to_name_ident).await?; - debug!(ident :% =(&db_id_to_name_key); "get_db_name_by_id"); + debug!(ident :% =(&db_id_to_name_ident.display()); "get_db_name_by_id"); if meta_seq == 0 || db_name.is_none() { return Err(KVAppError::AppError(AppError::UnknownDatabaseId( - UnknownDatabaseId::new(db_id, "get_db_name_by_id"), + UnknownDatabaseId::new(db_id_ident.database_id(), "get_db_name_by_id"), ))); } @@ -2313,13 +2286,14 @@ impl + ?Sized> SchemaApi for KV { #[minitrace::trace] async fn mget_database_names_by_ids( &self, + tenant: &Tenant, db_ids: &[MetaId], ) -> Result>, KVAppError> { debug!(req :? =(&db_ids); "SchemaApi: {}", func_name!()); let mut kv_keys = Vec::with_capacity(db_ids.len()); for id in db_ids { - let k = DatabaseIdToName { db_id: *id }.to_string_key(); + let k = DatabaseIdToNameIdent::new(tenant, *id).to_string_key(); kv_keys.push(k); } @@ -2335,7 +2309,7 @@ impl + ?Sized> SchemaApi for KV { let mut meta_kv_keys = Vec::with_capacity(db_ids.len()); for id in db_ids { - let k = DatabaseId { db_id: *id }.to_string_key(); + let k = DatabaseIdIdent::new(tenant, *id).to_string_key(); meta_kv_keys.push(k); } @@ -2366,7 +2340,7 @@ impl + ?Sized> SchemaApi for KV { let mut condition = vec![]; let mut if_then = vec![]; - let opt = construct_drop_table_txn_operations( + let seq = construct_drop_table_txn_operations( self, req.table_name.clone(), &req.tenant, @@ -2380,8 +2354,8 @@ impl + ?Sized> SchemaApi for KV { .await?; // seq == 0 means that req.if_exists == true and cannot find table meta, // in this case just return directly - if opt.1 == 0 { - return Ok(DropTableReply { spec_vec: None }); + if seq == 0 { + return Ok(DropTableReply {}); } let txn_req = TxnRequest { condition, @@ -2398,13 +2372,7 @@ impl + ?Sized> SchemaApi for KV { "drop_table_by_id" ); if succ { - return Ok(DropTableReply { - spec_vec: if let Some((spec_vec, mut_share_table_info)) = opt.0 { - Some((spec_vec, mut_share_table_info)) - } else { - None - }, - }); + return Ok(DropTableReply {}); } } } @@ -2643,9 +2611,7 @@ impl + ?Sized> SchemaApi for KV { ); if succ { - return Ok(UpsertTableOptionReply { - share_table_info: get_share_table_info_map(self, &table_meta).await?, - }); + return Ok(UpsertTableOptionReply {}); } } } @@ -2770,9 +2736,7 @@ impl + ?Sized> SchemaApi for KV { ); if succ { - return Ok(UpdateTableMetaReply { - share_table_info: get_share_table_info_map(self, &table_meta.unwrap()).await?, - }); + return Ok(UpdateTableMetaReply {}); } else { let resp = responses .first() @@ -3015,9 +2979,7 @@ impl + ?Sized> SchemaApi for KV { ); if succ { - return Ok(SetTableColumnMaskPolicyReply { - share_table_info: get_share_table_info_map(self, &new_table_meta).await?, - }); + return Ok(SetTableColumnMaskPolicyReply {}); } } } @@ -4017,7 +3979,7 @@ async fn construct_drop_table_txn_operations( if_delete: bool, condition: &mut Vec, if_then: &mut Vec, -) -> Result<(Option<(Vec, Vec)>, u64), KVAppError> { +) -> Result { let tbid = TableId { table_id }; // Check if table exists. @@ -4053,7 +4015,7 @@ async fn construct_drop_table_txn_operations( let (tb_id_seq, _) = get_u64_value(kv_api, &dbid_tbname).await?; if tb_id_seq == 0 { return if if_exists { - Ok((None, 0)) + Ok(0) } else { return Err(KVAppError::AppError(AppError::UnknownTable( UnknownTable::new(tbname, "drop_table_by_id"), @@ -4061,7 +4023,10 @@ async fn construct_drop_table_txn_operations( }; } - let (db_meta_seq, db_meta) = get_db_by_id_or_err(kv_api, db_id, "drop_table_by_id").await?; + let db_id_ident = DatabaseIdIdent::new(tenant, db_id); + + let (db_meta_seq, db_meta) = + get_db_by_id_or_err(kv_api, &db_id_ident, "drop_table_by_id").await?; // cannot operate on shared database if let Some(from_share) = db_meta.from_share { @@ -4091,14 +4056,17 @@ async fn construct_drop_table_txn_operations( // We guarantee there is no `(b)` so we do not have to assert db seq. condition.extend(vec![ // assert db_meta seq so that no other txn can delete this db - txn_cond_seq(&DatabaseId { db_id }, Eq, db_meta_seq), + txn_cond_seq(&DatabaseIdIdent::new(tenant, db_id), Eq, db_meta_seq), // table is not changed txn_cond_seq(&tbid, Eq, tb_meta_seq), ]); if_then.extend(vec![ // update db_meta seq so that no other txn can delete this db - txn_op_put(&DatabaseId { db_id }, serialize_struct(&db_meta)?), // (db_id) -> db_meta + txn_op_put( + &DatabaseIdIdent::new(tenant, db_id), + serialize_struct(&db_meta)?, + ), // (db_id) -> db_meta txn_op_put(&tbid, serialize_struct(&tb_meta)?), // (tenant, db_id, tb_id) -> tb_meta ]); if if_delete { @@ -4108,35 +4076,6 @@ async fn construct_drop_table_txn_operations( if_then.push(txn_op_del(&dbid_tbname)); } - // remove table from share - let mut spec_vec = Vec::with_capacity(db_meta.shared_by.len()); - let mut mut_share_table_info = Vec::with_capacity(db_meta.shared_by.len()); - for share_id in &db_meta.shared_by { - let res = - remove_table_from_share(kv_api, *share_id, table_id, tenant, condition, if_then).await; - - match res { - Ok((share_name, share_meta, share_table_info)) => { - spec_vec.push( - convert_share_meta_to_spec(kv_api, &share_name, *share_id, share_meta).await?, - ); - mut_share_table_info.push((share_name.to_string(), share_table_info)); - } - Err(e) => match e { - // ignore UnknownShareId error - KVAppError::AppError(AppError::UnknownShareId(_)) => { - error!( - "UnknownShareId {} when drop_table_by_id tenant:{} table_id:{} shared by", - share_id, - tenant.tenant_name(), - table_id - ); - } - _ => return Err(e), - }, - } - } - // add TableIdListKey if not exist if if_delete { // get table id list from _fd_table_id_list/db_id/table_name @@ -4162,11 +4101,8 @@ async fn construct_drop_table_txn_operations( )); } } - if spec_vec.is_empty() { - Ok((None, tb_id_seq)) - } else { - Ok((Some((spec_vec, mut_share_table_info)), tb_id_seq)) - } + + Ok(tb_id_seq) } async fn drop_database_meta( @@ -4176,7 +4112,9 @@ async fn drop_database_meta( drop_name_key: bool, condition: &mut Vec, if_then: &mut Vec, -) -> Result>, KVAppError> { +) -> Result<(), KVAppError> { + let tenant = tenant_dbname.tenant(); + let res = get_db_or_err( kv_api, tenant_dbname, @@ -4189,7 +4127,7 @@ async fn drop_database_meta( Err(e) => { if let KVAppError::AppError(AppError::UnknownDatabase(_)) = e { if if_exists { - return Ok(None); + return Ok(()); } } @@ -4203,121 +4141,54 @@ async fn drop_database_meta( if_then.push(txn_op_del(tenant_dbname)); // (tenant, db_name) -> db_id } - // remove db from share - let mut spec_vec = Vec::with_capacity(db_meta.shared_by.len()); - for share_id in &db_meta.shared_by { - let res = - remove_db_from_share(kv_api, *share_id, db_id, tenant_dbname, condition, if_then).await; + // Delete db by these operations: + // del (tenant, db_name) -> db_id + // set db_meta.drop_on = now and update (db_id) -> db_meta - match res { - Ok((share_name, share_meta)) => { - spec_vec.push( - convert_share_meta_to_spec(kv_api, &share_name, *share_id, share_meta).await?, - ); - } - Err(e) => match e { - // ignore UnknownShareId error - KVAppError::AppError(AppError::UnknownShareId(_)) => { - error!( - "UnknownShareId {} when drop_database {} shared by", - share_id, - tenant_dbname.display() - ); - } - _ => return Err(e), - }, - } - } - if !spec_vec.is_empty() { - db_meta.shared_by.clear(); - } - - let (removed, _from_share) = is_db_need_to_be_remove( - kv_api, - db_id, - // remove db directly if created from share - |db_meta| db_meta.from_share.is_some(), - condition, - if_then, - ) - .await?; - - if removed { - // if db create from share then remove it directly and remove db id from share - debug!( - name :? =(tenant_dbname), - id :? =(&DatabaseId { db_id }); - "drop_database from share" - ); + let db_id_key = DatabaseIdIdent::new(tenant, db_id); - // if remove db, MUST also removed db id from db id list - let dbid_idlist = - DatabaseIdHistoryIdent::new(tenant_dbname.tenant(), tenant_dbname.database_name()); - let (db_id_list_seq, db_id_list_opt): (_, Option) = - get_pb_value(kv_api, &dbid_idlist).await?; + debug!( + db_id = db_id, + name_key :? =(tenant_dbname); + "drop_database" + ); - let mut db_id_list = if db_id_list_seq == 0 { - DbIdList::new() - } else { - db_id_list_opt.unwrap_or(DbIdList::new()) - }; - if let Some(last_db_id) = db_id_list.last() { - if *last_db_id == db_id { - db_id_list.pop(); - condition.push(txn_cond_seq(&dbid_idlist, Eq, db_id_list_seq)); - if_then.push(txn_op_put(&dbid_idlist, serialize_struct(&db_id_list)?)); - } + { + // drop a table with drop time + if db_meta.drop_on.is_some() { + return Err(KVAppError::AppError(AppError::DropDbWithDropTime( + DropDbWithDropTime::new(tenant_dbname.database_name()), + ))); } - } else { - // Delete db by these operations: - // del (tenant, db_name) -> db_id - // set db_meta.drop_on = now and update (db_id) -> db_meta + // update drop on time + db_meta.drop_on = Some(Utc::now()); - let db_id_key = DatabaseId { db_id }; + condition.push(txn_cond_seq(&db_id_key, Eq, db_meta_seq)); - debug!( - db_id = db_id, - name_key :? =(tenant_dbname); - "drop_database" - ); - - { - // drop a table with drop time - if db_meta.drop_on.is_some() { - return Err(KVAppError::AppError(AppError::DropDbWithDropTime( - DropDbWithDropTime::new(tenant_dbname.database_name()), - ))); - } - // update drop on time - db_meta.drop_on = Some(Utc::now()); - - condition.push(txn_cond_seq(&db_id_key, Eq, db_meta_seq)); - - if_then.push(txn_op_put(&db_id_key, serialize_struct(&db_meta)?)); // (db_id) -> db_meta - } + if_then.push(txn_op_put(&db_id_key, serialize_struct(&db_meta)?)); // (db_id) -> db_meta + } - // add DbIdListKey if not exists - let dbid_idlist = - DatabaseIdHistoryIdent::new(tenant_dbname.tenant(), tenant_dbname.database_name()); - let (db_id_list_seq, db_id_list_opt): (_, Option) = - get_pb_value(kv_api, &dbid_idlist).await?; + // add DbIdListKey if not exists + let dbid_idlist = + DatabaseIdHistoryIdent::new(tenant_dbname.tenant(), tenant_dbname.database_name()); + let (db_id_list_seq, db_id_list_opt): (_, Option) = + get_pb_value(kv_api, &dbid_idlist).await?; - if db_id_list_seq == 0 || db_id_list_opt.is_none() { - warn!( - "drop db:{:?}, db_id:{:?} has no DbIdListKey", - tenant_dbname, db_id - ); + if db_id_list_seq == 0 || db_id_list_opt.is_none() { + warn!( + "drop db:{:?}, db_id:{:?} has no DbIdListKey", + tenant_dbname, db_id + ); - let mut db_id_list = DbIdList::new(); - db_id_list.append(db_id); + let mut db_id_list = DbIdList::new(); + db_id_list.append(db_id); - condition.push(txn_cond_seq(&dbid_idlist, Eq, db_id_list_seq)); - // _fd_db_id_list// -> db_id_list - if_then.push(txn_op_put(&dbid_idlist, serialize_struct(&db_id_list)?)); - }; - } + condition.push(txn_cond_seq(&dbid_idlist, Eq, db_id_list_seq)); + // _fd_db_id_list// -> db_id_list + if_then.push(txn_op_put(&dbid_idlist, serialize_struct(&db_id_list)?)); + }; - Ok(Some(spec_vec)) + Ok(()) } /// remove copied files for a table. @@ -4413,10 +4284,12 @@ pub(crate) async fn get_db_or_err( name_key: &DatabaseNameIdent, msg: impl Display, ) -> Result<(u64, u64, u64, DatabaseMeta), KVAppError> { + let tenant = name_key.tenant(); + let (db_id_seq, db_id) = get_u64_value(kv_api, name_key).await?; db_has_to_exist(db_id_seq, name_key, &msg)?; - let id_key = DatabaseId { db_id }; + let id_key = DatabaseIdIdent::new(tenant, db_id); let (db_meta_seq, db_meta) = get_pb_value(kv_api, &id_key).await?; db_has_to_exist(db_meta_seq, name_key, msg)?; @@ -4433,13 +4306,11 @@ pub(crate) async fn get_db_or_err( /// Returns (db_meta_seq, db_meta) pub(crate) async fn get_db_by_id_or_err( kv_api: &(impl kvapi::KVApi + ?Sized), - db_id: u64, + db_id_ident: &DatabaseIdIdent, msg: impl Display, ) -> Result<(u64, DatabaseMeta), KVAppError> { - let id_key = DatabaseId { db_id }; - - let (db_meta_seq, db_meta) = get_pb_value(kv_api, &id_key).await?; - db_id_has_to_exist(db_meta_seq, db_id, msg)?; + let (db_meta_seq, db_meta) = get_pb_value(kv_api, db_id_ident).await?; + db_id_has_to_exist(db_meta_seq, db_id_ident.database_id(), msg)?; Ok(( db_meta_seq, @@ -4489,98 +4360,6 @@ fn table_has_to_not_exist( } } -async fn get_share_table_info_map( - kv_api: &(impl kvapi::KVApi + ?Sized), - table_meta: &TableMeta, -) -> Result>, KVAppError> { - if table_meta.shared_by.is_empty() { - return Ok(None); - } - let mut share_table_info_map_vec = vec![]; - for share_id in &table_meta.shared_by { - let res = get_share_id_to_name_or_err( - kv_api, - *share_id, - format!("get_share_table_info_map: {}", share_id), - ) - .await; - - let (_seq, share_name) = match res { - Ok((seq, share_name)) => (seq, share_name), - Err(e) => match e { - // ignore UnknownShareId error - KVAppError::AppError(AppError::UnknownShareId(_)) => { - error!("UnknownShareId {} when get_share_table_info_map", share_id); - continue; - } - _ => return Err(e), - }, - }; - let res = get_share_meta_by_id_or_err( - kv_api, - *share_id, - format!("get_share_table_info_map: {}", share_id), - ) - .await; - - let (_share_meta_seq, share_meta) = match res { - Ok((seq, share_meta)) => (seq, share_meta), - Err(e) => match e { - // ignore UnknownShareId error - KVAppError::AppError(AppError::UnknownShareId(_)) => { - error!("UnknownShareId {} when get_share_table_info_map", share_id); - continue; - } - _ => return Err(e), - }, - }; - share_table_info_map_vec - .push(get_share_table_info(kv_api, &share_name.to_tident(()), &share_meta).await?); - } - - Ok(Some(share_table_info_map_vec)) -} - -async fn get_table_id_from_share_by_name( - kv_api: &(impl kvapi::KVApi + ?Sized), - share: &ShareNameIdent, - table_name: &String, -) -> Result { - let res = get_share_or_err( - kv_api, - share, - format!("list_tables_from_share_db: {}", share.display()), - ) - .await; - - let (share_id_seq, _share_id, _share_meta_seq, share_meta) = match res { - Ok(x) => x, - Err(e) => { - return Err(e); - } - }; - if share_id_seq == 0 { - return Err(KVAppError::AppError(AppError::WrongShare(WrongShare::new( - share.to_string_key(), - )))); - } - - let mut ids = Vec::with_capacity(share_meta.entries.len()); - for (_, entry) in share_meta.entries.iter() { - if let ShareGrantObject::Table(table_id) = entry.object { - ids.push(table_id); - } - } - - let table_names = get_table_names_by_ids(kv_api, &ids).await?; - match table_names.binary_search(table_name) { - Ok(i) => Ok(ids[i]), - Err(_) => Err(KVAppError::AppError(AppError::WrongShareObject( - WrongShareObject::new(table_name.to_string()), - ))), - } -} - fn build_upsert_table_copied_file_info_conditions( table_id: &TableId, req: &UpsertTableCopiedFileReq, @@ -4898,13 +4677,15 @@ async fn gc_dropped_db_by_id( if *dbid != db_id { continue; } - let dbid = DatabaseId { db_id }; + + let db_id_ident = DatabaseIdIdent::new(tenant, db_id); + let (db_meta_seq, _db_meta): (_, Option) = - get_pb_value(kv_api, &dbid).await?; + get_pb_value(kv_api, &db_id_ident).await?; if db_meta_seq == 0 { return Ok(()); } - let id_to_name = DatabaseIdToName { db_id }; + let id_to_name = DatabaseIdToNameIdent::new(tenant, db_id); let (name_ident_seq, _name_ident): (_, Option) = get_pb_value(kv_api, &id_to_name).await?; if name_ident_seq == 0 { @@ -4967,8 +4748,8 @@ async fn gc_dropped_db_by_id( if_then.push(txn_op_put(&dbid_idlist, serialize_struct(&db_id_list)?)); } - condition.push(txn_cond_seq(&dbid, Eq, db_meta_seq)); - if_then.push(txn_op_del(&dbid)); + condition.push(txn_cond_seq(&db_id_ident, Eq, db_meta_seq)); + if_then.push(txn_op_del(&db_id_ident)); condition.push(txn_cond_seq(&id_to_name, Eq, name_ident_seq)); if_then.push(txn_op_del(&id_to_name)); @@ -5345,14 +5126,15 @@ impl UndropTableStrategy for UndropTableByIdReq { fn force_replace(&self) -> bool { self.force_replace } + async fn refresh_target_db_meta<'a>( &'a self, kv_api: &'a (impl kvapi::KVApi + ?Sized), ) -> Result<(u64, u64, DatabaseMeta), KVAppError> { // for un-drop table by id, database meta is refreshed by database id let (db_meta_seq, db_meta) = - get_db_by_id_or_err(kv_api, self.db_id, "undrop_table_by_id").await?; - Ok((self.db_id, db_meta_seq, db_meta)) + get_db_by_id_or_err(kv_api, &self.db_id_ident, "undrop_table_by_id").await?; + Ok((self.db_id_ident.database_id(), db_meta_seq, db_meta)) } fn extract_and_validate_table_id( @@ -5377,6 +5159,8 @@ async fn handle_undrop_table( ) -> Result { let tenant_dbname_tbname = req.table_name_ident(); + let tenant = tenant_dbname_tbname.tenant(); + let mut trials = txn_backoff(None, func_name!()); loop { trials.next().unwrap()?.await; @@ -5456,7 +5240,7 @@ async fn handle_undrop_table( condition: vec![ // db has not to change, i.e., no new table is created. // Renaming db is OK and does not affect the seq of db_meta. - txn_cond_seq(&DatabaseId { db_id }, Eq, db_meta_seq), + txn_cond_seq(&DatabaseIdIdent::new(tenant, db_id), Eq, db_meta_seq), // still this table id txn_cond_seq(&dbid_tbname, Eq, dbid_tbname_seq), // table is not changed @@ -5465,7 +5249,10 @@ async fn handle_undrop_table( if_then: vec![ // Changing a table in a db has to update the seq of db_meta, // to block the batch-delete-tables when deleting a db. - txn_op_put(&DatabaseId { db_id }, serialize_struct(&db_meta)?), /* (db_id) -> db_meta */ + txn_op_put( + &DatabaseIdIdent::new(tenant, db_id), + serialize_struct(&db_meta)?, + ), // (db_id) -> db_meta txn_op_put(&dbid_tbname, serialize_u64(table_id)?), /* (tenant, db_id, tb_name) -> tb_id */ // txn_op_put(&dbid_tbname_idlist, serialize_struct(&tb_id_list)?)?, // _fd_table_id_list/db_id/table_name -> tb_id_list txn_op_put(&tbid, serialize_struct(&tb_meta)?), /* (tenant, db_id, tb_id) -> tb_meta */ diff --git a/src/meta/api/src/schema_api_test_suite.rs b/src/meta/api/src/schema_api_test_suite.rs index 236c5110d03a..c0a6eb52cf54 100644 --- a/src/meta/api/src/schema_api_test_suite.rs +++ b/src/meta/api/src/schema_api_test_suite.rs @@ -50,12 +50,11 @@ use databend_common_meta_app::schema::CreateTableIndexReq; use databend_common_meta_app::schema::CreateTableReq; use databend_common_meta_app::schema::CreateVirtualColumnReq; use databend_common_meta_app::schema::DBIdTableName; -use databend_common_meta_app::schema::DatabaseId; use databend_common_meta_app::schema::DatabaseIdHistoryIdent; -use databend_common_meta_app::schema::DatabaseIdToName; +use databend_common_meta_app::schema::DatabaseIdIdent; +use databend_common_meta_app::schema::DatabaseIdToNameIdent; use databend_common_meta_app::schema::DatabaseInfo; use databend_common_meta_app::schema::DatabaseMeta; -use databend_common_meta_app::schema::DatabaseType; use databend_common_meta_app::schema::DbIdList; use databend_common_meta_app::schema::DeleteLockRevReq; use databend_common_meta_app::schema::DropCatalogReq; @@ -119,12 +118,6 @@ use databend_common_meta_app::schema::UpdateVirtualColumnReq; use databend_common_meta_app::schema::UpsertTableCopiedFileReq; use databend_common_meta_app::schema::UpsertTableOptionReq; use databend_common_meta_app::schema::VirtualColumnIdent; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::AddShareAccountsReq; -use databend_common_meta_app::share::CreateShareReq; -use databend_common_meta_app::share::GrantShareObjectReq; -use databend_common_meta_app::share::ShareGrantObjectName; -use databend_common_meta_app::share::ShareGrantObjectPrivilege; use databend_common_meta_app::storage::StorageParams; use databend_common_meta_app::storage::StorageS3Config; use databend_common_meta_app::tenant::Tenant; @@ -137,20 +130,19 @@ use databend_common_meta_types::MatchSeq; use databend_common_meta_types::MetaError; use databend_common_meta_types::Operation; use databend_common_meta_types::UpsertKV; +use databend_common_proto_conv::FromToProto; use log::debug; use log::info; use minitrace::func_name; use crate::deserialize_struct; -use crate::is_all_db_data_removed; use crate::kv_app_error::KVAppError; -use crate::serialize_struct; +use crate::kv_pb_api::KVPbApi; use crate::testing::get_kv_data; use crate::testing::get_kv_u64_data; use crate::DatamaskApi; use crate::SchemaApi; use crate::SequenceApi; -use crate::ShareApi; use crate::DEFAULT_MGET_SIZE; /// Test suite of `SchemaApi`. @@ -241,20 +233,16 @@ fn calc_and_compare_drop_on_table_result(result: Vec>, expected: assert_eq!(get, expected_map); } -async fn upsert_test_data( +async fn upsert_test_data( kv_api: &(impl kvapi::KVApi + ?Sized), - key: &impl kvapi::Key, - value: Vec, -) -> Result { - let res = kv_api - .upsert_kv(UpsertKVReq { - key: key.to_string_key(), - seq: MatchSeq::GE(0), - value: Operation::Update(value), - value_meta: None, - }) - .await?; - + key: K, + value: K::ValueType, +) -> Result +where + K: kvapi::Key + Send + 'static, + K::ValueType: FromToProto + Send, +{ + let res = kv_api.update_pb(key, value).await?; let seq_v = res.result.unwrap(); Ok(seq_v.seq) } @@ -280,15 +268,12 @@ impl SchemaApiTestSuite { pub async fn test_single_node(b: B) -> anyhow::Result<()> where B: kvapi::ApiBuilder, - MT: ShareApi + kvapi::AsKVApi + SchemaApi + DatamaskApi + SequenceApi, + MT: kvapi::AsKVApi + SchemaApi + DatamaskApi + SequenceApi, { let suite = SchemaApiTestSuite {}; suite.database_and_table_rename(&b.build().await).await?; suite.database_create_get_drop(&b.build().await).await?; - suite - .database_create_from_share_and_drop(&b.build().await) - .await?; suite .database_create_get_drop_in_diff_tenant(&b.build().await) .await?; @@ -338,7 +323,7 @@ impl SchemaApiTestSuite { suite.get_table_by_id(&b.build().await).await?; suite.get_table_copied_file(&b.build().await).await?; suite.truncate_table(&b.build().await).await?; - suite.get_tables_from_share(&b.build().await).await?; + suite .update_table_with_copied_files(&b.build().await) .await?; @@ -485,7 +470,7 @@ impl SchemaApiTestSuite { let res = mt.create_table(req).await?; table_id = res.table_id; - let db_id_name_key = DatabaseIdToName { db_id }; + let db_id_name_key = DatabaseIdToNameIdent::new(&tenant, db_id); let ret_db_name_ident: DatabaseNameIdentRaw = get_kv_data(mt.as_kv_api(), &db_id_name_key).await?; assert_eq!( @@ -513,7 +498,7 @@ impl SchemaApiTestSuite { info!("rename database res: {:?}", res); assert!(res.is_ok()); - let db_id_2_name_key = DatabaseIdToName { db_id }; + let db_id_2_name_key = DatabaseIdToNameIdent::new(&tenant, db_id); let ret_db_name_ident: DatabaseNameIdentRaw = get_kv_data(mt.as_kv_api(), &db_id_2_name_key).await?; assert_eq!( @@ -739,7 +724,7 @@ impl SchemaApiTestSuite { let orig_db_id: u64 = get_kv_u64_data(mt.as_kv_api(), &db_name).await?; assert_eq!(orig_db_id, res.ident.db_id); - let db_id_name_key = DatabaseIdToName { db_id: orig_db_id }; + let db_id_name_key = DatabaseIdToNameIdent::new(&tenant, orig_db_id); let ret_db_name_ident: DatabaseNameIdentRaw = get_kv_data(mt.as_kv_api(), &db_id_name_key).await?; assert_eq!(ret_db_name_ident, DatabaseNameIdentRaw::from(&db_name)); @@ -763,7 +748,7 @@ impl SchemaApiTestSuite { let db_id: u64 = get_kv_u64_data(mt.as_kv_api(), &db_name).await?; assert_eq!(db_id, res.ident.db_id); - let db_id_name_key = DatabaseIdToName { db_id }; + let db_id_name_key = DatabaseIdToNameIdent::new(&tenant, db_id); let ret_db_name_ident: DatabaseNameIdentRaw = get_kv_data(mt.as_kv_api(), &db_id_name_key).await?; assert_eq!(ret_db_name_ident, DatabaseNameIdentRaw::from(&db_name)); @@ -773,69 +758,6 @@ impl SchemaApiTestSuite { Ok(()) } - #[minitrace::trace] - async fn database_create_from_share_and_drop< - MT: ShareApi + kvapi::AsKVApi + SchemaApi, - >( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant_name1 = "tenant1"; - let tenant = Tenant::new_or_err(tenant_name1, func_name!())?; - let db1 = "db1"; - let share = "share"; - let share_name = ShareNameIdent::new(&tenant, share); - let db_name1 = DatabaseNameIdent::new(&tenant, db1); - - let db_id; - - info!("--- create a share and tenant1 create db1 from a share"); - { - let req = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: db_name1.clone(), - meta: DatabaseMeta { - from_share: Some(share_name.clone().into()), - ..Default::default() - }, - }; - - let res = mt.create_database(req).await; - info!("create database res: {:?}", res); - - assert!(res.is_ok()); - // save the db id - db_id = res.unwrap().db_id; - }; - - // drop database created from share - { - mt.drop_database(DropDatabaseReq { - if_exists: false, - name_ident: db_name1.clone(), - }) - .await?; - - // check that DatabaseMeta has been removed - let res = is_all_db_data_removed(mt.as_kv_api(), db_id).await?; - assert!(res); - - // db has been removed, so undrop_database MUST return error - let res = mt - .undrop_database(UndropDatabaseReq { - name_ident: db_name1.clone(), - }) - .await; - assert!(res.is_err()); - assert_eq!( - ErrorCode::UNDROP_DB_HAS_NO_HISTORY, - ErrorCode::from(res.unwrap_err()).code() - ); - } - - Ok(()) - } - #[minitrace::trace] async fn database_create_get_drop_in_diff_tenant( &self, @@ -1993,7 +1915,7 @@ impl SchemaApiTestSuite { { let undrop_table_req = UndropTableByIdReq { name_ident: create_table_req.name_ident.clone(), - db_id: create_table_as_dropped_resp.db_id, + db_id_ident: create_table_as_dropped_resp.database_id_ident.clone(), table_id: create_table_as_dropped_resp.table_id, table_id_seq: create_table_as_dropped_resp.table_id_seq.unwrap(), force_replace: true, @@ -2012,7 +1934,7 @@ impl SchemaApiTestSuite { // undrop-table-by-id with force_replace set to false should fail. let undrop_table_req = UndropTableByIdReq { name_ident: create_table_req.name_ident.clone(), - db_id: create_table_as_dropped_resp.db_id, + db_id_ident: create_table_as_dropped_resp.database_id_ident.clone(), table_id: create_table_as_dropped_resp.table_id, table_id_seq: create_table_as_dropped_resp.table_id_seq.unwrap(), force_replace: false, @@ -2116,7 +2038,7 @@ impl SchemaApiTestSuite { info!("--- drop db-id-to-name mapping to ensure dropping table does not rely on it"); { - let id_to_name_key = DatabaseIdToName { db_id: util.db_id }; + let id_to_name_key = DatabaseIdToNameIdent::new(&util.tenant, util.db_id); util.mt .as_kv_api() .upsert_kv(UpsertKV::delete(id_to_name_key.to_string_key())) @@ -3338,9 +3260,9 @@ impl SchemaApiTestSuite { drop_on, ..Default::default() }; - let id_key = DatabaseId { db_id }; - let data = serialize_struct(&drop_data)?; - upsert_test_data(mt.as_kv_api(), &id_key, data).await?; + + let db_id_ident = DatabaseIdIdent::new(&tenant, db_id); + upsert_test_data(mt.as_kv_api(), db_id_ident, drop_data).await?; let res = mt .get_database_history(ListDatabaseReq { @@ -3384,9 +3306,8 @@ impl SchemaApiTestSuite { drop_on, ..Default::default() }; - let id_key = DatabaseId { db_id }; - let data = serialize_struct(&drop_data)?; - upsert_test_data(mt.as_kv_api(), &id_key, data).await?; + let id_key = DatabaseIdIdent::new(db_name.tenant(), db_id); + upsert_test_data(mt.as_kv_api(), id_key, drop_data).await?; if delete { delete_test_data(mt.as_kv_api(), &db_name).await?; @@ -3462,8 +3383,8 @@ impl SchemaApiTestSuite { // assert old db meta and id to name mapping has been removed for db_id in old_id_list.iter() { - let id_key = DatabaseId { db_id: *db_id }; - let id_mapping = DatabaseIdToName { db_id: *db_id }; + let id_key = DatabaseIdIdent::new(&tenant, *db_id); + let id_mapping = DatabaseIdToNameIdent::new(&tenant, *db_id); let meta_res: Result = get_kv_data(mt.as_kv_api(), &id_key).await; @@ -3527,8 +3448,7 @@ impl SchemaApiTestSuite { }; let id_key = TableId { table_id }; - let data = serialize_struct(&drop_data)?; - upsert_test_data(mt.as_kv_api(), &id_key, data).await?; + upsert_test_data(mt.as_kv_api(), id_key, drop_data.clone()).await?; if delete { delete_test_data(mt.as_kv_api(), &dbid_tbname).await?; @@ -3806,9 +3726,8 @@ impl SchemaApiTestSuite { drop_on, ..Default::default() }; - let id_key = DatabaseId { db_id }; - let data = serialize_struct(&drop_data)?; - upsert_test_data(mt.as_kv_api(), &id_key, data).await?; + let id_key = DatabaseIdIdent::new(&tenant, db_id); + upsert_test_data(mt.as_kv_api(), id_key, drop_data).await?; let dbid_idlist1 = DatabaseIdHistoryIdent::new(&tenant, db1_name); let old_id_list: DbIdList = get_kv_data(mt.as_kv_api(), &dbid_idlist1).await?; @@ -3847,8 +3766,8 @@ impl SchemaApiTestSuite { // assert old db meta and id to name mapping has been removed for db_id in old_id_list.id_list.iter() { - let id_key = DatabaseId { db_id: *db_id }; - let id_mapping = DatabaseIdToName { db_id: *db_id }; + let id_key = DatabaseIdIdent::new(&tenant, *db_id); + let id_mapping = DatabaseIdToNameIdent::new(&tenant, *db_id); let meta_res: Result = get_kv_data(mt.as_kv_api(), &id_key).await; @@ -3989,9 +3908,8 @@ impl SchemaApiTestSuite { drop_on: Some(created_on - Duration::days(1)), ..TableMeta::default() }; - let data = serialize_struct(&create_drop_table_meta)?; - upsert_test_data(mt.as_kv_api(), &tbid, data).await?; + upsert_test_data(mt.as_kv_api(), tbid, create_drop_table_meta).await?; // assert not return out of retention time data let res = mt .get_table_history(ListTableReq::new(&tenant, db_name)) @@ -4145,8 +4063,7 @@ impl SchemaApiTestSuite { let table_id = resp.table_id; let id_key = TableId { table_id }; table_meta.drop_on = Some(created_on + Duration::seconds(100)); - let data = serialize_struct(&table_meta)?; - upsert_test_data(mt.as_kv_api(), &id_key, data).await?; + upsert_test_data(mt.as_kv_api(), id_key, table_meta).await?; } info!("--- create db2.tb3"); @@ -4173,9 +4090,8 @@ impl SchemaApiTestSuite { // change db meta to make this db drop time outof filter time let mut drop_db_meta = create_db_req.meta.clone(); drop_db_meta.drop_on = Some(created_on + Duration::seconds(100)); - let id_key = DatabaseId { db_id }; - let data = serialize_struct(&drop_db_meta)?; - upsert_test_data(mt.as_kv_api(), &id_key, data).await?; + let id_key = DatabaseIdIdent::new(&tenant, db_id); + upsert_test_data(mt.as_kv_api(), id_key, drop_db_meta).await?; } // third create a database not dropped, but has a table drop within filter time @@ -4245,8 +4161,7 @@ impl SchemaApiTestSuite { let table_id = resp.table_id; let id_key = TableId { table_id }; table_meta.drop_on = Some(created_on + Duration::seconds(100)); - let data = serialize_struct(&table_meta)?; - upsert_test_data(mt.as_kv_api(), &id_key, data).await?; + upsert_test_data(mt.as_kv_api(), id_key, table_meta).await?; } info!("--- create db3.tb3"); @@ -5066,7 +4981,9 @@ impl SchemaApiTestSuite { assert_eq!(1, res.db_id, "first database id is 1"); - let got = mt.get_db_name_by_id(res.db_id).await?; + let got = mt + .get_db_name_by_id(DatabaseIdIdent::new(&tenant, res.db_id)) + .await?; assert_eq!(got, db_name.to_string()) } @@ -5080,14 +4997,18 @@ impl SchemaApiTestSuite { let db = mt.get_database(plan).await.unwrap(); - let got = mt.get_db_name_by_id(db.ident.db_id).await?; + let got = mt + .get_db_name_by_id(DatabaseIdIdent::new(&tenant, db.ident.db_id)) + .await?; assert_eq!(got, db_name.to_string()); } info!("--- get_db_name_by_id with not exists db_id"); { - let got = mt.get_db_name_by_id(1024).await; + let got = mt + .get_db_name_by_id(DatabaseIdIdent::new(&tenant, 1024)) + .await; let err = got.unwrap_err(); let err = ErrorCode::from(err); @@ -5373,162 +5294,6 @@ impl SchemaApiTestSuite { Ok(()) } - async fn get_tables_from_share + SchemaApi>( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant_name1 = "tenant1"; - let tenant1 = Tenant::new_or_err(tenant_name1, func_name!())?; - let tenant_name2 = "tenant1"; - let tenant2 = Tenant::new_or_err(tenant_name2, func_name!())?; - - let db1 = "db1"; - let db2 = "db2"; - let share = "share"; - let tb1 = "tb1"; - let tb2 = "tb2"; - let share_name = ShareNameIdent::new(&tenant1, share); - let db_name1 = DatabaseNameIdent::new(&tenant1, db1); - let db_name2 = DatabaseNameIdent::new(&tenant2, db2); - let tb_name1 = TableNameIdent { - tenant: tenant1.clone(), - db_name: db1.to_string(), - table_name: tb1.to_string(), - }; - let tb_name2 = TableNameIdent { - tenant: tenant1.clone(), - db_name: db1.to_string(), - table_name: tb2.to_string(), - }; - let tb_names = vec![&tb_name1, &tb_name2]; - let mut share_table_id = 0; - - info!("--- create a share and grant access to db and table"); - { - let create_on = Utc::now(); - let share_on = Utc::now(); - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name.clone(), - comment: None, - create_on, - }; - - let _ = mt.create_share(req).await?; - - // create share db - let req = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: db_name1.clone(), - meta: DatabaseMeta { - ..Default::default() - }, - }; - let _ = mt.create_database(req).await?; - - // create share table - let schema = || { - Arc::new(TableSchema::new(vec![TableField::new( - "number", - TableDataType::Number(NumberDataType::UInt64), - )])) - }; - let table_meta = |created_on| TableMeta { - schema: schema(), - engine: "JSON".to_string(), - options: BTreeMap::new(), - updated_on: created_on, - created_on, - ..TableMeta::default() - }; - for tb_name in tb_names { - let req = CreateTableReq { - create_option: CreateOption::Create, - name_ident: tb_name.clone(), - table_meta: table_meta(create_on), - as_dropped: false, - }; - let res = mt.create_table(req).await?; - if tb_name == &tb_name1 { - share_table_id = res.table_id; - } - } - - // grant the tenant2 to access the share - let req = AddShareAccountsReq { - share_name: share_name.clone(), - share_on, - if_exists: false, - accounts: vec![tenant_name2.to_string()], - }; - - let res = mt.add_share_tenants(req).await; - assert!(res.is_ok()); - - // grant access to database and table1 - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Database(db1.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - let _ = mt.grant_share_object(req).await?; - - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Table(db1.to_string(), tb1.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Select, - }; - let _ = mt.grant_share_object(req).await?; - } - - info!("--- create a share db"); - { - let req = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: db_name2.clone(), - meta: DatabaseMeta { - from_share: Some(share_name.clone().into()), - ..Default::default() - }, - }; - let _ = mt.create_database(req).await?; - }; - - info!("--- list tables from share db"); - { - let res = mt.list_tables(ListTableReq::new(&tenant2, db2)).await; - assert!(res.is_ok()); - let res = res.unwrap(); - assert_eq!(res.len(), 1); - // since share has not grant access to tb2, so list tables only return tb1. - let table_info = &res[0]; - assert_eq!(table_info.name, tb1.to_string()); - assert_eq!(table_info.ident.table_id, share_table_id); - assert_eq!(table_info.tenant, tenant_name2.to_string()); - assert_eq!(table_info.db_type, DatabaseType::ShareDB(share_name.into())); - } - - info!("--- get tables from share db"); - { - let got = mt.get_table((tenant_name2, db2, tb1).into()).await; - assert!(got.is_ok()); - let got = got.unwrap(); - assert_eq!(got.ident.table_id, share_table_id); - assert_eq!(got.name, tb1.to_string()); - - let got = mt.get_table((tenant_name2, db2, tb2).into()).await; - assert!(got.is_err()); - assert_eq!( - ErrorCode::from(got.unwrap_err()).code(), - ErrorCode::WRONG_SHARE_OBJECT - ); - } - - Ok(()) - } - #[minitrace::trace] async fn table_list(&self, mt: &MT) -> anyhow::Result<()> { let tenant_name = "tenant1"; diff --git a/src/meta/api/src/share_api.rs b/src/meta/api/src/share_api.rs deleted file mode 100644 index ccce4f5d8483..000000000000 --- a/src/meta/api/src/share_api.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use databend_common_meta_app::share::*; - -use crate::kv_app_error::KVAppError; - -#[async_trait::async_trait] -pub trait ShareApi: Sync + Send { - async fn show_shares(&self, req: ShowSharesReq) -> Result; - async fn create_share(&self, req: CreateShareReq) -> Result; - - async fn drop_share(&self, req: DropShareReq) -> Result; - - async fn grant_share_object( - &self, - req: GrantShareObjectReq, - ) -> Result; - async fn revoke_share_object( - &self, - req: RevokeShareObjectReq, - ) -> Result; - - async fn add_share_tenants( - &self, - req: AddShareAccountsReq, - ) -> Result; - async fn remove_share_tenants( - &self, - req: RemoveShareAccountsReq, - ) -> Result; - - async fn get_share_grant_objects( - &self, - req: GetShareGrantObjectReq, - ) -> Result; - - // Return all the grant tenants of the share - async fn get_grant_tenants_of_share( - &self, - req: GetShareGrantTenantsReq, - ) -> Result; - - // Return all the grant privileges of the object - async fn get_grant_privileges_of_object( - &self, - req: GetObjectGrantPrivilegesReq, - ) -> Result; - - async fn create_share_endpoint( - &self, - req: CreateShareEndpointReq, - ) -> Result; - - async fn upsert_share_endpoint( - &self, - req: UpsertShareEndpointReq, - ) -> Result; - - async fn get_share_endpoint( - &self, - req: GetShareEndpointReq, - ) -> Result; - - async fn drop_share_endpoint( - &self, - req: DropShareEndpointReq, - ) -> Result; -} diff --git a/src/meta/api/src/share_api_impl.rs b/src/meta/api/src/share_api_impl.rs deleted file mode 100644 index 4475c0a52c44..000000000000 --- a/src/meta/api/src/share_api_impl.rs +++ /dev/null @@ -1,1881 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use chrono::DateTime; -use chrono::Utc; -use databend_common_meta_app::app_error::AppError; -use databend_common_meta_app::app_error::CannotShareDatabaseCreatedFromShare; -use databend_common_meta_app::app_error::ShareAccountsAlreadyExists; -use databend_common_meta_app::app_error::ShareAlreadyExists; -use databend_common_meta_app::app_error::ShareEndpointAlreadyExists; -use databend_common_meta_app::app_error::UnknownShare; -use databend_common_meta_app::app_error::UnknownShareAccounts; -use databend_common_meta_app::app_error::UnknownTable; -use databend_common_meta_app::app_error::WrongShare; -use databend_common_meta_app::app_error::WrongShareObject; -use databend_common_meta_app::id_generator::IdGenerator; -use databend_common_meta_app::schema::database_name_ident::DatabaseNameIdent; -use databend_common_meta_app::schema::database_name_ident::DatabaseNameIdentRaw; -use databend_common_meta_app::schema::CreateOption; -use databend_common_meta_app::schema::DBIdTableName; -use databend_common_meta_app::schema::DatabaseId; -use databend_common_meta_app::schema::DatabaseIdToName; -use databend_common_meta_app::schema::DatabaseMeta; -use databend_common_meta_app::schema::TableId; -use databend_common_meta_app::schema::TableIdToName; -use databend_common_meta_app::schema::TableMeta; -use databend_common_meta_app::schema::TableNameIdent; -use databend_common_meta_app::share::share_end_point_ident::ShareEndpointIdentRaw; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::*; -use databend_common_meta_app::tenant::Tenant; -use databend_common_meta_app::KeyWithTenant; -use databend_common_meta_kvapi::kvapi; -use databend_common_meta_kvapi::kvapi::DirName; -use databend_common_meta_types::ConditionResult::Eq; -use databend_common_meta_types::MetaError; -use databend_common_meta_types::TxnCondition; -use databend_common_meta_types::TxnOp; -use databend_common_meta_types::TxnRequest; -use log::debug; -use log::error; -use minitrace::func_name; - -use crate::assert_table_exist; -use crate::convert_share_meta_to_spec; -use crate::db_has_to_exist; -use crate::fetch_id; -use crate::get_db_or_err; -use crate::get_object_shared_by_share_ids; -use crate::get_pb_value; -use crate::get_share_account_meta_or_err; -use crate::get_share_id_to_name_or_err; -use crate::get_share_meta_by_id_or_err; -use crate::get_share_or_err; -use crate::get_share_table_info; -use crate::get_u64_value; -use crate::kv_app_error::KVAppError; -use crate::list_keys; -use crate::send_txn; -use crate::serialize_struct; -use crate::serialize_u64; -use crate::txn_backoff::txn_backoff; -use crate::txn_cond_seq; -use crate::txn_op_del; -use crate::txn_op_put; -use crate::util::get_share_endpoint_id_to_name_or_err; -use crate::util::get_share_endpoint_or_err; -use crate::ShareApi; - -/// ShareApi is implemented upon kvapi::KVApi. -/// Thus every type that impl kvapi::KVApi impls ShareApi. -#[async_trait::async_trait] -impl> ShareApi for KV { - #[logcall::logcall("debug")] - #[minitrace::trace] - async fn show_shares(&self, req: ShowSharesReq) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - // Get all outbound share accounts. - let outbound_accounts = get_outbound_share_infos_by_tenant(self, &req.tenant).await?; - - Ok(ShowSharesReply { outbound_accounts }) - } - - #[logcall::logcall("debug")] - #[minitrace::trace] - async fn create_share(&self, req: CreateShareReq) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let name_key = &req.share_name; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - // Get share by name to ensure absence - let (share_id_seq, share_id) = get_u64_value(self, name_key).await?; - debug!(share_id_seq = share_id_seq, share_id = share_id, name_key :? =(name_key); "get_share"); - - if share_id_seq > 0 { - return if req.if_not_exists { - Ok(CreateShareReply { - share_id, - spec_vec: None, - }) - } else { - Err(KVAppError::AppError(AppError::ShareAlreadyExists( - ShareAlreadyExists::new( - name_key.name(), - format!("create share: tenant: {}", name_key.tenant_name()), - ), - ))) - }; - } - - // Create share by inserting these record: - // (tenant, share_name) -> share_id - // (share_id) -> share_meta - // (share) -> (tenant,share_name) - - let share_id = fetch_id(self, IdGenerator::share_id()).await?; - let id_key = ShareId { share_id }; - let id_to_name_key = ShareIdToName { share_id }; - - debug!(share_id = share_id, name_key :? =(name_key); "new share id"); - - // Create share by transaction. - { - let share_meta = ShareMeta::new(req.create_on, req.comment.clone()); - let txn_req = TxnRequest { - condition: vec![ - txn_cond_seq(name_key, Eq, 0), - txn_cond_seq(&id_to_name_key, Eq, 0), - ], - if_then: vec![ - txn_op_put(name_key, serialize_u64(share_id)?), /* (tenant, share_name) -> share_id */ - txn_op_put(&id_key, serialize_struct(&share_meta)?), /* (share_id) -> share_meta */ - txn_op_put(&id_to_name_key, serialize_struct(&name_key.to_raw())?), /* __fd_share_id_to_name/ -> (tenant,share_name) */ - ], - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - debug!( - name :? =(name_key) , - id :? =(&id_key), - succ = succ; - "create_share" - ); - - if succ { - return Ok(CreateShareReply { - share_id, - spec_vec: Some(get_tenant_share_spec_vec(self, name_key.tenant()).await?), - }); - } - } - } - } - - // When drop a share, need to: - // drop __fd_share// -> - // drop __fd_share_id/ -> - // drop __fd_share_id_to_name/ -> ShareNameIdent - // iterator all the granted accounts(from ShareMeta.accounts), - // drop __fd_share_account/tenant/id -> ShareAccountMeta - // iterator all the granted objects(from ShareMeta.{database|entries}), - // remove share id from ObjectSharedByShareIds - // drop all the databases created from the share(from ShareMeta.share_from_db_ids), - async fn drop_share(&self, req: DropShareReq) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let name_key = &req.share_name; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - let res = get_share_or_err( - self, - name_key, - format!("drop_share: {}", name_key.display()), - ) - .await; - - let (share_id_seq, share_id, share_meta_seq, share_meta) = match res { - Ok(x) => x, - Err(e) => { - if let KVAppError::AppError(AppError::UnknownShare(_)) = e { - if req.if_exists { - return Ok(DropShareReply { - share_id: None, - spec_vec: None, - }); - } - } - - return Err(e); - } - }; - - let res = get_share_id_to_name_or_err( - self, - share_id, - format!("drop_share: {}", name_key.display()), - ) - .await; - let (share_name_seq, _share_name) = match res { - Ok(x) => x, - Err(e) => { - if let KVAppError::AppError(AppError::UnknownShareId(_)) = e { - if req.if_exists { - return Ok(DropShareReply { - share_id: Some(share_id), - spec_vec: None, - }); - } - } - - return Err(e); - } - }; - - // Delete share by these operations: - // del (tenant, share_name) - // del share_id - // del (share_id) -> (tenant, share_name) - // del all outbound of share - // remove share id from share object metas - // drop the database created from share - - let mut condition = vec![]; - let mut if_then = vec![]; - - // drop all accounts seq from share_meta - drop_accounts_granted_from_share( - self, - share_id, - &share_meta, - &mut condition, - &mut if_then, - ) - .await?; - - // remove share id from the share objects - remove_share_id_from_share_objects( - self, - share_id, - &share_meta, - &mut condition, - &mut if_then, - ) - .await?; - - // drop all the databases created from the share - // drop_all_database_from_share(self, share_id, &share_meta, &mut condition, &mut if_then) - // .await?; - - let share_id_key = ShareId { share_id }; - let id_name_key = ShareIdToName { share_id }; - - debug!(share_id = share_id, name_key :? =(name_key); "drop_share"); - - { - condition.push(txn_cond_seq(name_key, Eq, share_id_seq)); - condition.push(txn_cond_seq(&share_id_key, Eq, share_meta_seq)); - condition.push(txn_cond_seq(&id_name_key, Eq, share_name_seq)); - if_then.push(txn_op_del(name_key)); // del (tenant, share_name) - if_then.push(txn_op_del(&share_id_key)); // del share_id - if_then.push(txn_op_del(&id_name_key)); // del (share_id) -> (tenant, share_name) - - let txn_req = TxnRequest { - condition, - if_then, - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - debug!( - name :? =(name_key) , - id :? =(&share_id_key), - succ = succ; - "drop_share" - ); - - if succ { - return Ok(DropShareReply { - share_id: Some(share_id), - spec_vec: Some(get_tenant_share_spec_vec(self, name_key.tenant()).await?), - }); - } - } - } - } - - async fn add_share_tenants( - &self, - req: AddShareAccountsReq, - ) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let name_key = &req.share_name; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - let res = get_share_or_err( - self, - name_key, - format!("add_share_tenants: {}", name_key.display()), - ) - .await; - - let (share_id_seq, share_id, share_meta_seq, mut share_meta) = match res { - Ok(x) => x, - Err(e) => { - if let KVAppError::AppError(AppError::UnknownShare(_)) = e { - if req.if_exists { - return Ok(AddShareAccountsReply { - share_id: None, - spec_vec: None, - }); - } - } - return Err(e); - } - }; - - let mut add_share_account_keys = vec![]; - for account in req.accounts.iter() { - if !share_meta.has_account(account) { - add_share_account_keys.push(ShareConsumerIdent::new( - Tenant::new_or_err(account, "add_share_tenants")?, - share_id, - )); - } - } - if add_share_account_keys.is_empty() { - return Err(KVAppError::AppError(AppError::ShareAccountsAlreadyExists( - ShareAccountsAlreadyExists::new( - req.share_name.name(), - &req.accounts, - "share accounts already exists", - ), - ))); - } - - // Add share account by these operations: - // mod share_meta add account - // add (account, share_id) -> share_account_meta - // return share_id - { - let id_key = ShareId { share_id }; - let mut condition = vec![ - txn_cond_seq(name_key, Eq, share_id_seq), - txn_cond_seq(&id_key, Eq, share_meta_seq), - ]; - let mut if_then = vec![]; - - for share_account_key in add_share_account_keys.iter() { - condition.push(txn_cond_seq(share_account_key, Eq, 0)); - - let share_account_meta = ShareAccountMeta::new( - share_account_key.tenant_name().to_string(), - share_id, - req.share_on, - ); - - if_then.push(txn_op_put( - share_account_key, - serialize_struct(&share_account_meta)?, - )); /* (account, share_id) -> share_account_meta */ - - share_meta.add_account(share_account_key.tenant_name().to_string()); - } - if_then.push(txn_op_put(&id_key, serialize_struct(&share_meta)?)); /* (share_id) -> share_meta */ - - let txn_req = TxnRequest { - condition, - if_then, - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - debug!( - name :? =(name_key) , - id :? =(&id_key), - succ = succ; - "add_share_tenants" - ); - - if succ { - return Ok(AddShareAccountsReply { - share_id: Some(share_id), - spec_vec: Some(get_tenant_share_spec_vec(self, name_key.tenant()).await?), - }); - } - } - } - } - - async fn remove_share_tenants( - &self, - req: RemoveShareAccountsReq, - ) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let name_key = &req.share_name; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - let res = get_share_or_err( - self, - name_key, - format!("remove_share_tenants: {}", name_key.display()), - ) - .await; - - let (_share_id_seq, share_id, share_meta_seq, mut share_meta) = match res { - Ok(x) => x, - Err(e) => { - if let KVAppError::AppError(AppError::UnknownShare(_)) = e { - if req.if_exists { - return Ok(RemoveShareAccountsReply { - share_id: None, - spec_vec: None, - }); - } - } - return Err(e); - } - }; - - let mut remove_share_account_keys_and_seqs = vec![]; - for account in req.accounts.iter() { - if account == name_key.tenant_name() { - continue; - } - if share_meta.has_account(account) { - let share_account_key = ShareConsumerIdent::new( - Tenant::new_or_err(account, "remove_share_tenants")?, - share_id, - ); - - let res = get_share_account_meta_or_err( - self, - &share_account_key, - format!("remove_share_tenants: {}", share_id), - ) - .await; - - let (share_meta_account_seq, _share_account_meta) = match res { - Ok(x) => x, - Err(e) => { - return Err(e); - } - }; - - remove_share_account_keys_and_seqs - .push((share_account_key, share_meta_account_seq)); - } - } - - if remove_share_account_keys_and_seqs.is_empty() { - return Err(KVAppError::AppError(AppError::UnknownShareAccounts( - UnknownShareAccounts::new(&req.accounts, share_id, "unknown share account"), - ))); - } - - // Remove share account by these operations: - // mod share_meta delete account - // del (account, share_id) - // return share_id - { - let id_key = ShareId { share_id }; - let mut condition = vec![txn_cond_seq(&id_key, Eq, share_meta_seq)]; - let mut if_then = vec![]; - - for share_account_key_and_seq in remove_share_account_keys_and_seqs.iter() { - condition.push(txn_cond_seq( - &share_account_key_and_seq.0, - Eq, - share_account_key_and_seq.1, - )); - - if_then.push(txn_op_del(&share_account_key_and_seq.0)); // del (account, share_id) - - share_meta.del_account(share_account_key_and_seq.0.tenant_name()); - } - if_then.push(txn_op_put(&id_key, serialize_struct(&share_meta)?)); /* (share_id) -> share_meta */ - - let txn_req = TxnRequest { - condition, - if_then, - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - debug!( - id :? =(&id_key), - succ = succ; - "remove_share_tenants" - ); - - if succ { - return Ok(RemoveShareAccountsReply { - share_id: Some(share_id), - spec_vec: Some(get_tenant_share_spec_vec(self, name_key.tenant()).await?), - }); - } - } - } - } - - async fn grant_share_object( - &self, - req: GrantShareObjectReq, - ) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let share_name_key = &req.share_name; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - let res = get_share_or_err( - self, - share_name_key, - format!("grant_share_object: {}", share_name_key.display()), - ) - .await; - - let (share_id_seq, share_id, share_meta_seq, mut share_meta) = match res { - Ok(x) => x, - Err(e) => { - return Err(e); - } - }; - - let seq_and_id = - get_share_object_seq_and_id(self, &req.object, share_name_key.tenant(), true) - .await?; - - check_share_object(&share_meta.database, &seq_and_id, &req.object)?; - - // Check the object privilege has been granted - let has_granted_privileges = - share_meta.has_granted_privileges(&req.object, &seq_and_id, req.privilege)?; - - if has_granted_privileges { - return Ok(GrantShareObjectReply { - share_id, - spec_vec: None, - share_table_info: (share_name_key.name().to_string(), None), - }); - } - - // Grant the object privilege by inserting these record: - // add privilege and upsert (share_id) -> share_meta - // if grant database then update db_meta.shared_on and upsert (db_id) -> db_meta - - // Grant the object privilege by transaction. - { - let id_key = ShareId { share_id }; - // modify the share_meta add privilege - let object = ShareGrantObject::new(&seq_and_id); - - // modify share_ids - let res = get_object_shared_by_share_ids(self, &object).await?; - let share_ids_seq = res.0; - let mut share_ids: ObjectSharedByShareIds = res.1; - share_ids.add(share_id); - - share_meta.grant_object_privileges(object.clone(), req.privilege, req.grant_on); - - // condition - let mut condition: Vec = vec![ - txn_cond_seq(share_name_key, Eq, share_id_seq), - txn_cond_seq(&id_key, Eq, share_meta_seq), - txn_cond_seq(&object, Eq, share_ids_seq), - ]; - add_txn_condition(&seq_and_id, &mut condition); - // if_then - let mut if_then = vec![ - txn_op_put(&id_key, serialize_struct(&share_meta)?), /* (share_id) -> share_meta */ - txn_op_put(&object, serialize_struct(&share_ids)?), // (object) -> share_ids - ]; - // Some database has been created before `DatabaseIdToName`, so create it if need. - create_db_name_to_id_key_if_need( - self, - &seq_and_id, - share_name_key.tenant(), - &req.object, - &mut condition, - &mut if_then, - ) - .await?; - add_grant_object_txn_if_then( - share_id, - seq_and_id.clone(), - &mut condition, - &mut if_then, - )?; - - let txn_req = TxnRequest { - condition, - if_then, - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - debug!( - name :? =(share_name_key), - id :? =(&id_key), - succ = succ; - "grant_share_object" - ); - - if succ { - return Ok(GrantShareObjectReply { - share_id, - spec_vec: Some( - get_tenant_share_spec_vec(self, share_name_key.tenant()).await?, - ), - share_table_info: get_share_table_info(self, share_name_key, &share_meta) - .await?, - }); - } - } - } - } - - async fn revoke_share_object( - &self, - req: RevokeShareObjectReq, - ) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let share_name_key = &req.share_name; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - let res = get_share_or_err( - self, - share_name_key, - format!("revoke_share_object: {}", share_name_key.display()), - ) - .await; - - let (share_id_seq, share_id, share_meta_seq, mut share_meta) = match res { - Ok(x) => x, - Err(e) => { - return Err(e); - } - }; - - let seq_and_id = - get_share_object_seq_and_id(self, &req.object, share_name_key.tenant(), false) - .await?; - - check_share_object(&share_meta.database, &seq_and_id, &req.object)?; - - // Check the object privilege has not been granted. - let has_granted_privileges = - share_meta.has_granted_privileges(&req.object, &seq_and_id, req.privilege)?; - - if !has_granted_privileges { - return Ok(RevokeShareObjectReply { - share_id, - spec_vec: None, - share_table_info: (share_name_key.name().to_string(), None), - }); - } - - // Revoke the object privilege by upserting these record: - // revoke privilege in share_meta and upsert (share_id) -> share_meta - // update {db_meta|table_meta}.shared_by and upsert (db_id|table_id) -> (db_meta|table_id) - - // Revoke the object privilege by transaction. - { - let id_key = ShareId { share_id }; - // modify the share_meta add privilege - let object = ShareGrantObject::new(&seq_and_id); - - // modify share_ids - let res = get_object_shared_by_share_ids(self, &object).await?; - let share_ids_seq = res.0; - let mut share_ids: ObjectSharedByShareIds = res.1; - share_ids.remove(share_id); - - // condition - let mut condition: Vec = vec![ - txn_cond_seq(share_name_key, Eq, share_id_seq), - txn_cond_seq(&id_key, Eq, share_meta_seq), - txn_cond_seq(&object, Eq, share_ids_seq), - ]; - add_txn_condition(&seq_and_id, &mut condition); - // if_then - let mut if_then = vec![ - txn_op_put(&object, serialize_struct(&share_ids)?), // (object) -> share_ids - ]; - - let _ = revoke_object_privileges( - self, - &mut share_meta, - object.clone(), - share_id, - req.privilege, - req.update_on, - &mut condition, - &mut if_then, - ) - .await?; - - // update share meta - if_then.push(txn_op_put(&id_key, serialize_struct(&share_meta)?)); /* (share_id) -> share_meta */ - - match seq_and_id { - ShareGrantObjectSeqAndId::Database(db_meta_seq, db_id, mut db_meta) => { - db_meta.shared_by.remove(&share_id); - let key = DatabaseId { db_id }; - if_then.push(txn_op_put(&key, serialize_struct(&db_meta)?)); - condition.push(txn_cond_seq(&key, Eq, db_meta_seq)); - } - ShareGrantObjectSeqAndId::Table( - _db_id, - table_meta_seq, - table_id, - mut table_meta, - ) => { - table_meta.shared_by.remove(&share_id); - let key = TableId { table_id }; - if_then.push(txn_op_put(&key, serialize_struct(&table_meta)?)); - condition.push(txn_cond_seq(&key, Eq, table_meta_seq)); - } - } - - let txn_req = TxnRequest { - condition, - if_then, - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - debug!( - name :? =(share_name_key), - id :? =(&id_key), - succ = succ; - "revoke_share_object" - ); - - if succ { - return Ok(RevokeShareObjectReply { - share_id, - spec_vec: Some( - get_tenant_share_spec_vec(self, share_name_key.tenant()).await?, - ), - share_table_info: get_share_table_info(self, share_name_key, &share_meta) - .await?, - }); - } - } - } - } - - async fn get_share_grant_objects( - &self, - req: GetShareGrantObjectReq, - ) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let share_name_key = &req.share_name; - - let res = get_share_or_err( - self, - share_name_key, - format!("revoke_share_object: {}", share_name_key.display()), - ) - .await; - - let (_share_id_seq, _share_id, _share_meta_seq, share_meta) = match res { - Ok(x) => x, - Err(e) => { - return Err(e); - } - }; - - if share_meta.database.is_none() { - return Ok(GetShareGrantObjectReply { - share_name: req.share_name, - objects: vec![], - }); - } - - let database_obj = share_meta.database.clone().unwrap(); - let database = get_object_name_from_id(self, &None, database_obj.object).await?; - if database.is_none() { - return Ok(GetShareGrantObjectReply { - share_name: req.share_name, - objects: vec![], - }); - } - let database_name = match database.as_ref().unwrap() { - ShareGrantObjectName::Database(db_name) => Some(db_name), - ShareGrantObjectName::Table(_, _) => { - return Ok(GetShareGrantObjectReply { - share_name: req.share_name, - objects: vec![], - }); - } - }; - - let mut entries = Vec::new(); - for entry in share_meta.entries { - entries.push(entry.1); - } - entries.push(share_meta.database.unwrap()); - - let mut objects = vec![]; - for entry in entries { - let object = get_object_name_from_id(self, &database_name, entry.object).await?; - if let Some(object) = object { - objects.push(ShareGrantReplyObject { - object, - privileges: entry.privileges, - grant_on: entry.grant_on, - }) - } - } - - Ok(GetShareGrantObjectReply { - share_name: req.share_name, - objects, - }) - } - - // Return all the grant tenants of the share - async fn get_grant_tenants_of_share( - &self, - req: GetShareGrantTenantsReq, - ) -> Result { - let accounts = get_outbound_share_tenants_by_name(self, &req.share_name).await?; - - Ok(GetShareGrantTenantsReply { accounts }) - } - - // Return all the grant privileges of the object - async fn get_grant_privileges_of_object( - &self, - req: GetObjectGrantPrivilegesReq, - ) -> Result { - let entries = match req.object { - ShareGrantObjectName::Database(db_name) => { - let db_name_key = DatabaseNameIdent::new(&req.tenant, db_name); - let (db_seq, db_id) = get_u64_value(self, &db_name_key).await?; - db_has_to_exist( - db_seq, - &db_name_key, - format!("get_grant_privileges_of_object: {}", db_name_key.display()), - )?; - let object = ShareGrantObject::Database(db_id); - let (_seq, share_ids) = get_object_shared_by_share_ids(self, &object).await?; - let mut entries = vec![]; - for share_id in share_ids.share_ids.iter() { - let (_seq, share_name) = get_share_id_to_name_or_err( - self, - *share_id, - format!("get_grant_privileges_of_object: {}", &share_id), - ) - .await?; - - let (_seq, share_meta) = get_share_meta_by_id_or_err( - self, - *share_id, - format!("get_grant_privileges_of_object: {}", &share_id), - ) - .await?; - - entries.push(( - share_meta.get_grant_entry(object.clone()), - share_name.share_name().to_string(), - )); - } - - entries - } - ShareGrantObjectName::Table(db_name, table_name) => { - let db_name_key = DatabaseNameIdent::new(&req.tenant, &db_name); - let (db_seq, db_id) = get_u64_value(self, &db_name_key).await?; - db_has_to_exist( - db_seq, - &db_name_key, - format!("get_grant_privileges_of_object: {}", db_name_key.display()), - )?; - - let table_name_key = DBIdTableName { - db_id, - table_name: table_name.clone(), - }; - let (table_seq, table_id) = get_u64_value(self, &table_name_key).await?; - assert_table_exist( - table_seq, - &TableNameIdent { - tenant: req.tenant.clone(), - db_name: db_name.clone(), - table_name, - }, - format!("get_grant_privileges_of_object: {}", table_name_key), - )?; - - let object = ShareGrantObject::Table(table_id); - let (_seq, share_ids) = get_object_shared_by_share_ids(self, &object).await?; - let mut entries = vec![]; - for share_id in share_ids.share_ids.iter() { - let (_seq, share_name_ident_raw) = get_share_id_to_name_or_err( - self, - *share_id, - format!("get_grant_privileges_of_object: {}", &share_id), - ) - .await?; - - let (_seq, share_meta) = get_share_meta_by_id_or_err( - self, - *share_id, - format!("get_grant_privileges_of_object: {}", &share_id), - ) - .await?; - - entries.push(( - share_meta.get_grant_entry(object.clone()), - share_name_ident_raw.share_name().to_string(), - )); - } - - entries - } - }; - let mut privileges = vec![]; - for (entry, share_name) in entries { - if let Some(entry) = entry { - privileges.push(ObjectGrantPrivilege { - share_name, - privileges: entry.privileges, - grant_on: entry.grant_on, - }); - } - } - Ok(GetObjectGrantPrivilegesReply { privileges }) - } - - async fn create_share_endpoint( - &self, - req: CreateShareEndpointReq, - ) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let name_key = &req.endpoint; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - // Get share endpoint by name to ensure absence - let (share_endpoint_id_seq, share_endpoint_id) = get_u64_value(self, name_key).await?; - debug!( - share_endpoint_id_seq = share_endpoint_id_seq, - share_endpoint_id = share_endpoint_id, - name_key :? =(name_key); - "create_share_endpoint" - ); - - let mut condition = vec![]; - let mut if_then = vec![]; - - if share_endpoint_id_seq > 0 { - match req.create_option { - CreateOption::Create => { - return Err(KVAppError::AppError(AppError::ShareEndpointAlreadyExists( - ShareEndpointAlreadyExists::new(name_key.name(), func_name!()), - ))); - } - CreateOption::CreateIfNotExists => { - return Ok(CreateShareEndpointReply { share_endpoint_id }); - } - CreateOption::CreateOrReplace => { - construct_drop_share_endpoint_txn_operations( - self, - name_key, - true, - false, - func_name!(), - &mut condition, - &mut if_then, - ) - .await?; - } - } - } - - // Create share endpoint by inserting these record: - // (tenant, endpoint) -> share_endpoint_id - // (share_endpoint_id) -> share_endpoint_meta - // (share) -> (tenant,share_name) - - let share_endpoint_id = fetch_id(self, IdGenerator::share_endpoint_id()).await?; - let id_key = ShareEndpointId { share_endpoint_id }; - let id_to_name_key = ShareEndpointIdToName { share_endpoint_id }; - - debug!( - share_endpoint_id = share_endpoint_id, - name_key :? =(name_key); - "new share endpoint id" - ); - - // Create share endpoint by transaction. - { - let share_endpoint_meta = ShareEndpointMeta::new(&req); - condition.extend(vec![ - txn_cond_seq(name_key, Eq, share_endpoint_id_seq), - txn_cond_seq(&id_to_name_key, Eq, 0), - ]); - if_then.extend(vec![ - txn_op_put(name_key, serialize_u64(share_endpoint_id)?), /* (tenant, share_endpoint_name) -> share_endpoint_id */ - txn_op_put(&id_key, serialize_struct(&share_endpoint_meta)?), /* (share_endpoint_id) -> share_endpoint_meta */ - txn_op_put(&id_to_name_key, serialize_struct(&ShareEndpointIdentRaw::from(name_key.clone()))?), /* __fd_share_endpoint_id_to_name/ -> (tenant,share_endpoint_name) */ - ]); - - let txn_req = TxnRequest { - condition, - if_then, - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - debug!( - name :? =(name_key) , - id :? =(&id_key), - succ = succ; - "create_share_endpoint" - ); - - if succ { - return Ok(CreateShareEndpointReply { share_endpoint_id }); - } - } - } - } - - async fn upsert_share_endpoint( - &self, - req: UpsertShareEndpointReq, - ) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let name_key = &req.endpoint; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - // Get share endpoint by name to ensure absence - let (share_endpoint_id_seq, share_endpoint_id) = get_u64_value(self, name_key).await?; - debug!( - share_endpoint_id_seq = share_endpoint_id_seq, - share_endpoint_id = share_endpoint_id, - name_key :? =(name_key); - "upsert_share_endpoint" - ); - - // Create share endpoint by inserting these record: - // (tenant, endpoint) -> share_endpoint_id - // (share_endpoint_id) -> share_endpoint_meta - // (share) -> (tenant,share_name) - - // get (share_endpoint_meta_seq, share_endpoint_meta) - let (share_endpoint_meta_seq, share_endpoint_meta) = if share_endpoint_id_seq == 0 { - let share_endpoint_meta = ShareEndpointMeta::empty().upsert(&req); - (0, share_endpoint_meta) - } else { - let id_key = ShareEndpointId { share_endpoint_id }; - let (seq, share_endpoint_meta_opt): (u64, Option) = - get_pb_value(self, &id_key).await?; - - let share_endpoint_meta = share_endpoint_meta_opt.unwrap(); - // no need to upsert meta, return - if !share_endpoint_meta.if_need_to_upsert(&req) { - return Ok(UpsertShareEndpointReply { share_endpoint_id }); - } - (seq, share_endpoint_meta.upsert(&req)) - }; - - debug!( - share_endpoint_id = share_endpoint_id, - name_key :? =(name_key); - "new share endpoint id" - ); - - // upsert share endpoint by transaction. - { - let id_key = ShareEndpointId { share_endpoint_id }; - let mut condition = vec![ - txn_cond_seq(name_key, Eq, share_endpoint_id_seq), - txn_cond_seq(&id_key, Eq, share_endpoint_meta_seq), - ]; - let mut if_then = vec![]; - - let share_endpoint_id = if share_endpoint_id_seq == 0 { - // create a new endpoint if no endpoint exists before - let new_share_endpoint_id = - fetch_id(self, IdGenerator::share_endpoint_id()).await?; - let id_to_name_key = ShareEndpointIdToName { - share_endpoint_id: new_share_endpoint_id, - }; - let share_endpoint_id_key = ShareEndpointId { - share_endpoint_id: new_share_endpoint_id, - }; - if_then.push(txn_op_put(name_key, serialize_u64(new_share_endpoint_id)?)); - if_then.push(txn_op_put( - &id_to_name_key, - serialize_struct(&ShareEndpointIdentRaw::from(name_key.clone()))?, - )); - if_then.push(txn_op_put( - &share_endpoint_id_key, - serialize_struct(&share_endpoint_meta)?, - )); - condition.push(txn_cond_seq(&id_to_name_key, Eq, 0)); - - new_share_endpoint_id - } else { - // else only update share endpoint meta - let share_endpoint_id_key = ShareEndpointId { share_endpoint_id }; - if_then.push(txn_op_put( - &share_endpoint_id_key, - serialize_struct(&share_endpoint_meta)?, - )); - share_endpoint_id - }; - - let txn_req = TxnRequest { - condition, - if_then, - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - debug!( - name :? =(name_key) , - succ = succ; - "upsert_share_endpoint" - ); - - if succ { - return Ok(UpsertShareEndpointReply { share_endpoint_id }); - } - } - } - } - - async fn get_share_endpoint( - &self, - req: GetShareEndpointReq, - ) -> Result { - let mut share_endpoint_meta_vec = vec![]; - - let idents = { - if let Some(endpoint) = &req.endpoint { - vec![ShareEndpointIdent::new(&req.tenant, endpoint.clone())] - } else { - let ident = ShareEndpointIdent::new(&req.tenant, "dummy"); - - let dir_name = DirName::new(ident); - - list_keys(self, &dir_name).await? - } - }; - - for share_endpoint in idents { - let (_seq, share_endpoint_id) = get_u64_value(self, &share_endpoint).await?; - let id_key = ShareEndpointId { share_endpoint_id }; - let (_seq, share_endpoint_meta): (u64, Option) = - get_pb_value(self, &id_key).await?; - - if let Some(share_endpoint_meta) = share_endpoint_meta { - if let Some(to_tenant) = &req.to_tenant { - if to_tenant.tenant_name() == share_endpoint_meta.tenant { - share_endpoint_meta_vec.push((share_endpoint, share_endpoint_meta)); - } - } else { - share_endpoint_meta_vec.push((share_endpoint, share_endpoint_meta)); - } - } - } - - Ok(GetShareEndpointReply { - share_endpoint_meta_vec, - }) - } - - async fn drop_share_endpoint( - &self, - req: DropShareEndpointReq, - ) -> Result { - debug!(req :? =(&req); "ShareApi: {}", func_name!()); - - let name_key = &req.endpoint; - - let mut trials = txn_backoff(None, func_name!()); - loop { - trials.next().unwrap()?.await; - - let mut condition = vec![]; - let mut if_then = vec![]; - - let share_endpoint_id = if let Some(share_endpoint_id) = - construct_drop_share_endpoint_txn_operations( - self, - name_key, - req.if_exists, - true, - func_name!(), - &mut condition, - &mut if_then, - ) - .await? - { - share_endpoint_id - } else { - return Ok(DropShareEndpointReply {}); - }; - - let txn_req = TxnRequest { - condition, - if_then, - else_then: vec![], - }; - - let (succ, _responses) = send_txn(self, txn_req).await?; - - let share_id_key = ShareEndpointId { share_endpoint_id }; - debug!( - name :? =(name_key) , - id :? =(&share_id_key), - succ = succ; - "drop_share_endpoint" - ); - - if succ { - return Ok(DropShareEndpointReply {}); - } - } - } -} - -async fn construct_drop_share_endpoint_txn_operations( - kv_api: &(impl kvapi::KVApi + ?Sized), - name_key: &ShareEndpointIdent, - drop_if_exists: bool, - if_delete: bool, - ctx: &str, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result, KVAppError> { - let res = get_share_endpoint_or_err( - kv_api, - name_key, - format!( - "construct_drop_share_endpoint_txn_operations: {}", - name_key.display() - ), - ) - .await; - - let (share_endpoint_id_seq, share_endpoint_id, share_endpoint_meta_seq, _share_endpoint_meta) = - match res { - Ok(x) => x, - Err(e) => { - if let KVAppError::AppError(AppError::UnknownShareEndpoint(_)) = e { - if drop_if_exists { - return Ok(None); - } - } - - return Err(e); - } - }; - let (share_endpoint_name_seq, _share_endpoint) = get_share_endpoint_id_to_name_or_err( - kv_api, - share_endpoint_id, - format!( - "construct_drop_share_endpoint_txn_operations: {}", - name_key.display() - ), - ) - .await?; - - // Delete share endpoint by these operations: - // del (tenant, share_endpoint) - // del share_endpoint_id - // del (share_endpoint_id) -> (tenant, share_endpoint) - let share_id_key = ShareEndpointId { share_endpoint_id }; - let id_name_key = ShareEndpointIdToName { share_endpoint_id }; - - debug!( - share_endpoint_id = share_endpoint_id, - name_key :? =(name_key), - ctx = ctx; - "construct_drop_share_endpoint_txn_operations" - ); - - condition.push(txn_cond_seq(&share_id_key, Eq, share_endpoint_meta_seq)); - condition.push(txn_cond_seq(&id_name_key, Eq, share_endpoint_name_seq)); - if_then.push(txn_op_del(&share_id_key)); // del share_endpoint_id - if_then.push(txn_op_del(&id_name_key)); // del (share_endpoint_id) -> (tenant, share_endpoint) - if if_delete { - condition.push(txn_cond_seq(name_key, Eq, share_endpoint_id_seq)); - if_then.push(txn_op_del(name_key)); // del (tenant, share_endpoint) - } - - Ok(Some(share_endpoint_id)) -} - -async fn get_share_database_name( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_meta: &ShareMeta, - share_name: &ShareNameIdent, -) -> Result, KVAppError> { - if let Some(entry) = &share_meta.database { - match entry.object { - ShareGrantObject::Database(db_id) => { - let id_to_name = DatabaseIdToName { db_id }; - let (name_ident_seq, name_ident): (_, Option) = - get_pb_value(kv_api, &id_to_name).await?; - if name_ident_seq == 0 || name_ident.is_none() { - return Err(KVAppError::AppError(AppError::UnknownShare( - UnknownShare::new(share_name.name(), ""), - ))); - } - Ok(Some(name_ident.unwrap().database_name().to_string())) - } - ShareGrantObject::Table(_id) => Err(KVAppError::AppError(AppError::WrongShare( - WrongShare::new(share_name.name()), - ))), - } - } else { - Ok(None) - } -} - -async fn get_outbound_share_tenants_by_name( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_name: &ShareNameIdent, -) -> Result, KVAppError> { - let res = get_share_or_err( - kv_api, - share_name, - format!("get_share: {}", share_name.display()), - ) - .await?; - let (_share_id_seq, share_id, _share_meta_seq, share_meta) = res; - - let mut accounts = vec![]; - for account in share_meta.get_accounts() { - let share_account_key = ShareConsumerIdent::new( - Tenant::new_or_err(&account, "get_outbound_share_tenants_by_name")?, - share_id, - ); - - let (_seq, meta) = get_share_account_meta_or_err( - kv_api, - &share_account_key, - format!("get_outbound_share_tenants_by_name's account: {share_id}/{account}"), - ) - .await?; - - accounts.push(GetShareGrantTenants { - account, - grant_on: meta.share_on, - }); - } - - Ok(accounts) -} - -async fn get_outbound_share_info_by_name( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_name: &ShareNameIdent, -) -> Result { - let res = get_share_or_err( - kv_api, - share_name, - format!("get_share: {}", share_name.display()), - ) - .await?; - let (_share_id_seq, _share_id, _share_meta_seq, share_meta) = res; - - let mut accounts = vec![]; - for account in share_meta.get_accounts().iter() { - accounts.push(account.clone()); - } - - let database_name = get_share_database_name(kv_api, &share_meta, share_name).await?; - - Ok(ShareAccountReply { - share_name: share_name.clone(), - database_name, - create_on: share_meta.share_on, - accounts: Some(accounts), - comment: share_meta.comment.clone(), - }) -} - -async fn get_outbound_share_infos_by_tenant( - kv_api: &(impl kvapi::KVApi + ?Sized), - tenant: &Tenant, -) -> Result, KVAppError> { - let mut outbound_share_accounts: Vec = vec![]; - - let tenant_share_name_key = ShareNameIdent::new(tenant, "dummy"); - - let dir_name = DirName::new(tenant_share_name_key); - - let share_name_keys = list_keys(kv_api, &dir_name).await?; - - for share_name in share_name_keys { - let reply = get_outbound_share_info_by_name(kv_api, &share_name).await; - if let Ok(reply) = reply { - outbound_share_accounts.push(reply) - } - } - - Ok(outbound_share_accounts) -} - -async fn get_object_name_from_id( - kv_api: &(impl kvapi::KVApi + ?Sized), - database_name: &Option<&String>, - object: ShareGrantObject, -) -> Result, KVAppError> { - match object { - ShareGrantObject::Database(db_id) => { - let db_id_key = DatabaseIdToName { db_id }; - let (_db_name_seq, db_name): (_, Option) = - get_pb_value(kv_api, &db_id_key).await?; - Ok(db_name - .map(|db_name| ShareGrantObjectName::Database(db_name.database_name().to_string()))) - } - ShareGrantObject::Table(table_id) => { - let table_id_key = TableIdToName { table_id }; - let (_db_id_table_name_seq, table_name): (_, Option) = - get_pb_value(kv_api, &table_id_key).await?; - Ok(table_name.map(|table_name| { - ShareGrantObjectName::Table( - database_name.as_ref().unwrap().to_string(), - table_name.table_name, - ) - })) - } - } -} - -async fn create_db_name_to_id_key_if_need( - kv_api: &(impl kvapi::KVApi + ?Sized), - seq_and_id: &ShareGrantObjectSeqAndId, - tenant: &Tenant, - obj_name: &ShareGrantObjectName, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(), KVAppError> { - if let ShareGrantObjectName::Database(db) = obj_name { - if let ShareGrantObjectSeqAndId::Database(_, db_id, _) = seq_and_id { - let db_id_key = DatabaseIdToName { db_id: *db_id }; - let (db_name_seq, _): (_, Option) = - get_pb_value(kv_api, &db_id_key).await?; - if db_name_seq == 0 { - condition.push(txn_cond_seq(&db_id_key, Eq, 0)); - - let name_key = DatabaseNameIdentRaw::new(tenant.tenant_name(), db); - if_then.push(txn_op_put(&db_id_key, serialize_struct(&name_key)?)); - } - } - }; - Ok(()) -} - -fn check_share_object( - database: &Option, - seq_and_id: &ShareGrantObjectSeqAndId, - obj_name: &ShareGrantObjectName, -) -> Result<(), KVAppError> { - if let Some(entry) = database { - if let ShareGrantObject::Database(db_id) = entry.object { - let object_db_id = match seq_and_id { - ShareGrantObjectSeqAndId::Database(_, db_id, _) => *db_id, - ShareGrantObjectSeqAndId::Table(db_id, _seq, _id, _meta) => *db_id, - }; - if db_id != object_db_id { - return Err(KVAppError::AppError(AppError::WrongShareObject( - WrongShareObject::new(obj_name.to_string()), - ))); - } - } else { - unreachable!("database MUST be Database object"); - } - } else { - // Table cannot be granted without database has been granted. - if let ShareGrantObjectSeqAndId::Table(_, _, _, _) = seq_and_id { - return Err(KVAppError::AppError(AppError::WrongShareObject( - WrongShareObject::new(obj_name.to_string()), - ))); - } - } - - Ok(()) -} - -/// Returns ShareGrantObjectSeqAndId by ShareGrantObjectName -async fn get_share_object_seq_and_id( - kv_api: &(impl kvapi::KVApi + ?Sized), - obj_name: &ShareGrantObjectName, - tenant: &Tenant, - grant: bool, -) -> Result { - match obj_name { - ShareGrantObjectName::Database(db_name) => { - let name_key = DatabaseNameIdent::new(tenant.clone(), db_name); - let (_db_id_seq, db_id, db_meta_seq, db_meta) = get_db_or_err( - kv_api, - &name_key, - format!("get_share_object_seq_and_id: {}", name_key.display()), - ) - .await?; - - if grant && db_meta.from_share.is_some() { - return Err(KVAppError::AppError( - AppError::CannotShareDatabaseCreatedFromShare( - CannotShareDatabaseCreatedFromShare::new( - db_name, - format!("get_share_object_seq_and_id: {}", name_key.display()), - ), - ), - )); - } - Ok(ShareGrantObjectSeqAndId::Database( - db_meta_seq, - db_id, - db_meta, - )) - } - - ShareGrantObjectName::Table(db_name, table_name) => { - let db_name_key = DatabaseNameIdent::new(tenant, db_name); - let (db_seq, db_id) = get_u64_value(kv_api, &db_name_key).await?; - db_has_to_exist( - db_seq, - &db_name_key, - format!("get_share_object_seq_and_id: {}", db_name_key.display()), - )?; - - let name_key = DBIdTableName { - db_id, - table_name: table_name.clone(), - }; - - let (table_seq, table_id) = get_u64_value(kv_api, &name_key).await?; - assert_table_exist( - table_seq, - &TableNameIdent { - tenant: tenant.clone(), - db_name: db_name.clone(), - table_name: table_name.clone(), - }, - format!("get_share_object_seq_and_id: {}", name_key), - )?; - - let tbid = TableId { table_id }; - let (table_meta_seq, table_meta): (_, Option) = - get_pb_value(kv_api, &tbid).await?; - - if table_meta_seq == 0 { - return Err(KVAppError::AppError(AppError::UnknownTable( - UnknownTable::new( - &name_key.table_name, - format!("get_share_object_seq_and_id: {}", name_key), - ), - ))); - } - - Ok(ShareGrantObjectSeqAndId::Table( - db_id, - table_meta_seq, - table_id, - table_meta.unwrap(), - )) - } - } -} - -fn add_txn_condition(seq_and_id: &ShareGrantObjectSeqAndId, condition: &mut Vec) { - match seq_and_id { - ShareGrantObjectSeqAndId::Database(db_meta_seq, db_id, _meta) => { - let key = DatabaseId { db_id: *db_id }; - condition.push(txn_cond_seq(&key, Eq, *db_meta_seq)) - } - ShareGrantObjectSeqAndId::Table(_db_id, table_meta_seq, table_id, _) => { - let key = TableId { - table_id: *table_id, - }; - condition.push(txn_cond_seq(&key, Eq, *table_meta_seq)) - } - } -} - -fn add_grant_object_txn_if_then( - share_id: u64, - seq_and_id: ShareGrantObjectSeqAndId, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(), KVAppError> { - match seq_and_id { - ShareGrantObjectSeqAndId::Database(db_meta_seq, db_id, mut db_meta) => { - // modify db_meta add share_id into shared_by - if !db_meta.shared_by.contains(&share_id) { - db_meta.shared_by.insert(share_id); - let key = DatabaseId { db_id }; - if_then.push(txn_op_put(&key, serialize_struct(&db_meta)?)); - condition.push(txn_cond_seq(&key, Eq, db_meta_seq)); - } - } - ShareGrantObjectSeqAndId::Table(_db_id, table_meta_seq, table_id, mut table_meta) => { - // modify table_meta add share_id into shared_by - if !table_meta.shared_by.contains(&share_id) { - table_meta.shared_by.insert(share_id); - let key = TableId { table_id }; - if_then.push(txn_op_put(&key, serialize_struct(&table_meta)?)); - condition.push(txn_cond_seq(&key, Eq, table_meta_seq)); - } - } - } - - Ok(()) -} - -async fn drop_accounts_granted_from_share( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_id: u64, - share_meta: &ShareMeta, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(), KVAppError> { - // get all accounts seq from share_meta - for account in share_meta.get_accounts() { - let share_account_key = ShareConsumerIdent::new( - Tenant::new_or_err(&account, "drop_accounts_granted_from_share")?, - share_id, - ); - let ret = get_share_account_meta_or_err( - kv_api, - &share_account_key, - format!("drop_share's account: {}/{}", share_id, account), - ) - .await; - - if let Ok((seq, _meta)) = ret { - condition.push(txn_cond_seq(&share_account_key, Eq, seq)); - if_then.push(txn_op_del(&share_account_key)); - } - } - - Ok(()) -} - -async fn remove_share_id_from_share_object( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_id: u64, - entry: &ShareGrantEntry, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(), KVAppError> { - if let Ok((seq, mut share_ids)) = get_object_shared_by_share_ids(kv_api, &entry.object).await { - share_ids.remove(share_id); - - condition.push(txn_cond_seq(&entry.object, Eq, seq)); - if_then.push(txn_op_put(&entry.object, serialize_struct(&share_ids)?)); - } - Ok(()) -} - -async fn remove_share_id_from_share_objects( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_id: u64, - share_meta: &ShareMeta, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(), KVAppError> { - if let Some(database) = &share_meta.database { - remove_share_id_from_share_object(kv_api, share_id, database, condition, if_then).await?; - if let ShareGrantObject::Database(db_id) = database.object { - let key = DatabaseId { db_id }; - - let (db_meta_seq, db_meta): (_, Option) = - get_pb_value(kv_api, &key).await?; - if let Some(mut db_meta) = db_meta { - db_meta.shared_by.remove(&share_id); - if_then.push(txn_op_put(&key, serialize_struct(&db_meta)?)); - condition.push(txn_cond_seq(&key, Eq, db_meta_seq)); - } - } else { - unreachable!("share database MUST to be database object"); - } - } - - for (_key, entry) in share_meta.entries.iter() { - remove_share_id_from_share_object(kv_api, share_id, entry, condition, if_then).await?; - if let ShareGrantObject::Table(table_id) = entry.object { - let key = TableId { table_id }; - - let (table_meta_seq, table_meta): (_, Option) = - get_pb_value(kv_api, &key).await?; - if let Some(mut table_meta) = table_meta { - table_meta.shared_by.remove(&share_id); - if_then.push(txn_op_put(&key, serialize_struct(&table_meta)?)); - condition.push(txn_cond_seq(&key, Eq, table_meta_seq)); - } - } else { - unreachable!("share entries MUST to be table object"); - } - } - - Ok(()) -} - -async fn get_tenant_share_spec_vec( - kv_api: &(impl kvapi::KVApi + ?Sized), - tenant: &Tenant, -) -> Result, KVAppError> { - let mut share_metas = vec![]; - let share_name_list = ShareNameIdent::new(tenant, "dummy"); - - let dir_name = DirName::new(share_name_list); - - let share_name_list_keys = list_keys(kv_api, &dir_name).await?; - for share_name in share_name_list_keys { - let res = get_share_or_err( - kv_api, - &share_name, - format!("get_tenant_share_spec_vec: {}", share_name.display()), - ) - .await; - - let (_share_id_seq, share_id, _share_meta_seq, share_meta) = match res { - Ok(x) => x, - Err(e) => match e { - KVAppError::AppError(AppError::UnknownShare(e)) => { - error!("{:?} when get_tenant_share_spec_vec", e); - continue; - } - KVAppError::AppError(AppError::UnknownShareId(_)) => { - error!("{:?} when get_tenant_share_spec_vec", e); - continue; - } - _ => { - return Err(e); - } - }, - }; - - share_metas.push( - convert_share_meta_to_spec(kv_api, share_name.name(), share_id, share_meta).await?, - ); - } - - Ok(share_metas) -} - -#[allow(clippy::too_many_arguments)] -async fn revoke_object_privileges( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_meta: &mut ShareMeta, - object: ShareGrantObject, - share_id: u64, - privileges: ShareGrantObjectPrivilege, - update_on: DateTime, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(), KVAppError> { - let key = object.to_string(); - - match object { - ShareGrantObject::Database(_db_id) => { - if let Some(entry) = &mut share_meta.database { - if object == entry.object { - if entry.revoke_privileges(privileges, update_on) { - // all database privileges have been revoked, clear database and entries. - share_meta.database = None; - share_meta.update_on = Some(update_on); - - // clean all shared table `shared_by` field - for (_key, entry) in share_meta.entries.iter() { - if let ShareGrantObject::Table(table_id) = entry.object { - let key = TableId { table_id }; - - let (table_meta_seq, table_meta): (_, Option) = - get_pb_value(kv_api, &key).await?; - if let Some(mut table_meta) = table_meta { - table_meta.shared_by.remove(&share_id); - if_then.push(txn_op_put(&key, serialize_struct(&table_meta)?)); - condition.push(txn_cond_seq(&key, Eq, table_meta_seq)); - } - } else { - unreachable!("share entries MUST to be table object"); - } - } - share_meta.entries.clear(); - } - } else { - return Err(KVAppError::AppError(AppError::WrongShareObject( - WrongShareObject::new(&key), - ))); - } - } else { - return Err(KVAppError::AppError(AppError::WrongShareObject( - WrongShareObject::new(object.to_string()), - ))); - } - } - ShareGrantObject::Table(table_id) => match share_meta.entries.get_mut(&key) { - Some(entry) => { - if let ShareGrantObject::Table(self_table_id) = entry.object { - if self_table_id == table_id { - if entry.revoke_privileges(privileges, update_on) { - share_meta.entries.remove(&key); - // remove share id from table `shared_by` field - let key = TableId { table_id }; - - let (table_meta_seq, table_meta): (_, Option) = - get_pb_value(kv_api, &key).await?; - if let Some(mut table_meta) = table_meta { - table_meta.shared_by.remove(&share_id); - if_then.push(txn_op_put(&key, serialize_struct(&table_meta)?)); - condition.push(txn_cond_seq(&key, Eq, table_meta_seq)); - } - } - } else { - return Err(KVAppError::AppError(AppError::WrongShareObject( - WrongShareObject::new(object.to_string()), - ))); - } - } else { - unreachable!("ShareMeta.entries MUST be Table Object"); - } - } - None => return Ok(()), - }, - } - Ok(()) -} diff --git a/src/meta/api/src/share_api_test_suite.rs b/src/meta/api/src/share_api_test_suite.rs deleted file mode 100644 index 6c76a7c2602a..000000000000 --- a/src/meta/api/src/share_api_test_suite.rs +++ /dev/null @@ -1,1749 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::collections::BTreeMap; -use std::collections::BTreeSet; - -use chrono::Utc; -use databend_common_exception::ErrorCode; -use databend_common_meta_app::schema::database_name_ident::DatabaseNameIdent; -use databend_common_meta_app::schema::CreateDatabaseReq; -use databend_common_meta_app::schema::CreateOption; -use databend_common_meta_app::schema::CreateTableReq; -use databend_common_meta_app::schema::DatabaseId; -use databend_common_meta_app::schema::DatabaseMeta; -use databend_common_meta_app::schema::DropDatabaseReq; -use databend_common_meta_app::schema::DropTableByIdReq; -use databend_common_meta_app::schema::TableId; -use databend_common_meta_app::schema::TableMeta; -use databend_common_meta_app::schema::TableNameIdent; -use databend_common_meta_app::share::share_end_point_ident::ShareEndpointIdentRaw; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::share_name_ident::ShareNameIdentRaw; -use databend_common_meta_app::share::*; -use databend_common_meta_app::tenant::Tenant; -use databend_common_meta_kvapi::kvapi; -use databend_common_meta_types::MetaError; -use enumflags2::BitFlags; -use log::info; - -use crate::get_object_shared_by_share_ids; -use crate::get_share_account_meta_or_err; -use crate::get_share_id_to_name_or_err; -use crate::get_share_meta_by_id_or_err; -use crate::get_share_or_err; -use crate::kv_app_error::KVAppError; -use crate::testing::get_kv_data; -use crate::SchemaApi; -use crate::ShareApi; - -/// Test suite of `ShareApi`. -/// -/// It is not used by this crate, but is used by other crate that impl `ShareApi`, -/// to ensure an impl works as expected, -/// such as `meta/embedded` and `metasrv`. -#[derive(Copy, Clone)] -pub struct ShareApiTestSuite {} - -async fn if_share_object_data_exists( - kv_api: &(impl kvapi::KVApi + ?Sized), - entry: &ShareGrantEntry, -) -> Result { - if let Ok((_seq, _share_ids)) = get_object_shared_by_share_ids(kv_api, &entry.object).await { - return Ok(false); - } - Ok(true) -} - -// Return true if all the share data has been removed. -async fn is_all_share_data_removed( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_name: &ShareNameIdent, - share_id: u64, - share_meta: &ShareMeta, -) -> Result { - let res = get_share_or_err(kv_api, share_name, "").await; - if res.is_ok() { - return Ok(false); - } - - let res = get_share_id_to_name_or_err(kv_api, share_id, "").await; - if res.is_ok() { - return Ok(false); - } - - for account in share_meta.get_accounts() { - let share_account_key = ShareConsumerIdent::new( - Tenant::new_or_err(account, "is_all_share_data_removed")?, - share_id, - ); - let res = get_share_account_meta_or_err(kv_api, &share_account_key, "").await; - if res.is_ok() { - return Ok(false); - } - } - - if let Some(database) = &share_meta.database { - if if_share_object_data_exists(kv_api, database).await? { - return Ok(false); - } - } - - for (_key, entry) in share_meta.entries.iter() { - if if_share_object_data_exists(kv_api, entry).await? { - return Ok(false); - } - } - - Ok(true) -} - -impl ShareApiTestSuite { - /// Test ShareApi on a single node - pub async fn test_single_node_share(b: B) -> anyhow::Result<()> - where - B: kvapi::ApiBuilder, - MT: ShareApi + kvapi::AsKVApi + SchemaApi, - { - let suite = ShareApiTestSuite {}; - - suite.share_create_show_drop(&b.build().await).await?; - suite - .share_endpoint_create_show_drop(&b.build().await) - .await?; - suite.share_add_remove_account(&b.build().await).await?; - suite.share_grant_revoke_object(&b.build().await).await?; - suite.get_share_grant_objects(&b.build().await).await?; - suite - .get_grant_privileges_of_object(&b.build().await) - .await?; - suite - .drop_share_database_and_table(&b.build().await) - .await?; - - Ok(()) - } - - #[minitrace::trace] - async fn share_create_show_drop>( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant = "tenant1"; - let tenant = Tenant::new_literal(tenant); - - let share1 = "share1"; - let share_name = ShareNameIdent::new(&tenant, share1); - let share_id: u64; - - info!("--- show share when there are no share"); - { - let req = ShowSharesReq { - tenant: tenant.clone(), - }; - - let res = mt.show_shares(req).await; - info!("show share res: {:?}", res); - assert!(res.is_ok()); - let resp = res.unwrap(); - assert!(resp.outbound_accounts.is_empty()); - } - - info!("--- create share1"); - let create_on = Utc::now(); - { - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name.clone(), - comment: None, - create_on, - }; - - let res = mt.create_share(req).await; - info!("create share res: {:?}", res); - let res = res.unwrap(); - assert_eq!(1, res.share_id, "first database id is 1"); - assert_eq!(1, res.spec_vec.unwrap().len()); - share_id = res.share_id; - - let (share_name_seq, share_name_ret) = - get_share_id_to_name_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(share_name_seq > 0); - assert_eq!(ShareNameIdentRaw::from(share_name.clone()), share_name_ret) - } - - info!("--- show share again"); - { - let req = ShowSharesReq { - tenant: tenant.clone(), - }; - - let res = mt.show_shares(req).await; - info!("show share res: {:?}", res); - assert!(res.is_ok()); - let resp = res.unwrap(); - assert_eq!(resp.outbound_accounts.len(), 1); - } - - Ok(()) - } - - #[minitrace::trace] - async fn share_endpoint_create_show_drop>( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant_name1 = "tenant1"; - let tenant_name2 = "tenant2"; - let tenant_name3 = "tenant3"; - let endpoint1 = "endpoint1"; - let endpoint2 = "endpoint2"; - - let tenant1 = Tenant::new_literal(tenant_name1); - let tenant2 = Tenant::new_literal(tenant_name2); - let tenant3 = Tenant::new_literal(tenant_name3); - - info!("--- create share endpoints"); - let create_on = Utc::now(); - { - let req = CreateShareEndpointReq { - create_option: CreateOption::Create, - endpoint: ShareEndpointIdent::new(&tenant1, endpoint1), - url: "http://127.0.0.1:22222".to_string(), - tenant: tenant2.clone(), - comment: None, - create_on, - args: BTreeMap::new(), - }; - - let res = mt.create_share_endpoint(req).await; - info!("create create_share_endpoint res: {:?}", res); - assert!(res.is_ok()); - - let req = CreateShareEndpointReq { - create_option: CreateOption::Create, - endpoint: ShareEndpointIdent::new(&tenant1, endpoint1), - url: "http://127.0.0.1:21111".to_string(), - tenant: tenant2.clone(), - comment: None, - args: BTreeMap::new(), - create_on, - }; - - let res = mt.create_share_endpoint(req).await; - info!("create create_share_endpoint res: {:?}", res); - assert!(res.is_err()); - let err = res.unwrap_err(); - assert_eq!( - ErrorCode::SHARE_ENDPOINT_ALREADY_EXISTS, - ErrorCode::from(err).code() - ); - - let req = CreateShareEndpointReq { - create_option: CreateOption::Create, - endpoint: ShareEndpointIdent::new(&tenant1, endpoint2), - url: "http://127.0.0.1:21111".to_string(), - tenant: tenant3.clone(), - comment: None, - create_on, - args: BTreeMap::new(), - }; - - let res = mt.create_share_endpoint(req).await; - info!("create create_share_endpoint res: {:?}", res); - assert!(res.is_ok()); - } - - info!("--- upsert share endpoints"); - { - let upsert_tenant_name = "upsert_tenant"; - let upsert_tenant = Tenant::new_literal(upsert_tenant_name); - - let upsert_req = UpsertShareEndpointReq { - endpoint: ShareEndpointIdent::new(&upsert_tenant, endpoint2), - url: "http://127.0.0.1:21111".to_string(), - tenant: tenant_name3.to_string(), - create_on, - args: BTreeMap::new(), - }; - let res = mt.upsert_share_endpoint(upsert_req.clone()).await; - assert!(res.is_ok()); - let upsert_share_endpoint_id = res.unwrap().share_endpoint_id; - - let req = GetShareEndpointReq { - tenant: upsert_tenant.clone(), - endpoint: None, - to_tenant: None, - }; - let res = mt.get_share_endpoint(req).await; - assert!(res.is_ok()); - assert_eq!(res.clone().unwrap().share_endpoint_meta_vec.len(), 1); - assert_eq!( - res.unwrap().share_endpoint_meta_vec[0].1.url, - "http://127.0.0.1:21111".to_string() - ); - - let res = mt.upsert_share_endpoint(upsert_req).await; - assert!(res.is_ok()); - assert_eq!(upsert_share_endpoint_id, res.unwrap().share_endpoint_id); - - let upsert_req = UpsertShareEndpointReq { - endpoint: ShareEndpointIdent::new(&upsert_tenant, endpoint2), - url: "http://127.0.0.1:22222".to_string(), - tenant: tenant_name3.to_string(), - create_on, - args: BTreeMap::new(), - }; - let res = mt.upsert_share_endpoint(upsert_req).await; - assert!(res.is_ok()); - assert_eq!(upsert_share_endpoint_id, res.unwrap().share_endpoint_id); - - let req = GetShareEndpointReq { - tenant: upsert_tenant.clone(), - endpoint: None, - to_tenant: None, - }; - let res = mt.get_share_endpoint(req).await; - assert!(res.is_ok()); - assert_eq!(res.clone().unwrap().share_endpoint_meta_vec.len(), 1); - assert_eq!( - res.unwrap().share_endpoint_meta_vec[0].1.url, - "http://127.0.0.1:22222".to_string() - ); - } - info!("--- get share endpoints"); - { - let req = GetShareEndpointReq { - tenant: tenant1.clone(), - endpoint: None, - to_tenant: None, - }; - - let res = mt.get_share_endpoint(req).await; - assert!(res.is_ok()); - assert_eq!(res.unwrap().share_endpoint_meta_vec.len(), 2); - - let req = GetShareEndpointReq { - tenant: tenant1.clone(), - endpoint: Some(endpoint1.to_string()), - to_tenant: None, - }; - - let res = mt.get_share_endpoint(req).await; - assert!(res.is_ok()); - assert_eq!(res.unwrap().share_endpoint_meta_vec.len(), 1); - } - - info!("--- drop share endpoints"); - { - let req = DropShareEndpointReq { - if_exists: true, - endpoint: ShareEndpointIdent::new(&tenant1, endpoint1), - }; - let res = mt.drop_share_endpoint(req).await; - assert!(res.is_ok()); - - let req = GetShareEndpointReq { - tenant: tenant1.clone(), - endpoint: None, - to_tenant: None, - }; - - let res = mt.get_share_endpoint(req).await; - assert!(res.is_ok()); - assert_eq!(res.unwrap().share_endpoint_meta_vec.len(), 1); - - let req = GetShareEndpointReq { - tenant: tenant1.clone(), - endpoint: Some(endpoint1.to_string()), - to_tenant: None, - }; - - let res = mt.get_share_endpoint(req).await; - assert!(res.is_ok()); - assert_eq!(res.unwrap().share_endpoint_meta_vec.len(), 0); - } - - { - info!("--- create or replace share endpoints"); - let endpoint_name = "replace_endpoint"; - let endpoint = ShareEndpointIdent::new(&tenant1, endpoint_name); - - let url = "http://127.0.0.1:22222".to_string(); - let req = CreateShareEndpointReq { - create_option: CreateOption::Create, - endpoint: endpoint.clone(), - url: url.clone(), - tenant: tenant2.clone(), - comment: None, - create_on, - args: BTreeMap::new(), - }; - - let res = mt.create_share_endpoint(req).await?; - - let old_share_endpoint_id = res.share_endpoint_id; - let old_id_key = ShareEndpointId { - share_endpoint_id: old_share_endpoint_id, - }; - let oldid_to_name_key = ShareEndpointIdToName { - share_endpoint_id: old_share_endpoint_id, - }; - let meta: ShareEndpointMeta = get_kv_data(mt.as_kv_api(), &old_id_key).await?; - assert_eq!(meta.url, url); - let name_key: ShareEndpointIdentRaw = - get_kv_data(mt.as_kv_api(), &oldid_to_name_key).await?; - assert_eq!(name_key, endpoint.clone().into()); - - let req = GetShareEndpointReq { - tenant: tenant1.clone(), - endpoint: Some(endpoint_name.to_string()), - to_tenant: None, - }; - - let res = mt.get_share_endpoint(req).await?; - assert_eq!(res.share_endpoint_meta_vec.len(), 1); - assert_eq!(res.share_endpoint_meta_vec[0].1.url, url); - - let url = "http://192.168.0.1".to_string(); - let req = CreateShareEndpointReq { - create_option: CreateOption::CreateOrReplace, - endpoint: endpoint.clone(), - url: url.clone(), - tenant: tenant2.clone(), - comment: None, - create_on, - args: BTreeMap::new(), - }; - - let res = mt.create_share_endpoint(req).await?; - let share_endpoint_id = res.share_endpoint_id; - - let req = GetShareEndpointReq { - tenant: tenant1.clone(), - endpoint: Some(endpoint_name.to_string()), - to_tenant: None, - }; - - let res = mt.get_share_endpoint(req).await?; - assert_eq!(res.share_endpoint_meta_vec.len(), 1); - assert_eq!(res.share_endpoint_meta_vec[0].1.url, url); - - // assert old id key has been deleted - let meta: Result = - get_kv_data(mt.as_kv_api(), &old_id_key).await; - assert!(meta.is_err()); - let name_key: Result = - get_kv_data(mt.as_kv_api(), &oldid_to_name_key).await; - assert!(name_key.is_err()); - - // assert new id key has been created - let id_key = ShareEndpointId { share_endpoint_id }; - let id_to_name_key = ShareEndpointIdToName { share_endpoint_id }; - let meta: ShareEndpointMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(meta.url, url); - let name_key: ShareEndpointIdentRaw = - get_kv_data(mt.as_kv_api(), &id_to_name_key).await?; - assert_eq!(name_key, endpoint.clone().into()); - } - Ok(()) - } - - #[minitrace::trace] - async fn share_add_remove_account>( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant_name1 = "tenant1"; - let tenant_name2 = "tenant2"; - - let tenant1 = Tenant::new_literal(tenant_name1); - let tenant2 = Tenant::new_literal(tenant_name2); - - let share1 = "share1"; - let share2 = "share2"; - let account = "account1"; - let account2 = "account2"; - let share_name = ShareNameIdent::new(&tenant1, share1); - let share_name2 = ShareNameIdent::new(&tenant1, share2); - let share_name3 = ShareNameIdent::new(&tenant2, share2); - let comment1 = "comment1"; - let comment2 = "comment2"; - let comment3 = "comment3"; - let share_id: u64; - let share_on = Utc::now(); - let create_on = Utc::now(); - let if_exists = true; - - info!("--- add and remove account with not exist share"); - { - let req = AddShareAccountsReq { - share_name: share_name.clone(), - share_on, - if_exists: false, - accounts: vec![account.to_string()], - }; - - // get share meta and check account has been added - let res = mt.add_share_tenants(req).await; - assert!(res.is_err()); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::UNKNOWN_SHARE, ErrorCode::from(err).code()); - - let req = RemoveShareAccountsReq { - share_name: share_name.clone(), - if_exists: false, - accounts: vec![account2.to_string()], - }; - - let res = mt.remove_share_tenants(req).await; - assert!(res.is_err()); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::UNKNOWN_SHARE, ErrorCode::from(err).code()); - } - - info!("--- prepare share1 share2 share3"); - { - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name.clone(), - comment: Some(comment1.to_string()), - create_on, - }; - - let res = mt.create_share(req).await; - info!("add share account res: {:?}", res); - let res = res.unwrap(); - assert_eq!(1, res.share_id, "first database id is 1"); - share_id = res.share_id; - - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name2.clone(), - comment: Some(comment2.to_string()), - create_on, - }; - - let res = mt.create_share(req).await; - info!("add share account res: {:?}", res); - assert!(res.is_ok()); - let res = res.unwrap(); - assert_eq!(2, res.spec_vec.unwrap().len()); - - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name3.clone(), - comment: Some(comment3.to_string()), - create_on, - }; - - let res = mt.create_share(req).await; - info!("add share account res: {:?}", res); - assert!(res.is_ok()); - let res = res.unwrap(); - assert_eq!(1, res.spec_vec.unwrap().len()); - } - - info!("--- add account account1"); - { - let req = AddShareAccountsReq { - share_name: share_name.clone(), - share_on, - if_exists, - accounts: vec![account.to_string()], - }; - - // get share meta and check account has been added - let res = mt.add_share_tenants(req).await; - info!("add share account res: {:?}", res); - assert!(res.is_ok()); - - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(share_meta.has_account(&account.to_string())); - - // get and check share account meta - let share_account_name = ShareConsumerIdent::new( - Tenant::new_or_err(account, "share_add_remove_account")?, - share_id, - ); - let (_share_account_meta_seq, share_account_meta) = - get_share_account_meta_or_err(mt.as_kv_api(), &share_account_name, "").await?; - assert_eq!(share_account_meta.share_id, share_id); - assert_eq!(share_account_meta.account, account.to_string()); - assert_eq!(share_account_meta.share_on, share_on); - - // get_grant_tenants_of_share - let req = GetShareGrantTenantsReq { - share_name: share_name.clone(), - }; - let resp = mt.get_grant_tenants_of_share(req).await; - assert!(resp.is_ok()); - let resp = resp.unwrap(); - assert_eq!(resp.accounts.len(), 1); - assert_eq!(resp.accounts[0].account, account.to_string()); - } - - info!("--- share tenant2.share2 to tenant1"); - { - let req = AddShareAccountsReq { - share_name: share_name3.clone(), - share_on, - if_exists, - accounts: vec![tenant_name1.to_string()], - }; - - // get share meta and check account has been added - let res = mt.add_share_tenants(req).await; - info!("add share account res: {:?}", res); - assert!(res.is_ok()); - } - - // test show share api - info!("--- show share check account information"); - { - let req = ShowSharesReq { - tenant: tenant1.clone(), - }; - - let res = mt.show_shares(req).await; - info!("show share res: {:?}", res); - assert!(res.is_ok()); - let resp = res.unwrap(); - - assert_eq!(resp.outbound_accounts.len(), 2); - assert_eq!(resp.outbound_accounts[0].share_name, share_name.clone()); - assert_eq!(resp.outbound_accounts[0].create_on, create_on.clone()); - assert_eq!( - resp.outbound_accounts[0].comment, - Some(comment1.to_string()) - ); - assert_eq!(resp.outbound_accounts[1].share_name, share_name2.clone()); - assert_eq!(resp.outbound_accounts[1].create_on, create_on.clone()); - assert_eq!( - resp.outbound_accounts[1].comment, - Some(comment2.to_string()) - ); - assert!(resp.outbound_accounts[0].accounts.is_some()); - assert!(resp.outbound_accounts[1].accounts.is_some()); - let accounts = resp.outbound_accounts[0].accounts.as_ref().unwrap(); - assert_eq!(accounts.len(), 1); - assert_eq!(accounts[0], account.to_string()); - assert_eq!( - resp.outbound_accounts[1].accounts.as_ref().unwrap().len(), - 0 - ); - } - - info!("--- add account account1 again"); - { - let req = AddShareAccountsReq { - share_name: share_name.clone(), - share_on, - if_exists, - accounts: vec![account.to_string()], - }; - - let res = mt.add_share_tenants(req).await; - info!("add share account res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!( - ErrorCode::SHARE_ACCOUNTS_ALREADY_EXISTS, - ErrorCode::from(err).code() - ); - } - - info!("--- add account account2"); - { - let req = AddShareAccountsReq { - share_name: share_name.clone(), - share_on, - if_exists, - accounts: vec![account2.to_string()], - }; - - let res = mt.add_share_tenants(req).await; - info!("add share account res: {:?}", res); - assert!(res.is_ok()); - - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(share_meta.has_account(&account2.to_string())); - } - - info!("--- remove account account2"); - { - let req = RemoveShareAccountsReq { - share_name: share_name.clone(), - if_exists, - accounts: vec![account2.to_string()], - }; - - let res = mt.remove_share_tenants(req).await; - info!("remove share account res: {:?}", res); - assert!(res.is_ok()); - - // check account2 has been removed from share_meta - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(!share_meta.has_account(&account2.to_string())); - - // check share account meta has been removed - let share_account_name = ShareConsumerIdent::new( - Tenant::new_or_err(account2, "share_add_remove_account")?, - share_id, - ); - let res = get_share_account_meta_or_err(mt.as_kv_api(), &share_account_name, "").await; - let err = res.unwrap_err(); - assert_eq!( - ErrorCode::UNKNOWN_SHARE_ACCOUNTS, - ErrorCode::from(err).code() - ); - } - - info!("--- drop share1 with if_exists=true"); - { - let req = DropShareReq { - if_exists: true, - share_name: share_name.clone(), - }; - - let res = mt.drop_share(req).await; - assert!(res.is_ok()); - - // check share account meta has been removed - let share_account_name = ShareConsumerIdent::new( - Tenant::new_or_err(account, "share_add_remove_account")?, - share_id, - ); - let res = get_share_account_meta_or_err(mt.as_kv_api(), &share_account_name, "").await; - let err = res.unwrap_err(); - assert_eq!( - ErrorCode::UNKNOWN_SHARE_ACCOUNTS, - ErrorCode::from(err).code() - ); - } - - Ok(()) - } - - #[minitrace::trace] - async fn share_grant_revoke_object< - MT: ShareApi + kvapi::AsKVApi + SchemaApi, - >( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant_name = "tenant1"; - - let tenant = Tenant::new_literal(tenant_name); - - let share1 = "share1"; - let db_name = "db1"; - let tbl_name = "table1"; - let db2_name = "db2"; - let tbl2_name = "table2"; - - let share_name = ShareNameIdent::new(&tenant, share1); - let share_id: u64; - let db_id: u64; - let table_id: u64; - - info!("--- create share1,db1,table1,table2"); - let create_on = Utc::now(); - { - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name.clone(), - comment: None, - create_on, - }; - - let res = mt.create_share(req).await; - info!("create share res: {:?}", res); - let res = res.unwrap(); - assert_eq!(1, res.share_id, "first database id is 1"); - share_id = res.share_id; - - let (share_name_seq, share_name_ret) = - get_share_id_to_name_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(share_name_seq > 0); - assert_eq!(ShareNameIdentRaw::from(share_name.clone()), share_name_ret); - - let plan = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: DatabaseNameIdent::new(&tenant, db_name), - meta: DatabaseMeta::default(), - }; - - let res = mt.create_database(plan).await?; - info!("create database res: {:?}", res); - db_id = res.db_id; - - let req = CreateTableReq { - create_option: CreateOption::Create, - name_ident: TableNameIdent { - tenant: tenant.clone(), - db_name: db_name.to_string(), - table_name: tbl_name.to_string(), - }, - table_meta: TableMeta::default(), - as_dropped: false, - }; - - let res = mt.create_table(req.clone()).await?; - info!("create table res: {:?}", res); - table_id = res.table_id; - - let plan = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: DatabaseNameIdent::new(&tenant, db2_name), - meta: DatabaseMeta::default(), - }; - - let req = CreateTableReq { - create_option: CreateOption::Create, - name_ident: TableNameIdent { - tenant: tenant.clone(), - db_name: db_name.to_string(), - table_name: tbl2_name.to_string(), - }, - table_meta: TableMeta::default(), - as_dropped: false, - }; - - let res = mt.create_table(req.clone()).await?; - info!("create table2 res: {:?}", res); - - let res = mt.create_database(plan).await?; - info!("create database res: {:?}", res); - - let req = CreateTableReq { - create_option: CreateOption::Create, - name_ident: TableNameIdent { - tenant: tenant.clone(), - db_name: db2_name.to_string(), - table_name: tbl2_name.to_string(), - }, - table_meta: TableMeta::default(), - as_dropped: false, - }; - - let res = mt.create_table(req.clone()).await?; - info!("create table res: {:?}", res); - } - - info!("--- grant unknown db2,table2"); - { - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Database("unknown_db".to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await; - info!("grant object res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::UNKNOWN_DATABASE, ErrorCode::from(err).code()); - - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Table( - db_name.to_string(), - "unknown_table".to_string(), - ), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await; - info!("grant object res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::UNKNOWN_TABLE, ErrorCode::from(err).code()); - } - - info!("--- grant unknown share2"); - { - let req = GrantShareObjectReq { - share_name: ShareNameIdent::new(&tenant, "share2"), - object: ShareGrantObjectName::Database("db2".to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await; - info!("grant object res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::UNKNOWN_SHARE, ErrorCode::from(err).code()); - } - - info!("--- grant table2 on a unbound database share"); - { - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Table(db2_name.to_string(), tbl2_name.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await; - info!("grant object res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::WRONG_SHARE_OBJECT, ErrorCode::from(err).code()); - } - - info!("--- grant db object and table object"); - { - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - assert_eq!(res.share_table_info.0, *share_name.name()); - assert!(res.share_table_info.1.unwrap().is_empty()); - - let tbl_ob_name = - ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()); - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: tbl_ob_name.clone(), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - - assert_eq!(res.share_table_info.0, *share_name.name()); - assert_eq!(res.share_table_info.1.as_ref().unwrap().len(), 1); - assert!( - res.share_table_info - .1 - .as_ref() - .unwrap() - .contains_key(tbl_name), - ); - - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - - match share_meta.database { - Some(entry) => match entry.object { - ShareGrantObject::Database(obj_db_id) => { - assert_eq!(obj_db_id, db_id); - - assert_eq!(entry.grant_on, create_on); - assert_eq!( - entry.privileges, - BitFlags::from(ShareGrantObjectPrivilege::Usage) - ); - } - _ => { - panic!("MUST has database entry!") - } - }, - None => { - panic!("MUST has database entry!") - } - } - - let object = ShareGrantObject::Table(table_id); - if let Some(entry) = share_meta.entries.get(&object.to_string()) { - assert_eq!(entry.object, object); - assert_eq!(entry.grant_on, create_on); - assert_eq!( - entry.privileges, - BitFlags::from(ShareGrantObjectPrivilege::Usage) - ); - } else { - panic!("MUST has table entry!") - } - } - - info!("--- grant db2, table2 on another bounded database share"); - { - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Database(db2_name.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await; - info!("grant object res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::WRONG_SHARE_OBJECT, ErrorCode::from(err).code()); - - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Table(db2_name.to_string(), tbl2_name.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await; - info!("grant object res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::WRONG_SHARE_OBJECT, ErrorCode::from(err).code()); - } - - info!("--- check db and table shared_by field"); - { - let mut shared_by = BTreeSet::new(); - shared_by.insert(share_id); - - { - let id_key = DatabaseId { db_id }; - - let db_meta: DatabaseMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(db_meta.shared_by, shared_by); - } - - { - let id_key = TableId { table_id }; - - let table_meta: TableMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(table_meta.shared_by, shared_by); - } - } - - info!("--- revoke share of table"); - { - let req = RevokeShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()), - update_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.revoke_share_object(req).await?; - info!("revoke object res: {:?}", res); - assert_eq!(res.share_table_info.0, *share_name.name()); - assert!(res.share_table_info.1.unwrap().is_empty()); - - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - - match share_meta.database { - Some(entry) => match entry.object { - ShareGrantObject::Database(obj_db_id) => { - assert_eq!(obj_db_id, db_id); - - assert_eq!(entry.grant_on, create_on); - assert_eq!( - entry.privileges, - BitFlags::from(ShareGrantObjectPrivilege::Usage) - ); - } - _ => { - panic!("MUST has database entry!") - } - }, - None => { - panic!("MUST has database entry!") - } - } - - let object = ShareGrantObject::Table(table_id); - assert!(share_meta.entries.get(&object.to_string()).is_none()); - } - - info!("--- check db and table shared_by field"); - { - let mut shared_by = BTreeSet::new(); - shared_by.insert(share_id); - - { - let id_key = DatabaseId { db_id }; - - let db_meta: DatabaseMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(db_meta.shared_by, shared_by); - } - - { - let id_key = TableId { table_id }; - - let table_meta: TableMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(table_meta.shared_by, BTreeSet::new()); - } - } - - info!("--- grant share of table again, and revoke the database"); - { - // first grant share table again - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - - // assert table share exists - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - let object = ShareGrantObject::Table(table_id); - assert!(share_meta.entries.get(&object.to_string()).is_some()); - - // then revoke the database - let req = RevokeShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - update_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.revoke_share_object(req).await?; - info!("revoke object res: {:?}", res); - assert_eq!(res.share_table_info.0, *share_name.name()); - assert!(res.share_table_info.1.is_none()); - - // assert share_meta.database is none, and share_meta.entries is empty - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(share_meta.database.is_none()); - assert!(share_meta.entries.is_empty()); - } - - info!("--- check db and table shared_by field"); - { - { - let id_key = DatabaseId { db_id }; - - let db_meta: DatabaseMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(db_meta.shared_by, BTreeSet::new()); - } - - { - let id_key = TableId { table_id }; - - let table_meta: TableMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(table_meta.shared_by, BTreeSet::new()); - } - } - - Ok(()) - } - - #[minitrace::trace] - async fn get_share_grant_objects< - MT: ShareApi + kvapi::AsKVApi + SchemaApi, - >( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant_name = "tenant1"; - let tenant = Tenant::new_literal(tenant_name); - - let share1 = "share1"; - let db_name = "db1"; - let tbl_name = "table1"; - - let share_name = ShareNameIdent::new(&tenant, share1); - - info!("--- get unknown share"); - { - let req = GetShareGrantObjectReq { - share_name: share_name.clone(), - }; - - let res = mt.get_share_grant_objects(req).await; - info!("get_share_grant_objects res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::UNKNOWN_SHARE, ErrorCode::from(err).code()); - } - - info!("--- create share1"); - let create_on = Utc::now(); - { - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name.clone(), - comment: None, - create_on, - }; - - let res = mt.create_share(req).await; - info!("create share res: {:?}", res); - let res = res.unwrap(); - assert_eq!(1, res.share_id, "first database id is 1"); - } - - info!("--- get share"); - { - let req = GetShareGrantObjectReq { - share_name: share_name.clone(), - }; - - let res = mt.get_share_grant_objects(req).await; - info!("get_share_grant_objects res: {:?}", res); - let res = res.unwrap(); - assert!(res.objects.is_empty()); - } - - info!("--- create db1,table1"); - { - let plan = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: DatabaseNameIdent::new(&tenant, db_name), - meta: DatabaseMeta::default(), - }; - - let res = mt.create_database(plan).await?; - info!("create database res: {:?}", res); - - let req = CreateTableReq { - create_option: CreateOption::Create, - name_ident: TableNameIdent { - tenant: tenant.clone(), - db_name: db_name.to_string(), - table_name: tbl_name.to_string(), - }, - table_meta: TableMeta::default(), - as_dropped: false, - }; - - let res = mt.create_table(req.clone()).await?; - info!("create table res: {:?}", res); - } - - info!("--- share db1 and table1"); - { - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - assert_eq!(1, res.spec_vec.unwrap().len()); - - let tbl_ob_name = - ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()); - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: tbl_ob_name.clone(), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - assert_eq!(1, res.spec_vec.unwrap().len()); - } - - info!("--- get all share objects"); - { - let req = GetShareGrantObjectReq { - share_name: share_name.clone(), - }; - - let res = mt.get_share_grant_objects(req).await; - info!("get_share_grant_objects res: {:?}", res); - let res = res.unwrap(); - assert_eq!(res.objects.len(), 2); - } - - Ok(()) - } - - #[minitrace::trace] - async fn get_grant_privileges_of_object< - MT: ShareApi + kvapi::AsKVApi + SchemaApi, - >( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant_name = "tenant1"; - let tenant = Tenant::new_literal(tenant_name); - - let share1 = "share1"; - let share2 = "share2"; - let share3 = "share3"; - let db_name = "db1"; - let tbl_name = "table1"; - let share_id; - - let share_name1 = ShareNameIdent::new(&tenant, share1); - let share_name2 = ShareNameIdent::new(&tenant, share2); - let share_name3 = ShareNameIdent::new(&tenant, share3); - - info!("--- get unknown object"); - { - let req = GetObjectGrantPrivilegesReq { - tenant: tenant.clone(), - object: ShareGrantObjectName::Database("db".to_string()), - }; - - let res = mt.get_grant_privileges_of_object(req).await; - info!("get_share_grant_objects res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::UNKNOWN_DATABASE, ErrorCode::from(err).code()); - - let req = GetObjectGrantPrivilegesReq { - tenant: tenant.clone(), - object: ShareGrantObjectName::Table("db".to_string(), "table".to_string()), - }; - - let res = mt.get_grant_privileges_of_object(req).await; - info!("get_share_grant_objects res: {:?}", res); - let err = res.unwrap_err(); - assert_eq!(ErrorCode::UNKNOWN_DATABASE, ErrorCode::from(err).code()); - } - - info!("--- create share1 and share2"); - let create_on = Utc::now(); - let grant_on = Utc::now(); - { - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name1.clone(), - comment: None, - create_on, - }; - - let res = mt.create_share(req).await; - assert!(res.is_ok()); - share_id = res.unwrap().share_id; - - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name2.clone(), - comment: None, - create_on, - }; - - let res = mt.create_share(req).await; - assert!(res.is_ok()); - } - - info!("--- create db1,table1"); - { - let plan = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: DatabaseNameIdent::new(&tenant, db_name), - meta: DatabaseMeta::default(), - }; - - let res = mt.create_database(plan).await?; - info!("create database res: {:?}", res); - - let req = CreateTableReq { - create_option: CreateOption::Create, - name_ident: TableNameIdent { - tenant: tenant.clone(), - db_name: db_name.to_string(), - table_name: tbl_name.to_string(), - }, - table_meta: TableMeta::default(), - as_dropped: false, - }; - - let res = mt.create_table(req.clone()).await?; - info!("create table res: {:?}", res); - } - - info!("--- share db1 and table1"); - { - let req = GrantShareObjectReq { - share_name: share_name1.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - grant_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - - let req = GrantShareObjectReq { - share_name: share_name2.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - grant_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - - let tbl_ob_name = - ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()); - let req = GrantShareObjectReq { - share_name: share_name1.clone(), - object: tbl_ob_name.clone(), - grant_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - } - - info!("--- get_grant_privileges_of_object of db and table"); - { - let req = GetObjectGrantPrivilegesReq { - tenant: tenant.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - }; - - let res = mt.get_grant_privileges_of_object(req).await; - assert!(res.is_ok()); - let res = res.unwrap(); - assert_eq!(res.privileges.len(), 2); - assert_eq!(&res.privileges[0].share_name, share1); - assert_eq!(res.privileges[0].grant_on, grant_on); - - let req = GetObjectGrantPrivilegesReq { - tenant: tenant.clone(), - object: ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()), - }; - - let res = mt.get_grant_privileges_of_object(req).await; - assert!(res.is_ok()); - let res = res.unwrap(); - assert_eq!(res.privileges.len(), 1); - assert_eq!(&res.privileges[0].share_name, share1); - assert_eq!(res.privileges[0].grant_on, grant_on); - } - - info!("--- drop share1 and check objects"); - { - let tenant_name2 = "tenant1"; - let tenant2 = Tenant::new_literal(tenant_name2); - let db2 = "db2"; - - let db_name2 = DatabaseNameIdent::new(&tenant2, db2); - - // first grant account tenant2 - let req = AddShareAccountsReq { - share_name: share_name1.clone(), - share_on: Utc::now(), - if_exists: false, - accounts: vec![tenant_name2.to_string()], - }; - let res = mt.add_share_tenants(req).await; - assert!(res.is_ok()); - - // tenant2 create a database from share1 - let req = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: db_name2.clone(), - meta: DatabaseMeta { - from_share: Some(share_name1.clone().into()), - ..Default::default() - }, - }; - - let res = mt.create_database(req).await; - info!("create database res: {:?}", res); - assert!(res.is_ok()); - - // cannot share a database created from a share - { - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name3.clone(), - comment: None, - create_on, - }; - - let res = mt.create_share(req).await; - assert!(res.is_ok()); - - let req = GrantShareObjectReq { - share_name: share_name3.clone(), - object: ShareGrantObjectName::Database(db2.to_string()), - grant_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await; - assert!(res.is_err()); - let err = res.unwrap_err(); - assert_eq!( - ErrorCode::CANNOT_SHARE_DATABASE_CREATED_FROM_SHARE, - ErrorCode::from(err).code() - ); - } - - let req = DropShareReq { - if_exists: true, - share_name: share_name1.clone(), - }; - - // get share meta - let share_id_key = ShareId { share_id }; - let share_meta: ShareMeta = get_kv_data(mt.as_kv_api(), &share_id_key).await?; - - let res = mt.drop_share(req).await; - assert!(res.is_ok()); - - // check if all the share data has been removed - let res = - is_all_share_data_removed(mt.as_kv_api(), &share_name1, share_id, &share_meta) - .await?; - assert!(res); - - // get_grant_privileges_of_object of db and table again - let req = GetObjectGrantPrivilegesReq { - tenant: tenant.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - }; - - let res = mt.get_grant_privileges_of_object(req).await; - assert!(res.is_ok()); - let res = res.unwrap(); - assert_eq!(res.privileges.len(), 1); - - let req = GetObjectGrantPrivilegesReq { - tenant: tenant.clone(), - object: ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()), - }; - - let res = mt.get_grant_privileges_of_object(req).await; - assert!(res.is_ok()); - let res = res.unwrap(); - assert_eq!(res.privileges.len(), 0); - } - - Ok(()) - } - - #[minitrace::trace] - async fn drop_share_database_and_table< - MT: ShareApi + kvapi::AsKVApi + SchemaApi, - >( - &self, - mt: &MT, - ) -> anyhow::Result<()> { - let tenant_name = "tenant1"; - let tenant = Tenant::new_literal(tenant_name); - - let share1 = "drop_share_database_and_table_share"; - let share2 = "drop_share_database_and_table_share2"; - let db_name = "drop_share_database_and_table_db"; - let tbl_name = "drop_share_database_and_table_table"; - let share_id: u64; - let share_id2: u64; - let db_id: u64; - let table_id: u64; - - let share_name = ShareNameIdent::new(&tenant, share1); - let share_name2 = ShareNameIdent::new(&tenant, share2); - - info!("--- create share1 and share2"); - let create_on = Utc::now(); - { - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name.clone(), - comment: None, - create_on, - }; - - let res = mt.create_share(req).await; - info!("create share res: {:?}", res); - let res = res.unwrap(); - assert_eq!(1, res.share_id, "first share id is 1"); - share_id = res.share_id; - - let req = CreateShareReq { - if_not_exists: false, - share_name: share_name2.clone(), - comment: None, - create_on, - }; - - let res = mt.create_share(req).await; - info!("create share res: {:?}", res); - let res = res.unwrap(); - share_id2 = res.share_id; - } - - info!("--- create db1,table1"); - { - let plan = CreateDatabaseReq { - create_option: CreateOption::Create, - name_ident: DatabaseNameIdent::new(&tenant, db_name), - meta: DatabaseMeta::default(), - }; - - let res = mt.create_database(plan).await?; - info!("create database res: {:?}", res); - db_id = res.db_id; - - let req = CreateTableReq { - create_option: CreateOption::Create, - name_ident: TableNameIdent { - tenant: tenant.clone(), - db_name: db_name.to_string(), - table_name: tbl_name.to_string(), - }, - table_meta: TableMeta::default(), - as_dropped: false, - }; - - let res = mt.create_table(req.clone()).await?; - info!("create table res: {:?}", res); - table_id = res.table_id; - } - - info!("--- share db1 and table1 to share1 and share2"); - { - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - assert_eq!(2, res.spec_vec.unwrap().len()); - - let tbl_ob_name = - ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()); - let req = GrantShareObjectReq { - share_name: share_name.clone(), - object: tbl_ob_name.clone(), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - assert_eq!(2, res.spec_vec.unwrap().len()); - - let req = GrantShareObjectReq { - share_name: share_name2.clone(), - object: ShareGrantObjectName::Database(db_name.to_string()), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - assert_eq!(2, res.spec_vec.unwrap().len()); - - let tbl_ob_name = - ShareGrantObjectName::Table(db_name.to_string(), tbl_name.to_string()); - let req = GrantShareObjectReq { - share_name: share_name2.clone(), - object: tbl_ob_name.clone(), - grant_on: create_on, - privilege: ShareGrantObjectPrivilege::Usage, - }; - - let res = mt.grant_share_object(req).await?; - info!("grant object res: {:?}", res); - assert_eq!(2, res.spec_vec.unwrap().len()); - } - - info!("--- check db and table shared_by field"); - { - let mut shared_by = BTreeSet::new(); - shared_by.insert(share_id); - shared_by.insert(share_id2); - - { - let id_key = DatabaseId { db_id }; - - let db_meta: DatabaseMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(db_meta.shared_by, shared_by); - } - - { - let id_key = TableId { table_id }; - - let table_meta: TableMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(table_meta.shared_by, shared_by); - } - } - - info!("--- drop share2 and check db\table shared_by field"); - { - let req = DropShareReq { - if_exists: true, - share_name: share_name2.clone(), - }; - - let res = mt.drop_share(req).await; - assert!(res.is_ok()); - - let mut shared_by = BTreeSet::new(); - shared_by.insert(share_id); - - { - let id_key = DatabaseId { db_id }; - - let db_meta: DatabaseMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(db_meta.shared_by, shared_by); - } - - { - let id_key = TableId { table_id }; - - let table_meta: TableMeta = get_kv_data(mt.as_kv_api(), &id_key).await?; - assert_eq!(table_meta.shared_by, shared_by); - } - } - - info!("--- drop share table"); - { - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - let table_key_name = ShareGrantObject::Table(table_id).to_string(); - assert!(share_meta.entries.contains_key(&table_key_name)); - - let plan = DropTableByIdReq { - if_exists: false, - tenant: tenant.clone(), - table_name: tbl_name.to_string(), - tb_id: table_id, - db_id, - }; - let _res = mt.drop_table_by_id(plan).await; - - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(!share_meta.entries.contains_key(&table_key_name)); - } - - info!("--- drop share database"); - { - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(share_meta.database.is_some()); - - mt.drop_database(DropDatabaseReq { - if_exists: false, - name_ident: DatabaseNameIdent::new(&tenant, db_name), - }) - .await?; - - let (_share_meta_seq, share_meta) = - get_share_meta_by_id_or_err(mt.as_kv_api(), share_id, "").await?; - assert!(share_meta.database.is_none()); - } - - Ok(()) - } -} diff --git a/src/meta/api/src/util.rs b/src/meta/api/src/util.rs index 74a76090e969..b891be29cd7b 100644 --- a/src/meta/api/src/util.rs +++ b/src/meta/api/src/util.rs @@ -13,32 +13,18 @@ // limitations under the License. use std::any::type_name; -use std::collections::BTreeMap; -use std::collections::HashSet; use std::fmt::Display; use std::sync::Arc; use databend_common_meta_app::app_error::AppError; -use databend_common_meta_app::app_error::ShareHasNoGrantedDatabase; use databend_common_meta_app::app_error::UnknownDatabase; use databend_common_meta_app::app_error::UnknownDatabaseId; -use databend_common_meta_app::app_error::UnknownShare; -use databend_common_meta_app::app_error::UnknownShareAccounts; -use databend_common_meta_app::app_error::UnknownShareEndpoint; -use databend_common_meta_app::app_error::UnknownShareEndpointId; -use databend_common_meta_app::app_error::UnknownShareId; use databend_common_meta_app::app_error::UnknownTable; use databend_common_meta_app::app_error::UnknownTableId; use databend_common_meta_app::app_error::VirtualColumnNotFound; -use databend_common_meta_app::app_error::WrongShare; -use databend_common_meta_app::app_error::WrongShareObject; use databend_common_meta_app::primitive::Id; use databend_common_meta_app::schema::database_name_ident::DatabaseNameIdent; -use databend_common_meta_app::schema::database_name_ident::DatabaseNameIdentRaw; use databend_common_meta_app::schema::DBIdTableName; -use databend_common_meta_app::schema::DatabaseId; -use databend_common_meta_app::schema::DatabaseIdToName; -use databend_common_meta_app::schema::DatabaseMeta; use databend_common_meta_app::schema::DatabaseType; use databend_common_meta_app::schema::IndexId; use databend_common_meta_app::schema::IndexMeta; @@ -50,11 +36,6 @@ use databend_common_meta_app::schema::TableMeta; use databend_common_meta_app::schema::TableNameIdent; use databend_common_meta_app::schema::VirtualColumnIdent; use databend_common_meta_app::schema::VirtualColumnMeta; -use databend_common_meta_app::share::share_end_point_ident::ShareEndpointIdentRaw; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::share_name_ident::ShareNameIdentRaw; -use databend_common_meta_app::share::*; -use databend_common_meta_app::tenant::Tenant; use databend_common_meta_app::KeyWithTenant; use databend_common_meta_kvapi::kvapi; use databend_common_meta_kvapi::kvapi::DirName; @@ -75,11 +56,8 @@ use databend_common_meta_types::TxnOp; use databend_common_meta_types::TxnOpResponse; use databend_common_meta_types::TxnRequest; use databend_common_proto_conv::FromToProto; -use enumflags2::BitFlags; use futures::TryStreamExt; use log::debug; -use log::warn; -use ConditionResult::Eq; use crate::kv_app_error::KVAppError; use crate::kv_pb_api::KVPbApi; @@ -458,322 +436,6 @@ pub async fn get_table_by_id_or_err( Ok((seq, table_meta)) } -// Return (share_endpoint_id_seq, share_endpoint_id, share_endpoint_meta_seq, share_endpoint_meta) -pub async fn get_share_endpoint_or_err( - kv_api: &(impl kvapi::KVApi + ?Sized), - name_key: &ShareEndpointIdent, - msg: impl Display, -) -> Result<(u64, u64, u64, ShareEndpointMeta), KVAppError> { - let (share_endpoint_id_seq, share_endpoint_id) = get_u64_value(kv_api, name_key).await?; - share_endpoint_has_to_exist(share_endpoint_id_seq, name_key, &msg)?; - - let (share_endpoint_meta_seq, share_endpoint_meta) = - get_share_endpoint_meta_by_id_or_err(kv_api, share_endpoint_id, msg).await?; - - Ok(( - share_endpoint_id_seq, - share_endpoint_id, - share_endpoint_meta_seq, - share_endpoint_meta, - )) -} - -async fn get_share_endpoint_meta_by_id_or_err( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_endpoint_id: u64, - msg: impl Display, -) -> Result<(u64, ShareEndpointMeta), KVAppError> { - let id_key = ShareEndpointId { share_endpoint_id }; - - let (share_endpoint_meta_seq, share_endpoint_meta) = get_pb_value(kv_api, &id_key).await?; - share_endpoint_meta_has_to_exist(share_endpoint_meta_seq, share_endpoint_id, msg)?; - - Ok((share_endpoint_meta_seq, share_endpoint_meta.unwrap())) -} - -fn share_endpoint_meta_has_to_exist( - seq: u64, - share_endpoint_id: u64, - msg: impl Display, -) -> Result<(), KVAppError> { - if seq == 0 { - debug!( - seq = seq, - share_endpoint_id = share_endpoint_id; - "share endpoint meta does not exist" - ); - - Err(KVAppError::AppError(AppError::UnknownShareEndpointId( - UnknownShareEndpointId::new( - share_endpoint_id, - format!("{}: {}", msg, share_endpoint_id), - ), - ))) - } else { - Ok(()) - } -} - -fn share_endpoint_has_to_exist( - seq: u64, - name_key: &ShareEndpointIdent, - msg: impl Display, -) -> Result<(), KVAppError> { - if seq == 0 { - debug!(seq = seq, name_key :? =(name_key); "share endpoint does not exist"); - - Err(KVAppError::AppError(AppError::UnknownShareEndpoint( - UnknownShareEndpoint::new(name_key.name(), format!("{}", msg)), - ))) - } else { - Ok(()) - } -} - -pub async fn get_share_endpoint_id_to_name_or_err( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_endpoint_id: u64, - msg: impl Display, -) -> Result<(u64, ShareEndpointIdentRaw), KVAppError> { - let id_key = ShareEndpointIdToName { share_endpoint_id }; - - let (share_endpoint_name_seq, share_endpoint) = get_pb_value(kv_api, &id_key).await?; - if share_endpoint_name_seq == 0 { - debug!( - share_endpoint_name_seq = share_endpoint_name_seq, - share_endpoint_id = share_endpoint_id; - "share meta does not exist" - ); - - return Err(KVAppError::AppError(AppError::UnknownShareEndpointId( - UnknownShareEndpointId::new( - share_endpoint_id, - format!("{}: {}", msg, share_endpoint_id), - ), - ))); - } - - Ok((share_endpoint_name_seq, share_endpoint.unwrap())) -} - -// Return (share_id_seq, share_id, share_meta_seq, share_meta) -pub async fn get_share_or_err( - kv_api: &(impl kvapi::KVApi + ?Sized), - name_key: &ShareNameIdent, - msg: impl Display, -) -> Result<(u64, u64, u64, ShareMeta), KVAppError> { - let (share_id_seq, share_id) = get_u64_value(kv_api, name_key).await?; - share_has_to_exist(share_id_seq, name_key, &msg)?; - - let (share_meta_seq, share_meta) = get_share_meta_by_id_or_err(kv_api, share_id, msg).await?; - - Ok((share_id_seq, share_id, share_meta_seq, share_meta)) -} - -/// Returns (share_meta_seq, share_meta) -pub async fn get_share_meta_by_id_or_err( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_id: u64, - msg: impl Display, -) -> Result<(u64, ShareMeta), KVAppError> { - let id_key = ShareId { share_id }; - - let (share_meta_seq, share_meta) = get_pb_value(kv_api, &id_key).await?; - share_meta_has_to_exist(share_meta_seq, share_id, msg)?; - - Ok((share_meta_seq, share_meta.unwrap())) -} - -fn share_meta_has_to_exist(seq: u64, share_id: u64, msg: impl Display) -> Result<(), KVAppError> { - if seq == 0 { - debug!(seq = seq, share_id = share_id; "share meta does not exist"); - - Err(KVAppError::AppError(AppError::UnknownShareId( - UnknownShareId::new(share_id, format!("{}: {}", msg, share_id)), - ))) - } else { - Ok(()) - } -} - -/// Return OK if a share_id or share_meta exists by checking the seq. -/// -/// Otherwise returns UnknownShare error -fn share_has_to_exist( - seq: u64, - share_name_ident: &ShareNameIdent, - msg: impl Display, -) -> Result<(), KVAppError> { - if seq == 0 { - debug!(seq = seq, share_name_ident :? =(share_name_ident); "share does not exist"); - - Err(KVAppError::AppError(AppError::UnknownShare( - UnknownShare::new( - share_name_ident.name(), - format!("{}: {}", msg, share_name_ident.display()), - ), - ))) - } else { - Ok(()) - } -} - -/// Returns (share_account_meta_seq, share_account_meta) -pub async fn get_share_account_meta_or_err( - kv_api: &(impl kvapi::KVApi + ?Sized), - name_key: &ShareConsumerIdent, - msg: impl Display, -) -> Result<(u64, ShareAccountMeta), KVAppError> { - let (share_account_meta_seq, share_account_meta): (u64, Option) = - get_pb_value(kv_api, name_key).await?; - share_account_meta_has_to_exist(share_account_meta_seq, name_key, msg)?; - - Ok(( - share_account_meta_seq, - // Safe unwrap(): share_meta_seq > 0 implies share_meta is not None. - share_account_meta.unwrap(), - )) -} - -/// Return OK if a share_id or share_account_meta exists by checking the seq. -/// -/// Otherwise returns UnknownShareAccounts error -fn share_account_meta_has_to_exist( - seq: u64, - name_key: &ShareConsumerIdent, - msg: impl Display, -) -> Result<(), KVAppError> { - if seq == 0 { - debug!(seq = seq, name_key :? =(name_key); "share account does not exist"); - - Err(KVAppError::AppError(AppError::UnknownShareAccounts( - UnknownShareAccounts::new( - &[name_key.tenant_name().to_string()], - name_key.share_id(), - format!("{}: {}", msg, name_key.display()), - ), - ))) - } else { - Ok(()) - } -} - -/// Returns (share_meta_seq, share_meta) -pub async fn get_share_id_to_name_or_err( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_id: u64, - msg: impl Display, -) -> Result<(u64, ShareNameIdentRaw), KVAppError> { - let id_key = ShareIdToName { share_id }; - - let (share_name_seq, share_name) = get_pb_value(kv_api, &id_key).await?; - if share_name_seq == 0 { - debug!(share_name_seq = share_name_seq, share_id = share_id; "share meta does not exist"); - - return Err(KVAppError::AppError(AppError::UnknownShareId( - UnknownShareId::new(share_id, format!("{}: {}", msg, share_id)), - ))); - } - - Ok((share_name_seq, share_name.unwrap())) -} - -pub fn get_share_database_id_and_privilege( - name_key: &ShareNameIdent, - share_meta: &ShareMeta, -) -> Result<(u64, BitFlags), KVAppError> { - if let Some(entry) = &share_meta.database { - if let ShareGrantObject::Database(db_id) = entry.object { - return Ok((db_id, entry.privileges)); - } else { - unreachable!("database MUST be Database object"); - } - } - - Err(KVAppError::AppError(AppError::ShareHasNoGrantedDatabase( - ShareHasNoGrantedDatabase::new(name_key.tenant_name(), name_key.share_name()), - ))) -} - -// Return true if all the database data has been removed. -pub async fn is_all_db_data_removed( - kv_api: &(impl kvapi::KVApi + ?Sized), - db_id: u64, -) -> Result { - let dbid = DatabaseId { db_id }; - - let (db_meta_seq, db_meta): (_, Option) = get_pb_value(kv_api, &dbid).await?; - debug_assert_eq!((db_meta_seq == 0), db_meta.is_none()); - if db_meta_seq != 0 { - return Ok(false); - } - - let id_to_name = DatabaseIdToName { db_id }; - let (name_ident_seq, ident_raw): (_, Option) = - get_pb_value(kv_api, &id_to_name).await?; - debug_assert_eq!((name_ident_seq == 0), ident_raw.is_none()); - if name_ident_seq != 0 { - return Ok(false); - } - - Ok(true) -} - -// Return (true, `DataBaseMeta.from_share`) if the database needs to be removed, otherwise return (false, None). -// f: the predict function whether or not the database needs to be removed -// base on the database meta passed by the user. -// When the database needs to be removed, add `TxnCondition` into `condition` -// and `TxnOp` into the `if_then`. -pub async fn is_db_need_to_be_remove( - kv_api: &(impl kvapi::KVApi + ?Sized), - db_id: u64, - mut f: F, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(bool, Option), KVAppError> -where - F: FnMut(&DatabaseMeta) -> bool, -{ - let dbid = DatabaseId { db_id }; - - let (db_meta_seq, db_meta): (_, Option) = get_pb_value(kv_api, &dbid).await?; - if db_meta_seq == 0 { - return Ok((false, None)); - } - - let id_to_name = DatabaseIdToName { db_id }; - let (name_ident_seq, _ident_raw): (_, Option) = - get_pb_value(kv_api, &id_to_name).await?; - if name_ident_seq == 0 { - return Ok((false, None)); - } - - if let Some(db_meta) = db_meta { - if f(&db_meta) { - condition.push(txn_cond_seq(&dbid, Eq, db_meta_seq)); - if_then.push(txn_op_del(&dbid)); - condition.push(txn_cond_seq(&id_to_name, Eq, name_ident_seq)); - if_then.push(txn_op_del(&id_to_name)); - - return Ok((true, db_meta.from_share)); - } - } - Ok((false, None)) -} - -pub async fn get_object_shared_by_share_ids( - kv_api: &(impl kvapi::KVApi + ?Sized), - object: &ShareGrantObject, -) -> Result<(u64, ObjectSharedByShareIds), KVAppError> { - let (seq, share_ids): (u64, Option) = - get_pb_value(kv_api, object).await?; - - match share_ids { - Some(share_ids) => Ok((seq, share_ids)), - None => Ok((0, ObjectSharedByShareIds::default())), - } -} - pub async fn get_table_names_by_ids( kv_api: &(impl kvapi::KVApi + ?Sized), ids: &[u64], @@ -893,310 +555,6 @@ pub async fn list_tables_from_unshare_db( .await } -pub async fn list_tables_from_share_db( - kv_api: &(impl kvapi::KVApi + ?Sized), - share: ShareNameIdent, - tenant_dbname: &DatabaseNameIdent, -) -> Result>, KVAppError> { - let res = get_share_or_err( - kv_api, - &share, - format!("list_tables_from_share_db: {}", share.display()), - ) - .await; - - let (share_id_seq, _share_id, _share_meta_seq, share_meta) = match res { - Ok(x) => x, - Err(e) => { - return Err(e); - } - }; - if share_id_seq == 0 { - return Err(KVAppError::AppError(AppError::WrongShare(WrongShare::new( - share.to_string_key(), - )))); - } - - let mut ids = Vec::with_capacity(share_meta.entries.len()); - for (_, entry) in share_meta.entries.iter() { - if let ShareGrantObject::Table(table_id) = entry.object { - ids.push(table_id); - } - } - get_tableinfos_by_ids( - kv_api, - &ids, - tenant_dbname, - None, - DatabaseType::ShareDB(share.into()), - ) - .await -} - -pub async fn convert_share_meta_to_spec( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_name: &str, - share_id: u64, - share_meta: ShareMeta, -) -> Result { - let (database, db_privileges) = if let Some(database) = share_meta.database { - if let ShareGrantObject::Database(db_id) = database.object { - let id_key = DatabaseIdToName { db_id }; - - let (_db_meta_seq, db_ident_raw): (_, Option) = - get_pb_value(kv_api, &id_key).await?; - if let Some(db_ident_raw) = db_ident_raw { - ( - Some(ShareDatabaseSpec { - name: db_ident_raw.database_name().to_string(), - id: db_id, - }), - Some(database.privileges), - ) - } else { - (None, None) - } - } else { - (None, None) - } - } else { - (None, None) - }; - - let mut tables = vec![]; - for (_, entry) in share_meta.entries.iter() { - if let ShareGrantObject::Table(table_id) = entry.object { - let table_id_to_name_key = TableIdToName { table_id }; - let (_table_id_to_name_seq, table_name): (_, Option) = - get_pb_value(kv_api, &table_id_to_name_key).await?; - if let Some(table_name) = table_name { - tables.push(ShareTableSpec::new( - &table_name.table_name, - table_name.db_id, - table_id, - )); - } - } - } - - Ok(ShareSpec { - name: share_name.to_owned(), - share_id, - version: 1, - database, - tables, - tenants: Vec::from_iter(share_meta.accounts.into_iter()), - db_privileges, - comment: share_meta.comment.clone(), - share_on: Some(share_meta.share_on), - }) -} - -// return share name and new share meta -pub async fn remove_db_from_share( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_id: u64, - db_id: u64, - db_name: &DatabaseNameIdent, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(String, ShareMeta), KVAppError> { - let (_seq, share_name) = get_share_id_to_name_or_err( - kv_api, - share_id, - format!("remove_db_from_share: {}", share_id), - ) - .await?; - - let (share_meta_seq, mut share_meta) = get_share_meta_by_id_or_err( - kv_api, - share_id, - format!("remove_db_from_share: {}", share_id), - ) - .await?; - - match share_meta.database { - Some(entry) => { - if let ShareGrantObject::Database(share_db_id) = entry.object { - if share_db_id != db_id { - return Err(KVAppError::AppError(AppError::WrongShareObject( - WrongShareObject::new(db_name.database_name()), - ))); - } - } - } - None => { - return Err(KVAppError::AppError(AppError::ShareHasNoGrantedDatabase( - ShareHasNoGrantedDatabase::new(db_name.tenant_name(), share_name.name()), - ))); - } - } - share_meta.database = None; - share_meta.entries = BTreeMap::new(); - - let id_key = ShareId { share_id }; - condition.push(txn_cond_seq(&id_key, Eq, share_meta_seq)); - if_then.push(txn_op_put(&id_key, serialize_struct(&share_meta)?)); - - Ok((share_name.name().to_string(), share_meta)) -} - -// return (share name, new share meta, new share table info) -pub async fn remove_table_from_share( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_id: u64, - table_id: u64, - tenant: &Tenant, - condition: &mut Vec, - if_then: &mut Vec, -) -> Result<(String, ShareMeta, Option), KVAppError> { - let (_seq, share_name) = get_share_id_to_name_or_err( - kv_api, - share_id, - format!("remove_table_from_share: {}", share_id), - ) - .await?; - - let (share_meta_seq, mut share_meta) = get_share_meta_by_id_or_err( - kv_api, - share_id, - format!("remove_table_from_share: {}", share_id), - ) - .await?; - - let mut remove_table_name = None; - let entries = share_meta.entries.clone(); - for (table_name, entry) in entries { - if let ShareGrantObject::Table(share_table_id) = entry.object { - if share_table_id == table_id { - remove_table_name = Some(table_name); - break; - } - } - } - match remove_table_name { - Some(table_name) => { - share_meta.entries.remove(&table_name); - } - None => { - warn!( - "remove_table_from_share: table-id {} not found of share {} in tenant {}", - table_id, - share_name.name(), - tenant.tenant_name() - ); - } - } - - let id_key = ShareId { share_id }; - condition.push(txn_cond_seq(&id_key, Eq, share_meta_seq)); - if_then.push(txn_op_put(&id_key, serialize_struct(&share_meta)?)); - - let mut db_ident_raw = None; - let mut shared_db_id = 0; - if let Some(ref entry) = share_meta.database { - if let ShareGrantObject::Database(db_id) = entry.object { - let db_id_key = DatabaseIdToName { db_id }; - let (_db_name_seq, db_name_ident_raw): (_, Option) = - get_pb_value(kv_api, &db_id_key).await?; - db_ident_raw = db_name_ident_raw; - shared_db_id = db_id; - } else { - return Err(KVAppError::AppError(AppError::ShareHasNoGrantedDatabase( - ShareHasNoGrantedDatabase::new(tenant.tenant_name(), share_name.name()), - ))); - } - } - - let share_table_info = match db_ident_raw { - Some(db_ident_raw) => { - let mut table_ids = HashSet::new(); - for entry in share_meta.entries.values() { - if let ShareGrantObject::Table(table_id) = entry.object { - table_ids.insert(table_id); - } else { - unreachable!(); - } - } - let db_name = db_ident_raw.to_tident(()); - let all_tables = list_tables_from_unshare_db(kv_api, shared_db_id, &db_name).await?; - let table_infos = BTreeMap::from_iter( - all_tables - .iter() - .filter(|table_info| table_ids.contains(&table_info.ident.table_id)) - .map(|table_info| { - let mut table_info = table_info.as_ref().clone(); - table_info.db_type = DatabaseType::ShareDB(share_name.clone()); - (table_info.name.clone(), table_info) - }) - .collect::>(), - ); - - if table_infos.is_empty() { - None - } else { - Some(table_infos) - } - } - None => { - return Err(KVAppError::AppError(AppError::ShareHasNoGrantedDatabase( - ShareHasNoGrantedDatabase::new(tenant.tenant_name(), share_name.name()), - ))); - } - }; - - Ok((share_name.name().to_string(), share_meta, share_table_info)) -} - -pub async fn get_share_table_info( - kv_api: &(impl kvapi::KVApi + ?Sized), - share_name: &ShareNameIdent, - share_meta: &ShareMeta, -) -> Result { - let mut db_ident_raw = None; - let mut shared_db_id = 0; - if let Some(ref entry) = share_meta.database { - if let ShareGrantObject::Database(db_id) = entry.object { - let db_id_key = DatabaseIdToName { db_id }; - let (_db_name_seq, db_name_ident): (_, Option) = - get_pb_value(kv_api, &db_id_key).await?; - db_ident_raw = db_name_ident; - shared_db_id = db_id; - } else { - unreachable!(); - } - } - - match db_ident_raw { - Some(db_name) => { - let mut table_ids = HashSet::new(); - for entry in share_meta.entries.values() { - if let ShareGrantObject::Table(table_id) = entry.object { - table_ids.insert(table_id); - } else { - unreachable!(); - } - } - let db_name = db_name.to_tident(()); - let all_tables = list_tables_from_unshare_db(kv_api, shared_db_id, &db_name).await?; - let table_infos = BTreeMap::from_iter( - all_tables - .iter() - .filter(|table_info| table_ids.contains(&table_info.ident.table_id)) - .map(|table_info| { - let mut table_info = table_info.as_ref().clone(); - table_info.db_type = DatabaseType::ShareDB(share_name.clone().into()); - (table_info.name.clone(), table_info) - }) - .collect::>(), - ); - - Ok((share_name.name().to_string(), Some(table_infos))) - } - None => Ok((share_name.name().to_string(), None)), - } -} - pub async fn get_index_metas_by_ids( kv_api: &(impl kvapi::KVApi + ?Sized), id_name_list: Vec<(u64, String)>, diff --git a/src/meta/app/src/schema/database.rs b/src/meta/app/src/schema/database.rs index 70feca8d1d6f..11b2206ab72a 100644 --- a/src/meta/app/src/schema/database.rs +++ b/src/meta/app/src/schema/database.rs @@ -25,7 +25,6 @@ use chrono::Utc; use super::CreateOption; use crate::schema::database_name_ident::DatabaseNameIdent; use crate::share::share_name_ident::ShareNameIdentRaw; -use crate::share::ShareSpec; use crate::tenant::Tenant; use crate::tenant::ToTenant; use crate::KeyWithTenant; @@ -43,46 +42,6 @@ pub struct DatabaseIdent { pub seq: u64, } -#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] -pub struct DatabaseId { - pub db_id: u64, -} - -impl DatabaseId { - pub fn new(db_id: u64) -> Self { - DatabaseId { db_id } - } -} - -impl From for DatabaseId { - fn from(db_id: u64) -> Self { - DatabaseId { db_id } - } -} - -impl Display for DatabaseId { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.db_id) - } -} - -#[derive(Clone, Debug, Default, Eq, PartialEq)] -pub struct DatabaseIdToName { - pub db_id: u64, -} - -impl Display for DatabaseIdToName { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.db_id) - } -} - -impl DatabaseIdToName { - pub fn new(db_id: u64) -> Self { - DatabaseIdToName { db_id } - } -} - #[derive(Clone, Debug, Eq, PartialEq)] pub struct DatabaseMeta { pub engine: String, @@ -212,7 +171,6 @@ impl Display for CreateDatabaseReq { #[derive(serde::Serialize, serde::Deserialize, Clone, Debug, Eq, PartialEq)] pub struct CreateDatabaseReply { pub db_id: u64, - pub spec_vec: Option>, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -256,9 +214,7 @@ impl Display for DropDatabaseReq { } #[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)] -pub struct DropDatabaseReply { - pub spec_vec: Option>, -} +pub struct DropDatabaseReply {} #[derive(Clone, Debug, PartialEq, Eq)] pub struct UndropDatabaseReq { @@ -326,68 +282,3 @@ impl ListDatabaseReq { &self.tenant } } - -mod kvapi_key_impl { - use databend_common_meta_kvapi::kvapi; - - use crate::schema::database_name_ident::DatabaseNameIdentRaw; - use crate::schema::DatabaseId; - use crate::schema::DatabaseIdToName; - use crate::schema::DatabaseMeta; - - impl kvapi::KeyCodec for DatabaseId { - fn encode_key(&self, b: kvapi::KeyBuilder) -> kvapi::KeyBuilder { - b.push_u64(self.db_id) - } - - fn decode_key(parser: &mut kvapi::KeyParser) -> Result { - let db_id = parser.next_u64()?; - Ok(Self { db_id }) - } - } - - /// "__fd_database_by_id/" - impl kvapi::Key for DatabaseId { - const PREFIX: &'static str = "__fd_database_by_id"; - - type ValueType = DatabaseMeta; - - fn parent(&self) -> Option { - None - } - } - - impl kvapi::KeyCodec for DatabaseIdToName { - fn encode_key(&self, b: kvapi::KeyBuilder) -> kvapi::KeyBuilder { - b.push_u64(self.db_id) - } - - fn decode_key(parser: &mut kvapi::KeyParser) -> Result { - let db_id = parser.next_u64()?; - Ok(Self { db_id }) - } - } - - /// "__fd_database_id_to_name/ -> DatabaseNameIdent" - impl kvapi::Key for DatabaseIdToName { - const PREFIX: &'static str = "__fd_database_id_to_name"; - - type ValueType = DatabaseNameIdentRaw; - - fn parent(&self) -> Option { - Some(DatabaseId::new(self.db_id).to_string_key()) - } - } - - impl kvapi::Value for DatabaseMeta { - fn dependency_keys(&self) -> impl IntoIterator { - [] - } - } - - impl kvapi::Value for DatabaseNameIdentRaw { - fn dependency_keys(&self) -> impl IntoIterator { - [] - } - } -} diff --git a/src/meta/app/src/schema/database_id_history_ident.rs b/src/meta/app/src/schema/database_id_history_ident.rs index 0d129baf6f29..c57069330241 100644 --- a/src/meta/app/src/schema/database_id_history_ident.rs +++ b/src/meta/app/src/schema/database_id_history_ident.rs @@ -39,8 +39,9 @@ mod kvapi_impl { use databend_common_meta_kvapi::kvapi; use databend_common_meta_kvapi::kvapi::Key; - use crate::schema::DatabaseId; + use crate::schema::DatabaseIdIdent; use crate::schema::DbIdList; + use crate::tenant::Tenant; use crate::tenant_key::resource::TenantResource; pub struct Resource; @@ -53,9 +54,10 @@ mod kvapi_impl { impl kvapi::Value for DbIdList { fn dependency_keys(&self) -> impl IntoIterator { + // TODO(TIdent): add real tenant: self.id_list .iter() - .map(|id| DatabaseId::new(*id).to_string_key()) + .map(|id| DatabaseIdIdent::new(Tenant::new_literal("dummy"), *id).to_string_key()) } } diff --git a/src/meta/app/src/schema/database_id_ident.rs b/src/meta/app/src/schema/database_id_ident.rs new file mode 100644 index 000000000000..6a3652d82996 --- /dev/null +++ b/src/meta/app/src/schema/database_id_ident.rs @@ -0,0 +1,90 @@ +// Copyright 2021 Datafuse Labs +// +// 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. + +use crate::tenant_key::ident::TIdent; +use crate::tenant_key::raw::TIdentRaw; + +pub type DatabaseIdIdent = TIdent; +pub type DatabaseIdIdentRaw = TIdentRaw; + +pub use kvapi_impl::Resource; + +impl DatabaseIdIdent { + pub fn database_id(&self) -> u64 { + *self.name() + } +} + +impl DatabaseIdIdentRaw { + pub fn database_id(&self) -> u64 { + *self.name() + } +} + +mod kvapi_impl { + + use databend_common_meta_kvapi::kvapi; + + use crate::schema::DatabaseMeta; + use crate::tenant_key::resource::TenantResource; + + pub struct Resource; + impl TenantResource for Resource { + const PREFIX: &'static str = "__fd_database_by_id"; + const TYPE: &'static str = "DatabaseIdIdent"; + const HAS_TENANT: bool = false; + type ValueType = DatabaseMeta; + } + + impl kvapi::Value for DatabaseMeta { + fn dependency_keys(&self) -> impl IntoIterator { + [] + } + } + + // // Use these error types to replace usage of ErrorCode if possible. + // impl From> for ErrorCode { + // impl From> for ErrorCode { +} + +#[cfg(test)] +mod tests { + use databend_common_meta_kvapi::kvapi::Key; + + use super::DatabaseIdIdent; + use crate::tenant::Tenant; + + #[test] + fn test_background_job_id_ident() { + let tenant = Tenant::new_literal("dummy"); + let ident = DatabaseIdIdent::new(tenant, 3); + + let key = ident.to_string_key(); + assert_eq!(key, "__fd_database_by_id/3"); + + assert_eq!(ident, DatabaseIdIdent::from_str_key(&key).unwrap()); + } + + #[test] + fn test_background_job_id_ident_with_key_space() { + // TODO(xp): implement this test + // let tenant = Tenant::new_literal("test"); + // let ident = DatabaseIdIdent::new(tenant, 3); + // + // let key = ident.to_string_key(); + // assert_eq!(key, "__fd_database_by_id/3"); + // + // assert_eq!(ident, DatabaseIdIdent::from_str_key(&key).unwrap()); + } +} diff --git a/src/meta/app/src/schema/database_id_to_name_ident.rs b/src/meta/app/src/schema/database_id_to_name_ident.rs new file mode 100644 index 000000000000..56cd3758eac0 --- /dev/null +++ b/src/meta/app/src/schema/database_id_to_name_ident.rs @@ -0,0 +1,91 @@ +// Copyright 2021 Datafuse Labs +// +// 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. + +use crate::tenant_key::ident::TIdent; +use crate::tenant_key::raw::TIdentRaw; + +pub type DatabaseIdToNameIdent = TIdent; +pub type DatabaseIdToNameIdentRaw = TIdentRaw; + +pub use kvapi_impl::Resource; + +impl DatabaseIdToNameIdent { + pub fn database_id(&self) -> u64 { + *self.name() + } +} + +impl DatabaseIdToNameIdentRaw { + pub fn database_id(&self) -> u64 { + *self.name() + } +} + +mod kvapi_impl { + + use databend_common_meta_kvapi::kvapi; + + use crate::schema::database_name_ident::DatabaseNameIdentRaw; + use crate::tenant_key::resource::TenantResource; + + pub struct Resource; + impl TenantResource for Resource { + const PREFIX: &'static str = "__fd_database_id_to_name"; + const TYPE: &'static str = "DatabaseIdToNameIdent"; + const HAS_TENANT: bool = false; + type ValueType = DatabaseNameIdentRaw; + } + + // TODO(TIdent): parent: DatabaseIdIdent + impl kvapi::Value for DatabaseNameIdentRaw { + fn dependency_keys(&self) -> impl IntoIterator { + [] + } + } + + // // Use these error types to replace usage of ErrorCode if possible. + // impl From> for ErrorCode { + // impl From> for ErrorCode { +} + +#[cfg(test)] +mod tests { + use databend_common_meta_kvapi::kvapi::Key; + + use super::DatabaseIdToNameIdent; + use crate::tenant::Tenant; + + #[test] + fn test_background_job_id_ident() { + let tenant = Tenant::new_literal("dummy"); + let ident = DatabaseIdToNameIdent::new(tenant, 3); + + let key = ident.to_string_key(); + assert_eq!(key, "__fd_database_id_to_name/3"); + + assert_eq!(ident, DatabaseIdToNameIdent::from_str_key(&key).unwrap()); + } + + #[test] + fn test_background_job_id_ident_with_key_space() { + // TODO(xp): implement this test + // let tenant = Tenant::new_literal("test"); + // let ident = DatabaseIdToNameIdent::new(tenant, 3); + // + // let key = ident.to_string_key(); + // assert_eq!(key, "__fd_database_id_to_name/3"); + // + // assert_eq!(ident, DatabaseIdToNameIdent::from_str_key(&key).unwrap()); + } +} diff --git a/src/meta/app/src/schema/database_name_ident.rs b/src/meta/app/src/schema/database_name_ident.rs index 86b49cb87236..18652b09a071 100644 --- a/src/meta/app/src/schema/database_name_ident.rs +++ b/src/meta/app/src/schema/database_name_ident.rs @@ -37,7 +37,7 @@ mod kvapi_impl { use databend_common_meta_kvapi::kvapi; use databend_common_meta_kvapi::kvapi::Key; - use crate::schema::DatabaseId; + use crate::schema::DatabaseIdIdent; use crate::tenant_key::resource::TenantResource; pub struct Resource; @@ -45,10 +45,10 @@ mod kvapi_impl { const PREFIX: &'static str = "__fd_database"; const TYPE: &'static str = "DatabaseNameIdent"; const HAS_TENANT: bool = true; - type ValueType = DatabaseId; + type ValueType = DatabaseIdIdent; } - impl kvapi::Value for DatabaseId { + impl kvapi::Value for DatabaseIdIdent { fn dependency_keys(&self) -> impl IntoIterator { [self.to_string_key()] } diff --git a/src/meta/app/src/schema/mod.rs b/src/meta/app/src/schema/mod.rs index 32ab0fb974a5..fed4c5f0249c 100644 --- a/src/meta/app/src/schema/mod.rs +++ b/src/meta/app/src/schema/mod.rs @@ -19,6 +19,8 @@ pub mod catalog_id_ident; pub mod catalog_id_to_name_ident; pub mod catalog_name_ident; pub mod database_id_history_ident; +pub mod database_id_ident; +pub mod database_id_to_name_ident; pub mod database_name_ident; pub mod index_name_ident; pub mod table_lock_ident; @@ -41,8 +43,6 @@ pub use catalog_name_ident::CatalogNameIdent; pub use create_option::CreateOption; pub use database::CreateDatabaseReply; pub use database::CreateDatabaseReq; -pub use database::DatabaseId; -pub use database::DatabaseIdToName; pub use database::DatabaseIdent; pub use database::DatabaseInfo; pub use database::DatabaseInfoFilter; @@ -57,6 +57,8 @@ pub use database::RenameDatabaseReq; pub use database::UndropDatabaseReply; pub use database::UndropDatabaseReq; pub use database_id_history_ident::DatabaseIdHistoryIdent; +pub use database_id_ident::DatabaseIdIdent; +pub use database_id_to_name_ident::DatabaseIdToNameIdent; pub use index::*; pub use index_name_ident::IndexNameIdent; pub use index_name_ident::IndexNameIdentRaw; diff --git a/src/meta/app/src/schema/table.rs b/src/meta/app/src/schema/table.rs index 3a603ed46032..5523934207bb 100644 --- a/src/meta/app/src/schema/table.rs +++ b/src/meta/app/src/schema/table.rs @@ -34,9 +34,8 @@ use maplit::hashmap; use super::CreateOption; use crate::schema::database_name_ident::DatabaseNameIdent; +use crate::schema::DatabaseIdIdent; use crate::share::share_name_ident::ShareNameIdentRaw; -use crate::share::ShareSpec; -use crate::share::ShareTableInfoMap; use crate::storage::StorageParams; use crate::tenant::Tenant; use crate::tenant::ToTenant; @@ -534,9 +533,8 @@ impl Display for CreateTableReq { pub struct CreateTableReply { pub table_id: u64, pub table_id_seq: Option, - pub db_id: u64, + pub database_id_ident: DatabaseIdIdent, pub new_table: bool, - pub spec_vec: Option<(Vec, Vec)>, } /// Drop table by id. @@ -574,9 +572,7 @@ impl Display for DropTableByIdReq { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct DropTableReply { - pub spec_vec: Option<(Vec, Vec)>, -} +pub struct DropTableReply {} #[derive(Clone, Debug, PartialEq, Eq)] pub struct UndropTableReq { @@ -586,7 +582,7 @@ pub struct UndropTableReq { #[derive(Clone, Debug, PartialEq, Eq)] pub struct UndropTableByIdReq { pub name_ident: TableNameIdent, - pub db_id: MetaId, + pub db_id_ident: DatabaseIdIdent, pub table_id: MetaId, pub table_id_seq: u64, // Indicates whether to forcefully replace an existing table with the same name, if it exists. @@ -737,19 +733,13 @@ pub struct SetTableColumnMaskPolicyReq { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct SetTableColumnMaskPolicyReply { - pub share_table_info: Option>, -} +pub struct SetTableColumnMaskPolicyReply {} #[derive(Clone, Debug, PartialEq, Eq)] -pub struct UpsertTableOptionReply { - pub share_table_info: Option>, -} +pub struct UpsertTableOptionReply {} #[derive(Clone, Debug, PartialEq, Eq)] -pub struct UpdateTableMetaReply { - pub share_table_info: Option>, -} +pub struct UpdateTableMetaReply {} #[derive(Clone, Debug, PartialEq, Eq)] pub struct CreateTableIndexReq { @@ -975,7 +965,7 @@ mod kvapi_key_impl { use databend_common_meta_kvapi::kvapi::KeyParser; use crate::schema::DBIdTableName; - use crate::schema::DatabaseId; + use crate::schema::DatabaseIdIdent; use crate::schema::LeastVisibleTime; use crate::schema::LeastVisibleTimeKey; use crate::schema::TableCopiedFileInfo; @@ -985,6 +975,7 @@ mod kvapi_key_impl { use crate::schema::TableIdList; use crate::schema::TableIdToName; use crate::schema::TableMeta; + use crate::tenant::Tenant; impl kvapi::KeyCodec for DBIdTableName { fn encode_key(&self, b: KeyBuilder) -> KeyBuilder { @@ -1005,7 +996,8 @@ mod kvapi_key_impl { type ValueType = TableId; fn parent(&self) -> Option { - Some(DatabaseId::new(self.db_id).to_string_key()) + // TODO(TIdent): add real tenant + Some(DatabaseIdIdent::new(Tenant::new_literal("dummy"), self.db_id).to_string_key()) } } @@ -1075,7 +1067,11 @@ mod kvapi_key_impl { type ValueType = TableIdList; fn parent(&self) -> Option { - Some(DatabaseId::new(self.database_id).to_string_key()) + // TODO(TIdent): add real tenant + Some( + DatabaseIdIdent::new(Tenant::new_literal("dummy"), self.database_id) + .to_string_key(), + ) } } diff --git a/src/meta/app/src/share/share.rs b/src/meta/app/src/share/share.rs index e096c5ae4040..9b1aee82c4c6 100644 --- a/src/meta/app/src/share/share.rs +++ b/src/meta/app/src/share/share.rs @@ -730,7 +730,7 @@ mod kvapi_key_impl { use databend_common_meta_kvapi::kvapi; use super::ShareEndpointId; - use crate::schema::DatabaseId; + use crate::schema::DatabaseIdIdent; use crate::schema::TableId; use crate::share::share_end_point_ident::ShareEndpointIdentRaw; use crate::share::share_name_ident::ShareNameIdentRaw; @@ -741,6 +741,7 @@ mod kvapi_key_impl { use crate::share::ShareId; use crate::share::ShareIdToName; use crate::share::ShareMeta; + use crate::tenant::Tenant; impl kvapi::KeyCodec for ShareGrantObject { fn encode_key(&self, b: kvapi::KeyBuilder) -> kvapi::KeyBuilder { @@ -773,8 +774,12 @@ mod kvapi_key_impl { type ValueType = ObjectSharedByShareIds; fn parent(&self) -> Option { + // TODO(TIdent): add real tenant + let k = match self { - ShareGrantObject::Database(db_id) => DatabaseId::new(*db_id).to_string_key(), + ShareGrantObject::Database(db_id) => { + DatabaseIdIdent::new(Tenant::new_literal("dummy"), *db_id).to_string_key() + } ShareGrantObject::Table(table_id) => TableId::new(*table_id).to_string_key(), }; Some(k) diff --git a/src/meta/embedded/tests/it/schema_api_impl.rs b/src/meta/embedded/tests/it/schema_api_impl.rs index 0baf123f63ea..7daf65230594 100644 --- a/src/meta/embedded/tests/it/schema_api_impl.rs +++ b/src/meta/embedded/tests/it/schema_api_impl.rs @@ -16,7 +16,6 @@ use async_trait::async_trait; use databend_common_base::base::tokio; use databend_common_meta_api::BackgroundApiTestSuite; use databend_common_meta_api::SchemaApiTestSuite; -use databend_common_meta_api::ShareApiTestSuite; use databend_common_meta_embedded::MetaEmbedded; use databend_common_meta_kvapi::kvapi; @@ -36,7 +35,7 @@ impl kvapi::ApiBuilder for MetaEmbeddedBuilder { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_meta_embedded() -> anyhow::Result<()> { SchemaApiTestSuite::test_single_node(MetaEmbeddedBuilder {}).await?; - ShareApiTestSuite::test_single_node_share(MetaEmbeddedBuilder {}).await?; + BackgroundApiTestSuite::test_single_node(MetaEmbeddedBuilder {}).await?; Ok(()) diff --git a/src/meta/raft-store/tests/it/state_machine/schema_api_impl.rs b/src/meta/raft-store/tests/it/state_machine/schema_api_impl.rs index 182102685596..2d2f60e4092d 100644 --- a/src/meta/raft-store/tests/it/state_machine/schema_api_impl.rs +++ b/src/meta/raft-store/tests/it/state_machine/schema_api_impl.rs @@ -18,7 +18,6 @@ use std::sync::Mutex; use async_trait::async_trait; use databend_common_meta_api::BackgroundApiTestSuite; use databend_common_meta_api::SchemaApiTestSuite; -use databend_common_meta_api::ShareApiTestSuite; use databend_common_meta_kvapi::kvapi; use databend_common_meta_raft_store::state_machine::StateMachine; use test_harness::test; @@ -58,7 +57,7 @@ async fn test_meta_embedded_single() -> anyhow::Result<()> { }; SchemaApiTestSuite::test_single_node(builder.clone()).await?; - ShareApiTestSuite::test_single_node_share(builder.clone()).await?; + BackgroundApiTestSuite::test_single_node(builder).await?; Ok(()) diff --git a/src/meta/service/tests/it/grpc/metasrv_grpc_schema_api.rs b/src/meta/service/tests/it/grpc/metasrv_grpc_schema_api.rs index f0bfe26db237..3f9dcad8839a 100644 --- a/src/meta/service/tests/it/grpc/metasrv_grpc_schema_api.rs +++ b/src/meta/service/tests/it/grpc/metasrv_grpc_schema_api.rs @@ -19,7 +19,6 @@ use std::sync::Mutex; use databend_common_meta_api::BackgroundApiTestSuite; use databend_common_meta_api::SchemaApiTestSuite; -use databend_common_meta_api::ShareApiTestSuite; use test_harness::test; use crate::testing::meta_service_test_harness; @@ -33,7 +32,7 @@ async fn test_meta_grpc_client_single() -> anyhow::Result<()> { }; SchemaApiTestSuite::test_single_node(builder.clone()).await?; - ShareApiTestSuite::test_single_node_share(builder.clone()).await?; + BackgroundApiTestSuite::test_single_node(builder).await?; Ok(()) diff --git a/src/query/ast/src/ast/format/ast_format.rs b/src/query/ast/src/ast/format/ast_format.rs index 8721b328e4c9..0e48f4694379 100644 --- a/src/query/ast/src/ast/format/ast_format.rs +++ b/src/query/ast/src/ast/format/ast_format.rs @@ -2591,151 +2591,6 @@ impl<'ast> Visitor<'ast> for AstFormatVisitor { self.children.push(node); } - fn visit_create_share_endpoint(&mut self, stmt: &'ast CreateShareEndpointStmt) { - let mut children = Vec::new(); - let share_endpoint_format_ctx = - AstFormatContext::new(format!("ShareEndpoint {}", stmt.endpoint)); - children.push(FormatTreeNode::new(share_endpoint_format_ctx)); - if let Some(comment) = &stmt.comment { - let comment_format_ctx = AstFormatContext::new(format!("Comment {}", comment)); - children.push(FormatTreeNode::new(comment_format_ctx)); - } - - let name = "CreateShareEndpoint".to_string(); - let format_ctx = AstFormatContext::with_children(name, children.len()); - let node = FormatTreeNode::with_children(format_ctx, children); - self.children.push(node); - } - - fn visit_show_share_endpoint(&mut self, _stmt: &'ast ShowShareEndpointStmt) { - let name = "ShowShareEndpoint".to_string(); - let format_ctx = AstFormatContext::new(name); - let node = FormatTreeNode::new(format_ctx); - self.children.push(node); - } - - fn visit_drop_share_endpoint(&mut self, _stmt: &'ast DropShareEndpointStmt) { - let name = "DropShareEndpoint".to_string(); - let format_ctx = AstFormatContext::new(name); - let node = FormatTreeNode::new(format_ctx); - self.children.push(node); - } - - fn visit_create_share(&mut self, stmt: &'ast CreateShareStmt) { - let mut children = Vec::new(); - let share_format_ctx = AstFormatContext::new(format!("ShareIdentifier {}", stmt.share)); - children.push(FormatTreeNode::new(share_format_ctx)); - if let Some(comment) = &stmt.comment { - let comment_format_ctx = AstFormatContext::new(format!("Comment {}", comment)); - children.push(FormatTreeNode::new(comment_format_ctx)); - } - - let name = "CreateShare".to_string(); - let format_ctx = AstFormatContext::with_children(name, children.len()); - let node = FormatTreeNode::with_children(format_ctx, children); - self.children.push(node); - } - - fn visit_drop_share(&mut self, stmt: &'ast DropShareStmt) { - let share_format_ctx = AstFormatContext::new(format!("ShareIdentifier {}", stmt.share)); - let child = FormatTreeNode::new(share_format_ctx); - - let name = "DropShare".to_string(); - let format_ctx = AstFormatContext::with_children(name, 1); - let node = FormatTreeNode::with_children(format_ctx, vec![child]); - self.children.push(node); - } - - fn visit_grant_share_object(&mut self, stmt: &'ast GrantShareObjectStmt) { - let mut children = Vec::new(); - let share_format_ctx = AstFormatContext::new(format!("ShareIdentifier {}", stmt.share)); - children.push(FormatTreeNode::new(share_format_ctx)); - let object_format_ctx = AstFormatContext::new(format!("Object {}", stmt.object)); - children.push(FormatTreeNode::new(object_format_ctx)); - let privilege_format_ctx = AstFormatContext::new(format!("Privilege {}", stmt.privilege)); - children.push(FormatTreeNode::new(privilege_format_ctx)); - - let name = "GrantShareObject".to_string(); - let format_ctx = AstFormatContext::with_children(name, children.len()); - let node = FormatTreeNode::with_children(format_ctx, children); - self.children.push(node); - } - - fn visit_revoke_share_object(&mut self, stmt: &'ast RevokeShareObjectStmt) { - let mut children = Vec::new(); - let share_format_ctx = AstFormatContext::new(format!("ShareIdentifier {}", stmt.share)); - children.push(FormatTreeNode::new(share_format_ctx)); - let object_format_ctx = AstFormatContext::new(format!("Object {}", stmt.object)); - children.push(FormatTreeNode::new(object_format_ctx)); - let privilege_format_ctx = AstFormatContext::new(format!("Privilege {}", stmt.privilege)); - children.push(FormatTreeNode::new(privilege_format_ctx)); - - let name = "RevokeShareObject".to_string(); - let format_ctx = AstFormatContext::with_children(name, children.len()); - let node = FormatTreeNode::with_children(format_ctx, children); - self.children.push(node); - } - - fn visit_alter_share_tenants(&mut self, stmt: &'ast AlterShareTenantsStmt) { - let mut children = Vec::new(); - let share_format_ctx = AstFormatContext::new(format!("ShareIdentifier {}", stmt.share)); - children.push(FormatTreeNode::new(share_format_ctx)); - if !stmt.tenants.is_empty() { - let mut tenants_children = Vec::with_capacity(stmt.tenants.len()); - for tenant in stmt.tenants.iter() { - self.visit_identifier(tenant); - tenants_children.push(self.children.pop().unwrap()); - } - let tenants_name = "Tenants".to_string(); - let tenants_format_ctx = - AstFormatContext::with_children(tenants_name, tenants_children.len()); - let tenants_node = FormatTreeNode::with_children(tenants_format_ctx, tenants_children); - children.push(tenants_node); - } - - let name = "AlterShareTenants".to_string(); - let format_ctx = AstFormatContext::with_children(name, children.len()); - let node = FormatTreeNode::with_children(format_ctx, children); - self.children.push(node); - } - - fn visit_desc_share(&mut self, stmt: &'ast DescShareStmt) { - let share_format_ctx = AstFormatContext::new(format!("ShareIdentifier {}", stmt.share)); - let child = FormatTreeNode::new(share_format_ctx); - - let name = "DescShare".to_string(); - let format_ctx = AstFormatContext::with_children(name, 1); - let node = FormatTreeNode::with_children(format_ctx, vec![child]); - self.children.push(node); - } - - fn visit_show_shares(&mut self, _stmt: &'ast ShowSharesStmt) { - let name = "ShowShares".to_string(); - let format_ctx = AstFormatContext::new(name); - let node = FormatTreeNode::new(format_ctx); - self.children.push(node); - } - - fn visit_show_object_grant_privileges(&mut self, stmt: &'ast ShowObjectGrantPrivilegesStmt) { - let object_format_ctx = AstFormatContext::new(format!("Object {}", stmt.object)); - let child = FormatTreeNode::new(object_format_ctx); - - let name = "ShowObjectGrantPrivileges".to_string(); - let format_ctx = AstFormatContext::with_children(name, 1); - let node = FormatTreeNode::with_children(format_ctx, vec![child]); - self.children.push(node); - } - - fn visit_show_grants_of_share(&mut self, stmt: &'ast ShowGrantsOfShareStmt) { - let share_format_ctx = AstFormatContext::new(format!("ShareName {}", stmt.share_name)); - let child = FormatTreeNode::new(share_format_ctx); - - let name = "ShowGrantsOfShare".to_string(); - let format_ctx = AstFormatContext::with_children(name, 1); - let node = FormatTreeNode::with_children(format_ctx, vec![child]); - self.children.push(node); - } - fn visit_create_data_mask_policy(&mut self, stmt: &'ast CreateDatamaskPolicyStmt) { let ctx = AstFormatContext::new(format!("DataMaskPolicyName {}", stmt.name)); let child = FormatTreeNode::new(ctx); diff --git a/src/query/ast/src/ast/statements/mod.rs b/src/query/ast/src/ast/statements/mod.rs index 5e5b81625e50..91a8ba92fd74 100644 --- a/src/query/ast/src/ast/statements/mod.rs +++ b/src/query/ast/src/ast/statements/mod.rs @@ -39,7 +39,6 @@ mod procedure; mod replace; mod script; mod sequence; -mod share; mod show; mod stage; mod statement; @@ -80,7 +79,6 @@ pub use procedure::*; pub use replace::*; pub use script::*; pub use sequence::*; -pub use share::*; pub use show::*; pub use stage::*; pub use statement::*; diff --git a/src/query/ast/src/ast/statements/share.rs b/src/query/ast/src/ast/statements/share.rs deleted file mode 100644 index 97cce82e92d9..000000000000 --- a/src/query/ast/src/ast/statements/share.rs +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::collections::BTreeMap; -use std::fmt::Display; -use std::fmt::Formatter; - -use databend_common_meta_app::schema::CreateOption; -use databend_common_meta_app::share::ShareGrantObjectName; -use databend_common_meta_app::share::ShareGrantObjectPrivilege; -use derive_visitor::Drive; -use derive_visitor::DriveMut; -use itertools::Itertools; - -use super::UriLocation; -use crate::ast::write_comma_separated_string_map; -use crate::ast::Identifier; - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct CreateShareEndpointStmt { - #[drive(skip)] - pub create_option: CreateOption, - pub endpoint: Identifier, - pub url: UriLocation, - pub tenant: Identifier, - #[drive(skip)] - pub args: BTreeMap, - #[drive(skip)] - pub comment: Option, -} - -impl Display for CreateShareEndpointStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "CREATE ")?; - if let CreateOption::CreateOrReplace = self.create_option { - write!(f, "OR REPLACE ")?; - } - write!(f, "SHARE ENDPOINT ")?; - if let CreateOption::CreateIfNotExists = self.create_option { - write!(f, "IF NOT EXISTS ")?; - } - write!(f, "{}", self.endpoint)?; - write!(f, " URL={}", self.url)?; - write!(f, " TENANT={} ARGS=(", self.tenant)?; - write_comma_separated_string_map(f, &self.args)?; - write!(f, ")")?; - if let Some(comment) = &self.comment { - write!(f, " COMMENT = '{comment}'")?; - } - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct CreateShareStmt { - #[drive(skip)] - pub if_not_exists: bool, - pub share: Identifier, - #[drive(skip)] - pub comment: Option, -} - -impl Display for CreateShareStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "CREATE SHARE ")?; - if self.if_not_exists { - write!(f, "IF NOT EXISTS ")?; - } - write!(f, "{}", self.share)?; - if let Some(comment) = &self.comment { - write!(f, " COMMENT = '{comment}'")?; - } - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct DropShareStmt { - #[drive(skip)] - pub if_exists: bool, - pub share: Identifier, -} - -impl Display for DropShareStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "DROP SHARE ")?; - if self.if_exists { - write!(f, "IF EXISTS ")?; - } - write!(f, "{}", self.share)?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct GrantShareObjectStmt { - pub share: Identifier, - #[drive(skip)] - pub object: ShareGrantObjectName, - #[drive(skip)] - pub privilege: ShareGrantObjectPrivilege, -} - -impl Display for GrantShareObjectStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!( - f, - "GRANT {} ON {} TO SHARE {}", - self.privilege, self.object, self.share - )?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct RevokeShareObjectStmt { - pub share: Identifier, - #[drive(skip)] - pub object: ShareGrantObjectName, - #[drive(skip)] - pub privilege: ShareGrantObjectPrivilege, -} - -impl Display for RevokeShareObjectStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!( - f, - "REVOKE {} ON {} FROM SHARE {}", - self.privilege, self.object, self.share - )?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct AlterShareTenantsStmt { - pub share: Identifier, - #[drive(skip)] - pub if_exists: bool, - pub tenants: Vec, - #[drive(skip)] - pub is_add: bool, -} - -impl Display for AlterShareTenantsStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "ALTER SHARE ")?; - if self.if_exists { - write!(f, "IF EXISTS ")?; - } - write!(f, "{}", self.share)?; - if self.is_add { - write!(f, " ADD TENANTS = ")?; - } else { - write!(f, " REMOVE TENANTS = ")?; - } - write!( - f, - "{}", - self.tenants.iter().map(|v| v.to_string()).join(",") - )?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct DescShareStmt { - pub share: Identifier, -} - -impl Display for DescShareStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "DESC SHARE {}", self.share)?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct ShowSharesStmt {} - -impl Display for ShowSharesStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "SHOW SHARES")?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct ShowShareEndpointStmt {} - -impl Display for ShowShareEndpointStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "SHOW SHARE ENDPOINT")?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct DropShareEndpointStmt { - #[drive(skip)] - pub if_exists: bool, - pub endpoint: Identifier, -} - -impl Display for DropShareEndpointStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "DROP SHARE ENDPOINT {}", self.endpoint)?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct ShowObjectGrantPrivilegesStmt { - #[drive(skip)] - pub object: ShareGrantObjectName, -} - -impl Display for ShowObjectGrantPrivilegesStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "SHOW GRANTS ON {}", self.object)?; - - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)] -pub struct ShowGrantsOfShareStmt { - #[drive(skip)] - pub share_name: String, -} - -impl Display for ShowGrantsOfShareStmt { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "SHOW GRANTS OF SHARE {}", self.share_name)?; - - Ok(()) - } -} diff --git a/src/query/ast/src/ast/statements/statement.rs b/src/query/ast/src/ast/statements/statement.rs index 6b2554d8ad20..9628dfa72679 100644 --- a/src/query/ast/src/ast/statements/statement.rs +++ b/src/query/ast/src/ast/statements/statement.rs @@ -266,20 +266,6 @@ pub enum Statement { ShowFileFormats, Presign(PresignStmt), - // share - CreateShareEndpoint(CreateShareEndpointStmt), - ShowShareEndpoint(ShowShareEndpointStmt), - DropShareEndpoint(DropShareEndpointStmt), - CreateShare(CreateShareStmt), - DropShare(DropShareStmt), - GrantShareObject(GrantShareObjectStmt), - RevokeShareObject(RevokeShareObjectStmt), - AlterShareTenants(AlterShareTenantsStmt), - DescShare(DescShareStmt), - ShowShares(ShowSharesStmt), - ShowObjectGrantPrivileges(ShowObjectGrantPrivilegesStmt), - ShowGrantsOfShare(ShowGrantsOfShareStmt), - // data mask CreateDatamaskPolicy(CreateDatamaskPolicyStmt), DropDatamaskPolicy(DropDatamaskPolicyStmt), @@ -681,18 +667,6 @@ impl Display for Statement { Statement::ShowFileFormats => write!(f, "SHOW FILE FORMATS")?, Statement::Call(stmt) => write!(f, "{stmt}")?, Statement::Presign(stmt) => write!(f, "{stmt}")?, - Statement::CreateShareEndpoint(stmt) => write!(f, "{stmt}")?, - Statement::ShowShareEndpoint(stmt) => write!(f, "{stmt}")?, - Statement::DropShareEndpoint(stmt) => write!(f, "{stmt}")?, - Statement::CreateShare(stmt) => write!(f, "{stmt}")?, - Statement::DropShare(stmt) => write!(f, "{stmt}")?, - Statement::GrantShareObject(stmt) => write!(f, "{stmt}")?, - Statement::RevokeShareObject(stmt) => write!(f, "{stmt}")?, - Statement::AlterShareTenants(stmt) => write!(f, "{stmt}")?, - Statement::DescShare(stmt) => write!(f, "{stmt}")?, - Statement::ShowShares(stmt) => write!(f, "{stmt}")?, - Statement::ShowObjectGrantPrivileges(stmt) => write!(f, "{stmt}")?, - Statement::ShowGrantsOfShare(stmt) => write!(f, "{stmt}")?, Statement::CreateDatamaskPolicy(stmt) => write!(f, "{stmt}")?, Statement::DropDatamaskPolicy(stmt) => write!(f, "{stmt}")?, Statement::DescDatamaskPolicy(stmt) => write!(f, "{stmt}")?, diff --git a/src/query/ast/src/ast/visitors/visitor.rs b/src/query/ast/src/ast/visitors/visitor.rs index 12a20c0aedf0..8ceebe86c494 100644 --- a/src/query/ast/src/ast/visitors/visitor.rs +++ b/src/query/ast/src/ast/visitors/visitor.rs @@ -646,30 +646,6 @@ pub trait Visitor<'ast>: Sized { fn visit_presign(&mut self, _presign: &'ast PresignStmt) {} - fn visit_create_share_endpoint(&mut self, _stmt: &'ast CreateShareEndpointStmt) {} - - fn visit_show_share_endpoint(&mut self, _stmt: &'ast ShowShareEndpointStmt) {} - - fn visit_drop_share_endpoint(&mut self, _stmt: &'ast DropShareEndpointStmt) {} - - fn visit_create_share(&mut self, _stmt: &'ast CreateShareStmt) {} - - fn visit_drop_share(&mut self, _stmt: &'ast DropShareStmt) {} - - fn visit_grant_share_object(&mut self, _stmt: &'ast GrantShareObjectStmt) {} - - fn visit_revoke_share_object(&mut self, _stmt: &'ast RevokeShareObjectStmt) {} - - fn visit_alter_share_tenants(&mut self, _stmt: &'ast AlterShareTenantsStmt) {} - - fn visit_desc_share(&mut self, _stmt: &'ast DescShareStmt) {} - - fn visit_show_shares(&mut self, _stmt: &'ast ShowSharesStmt) {} - - fn visit_show_object_grant_privileges(&mut self, _stmt: &'ast ShowObjectGrantPrivilegesStmt) {} - - fn visit_show_grants_of_share(&mut self, _stmt: &'ast ShowGrantsOfShareStmt) {} - fn visit_create_data_mask_policy(&mut self, _stmt: &'ast CreateDatamaskPolicyStmt) {} fn visit_drop_data_mask_policy(&mut self, _stmt: &'ast DropDatamaskPolicyStmt) {} diff --git a/src/query/ast/src/ast/visitors/visitor_mut.rs b/src/query/ast/src/ast/visitors/visitor_mut.rs index 1adfd9b2b742..8cb7f36c2119 100644 --- a/src/query/ast/src/ast/visitors/visitor_mut.rs +++ b/src/query/ast/src/ast/visitors/visitor_mut.rs @@ -658,30 +658,6 @@ pub trait VisitorMut: Sized { fn visit_presign(&mut self, _presign: &mut PresignStmt) {} - fn visit_create_share_endpoint(&mut self, _stmt: &mut CreateShareEndpointStmt) {} - - fn visit_show_share_endpoint(&mut self, _stmt: &mut ShowShareEndpointStmt) {} - - fn visit_drop_share_endpoint(&mut self, _stmt: &mut DropShareEndpointStmt) {} - - fn visit_create_share(&mut self, _stmt: &mut CreateShareStmt) {} - - fn visit_drop_share(&mut self, _stmt: &mut DropShareStmt) {} - - fn visit_grant_share_object(&mut self, _stmt: &mut GrantShareObjectStmt) {} - - fn visit_revoke_share_object(&mut self, _stmt: &mut RevokeShareObjectStmt) {} - - fn visit_alter_share_tenants(&mut self, _stmt: &mut AlterShareTenantsStmt) {} - - fn visit_desc_share(&mut self, _stmt: &mut DescShareStmt) {} - - fn visit_show_shares(&mut self, _stmt: &mut ShowSharesStmt) {} - - fn visit_show_object_grant_privileges(&mut self, _stmt: &mut ShowObjectGrantPrivilegesStmt) {} - - fn visit_show_grants_of_share(&mut self, _stmt: &mut ShowGrantsOfShareStmt) {} - fn visit_create_data_mask_policy(&mut self, _stmt: &mut CreateDatamaskPolicyStmt) {} fn visit_drop_data_mask_policy(&mut self, _stmt: &mut DropDatamaskPolicyStmt) {} diff --git a/src/query/ast/src/ast/visitors/walk.rs b/src/query/ast/src/ast/visitors/walk.rs index a84880106e5f..f56df5190c5f 100644 --- a/src/query/ast/src/ast/visitors/walk.rs +++ b/src/query/ast/src/ast/visitors/walk.rs @@ -533,20 +533,6 @@ pub fn walk_statement<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Statem Statement::DescribeStage { stage_name } => visitor.visit_describe_stage(stage_name), Statement::Call(stmt) => visitor.visit_call(stmt), Statement::Presign(stmt) => visitor.visit_presign(stmt), - Statement::CreateShareEndpoint(stmt) => visitor.visit_create_share_endpoint(stmt), - Statement::ShowShareEndpoint(stmt) => visitor.visit_show_share_endpoint(stmt), - Statement::DropShareEndpoint(stmt) => visitor.visit_drop_share_endpoint(stmt), - Statement::CreateShare(stmt) => visitor.visit_create_share(stmt), - Statement::DropShare(stmt) => visitor.visit_drop_share(stmt), - Statement::GrantShareObject(stmt) => visitor.visit_grant_share_object(stmt), - Statement::RevokeShareObject(stmt) => visitor.visit_revoke_share_object(stmt), - Statement::AlterShareTenants(stmt) => visitor.visit_alter_share_tenants(stmt), - Statement::DescShare(stmt) => visitor.visit_desc_share(stmt), - Statement::ShowShares(stmt) => visitor.visit_show_shares(stmt), - Statement::ShowObjectGrantPrivileges(stmt) => { - visitor.visit_show_object_grant_privileges(stmt) - } - Statement::ShowGrantsOfShare(stmt) => visitor.visit_show_grants_of_share(stmt), Statement::CreateDatamaskPolicy(stmt) => visitor.visit_create_data_mask_policy(stmt), Statement::DropDatamaskPolicy(stmt) => visitor.visit_drop_data_mask_policy(stmt), Statement::DescDatamaskPolicy(stmt) => visitor.visit_desc_data_mask_policy(stmt), diff --git a/src/query/ast/src/ast/visitors/walk_mut.rs b/src/query/ast/src/ast/visitors/walk_mut.rs index 7768e8d05e39..4c9062ab3e6e 100644 --- a/src/query/ast/src/ast/visitors/walk_mut.rs +++ b/src/query/ast/src/ast/visitors/walk_mut.rs @@ -528,20 +528,6 @@ pub fn walk_statement_mut(visitor: &mut V, statement: &mut Statem Statement::ShowFileFormats => visitor.visit_show_file_formats(), Statement::Call(stmt) => visitor.visit_call(stmt), Statement::Presign(stmt) => visitor.visit_presign(stmt), - Statement::CreateShareEndpoint(stmt) => visitor.visit_create_share_endpoint(stmt), - Statement::ShowShareEndpoint(stmt) => visitor.visit_show_share_endpoint(stmt), - Statement::DropShareEndpoint(stmt) => visitor.visit_drop_share_endpoint(stmt), - Statement::CreateShare(stmt) => visitor.visit_create_share(stmt), - Statement::DropShare(stmt) => visitor.visit_drop_share(stmt), - Statement::GrantShareObject(stmt) => visitor.visit_grant_share_object(stmt), - Statement::RevokeShareObject(stmt) => visitor.visit_revoke_share_object(stmt), - Statement::AlterShareTenants(stmt) => visitor.visit_alter_share_tenants(stmt), - Statement::DescShare(stmt) => visitor.visit_desc_share(stmt), - Statement::ShowShares(stmt) => visitor.visit_show_shares(stmt), - Statement::ShowObjectGrantPrivileges(stmt) => { - visitor.visit_show_object_grant_privileges(stmt) - } - Statement::ShowGrantsOfShare(stmt) => visitor.visit_show_grants_of_share(stmt), Statement::CreateDatamaskPolicy(stmt) => visitor.visit_create_data_mask_policy(stmt), Statement::DropDatamaskPolicy(stmt) => visitor.visit_drop_data_mask_policy(stmt), Statement::DescDatamaskPolicy(stmt) => visitor.visit_desc_data_mask_policy(stmt), diff --git a/src/query/ast/src/parser/mod.rs b/src/query/ast/src/parser/mod.rs index 68d712f79039..2f4be6c3ce07 100644 --- a/src/query/ast/src/parser/mod.rs +++ b/src/query/ast/src/parser/mod.rs @@ -20,7 +20,6 @@ pub mod query; pub mod quote; pub mod script; mod sequence; -mod share; mod stage; pub mod statement; pub mod stream; diff --git a/src/query/ast/src/parser/share.rs b/src/query/ast/src/parser/share.rs deleted file mode 100644 index ae40abe4077b..000000000000 --- a/src/query/ast/src/parser/share.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::collections::BTreeMap; - -use crate::ast::UriLocation; -use crate::parser::common::*; -use crate::parser::expr::*; -use crate::parser::input::Input; -use crate::parser::ErrorKind; -use crate::rule; - -pub fn share_endpoint_uri_location(i: Input) -> IResult { - map_res( - rule! { - #literal_string - }, - |location| { - UriLocation::from_uri(location, "".to_string(), BTreeMap::new()) - .map_err(|_| nom::Err::Failure(ErrorKind::Other("invalid uri"))) - }, - )(i) -} diff --git a/src/query/ast/src/parser/stage.rs b/src/query/ast/src/parser/stage.rs index 019833b2c043..8f267738a1b5 100644 --- a/src/query/ast/src/parser/stage.rs +++ b/src/query/ast/src/parser/stage.rs @@ -191,6 +191,7 @@ pub fn file_format_clause(i: Input) -> IResult { } // parse: (k = v ...)* into a map +#[allow(dead_code)] pub fn options(i: Input) -> IResult> { map( rule! { diff --git a/src/query/ast/src/parser/statement.rs b/src/query/ast/src/parser/statement.rs index d0eadc68fc43..dffafd0403e7 100644 --- a/src/query/ast/src/parser/statement.rs +++ b/src/query/ast/src/parser/statement.rs @@ -23,7 +23,6 @@ use databend_common_meta_app::schema::CatalogType; use databend_common_meta_app::schema::CreateOption; use databend_common_meta_app::share::share_name_ident::ShareNameIdent; use databend_common_meta_app::share::ShareGrantObjectName; -use databend_common_meta_app::share::ShareGrantObjectPrivilege; use databend_common_meta_app::tenant::Tenant; use minitrace::func_name; use nom::branch::alt; @@ -44,7 +43,6 @@ use crate::parser::expr::subexpr; use crate::parser::expr::*; use crate::parser::input::Input; use crate::parser::query::*; -use crate::parser::share::share_endpoint_uri_location; use crate::parser::stage::*; use crate::parser::stream::stream_table; use crate::parser::token::*; @@ -54,8 +52,6 @@ use crate::rule; pub enum ShowGrantOption { PrincipalIdentity(PrincipalIdentity), - ShareGrantObjectName(ShareGrantObjectName), - ShareName(String), } #[derive(Clone)] @@ -1294,12 +1290,6 @@ pub fn statement_body(i: Input) -> IResult { Some(ShowGrantOption::PrincipalIdentity(principal)) => Statement::ShowGrants { principal: Some(principal), }, - Some(ShowGrantOption::ShareGrantObjectName(object)) => { - Statement::ShowObjectGrantPrivileges(ShowObjectGrantPrivilegesStmt { object }) - } - Some(ShowGrantOption::ShareName(share_name)) => { - Statement::ShowGrantsOfShare(ShowGrantsOfShareStmt { share_name }) - } None => Statement::ShowGrants { principal: None }, }, ); @@ -1525,149 +1515,6 @@ pub fn statement_body(i: Input) -> IResult { }, ); - // share statements - let create_share_endpoint = map_res( - rule! { - CREATE ~ ( OR ~ ^REPLACE )? ~ SHARE ~ ENDPOINT ~ ( IF ~ ^NOT ~ ^EXISTS )? - ~ #ident - ~ URL ~ "=" ~ #share_endpoint_uri_location - ~ TENANT ~ "=" ~ #ident - ~ ( ARGS ~ ^"=" ~ ^#options)? - ~ ( COMMENT ~ ^"=" ~ ^#literal_string)? - }, - |( - _, - opt_or_replace, - _, - _, - opt_if_not_exists, - endpoint, - _, - _, - url, - _, - _, - tenant, - args_opt, - comment_opt, - )| { - let create_option = - parse_create_option(opt_or_replace.is_some(), opt_if_not_exists.is_some())?; - - Ok(Statement::CreateShareEndpoint(CreateShareEndpointStmt { - create_option, - endpoint, - url, - tenant, - args: match args_opt { - Some(opt) => opt.2, - None => BTreeMap::new(), - }, - comment: match comment_opt { - Some(opt) => Some(opt.2), - None => None, - }, - })) - }, - ); - let show_share_endpoints = map( - rule! { - SHOW ~ SHARE ~ ENDPOINT - }, - |(_, _, _)| Statement::ShowShareEndpoint(ShowShareEndpointStmt {}), - ); - let drop_share_endpoint = map( - rule! { - DROP ~ SHARE ~ ENDPOINT ~ ( IF ~ EXISTS)? ~ #ident - }, - |(_, _, _, opt_if_exists, endpoint)| { - Statement::DropShareEndpoint(DropShareEndpointStmt { - if_exists: opt_if_exists.is_some(), - endpoint, - }) - }, - ); - let create_share = map( - rule! { - CREATE ~ SHARE ~ ( IF ~ ^NOT ~ ^EXISTS )? ~ #ident ~ ( COMMENT ~ "=" ~ #literal_string)? - }, - |(_, _, opt_if_not_exists, share, comment_opt)| { - Statement::CreateShare(CreateShareStmt { - if_not_exists: opt_if_not_exists.is_some(), - share, - comment: match comment_opt { - Some(opt) => Some(opt.2), - None => None, - }, - }) - }, - ); - let drop_share = map( - rule! { - DROP ~ SHARE ~ ( IF ~ ^EXISTS )? ~ #ident - }, - |(_, _, opt_if_exists, share)| { - Statement::DropShare(DropShareStmt { - if_exists: opt_if_exists.is_some(), - share, - }) - }, - ); - let grant_share_object = map( - rule! { - GRANT ~ #priv_share_type ~ ON ~ #grant_share_object_name ~ TO ~ SHARE ~ #ident - }, - |(_, privilege, _, object, _, _, share)| { - Statement::GrantShareObject(GrantShareObjectStmt { - share, - object, - privilege, - }) - }, - ); - let revoke_share_object = map( - rule! { - REVOKE ~ #priv_share_type ~ ON ~ #grant_share_object_name ~ FROM ~ SHARE ~ #ident - }, - |(_, privilege, _, object, _, _, share)| { - Statement::RevokeShareObject(RevokeShareObjectStmt { - share, - object, - privilege, - }) - }, - ); - let alter_share_tenants = map( - rule! { - ALTER - ~ SHARE - ~ ( IF ~ ^EXISTS )? - ~ #ident - ~ #alter_add_share_accounts - ~ TENANTS ~ Eq ~ #comma_separated_list1(ident) - }, - |(_, _, opt_if_exists, share, is_add, _, _, tenants)| { - Statement::AlterShareTenants(AlterShareTenantsStmt { - share, - if_exists: opt_if_exists.is_some(), - is_add, - tenants, - }) - }, - ); - let desc_share = map( - rule! { - (DESC | DESCRIBE) ~ SHARE ~ #ident - }, - |(_, _, share)| Statement::DescShare(DescShareStmt { share }), - ); - let show_shares = map( - rule! { - SHOW ~ SHARES - }, - |(_, _)| Statement::ShowShares(ShowSharesStmt {}), - ); - let create_file_format = map_res( rule! { CREATE ~ ( OR ~ ^REPLACE )? ~ FILE ~ FORMAT ~ ( IF ~ ^NOT ~ ^EXISTS )? @@ -2188,19 +2035,6 @@ pub fn statement_body(i: Input) -> IResult { | #drop_data_mask_policy: "`DROP MASKING POLICY [IF EXISTS] mask_name`" | #describe_data_mask_policy: "`DESC MASKING POLICY mask_name`" ), - // share - rule!( - #create_share_endpoint: "`CREATE SHARE ENDPOINT [IF NOT EXISTS] URL=endpoint_location tenant=tenant_name ARGS=(arg=..) [ COMMENT = '' ]`" - | #show_share_endpoints: "`SHOW SHARE ENDPOINT`" - | #drop_share_endpoint: "`DROP SHARE ENDPOINT `" - | #create_share: "`CREATE SHARE [IF NOT EXISTS] [ COMMENT = '' ]`" - | #drop_share: "`DROP SHARE [IF EXISTS] `" - | #grant_share_object: "`GRANT { USAGE | SELECT | REFERENCE_USAGE } ON { DATABASE db | TABLE db.table } TO SHARE `" - | #revoke_share_object: "`REVOKE { USAGE | SELECT | REFERENCE_USAGE } ON { DATABASE db | TABLE db.table } FROM SHARE `" - | #alter_share_tenants: "`ALTER SHARE [IF EXISTS] { ADD | REMOVE } TENANTS = tenant [, tenant, ...]`" - | #desc_share: "`{DESC | DESCRIBE} SHARE `" - | #show_shares: "`SHOW SHARES`" - ), // catalog rule!( #show_catalogs : "`SHOW CATALOGS []`" @@ -2848,17 +2682,6 @@ pub fn stage_priv_type(i: Input) -> IResult { ))(i) } -pub fn priv_share_type(i: Input) -> IResult { - alt(( - value(ShareGrantObjectPrivilege::Usage, rule! { USAGE }), - value(ShareGrantObjectPrivilege::Select, rule! { SELECT }), - value( - ShareGrantObjectPrivilege::ReferenceUsage, - rule! { REFERENCE_USAGE }, - ), - ))(i) -} - pub fn alter_add_share_accounts(i: Input) -> IResult { alt((value(true, rule! { ADD }), value(false, rule! { REMOVE })))(i) } @@ -3003,24 +2826,8 @@ pub fn show_grant_option(i: Input) -> IResult { |(_, opt_principal)| ShowGrantOption::PrincipalIdentity(opt_principal), ); - let share_object_name = map( - rule! { - ON ~ #grant_share_object_name - }, - |(_, object_name)| ShowGrantOption::ShareGrantObjectName(object_name), - ); - - let share_name = map( - rule! { - OF ~ SHARE ~ #ident - }, - |(_, _, share_name)| ShowGrantOption::ShareName(share_name.to_string()), - ); - rule!( #grant_role: "FOR { ROLE | [USER] }" - | #share_object_name: "ON {DATABASE | TABLE .}" - | #share_name: "OF SHARE " )(i) } diff --git a/src/query/ast/tests/it/parser.rs b/src/query/ast/tests/it/parser.rs index ccf85f00b7d9..829595b8373f 100644 --- a/src/query/ast/tests/it/parser.rs +++ b/src/query/ast/tests/it/parser.rs @@ -146,7 +146,6 @@ fn test_statement() { r#"create database if not exists a;"#, r#"create database ctl.t engine = Default;"#, r#"create database t engine = Default;"#, - r#"create database t FROM SHARE a.s;"#, r#"CREATE TABLE `t3`(a int not null, b int not null, c int not null) bloom_index_columns='a,b,c' COMPRESSION='zstd' STORAGE_FORMAT='native';"#, r#"create or replace database a;"#, r#"drop database ctl.t;"#, @@ -538,14 +537,6 @@ fn test_statement() { r#"PRESIGN UPLOAD @my_stage/path/to/file EXPIRE=7200"#, r#"PRESIGN UPLOAD @my_stage/path/to/file EXPIRE=7200 CONTENT_TYPE='application/octet-stream'"#, r#"PRESIGN UPLOAD @my_stage/path/to/file CONTENT_TYPE='application/octet-stream' EXPIRE=7200"#, - r#"CREATE SHARE ENDPOINT IF NOT EXISTS t URL='http://127.0.0.1' TENANT=x ARGS=(jwks_key_file="https://eks.public/keys" ssl_cert="cert.pem") COMMENT='share endpoint comment';"#, - r#"CREATE OR REPLACE SHARE ENDPOINT t URL='http://127.0.0.1' TENANT=x ARGS=(jwks_key_file="https://eks.public/keys" ssl_cert="cert.pem") COMMENT='share endpoint comment';"#, - r#"CREATE SHARE t COMMENT='share comment';"#, - r#"CREATE SHARE IF NOT EXISTS t;"#, - r#"DROP SHARE a;"#, - r#"DROP SHARE IF EXISTS a;"#, - r#"GRANT USAGE ON DATABASE db1 TO SHARE a;"#, - r#"GRANT SELECT ON TABLE db1.tb1 TO SHARE a;"#, r#"GRANT all ON stage s1 TO a;"#, r#"GRANT read ON stage s1 TO a;"#, r#"GRANT write ON stage s1 TO a;"#, @@ -554,17 +545,6 @@ fn test_statement() { r#"GRANT usage ON UDF a TO 'test-grant';"#, r#"REVOKE usage ON UDF a FROM 'test-grant';"#, r#"REVOKE all ON UDF a FROM 'test-grant';"#, - r#"REVOKE USAGE ON DATABASE db1 FROM SHARE a;"#, - r#"REVOKE SELECT ON TABLE db1.tb1 FROM SHARE a;"#, - r#"ALTER SHARE a ADD TENANTS = b,c;"#, - r#"ALTER SHARE IF EXISTS a ADD TENANTS = b,c;"#, - r#"ALTER SHARE IF EXISTS a REMOVE TENANTS = b,c;"#, - r#"DESC SHARE b;"#, - r#"DESCRIBE SHARE b;"#, - r#"SHOW SHARES;"#, - r#"SHOW GRANTS ON TABLE db1.tb1;"#, - r#"SHOW GRANTS ON DATABASE db;"#, - r#"SHOW GRANTS OF SHARE t;"#, r#"UPDATE db1.tb1 set a = a + 1, b = 2 WHERE c > 3;"#, r#"SET max_threads = 10;"#, r#"SET max_threads = 10*2;"#, diff --git a/src/query/ast/tests/it/testdata/statement-error.txt b/src/query/ast/tests/it/testdata/statement-error.txt index eca848620a7d..17b71e0dd502 100644 --- a/src/query/ast/tests/it/testdata/statement-error.txt +++ b/src/query/ast/tests/it/testdata/statement-error.txt @@ -148,7 +148,7 @@ error: --> SQL:1:6 | 1 | drop a - | ^ unexpected `a`, expecting `TASK`, `TABLE`, `MASKING`, `CATALOG`, `DATABASE`, `PASSWORD`, `AGGREGATING`, `SCHEMA`, `NETWORK`, `VIEW`, `INVERTED`, `VIRTUAL`, `SEQUENCE`, `USER`, `ROLE`, `FUNCTION`, `STAGE`, `FILE`, `SHARE`, `STREAM`, `PIPE`, `NOTIFICATION`, or `CONNECTION` + | ^ unexpected `a`, expecting `TASK`, `TABLE`, `MASKING`, `CATALOG`, `DATABASE`, `PASSWORD`, `AGGREGATING`, `SCHEMA`, `NETWORK`, `VIEW`, `INVERTED`, `VIRTUAL`, `SEQUENCE`, `USER`, `ROLE`, `FUNCTION`, `STAGE`, `FILE`, `STREAM`, `PIPE`, `NOTIFICATION`, or `CONNECTION` ---------- Input ---------- @@ -214,7 +214,7 @@ error: --> SQL:1:6 | 1 | drop usar if exists 'test-j'; - | ^^^^ unexpected `usar`, expecting `USER`, `SHARE`, `STREAM`, `STAGE`, `PASSWORD`, `AGGREGATING`, `ROLE`, `TABLE`, `SCHEMA`, `NETWORK`, `VIRTUAL`, `CATALOG`, `DATABASE`, `INVERTED`, `FUNCTION`, `TASK`, `NOTIFICATION`, `MASKING`, `SEQUENCE`, `VIEW`, `FILE`, `PIPE`, or `CONNECTION` + | ^^^^ unexpected `usar`, expecting `USER`, `STREAM`, `STAGE`, `PASSWORD`, `AGGREGATING`, `ROLE`, `TABLE`, `SCHEMA`, `NETWORK`, `VIRTUAL`, `CATALOG`, `DATABASE`, `INVERTED`, `FUNCTION`, `TASK`, `NOTIFICATION`, `MASKING`, `SEQUENCE`, `VIEW`, `FILE`, `PIPE`, or `CONNECTION` ---------- Input ---------- @@ -254,7 +254,7 @@ error: --> SQL:1:6 | 1 | SHOW GRANT FOR ROLE 'role1'; - | ^^^^^ unexpected `GRANT`, expecting `GRANTS`, `CREATE`, `NETWORK`, `VIRTUAL`, `CATALOGS`, `STREAMS`, `FUNCTIONS`, `DATABASES`, `CONNECTIONS`, `TABLE_FUNCTIONS`, `DROP`, `TABLE`, `ROLES`, `SHARE`, `TASKS`, `INDEXES`, `COLUMNS`, `PASSWORD`, `PROCESSLIST`, `STAGES`, `TABLES`, `SHARES`, `ENGINES`, `METRICS`, `SETTINGS`, `LOCKS`, `SCHEMAS`, `FIELDS`, `VIEWS`, `USERS`, `USER`, `FILE`, or `FULL` + | ^^^^^ unexpected `GRANT`, expecting `GRANTS`, `CREATE`, `NETWORK`, `VIRTUAL`, `CATALOGS`, `STREAMS`, `FUNCTIONS`, `DATABASES`, `CONNECTIONS`, `TABLE_FUNCTIONS`, `DROP`, `TABLE`, `ROLES`, `TASKS`, `INDEXES`, `COLUMNS`, `PASSWORD`, `PROCESSLIST`, `STAGES`, `TABLES`, `ENGINES`, `METRICS`, `SETTINGS`, `LOCKS`, `SCHEMAS`, `FIELDS`, `VIEWS`, `USERS`, `USER`, `FILE`, or `FULL` ---------- Input ---------- @@ -299,7 +299,10 @@ error: --> SQL:1:17 | 1 | GRANT select ON UDF a TO 'test-grant'; - | ^^^ unexpected `UDF`, expecting `IDENTIFIER`, , , `FALSE`, `DATABASE`, `*`, , , , `TRUE`, or `TABLE` + | ----- ------ ^^^ unexpected `UDF`, expecting `IDENTIFIER`, , , `FALSE`, `*`, , , , or `TRUE` + | | | + | | while parsing ON + | while parsing `GRANT { ROLE | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON } TO { [ROLE ] | [USER] }` ---------- Input ---------- @@ -830,7 +833,9 @@ error: --> SQL:1:8 | 1 | REVOKE OWNERSHIP, SELECT ON d20_0014.* FROM ROLE 'd20_0015_owner'; - | ^^^^^^^^^ unexpected `OWNERSHIP`, expecting `INSERT`, `ALTER`, `SUPER`, `ROLE`, `WRITE`, `SET`, `SELECT`, `UPDATE`, `DELETE`, `REFERENCE_USAGE`, `DROP`, `READ`, `USAGE`, `GRANT`, `CREATE`, or `ALL` + | ------ ^^^^^^^^^ unexpected `OWNERSHIP`, expecting `INSERT`, `ALTER`, `SUPER`, `ROLE`, `WRITE`, `SET`, `SELECT`, `UPDATE`, `DELETE`, `DROP`, `READ`, `USAGE`, `GRANT`, `CREATE`, or `ALL` + | | + | while parsing `REVOKE { ROLE | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON } FROM { [ROLE ] | [USER] }` ---------- Input ---------- @@ -840,7 +845,9 @@ error: --> SQL:1:8 | 1 | REVOKE OWNERSHIP ON d20_0014.* FROM USER A; - | ^^^^^^^^^ unexpected `OWNERSHIP`, expecting `INSERT`, `ALTER`, `SUPER`, `ROLE`, `WRITE`, `SET`, `SELECT`, `UPDATE`, `DELETE`, `REFERENCE_USAGE`, `DROP`, `READ`, `USAGE`, `GRANT`, `CREATE`, or `ALL` + | ------ ^^^^^^^^^ unexpected `OWNERSHIP`, expecting `INSERT`, `ALTER`, `SUPER`, `ROLE`, `WRITE`, `SET`, `SELECT`, `UPDATE`, `DELETE`, `DROP`, `READ`, `USAGE`, `GRANT`, `CREATE`, or `ALL` + | | + | while parsing `REVOKE { ROLE | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON } FROM { [ROLE ] | [USER] }` ---------- Input ---------- @@ -850,7 +857,9 @@ error: --> SQL:1:8 | 1 | REVOKE OWNERSHIP ON d20_0014.* FROM ROLE A; - | ^^^^^^^^^ unexpected `OWNERSHIP`, expecting `INSERT`, `ALTER`, `SUPER`, `ROLE`, `WRITE`, `SET`, `SELECT`, `UPDATE`, `DELETE`, `REFERENCE_USAGE`, `DROP`, `READ`, `USAGE`, `GRANT`, `CREATE`, or `ALL` + | ------ ^^^^^^^^^ unexpected `OWNERSHIP`, expecting `INSERT`, `ALTER`, `SUPER`, `ROLE`, `WRITE`, `SET`, `SELECT`, `UPDATE`, `DELETE`, `DROP`, `READ`, `USAGE`, `GRANT`, `CREATE`, or `ALL` + | | + | while parsing `REVOKE { ROLE | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON } FROM { [ROLE ] | [USER] }` ---------- Input ---------- diff --git a/src/query/ast/tests/it/testdata/statement.txt b/src/query/ast/tests/it/testdata/statement.txt index dc9869740e8f..67adddf510fd 100644 --- a/src/query/ast/tests/it/testdata/statement.txt +++ b/src/query/ast/tests/it/testdata/statement.txt @@ -2543,39 +2543,6 @@ CreateDatabase( ) ----------- Input ---------- -create database t FROM SHARE a.s; ----------- Output --------- -CREATE DATABASE t FROM SHARE a.s ----------- AST ------------ -CreateDatabase( - CreateDatabaseStmt { - create_option: Create, - database: DatabaseRef { - catalog: None, - database: Identifier { - span: Some( - 16..17, - ), - name: "t", - quote: None, - is_hole: false, - }, - }, - engine: None, - options: [], - from_share: Some( - ShareNameIdent { - tenant: Tenant { - tenant: "a", - }, - name: "s", - }, - ), - }, -) - - ---------- Input ---------- CREATE TABLE `t3`(a int not null, b int not null, c int not null) bloom_index_columns='a,b,c' COMPRESSION='zstd' STORAGE_FORMAT='native'; ---------- Output --------- @@ -14030,227 +13997,6 @@ Presign( ) ----------- Input ---------- -CREATE SHARE ENDPOINT IF NOT EXISTS t URL='http://127.0.0.1' TENANT=x ARGS=(jwks_key_file="https://eks.public/keys" ssl_cert="cert.pem") COMMENT='share endpoint comment'; ----------- Output --------- -CREATE SHARE ENDPOINT IF NOT EXISTS t URL='http://127.0.0.1/' TENANT=x ARGS=(jwks_key_file = 'https://eks.public/keys', ssl_cert = 'cert.pem') COMMENT = 'share endpoint comment' ----------- AST ------------ -CreateShareEndpoint( - CreateShareEndpointStmt { - create_option: CreateIfNotExists, - endpoint: Identifier { - span: Some( - 36..37, - ), - name: "t", - quote: None, - is_hole: false, - }, - url: UriLocation { - protocol: "http", - name: "127.0.0.1", - path: "/", - part_prefix: "", - connection: Connection { - visited_keys: {}, - conns: {}, - }, - }, - tenant: Identifier { - span: Some( - 68..69, - ), - name: "x", - quote: None, - is_hole: false, - }, - args: { - "jwks_key_file": "https://eks.public/keys", - "ssl_cert": "cert.pem", - }, - comment: Some( - "share endpoint comment", - ), - }, -) - - ----------- Input ---------- -CREATE OR REPLACE SHARE ENDPOINT t URL='http://127.0.0.1' TENANT=x ARGS=(jwks_key_file="https://eks.public/keys" ssl_cert="cert.pem") COMMENT='share endpoint comment'; ----------- Output --------- -CREATE OR REPLACE SHARE ENDPOINT t URL='http://127.0.0.1/' TENANT=x ARGS=(jwks_key_file = 'https://eks.public/keys', ssl_cert = 'cert.pem') COMMENT = 'share endpoint comment' ----------- AST ------------ -CreateShareEndpoint( - CreateShareEndpointStmt { - create_option: CreateOrReplace, - endpoint: Identifier { - span: Some( - 33..34, - ), - name: "t", - quote: None, - is_hole: false, - }, - url: UriLocation { - protocol: "http", - name: "127.0.0.1", - path: "/", - part_prefix: "", - connection: Connection { - visited_keys: {}, - conns: {}, - }, - }, - tenant: Identifier { - span: Some( - 65..66, - ), - name: "x", - quote: None, - is_hole: false, - }, - args: { - "jwks_key_file": "https://eks.public/keys", - "ssl_cert": "cert.pem", - }, - comment: Some( - "share endpoint comment", - ), - }, -) - - ----------- Input ---------- -CREATE SHARE t COMMENT='share comment'; ----------- Output --------- -CREATE SHARE t COMMENT = 'share comment' ----------- AST ------------ -CreateShare( - CreateShareStmt { - if_not_exists: false, - share: Identifier { - span: Some( - 13..14, - ), - name: "t", - quote: None, - is_hole: false, - }, - comment: Some( - "share comment", - ), - }, -) - - ----------- Input ---------- -CREATE SHARE IF NOT EXISTS t; ----------- Output --------- -CREATE SHARE IF NOT EXISTS t ----------- AST ------------ -CreateShare( - CreateShareStmt { - if_not_exists: true, - share: Identifier { - span: Some( - 27..28, - ), - name: "t", - quote: None, - is_hole: false, - }, - comment: None, - }, -) - - ----------- Input ---------- -DROP SHARE a; ----------- Output --------- -DROP SHARE a ----------- AST ------------ -DropShare( - DropShareStmt { - if_exists: false, - share: Identifier { - span: Some( - 11..12, - ), - name: "a", - quote: None, - is_hole: false, - }, - }, -) - - ----------- Input ---------- -DROP SHARE IF EXISTS a; ----------- Output --------- -DROP SHARE IF EXISTS a ----------- AST ------------ -DropShare( - DropShareStmt { - if_exists: true, - share: Identifier { - span: Some( - 21..22, - ), - name: "a", - quote: None, - is_hole: false, - }, - }, -) - - ----------- Input ---------- -GRANT USAGE ON DATABASE db1 TO SHARE a; ----------- Output --------- -GRANT USAGE ON DATABASE db1 TO SHARE a ----------- AST ------------ -GrantShareObject( - GrantShareObjectStmt { - share: Identifier { - span: Some( - 37..38, - ), - name: "a", - quote: None, - is_hole: false, - }, - object: Database( - "db1", - ), - privilege: Usage, - }, -) - - ----------- Input ---------- -GRANT SELECT ON TABLE db1.tb1 TO SHARE a; ----------- Output --------- -GRANT SELECT ON TABLE db1.tb1 TO SHARE a ----------- AST ------------ -GrantShareObject( - GrantShareObjectStmt { - share: Identifier { - span: Some( - 39..40, - ), - name: "a", - quote: None, - is_hole: false, - }, - object: Table( - "db1", - "tb1", - ), - privilege: Select, - }, -) - - ---------- Input ---------- GRANT all ON stage s1 TO a; ---------- Output --------- @@ -14448,259 +14194,6 @@ Revoke( ) ----------- Input ---------- -REVOKE USAGE ON DATABASE db1 FROM SHARE a; ----------- Output --------- -REVOKE USAGE ON DATABASE db1 FROM SHARE a ----------- AST ------------ -RevokeShareObject( - RevokeShareObjectStmt { - share: Identifier { - span: Some( - 40..41, - ), - name: "a", - quote: None, - is_hole: false, - }, - object: Database( - "db1", - ), - privilege: Usage, - }, -) - - ----------- Input ---------- -REVOKE SELECT ON TABLE db1.tb1 FROM SHARE a; ----------- Output --------- -REVOKE SELECT ON TABLE db1.tb1 FROM SHARE a ----------- AST ------------ -RevokeShareObject( - RevokeShareObjectStmt { - share: Identifier { - span: Some( - 42..43, - ), - name: "a", - quote: None, - is_hole: false, - }, - object: Table( - "db1", - "tb1", - ), - privilege: Select, - }, -) - - ----------- Input ---------- -ALTER SHARE a ADD TENANTS = b,c; ----------- Output --------- -ALTER SHARE a ADD TENANTS = b,c ----------- AST ------------ -AlterShareTenants( - AlterShareTenantsStmt { - share: Identifier { - span: Some( - 12..13, - ), - name: "a", - quote: None, - is_hole: false, - }, - if_exists: false, - tenants: [ - Identifier { - span: Some( - 28..29, - ), - name: "b", - quote: None, - is_hole: false, - }, - Identifier { - span: Some( - 30..31, - ), - name: "c", - quote: None, - is_hole: false, - }, - ], - is_add: true, - }, -) - - ----------- Input ---------- -ALTER SHARE IF EXISTS a ADD TENANTS = b,c; ----------- Output --------- -ALTER SHARE IF EXISTS a ADD TENANTS = b,c ----------- AST ------------ -AlterShareTenants( - AlterShareTenantsStmt { - share: Identifier { - span: Some( - 22..23, - ), - name: "a", - quote: None, - is_hole: false, - }, - if_exists: true, - tenants: [ - Identifier { - span: Some( - 38..39, - ), - name: "b", - quote: None, - is_hole: false, - }, - Identifier { - span: Some( - 40..41, - ), - name: "c", - quote: None, - is_hole: false, - }, - ], - is_add: true, - }, -) - - ----------- Input ---------- -ALTER SHARE IF EXISTS a REMOVE TENANTS = b,c; ----------- Output --------- -ALTER SHARE IF EXISTS a REMOVE TENANTS = b,c ----------- AST ------------ -AlterShareTenants( - AlterShareTenantsStmt { - share: Identifier { - span: Some( - 22..23, - ), - name: "a", - quote: None, - is_hole: false, - }, - if_exists: true, - tenants: [ - Identifier { - span: Some( - 41..42, - ), - name: "b", - quote: None, - is_hole: false, - }, - Identifier { - span: Some( - 43..44, - ), - name: "c", - quote: None, - is_hole: false, - }, - ], - is_add: false, - }, -) - - ----------- Input ---------- -DESC SHARE b; ----------- Output --------- -DESC SHARE b ----------- AST ------------ -DescShare( - DescShareStmt { - share: Identifier { - span: Some( - 11..12, - ), - name: "b", - quote: None, - is_hole: false, - }, - }, -) - - ----------- Input ---------- -DESCRIBE SHARE b; ----------- Output --------- -DESC SHARE b ----------- AST ------------ -DescShare( - DescShareStmt { - share: Identifier { - span: Some( - 15..16, - ), - name: "b", - quote: None, - is_hole: false, - }, - }, -) - - ----------- Input ---------- -SHOW SHARES; ----------- Output --------- -SHOW SHARES ----------- AST ------------ -ShowShares( - ShowSharesStmt, -) - - ----------- Input ---------- -SHOW GRANTS ON TABLE db1.tb1; ----------- Output --------- -SHOW GRANTS ON TABLE db1.tb1 ----------- AST ------------ -ShowObjectGrantPrivileges( - ShowObjectGrantPrivilegesStmt { - object: Table( - "db1", - "tb1", - ), - }, -) - - ----------- Input ---------- -SHOW GRANTS ON DATABASE db; ----------- Output --------- -SHOW GRANTS ON DATABASE db ----------- AST ------------ -ShowObjectGrantPrivileges( - ShowObjectGrantPrivilegesStmt { - object: Database( - "db", - ), - }, -) - - ----------- Input ---------- -SHOW GRANTS OF SHARE t; ----------- Output --------- -SHOW GRANTS OF SHARE t ----------- AST ------------ -ShowGrantsOfShare( - ShowGrantsOfShareStmt { - share_name: "t", - }, -) - - ---------- Input ---------- UPDATE db1.tb1 set a = a + 1, b = 2 WHERE c > 3; ---------- Output --------- diff --git a/src/query/catalog/src/catalog/interface.rs b/src/query/catalog/src/catalog/interface.rs index e6d1b19daa14..954251f3bf38 100644 --- a/src/query/catalog/src/catalog/interface.rs +++ b/src/query/catalog/src/catalog/interface.rs @@ -206,7 +206,11 @@ pub trait Catalog: DynClone + Send + Sync + Debug { ) -> databend_common_exception::Result>>; // Mget the db name by meta id. - async fn get_db_name_by_id(&self, db_ids: MetaId) -> databend_common_exception::Result; + async fn get_db_name_by_id( + &self, + tenant: &Tenant, + db_ids: MetaId, + ) -> databend_common_exception::Result; // Mget the dbs name by meta ids. async fn mget_database_names_by_ids( diff --git a/src/query/catalog/src/catalog/session_catalog.rs b/src/query/catalog/src/catalog/session_catalog.rs index c67070a7f51c..698951ce7b61 100644 --- a/src/query/catalog/src/catalog/session_catalog.rs +++ b/src/query/catalog/src/catalog/session_catalog.rs @@ -250,8 +250,12 @@ impl Catalog for SessionCatalog { } // Mget the db name by meta id. - async fn get_db_name_by_id(&self, db_id: MetaId) -> databend_common_exception::Result { - self.inner.get_db_name_by_id(db_id).await + async fn get_db_name_by_id( + &self, + tenant: &Tenant, + db_id: MetaId, + ) -> databend_common_exception::Result { + self.inner.get_db_name_by_id(tenant, db_id).await } // Mget the dbs name by meta ids. @@ -355,9 +359,7 @@ impl Catalog for SessionCatalog { TxnState::AutoCommit => self.inner.update_table_meta(table_info, req).await, TxnState::Active => { self.txn_mgr.lock().update_table_meta(req, table_info); - Ok(UpdateTableMetaReply { - share_table_info: None, - }) + Ok(UpdateTableMetaReply {}) } TxnState::Fail => unreachable!(), } diff --git a/src/query/ee/src/stream/handler.rs b/src/query/ee/src/stream/handler.rs index 869ff8adf13d..f1cfb5f3bfad 100644 --- a/src/query/ee/src/stream/handler.rs +++ b/src/query/ee/src/stream/handler.rs @@ -175,7 +175,7 @@ impl StreamHandler for RealStreamHandler { }) .await } else if plan.if_exists { - Ok(DropTableReply { spec_vec: None }) + Ok(DropTableReply {}) } else { Err(ErrorCode::UnknownStream(format!( "unknown stream `{}`.`{}` in catalog '{}'", diff --git a/src/query/service/Cargo.toml b/src/query/service/Cargo.toml index 2fc5bc2ecb91..32c59ccee30a 100644 --- a/src/query/service/Cargo.toml +++ b/src/query/service/Cargo.toml @@ -65,7 +65,6 @@ databend-common-pipeline-sinks = { path = "../pipeline/sinks" } databend-common-pipeline-sources = { path = "../pipeline/sources" } databend-common-pipeline-transforms = { path = "../pipeline/transforms" } databend-common-settings = { path = "../settings" } -databend-common-sharing = { path = "../sharing" } databend-common-sql = { path = "../sql" } databend-common-storage = { path = "../../common/storage" } databend-common-storages-delta = { path = "../storages/delta" } @@ -77,7 +76,6 @@ databend-common-storages-information-schema = { path = "../storages/information_ databend-common-storages-null = { path = "../storages/null" } databend-common-storages-parquet = { path = "../storages/parquet" } databend-common-storages-result-cache = { path = "../storages/result_cache" } -databend-common-storages-share = { path = "../storages/share" } databend-common-storages-stage = { path = "../storages/stage" } databend-common-storages-stream = { path = "../storages/stream" } databend-common-storages-system = { path = "../storages/system" } diff --git a/src/query/service/src/catalogs/default/database_catalog.rs b/src/query/service/src/catalogs/default/database_catalog.rs index b6a3f60e3e34..e0333418a8dd 100644 --- a/src/query/service/src/catalogs/default/database_catalog.rs +++ b/src/query/service/src/catalogs/default/database_catalog.rs @@ -318,13 +318,16 @@ impl Catalog for DatabaseCatalog { } #[async_backtrace::framed] - async fn get_db_name_by_id(&self, db_id: MetaId) -> Result { - let res = self.immutable_catalog.get_db_name_by_id(db_id).await; + async fn get_db_name_by_id(&self, tenant: &Tenant, db_id: MetaId) -> Result { + let res = self + .immutable_catalog + .get_db_name_by_id(tenant, db_id) + .await; if let Ok(x) = res { Ok(x) } else { - self.mutable_catalog.get_db_name_by_id(db_id).await + self.mutable_catalog.get_db_name_by_id(tenant, db_id).await } } diff --git a/src/query/service/src/catalogs/default/immutable_catalog.rs b/src/query/service/src/catalogs/default/immutable_catalog.rs index e9497efbfc56..fa43a8b99cc3 100644 --- a/src/query/service/src/catalogs/default/immutable_catalog.rs +++ b/src/query/service/src/catalogs/default/immutable_catalog.rs @@ -217,7 +217,11 @@ impl Catalog for ImmutableCatalog { Ok(table_name) } - async fn get_db_name_by_id(&self, db_id: MetaId) -> databend_common_exception::Result { + async fn get_db_name_by_id( + &self, + _tenant: &Tenant, + db_id: MetaId, + ) -> databend_common_exception::Result { if self.sys_db.get_db_info().ident.db_id == db_id { Ok("system".to_string()) } else if self.info_schema_db.get_db_info().ident.db_id == db_id { diff --git a/src/query/service/src/catalogs/default/mutable_catalog.rs b/src/query/service/src/catalogs/default/mutable_catalog.rs index b56829394b60..4bbcf06509e4 100644 --- a/src/query/service/src/catalogs/default/mutable_catalog.rs +++ b/src/query/service/src/catalogs/default/mutable_catalog.rs @@ -39,6 +39,7 @@ use databend_common_meta_app::schema::CreateTableReply; use databend_common_meta_app::schema::CreateTableReq; use databend_common_meta_app::schema::CreateVirtualColumnReply; use databend_common_meta_app::schema::CreateVirtualColumnReq; +use databend_common_meta_app::schema::DatabaseIdIdent; use databend_common_meta_app::schema::DatabaseIdent; use databend_common_meta_app::schema::DatabaseInfo; use databend_common_meta_app::schema::DatabaseMeta; @@ -262,10 +263,7 @@ impl Catalog for MutableCatalog { }); let database = self.build_db_instance(&db_info)?; database.init_database(req.name_ident.tenant_name()).await?; - Ok(CreateDatabaseReply { - db_id: res.db_id, - spec_vec: None, - }) + Ok(CreateDatabaseReply { db_id: res.db_id }) } #[async_backtrace::framed] @@ -373,25 +371,41 @@ impl Catalog for MutableCatalog { async fn mget_table_names_by_ids( &self, - _tenant: &Tenant, + tenant: &Tenant, table_ids: &[MetaId], ) -> databend_common_exception::Result>> { - let res = self.ctx.meta.mget_table_names_by_ids(table_ids).await?; + let res = self + .ctx + .meta + .mget_table_names_by_ids(tenant, table_ids) + .await?; Ok(res) } #[async_backtrace::framed] - async fn get_db_name_by_id(&self, db_id: MetaId) -> databend_common_exception::Result { - let res = self.ctx.meta.get_db_name_by_id(db_id).await?; + async fn get_db_name_by_id( + &self, + tenant: &Tenant, + db_id: MetaId, + ) -> databend_common_exception::Result { + let res = self + .ctx + .meta + .get_db_name_by_id(DatabaseIdIdent::new(tenant, db_id)) + .await?; Ok(res) } async fn mget_database_names_by_ids( &self, - _tenant: &Tenant, + tenant: &Tenant, db_ids: &[MetaId], ) -> Result>> { - let res = self.ctx.meta.mget_database_names_by_ids(db_ids).await?; + let res = self + .ctx + .meta + .mget_database_names_by_ids(tenant, db_ids) + .await?; Ok(res) } diff --git a/src/query/service/src/databases/database_factory.rs b/src/query/service/src/databases/database_factory.rs index f69dc4f56f1a..ee4e57ad1a2b 100644 --- a/src/query/service/src/databases/database_factory.rs +++ b/src/query/service/src/databases/database_factory.rs @@ -20,7 +20,6 @@ use databend_common_exception::Result; use databend_common_meta_app::schema::DatabaseInfo; use crate::databases::default::DefaultDatabase; -use crate::databases::share::ShareDatabase; use crate::databases::Database; use crate::databases::DatabaseContext; @@ -46,7 +45,6 @@ impl DatabaseFactory { let db = match engine.as_str() { DefaultDatabase::NAME => DefaultDatabase::try_create(ctx, db_info.clone())?, - ShareDatabase::NAME => ShareDatabase::try_create(ctx, db_info.clone())?, _ => { let err = diff --git a/src/query/service/src/databases/mod.rs b/src/query/service/src/databases/mod.rs index 769a63f85f81..7cd74c91decc 100644 --- a/src/query/service/src/databases/mod.rs +++ b/src/query/service/src/databases/mod.rs @@ -17,7 +17,6 @@ mod database_context; mod database_factory; mod default; mod information_schema; -mod share; mod system; pub use database::Database; diff --git a/src/query/service/src/databases/share/mod.rs b/src/query/service/src/databases/share/mod.rs deleted file mode 100644 index 9663806f6277..000000000000 --- a/src/query/service/src/databases/share/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -mod share_database; - -pub use share_database::ShareDatabase; diff --git a/src/query/service/src/databases/share/share_database.rs b/src/query/service/src/databases/share/share_database.rs deleted file mode 100644 index a0a7e055d2b2..000000000000 --- a/src/query/service/src/databases/share/share_database.rs +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::str; -use std::sync::Arc; - -use databend_common_catalog::table::Table; -use databend_common_exception::ErrorCode; -use databend_common_exception::Result; -use databend_common_meta_api::SchemaApi; -use databend_common_meta_app::schema::CreateTableReply; -use databend_common_meta_app::schema::CreateTableReq; -use databend_common_meta_app::schema::DatabaseInfo; -use databend_common_meta_app::schema::DropTableByIdReq; -use databend_common_meta_app::schema::DropTableReply; -use databend_common_meta_app::schema::GetTableCopiedFileReply; -use databend_common_meta_app::schema::GetTableCopiedFileReq; -use databend_common_meta_app::schema::RenameTableReply; -use databend_common_meta_app::schema::RenameTableReq; -use databend_common_meta_app::schema::SetTableColumnMaskPolicyReply; -use databend_common_meta_app::schema::SetTableColumnMaskPolicyReq; -use databend_common_meta_app::schema::TableInfo; -use databend_common_meta_app::schema::TruncateTableReply; -use databend_common_meta_app::schema::TruncateTableReq; -use databend_common_meta_app::schema::UndropTableReply; -use databend_common_meta_app::schema::UndropTableReq; -use databend_common_meta_app::schema::UpdateTableMetaReply; -use databend_common_meta_app::schema::UpdateTableMetaReq; -use databend_common_meta_app::schema::UpsertTableOptionReply; -use databend_common_meta_app::schema::UpsertTableOptionReq; -use databend_common_sharing::ShareEndpointManager; - -use crate::databases::Database; -use crate::databases::DatabaseContext; - -// Share Database implementation for `Database` trait. -#[derive(Clone)] -pub struct ShareDatabase { - ctx: DatabaseContext, - - db_info: DatabaseInfo, -} - -impl ShareDatabase { - pub const NAME: &'static str = "SHARE"; - pub fn try_create(ctx: DatabaseContext, db_info: DatabaseInfo) -> Result> { - Ok(Box::new(Self { ctx, db_info })) - } - - fn load_tables(&self, table_infos: Vec>) -> Result>> { - table_infos.iter().try_fold(vec![], |mut acc, item| { - let tbl = self.get_table_by_info(item.as_ref())?; - acc.push(tbl); - Ok(acc) - }) - } - - #[async_backtrace::framed] - async fn get_table_info(&self, table_name: &str) -> Result> { - let table_info_map = ShareEndpointManager::instance() - .get_table_info_map(self.ctx.tenant(), &self.db_info, vec![ - table_name.to_string(), - ]) - .await?; - match table_info_map.get(table_name) { - None => Err(ErrorCode::UnknownTable(format!( - "share table `{}`.`{}` is unknown", - self.db_info.name_ident.database_name(), - table_name - ))), - Some(table_info) => Ok(Arc::new(table_info.clone())), - } - } - - #[async_backtrace::framed] - async fn list_tables(&self) -> Result>> { - let table_info_map = ShareEndpointManager::instance() - .get_table_info_map(&self.ctx.tenant, &self.db_info, vec![]) - .await?; - let table_infos: Vec> = table_info_map - .values() - .map(|table_info| Arc::new(table_info.to_owned())) - .collect(); - Ok(table_infos) - } -} - -#[async_trait::async_trait] -impl Database for ShareDatabase { - fn name(&self) -> &str { - self.db_info.name_ident.database_name() - } - - fn get_db_info(&self) -> &DatabaseInfo { - &self.db_info - } - - fn get_table_by_info(&self, table_info: &TableInfo) -> Result> { - let storage = self.ctx.storage_factory.clone(); - storage.get_table(table_info) - } - - // Get one table by db and table name. - #[async_backtrace::framed] - async fn get_table(&self, table_name: &str) -> Result> { - let table_info = self.get_table_info(table_name).await?; - self.get_table_by_info(table_info.as_ref()) - } - - #[async_backtrace::framed] - async fn list_tables(&self) -> Result>> { - let table_infos = self.list_tables().await?; - - self.load_tables(table_infos) - } - - #[async_backtrace::framed] - async fn list_tables_history(&self) -> Result>> { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot list table history from a shared database".to_string(), - )) - } - - #[async_backtrace::framed] - async fn create_table(&self, _req: CreateTableReq) -> Result { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot create table from a shared database".to_string(), - )) - } - - #[async_backtrace::framed] - async fn drop_table_by_id(&self, _req: DropTableByIdReq) -> Result { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot drop table from a shared database".to_string(), - )) - } - - #[async_backtrace::framed] - async fn undrop_table(&self, _req: UndropTableReq) -> Result { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot undrop table from a shared database".to_string(), - )) - } - - #[async_backtrace::framed] - async fn rename_table(&self, _req: RenameTableReq) -> Result { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot rename table from a shared database".to_string(), - )) - } - - #[async_backtrace::framed] - async fn upsert_table_option( - &self, - _req: UpsertTableOptionReq, - ) -> Result { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot upsert table option from a shared database".to_string(), - )) - } - - #[async_backtrace::framed] - async fn update_table_meta(&self, _req: UpdateTableMetaReq) -> Result { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot upsert table meta from a shared database".to_string(), - )) - } - - #[async_backtrace::framed] - async fn set_table_column_mask_policy( - &self, - _req: SetTableColumnMaskPolicyReq, - ) -> Result { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot set_table_column_mask_policy from a shared database" - .to_string(), - )) - } - - #[async_backtrace::framed] - async fn get_table_copied_file_info( - &self, - req: GetTableCopiedFileReq, - ) -> Result { - let res = self.ctx.meta.get_table_copied_file_info(req).await?; - Ok(res) - } - - #[async_backtrace::framed] - async fn truncate_table(&self, _req: TruncateTableReq) -> Result { - Err(ErrorCode::PermissionDenied( - "Permission denied, cannot truncate table from a shared database".to_string(), - )) - } -} diff --git a/src/query/service/src/global_services.rs b/src/query/service/src/global_services.rs index 93df6d01714b..629388adacd2 100644 --- a/src/query/service/src/global_services.rs +++ b/src/query/service/src/global_services.rs @@ -25,7 +25,6 @@ use databend_common_config::GlobalConfig; use databend_common_config::InnerConfig; use databend_common_exception::Result; use databend_common_meta_app::schema::CatalogType; -use databend_common_sharing::ShareEndpointManager; use databend_common_storage::DataOperator; use databend_common_storage::ShareTableConfig; use databend_common_storages_hive::HiveCreator; @@ -115,7 +114,6 @@ impl GlobalServices { ) .await?; RoleCacheManager::init()?; - ShareEndpointManager::init()?; DataOperator::init(&config.storage).await?; ShareTableConfig::init( diff --git a/src/query/service/src/interpreters/access/privilege_access.rs b/src/query/service/src/interpreters/access/privilege_access.rs index c6a3fd7398de..a7ea1ed844cc 100644 --- a/src/query/service/src/interpreters/access/privilege_access.rs +++ b/src/query/service/src/interpreters/access/privilege_access.rs @@ -978,10 +978,6 @@ impl AccessChecker for PrivilegeAccess { ) .await?; } - Plan::GrantShareObject(_) - | Plan::RevokeShareObject(_) - | Plan::ShowObjectGrantPrivileges(_) - | Plan::ShowGrantTenantsOfShare(_) | Plan::GrantRole(_) | Plan::GrantPriv(_) | Plan::RevokePriv(_) @@ -1023,7 +1019,6 @@ impl AccessChecker for PrivilegeAccess { | Plan::RenameDatabase(_) | Plan::RevertTable(_) | Plan::AlterUDF(_) - | Plan::AlterShareTenants(_) | Plan::RefreshIndex(_) | Plan::RefreshTableIndex(_) => { self.validate_access(&GrantObject::Global, UserPrivilegeType::Alter) @@ -1044,13 +1039,6 @@ impl AccessChecker for PrivilegeAccess { Plan::RemoveStage(plan) => { self.validate_stage_access(&plan.stage, UserPrivilegeType::Write).await?; } - Plan::CreateShareEndpoint(_) - | Plan::ShowShareEndpoint(_) - | Plan::DropShareEndpoint(_) - | Plan::CreateShare(_) - | Plan::DropShare(_) - | Plan::DescShare(_) - | Plan::ShowShares(_) | Plan::ShowCreateCatalog(_) | Plan::CreateCatalog(_) | Plan::DropCatalog(_) diff --git a/src/query/service/src/interpreters/common/grant.rs b/src/query/service/src/interpreters/common/grant.rs index fb675b6284e4..3106ba2d3cd0 100644 --- a/src/query/service/src/interpreters/common/grant.rs +++ b/src/query/service/src/interpreters/common/grant.rs @@ -55,7 +55,7 @@ pub async fn validate_grant_object_exists( } GrantObject::DatabaseById(catalog_name, db_id) => { let catalog = ctx.get_catalog(catalog_name).await?; - if catalog.get_db_name_by_id(*db_id).await.is_err() { + if catalog.get_db_name_by_id(&tenant, *db_id).await.is_err() { return Err(databend_common_exception::ErrorCode::UnknownDatabaseId( format!( "database id {} not exists in catalog {}", diff --git a/src/query/service/src/interpreters/interpreter_database_create.rs b/src/query/service/src/interpreters/interpreter_database_create.rs index 2214b6076188..d7ab0391ea39 100644 --- a/src/query/service/src/interpreters/interpreter_database_create.rs +++ b/src/query/service/src/interpreters/interpreter_database_create.rs @@ -19,14 +19,8 @@ use databend_common_exception::Result; use databend_common_management::RoleApi; use databend_common_meta_app::principal::OwnershipObject; use databend_common_meta_app::schema::CreateDatabaseReq; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::ShareGrantObjectPrivilege; -use databend_common_meta_app::tenant::Tenant; -use databend_common_meta_app::KeyWithTenant; use databend_common_meta_types::MatchSeq; -use databend_common_sharing::ShareEndpointManager; use databend_common_sql::plans::CreateDatabasePlan; -use databend_common_storages_share::save_share_spec; use databend_common_users::RoleCacheManager; use databend_common_users::UserApiProvider; use log::debug; @@ -46,55 +40,6 @@ impl CreateDatabaseInterpreter { pub fn try_create(ctx: Arc, plan: CreateDatabasePlan) -> Result { Ok(CreateDatabaseInterpreter { ctx, plan }) } - - async fn check_create_database_from_share( - &self, - tenant: &Tenant, - share_name: &ShareNameIdent, - ) -> Result<()> { - let share_specs = ShareEndpointManager::instance() - .get_inbound_shares(tenant, Some(share_name.tenant()), Some(share_name.clone())) - .await?; - match share_specs.first() { - Some((_, share_spec)) => { - if !share_spec - .tenants - .contains(&tenant.tenant_name().to_string()) - { - return Err(ErrorCode::UnknownShareAccounts(format!( - "share {} has not granted privilege to {}", - share_name.display(), - tenant.tenant_name() - ))); - } - match share_spec.db_privileges { - Some(db_privileges) => { - if !db_privileges.contains(ShareGrantObjectPrivilege::Usage) { - return Err(ErrorCode::ShareHasNoGrantedPrivilege(format!( - "share {} has not granted privilege to {}", - share_name.display(), - tenant.tenant_name() - ))); - } - } - None => { - return Err(ErrorCode::ShareHasNoGrantedPrivilege(format!( - "share {} has not granted privilege to {}", - share_name.display(), - tenant.tenant_name() - ))); - } - } - } - None => { - return Err(ErrorCode::UnknownShare(format!( - "UnknownShare {:?}", - share_name - ))); - } - } - Ok(()) - } } #[async_trait::async_trait] @@ -124,12 +69,6 @@ impl Interpreter for CreateDatabaseInterpreter { quota.max_databases ))); }; - // if create from other tenant, check from share endpoint - if let Some(ref share_name) = self.plan.meta.from_share { - let share_name_ident = share_name.clone().to_tident(()); - self.check_create_database_from_share(&tenant, &share_name_ident) - .await?; - } let create_db_req: CreateDatabaseReq = self.plan.clone().into(); let reply = catalog.create_database(create_db_req).await?; @@ -150,22 +89,6 @@ impl Interpreter for CreateDatabaseInterpreter { RoleCacheManager::instance().invalidate_cache(&tenant); } - // handle share cleanups with the DropDatabaseReply - if let Some(spec_vec) = reply.spec_vec { - let mut share_table_into = Vec::with_capacity(spec_vec.len()); - for share_spec in &spec_vec { - share_table_into.push((share_spec.name.clone(), None)); - } - - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - Some(spec_vec), - Some(share_table_into), - ) - .await?; - } - Ok(PipelineBuildResult::create()) } } diff --git a/src/query/service/src/interpreters/interpreter_database_drop.rs b/src/query/service/src/interpreters/interpreter_database_drop.rs index bfc77621e651..9269f6838577 100644 --- a/src/query/service/src/interpreters/interpreter_database_drop.rs +++ b/src/query/service/src/interpreters/interpreter_database_drop.rs @@ -18,7 +18,6 @@ use databend_common_exception::Result; use databend_common_management::RoleApi; use databend_common_meta_app::principal::OwnershipObject; use databend_common_sql::plans::DropDatabasePlan; -use databend_common_storages_share::save_share_spec; use databend_common_users::RoleCacheManager; use databend_common_users::UserApiProvider; @@ -67,23 +66,7 @@ impl Interpreter for DropDatabaseInterpreter { } // actual drop database - let resp = catalog.drop_database(self.plan.clone().into()).await?; - - // handle share cleanups with the DropDatabaseReply - if let Some(spec_vec) = resp.spec_vec { - let mut share_table_into = Vec::with_capacity(spec_vec.len()); - for share_spec in &spec_vec { - share_table_into.push((share_spec.name.clone(), None)); - } - - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - Some(spec_vec), - Some(share_table_into), - ) - .await?; - } + let _resp = catalog.drop_database(self.plan.clone().into()).await?; Ok(PipelineBuildResult::create()) } diff --git a/src/query/service/src/interpreters/interpreter_factory.rs b/src/query/service/src/interpreters/interpreter_factory.rs index 00c9ae6a39ed..e81cb0a25268 100644 --- a/src/query/service/src/interpreters/interpreter_factory.rs +++ b/src/query/service/src/interpreters/interpreter_factory.rs @@ -25,7 +25,6 @@ use super::interpreter_catalog_show_create::ShowCreateCatalogInterpreter; use super::interpreter_index_create::CreateIndexInterpreter; use super::interpreter_index_drop::DropIndexInterpreter; use super::interpreter_merge_into::MergeIntoInterpreter; -use super::interpreter_share_desc::DescShareInterpreter; use super::interpreter_table_index_create::CreateTableIndexInterpreter; use super::interpreter_table_index_drop::DropTableIndexInterpreter; use super::interpreter_table_index_refresh::RefreshTableIndexInterpreter; @@ -63,10 +62,7 @@ use crate::interpreters::interpreter_txn_begin::BeginInterpreter; use crate::interpreters::interpreter_txn_commit::CommitInterpreter; use crate::interpreters::interpreter_view_describe::DescribeViewInterpreter; use crate::interpreters::AlterUserInterpreter; -use crate::interpreters::CreateShareEndpointInterpreter; -use crate::interpreters::CreateShareInterpreter; use crate::interpreters::CreateStreamInterpreter; -use crate::interpreters::DropShareInterpreter; use crate::interpreters::DropStreamInterpreter; use crate::interpreters::DropUserInterpreter; use crate::interpreters::SetRoleInterpreter; @@ -446,43 +442,6 @@ impl InterpreterFactory { )?)), Plan::Kill(p) => Ok(Arc::new(KillInterpreter::try_create(ctx, *p.clone())?)), - // share plans - Plan::CreateShareEndpoint(p) => Ok(Arc::new( - CreateShareEndpointInterpreter::try_create(ctx, *p.clone())?, - )), - Plan::ShowShareEndpoint(p) => Ok(Arc::new(ShowShareEndpointInterpreter::try_create( - ctx, - *p.clone(), - )?)), - Plan::DropShareEndpoint(p) => Ok(Arc::new(DropShareEndpointInterpreter::try_create( - ctx, - *p.clone(), - )?)), - Plan::CreateShare(p) => Ok(Arc::new(CreateShareInterpreter::try_create( - ctx, - *p.clone(), - )?)), - Plan::DropShare(p) => Ok(Arc::new(DropShareInterpreter::try_create(ctx, *p.clone())?)), - Plan::GrantShareObject(p) => Ok(Arc::new(GrantShareObjectInterpreter::try_create( - ctx, - *p.clone(), - )?)), - Plan::RevokeShareObject(p) => Ok(Arc::new(RevokeShareObjectInterpreter::try_create( - ctx, - *p.clone(), - )?)), - Plan::AlterShareTenants(p) => Ok(Arc::new(AlterShareTenantsInterpreter::try_create( - ctx, - *p.clone(), - )?)), - Plan::DescShare(p) => Ok(Arc::new(DescShareInterpreter::try_create(ctx, *p.clone())?)), - Plan::ShowShares(_) => Ok(Arc::new(ShowSharesInterpreter::try_create(ctx)?)), - Plan::ShowObjectGrantPrivileges(p) => Ok(Arc::new( - ShowObjectGrantPrivilegesInterpreter::try_create(ctx, *p.clone())?, - )), - Plan::ShowGrantTenantsOfShare(p) => Ok(Arc::new( - ShowGrantTenantsOfShareInterpreter::try_create(ctx, *p.clone())?, - )), Plan::RevertTable(p) => Ok(Arc::new(RevertTableInterpreter::try_create( ctx, *p.clone(), diff --git a/src/query/service/src/interpreters/interpreter_share_alter_tenants.rs b/src/query/service/src/interpreters/interpreter_share_alter_tenants.rs deleted file mode 100644 index f757224678a9..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_alter_tenants.rs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use chrono::Utc; -use databend_common_exception::Result; -use databend_common_meta_api::ShareApi; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::AddShareAccountsReq; -use databend_common_meta_app::share::RemoveShareAccountsReq; -use databend_common_storages_share::save_share_spec; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; -use crate::sql::plans::share::AlterShareTenantsPlan; - -pub struct AlterShareTenantsInterpreter { - ctx: Arc, - plan: AlterShareTenantsPlan, -} - -impl AlterShareTenantsInterpreter { - pub fn try_create(ctx: Arc, plan: AlterShareTenantsPlan) -> Result { - Ok(AlterShareTenantsInterpreter { ctx, plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for AlterShareTenantsInterpreter { - fn name(&self) -> &str { - "AlterShareTenantsInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let tenant = self.ctx.get_tenant(); - let meta_api = UserApiProvider::instance().get_meta_store_client(); - if self.plan.is_add { - let req = AddShareAccountsReq { - share_name: ShareNameIdent::new(&tenant, &self.plan.share), - if_exists: self.plan.if_exists, - accounts: self.plan.accounts.clone(), - share_on: Utc::now(), - }; - let resp = meta_api.add_share_tenants(req).await?; - - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - resp.spec_vec, - None, - ) - .await?; - } else { - let req = RemoveShareAccountsReq { - share_name: ShareNameIdent::new(&tenant, &self.plan.share), - if_exists: self.plan.if_exists, - accounts: self.plan.accounts.clone(), - }; - let resp = meta_api.remove_share_tenants(req).await?; - - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - resp.spec_vec, - None, - ) - .await?; - }; - - Ok(PipelineBuildResult::create()) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_create.rs b/src/query/service/src/interpreters/interpreter_share_create.rs deleted file mode 100644 index 590829a7777f..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_create.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_meta_api::ShareApi; -use databend_common_storages_share::save_share_spec; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; -use crate::sql::plans::share::CreateSharePlan; - -pub struct CreateShareInterpreter { - ctx: Arc, - plan: CreateSharePlan, -} - -impl CreateShareInterpreter { - pub fn try_create(ctx: Arc, plan: CreateSharePlan) -> Result { - Ok(CreateShareInterpreter { ctx, plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for CreateShareInterpreter { - fn name(&self) -> &str { - "CreateShareInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let resp = meta_api.create_share(self.plan.clone().into()).await?; - - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - resp.spec_vec, - None, - ) - .await?; - - Ok(PipelineBuildResult::create()) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_desc.rs b/src/query/service/src/interpreters/interpreter_share_desc.rs deleted file mode 100644 index 93b85405eb2a..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_desc.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_expression::types::StringType; -use databend_common_expression::DataBlock; -use databend_common_expression::FromData; -use databend_common_meta_api::ShareApi; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::GetShareGrantObjectReq; -use databend_common_meta_app::share::ShareGrantObjectName; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; -use crate::sql::plans::share::DescSharePlan; - -pub struct DescShareInterpreter { - ctx: Arc, - plan: DescSharePlan, -} - -impl DescShareInterpreter { - pub fn try_create(ctx: Arc, plan: DescSharePlan) -> Result { - Ok(DescShareInterpreter { ctx, plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for DescShareInterpreter { - fn name(&self) -> &str { - "DescShareInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let req = GetShareGrantObjectReq { - share_name: ShareNameIdent::new(self.ctx.get_tenant(), &self.plan.share), - }; - let resp = meta_api.get_share_grant_objects(req).await?; - if resp.objects.is_empty() { - return Ok(PipelineBuildResult::create()); - } - - let mut names: Vec = vec![]; - let mut kinds: Vec = vec![]; - let mut shared_owns: Vec = vec![]; - for entry in resp.objects.iter() { - match &entry.object { - ShareGrantObjectName::Database(db) => { - kinds.push("DATABASE".to_string()); - names.push(db.clone()); - } - ShareGrantObjectName::Table(db, table_name) => { - kinds.push("TABLE".to_string()); - names.push(format!("{}.{}", db, table_name)); - } - } - shared_owns.push(entry.grant_on.to_string()); - } - - PipelineBuildResult::from_blocks(vec![DataBlock::new_from_columns(vec![ - StringType::from_data(kinds), - StringType::from_data(names), - StringType::from_data(shared_owns), - ])]) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_drop.rs b/src/query/service/src/interpreters/interpreter_share_drop.rs deleted file mode 100644 index 274342a516bf..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_drop.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_meta_api::ShareApi; -use databend_common_storages_share::save_share_spec; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; -use crate::sql::plans::share::DropSharePlan; - -pub struct DropShareInterpreter { - ctx: Arc, - plan: DropSharePlan, -} - -impl DropShareInterpreter { - pub fn try_create(ctx: Arc, plan: DropSharePlan) -> Result { - Ok(DropShareInterpreter { ctx, plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for DropShareInterpreter { - fn name(&self) -> &str { - "DropShareInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let resp = meta_api.drop_share(self.plan.clone().into()).await?; - - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - resp.spec_vec, - Some(vec![(self.plan.share.clone(), None)]), - ) - .await?; - - Ok(PipelineBuildResult::create()) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_endpoint_create.rs b/src/query/service/src/interpreters/interpreter_share_endpoint_create.rs deleted file mode 100644 index e089f8fdb1b5..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_endpoint_create.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_meta_api::ShareApi; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sql::plans::share::CreateShareEndpointPlan; - -pub struct CreateShareEndpointInterpreter { - plan: CreateShareEndpointPlan, -} - -impl CreateShareEndpointInterpreter { - pub fn try_create(_ctx: Arc, plan: CreateShareEndpointPlan) -> Result { - Ok(CreateShareEndpointInterpreter { plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for CreateShareEndpointInterpreter { - fn name(&self) -> &str { - "CreateShareEndpointInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let _resp = meta_api - .create_share_endpoint(self.plan.clone().into()) - .await?; - - Ok(PipelineBuildResult::create()) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_endpoint_drop.rs b/src/query/service/src/interpreters/interpreter_share_endpoint_drop.rs deleted file mode 100644 index a56c97b81c8c..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_endpoint_drop.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_meta_api::ShareApi; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sql::plans::share::DropShareEndpointPlan; - -pub struct DropShareEndpointInterpreter { - plan: DropShareEndpointPlan, -} - -impl DropShareEndpointInterpreter { - pub fn try_create(_ctx: Arc, plan: DropShareEndpointPlan) -> Result { - Ok(DropShareEndpointInterpreter { plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for DropShareEndpointInterpreter { - fn name(&self) -> &str { - "DropShareEndpointInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let _resp = meta_api - .drop_share_endpoint(self.plan.clone().into()) - .await?; - - Ok(PipelineBuildResult::create()) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_endpoint_show.rs b/src/query/service/src/interpreters/interpreter_share_endpoint_show.rs deleted file mode 100644 index 5deed34419be..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_endpoint_show.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_expression::types::StringType; -use databend_common_expression::DataBlock; -use databend_common_expression::FromData; -use databend_common_meta_api::ShareApi; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sql::plans::share::ShowShareEndpointPlan; - -pub struct ShowShareEndpointInterpreter { - plan: ShowShareEndpointPlan, -} - -impl ShowShareEndpointInterpreter { - pub fn try_create(_ctx: Arc, plan: ShowShareEndpointPlan) -> Result { - Ok(ShowShareEndpointInterpreter { plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for ShowShareEndpointInterpreter { - fn name(&self) -> &str { - "ShowShareEndpointInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let resp = meta_api - .get_share_endpoint(self.plan.clone().into()) - .await?; - - let mut endpoints: Vec = vec![]; - let mut urls: Vec = vec![]; - let mut to_tenants: Vec = vec![]; - let mut args: Vec = vec![]; - let mut comments: Vec = vec![]; - let mut created_on_vec: Vec = vec![]; - for (endpoint, meta) in resp.share_endpoint_meta_vec { - endpoints.push(endpoint.name().to_string()); - urls.push(meta.url.clone()); - to_tenants.push(meta.tenant.clone()); - args.push(format!("{:?}", meta.args)); - comments.push(meta.comment.unwrap_or_default()); - created_on_vec.push(meta.create_on.to_string()); - } - - PipelineBuildResult::from_blocks(vec![DataBlock::new_from_columns(vec![ - StringType::from_data(endpoints), - StringType::from_data(urls), - StringType::from_data(to_tenants), - StringType::from_data(args), - StringType::from_data(comments), - StringType::from_data(created_on_vec), - ])]) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_grant_object.rs b/src/query/service/src/interpreters/interpreter_share_grant_object.rs deleted file mode 100644 index 65f81bc2458b..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_grant_object.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use chrono::Utc; -use databend_common_exception::Result; -use databend_common_meta_api::ShareApi; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::GrantShareObjectReq; -use databend_common_storages_share::save_share_spec; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; -use crate::sql::plans::share::GrantShareObjectPlan; - -pub struct GrantShareObjectInterpreter { - ctx: Arc, - plan: GrantShareObjectPlan, -} - -impl GrantShareObjectInterpreter { - pub fn try_create(ctx: Arc, plan: GrantShareObjectPlan) -> Result { - Ok(GrantShareObjectInterpreter { ctx, plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for GrantShareObjectInterpreter { - fn name(&self) -> &str { - "GrantShareObjectInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let tenant = self.ctx.get_tenant(); - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let req = GrantShareObjectReq { - share_name: ShareNameIdent::new(&tenant, &self.plan.share), - object: self.plan.object.clone(), - privilege: self.plan.privilege, - grant_on: Utc::now(), - }; - let resp = meta_api.grant_share_object(req).await?; - - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - resp.spec_vec, - Some(vec![resp.share_table_info]), - ) - .await?; - - Ok(PipelineBuildResult::create()) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_revoke_object.rs b/src/query/service/src/interpreters/interpreter_share_revoke_object.rs deleted file mode 100644 index e6b1e17f47cb..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_revoke_object.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use chrono::Utc; -use databend_common_exception::Result; -use databend_common_meta_api::ShareApi; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::RevokeShareObjectReq; -use databend_common_storages_share::save_share_spec; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; -use crate::sql::plans::share::RevokeShareObjectPlan; - -pub struct RevokeShareObjectInterpreter { - ctx: Arc, - plan: RevokeShareObjectPlan, -} - -impl RevokeShareObjectInterpreter { - pub fn try_create(ctx: Arc, plan: RevokeShareObjectPlan) -> Result { - Ok(RevokeShareObjectInterpreter { ctx, plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for RevokeShareObjectInterpreter { - fn name(&self) -> &str { - "RevokeShareObjectInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let tenant = self.ctx.get_tenant(); - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let req = RevokeShareObjectReq { - share_name: ShareNameIdent::new(&tenant, &self.plan.share), - object: self.plan.object.clone(), - privilege: self.plan.privilege, - update_on: Utc::now(), - }; - let resp = meta_api.revoke_share_object(req).await?; - - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - resp.spec_vec, - Some(vec![resp.share_table_info]), - ) - .await?; - - Ok(PipelineBuildResult::create()) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_show.rs b/src/query/service/src/interpreters/interpreter_share_show.rs deleted file mode 100644 index 6400662eafb4..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_show.rs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_expression::types::StringType; -use databend_common_expression::DataBlock; -use databend_common_expression::FromData; -use databend_common_meta_api::ShareApi; -use databend_common_meta_app::share::ShowSharesReq; -use databend_common_meta_app::KeyWithTenant; -use databend_common_sharing::ShareEndpointManager; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; - -pub struct ShowSharesInterpreter { - ctx: Arc, -} - -impl ShowSharesInterpreter { - pub fn try_create(ctx: Arc) -> Result { - Ok(ShowSharesInterpreter { ctx }) - } -} - -#[async_trait::async_trait] -impl Interpreter for ShowSharesInterpreter { - fn name(&self) -> &str { - "ShowSharesInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let tenant = self.ctx.get_tenant(); - let mut names: Vec = vec![]; - let mut kinds: Vec = vec![]; - let mut created_owns: Vec = vec![]; - let mut database_names: Vec = vec![]; - let mut from: Vec = vec![]; - let mut to: Vec = vec![]; - let mut comments: Vec = vec![]; - - // query all share endpoint for other tenant inbound shares - let share_specs = ShareEndpointManager::instance() - .get_inbound_shares(&tenant, None, None) - .await?; - for (from_tenant, share_spec) in share_specs { - names.push(share_spec.name.clone()); - kinds.push("INBOUND".to_string()); - created_owns.push(share_spec.share_on.unwrap_or_default().to_string()); - database_names.push(share_spec.database.unwrap_or_default().name); - from.push(from_tenant); - to.push(tenant.tenant_name().to_string()); - comments.push(share_spec.comment.unwrap_or_default()); - } - - let req = ShowSharesReq { - tenant: tenant.clone(), - }; - let resp = meta_api.show_shares(req).await?; - - for entry in resp.outbound_accounts { - names.push(entry.share_name.share_name().to_string()); - kinds.push("OUTBOUND".to_string()); - created_owns.push(entry.create_on.to_string()); - database_names.push(entry.database_name.unwrap_or_default()); - from.push(entry.share_name.tenant_name().to_string()); - to.push( - entry - .accounts - .map_or("".to_string(), |accounts| accounts.join(",")), - ); - comments.push(entry.comment.unwrap_or_default()); - } - - PipelineBuildResult::from_blocks(vec![DataBlock::new_from_columns(vec![ - StringType::from_data(created_owns), - StringType::from_data(kinds), - StringType::from_data(names), - StringType::from_data(database_names), - StringType::from_data(from), - StringType::from_data(to), - StringType::from_data(comments), - ])]) - } -} diff --git a/src/query/service/src/interpreters/interpreter_share_show_grant_tenants.rs b/src/query/service/src/interpreters/interpreter_share_show_grant_tenants.rs deleted file mode 100644 index 4abfe029e218..000000000000 --- a/src/query/service/src/interpreters/interpreter_share_show_grant_tenants.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_expression::types::StringType; -use databend_common_expression::DataBlock; -use databend_common_expression::FromData; -use databend_common_meta_api::ShareApi; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::GetShareGrantTenantsReq; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; -use crate::sql::plans::share::ShowGrantTenantsOfSharePlan; - -pub struct ShowGrantTenantsOfShareInterpreter { - ctx: Arc, - plan: ShowGrantTenantsOfSharePlan, -} - -impl ShowGrantTenantsOfShareInterpreter { - pub fn try_create(ctx: Arc, plan: ShowGrantTenantsOfSharePlan) -> Result { - Ok(ShowGrantTenantsOfShareInterpreter { ctx, plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for ShowGrantTenantsOfShareInterpreter { - fn name(&self) -> &str { - "ShowGrantTenantsOfShareInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let tenant = self.ctx.get_tenant(); - let req = GetShareGrantTenantsReq { - share_name: ShareNameIdent::new(&tenant, &self.plan.share_name), - }; - let resp = meta_api.get_grant_tenants_of_share(req).await?; - if resp.accounts.is_empty() { - return Ok(PipelineBuildResult::create()); - } - - let mut granted_owns: Vec = vec![]; - let mut accounts: Vec = vec![]; - - for account in resp.accounts { - granted_owns.push(account.grant_on.to_string()); - accounts.push(account.account.clone()); - } - - PipelineBuildResult::from_blocks(vec![DataBlock::new_from_columns(vec![ - StringType::from_data(granted_owns), - StringType::from_data(accounts), - ])]) - } -} diff --git a/src/query/service/src/interpreters/interpreter_show_object_grant_privileges.rs b/src/query/service/src/interpreters/interpreter_show_object_grant_privileges.rs deleted file mode 100644 index 058cb2a3db15..000000000000 --- a/src/query/service/src/interpreters/interpreter_show_object_grant_privileges.rs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use databend_common_exception::Result; -use databend_common_expression::types::StringType; -use databend_common_expression::DataBlock; -use databend_common_expression::FromData; -use databend_common_meta_api::ShareApi; -use databend_common_meta_app::share::GetObjectGrantPrivilegesReq; -use databend_common_users::UserApiProvider; - -use crate::interpreters::Interpreter; -use crate::pipelines::PipelineBuildResult; -use crate::sessions::QueryContext; -use crate::sessions::TableContext; -use crate::sql::plans::share::ShowObjectGrantPrivilegesPlan; - -pub struct ShowObjectGrantPrivilegesInterpreter { - ctx: Arc, - plan: ShowObjectGrantPrivilegesPlan, -} - -impl ShowObjectGrantPrivilegesInterpreter { - pub fn try_create(ctx: Arc, plan: ShowObjectGrantPrivilegesPlan) -> Result { - Ok(ShowObjectGrantPrivilegesInterpreter { ctx, plan }) - } -} - -#[async_trait::async_trait] -impl Interpreter for ShowObjectGrantPrivilegesInterpreter { - fn name(&self) -> &str { - "ShowObjectGrantPrivilegesInterpreter" - } - - fn is_ddl(&self) -> bool { - true - } - - #[async_backtrace::framed] - async fn execute2(&self) -> Result { - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let req = GetObjectGrantPrivilegesReq { - tenant: self.ctx.get_tenant(), - object: self.plan.object.clone(), - }; - let resp = meta_api.get_grant_privileges_of_object(req).await?; - if resp.privileges.is_empty() { - return Ok(PipelineBuildResult::create()); - } - let mut share_names: Vec = vec![]; - let mut privileges: Vec = vec![]; - let mut created_owns: Vec = vec![]; - - for privilege in resp.privileges { - share_names.push(privilege.share_name); - privileges.push(privilege.privileges.to_string()); - created_owns.push(privilege.grant_on.to_string()); - } - - PipelineBuildResult::from_blocks(vec![DataBlock::new_from_columns(vec![ - StringType::from_data(created_owns), - StringType::from_data(privileges), - StringType::from_data(share_names), - ])]) - } -} diff --git a/src/query/service/src/interpreters/interpreter_table_add_column.rs b/src/query/service/src/interpreters/interpreter_table_add_column.rs index 0076d0b00c9b..7f39f72ac87c 100644 --- a/src/query/service/src/interpreters/interpreter_table_add_column.rs +++ b/src/query/service/src/interpreters/interpreter_table_add_column.rs @@ -28,7 +28,6 @@ use databend_common_sql::field_default_value; use databend_common_sql::plans::AddColumnOption; use databend_common_sql::plans::AddTableColumnPlan; use databend_common_storages_fuse::FuseTable; -use databend_common_storages_share::save_share_table_info; use databend_common_storages_stream::stream_table::STREAM_ENGINE; use databend_common_storages_view::view_table::VIEW_ENGINE; use databend_storages_common_table_meta::meta::TableSnapshot; @@ -131,16 +130,7 @@ impl Interpreter for AddTableColumnInterpreter { update_stream_meta: vec![], }; - let res = catalog.update_table_meta(table_info, req).await?; - - if let Some(share_table_info) = res.share_table_info { - save_share_table_info( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - share_table_info, - ) - .await?; - } + let _res = catalog.update_table_meta(table_info, req).await?; }; Ok(PipelineBuildResult::create()) diff --git a/src/query/service/src/interpreters/interpreter_table_create.rs b/src/query/service/src/interpreters/interpreter_table_create.rs index 1b702bcdcee4..27f178e44bbb 100644 --- a/src/query/service/src/interpreters/interpreter_table_create.rs +++ b/src/query/service/src/interpreters/interpreter_table_create.rs @@ -50,7 +50,6 @@ use databend_common_storages_fuse::FUSE_OPT_KEY_ROW_AVG_DEPTH_THRESHOLD; use databend_common_storages_fuse::FUSE_OPT_KEY_ROW_PER_BLOCK; use databend_common_storages_fuse::FUSE_OPT_KEY_ROW_PER_PAGE; use databend_common_storages_fuse::FUSE_TBL_LAST_SNAPSHOT_HINT; -use databend_common_storages_share::save_share_spec; use databend_common_users::RoleCacheManager; use databend_common_users::UserApiProvider; use databend_storages_common_cache::LoadParams; @@ -192,7 +191,7 @@ impl CreateTableInterpreter { let table_id_seq = reply .table_id_seq .expect("internal error: table_id_seq must have been set. CTAS(replace) of table"); - let db_id = reply.db_id; + let db_id_ident = reply.database_id_ident; // grant the ownership of the table to the current role. let current_role = self.ctx.get_current_role(); @@ -202,7 +201,7 @@ impl CreateTableInterpreter { .grant_ownership( &OwnershipObject::Table { catalog_name: self.plan.catalog.clone(), - db_id, + db_id: db_id_ident.database_id(), table_id, }, ¤t_role.name, @@ -238,17 +237,6 @@ impl CreateTableInterpreter { table_info: Some(table_info), }; - // update share spec if needed - if let Some((spec_vec, share_table_info)) = reply.spec_vec { - save_share_spec( - tenant.tenant_name(), - self.ctx.get_data_operator()?.operator(), - Some(spec_vec), - Some(share_table_info), - ) - .await?; - } - let mut pipeline = InsertInterpreter::try_create(self.ctx.clone(), insert_plan)? .execute2() .await?; @@ -275,7 +263,7 @@ impl CreateTableInterpreter { db_name, table_name, }, - db_id, + db_id_ident: db_id_ident, table_id, table_id_seq, force_replace: true, @@ -351,17 +339,6 @@ impl CreateTableInterpreter { RoleCacheManager::instance().invalidate_cache(&tenant); } - // update share spec if needed - if let Some((spec_vec, share_table_info)) = reply.spec_vec { - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - Some(spec_vec), - Some(share_table_info), - ) - .await?; - } - Ok(PipelineBuildResult::create()) } diff --git a/src/query/service/src/interpreters/interpreter_table_drop.rs b/src/query/service/src/interpreters/interpreter_table_drop.rs index c08dc4bbdd40..fb572a9cd1e8 100644 --- a/src/query/service/src/interpreters/interpreter_table_drop.rs +++ b/src/query/service/src/interpreters/interpreter_table_drop.rs @@ -23,7 +23,6 @@ use databend_common_meta_app::schema::DropTableByIdReq; use databend_common_sql::plans::DropTablePlan; use databend_common_storages_fuse::operations::TruncateMode; use databend_common_storages_fuse::FuseTable; -use databend_common_storages_share::save_share_spec; use databend_common_storages_stream::stream_table::STREAM_ENGINE; use databend_common_storages_view::view_table::VIEW_ENGINE; use databend_common_users::RoleCacheManager; @@ -102,7 +101,7 @@ impl Interpreter for DropTableInterpreter { let tenant = self.ctx.get_tenant(); let db = catalog.get_database(&tenant, &self.plan.database).await?; // actually drop table - let resp = catalog + let _resp = catalog .drop_table_by_id(DropTableByIdReq { if_exists: self.plan.if_exists, tenant: tenant.clone(), @@ -149,17 +148,6 @@ impl Interpreter for DropTableInterpreter { } } - // update share spec if needed - if let Some((spec_vec, share_table_info)) = resp.spec_vec { - save_share_spec( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - Some(spec_vec), - Some(share_table_info), - ) - .await?; - } - Ok(build_res) } } diff --git a/src/query/service/src/interpreters/interpreter_table_drop_column.rs b/src/query/service/src/interpreters/interpreter_table_drop_column.rs index e734dc63fb56..85893a567f1a 100644 --- a/src/query/service/src/interpreters/interpreter_table_drop_column.rs +++ b/src/query/service/src/interpreters/interpreter_table_drop_column.rs @@ -23,7 +23,6 @@ use databend_common_meta_app::schema::UpdateTableMetaReq; use databend_common_meta_types::MatchSeq; use databend_common_sql::plans::DropTableColumnPlan; use databend_common_sql::BloomIndexColumns; -use databend_common_storages_share::save_share_table_info; use databend_common_storages_stream::stream_table::STREAM_ENGINE; use databend_common_storages_view::view_table::VIEW_ENGINE; use databend_storages_common_table_meta::table::OPT_KEY_BLOOM_INDEX_COLUMNS; @@ -129,15 +128,7 @@ impl Interpreter for DropTableColumnInterpreter { update_stream_meta: vec![], }; - let res = catalog.update_table_meta(table_info, req).await?; - if let Some(share_table_info) = res.share_table_info { - save_share_table_info( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - share_table_info, - ) - .await?; - } + let _res = catalog.update_table_meta(table_info, req).await?; Ok(PipelineBuildResult::create()) } diff --git a/src/query/service/src/interpreters/interpreter_table_modify_column.rs b/src/query/service/src/interpreters/interpreter_table_modify_column.rs index 4372419f0ef8..f0f7d5c42657 100644 --- a/src/query/service/src/interpreters/interpreter_table_modify_column.rs +++ b/src/query/service/src/interpreters/interpreter_table_modify_column.rs @@ -43,7 +43,6 @@ use databend_common_sql::plans::Plan; use databend_common_sql::BloomIndexColumns; use databend_common_sql::Planner; use databend_common_storages_fuse::FuseTable; -use databend_common_storages_share::save_share_table_info; use databend_common_storages_stream::stream_table::STREAM_ENGINE; use databend_common_storages_view::view_table::VIEW_ENGINE; use databend_common_users::UserApiProvider; @@ -124,16 +123,8 @@ impl ModifyTableColumnInterpreter { action: SetTableColumnMaskPolicyAction::Set(mask_name, prev_column_mask_name), }; - let res = catalog.set_table_column_mask_policy(req).await?; + let _res = catalog.set_table_column_mask_policy(req).await?; - if let Some(share_table_info) = res.share_table_info { - save_share_table_info( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - share_table_info, - ) - .await?; - } Ok(PipelineBuildResult::create()) } @@ -332,19 +323,10 @@ impl ModifyTableColumnInterpreter { update_stream_meta: vec![], }; - let res = catalog + let _res = catalog .update_table_meta(table.get_table_info(), req) .await?; - if let Some(share_table_info) = res.share_table_info { - save_share_table_info( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - share_table_info, - ) - .await?; - } - return Ok(PipelineBuildResult::create()); } @@ -456,16 +438,7 @@ impl ModifyTableColumnInterpreter { action: SetTableColumnMaskPolicyAction::Unset(prev_column_mask_name), }; - let res = catalog.set_table_column_mask_policy(req).await?; - - if let Some(share_table_info) = res.share_table_info { - save_share_table_info( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - share_table_info, - ) - .await?; - } + let _res = catalog.set_table_column_mask_policy(req).await?; } Ok(PipelineBuildResult::create()) @@ -522,16 +495,7 @@ impl ModifyTableColumnInterpreter { update_stream_meta: vec![], }; - let res = catalog.update_table_meta(table_info, req).await?; - - if let Some(share_table_info) = res.share_table_info { - save_share_table_info( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - share_table_info, - ) - .await?; - } + let _res = catalog.update_table_meta(table_info, req).await?; Ok(PipelineBuildResult::create()) } diff --git a/src/query/service/src/interpreters/interpreter_table_rename_column.rs b/src/query/service/src/interpreters/interpreter_table_rename_column.rs index 6431f499ffb9..734b6d38420a 100644 --- a/src/query/service/src/interpreters/interpreter_table_rename_column.rs +++ b/src/query/service/src/interpreters/interpreter_table_rename_column.rs @@ -23,7 +23,6 @@ use databend_common_meta_app::schema::UpdateTableMetaReq; use databend_common_meta_types::MatchSeq; use databend_common_sql::plans::RenameTableColumnPlan; use databend_common_sql::BloomIndexColumns; -use databend_common_storages_share::save_share_table_info; use databend_common_storages_stream::stream_table::STREAM_ENGINE; use databend_common_storages_view::view_table::VIEW_ENGINE; use databend_storages_common_table_meta::table::OPT_KEY_BLOOM_INDEX_COLUMNS; @@ -133,16 +132,7 @@ impl Interpreter for RenameTableColumnInterpreter { update_stream_meta: vec![], }; - let res = catalog.update_table_meta(table_info, req).await?; - - if let Some(share_table_info) = res.share_table_info { - save_share_table_info( - self.ctx.get_tenant().tenant_name(), - self.ctx.get_data_operator()?.operator(), - share_table_info, - ) - .await?; - } + let _res = catalog.update_table_meta(table_info, req).await?; }; Ok(PipelineBuildResult::create()) diff --git a/src/query/service/src/interpreters/mod.rs b/src/query/service/src/interpreters/mod.rs index 989a2954ea07..5a2815d0c780 100644 --- a/src/query/service/src/interpreters/mod.rs +++ b/src/query/service/src/interpreters/mod.rs @@ -80,19 +80,7 @@ mod interpreter_sequence_create; mod interpreter_sequence_drop; mod interpreter_set_priority; mod interpreter_setting; -mod interpreter_share_alter_tenants; -mod interpreter_share_create; -mod interpreter_share_desc; -mod interpreter_share_drop; -mod interpreter_share_endpoint_create; -mod interpreter_share_endpoint_drop; -mod interpreter_share_endpoint_show; -mod interpreter_share_grant_object; -mod interpreter_share_revoke_object; -mod interpreter_share_show; -mod interpreter_share_show_grant_tenants; mod interpreter_show_grants; -mod interpreter_show_object_grant_privileges; mod interpreter_stream_create; mod interpreter_stream_drop; mod interpreter_table_add_column; @@ -199,18 +187,7 @@ pub use interpreter_sequence_create::CreateSequenceInterpreter; pub use interpreter_sequence_drop::DropSequenceInterpreter; pub use interpreter_set_priority::SetPriorityInterpreter; pub use interpreter_setting::SettingInterpreter; -pub use interpreter_share_alter_tenants::AlterShareTenantsInterpreter; -pub use interpreter_share_create::CreateShareInterpreter; -pub use interpreter_share_drop::DropShareInterpreter; -pub use interpreter_share_endpoint_create::CreateShareEndpointInterpreter; -pub use interpreter_share_endpoint_drop::DropShareEndpointInterpreter; -pub use interpreter_share_endpoint_show::ShowShareEndpointInterpreter; -pub use interpreter_share_grant_object::GrantShareObjectInterpreter; -pub use interpreter_share_revoke_object::RevokeShareObjectInterpreter; -pub use interpreter_share_show::ShowSharesInterpreter; -pub use interpreter_share_show_grant_tenants::ShowGrantTenantsOfShareInterpreter; pub use interpreter_show_grants::ShowGrantsInterpreter; -pub use interpreter_show_object_grant_privileges::ShowObjectGrantPrivilegesInterpreter; pub use interpreter_stream_create::CreateStreamInterpreter; pub use interpreter_stream_drop::DropStreamInterpreter; pub use interpreter_table_add_column::AddTableColumnInterpreter; diff --git a/src/query/service/tests/it/sql/exec/get_table_bind_test.rs b/src/query/service/tests/it/sql/exec/get_table_bind_test.rs index 0038d8f2274f..59379e49fdf0 100644 --- a/src/query/service/tests/it/sql/exec/get_table_bind_test.rs +++ b/src/query/service/tests/it/sql/exec/get_table_bind_test.rs @@ -196,8 +196,8 @@ impl Catalog for FakedCatalog { self.cat.mget_table_names_by_ids(tenant, table_ids).await } - async fn get_db_name_by_id(&self, db_id: MetaId) -> Result { - self.cat.get_db_name_by_id(db_id).await + async fn get_db_name_by_id(&self, tenant: &Tenant, db_id: MetaId) -> Result { + self.cat.get_db_name_by_id(tenant, db_id).await } async fn mget_database_names_by_ids( diff --git a/src/query/service/tests/it/storages/fuse/operations/commit.rs b/src/query/service/tests/it/storages/fuse/operations/commit.rs index dc83779d479e..d69d96c2ea71 100644 --- a/src/query/service/tests/it/storages/fuse/operations/commit.rs +++ b/src/query/service/tests/it/storages/fuse/operations/commit.rs @@ -841,8 +841,8 @@ impl Catalog for FakedCatalog { self.cat.mget_table_names_by_ids(tenant, table_id).await } - async fn get_db_name_by_id(&self, db_id: MetaId) -> Result { - self.cat.get_db_name_by_id(db_id).await + async fn get_db_name_by_id(&self, tenant: &Tenant, db_id: MetaId) -> Result { + self.cat.get_db_name_by_id(tenant, db_id).await } #[async_backtrace::framed] diff --git a/src/query/sharing/Cargo.toml b/src/query/sharing/Cargo.toml index ba66463caeed..dd79f2ccefed 100644 --- a/src/query/sharing/Cargo.toml +++ b/src/query/sharing/Cargo.toml @@ -13,13 +13,9 @@ doctest = false anyhow = { workspace = true } bytes = { workspace = true } databend-common-auth = { path = "../../common/auth" } -databend-common-base = { path = "../../common/base" } databend-common-config = { path = "../config" } databend-common-exception = { path = "../../common/exception" } -databend-common-meta-api = { path = "../../meta/api" } databend-common-meta-app = { path = "../../meta/app" } -databend-common-storage = { path = "../../common/storage" } -databend-common-users = { path = "../users" } async-backtrace = { workspace = true } http = { workspace = true } diff --git a/src/query/sharing/src/lib.rs b/src/query/sharing/src/lib.rs index d7825a54d277..36afaef44c57 100644 --- a/src/query/sharing/src/lib.rs +++ b/src/query/sharing/src/lib.rs @@ -21,6 +21,3 @@ pub use layer::create_share_table_operator; mod signer; pub use signer::SharedSigner; - -mod share_endpoint; -pub use share_endpoint::ShareEndpointManager; diff --git a/src/query/sharing/src/share_endpoint.rs b/src/query/sharing/src/share_endpoint.rs deleted file mode 100644 index faa149fadfa3..000000000000 --- a/src/query/sharing/src/share_endpoint.rs +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::sync::Arc; - -use bytes::Buf; -use bytes::Bytes; -use databend_common_auth::RefreshableToken; -use databend_common_base::base::GlobalInstance; -use databend_common_config::GlobalConfig; -use databend_common_exception::ErrorCode; -use databend_common_exception::Result; -use databend_common_meta_api::ShareApi; -use databend_common_meta_app::schema::DatabaseInfo; -use databend_common_meta_app::share::share_name_ident::ShareNameIdent; -use databend_common_meta_app::share::GetShareEndpointReq; -use databend_common_meta_app::share::ShareSpec; -use databend_common_meta_app::share::TableInfoMap; -use databend_common_meta_app::tenant::Tenant; -use databend_common_meta_app::KeyWithTenant; -use databend_common_storage::ShareTableConfig; -use databend_common_users::UserApiProvider; -use http::header::AUTHORIZATION; -use http::header::CONTENT_LENGTH; -use http::Method; -use http::Request; -use log::debug; -use log::error; -use opendal::raw::HttpClient; -use opendal::Buffer; - -use crate::signer::TENANT_HEADER; - -#[derive(Debug)] -struct EndpointConfig { - pub url: String, - pub token: RefreshableToken, - pub tenant: String, -} - -pub struct ShareEndpointManager { - client: HttpClient, -} - -impl ShareEndpointManager { - pub fn init() -> Result<()> { - GlobalInstance::set(Arc::new(ShareEndpointManager { - client: HttpClient::new()?, - })); - Ok(()) - } - - pub fn instance() -> Arc { - GlobalInstance::get() - } - - #[async_backtrace::framed] - async fn get_share_endpoint_config( - &self, - from_tenant: &Tenant, - to_tenant: Option<&Tenant>, - ) -> Result> { - debug!( - "get_share_endpoint_config from_tenant: {:?}, to_tenant: {:?}", - from_tenant, to_tenant - ); - - if let Some(to_tenant) = to_tenant { - if to_tenant.tenant_name() == from_tenant.tenant_name() { - match ShareTableConfig::share_endpoint_address() { - Some(url) => { - return Ok(vec![EndpointConfig { - url: format!("http://{}/", url), - token: ShareTableConfig::share_endpoint_token(), - tenant: from_tenant.tenant_name().to_string(), - }]); - } - None => return Ok(vec![]), - } - } - } - - let req = GetShareEndpointReq { - tenant: from_tenant.clone(), - endpoint: None, - to_tenant: to_tenant.cloned(), - }; - - debug!("get_share_endpoint_config req: {:?}", req); - - let meta_api = UserApiProvider::instance().get_meta_store_client(); - let resp = meta_api.get_share_endpoint(req).await?; - - debug!("get_share_endpoint_config resp: {:?}", resp); - - let mut share_endpoint_config_vec = Vec::with_capacity(resp.share_endpoint_meta_vec.len()); - for (_, endpoint_meta) in resp.share_endpoint_meta_vec.iter() { - share_endpoint_config_vec.push(EndpointConfig { - url: endpoint_meta.url.clone(), - token: RefreshableToken::Direct(from_tenant.tenant_name().to_string()), - tenant: endpoint_meta.tenant.clone(), - }); - } - Ok(share_endpoint_config_vec) - } - - #[async_backtrace::framed] - pub async fn get_table_info_map( - &self, - from_tenant: &Tenant, - db_info: &DatabaseInfo, - tables: Vec, - ) -> Result { - let share_name_ident_raw = db_info.meta.from_share.as_ref().unwrap(); - - let share_name_ident = share_name_ident_raw.clone().to_tident(()); - - let to_tenant = share_name_ident.tenant(); - let share_name = share_name_ident.share_name(); - - let endpoint_meta_config_vec = self - .get_share_endpoint_config(from_tenant, Some(to_tenant)) - .await?; - let endpoint_config = match endpoint_meta_config_vec.first() { - Some(endpoint_meta_config) => endpoint_meta_config, - None => { - return Err(ErrorCode::UnknownShareEndpoint(format!( - "Unknown share endpoint on accessing shared database from tenant '{}' to target tenant '{}'", - from_tenant.tenant_name(), - to_tenant.tenant_name() - ))); - } - }; - - let url = format!( - "{}tenant/{}/{}/meta", - endpoint_config.url, - to_tenant.tenant_name(), - share_name - ); - let bs = Bytes::from(serde_json::to_vec(&tables)?); - let auth = endpoint_config.token.to_header().await?; - let requester = GlobalConfig::instance() - .as_ref() - .query - .tenant_id - .tenant_name() - .to_string(); - let req = Request::builder() - .method(Method::POST) - .uri(&url) - .header(AUTHORIZATION, auth) - .header(CONTENT_LENGTH, bs.len()) - .header(TENANT_HEADER, requester) - .body(Buffer::from(bs))?; - let resp = self.client.send(req).await; - match resp { - Ok(resp) => { - if !resp.status().is_success() { - return Err(ErrorCode::ShareStorageError(format!( - "share {:?} storage error: HTTP status {:?}", - share_name, - match resp.status().canonical_reason() { - Some(reason) => reason.to_string(), - None => resp.status().to_string(), - } - ))); - } - let bs = resp.into_body(); - match serde_json::from_reader(bs.reader()) { - Ok(table_info_map) => Ok(table_info_map), - Err(e) => Err(ErrorCode::ShareStorageError(format!( - "share {:?} storage error: deser json file error: {:?}", - share_name, e - ))), - } - } - Err(err) => Err(err.into()), - } - } - - #[async_backtrace::framed] - pub async fn get_inbound_shares( - &self, - from_tenant: &Tenant, - to_tenant: Option<&Tenant>, - share_name: Option, - ) -> Result> { - debug!( - "get_inbound_shares from_tenant: {:?}, to_tenant: {:?}, share_name: {:?}", - from_tenant, to_tenant, share_name - ); - - let mut endpoint_meta_config_vec = vec![]; - // If `to_tenant` is None, query from same tenant for inbound shares - if to_tenant.is_none() { - debug!("get_inbound_shares to_tenant is None"); - if let Ok(config_vec) = self - .get_share_endpoint_config(from_tenant, Some(from_tenant)) - .await - { - endpoint_meta_config_vec.extend(config_vec); - } - } - - if let Ok(config_vec) = self.get_share_endpoint_config(from_tenant, to_tenant).await { - endpoint_meta_config_vec.extend(config_vec); - } - - debug!( - "get_inbound_shares endpoint_meta_config_vec: {:?}", - endpoint_meta_config_vec - ); - - let mut share_spec_vec = vec![]; - let share_names: Vec = vec![]; - for endpoint_config in endpoint_meta_config_vec { - let url = format!( - "{}tenant/{}/share_spec", - endpoint_config.url, - from_tenant.tenant_name() - ); - - debug!("get_inbound_shares url: {:?}", url); - - let bs = Bytes::from(serde_json::to_vec(&share_names)?); - let auth = endpoint_config.token.to_header().await?; - let requester = GlobalConfig::instance() - .as_ref() - .query - .tenant_id - .tenant_name() - .to_string(); - let req = Request::builder() - .method(Method::POST) - .uri(&url) - .header(AUTHORIZATION, auth) - .header(CONTENT_LENGTH, bs.len()) - .header(TENANT_HEADER, requester) - .body(Buffer::from(bs))?; - let resp = self.client.send(req).await; - - match resp { - Ok(resp) => { - let bs = resp.into_body(); - let ret: Vec = serde_json::from_reader(bs.reader())?; - debug!("get_inbound_shares OK resp ret: {:?}", ret); - - for share_spec in ret { - if let Some(ref share_name) = share_name { - if share_spec.name == share_name.share_name() - && endpoint_config.tenant == share_name.tenant_name() - { - share_spec_vec.push((endpoint_config.tenant.clone(), share_spec)); - return Ok(share_spec_vec); - } - } - share_spec_vec.push((endpoint_config.tenant.clone(), share_spec)); - } - } - Err(err) => { - error!("get_inbound_shares error: {:?}", err); - continue; - } - } - } - - Ok(share_spec_vec) - } -} diff --git a/src/query/sharing_endpoint/Cargo.toml b/src/query/sharing_endpoint/Cargo.toml index 43896c6ca8f5..1a80792944da 100644 --- a/src/query/sharing_endpoint/Cargo.toml +++ b/src/query/sharing_endpoint/Cargo.toml @@ -17,18 +17,13 @@ databend-common-config = { path = "../../query/config" } databend-common-exception = { path = "../../common/exception" } databend-common-meta-app = { path = "../../meta/app" } databend-common-storage = { path = "../../common/storage" } -databend-common-storages-share = { path = "../storages/share" } uuid = { workspace = true } -time = { version = "0.3", features = ["serde"] } - -base64 = { workspace = true } -bytes = { workspace = true } +base64 = "0.21.0" clap = { workspace = true } enumflags2 = { workspace = true } http = { workspace = true } opendal = { workspace = true } poem = { workspace = true } serde = { workspace = true } -serde_json = { workspace = true } serfig = { workspace = true } diff --git a/src/query/sharing_endpoint/src/accessor.rs b/src/query/sharing_endpoint/src/accessor.rs deleted file mode 100644 index 8f2a5569e5d8..000000000000 --- a/src/query/sharing_endpoint/src/accessor.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use databend_common_base::base::GlobalInstance; -use databend_common_exception::Result; -use databend_common_meta_app::storage::StorageParams; -use databend_common_storage::init_operator; -use opendal::Operator; - -use crate::configs::Config; - -mod share_spec_accessor; -mod share_table_accessor; -mod share_table_meta_accessor; - -#[derive(Clone)] -pub struct SharingAccessor { - op: Operator, - config: Config, -} - -// file would have two kind of path: -// 1. with root. e.g. /root1/root2/root3/db1/tb1/file1 -// 2. without root e.g. db1/tb1/file1 -// after it would be converted to file1 -// and then it would use the location in table spec to form the final path -// {location}/file1 -pub fn truncate_root(root: String, loc: String) -> String { - let root = root.trim_matches('/'); - let loc = loc.trim_matches('/'); - return if loc.starts_with(root) { - let o1 = loc.strip_prefix(root).unwrap(); - - let updated = o1.trim_matches('/'); - let arr = updated.split('/').collect::>(); - if arr.len() > 2 { - return arr[2..].join("/"); - } - updated.to_string() - } else { - let arr = loc.split('/').collect::>(); - if arr.len() > 2 { - return arr[2..].join("/"); - } - loc.to_string() - }; -} - -impl SharingAccessor { - #[async_backtrace::framed] - pub async fn init(cfg: &Config) -> Result<()> { - GlobalInstance::set(Self::try_create(cfg).await?); - - Ok(()) - } - - pub fn instance() -> SharingAccessor { - GlobalInstance::get() - } - - #[async_backtrace::framed] - pub async fn try_create(cfg: &Config) -> Result { - let operator = init_operator(&cfg.storage.params)?; - - Ok(SharingAccessor { - op: operator, - config: cfg.clone(), - }) - } - - fn get_root(&self) -> String { - match self.config.storage.params { - StorageParams::S3(ref s3) => s3.root.trim_matches('/').to_string(), - StorageParams::Oss(ref oss) => oss.root.trim_matches('/').to_string(), - _ => "".to_string(), - } - } -} diff --git a/src/query/sharing_endpoint/src/accessor/share_spec_accessor.rs b/src/query/sharing_endpoint/src/accessor/share_spec_accessor.rs deleted file mode 100644 index ce5feb030fa8..000000000000 --- a/src/query/sharing_endpoint/src/accessor/share_spec_accessor.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use bytes::Buf; -use databend_common_exception::Result; -use databend_common_storages_share::get_share_spec_location; - -use crate::accessor::SharingAccessor; -use crate::models; -use crate::models::ShareSpec; - -// Methods for access share spec by tenant. -impl SharingAccessor { - #[async_backtrace::framed] - pub async fn get_share_spec(tenant: &String) -> Result> { - let sharing_accessor = Self::instance(); - let path = get_share_spec_location(&sharing_accessor.config.tenant); - let data = sharing_accessor.op.read(&path).await?; - let share_specs: models::SharingConfig = serde_json::from_reader(data.reader())?; - let mut share_spec_vec = vec![]; - - for (_, share_spec) in share_specs.share_specs { - if share_spec.tenants.contains(tenant) { - share_spec_vec.push(share_spec); - } - } - Ok(share_spec_vec) - } -} diff --git a/src/query/sharing_endpoint/src/accessor/share_table_accessor.rs b/src/query/sharing_endpoint/src/accessor/share_table_accessor.rs deleted file mode 100644 index 43f8c5b7b667..000000000000 --- a/src/query/sharing_endpoint/src/accessor/share_table_accessor.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::time::Duration; - -use bytes::Buf; -use databend_common_exception::Result; -use databend_common_storages_share::get_share_spec_location; - -use crate::accessor::truncate_root; -use crate::accessor::SharingAccessor; -use crate::models; -use crate::models::PresignFileResponse; -use crate::models::SharedTableResponse; - -// Methods for access share table spec. -impl SharingAccessor { - // Note that too short expire duration may cause return `Request has expired` error - const PRESIGNED_URL_EXPIRE_SECONDS: u64 = 3600; - - // read share table spec from S3 and check whether requester has permission on the table - #[async_backtrace::framed] - async fn get_shared_table_spec( - &self, - input: &models::LambdaInput, - ) -> Result> { - let sharing_accessor = Self::instance(); - let path = get_share_spec_location(&sharing_accessor.config.tenant); - let data = sharing_accessor.op.read(&path).await?; - let share_specs: models::SharingConfig = serde_json::from_reader(data.reader())?; - share_specs.get_tables(input) - } - - // presign_file would be separated into two steps: - // 1. fetch the table location - // 2. form the final path and presign it - #[async_backtrace::framed] - async fn share_table_spec_presign_file( - &self, - table: &SharedTableResponse, - input: &models::RequestFile, - ) -> Result { - let loc_prefix = table.location.trim_matches('/'); - let loc_prefix = loc_prefix.strip_prefix(self.get_root().as_str()).unwrap(); - - let file_path = truncate_root(self.get_root(), input.file_name.clone()); - let obj_path = format!("{}/{}", loc_prefix, file_path); - let op = self.op.clone(); - - if input.method == "HEAD" { - let s = op - .presign_stat( - obj_path.as_str(), - Duration::from_secs(Self::PRESIGNED_URL_EXPIRE_SECONDS), - ) - .await?; - return Ok(PresignFileResponse::new(&s, input.file_name.clone())); - } - - let s = op - .presign_read( - obj_path.as_str(), - Duration::from_secs(Self::PRESIGNED_URL_EXPIRE_SECONDS), - ) - .await?; - Ok(PresignFileResponse::new(&s, input.file_name.clone())) - } - - #[async_backtrace::framed] - pub async fn get_share_table_spec_presigned_files( - input: &models::LambdaInput, - ) -> Result> { - let accessor = Self::instance(); - let table = accessor.get_shared_table_spec(input).await?; - match table { - Some(t) => { - let mut presigned_files = vec![]; - for f in input.request_files.iter() { - let presigned_file = accessor.share_table_spec_presign_file(&t, f).await?; - presigned_files.push(presigned_file); - } - Ok(presigned_files) - } - None => Ok(vec![]), - } - } -} diff --git a/src/query/sharing_endpoint/src/accessor/share_table_meta_accessor.rs b/src/query/sharing_endpoint/src/accessor/share_table_meta_accessor.rs deleted file mode 100644 index af4a2d70cd1a..000000000000 --- a/src/query/sharing_endpoint/src/accessor/share_table_meta_accessor.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::collections::BTreeMap; - -use bytes::Buf; -use databend_common_exception::Result; -use databend_common_meta_app::share::TableInfoMap; -use databend_common_storages_share::share_table_info_location; - -use crate::accessor::SharingAccessor; -use crate::models::TableMetaLambdaInput; - -// Methods for access share table meta. -impl SharingAccessor { - #[async_backtrace::framed] - pub async fn get_share_table_meta(input: &TableMetaLambdaInput) -> Result { - let sharing_accessor = Self::instance(); - let share_table_meta_loc = - share_table_info_location(&sharing_accessor.config.tenant, &input.share_name); - let data = sharing_accessor.op.read(&share_table_meta_loc).await?; - let share_table_map: TableInfoMap = serde_json::from_reader(data.reader())?; - - if input.request_tables.is_empty() { - Ok(share_table_map) - } else { - Ok(BTreeMap::from_iter(share_table_map.into_iter().filter( - |(table_name, _table_info)| input.request_tables.contains(table_name), - ))) - } - } -} diff --git a/src/query/sharing_endpoint/src/handlers.rs b/src/query/sharing_endpoint/src/handlers.rs index c31789f54d65..0b67d7f9d9e4 100644 --- a/src/query/sharing_endpoint/src/handlers.rs +++ b/src/query/sharing_endpoint/src/handlers.rs @@ -15,12 +15,10 @@ use databend_common_meta_app::share::TableInfoMap; use models::Credentials; use models::RequestFile; -use poem::error::BadRequest; use poem::error::Result as PoemResult; use poem::web::Json; use poem::web::Path; -use crate::accessor::SharingAccessor; use crate::models; use crate::models::PresignFileResponse; use crate::models::ShareSpec; @@ -28,55 +26,29 @@ use crate::models::ShareSpec; #[poem::handler] #[async_backtrace::framed] pub async fn share_table_presign_files( - credentials: &Credentials, - Path((_tenant_id, share_name, table_name)): Path<(String, String, String)>, - Json(request_files): Json>, + _credentials: &Credentials, + Path((_tenant_id, _share_name, _table_name)): Path<(String, String, String)>, + Json(_request_files): Json>, ) -> PoemResult>> { - let requester = credentials.token.clone(); - let input = models::LambdaInput::new( - credentials.token.clone(), - share_name, - requester, - table_name, - request_files, - None, - ); - match SharingAccessor::get_share_table_spec_presigned_files(&input).await { - Ok(output) => Ok(Json(output)), - Err(e) => Err(BadRequest(e)), - } + unimplemented!() } #[poem::handler] #[async_backtrace::framed] pub async fn share_table_meta( - credentials: &Credentials, - Path((_tenant_id, share_name)): Path<(String, String)>, - Json(request_tables): Json>, + _credentials: &Credentials, + Path((_tenant_id, _share_name)): Path<(String, String)>, + Json(_request_tables): Json>, ) -> PoemResult> { - let requester = credentials.token.clone(); - let input = models::TableMetaLambdaInput::new( - credentials.token.clone(), - share_name, - requester, - request_tables, - None, - ); - match SharingAccessor::get_share_table_meta(&input).await { - Ok(output) => Ok(Json(output)), - Err(e) => Err(BadRequest(e)), - } + unimplemented!() } #[poem::handler] #[async_backtrace::framed] pub async fn share_spec( _credentials: &Credentials, - Path(tenant_id): Path, + Path(_tenant_id): Path, Json(_request_tables): Json>, ) -> PoemResult>> { - match SharingAccessor::get_share_spec(&tenant_id).await { - Ok(output) => Ok(Json(output)), - Err(e) => Err(BadRequest(e)), - } + unimplemented!() } diff --git a/src/query/sharing_endpoint/src/lib.rs b/src/query/sharing_endpoint/src/lib.rs index 089c2539585c..d1c108bacb7b 100644 --- a/src/query/sharing_endpoint/src/lib.rs +++ b/src/query/sharing_endpoint/src/lib.rs @@ -14,7 +14,6 @@ #![allow(clippy::uninlined_format_args)] -pub mod accessor; pub mod configs; pub mod handlers; pub mod middlewares; diff --git a/src/query/sharing_endpoint/src/services.rs b/src/query/sharing_endpoint/src/services.rs index 8c115f1504e5..05c1f04331e7 100644 --- a/src/query/sharing_endpoint/src/services.rs +++ b/src/query/sharing_endpoint/src/services.rs @@ -16,7 +16,6 @@ use databend_common_base::base::GlobalInstance; use databend_common_base::runtime::GlobalIORuntime; use databend_common_exception::Result; -use crate::accessor::SharingAccessor; use crate::configs::Config; // hold singleton services. @@ -29,6 +28,7 @@ impl SharingServices { GlobalInstance::init_production(); GlobalIORuntime::init(config.storage.num_cpus as usize)?; - SharingAccessor::init(&config).await + + Ok(()) } } diff --git a/src/query/sharing_endpoint/tests/it/accessor.rs b/src/query/sharing_endpoint/tests/it/accessor.rs deleted file mode 100644 index 30d7bb07515a..000000000000 --- a/src/query/sharing_endpoint/tests/it/accessor.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2022 Datafuse Labs. -// -// 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. - -use databend_common_base::base::tokio; -use databend_common_exception::Result; -use databend_sharing_endpoint::accessor::truncate_root; - -#[tokio::test(flavor = "multi_thread")] -async fn test_truncate_root() -> Result<()> { - let t = truncate_root("tenant1/".to_string(), "tenant1/db1/tb1/file1".to_string()); - assert_eq!(t, "file1".to_string()); - Ok(()) -} diff --git a/src/query/sharing_endpoint/tests/it/main.rs b/src/query/sharing_endpoint/tests/it/main.rs index 509e050a909c..660bff637faf 100644 --- a/src/query/sharing_endpoint/tests/it/main.rs +++ b/src/query/sharing_endpoint/tests/it/main.rs @@ -13,5 +13,4 @@ // limitations under the License. #![feature(thread_local)] -mod accessor; mod models; diff --git a/src/query/sql/src/planner/binder/binder.rs b/src/query/sql/src/planner/binder/binder.rs index cf3d1d0c6c8e..8c98803efaa0 100644 --- a/src/query/sql/src/planner/binder/binder.rs +++ b/src/query/sql/src/planner/binder/binder.rs @@ -521,43 +521,6 @@ impl<'a> Binder { .await? } - // share statements - Statement::CreateShareEndpoint(stmt) => { - self.bind_create_share_endpoint(stmt).await? - } - Statement::ShowShareEndpoint(stmt) => { - self.bind_show_share_endpoint(stmt).await? - } - Statement::DropShareEndpoint(stmt) => { - self.bind_drop_share_endpoint(stmt).await? - } - Statement::CreateShare(stmt) => { - self.bind_create_share(stmt).await? - } - Statement::DropShare(stmt) => { - self.bind_drop_share(stmt).await? - } - Statement::GrantShareObject(stmt) => { - self.bind_grant_share_object(stmt).await? - } - Statement::RevokeShareObject(stmt) => { - self.bind_revoke_share_object(stmt).await? - } - Statement::AlterShareTenants(stmt) => { - self.bind_alter_share_accounts(stmt).await? - } - Statement::DescShare(stmt) => { - self.bind_desc_share(stmt).await? - } - Statement::ShowShares(stmt) => { - self.bind_show_shares(stmt).await? - } - Statement::ShowObjectGrantPrivileges(stmt) => { - self.bind_show_object_grant_privileges(stmt).await? - } - Statement::ShowGrantsOfShare(stmt) => { - self.bind_show_grants_of_share(stmt).await? - } Statement::CreateDatamaskPolicy(stmt) => { self.bind_create_data_mask_policy(stmt).await? } diff --git a/src/query/sql/src/planner/binder/ddl/mod.rs b/src/query/sql/src/planner/binder/ddl/mod.rs index a344e82f6b66..27e2255de955 100644 --- a/src/query/sql/src/planner/binder/ddl/mod.rs +++ b/src/query/sql/src/planner/binder/ddl/mod.rs @@ -26,7 +26,6 @@ mod password_policy; mod procedure; mod role; mod sequence; -mod share; mod stage; mod stream; mod table; diff --git a/src/query/sql/src/planner/binder/ddl/share.rs b/src/query/sql/src/planner/binder/ddl/share.rs deleted file mode 100644 index 7741b556be5b..000000000000 --- a/src/query/sql/src/planner/binder/ddl/share.rs +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use databend_common_ast::ast::*; -use databend_common_exception::Result; -use databend_common_meta_app::share::ShareEndpointIdent; -use databend_common_meta_app::tenant::UninitTenant; -use itertools::Itertools; -use minitrace::func_name; - -use crate::binder::Binder; -use crate::normalize_identifier; -use crate::plans::AlterShareTenantsPlan; -use crate::plans::CreateShareEndpointPlan; -use crate::plans::CreateSharePlan; -use crate::plans::DescSharePlan; -use crate::plans::DropShareEndpointPlan; -use crate::plans::DropSharePlan; -use crate::plans::GrantShareObjectPlan; -use crate::plans::Plan; -use crate::plans::RevokeShareObjectPlan; -use crate::plans::ShowGrantTenantsOfSharePlan; -use crate::plans::ShowObjectGrantPrivilegesPlan; -use crate::plans::ShowShareEndpointPlan; -use crate::plans::ShowSharesPlan; - -impl Binder { - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_create_share_endpoint( - &mut self, - stmt: &CreateShareEndpointStmt, - ) -> Result { - let CreateShareEndpointStmt { - create_option, - endpoint, - url, - tenant, - args, - comment, - } = stmt; - - let endpoint = normalize_identifier(endpoint, &self.name_resolution_ctx).name; - - let tenant = { - let tenant_name = tenant.to_string(); - let uninit_tenant = UninitTenant::new_or_err(tenant_name, func_name!())?; - uninit_tenant.initialize(()) - }; - - let plan = CreateShareEndpointPlan { - create_option: *create_option, - endpoint: ShareEndpointIdent::new(self.ctx.get_tenant(), endpoint), - tenant, - url: format!("{}://{}{}", url.protocol, url.name, url.path), - args: args.clone(), - comment: comment.as_ref().cloned(), - }; - Ok(Plan::CreateShareEndpoint(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_show_share_endpoint( - &mut self, - _stmt: &ShowShareEndpointStmt, - ) -> Result { - let plan = ShowShareEndpointPlan { - tenant: self.ctx.get_tenant(), - }; - Ok(Plan::ShowShareEndpoint(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_drop_share_endpoint( - &mut self, - stmt: &DropShareEndpointStmt, - ) -> Result { - let DropShareEndpointStmt { - if_exists, - endpoint, - } = stmt; - let plan = DropShareEndpointPlan { - if_exists: *if_exists, - tenant: self.ctx.get_tenant(), - endpoint: endpoint.to_string(), - }; - Ok(Plan::DropShareEndpoint(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_create_share( - &mut self, - stmt: &CreateShareStmt, - ) -> Result { - let CreateShareStmt { - if_not_exists, - share, - comment, - } = stmt; - - let share = normalize_identifier(share, &self.name_resolution_ctx).name; - - let plan = CreateSharePlan { - if_not_exists: *if_not_exists, - tenant: self.ctx.get_tenant(), - share, - comment: comment.as_ref().cloned(), - }; - Ok(Plan::CreateShare(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_drop_share( - &mut self, - stmt: &DropShareStmt, - ) -> Result { - let DropShareStmt { if_exists, share } = stmt; - - let share = normalize_identifier(share, &self.name_resolution_ctx).name; - - let plan = DropSharePlan { - if_exists: *if_exists, - tenant: self.ctx.get_tenant(), - share, - }; - Ok(Plan::DropShare(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_grant_share_object( - &mut self, - stmt: &GrantShareObjectStmt, - ) -> Result { - let GrantShareObjectStmt { - share, - object, - privilege, - } = stmt; - - let share = normalize_identifier(share, &self.name_resolution_ctx).name; - - let plan = GrantShareObjectPlan { - share, - object: object.clone(), - privilege: *privilege, - }; - Ok(Plan::GrantShareObject(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_revoke_share_object( - &mut self, - stmt: &RevokeShareObjectStmt, - ) -> Result { - let RevokeShareObjectStmt { - share, - object, - privilege, - } = stmt; - - let share = normalize_identifier(share, &self.name_resolution_ctx).name; - - let plan = RevokeShareObjectPlan { - share, - object: object.clone(), - privilege: *privilege, - }; - Ok(Plan::RevokeShareObject(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_alter_share_accounts( - &mut self, - stmt: &AlterShareTenantsStmt, - ) -> Result { - let AlterShareTenantsStmt { - share, - if_exists, - tenants, - is_add, - } = stmt; - - let share = normalize_identifier(share, &self.name_resolution_ctx).name; - - let plan = AlterShareTenantsPlan { - share, - if_exists: *if_exists, - is_add: *is_add, - accounts: tenants.iter().map(|v| v.to_string()).collect_vec(), - }; - Ok(Plan::AlterShareTenants(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_desc_share( - &mut self, - stmt: &DescShareStmt, - ) -> Result { - let DescShareStmt { share } = stmt; - - let share = normalize_identifier(share, &self.name_resolution_ctx).name; - - let plan = DescSharePlan { share }; - Ok(Plan::DescShare(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_show_shares( - &mut self, - _stmt: &ShowSharesStmt, - ) -> Result { - Ok(Plan::ShowShares(Box::new(ShowSharesPlan {}))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_show_object_grant_privileges( - &mut self, - stmt: &ShowObjectGrantPrivilegesStmt, - ) -> Result { - let ShowObjectGrantPrivilegesStmt { object } = stmt; - - let plan = ShowObjectGrantPrivilegesPlan { - object: object.clone(), - }; - Ok(Plan::ShowObjectGrantPrivileges(Box::new(plan))) - } - - #[async_backtrace::framed] - pub(in crate::planner::binder) async fn bind_show_grants_of_share( - &mut self, - stmt: &ShowGrantsOfShareStmt, - ) -> Result { - let ShowGrantsOfShareStmt { share_name } = stmt; - - let plan = ShowGrantTenantsOfSharePlan { - share_name: share_name.clone(), - }; - Ok(Plan::ShowGrantTenantsOfShare(Box::new(plan))) - } -} diff --git a/src/query/sql/src/planner/format/display_plan.rs b/src/query/sql/src/planner/format/display_plan.rs index cc2872b742f5..b1a71017bd70 100644 --- a/src/query/sql/src/planner/format/display_plan.rs +++ b/src/query/sql/src/planner/format/display_plan.rs @@ -163,19 +163,7 @@ impl Plan { Plan::UseDatabase(_) => Ok("UseDatabase".to_string()), Plan::Kill(_) => Ok("Kill".to_string()), - Plan::CreateShareEndpoint(_) => Ok("CreateShareEndpoint".to_string()), - Plan::ShowShareEndpoint(_) => Ok("ShowShareEndpoint".to_string()), - Plan::DropShareEndpoint(_) => Ok("DropShareEndpoint".to_string()), - Plan::CreateShare(_) => Ok("CreateShare".to_string()), - Plan::DropShare(_) => Ok("DropShare".to_string()), - Plan::GrantShareObject(_) => Ok("GrantShareObject".to_string()), - Plan::RevokeShareObject(_) => Ok("RevokeShareObject".to_string()), - Plan::AlterShareTenants(_) => Ok("AlterShareTenants".to_string()), - Plan::DescShare(_) => Ok("DescShare".to_string()), - Plan::ShowShares(_) => Ok("ShowShares".to_string()), Plan::ShowRoles(_) => Ok("ShowRoles".to_string()), - Plan::ShowObjectGrantPrivileges(_) => Ok("ShowObjectGrantPrivileges".to_string()), - Plan::ShowGrantTenantsOfShare(_) => Ok("ShowGrantTenantsOfShare".to_string()), Plan::RevertTable(_) => Ok("RevertTable".to_string()), // data mask diff --git a/src/query/sql/src/planner/plans/plan.rs b/src/query/sql/src/planner/plans/plan.rs index bed9d4225e02..1d0dc78c4e54 100644 --- a/src/query/sql/src/planner/plans/plan.rs +++ b/src/query/sql/src/planner/plans/plan.rs @@ -31,7 +31,6 @@ use crate::plans::AddTableColumnPlan; use crate::plans::AlterNetworkPolicyPlan; use crate::plans::AlterNotificationPlan; use crate::plans::AlterPasswordPolicyPlan; -use crate::plans::AlterShareTenantsPlan; use crate::plans::AlterTableClusterKeyPlan; use crate::plans::AlterTaskPlan; use crate::plans::AlterUDFPlan; @@ -53,8 +52,6 @@ use crate::plans::CreateNotificationPlan; use crate::plans::CreatePasswordPolicyPlan; use crate::plans::CreateRolePlan; use crate::plans::CreateSequencePlan; -use crate::plans::CreateShareEndpointPlan; -use crate::plans::CreateSharePlan; use crate::plans::CreateStagePlan; use crate::plans::CreateStreamPlan; use crate::plans::CreateTableIndexPlan; @@ -70,7 +67,6 @@ use crate::plans::DescDatamaskPolicyPlan; use crate::plans::DescNetworkPolicyPlan; use crate::plans::DescNotificationPlan; use crate::plans::DescPasswordPolicyPlan; -use crate::plans::DescSharePlan; use crate::plans::DescribeTablePlan; use crate::plans::DescribeTaskPlan; use crate::plans::DescribeViewPlan; @@ -85,8 +81,6 @@ use crate::plans::DropNotificationPlan; use crate::plans::DropPasswordPolicyPlan; use crate::plans::DropRolePlan; use crate::plans::DropSequencePlan; -use crate::plans::DropShareEndpointPlan; -use crate::plans::DropSharePlan; use crate::plans::DropStagePlan; use crate::plans::DropStreamPlan; use crate::plans::DropTableClusterKeyPlan; @@ -103,7 +97,6 @@ use crate::plans::ExecuteTaskPlan; use crate::plans::ExistsTablePlan; use crate::plans::GrantPrivilegePlan; use crate::plans::GrantRolePlan; -use crate::plans::GrantShareObjectPlan; use crate::plans::Insert; use crate::plans::InsertMultiTable; use crate::plans::KillPlan; @@ -124,7 +117,6 @@ use crate::plans::Replace; use crate::plans::RevertTablePlan; use crate::plans::RevokePrivilegePlan; use crate::plans::RevokeRolePlan; -use crate::plans::RevokeShareObjectPlan; use crate::plans::SetOptionsPlan; use crate::plans::SetPriorityPlan; use crate::plans::SetRolePlan; @@ -135,13 +127,9 @@ use crate::plans::ShowCreateCatalogPlan; use crate::plans::ShowCreateDatabasePlan; use crate::plans::ShowCreateTablePlan; use crate::plans::ShowFileFormatsPlan; -use crate::plans::ShowGrantTenantsOfSharePlan; use crate::plans::ShowGrantsPlan; use crate::plans::ShowNetworkPoliciesPlan; -use crate::plans::ShowObjectGrantPrivilegesPlan; use crate::plans::ShowRolesPlan; -use crate::plans::ShowShareEndpointPlan; -use crate::plans::ShowSharesPlan; use crate::plans::ShowTasksPlan; use crate::plans::TruncateTablePlan; use crate::plans::UnSettingPlan; @@ -306,20 +294,6 @@ pub enum Plan { Kill(Box), SetPriority(Box), - // Share - CreateShareEndpoint(Box), - ShowShareEndpoint(Box), - DropShareEndpoint(Box), - CreateShare(Box), - DropShare(Box), - GrantShareObject(Box), - RevokeShareObject(Box), - AlterShareTenants(Box), - DescShare(Box), - ShowShares(Box), - ShowObjectGrantPrivileges(Box), - ShowGrantTenantsOfShare(Box), - // Data mask CreateDatamaskPolicy(Box), DropDatamaskPolicy(Box), @@ -458,10 +432,6 @@ impl Plan { Plan::ShowFileFormats(plan) => plan.schema(), Plan::Replace(plan) => plan.schema(), Plan::Presign(plan) => plan.schema(), - Plan::ShowShareEndpoint(plan) => plan.schema(), - Plan::DescShare(plan) => plan.schema(), - Plan::ShowShares(plan) => plan.schema(), - Plan::ShowGrantTenantsOfShare(plan) => plan.schema(), Plan::CreateDatamaskPolicy(plan) => plan.schema(), Plan::DropDatamaskPolicy(plan) => plan.schema(), Plan::DescDatamaskPolicy(plan) => plan.schema(), diff --git a/src/query/storages/hive/hive/src/hive_catalog.rs b/src/query/storages/hive/hive/src/hive_catalog.rs index 5614fceb83d0..537def840556 100644 --- a/src/query/storages/hive/hive/src/hive_catalog.rs +++ b/src/query/storages/hive/hive/src/hive_catalog.rs @@ -366,7 +366,7 @@ impl Catalog for HiveCatalog { )) } - async fn get_db_name_by_id(&self, _db_id: MetaId) -> Result { + async fn get_db_name_by_id(&self, _tenant: &Tenant, _db_id: MetaId) -> Result { Err(ErrorCode::Unimplemented( "Cannot get db name by id in HIVE catalog", )) diff --git a/src/query/storages/iceberg/src/catalog.rs b/src/query/storages/iceberg/src/catalog.rs index 988a873c4005..08824f819de9 100644 --- a/src/query/storages/iceberg/src/catalog.rs +++ b/src/query/storages/iceberg/src/catalog.rs @@ -276,7 +276,7 @@ impl Catalog for IcebergCatalog { } #[async_backtrace::framed] - async fn get_db_name_by_id(&self, _table_id: MetaId) -> Result { + async fn get_db_name_by_id(&self, _tenant: &Tenant, _table_id: MetaId) -> Result { Err(ErrorCode::Unimplemented( "Cannot get db name by id in ICEBERG catalog", )) diff --git a/src/query/storages/share/Cargo.toml b/src/query/storages/share/Cargo.toml deleted file mode 100644 index f91bb20f9a5a..000000000000 --- a/src/query/storages/share/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "databend-common-storages-share" -version = { workspace = true } -authors = { workspace = true } -license = { workspace = true } -publish = { workspace = true } -edition = { workspace = true } - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[lib] -doctest = false -test = true - -[dependencies] -chrono = { workspace = true } -databend-common-exception = { path = "../../../common/exception" } -databend-common-meta-app = { path = "../../../meta/app" } -enumflags2 = { workspace = true } - -databend-storages-common-table-meta = { path = "../common/table_meta" } - -async-backtrace = { workspace = true } -opendal = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } - -[dev-dependencies] -goldenfile = "1.4" -tempfile = "3.4.0" diff --git a/src/query/storages/share/src/lib.rs b/src/query/storages/share/src/lib.rs deleted file mode 100644 index b5e68929cac4..000000000000 --- a/src/query/storages/share/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -#![allow(clippy::uninlined_format_args)] - -mod share; - -pub use share::get_share_spec_location; -pub use share::save_share_spec; -pub use share::save_share_table_info; -pub use share::share_table_info_location; diff --git a/src/query/storages/share/src/share.rs b/src/query/storages/share/src/share.rs deleted file mode 100644 index c5cda18e41ae..000000000000 --- a/src/query/storages/share/src/share.rs +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2021 Datafuse Labs -// -// 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. - -use std::collections::BTreeMap; - -use chrono::DateTime; -use chrono::Utc; -use databend_common_exception::Result; -use databend_common_meta_app::share::ShareDatabaseSpec; -use databend_common_meta_app::share::ShareSpec; -use databend_common_meta_app::share::ShareTableInfoMap; -use databend_common_meta_app::share::ShareTableSpec; -use opendal::Operator; - -const SHARE_CONFIG_PREFIX: &str = "_share_config"; - -#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, Default, Eq, PartialEq)] -pub struct ShareSpecVec { - share_specs: BTreeMap, -} - -pub fn get_share_spec_location(tenant: &str) -> String { - format!("{}/{}/share_specs.json", SHARE_CONFIG_PREFIX, tenant,) -} - -pub fn share_table_info_location(tenant: &str, share_name: &str) -> String { - format!( - "{}/{}/{}_table_info.json", - SHARE_CONFIG_PREFIX, tenant, share_name - ) -} - -#[async_backtrace::framed] -pub async fn save_share_table_info( - tenant: &str, - operator: Operator, - share_table_info: Vec, -) -> Result<()> { - for (share_name, share_table_info) in share_table_info { - let share_name = share_name.clone(); - let location = share_table_info_location(tenant, &share_name); - match share_table_info { - Some(table_info_map) => { - operator - .write(&location, serde_json::to_vec(&table_info_map)?) - .await?; - } - None => { - operator.delete(&location).await?; - } - } - } - - Ok(()) -} - -#[async_backtrace::framed] -pub async fn save_share_spec( - tenant: &str, - operator: Operator, - spec_vec: Option>, - share_table_info: Option>, -) -> Result<()> { - if let Some(share_spec) = spec_vec { - let location = get_share_spec_location(tenant); - let mut share_spec_vec = ShareSpecVec::default(); - for spec in share_spec { - let share_name = spec.name.clone(); - let share_spec_ext = ext::ShareSpecExt::from_share_spec(spec, &operator); - share_spec_vec - .share_specs - .insert(share_name, share_spec_ext); - } - operator - .write(&location, serde_json::to_vec(&share_spec_vec)?) - .await?; - } - - // save share table info - if let Some(share_table_info) = share_table_info { - save_share_table_info(tenant, operator, share_table_info).await? - } - - Ok(()) -} - -mod ext { - use databend_common_meta_app::share::ShareGrantObjectPrivilege; - use databend_storages_common_table_meta::table::database_storage_prefix; - use databend_storages_common_table_meta::table::table_storage_prefix; - use enumflags2::BitFlags; - - use super::*; - - #[derive(serde::Serialize, serde::Deserialize, Clone, Debug, Default, Eq, PartialEq)] - struct WithLocation { - location: String, - #[serde(flatten)] - t: T, - } - - /// An extended form of [ShareSpec], which decorates [ShareDatabaseSpec] and [ShareTableSpec] - /// with location - #[derive(serde::Serialize, serde::Deserialize, Clone, Debug, Default, Eq, PartialEq)] - pub(super) struct ShareSpecExt { - name: String, - share_id: u64, - version: u64, - database: Option>, - tables: Vec>, - tenants: Vec, - db_privileges: Option>, - comment: Option, - share_on: Option>, - } - - impl ShareSpecExt { - pub fn from_share_spec(spec: ShareSpec, operator: &Operator) -> Self { - Self { - name: spec.name, - share_id: spec.share_id, - version: spec.version, - database: spec.database.map(|db_spec| WithLocation { - location: shared_database_prefix(operator, db_spec.id), - t: db_spec, - }), - tables: spec - .tables - .into_iter() - .map(|tbl_spec| WithLocation { - location: shared_table_prefix( - operator, - tbl_spec.database_id, - tbl_spec.table_id, - ), - t: tbl_spec, - }) - .collect(), - tenants: spec.tenants, - db_privileges: spec.db_privileges, - comment: spec.comment.clone(), - share_on: spec.share_on, - } - } - } - - /// Returns prefix path which covers all the data of give table. - /// something like "query-storage-bd5efc6/tnc7yee14/501248/501263/", where - /// - "/query-storage-bd5efc6/tnc7yee14/" is the storage prefix - /// - "501248/" is the database id suffixed with '/' - /// - "501263/" is the table id suffixed with '/' - fn shared_table_prefix(operator: &Operator, database_id: u64, table_id: u64) -> String { - let operator_meta_data = operator.info(); - let storage_prefix = operator_meta_data.root(); - let table_storage_prefix = table_storage_prefix(database_id, table_id); - // storage_prefix has suffix character '/' - format!("{}{}/", storage_prefix, table_storage_prefix) - } - - /// Returns prefix path which covers all the data of give database. - /// something like "query-storage-bd5efc6/tnc7yee14/501248/", where - /// - "/query-storage-bd5efc6/tnc7yee14/" is the storage prefix - /// - "501248/" is the database id suffixed with '/' - fn shared_database_prefix(operator: &Operator, database_id: u64) -> String { - let operator_meta_data = operator.info(); - let storage_prefix = operator_meta_data.root(); - let database_storage_prefix = database_storage_prefix(database_id); - // storage_prefix has suffix character '/' - format!("{}{}/", storage_prefix, database_storage_prefix) - } -} diff --git a/tests/sqllogictests/suites/base/06_show/06_0009_show_shares.test b/tests/sqllogictests/suites/base/06_show/06_0009_show_shares.test deleted file mode 100644 index 6f6c97b529a2..000000000000 --- a/tests/sqllogictests/suites/base/06_show/06_0009_show_shares.test +++ /dev/null @@ -1,59 +0,0 @@ -statement ok -DROP DATABASE IF EXISTS show_shares - -statement ok -DROP SHARE IF EXISTS test_share - -statement ok -CREATE DATABASE show_shares - -statement ok -USE show_shares - -statement ok -DROP TABLE IF EXISTS test_tb - -statement ok -create table test_tb (a int) - -statement ok -create share test_share comment = 'comment' - -statement ok -alter share test_share add tenants = x - -statement ok -grant USAGE on DATABASE show_shares TO SHARE test_share - -statement ok -grant SELECT on TABLE show_shares.test_tb TO SHARE test_share - -# query RTTTTTT -# show shares -# ---- -# $DATE_IN_SHARE OUTBOUND test_share show_shares test_tenant x comment - -# query RTT -# desc share test_share -# ---- -# TABLE show_shares.test_tb $DATE_IN_SHARE -# DATABASE show_shares $DATE_IN_SHARE - -# query RTT -# show grants on DATABASE show_shares -# ---- -# $DATE_IN_SHARE Usage test_share - -# query RTT -# show grants on TABLE show_shares.test_tb -# ---- -# $DATE_IN_SHARE Select test_share - -statement ok -DROP TABLE IF EXISTS test_tb - -statement ok -DROP DATABASE IF EXISTS show_shares - -statement ok -DROP SHARE IF EXISTS test_share diff --git a/tests/sqllogictests/suites/base/06_show/06_0020_show_share_endpoint.test b/tests/sqllogictests/suites/base/06_show/06_0020_show_share_endpoint.test deleted file mode 100644 index 4fada87658d3..000000000000 --- a/tests/sqllogictests/suites/base/06_show/06_0020_show_share_endpoint.test +++ /dev/null @@ -1,23 +0,0 @@ -statement ok -DROP SHARE ENDPOINT IF EXISTS t; - -statement ok -CREATE SHARE ENDPOINT t URL='http://127.0.0.1/' TENANT=x ARGS=(jwks_key_file='https://eks.public/keys,ssl_cert=cert.pem',) COMMENT = 'share endpoint comment'; - -statement ok -SHOW SHARE ENDPOINT; - -statement ok -DROP SHARE ENDPOINT t; - -statement ok -CREATE SHARE ENDPOINT replace_share_endpoint URL='http://127.0.0.1/' TENANT=x ARGS=(jwks_key_file='https://eks.public/keys,ssl_cert=cert.pem',) COMMENT = 'share endpoint comment'; - -statement error 1005 -CREATE OR REPLACE SHARE ENDPOINT IF NOT EXISTS replace_share_endpoint URL='http://192.168.0.1/' TENANT=x ARGS=(jwks_key_file='https://eks.public/keys,ssl_cert=cert.pem',) COMMENT = 'replace share endpoint comment'; - -statement ok -CREATE OR REPLACE SHARE ENDPOINT replace_share_endpoint URL='http://192.168.0.1/' TENANT=x ARGS=(jwks_key_file='https://eks.public/keys,ssl_cert=cert.pem',) COMMENT = 'replace share endpoint comment'; - -statement ok -DROP SHARE ENDPOINT replace_share_endpoint; \ No newline at end of file diff --git a/tests/suites/3_stateful_sharing/01_sharing/01_0000_basic_sharing.result b/tests/suites/3_stateful_sharing/01_sharing/01_0000_basic_sharing.result deleted file mode 100644 index 75e7a5dfe1ea..000000000000 --- a/tests/suites/3_stateful_sharing/01_sharing/01_0000_basic_sharing.result +++ /dev/null @@ -1,61 +0,0 @@ -drop test share and database -prepare shared database and table -OUTBOUND test_share test_database shared_tenant shared_tenant,to_tenant -get shared database and table from same tenant -INBOUND test_share test_database shared_tenant shared_tenant -1 -2 -3 -4 -5 -6 -get shared database and table from another tenant -INBOUND test_share test_database to_tenant to_tenant -INBOUND test_share test_database shared_tenant to_tenant -1 -2 -3 -4 -5 -6 -cannot grant a database which create from share -ERROR 1105 (HY000) at line 1: CannotShareDatabaseCreatedFromShare. Code: 2718, Text = Cannot share database 'shared_db' which created from share. -alter table add column and query table data again -1,1 -2,1 -3,1 -1,1 -2,1 -3,1 -alter table drop column and query table data again -1 -1 -1 -1 -1 -1 -drop shared table and query data from share -ERROR 1105 (HY000) at line 1: UnknownTable. Code: 1025, Text = error: - --> SQL:1:15 - | -1 | SELECT * FROM shared_db.t1 - | ^^^^^^^^^^^^ Unknown table `shared_db`.`t1` in catalog 'default' - -. -ERROR 1105 (HY000) at line 1: UnknownTable. Code: 1025, Text = error: - --> SQL:1:15 - | -1 | SELECT * FROM shared_db.t1 - | ^^^^^^^^^^^^ Unknown table `shared_db`.`t1` in catalog 'default' - -. -drop shared database and query data from share -4 -5 -6 -4 -5 -6 -ERROR 1105 (HY000) at line 1: ShareStorageError. Code: 2719, Text = share "test_share" storage error: HTTP status "Bad Request". -ERROR 1105 (HY000) at line 1: ShareStorageError. Code: 2719, Text = share "test_share" storage error: HTTP status "Bad Request". -all is good diff --git a/tests/suites/3_stateful_sharing/01_sharing/01_0000_basic_sharing.sh b/tests/suites/3_stateful_sharing/01_sharing/01_0000_basic_sharing.sh deleted file mode 100755 index d7dcf8e26169..000000000000 --- a/tests/suites/3_stateful_sharing/01_sharing/01_0000_basic_sharing.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env bash - -CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) -. "$CURDIR"/../../../shell_env.sh - -echo "drop test share and database" -echo "drop share if exists test_share" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "drop share if exists my_share" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "drop database if exists test_database" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "drop database if exists shared_db" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "drop database if exists shared_db" | $MYSQL_CLIENT_SHARE_3_CONNECT - -# prepare shared database and table -echo "prepare shared database and table" -echo "CREATE SHARE test_share" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "CREATE DATABASE test_database" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "CREATE TABLE test_database.t1 (number UInt64)" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "INSERT INTO test_database.t1 VALUES (1),(2),(3)" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "CREATE TABLE test_database.t2 (number UInt64)" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "INSERT INTO test_database.t2 VALUES (4),(5),(6)" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "GRANT USAGE ON DATABASE test_database TO SHARE test_share" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "GRANT SELECT ON TABLE test_database.t1 TO SHARE test_share" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "GRANT SELECT ON TABLE test_database.t2 TO SHARE test_share" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "ALTER SHARE test_share ADD TENANTS = shared_tenant,to_tenant" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "SHOW SHARES" | $MYSQL_CLIENT_SHARE_1_CONNECT | awk '{print $(NF-4), $(NF-3), $(NF-2), $(NF-1), $NF}' - -# get shared database and table from same tenant -echo "get shared database and table from same tenant" -echo "SHOW SHARES" | $MYSQL_CLIENT_SHARE_3_CONNECT | awk '{print $(NF-4), $(NF-3), $(NF-2), $(NF-1), $NF}' -echo "CREATE DATABASE if not exists shared_db FROM SHARE shared_tenant.test_share" | $MYSQL_CLIENT_SHARE_3_CONNECT -echo "SELECT * FROM shared_db.t1" | $MYSQL_CLIENT_SHARE_3_CONNECT -echo "SELECT * FROM shared_db.t2" | $MYSQL_CLIENT_SHARE_3_CONNECT - -# get shared database and table from another tenant -echo "get shared database and table from another tenant" -echo "drop share endpoint if exists to_share" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "create share endpoint to_share url='http://127.0.0.1:23003' tenant=shared_tenant" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "SHOW SHARES" | $MYSQL_CLIENT_SHARE_2_CONNECT | awk '{print $(NF-4), $(NF-3), $(NF-2), $(NF-1), $NF}' -echo "CREATE DATABASE if not exists shared_db FROM SHARE shared_tenant.test_share" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "SELECT * FROM shared_db.t1" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "SELECT * FROM shared_db.t2" | $MYSQL_CLIENT_SHARE_2_CONNECT - -# cannot grant a database which create from share -echo "cannot grant a database which create from share" -echo "CREATE SHARE my_share" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "GRANT USAGE ON DATABASE shared_db TO SHARE my_share" | $MYSQL_CLIENT_SHARE_2_CONNECT - -# alter table and query table data again -echo "alter table add column and query table data again" -echo "ALTER table test_database.t1 add column b UInt64 default 1" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "SELECT * FROM shared_db.t1 order by number" | $MYSQL_CLIENT_SHARE_2_CONNECT | awk '{print $(NF-1)","$(NF)}' -echo "SELECT * FROM shared_db.t1 order by number" | $MYSQL_CLIENT_SHARE_3_CONNECT | awk '{print $(NF-1)","$(NF)}' -echo "alter table drop column and query table data again" -echo "ALTER table test_database.t1 drop column number" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "SELECT * FROM shared_db.t1" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "SELECT * FROM shared_db.t1" | $MYSQL_CLIENT_SHARE_3_CONNECT - -# drop shared table and query data from share -echo "drop shared table and query data from share" -echo "drop table if exists test_database.t1" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "SELECT * FROM shared_db.t1" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "SELECT * FROM shared_db.t1" | $MYSQL_CLIENT_SHARE_3_CONNECT - -# drop shared database and query data from share -echo "drop shared database and query data from share" -echo "SELECT * FROM shared_db.t2" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "SELECT * FROM shared_db.t2" | $MYSQL_CLIENT_SHARE_3_CONNECT -echo "drop database if exists test_database" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "SELECT * FROM shared_db.t2" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "SELECT * FROM shared_db.t2" | $MYSQL_CLIENT_SHARE_3_CONNECT - -## Drop database and share. -echo "all is good" -echo "drop share if exists test_share" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "drop share if exists my_share" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "drop database if exists test_database" | $MYSQL_CLIENT_SHARE_1_CONNECT -echo "drop database if exists shared_db" | $MYSQL_CLIENT_SHARE_2_CONNECT -echo "drop database if exists shared_db" | $MYSQL_CLIENT_SHARE_3_CONNECT