|
| 1 | +// Copyright 2021 Datafuse Labs |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +use std::sync::Arc; |
| 16 | + |
| 17 | +use chrono::Utc; |
| 18 | +use databend_common_expression::types::NumberDataType; |
| 19 | +use databend_common_expression::AutoIncrementExpr; |
| 20 | +use databend_common_expression::TableDataType; |
| 21 | +use databend_common_expression::TableField; |
| 22 | +use databend_common_expression::TableSchema; |
| 23 | +use databend_common_meta_app::principal::AutoIncrementKey; |
| 24 | +use databend_common_meta_app::schema::database_name_ident::DatabaseNameIdent; |
| 25 | +use databend_common_meta_app::schema::AutoIncrementStorageIdent; |
| 26 | +use databend_common_meta_app::schema::CreateDatabaseReq; |
| 27 | +use databend_common_meta_app::schema::CreateOption; |
| 28 | +use databend_common_meta_app::schema::CreateTableReq; |
| 29 | +use databend_common_meta_app::schema::DatabaseMeta; |
| 30 | +use databend_common_meta_app::schema::GcDroppedTableReq; |
| 31 | +use databend_common_meta_app::schema::GetAutoIncrementNextValueReq; |
| 32 | +use databend_common_meta_app::schema::ListDroppedTableReq; |
| 33 | +use databend_common_meta_app::schema::TableMeta; |
| 34 | +use databend_common_meta_app::schema::TableNameIdent; |
| 35 | +use databend_common_meta_app::tenant::Tenant; |
| 36 | +use databend_common_meta_kvapi::kvapi; |
| 37 | +use databend_common_meta_kvapi::kvapi::Key; |
| 38 | +use databend_common_meta_kvapi::kvapi::KvApiExt; |
| 39 | +use databend_common_meta_types::MetaError; |
| 40 | +use fastrace::func_name; |
| 41 | +use log::info; |
| 42 | + |
| 43 | +use crate::kv_pb_api::KVPbApi; |
| 44 | +use crate::AutoIncrementApi; |
| 45 | +use crate::DatabaseApi; |
| 46 | +use crate::DatamaskApi; |
| 47 | +use crate::GarbageCollectionApi; |
| 48 | +use crate::RowAccessPolicyApi; |
| 49 | +use crate::SchemaApi; |
| 50 | +use crate::TableApi; |
| 51 | + |
| 52 | +/// Test suite of `AutoIncrementApi`. |
| 53 | +/// |
| 54 | +/// It is not used by this crate, but is used by other crate that impl `AutoIncrementApi`, |
| 55 | +/// to ensure an impl works as expected, |
| 56 | +/// such as `meta/embedded` and `metasrv`. |
| 57 | +#[derive(Copy, Clone)] |
| 58 | +pub struct AutoIncrementApiTestSuite {} |
| 59 | + |
| 60 | +impl AutoIncrementApiTestSuite { |
| 61 | + /// Test AutoIncrementApi on a single node |
| 62 | + pub async fn test_single_node<B, MT>(b: B) -> anyhow::Result<()> |
| 63 | + where |
| 64 | + B: kvapi::ApiBuilder<MT>, |
| 65 | + MT: kvapi::KVApi<Error = MetaError> |
| 66 | + + SchemaApi |
| 67 | + + DatamaskApi |
| 68 | + + AutoIncrementApi |
| 69 | + + RowAccessPolicyApi |
| 70 | + + 'static, |
| 71 | + { |
| 72 | + let suite = AutoIncrementApiTestSuite {}; |
| 73 | + suite.table_commit_table_meta(&b.build().await).await?; |
| 74 | + Ok(()) |
| 75 | + } |
| 76 | + |
| 77 | + #[fastrace::trace] |
| 78 | + async fn table_commit_table_meta<MT: AutoIncrementApi + kvapi::KVApi<Error = MetaError>>( |
| 79 | + &self, |
| 80 | + mt: &MT, |
| 81 | + ) -> anyhow::Result<()> { |
| 82 | + let tenant_name = "table_commit_table_meta_tenant"; |
| 83 | + let db_name = "db1"; |
| 84 | + let tbl_name = "tb2"; |
| 85 | + |
| 86 | + info!("--- prepare db"); |
| 87 | + let mut util = Util::new(mt, tenant_name, db_name, ""); |
| 88 | + util.create_db().await?; |
| 89 | + |
| 90 | + let schema = || { |
| 91 | + Arc::new(TableSchema::new(vec![TableField::new( |
| 92 | + "number", |
| 93 | + TableDataType::Number(NumberDataType::UInt64), |
| 94 | + ) |
| 95 | + .with_auto_increment_expr(Some(AutoIncrementExpr { |
| 96 | + column_id: 0, |
| 97 | + start: 0, |
| 98 | + step: 1, |
| 99 | + is_ordered: true, |
| 100 | + }))])) |
| 101 | + }; |
| 102 | + let options = || maplit::btreemap! {"opt‐1".into() => "val-1".into()}; |
| 103 | + |
| 104 | + let drop_table_meta = |created_on| TableMeta { |
| 105 | + schema: schema(), |
| 106 | + engine: "JSON".to_string(), |
| 107 | + options: options(), |
| 108 | + created_on, |
| 109 | + drop_on: Some(created_on), |
| 110 | + ..TableMeta::default() |
| 111 | + }; |
| 112 | + let created_on = Utc::now(); |
| 113 | + |
| 114 | + // verify the auto increment will be vacuum |
| 115 | + { |
| 116 | + // use a new tenant and db do test |
| 117 | + let db_name = "orphan_db"; |
| 118 | + let tenant_name = "orphan_tenant"; |
| 119 | + let mut orphan_util = Util::new(mt, tenant_name, db_name, ""); |
| 120 | + orphan_util.create_db().await?; |
| 121 | + let tenant = orphan_util.tenant(); |
| 122 | + |
| 123 | + let create_table_req = CreateTableReq { |
| 124 | + create_option: CreateOption::CreateOrReplace, |
| 125 | + catalog_name: Some("default".to_string()), |
| 126 | + name_ident: TableNameIdent { |
| 127 | + tenant: Tenant::new_or_err(tenant_name, func_name!())?, |
| 128 | + db_name: db_name.to_string(), |
| 129 | + table_name: tbl_name.to_string(), |
| 130 | + }, |
| 131 | + table_meta: drop_table_meta(created_on), |
| 132 | + as_dropped: true, |
| 133 | + table_properties: None, |
| 134 | + table_partition: None, |
| 135 | + }; |
| 136 | + |
| 137 | + let create_table_as_dropped_resp = mt.create_table(create_table_req.clone()).await?; |
| 138 | + |
| 139 | + let auto_increment_key = |
| 140 | + AutoIncrementKey::new(create_table_as_dropped_resp.table_id, 0); |
| 141 | + let auto_increment_sequence_storage = |
| 142 | + AutoIncrementStorageIdent::new_generic(&tenant, auto_increment_key.clone()); |
| 143 | + |
| 144 | + // assert auto increment exists |
| 145 | + let seqv = mt |
| 146 | + .get_kv(&auto_increment_sequence_storage.to_string_key()) |
| 147 | + .await?; |
| 148 | + assert!(seqv.is_some() && seqv.unwrap().seq != 0); |
| 149 | + |
| 150 | + // auto increment next val |
| 151 | + let expr = AutoIncrementExpr { |
| 152 | + column_id: 0, |
| 153 | + start: 0, |
| 154 | + step: 1, |
| 155 | + is_ordered: true, |
| 156 | + }; |
| 157 | + let next_val_req = GetAutoIncrementNextValueReq { |
| 158 | + tenant: tenant.clone(), |
| 159 | + expr, |
| 160 | + key: auto_increment_key, |
| 161 | + count: 1, |
| 162 | + }; |
| 163 | + mt.get_auto_increment_next_value(next_val_req) |
| 164 | + .await? |
| 165 | + .unwrap(); |
| 166 | + |
| 167 | + // assert auto increment current is 1 after next val |
| 168 | + let seqv = mt.get_pb(&auto_increment_sequence_storage).await?; |
| 169 | + assert!(seqv.as_ref().unwrap().seq != 0); |
| 170 | + assert_eq!(seqv.as_ref().unwrap().data.inner().0, 1); |
| 171 | + |
| 172 | + // assert auto increment exists |
| 173 | + let seqv = mt |
| 174 | + .get_kv(&auto_increment_sequence_storage.to_string_key()) |
| 175 | + .await?; |
| 176 | + assert!(seqv.is_some() && seqv.unwrap().seq != 0); |
| 177 | + |
| 178 | + // vacuum drop table |
| 179 | + let req = ListDroppedTableReq::new(&tenant); |
| 180 | + let resp = mt.get_drop_table_infos(req).await?; |
| 181 | + assert!(!resp.drop_ids.is_empty()); |
| 182 | + |
| 183 | + let req = GcDroppedTableReq { |
| 184 | + tenant: Tenant::new_or_err(tenant_name, func_name!())?, |
| 185 | + catalog: "default".to_string(), |
| 186 | + drop_ids: resp.drop_ids.clone(), |
| 187 | + }; |
| 188 | + mt.gc_drop_tables(req).await?; |
| 189 | + |
| 190 | + // assert auto increment has been vacuum |
| 191 | + let seqv = mt |
| 192 | + .get_kv(&auto_increment_sequence_storage.to_string_key()) |
| 193 | + .await?; |
| 194 | + assert!(seqv.is_none()); |
| 195 | + } |
| 196 | + |
| 197 | + Ok(()) |
| 198 | + } |
| 199 | +} |
| 200 | + |
| 201 | +struct Util<'a, MT> |
| 202 | +// where MT: AutoIncrementApi |
| 203 | +where MT: kvapi::KVApi<Error = MetaError> + AutoIncrementApi |
| 204 | +{ |
| 205 | + tenant: Tenant, |
| 206 | + db_name: String, |
| 207 | + engine: String, |
| 208 | + db_id: u64, |
| 209 | + mt: &'a MT, |
| 210 | +} |
| 211 | + |
| 212 | +impl<'a, MT> Util<'a, MT> |
| 213 | +where MT: AutoIncrementApi + kvapi::KVApi<Error = MetaError> |
| 214 | +{ |
| 215 | + fn new( |
| 216 | + mt: &'a MT, |
| 217 | + tenant: impl ToString, |
| 218 | + db_name: impl ToString, |
| 219 | + engine: impl ToString, |
| 220 | + ) -> Self { |
| 221 | + Self { |
| 222 | + tenant: Tenant::new_or_err(tenant, func_name!()).unwrap(), |
| 223 | + db_name: db_name.to_string(), |
| 224 | + engine: engine.to_string(), |
| 225 | + db_id: 0, |
| 226 | + mt, |
| 227 | + } |
| 228 | + } |
| 229 | + |
| 230 | + fn tenant(&self) -> Tenant { |
| 231 | + self.tenant.clone() |
| 232 | + } |
| 233 | + |
| 234 | + fn engine(&self) -> String { |
| 235 | + self.engine.clone() |
| 236 | + } |
| 237 | + |
| 238 | + fn db_name(&self) -> String { |
| 239 | + self.db_name.clone() |
| 240 | + } |
| 241 | + |
| 242 | + async fn create_db(&mut self) -> anyhow::Result<()> { |
| 243 | + let plan = CreateDatabaseReq { |
| 244 | + create_option: CreateOption::Create, |
| 245 | + catalog_name: None, |
| 246 | + name_ident: DatabaseNameIdent::new(self.tenant(), self.db_name()), |
| 247 | + meta: DatabaseMeta { |
| 248 | + engine: self.engine(), |
| 249 | + ..DatabaseMeta::default() |
| 250 | + }, |
| 251 | + }; |
| 252 | + |
| 253 | + let res = self.mt.create_database(plan).await?; |
| 254 | + self.db_id = *res.db_id; |
| 255 | + |
| 256 | + Ok(()) |
| 257 | + } |
| 258 | +} |
0 commit comments