| yiguolei | 2eef794 | 2026-03-09 09:26:05 +0800 | [diff] [blame] | 1 | // Licensed to the Apache Software Foundation (ASF) under one |
| 2 | // or more contributor license agreements. See the NOTICE file |
| 3 | // distributed with this work for additional information |
| 4 | // regarding copyright ownership. The ASF licenses this file |
| 5 | // to you under the Apache License, Version 2.0 (the |
| 6 | // "License"); you may not use this file except in compliance |
| 7 | // with the License. You may obtain a copy of the License at |
| 8 | // |
| 9 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | // |
| 11 | // Unless required by applicable law or agreed to in writing, |
| 12 | // software distributed under the License is distributed on an |
| 13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 14 | // KIND, either express or implied. See the License for the |
| 15 | // specific language governing permissions and limitations |
| 16 | // under the License. |
| 17 | |
| 18 | #include "information_schema/schema_cluster_snapshots_scanner.h" |
| 19 | |
| 20 | #include <cstdint> |
| 21 | #include <string> |
| 22 | |
| 23 | #include "cloud/cloud_meta_mgr.h" |
| 24 | #include "cloud/cloud_storage_engine.h" |
| 25 | #include "common/status.h" |
| 26 | #include "core/data_type/define_primitive_type.h" |
| 27 | #include "core/string_ref.h" |
| 28 | #include "information_schema/schema_helper.h" |
| 29 | #include "runtime/exec_env.h" |
| 30 | #include "storage/storage_engine.h" |
| 31 | |
| 32 | namespace doris { |
| 33 | #include "common/compile_check_begin.h" |
| 34 | class RuntimeState; |
| yiguolei | 2eef794 | 2026-03-09 09:26:05 +0800 | [diff] [blame] | 35 | class Block; |
| yiguolei | 2eef794 | 2026-03-09 09:26:05 +0800 | [diff] [blame] | 36 | |
| 37 | std::vector<SchemaScanner::ColumnDesc> SchemaClusterSnapshotsScanner::_s_tbls_columns = { |
| 38 | {"ID", TYPE_STRING, sizeof(StringRef), true}, |
| 39 | {"ANCESTOR", TYPE_STRING, sizeof(StringRef), true}, |
| 40 | {"CREATE_AT", TYPE_DATETIMEV2, sizeof(DateTimeV2ValueType), true}, |
| 41 | {"FINISH_AT", TYPE_DATETIMEV2, sizeof(DateTimeV2ValueType), true}, |
| 42 | {"IMAGE_URL", TYPE_STRING, sizeof(StringRef), true}, |
| 43 | {"JOURNAL_ID", TYPE_BIGINT, sizeof(int64_t), true}, |
| 44 | {"STATE", TYPE_STRING, sizeof(StringRef), true}, |
| 45 | {"AUTO", TYPE_BOOLEAN, sizeof(int8_t), true}, |
| 46 | {"TTL", TYPE_BIGINT, sizeof(int64_t), true}, |
| 47 | {"LABEL", TYPE_STRING, sizeof(StringRef), true}, |
| 48 | {"MSG", TYPE_STRING, sizeof(StringRef), true}, |
| 49 | {"COUNT", TYPE_INT, sizeof(int32_t), true}, |
| 50 | }; |
| 51 | |
| 52 | SchemaClusterSnapshotsScanner::SchemaClusterSnapshotsScanner() |
| 53 | : SchemaScanner(_s_tbls_columns, TSchemaTableType::SCH_CLUSTER_SNAPSHOTS) {} |
| 54 | |
| 55 | SchemaClusterSnapshotsScanner::~SchemaClusterSnapshotsScanner() {} |
| 56 | |
| 57 | Status SchemaClusterSnapshotsScanner::start(RuntimeState* state) { |
| 58 | if (!_is_init) { |
| 59 | return Status::InternalError("used before initialized."); |
| 60 | } |
| 61 | if (!config::is_cloud_mode()) { |
| 62 | return Status::InternalError("only support cloud mode"); |
| 63 | } |
| 64 | |
| 65 | return ExecEnv::GetInstance()->storage_engine().to_cloud().meta_mgr().list_snapshot(_snapshots); |
| 66 | } |
| 67 | |
| yiguolei | 4d85ff1 | 2026-03-09 18:44:51 +0800 | [diff] [blame] | 68 | Status SchemaClusterSnapshotsScanner::get_next_block_internal(Block* block, bool* eos) { |
| yiguolei | 2eef794 | 2026-03-09 09:26:05 +0800 | [diff] [blame] | 69 | if (!_is_init) { |
| 70 | return Status::InternalError("call this before initial."); |
| 71 | } |
| 72 | if (block == nullptr || eos == nullptr) { |
| 73 | return Status::InternalError("invalid parameter."); |
| 74 | } |
| 75 | |
| 76 | *eos = true; |
| 77 | if (_snapshots.empty()) { |
| 78 | return Status::OK(); |
| 79 | } |
| 80 | |
| 81 | return _fill_block_impl(block); |
| 82 | } |
| 83 | |
| yiguolei | 4d85ff1 | 2026-03-09 18:44:51 +0800 | [diff] [blame] | 84 | Status SchemaClusterSnapshotsScanner::_fill_block_impl(Block* block) { |
| yiguolei | 2eef794 | 2026-03-09 09:26:05 +0800 | [diff] [blame] | 85 | SCOPED_TIMER(_fill_block_timer); |
| 86 | size_t row_num = _snapshots.size(); |
| 87 | if (row_num == 0) { |
| 88 | return Status::OK(); |
| 89 | } |
| 90 | |
| 91 | std::vector<void*> datas(row_num); |
| 92 | std::vector<StringRef> strs(row_num); |
| 93 | // snapshot_id |
| 94 | { |
| 95 | for (int i = 0; i < row_num; ++i) { |
| 96 | auto& snapshot = _snapshots[i]; |
| 97 | if (snapshot.has_snapshot_id()) { |
| 98 | strs[i] = StringRef(snapshot.snapshot_id().c_str(), snapshot.snapshot_id().size()); |
| 99 | datas[i] = strs.data() + i; |
| 100 | } else { |
| 101 | datas[i] = nullptr; |
| 102 | } |
| 103 | } |
| 104 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 0, datas)); |
| 105 | } |
| 106 | // ancestor_id |
| 107 | { |
| 108 | for (int i = 0; i < row_num; ++i) { |
| 109 | auto& snapshot = _snapshots[i]; |
| 110 | if (snapshot.has_ancestor_id()) { |
| 111 | strs[i] = StringRef(snapshot.ancestor_id().c_str(), snapshot.ancestor_id().size()); |
| 112 | datas[i] = strs.data() + i; |
| 113 | } else { |
| 114 | datas[i] = nullptr; |
| 115 | } |
| 116 | } |
| 117 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 1, datas)); |
| 118 | } |
| 119 | // create_at |
| 120 | { |
| 121 | std::vector<DateV2Value<DateTimeV2ValueType>> srcs(row_num); |
| 122 | for (int i = 0; i < row_num; ++i) { |
| 123 | if (_snapshots[i].has_create_at()) { |
| 124 | int64_t value = _snapshots[i].create_at(); |
| 125 | srcs[i].from_unixtime(value, _timezone_obj); |
| 126 | datas[i] = srcs.data() + i; |
| 127 | } else { |
| 128 | datas[i] = nullptr; |
| 129 | } |
| 130 | } |
| 131 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 2, datas)); |
| 132 | } |
| 133 | // finish_at |
| 134 | { |
| 135 | std::vector<DateV2Value<DateTimeV2ValueType>> srcs(row_num); |
| 136 | for (int i = 0; i < row_num; ++i) { |
| 137 | if (_snapshots[i].has_finish_at()) { |
| 138 | int64_t value = _snapshots[i].finish_at(); |
| 139 | srcs[i].from_unixtime(value, _timezone_obj); |
| 140 | datas[i] = srcs.data() + i; |
| 141 | } else { |
| 142 | datas[i] = nullptr; |
| 143 | } |
| 144 | } |
| 145 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 3, datas)); |
| 146 | } |
| 147 | // image_url |
| 148 | { |
| 149 | for (int i = 0; i < row_num; ++i) { |
| 150 | auto& snapshot = _snapshots[i]; |
| 151 | if (snapshot.has_image_url()) { |
| 152 | strs[i] = StringRef(snapshot.image_url().c_str(), snapshot.image_url().size()); |
| 153 | datas[i] = strs.data() + i; |
| 154 | } else { |
| 155 | datas[i] = nullptr; |
| 156 | } |
| 157 | } |
| 158 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 4, datas)); |
| 159 | } |
| 160 | // journal_id |
| 161 | { |
| 162 | std::vector<int64_t> srcs(row_num); |
| 163 | for (int i = 0; i < row_num; ++i) { |
| 164 | if (_snapshots[i].has_journal_id()) { |
| 165 | srcs[i] = _snapshots[i].journal_id(); |
| 166 | datas[i] = srcs.data() + i; |
| 167 | } else { |
| 168 | datas[i] = nullptr; |
| 169 | } |
| 170 | } |
| 171 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 5, datas)); |
| 172 | } |
| 173 | // status |
| 174 | { |
| 175 | std::vector<std::string> status(row_num); |
| 176 | for (int i = 0; i < row_num; ++i) { |
| 177 | auto& snapshot = _snapshots[i]; |
| 178 | if (snapshot.has_status()) { |
| 179 | status[i] = SnapshotStatus_Name(snapshot.status()); |
| 180 | strs[i] = StringRef(status[i].c_str(), status[i].size()); |
| 181 | datas[i] = strs.data() + i; |
| 182 | } else { |
| 183 | datas[i] = nullptr; |
| 184 | } |
| 185 | } |
| 186 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 6, datas)); |
| 187 | } |
| 188 | // auto_snapshot |
| 189 | { |
| 190 | std::vector<int8_t> srcs(row_num); |
| 191 | for (int i = 0; i < row_num; ++i) { |
| 192 | if (_snapshots[i].has_auto_snapshot()) { |
| 193 | srcs[i] = _snapshots[i].auto_snapshot() ? 1 : 0; |
| 194 | datas[i] = srcs.data() + i; |
| 195 | } else { |
| 196 | datas[i] = nullptr; |
| 197 | } |
| 198 | } |
| 199 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 7, datas)); |
| 200 | } |
| 201 | // ttl_seconds |
| 202 | { |
| 203 | std::vector<int64_t> srcs(row_num); |
| 204 | for (int i = 0; i < row_num; ++i) { |
| 205 | if (_snapshots[i].has_ttl_seconds()) { |
| 206 | srcs[i] = _snapshots[i].ttl_seconds(); |
| 207 | datas[i] = srcs.data() + i; |
| 208 | } else { |
| 209 | datas[i] = nullptr; |
| 210 | } |
| 211 | } |
| 212 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 8, datas)); |
| 213 | } |
| 214 | // label |
| 215 | { |
| 216 | for (int i = 0; i < row_num; ++i) { |
| 217 | auto& snapshot = _snapshots[i]; |
| 218 | if (snapshot.has_snapshot_label()) { |
| 219 | strs[i] = StringRef(snapshot.snapshot_label().c_str(), |
| 220 | snapshot.snapshot_label().size()); |
| 221 | datas[i] = strs.data() + i; |
| 222 | } else { |
| 223 | datas[i] = nullptr; |
| 224 | } |
| 225 | } |
| 226 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 9, datas)); |
| 227 | } |
| 228 | // reason |
| 229 | { |
| 230 | for (int i = 0; i < row_num; ++i) { |
| 231 | auto& snapshot = _snapshots[i]; |
| 232 | if (snapshot.has_reason()) { |
| 233 | strs[i] = StringRef(snapshot.reason().c_str(), snapshot.reason().size()); |
| 234 | datas[i] = strs.data() + i; |
| 235 | } else { |
| 236 | datas[i] = nullptr; |
| 237 | } |
| 238 | } |
| 239 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 10, datas)); |
| 240 | } |
| 241 | // count |
| 242 | { |
| 243 | std::vector<int32_t> srcs(row_num); |
| 244 | for (int i = 0; i < row_num; ++i) { |
| 245 | srcs[i] = _snapshots[i].derived_instance_ids_size(); |
| 246 | datas[i] = srcs.data() + i; |
| 247 | } |
| 248 | RETURN_IF_ERROR(fill_dest_column_for_range(block, 11, datas)); |
| 249 | } |
| 250 | return Status::OK(); |
| 251 | } |
| 252 | |
| 253 | #include "common/compile_check_end.h" |
| 254 | } // namespace doris |