1use std::collections::{BTreeMap, BTreeSet};
30use std::num::NonZeroUsize;
31use std::str::FromStr;
32use std::time::Duration;
33
34use chrono::{DateTime, Utc};
35use enum_kinds::EnumKind;
36use ipnet::IpNet;
37use maplit::btreeset;
38use mz_adapter_types::compaction::CompactionWindow;
39use mz_controller_types::{ClusterId, ReplicaId};
40use mz_expr::{CollectionPlan, ColumnOrder, MapFilterProject, MirScalarExpr, RowSetFinishing};
41use mz_ore::now::{self, NOW_ZERO};
42use mz_pgcopy::CopyFormatParams;
43use mz_repr::adt::mz_acl_item::{AclMode, MzAclItem};
44use mz_repr::explain::{ExplainConfig, ExplainFormat};
45use mz_repr::network_policy_id::NetworkPolicyId;
46use mz_repr::optimize::OptimizerFeatureOverrides;
47use mz_repr::refresh_schedule::RefreshSchedule;
48use mz_repr::role_id::RoleId;
49use mz_repr::{
50 CatalogItemId, ColumnIndex, ColumnName, Diff, GlobalId, RelationDesc, ReprColumnType, Row,
51 SqlColumnType, SqlRelationType, SqlScalarType, Timestamp, VersionedRelationDesc,
52};
53use mz_sql_parser::ast::{
54 AlterSourceAddSubsourceOption, ClusterAlterOptionValue, ConnectionOptionName, CreateSinkOption,
55 CreateSinkOptionName, QualifiedReplica, RawDataType, SelectStatement,
56 TransactionIsolationLevel, TransactionMode, UnresolvedItemName, Value, WithOptionValue,
57};
58use mz_ssh_util::keys::SshKeyPair;
59use mz_storage_types::connections::aws::AwsConnection;
60use mz_storage_types::connections::gcp::{GcpConnection, GcpServiceAccountKeyTokenUri};
61use mz_storage_types::connections::inline::ReferencedConnection;
62use mz_storage_types::connections::{
63 AwsPrivatelinkConnection, CsrConnection, GlueSchemaRegistryConnection,
64 IcebergCatalogConnection, KafkaConnection, MySqlConnection, PostgresConnection,
65 SqlServerConnectionDetails, SshConnection,
66};
67use mz_storage_types::instances::StorageInstanceId;
68use mz_storage_types::sinks::{S3SinkFormat, SinkEnvelope, StorageSinkConnection};
69use mz_storage_types::sources::{
70 SourceDesc, SourceExportDataConfig, SourceExportDetails, Timeline,
71};
72use proptest_derive::Arbitrary;
73use serde::{Deserialize, Serialize};
74
75use crate::ast::{
76 ExplainStage, Expr, FetchDirection, NoticeSeverity, Raw, Statement, StatementKind,
77 TransactionAccessMode,
78};
79use crate::catalog::{
80 CatalogType, DefaultPrivilegeAclItem, DefaultPrivilegeObject, IdReference, ObjectType,
81 RoleAttributesRaw,
82};
83use crate::names::{
84 Aug, CommentObjectId, DependencyIds, FullItemName, ObjectId, QualifiedItemName,
85 ResolvedDatabaseSpecifier, ResolvedIds, SchemaSpecifier, SystemObjectId,
86};
87
88pub(crate) mod error;
89pub(crate) mod explain;
90pub(crate) mod hir;
91pub(crate) mod literal;
92pub(crate) mod lowering;
93pub(crate) mod notice;
94pub(crate) mod plan_utils;
95pub(crate) mod query;
96pub(crate) mod scope;
97pub(crate) mod side_effecting_func;
98pub(crate) mod statement;
99pub(crate) mod transform_ast;
100pub(crate) mod transform_hir;
101pub(crate) mod typeconv;
102pub(crate) mod with_options;
103
104use crate::plan;
105use crate::plan::statement::ddl::ClusterAlterUntilReadyOptionExtracted;
106use crate::plan::with_options::OptionalDuration;
107pub use error::PlanError;
108pub use explain::normalize_subqueries;
109pub use hir::{
110 AggregateExpr, CoercibleScalarExpr, Hir, HirRelationExpr, HirScalarExpr, JoinKind,
111 WindowExprType,
112};
113pub use lowering::Config as HirToMirConfig;
114pub use notice::PlanNotice;
115pub use query::{ExprContext, QueryContext, QueryLifetime};
116pub use scope::Scope;
117pub use side_effecting_func::SideEffectingFunc;
118pub use statement::ddl::{
119 AlterSourceAddSubsourceOptionExtracted, MySqlConfigOptionExtracted, PgConfigOptionExtracted,
120 PlannedAlterRoleOption, PlannedRoleAttributes, PlannedRoleVariable,
121 SqlServerConfigOptionExtracted,
122};
123pub use statement::{
124 StatementClassification, StatementContext, StatementDesc, describe, plan, plan_copy_from,
125 resolve_cluster_for_materialized_view,
126};
127pub use with_options::TryFromValue;
128
129use self::statement::ddl::ClusterAlterOptionExtracted;
130
131#[derive(Debug, EnumKind)]
133#[enum_kind(PlanKind)]
134pub enum Plan {
135 CreateConnection(CreateConnectionPlan),
136 CreateDatabase(CreateDatabasePlan),
137 CreateSchema(CreateSchemaPlan),
138 CreateRole(CreateRolePlan),
139 CreateCluster(CreateClusterPlan),
140 CreateClusterReplica(CreateClusterReplicaPlan),
141 CreateSource(CreateSourcePlan),
142 CreateSources(Vec<CreateSourcePlanBundle>),
143 CreateSecret(CreateSecretPlan),
144 CreateSink(CreateSinkPlan),
145 CreateTable(CreateTablePlan),
146 CreateView(CreateViewPlan),
147 CreateMaterializedView(CreateMaterializedViewPlan),
148 CreateNetworkPolicy(CreateNetworkPolicyPlan),
149 CreateIndex(CreateIndexPlan),
150 CreateType(CreateTypePlan),
151 Comment(CommentPlan),
152 DiscardTemp,
153 DiscardAll,
154 DropObjects(DropObjectsPlan),
155 DropOwned(DropOwnedPlan),
156 EmptyQuery,
157 ShowAllVariables,
158 ShowCreate(ShowCreatePlan),
159 ShowColumns(ShowColumnsPlan),
160 ShowVariable(ShowVariablePlan),
161 InspectShard(InspectShardPlan),
162 SetVariable(SetVariablePlan),
163 ResetVariable(ResetVariablePlan),
164 SetTransaction(SetTransactionPlan),
165 StartTransaction(StartTransactionPlan),
166 CommitTransaction(CommitTransactionPlan),
167 AbortTransaction(AbortTransactionPlan),
168 Select(SelectPlan),
169 Subscribe(SubscribePlan),
170 CopyFrom(CopyFromPlan),
171 CopyTo(CopyToPlan),
172 ExplainPlan(ExplainPlanPlan),
173 ExplainPushdown(ExplainPushdownPlan),
174 ExplainTimestamp(ExplainTimestampPlan),
175 ExplainSinkSchema(ExplainSinkSchemaPlan),
176 Insert(InsertPlan),
177 AlterCluster(AlterClusterPlan),
178 AlterClusterSwap(AlterClusterSwapPlan),
179 AlterNoop(AlterNoopPlan),
180 AlterSetCluster(AlterSetClusterPlan),
181 AlterConnection(AlterConnectionPlan),
182 AlterSource(AlterSourcePlan),
183 AlterClusterRename(AlterClusterRenamePlan),
184 AlterClusterReplicaRename(AlterClusterReplicaRenamePlan),
185 AlterItemRename(AlterItemRenamePlan),
186 AlterSchemaRename(AlterSchemaRenamePlan),
187 AlterSchemaSwap(AlterSchemaSwapPlan),
188 AlterSecret(AlterSecretPlan),
189 AlterSink(AlterSinkPlan),
190 AlterSystemSet(AlterSystemSetPlan),
191 AlterSystemReset(AlterSystemResetPlan),
192 AlterSystemResetAll(AlterSystemResetAllPlan),
193 AlterRole(AlterRolePlan),
194 AlterOwner(AlterOwnerPlan),
195 AlterTableAddColumn(AlterTablePlan),
196 AlterMaterializedViewApplyReplacement(AlterMaterializedViewApplyReplacementPlan),
197 AlterNetworkPolicy(AlterNetworkPolicyPlan),
198 Declare(DeclarePlan),
199 Fetch(FetchPlan),
200 Close(ClosePlan),
201 ReadThenWrite(ReadThenWritePlan),
202 Prepare(PreparePlan),
203 Execute(ExecutePlan),
204 Deallocate(DeallocatePlan),
205 Raise(RaisePlan),
206 GrantRole(GrantRolePlan),
207 RevokeRole(RevokeRolePlan),
208 GrantPrivileges(GrantPrivilegesPlan),
209 RevokePrivileges(RevokePrivilegesPlan),
210 AlterDefaultPrivileges(AlterDefaultPrivilegesPlan),
211 ReassignOwned(ReassignOwnedPlan),
212 SideEffectingFunc(SideEffectingFunc),
213 ValidateConnection(ValidateConnectionPlan),
214 AlterRetainHistory(AlterRetainHistoryPlan),
215 AlterSourceTimestampInterval(AlterSourceTimestampIntervalPlan),
216}
217
218impl Plan {
219 pub fn generated_from(stmt: &StatementKind) -> &'static [PlanKind] {
222 match stmt {
223 StatementKind::AlterCluster => &[PlanKind::AlterNoop, PlanKind::AlterCluster],
224 StatementKind::AlterConnection => &[PlanKind::AlterNoop, PlanKind::AlterConnection],
225 StatementKind::AlterDefaultPrivileges => &[PlanKind::AlterDefaultPrivileges],
226 StatementKind::AlterIndex => &[PlanKind::AlterRetainHistory, PlanKind::AlterNoop],
227 StatementKind::AlterObjectRename => &[
228 PlanKind::AlterClusterRename,
229 PlanKind::AlterClusterReplicaRename,
230 PlanKind::AlterItemRename,
231 PlanKind::AlterSchemaRename,
232 PlanKind::AlterNoop,
233 ],
234 StatementKind::AlterObjectSwap => &[
235 PlanKind::AlterClusterSwap,
236 PlanKind::AlterSchemaSwap,
237 PlanKind::AlterNoop,
238 ],
239 StatementKind::AlterRole => &[PlanKind::AlterRole],
240 StatementKind::AlterNetworkPolicy => &[PlanKind::AlterNetworkPolicy],
241 StatementKind::AlterSecret => &[PlanKind::AlterNoop, PlanKind::AlterSecret],
242 StatementKind::AlterSetCluster => &[PlanKind::AlterNoop, PlanKind::AlterSetCluster],
243 StatementKind::AlterSink => &[PlanKind::AlterNoop, PlanKind::AlterSink],
244 StatementKind::AlterSource => &[
245 PlanKind::AlterNoop,
246 PlanKind::AlterSource,
247 PlanKind::AlterRetainHistory,
248 PlanKind::AlterSourceTimestampInterval,
249 ],
250 StatementKind::AlterSystemReset => &[PlanKind::AlterNoop, PlanKind::AlterSystemReset],
251 StatementKind::AlterSystemResetAll => {
252 &[PlanKind::AlterNoop, PlanKind::AlterSystemResetAll]
253 }
254 StatementKind::AlterSystemSet => &[PlanKind::AlterNoop, PlanKind::AlterSystemSet],
255 StatementKind::AlterOwner => &[PlanKind::AlterNoop, PlanKind::AlterOwner],
256 StatementKind::AlterTableAddColumn => {
257 &[PlanKind::AlterNoop, PlanKind::AlterTableAddColumn]
258 }
259 StatementKind::AlterMaterializedViewApplyReplacement => &[
260 PlanKind::AlterNoop,
261 PlanKind::AlterMaterializedViewApplyReplacement,
262 ],
263 StatementKind::Close => &[PlanKind::Close],
264 StatementKind::Comment => &[PlanKind::Comment],
265 StatementKind::Commit => &[PlanKind::CommitTransaction],
266 StatementKind::Copy => &[
267 PlanKind::CopyFrom,
268 PlanKind::Select,
269 PlanKind::Subscribe,
270 PlanKind::CopyTo,
271 ],
272 StatementKind::CreateCluster => &[PlanKind::CreateCluster],
273 StatementKind::CreateClusterReplica => &[PlanKind::CreateClusterReplica],
274 StatementKind::CreateConnection => &[PlanKind::CreateConnection],
275 StatementKind::CreateDatabase => &[PlanKind::CreateDatabase],
276 StatementKind::CreateIndex => &[PlanKind::CreateIndex],
277 StatementKind::CreateNetworkPolicy => &[PlanKind::CreateNetworkPolicy],
278 StatementKind::CreateMaterializedView => &[PlanKind::CreateMaterializedView],
279 StatementKind::CreateRole => &[PlanKind::CreateRole],
280 StatementKind::CreateSchema => &[PlanKind::CreateSchema],
281 StatementKind::CreateSecret => &[PlanKind::CreateSecret],
282 StatementKind::CreateSink => &[PlanKind::CreateSink],
283 StatementKind::CreateSource | StatementKind::CreateSubsource => {
284 &[PlanKind::CreateSource]
285 }
286 StatementKind::CreateWebhookSource => &[PlanKind::CreateSource, PlanKind::CreateTable],
287 StatementKind::CreateTable => &[PlanKind::CreateTable],
288 StatementKind::CreateTableFromSource => &[PlanKind::CreateTable],
289 StatementKind::CreateType => &[PlanKind::CreateType],
290 StatementKind::CreateView => &[PlanKind::CreateView],
291 StatementKind::Deallocate => &[PlanKind::Deallocate],
292 StatementKind::Declare => &[PlanKind::Declare],
293 StatementKind::Delete => &[PlanKind::ReadThenWrite],
294 StatementKind::Discard => &[PlanKind::DiscardAll, PlanKind::DiscardTemp],
295 StatementKind::DropObjects => &[PlanKind::DropObjects],
296 StatementKind::DropOwned => &[PlanKind::DropOwned],
297 StatementKind::Execute => &[PlanKind::Execute],
298 StatementKind::ExplainPlan => &[PlanKind::ExplainPlan],
299 StatementKind::ExplainPushdown => &[PlanKind::ExplainPushdown],
300 StatementKind::ExplainAnalyzeObject => &[PlanKind::Select],
301 StatementKind::ExplainAnalyzeCluster => &[PlanKind::Select],
302 StatementKind::ExplainTimestamp => &[PlanKind::ExplainTimestamp],
303 StatementKind::ExplainSinkSchema => &[PlanKind::ExplainSinkSchema],
304 StatementKind::Fetch => &[PlanKind::Fetch],
305 StatementKind::GrantPrivileges => &[PlanKind::GrantPrivileges],
306 StatementKind::GrantRole => &[PlanKind::GrantRole],
307 StatementKind::Insert => &[PlanKind::Insert],
308 StatementKind::Prepare => &[PlanKind::Prepare],
309 StatementKind::Raise => &[PlanKind::Raise],
310 StatementKind::ReassignOwned => &[PlanKind::ReassignOwned],
311 StatementKind::ResetVariable => &[PlanKind::ResetVariable],
312 StatementKind::RevokePrivileges => &[PlanKind::RevokePrivileges],
313 StatementKind::RevokeRole => &[PlanKind::RevokeRole],
314 StatementKind::Rollback => &[PlanKind::AbortTransaction],
315 StatementKind::Select => &[PlanKind::Select, PlanKind::SideEffectingFunc],
316 StatementKind::SetTransaction => &[PlanKind::SetTransaction],
317 StatementKind::SetVariable => &[PlanKind::SetVariable],
318 StatementKind::Show => &[
319 PlanKind::Select,
320 PlanKind::ShowVariable,
321 PlanKind::ShowCreate,
322 PlanKind::ShowColumns,
323 PlanKind::ShowAllVariables,
324 PlanKind::InspectShard,
325 ],
326 StatementKind::StartTransaction => &[PlanKind::StartTransaction],
327 StatementKind::Subscribe => &[PlanKind::Subscribe],
328 StatementKind::Update => &[PlanKind::ReadThenWrite],
329 StatementKind::ValidateConnection => &[PlanKind::ValidateConnection],
330 StatementKind::AlterRetainHistory => &[PlanKind::AlterRetainHistory],
331 StatementKind::ExecuteUnitTest => &[],
332 }
333 }
334
335 pub fn name(&self) -> &str {
337 match self {
338 Plan::CreateConnection(_) => "create connection",
339 Plan::CreateDatabase(_) => "create database",
340 Plan::CreateSchema(_) => "create schema",
341 Plan::CreateRole(_) => "create role",
342 Plan::CreateCluster(_) => "create cluster",
343 Plan::CreateClusterReplica(_) => "create cluster replica",
344 Plan::CreateSource(_) => "create source",
345 Plan::CreateSources(_) => "create source",
346 Plan::CreateSecret(_) => "create secret",
347 Plan::CreateSink(_) => "create sink",
348 Plan::CreateTable(_) => "create table",
349 Plan::CreateView(_) => "create view",
350 Plan::CreateMaterializedView(_) => "create materialized view",
351 Plan::CreateIndex(_) => "create index",
352 Plan::CreateType(_) => "create type",
353 Plan::CreateNetworkPolicy(_) => "create network policy",
354 Plan::Comment(_) => "comment",
355 Plan::DiscardTemp => "discard temp",
356 Plan::DiscardAll => "discard all",
357 Plan::DropObjects(plan) => match plan.object_type {
358 ObjectType::Table => "drop table",
359 ObjectType::View => "drop view",
360 ObjectType::MaterializedView => "drop materialized view",
361 ObjectType::Source => "drop source",
362 ObjectType::Sink => "drop sink",
363 ObjectType::Index => "drop index",
364 ObjectType::Type => "drop type",
365 ObjectType::Role => "drop roles",
366 ObjectType::Cluster => "drop clusters",
367 ObjectType::ClusterReplica => "drop cluster replicas",
368 ObjectType::Secret => "drop secret",
369 ObjectType::Connection => "drop connection",
370 ObjectType::Database => "drop database",
371 ObjectType::Schema => "drop schema",
372 ObjectType::Func => "drop function",
373 ObjectType::NetworkPolicy => "drop network policy",
374 },
375 Plan::DropOwned(_) => "drop owned",
376 Plan::EmptyQuery => "do nothing",
377 Plan::ShowAllVariables => "show all variables",
378 Plan::ShowCreate(_) => "show create",
379 Plan::ShowColumns(_) => "show columns",
380 Plan::ShowVariable(_) => "show variable",
381 Plan::InspectShard(_) => "inspect shard",
382 Plan::SetVariable(_) => "set variable",
383 Plan::ResetVariable(_) => "reset variable",
384 Plan::SetTransaction(_) => "set transaction",
385 Plan::StartTransaction(_) => "start transaction",
386 Plan::CommitTransaction(_) => "commit",
387 Plan::AbortTransaction(_) => "abort",
388 Plan::Select(_) => "select",
389 Plan::Subscribe(_) => "subscribe",
390 Plan::CopyFrom(_) => "copy from",
391 Plan::CopyTo(_) => "copy to",
392 Plan::ExplainPlan(_) => "explain plan",
393 Plan::ExplainPushdown(_) => "EXPLAIN FILTER PUSHDOWN",
394 Plan::ExplainTimestamp(_) => "explain timestamp",
395 Plan::ExplainSinkSchema(_) => "explain schema",
396 Plan::Insert(_) => "insert",
397 Plan::AlterNoop(plan) => match plan.object_type {
398 ObjectType::Table => "alter table",
399 ObjectType::View => "alter view",
400 ObjectType::MaterializedView => "alter materialized view",
401 ObjectType::Source => "alter source",
402 ObjectType::Sink => "alter sink",
403 ObjectType::Index => "alter index",
404 ObjectType::Type => "alter type",
405 ObjectType::Role => "alter role",
406 ObjectType::Cluster => "alter cluster",
407 ObjectType::ClusterReplica => "alter cluster replica",
408 ObjectType::Secret => "alter secret",
409 ObjectType::Connection => "alter connection",
410 ObjectType::Database => "alter database",
411 ObjectType::Schema => "alter schema",
412 ObjectType::Func => "alter function",
413 ObjectType::NetworkPolicy => "alter network policy",
414 },
415 Plan::AlterCluster(_) => "alter cluster",
416 Plan::AlterClusterRename(_) => "alter cluster rename",
417 Plan::AlterClusterSwap(_) => "alter cluster swap",
418 Plan::AlterClusterReplicaRename(_) => "alter cluster replica rename",
419 Plan::AlterSetCluster(_) => "alter set cluster",
420 Plan::AlterConnection(_) => "alter connection",
421 Plan::AlterSource(_) => "alter source",
422 Plan::AlterItemRename(_) => "rename item",
423 Plan::AlterSchemaRename(_) => "alter rename schema",
424 Plan::AlterSchemaSwap(_) => "alter swap schema",
425 Plan::AlterSecret(_) => "alter secret",
426 Plan::AlterSink(_) => "alter sink",
427 Plan::AlterSystemSet(_) => "alter system",
428 Plan::AlterSystemReset(_) => "alter system",
429 Plan::AlterSystemResetAll(_) => "alter system",
430 Plan::AlterRole(_) => "alter role",
431 Plan::AlterNetworkPolicy(_) => "alter network policy",
432 Plan::AlterOwner(plan) => match plan.object_type {
433 ObjectType::Table => "alter table owner",
434 ObjectType::View => "alter view owner",
435 ObjectType::MaterializedView => "alter materialized view owner",
436 ObjectType::Source => "alter source owner",
437 ObjectType::Sink => "alter sink owner",
438 ObjectType::Index => "alter index owner",
439 ObjectType::Type => "alter type owner",
440 ObjectType::Role => "alter role owner",
441 ObjectType::Cluster => "alter cluster owner",
442 ObjectType::ClusterReplica => "alter cluster replica owner",
443 ObjectType::Secret => "alter secret owner",
444 ObjectType::Connection => "alter connection owner",
445 ObjectType::Database => "alter database owner",
446 ObjectType::Schema => "alter schema owner",
447 ObjectType::Func => "alter function owner",
448 ObjectType::NetworkPolicy => "alter network policy owner",
449 },
450 Plan::AlterTableAddColumn(_) => "alter table add column",
451 Plan::AlterMaterializedViewApplyReplacement(_) => {
452 "alter materialized view apply replacement"
453 }
454 Plan::Declare(_) => "declare",
455 Plan::Fetch(_) => "fetch",
456 Plan::Close(_) => "close",
457 Plan::ReadThenWrite(plan) => match plan.kind {
458 MutationKind::Insert => "insert into select",
459 MutationKind::Update => "update",
460 MutationKind::Delete => "delete",
461 },
462 Plan::Prepare(_) => "prepare",
463 Plan::Execute(_) => "execute",
464 Plan::Deallocate(_) => "deallocate",
465 Plan::Raise(_) => "raise",
466 Plan::GrantRole(_) => "grant role",
467 Plan::RevokeRole(_) => "revoke role",
468 Plan::GrantPrivileges(_) => "grant privilege",
469 Plan::RevokePrivileges(_) => "revoke privilege",
470 Plan::AlterDefaultPrivileges(_) => "alter default privileges",
471 Plan::ReassignOwned(_) => "reassign owned",
472 Plan::SideEffectingFunc(_) => "side effecting func",
473 Plan::ValidateConnection(_) => "validate connection",
474 Plan::AlterRetainHistory(_) => "alter retain history",
475 Plan::AlterSourceTimestampInterval(_) => "alter source timestamp interval",
476 }
477 }
478
479 pub fn allowed_in_read_only(&self) -> bool {
485 match self {
486 Plan::SetVariable(_) => true,
489 Plan::ResetVariable(_) => true,
490 Plan::SetTransaction(_) => true,
491 Plan::StartTransaction(_) => true,
492 Plan::CommitTransaction(_) => true,
493 Plan::AbortTransaction(_) => true,
494 Plan::Select(_) => true,
495 Plan::EmptyQuery => true,
496 Plan::ShowAllVariables => true,
497 Plan::ShowCreate(_) => true,
498 Plan::ShowColumns(_) => true,
499 Plan::ShowVariable(_) => true,
500 Plan::InspectShard(_) => true,
501 Plan::Subscribe(_) => true,
502 Plan::CopyTo(_) => true,
503 Plan::ExplainPlan(_) => true,
504 Plan::ExplainPushdown(_) => true,
505 Plan::ExplainTimestamp(_) => true,
506 Plan::ExplainSinkSchema(_) => true,
507 Plan::ValidateConnection(_) => true,
508 _ => false,
509 }
510 }
511}
512
513#[derive(Debug)]
514pub struct StartTransactionPlan {
515 pub access: Option<TransactionAccessMode>,
516 pub isolation_level: Option<TransactionIsolationLevel>,
517}
518
519#[derive(Debug)]
520pub enum TransactionType {
521 Explicit,
522 Implicit,
523}
524
525impl TransactionType {
526 pub fn is_explicit(&self) -> bool {
527 matches!(self, TransactionType::Explicit)
528 }
529
530 pub fn is_implicit(&self) -> bool {
531 matches!(self, TransactionType::Implicit)
532 }
533}
534
535#[derive(Debug)]
536pub struct CommitTransactionPlan {
537 pub transaction_type: TransactionType,
538}
539
540#[derive(Debug)]
541pub struct AbortTransactionPlan {
542 pub transaction_type: TransactionType,
543}
544
545#[derive(Debug)]
546pub struct CreateDatabasePlan {
547 pub name: String,
548 pub if_not_exists: bool,
549}
550
551#[derive(Debug)]
552pub struct CreateSchemaPlan {
553 pub database_spec: ResolvedDatabaseSpecifier,
554 pub schema_name: String,
555 pub if_not_exists: bool,
556}
557
558#[derive(Debug)]
559pub struct CreateRolePlan {
560 pub name: String,
561 pub attributes: RoleAttributesRaw,
562}
563
564#[derive(Debug, PartialEq, Eq, Clone)]
565pub struct CreateClusterPlan {
566 pub name: String,
567 pub variant: CreateClusterVariant,
568 pub workload_class: Option<String>,
569}
570
571#[derive(Debug, PartialEq, Eq, Clone)]
572pub enum CreateClusterVariant {
573 Managed(CreateClusterManagedPlan),
574 Unmanaged(CreateClusterUnmanagedPlan),
575}
576
577#[derive(Debug, PartialEq, Eq, Clone)]
578pub struct CreateClusterUnmanagedPlan {
579 pub replicas: Vec<(String, ReplicaConfig)>,
580}
581
582#[derive(Debug, PartialEq, Eq, Clone)]
583pub struct CreateClusterManagedPlan {
584 pub replication_factor: u32,
585 pub size: String,
586 pub availability_zones: Vec<String>,
587 pub compute: ComputeReplicaConfig,
588 pub optimizer_feature_overrides: OptimizerFeatureOverrides,
589 pub schedule: ClusterSchedule,
590}
591
592#[derive(Debug)]
593pub struct CreateClusterReplicaPlan {
594 pub cluster_id: ClusterId,
595 pub name: String,
596 pub config: ReplicaConfig,
597}
598
599#[derive(
601 Clone,
602 Copy,
603 Debug,
604 Serialize,
605 Deserialize,
606 PartialOrd,
607 Ord,
608 PartialEq,
609 Eq
610)]
611pub struct ComputeReplicaIntrospectionConfig {
612 pub debugging: bool,
614 pub interval: Duration,
616}
617
618#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
619pub struct ComputeReplicaConfig {
620 pub introspection: Option<ComputeReplicaIntrospectionConfig>,
621}
622
623#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
624pub enum ReplicaConfig {
625 Unorchestrated {
626 storagectl_addrs: Vec<String>,
627 computectl_addrs: Vec<String>,
628 compute: ComputeReplicaConfig,
629 },
630 Orchestrated {
631 size: String,
632 availability_zone: Option<String>,
633 compute: ComputeReplicaConfig,
634 internal: bool,
635 billed_as: Option<String>,
636 },
637}
638
639#[derive(Clone, Debug, Deserialize, Serialize, PartialOrd, PartialEq, Eq, Ord)]
640pub enum ClusterSchedule {
641 Manual,
643 Refresh { hydration_time_estimate: Duration },
647}
648
649impl Default for ClusterSchedule {
650 fn default() -> Self {
651 ClusterSchedule::Manual
653 }
654}
655
656#[derive(Clone, Debug, Deserialize, Serialize, PartialOrd, PartialEq, Eq, Ord)]
661pub struct AutoScalingStrategy {
662 pub on_hydration: Option<OnHydration>,
663}
664
665#[derive(Clone, Debug, Deserialize, Serialize, PartialOrd, PartialEq, Eq, Ord)]
668pub struct OnHydration {
669 pub hydration_size: String,
670 pub linger_duration: Option<Duration>,
673}
674
675#[derive(Debug)]
676pub struct CreateSourcePlan {
677 pub name: QualifiedItemName,
678 pub source: Source,
679 pub if_not_exists: bool,
680 pub timeline: Timeline,
681 pub in_cluster: Option<ClusterId>,
683}
684
685#[derive(Clone, Debug, PartialEq, Eq)]
686pub struct SourceReferences {
687 pub updated_at: u64,
688 pub references: Vec<SourceReference>,
689}
690
691#[derive(Clone, Debug, PartialEq, Eq)]
694pub struct SourceReference {
695 pub name: String,
696 pub namespace: Option<String>,
697 pub columns: Vec<String>,
698}
699
700#[derive(Debug)]
702pub struct CreateSourcePlanBundle {
703 pub item_id: CatalogItemId,
705 pub global_id: GlobalId,
707 pub plan: CreateSourcePlan,
709 pub resolved_ids: ResolvedIds,
711 pub available_source_references: Option<SourceReferences>,
715}
716
717#[derive(Debug)]
718pub struct CreateConnectionPlan {
719 pub name: QualifiedItemName,
720 pub if_not_exists: bool,
721 pub connection: Connection,
722 pub validate: bool,
723}
724
725#[derive(Debug)]
726pub struct ValidateConnectionPlan {
727 pub id: CatalogItemId,
729 pub connection: mz_storage_types::connections::Connection<ReferencedConnection>,
731}
732
733#[derive(Debug)]
734pub struct CreateSecretPlan {
735 pub name: QualifiedItemName,
736 pub secret: Secret,
737 pub if_not_exists: bool,
738}
739
740#[derive(Debug)]
741pub struct CreateSinkPlan {
742 pub name: QualifiedItemName,
743 pub sink: Sink,
744 pub with_snapshot: bool,
745 pub if_not_exists: bool,
746 pub in_cluster: ClusterId,
747}
748
749#[derive(Debug)]
750pub struct CreateTablePlan {
751 pub name: QualifiedItemName,
752 pub table: Table,
753 pub if_not_exists: bool,
754}
755
756#[derive(Debug, Clone)]
757pub struct CreateViewPlan {
758 pub name: QualifiedItemName,
759 pub view: View,
760 pub replace: Option<CatalogItemId>,
762 pub drop_ids: Vec<CatalogItemId>,
764 pub if_not_exists: bool,
765 pub ambiguous_columns: bool,
768}
769
770#[derive(Debug, Clone)]
771pub struct CreateMaterializedViewPlan {
772 pub name: QualifiedItemName,
773 pub materialized_view: MaterializedView,
774 pub replace: Option<CatalogItemId>,
776 pub drop_ids: Vec<CatalogItemId>,
778 pub if_not_exists: bool,
779 pub ambiguous_columns: bool,
782}
783
784#[derive(Debug, Clone)]
785pub struct CreateNetworkPolicyPlan {
786 pub name: String,
787 pub rules: Vec<NetworkPolicyRule>,
788}
789
790#[derive(Debug, Clone)]
791pub struct AlterNetworkPolicyPlan {
792 pub id: NetworkPolicyId,
793 pub name: String,
794 pub rules: Vec<NetworkPolicyRule>,
795}
796
797#[derive(Debug, Clone)]
798pub struct CreateIndexPlan {
799 pub name: QualifiedItemName,
800 pub index: Index,
801 pub if_not_exists: bool,
802}
803
804#[derive(Debug)]
805pub struct CreateTypePlan {
806 pub name: QualifiedItemName,
807 pub typ: Type,
808}
809
810#[derive(Debug)]
811pub struct DropObjectsPlan {
812 pub referenced_ids: Vec<ObjectId>,
814 pub drop_ids: Vec<ObjectId>,
816 pub object_type: ObjectType,
819}
820
821#[derive(Debug)]
822pub struct DropOwnedPlan {
823 pub role_ids: Vec<RoleId>,
825 pub drop_ids: Vec<ObjectId>,
827 pub privilege_revokes: Vec<(SystemObjectId, MzAclItem)>,
829 pub default_privilege_revokes: Vec<(DefaultPrivilegeObject, DefaultPrivilegeAclItem)>,
831}
832
833#[derive(Debug)]
834pub struct ShowVariablePlan {
835 pub name: String,
836}
837
838#[derive(Debug)]
839pub struct InspectShardPlan {
840 pub id: GlobalId,
842}
843
844#[derive(Debug)]
845pub struct SetVariablePlan {
846 pub name: String,
847 pub value: VariableValue,
848 pub local: bool,
849}
850
851#[derive(Debug)]
852pub enum VariableValue {
853 Default,
854 Values(Vec<String>),
855}
856
857#[derive(Debug)]
858pub struct ResetVariablePlan {
859 pub name: String,
860}
861
862#[derive(Debug)]
863pub struct SetTransactionPlan {
864 pub local: bool,
865 pub modes: Vec<TransactionMode>,
866}
867
868#[derive(Clone, Debug)]
870pub struct SelectPlan {
871 pub select: Option<Box<SelectStatement<Aug>>>,
874 pub source: HirRelationExpr,
876 pub when: QueryWhen,
878 pub finishing: RowSetFinishing,
880 pub copy_to: Option<CopyFormat>,
882}
883
884impl SelectPlan {
885 pub fn immediate(rows: Vec<Row>, typ: SqlRelationType) -> Self {
886 let arity = typ.arity();
887 SelectPlan {
888 select: None,
889 source: HirRelationExpr::Constant { rows, typ },
890 when: QueryWhen::Immediately,
891 finishing: RowSetFinishing::trivial(arity),
892 copy_to: None,
893 }
894 }
895}
896
897#[derive(Debug, Clone)]
898pub enum SubscribeOutput {
899 Diffs,
900 WithinTimestampOrderBy {
901 order_by: Vec<ColumnOrder>,
903 },
904 EnvelopeUpsert {
905 order_by_keys: Vec<ColumnOrder>,
907 },
908 EnvelopeDebezium {
909 order_by_keys: Vec<ColumnOrder>,
911 },
912}
913
914impl SubscribeOutput {
915 pub fn row_order(&self) -> &[ColumnOrder] {
916 match self {
917 SubscribeOutput::Diffs => &[],
918 SubscribeOutput::WithinTimestampOrderBy { .. } => &[],
920 SubscribeOutput::EnvelopeUpsert { order_by_keys } => order_by_keys,
921 SubscribeOutput::EnvelopeDebezium { order_by_keys } => order_by_keys,
922 }
923 }
924}
925
926#[derive(Debug, Clone)]
927pub struct SubscribePlan {
928 pub from: SubscribeFrom,
929 pub with_snapshot: bool,
930 pub when: QueryWhen,
931 pub up_to: Option<Timestamp>,
932 pub copy_to: Option<CopyFormat>,
933 pub emit_progress: bool,
934 pub output: SubscribeOutput,
935}
936
937#[derive(Debug, Clone)]
938pub enum SubscribeFrom {
939 Id(GlobalId),
941 Query {
943 expr: HirRelationExpr,
944 desc: RelationDesc,
945 },
946}
947
948impl SubscribeFrom {
949 pub fn depends_on(&self) -> BTreeSet<GlobalId> {
950 match self {
951 SubscribeFrom::Id(id) => BTreeSet::from([*id]),
952 SubscribeFrom::Query { expr, .. } => expr.depends_on(),
953 }
954 }
955
956 pub fn contains_temporal(&self) -> bool {
957 match self {
958 SubscribeFrom::Id(_) => false,
959 SubscribeFrom::Query { expr, .. } => expr.contains_temporal(),
960 }
961 }
962}
963
964#[derive(Debug)]
965pub struct ShowCreatePlan {
966 pub id: ObjectId,
967 pub row: Row,
968}
969
970#[derive(Debug)]
971pub struct ShowColumnsPlan {
972 pub id: CatalogItemId,
973 pub select_plan: SelectPlan,
974 pub new_resolved_ids: ResolvedIds,
975}
976
977#[derive(Debug)]
978pub struct CopyFromPlan {
979 pub target_id: CatalogItemId,
981 pub target_name: String,
983 pub source: CopyFromSource,
985 pub columns: Vec<ColumnIndex>,
989 pub source_desc: RelationDesc,
991 pub mfp: MapFilterProject,
993 pub params: CopyFormatParams<'static>,
995 pub filter: Option<CopyFromFilter>,
997}
998
999#[derive(Debug)]
1000pub enum CopyFromSource {
1001 Stdin,
1003 Url(HirScalarExpr),
1007 AwsS3 {
1009 uri: HirScalarExpr,
1011 connection: AwsConnection,
1013 connection_id: CatalogItemId,
1015 },
1016}
1017
1018#[derive(Debug)]
1019pub enum CopyFromFilter {
1020 Files(Vec<String>),
1021 Pattern(String),
1022}
1023
1024#[derive(Debug, Clone)]
1029pub struct CopyToPlan {
1030 pub select_plan: SelectPlan,
1032 pub desc: RelationDesc,
1033 pub to: HirScalarExpr,
1035 pub connection: mz_storage_types::connections::Connection<ReferencedConnection>,
1036 pub connection_id: CatalogItemId,
1038 pub format: S3SinkFormat,
1039 pub max_file_size: u64,
1040}
1041
1042#[derive(Clone, Debug)]
1043pub struct ExplainPlanPlan {
1044 pub stage: ExplainStage,
1045 pub format: ExplainFormat,
1046 pub config: ExplainConfig,
1047 pub explainee: Explainee,
1048}
1049
1050#[derive(Clone, Debug)]
1052pub enum Explainee {
1053 View(CatalogItemId),
1055 MaterializedView(CatalogItemId),
1057 Index(CatalogItemId),
1059 ReplanView(CatalogItemId),
1061 ReplanMaterializedView(CatalogItemId),
1063 ReplanIndex(CatalogItemId),
1065 Statement(ExplaineeStatement),
1067}
1068
1069#[derive(Clone, Debug, EnumKind)]
1071#[enum_kind(ExplaineeStatementKind)]
1072pub enum ExplaineeStatement {
1073 Select {
1075 broken: bool,
1077 plan: plan::SelectPlan,
1078 desc: RelationDesc,
1079 },
1080 CreateView {
1082 broken: bool,
1084 plan: plan::CreateViewPlan,
1085 },
1086 CreateMaterializedView {
1088 broken: bool,
1090 plan: plan::CreateMaterializedViewPlan,
1091 },
1092 CreateIndex {
1094 broken: bool,
1096 plan: plan::CreateIndexPlan,
1097 },
1098 Subscribe {
1100 broken: bool,
1102 plan: plan::SubscribePlan,
1103 },
1104}
1105
1106impl ExplaineeStatement {
1107 pub fn depends_on(&self) -> BTreeSet<GlobalId> {
1108 match self {
1109 Self::Select { plan, .. } => plan.source.depends_on(),
1110 Self::CreateView { plan, .. } => plan.view.expr.depends_on(),
1111 Self::CreateMaterializedView { plan, .. } => plan.materialized_view.expr.depends_on(),
1112 Self::CreateIndex { plan, .. } => btreeset! {plan.index.on},
1113 Self::Subscribe { plan, .. } => plan.from.depends_on(),
1114 }
1115 }
1116
1117 pub fn broken(&self) -> bool {
1128 match self {
1129 Self::Select { broken, .. } => *broken,
1130 Self::CreateView { broken, .. } => *broken,
1131 Self::CreateMaterializedView { broken, .. } => *broken,
1132 Self::CreateIndex { broken, .. } => *broken,
1133 Self::Subscribe { broken, .. } => *broken,
1134 }
1135 }
1136}
1137
1138impl ExplaineeStatementKind {
1139 pub fn supports(&self, stage: &ExplainStage) -> bool {
1140 use ExplainStage::*;
1141 match self {
1142 Self::Select => true,
1143 Self::CreateView => ![GlobalPlan, PhysicalPlan].contains(stage),
1144 Self::CreateMaterializedView => true,
1145 Self::CreateIndex => ![RawPlan, DecorrelatedPlan, LocalPlan].contains(stage),
1146 Self::Subscribe => ![RawPlan, DecorrelatedPlan, LocalPlan].contains(stage),
1149 }
1150 }
1151}
1152
1153impl std::fmt::Display for ExplaineeStatementKind {
1154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1155 match self {
1156 Self::Select => write!(f, "SELECT"),
1157 Self::CreateView => write!(f, "CREATE VIEW"),
1158 Self::CreateMaterializedView => write!(f, "CREATE MATERIALIZED VIEW"),
1159 Self::CreateIndex => write!(f, "CREATE INDEX"),
1160 Self::Subscribe => write!(f, "SUBSCRIBE"),
1161 }
1162 }
1163}
1164
1165#[derive(Clone, Debug)]
1166pub struct ExplainPushdownPlan {
1167 pub explainee: Explainee,
1168}
1169
1170#[derive(Clone, Debug)]
1171pub struct ExplainTimestampPlan {
1172 pub format: ExplainFormat,
1173 pub raw_plan: HirRelationExpr,
1174 pub when: QueryWhen,
1175}
1176
1177#[derive(Debug)]
1178pub struct ExplainSinkSchemaPlan {
1179 pub sink_from: GlobalId,
1180 pub json_schema: String,
1181}
1182
1183#[derive(Debug)]
1184pub struct SendDiffsPlan {
1185 pub id: CatalogItemId,
1186 pub updates: Vec<(Row, Diff)>,
1187 pub kind: MutationKind,
1188 pub returning: Vec<(Row, NonZeroUsize)>,
1189 pub max_result_size: u64,
1190}
1191
1192#[derive(Debug)]
1193pub struct InsertPlan {
1194 pub id: CatalogItemId,
1195 pub values: HirRelationExpr,
1196 pub returning: Vec<mz_expr::MirScalarExpr>,
1197}
1198
1199#[derive(Debug)]
1200pub struct ReadThenWritePlan {
1201 pub id: CatalogItemId,
1202 pub selection: HirRelationExpr,
1203 pub finishing: RowSetFinishing,
1204 pub assignments: BTreeMap<usize, mz_expr::MirScalarExpr>,
1205 pub kind: MutationKind,
1206 pub returning: Vec<mz_expr::MirScalarExpr>,
1207}
1208
1209#[derive(Debug)]
1211pub struct AlterNoopPlan {
1212 pub object_type: ObjectType,
1213}
1214
1215#[derive(Debug)]
1216pub struct AlterSetClusterPlan {
1217 pub id: CatalogItemId,
1218 pub set_cluster: ClusterId,
1219}
1220
1221#[derive(Debug)]
1222pub struct AlterRetainHistoryPlan {
1223 pub id: CatalogItemId,
1224 pub value: Option<Value>,
1225 pub window: CompactionWindow,
1226 pub object_type: ObjectType,
1227}
1228
1229#[derive(Debug)]
1230pub struct AlterSourceTimestampIntervalPlan {
1231 pub id: CatalogItemId,
1232 pub value: Option<Value>,
1233 pub interval: Duration,
1234}
1235
1236#[derive(Debug, Clone)]
1237
1238pub enum AlterOptionParameter<T = String> {
1239 Set(T),
1240 Reset,
1241 Unchanged,
1242}
1243
1244#[derive(Debug)]
1245pub enum AlterConnectionAction {
1246 RotateKeys,
1247 AlterOptions {
1248 set_options: BTreeMap<ConnectionOptionName, Option<WithOptionValue<Aug>>>,
1249 drop_options: BTreeSet<ConnectionOptionName>,
1250 validate: bool,
1251 },
1252}
1253
1254#[derive(Debug)]
1255pub struct AlterConnectionPlan {
1256 pub id: CatalogItemId,
1257 pub action: AlterConnectionAction,
1258}
1259
1260#[derive(Debug)]
1261pub enum AlterSourceAction {
1262 AddSubsourceExports {
1263 subsources: Vec<CreateSourcePlanBundle>,
1264 options: Vec<AlterSourceAddSubsourceOption<Aug>>,
1265 },
1266 RefreshReferences {
1267 references: SourceReferences,
1268 },
1269}
1270
1271#[derive(Debug)]
1272pub struct AlterSourcePlan {
1273 pub item_id: CatalogItemId,
1274 pub ingestion_id: GlobalId,
1275 pub action: AlterSourceAction,
1276}
1277
1278#[derive(Debug, Clone)]
1279pub struct AlterSinkPlan {
1280 pub item_id: CatalogItemId,
1281 pub global_id: GlobalId,
1282 pub sink: Sink,
1283 pub with_snapshot: bool,
1284 pub in_cluster: ClusterId,
1285 pub set_options: Vec<CreateSinkOption<Aug>>,
1290 pub reset_options: Vec<CreateSinkOptionName>,
1291}
1292
1293pub fn apply_sink_option_edits<T: mz_sql_parser::ast::AstInfo>(
1296 with_options: &mut Vec<CreateSinkOption<T>>,
1297 set_options: &[CreateSinkOption<T>],
1298 reset_options: &[CreateSinkOptionName],
1299) where
1300 CreateSinkOption<T>: Clone,
1301{
1302 with_options.retain(|o| {
1303 set_options.iter().all(|s| s.name != o.name) && !reset_options.contains(&o.name)
1304 });
1305 with_options.extend(set_options.iter().cloned());
1306}
1307
1308#[derive(Debug, Clone)]
1309pub struct AlterClusterPlan {
1310 pub id: ClusterId,
1311 pub name: String,
1312 pub options: PlanClusterOption,
1313 pub strategy: AlterClusterPlanStrategy,
1314}
1315
1316#[derive(Debug)]
1317pub struct AlterClusterRenamePlan {
1318 pub id: ClusterId,
1319 pub name: String,
1320 pub to_name: String,
1321}
1322
1323#[derive(Debug)]
1324pub struct AlterClusterReplicaRenamePlan {
1325 pub cluster_id: ClusterId,
1326 pub replica_id: ReplicaId,
1327 pub name: QualifiedReplica,
1328 pub to_name: String,
1329}
1330
1331#[derive(Debug)]
1332pub struct AlterItemRenamePlan {
1333 pub id: CatalogItemId,
1334 pub current_full_name: FullItemName,
1335 pub to_name: String,
1336 pub object_type: ObjectType,
1337}
1338
1339#[derive(Debug)]
1340pub struct AlterSchemaRenamePlan {
1341 pub cur_schema_spec: (ResolvedDatabaseSpecifier, SchemaSpecifier),
1342 pub new_schema_name: String,
1343}
1344
1345#[derive(Debug)]
1346pub struct AlterSchemaSwapPlan {
1347 pub schema_a_spec: (ResolvedDatabaseSpecifier, SchemaSpecifier),
1348 pub schema_a_name: String,
1349 pub schema_b_spec: (ResolvedDatabaseSpecifier, SchemaSpecifier),
1350 pub schema_b_name: String,
1351 pub name_temp: String,
1352}
1353
1354#[derive(Debug)]
1355pub struct AlterClusterSwapPlan {
1356 pub id_a: ClusterId,
1357 pub id_b: ClusterId,
1358 pub name_a: String,
1359 pub name_b: String,
1360 pub name_temp: String,
1361}
1362
1363#[derive(Debug)]
1364pub struct AlterSecretPlan {
1365 pub id: CatalogItemId,
1366 pub secret_as: MirScalarExpr,
1367}
1368
1369#[derive(Debug)]
1370pub struct AlterSystemSetPlan {
1371 pub name: String,
1372 pub value: VariableValue,
1373}
1374
1375#[derive(Debug)]
1376pub struct AlterSystemResetPlan {
1377 pub name: String,
1378}
1379
1380#[derive(Debug)]
1381pub struct AlterSystemResetAllPlan {}
1382
1383#[derive(Debug)]
1384pub struct AlterRolePlan {
1385 pub id: RoleId,
1386 pub name: String,
1387 pub option: PlannedAlterRoleOption,
1388}
1389
1390#[derive(Debug)]
1391pub struct AlterOwnerPlan {
1392 pub id: ObjectId,
1393 pub object_type: ObjectType,
1394 pub new_owner: RoleId,
1395}
1396
1397#[derive(Debug)]
1398pub struct AlterTablePlan {
1399 pub relation_id: CatalogItemId,
1400 pub column_name: ColumnName,
1401 pub column_type: SqlColumnType,
1402 pub raw_sql_type: RawDataType,
1403}
1404
1405#[derive(Debug, Clone)]
1406pub struct AlterMaterializedViewApplyReplacementPlan {
1407 pub id: CatalogItemId,
1408 pub replacement_id: CatalogItemId,
1409}
1410
1411#[derive(Debug)]
1412pub struct DeclarePlan {
1413 pub name: String,
1414 pub stmt: Statement<Raw>,
1415 pub sql: String,
1416 pub params: Params,
1417}
1418
1419#[derive(Debug)]
1420pub struct FetchPlan {
1421 pub name: String,
1422 pub count: Option<FetchDirection>,
1423 pub timeout: ExecuteTimeout,
1424}
1425
1426#[derive(Debug)]
1427pub struct ClosePlan {
1428 pub name: String,
1429}
1430
1431#[derive(Debug)]
1432pub struct PreparePlan {
1433 pub name: String,
1434 pub stmt: Statement<Raw>,
1435 pub sql: String,
1436 pub desc: StatementDesc,
1437}
1438
1439#[derive(Debug)]
1440pub struct ExecutePlan {
1441 pub name: String,
1442 pub params: Params,
1443}
1444
1445#[derive(Debug)]
1446pub struct DeallocatePlan {
1447 pub name: Option<String>,
1448}
1449
1450#[derive(Debug)]
1451pub struct RaisePlan {
1452 pub severity: NoticeSeverity,
1453}
1454
1455#[derive(Debug)]
1456pub struct GrantRolePlan {
1457 pub role_ids: Vec<RoleId>,
1459 pub member_ids: Vec<RoleId>,
1461 pub grantor_id: RoleId,
1463}
1464
1465#[derive(Debug)]
1466pub struct RevokeRolePlan {
1467 pub role_ids: Vec<RoleId>,
1469 pub member_ids: Vec<RoleId>,
1471 pub grantor_id: RoleId,
1473}
1474
1475#[derive(Debug)]
1476pub struct UpdatePrivilege {
1477 pub acl_mode: AclMode,
1479 pub target_id: SystemObjectId,
1481 pub grantor: RoleId,
1483 pub acl_from_all: bool,
1488}
1489
1490#[derive(Debug)]
1491pub struct GrantPrivilegesPlan {
1492 pub update_privileges: Vec<UpdatePrivilege>,
1494 pub grantees: Vec<RoleId>,
1496}
1497
1498#[derive(Debug)]
1499pub struct RevokePrivilegesPlan {
1500 pub update_privileges: Vec<UpdatePrivilege>,
1502 pub revokees: Vec<RoleId>,
1504}
1505#[derive(Debug)]
1506pub struct AlterDefaultPrivilegesPlan {
1507 pub privilege_objects: Vec<DefaultPrivilegeObject>,
1509 pub privilege_acl_items: Vec<DefaultPrivilegeAclItem>,
1511 pub is_grant: bool,
1513}
1514
1515#[derive(Debug)]
1516pub struct ReassignOwnedPlan {
1517 pub old_roles: Vec<RoleId>,
1519 pub new_role: RoleId,
1521 pub reassign_ids: Vec<ObjectId>,
1523}
1524
1525#[derive(Debug)]
1526pub struct CommentPlan {
1527 pub object_id: CommentObjectId,
1529 pub sub_component: Option<usize>,
1533 pub comment: Option<String>,
1535}
1536
1537#[derive(Clone, Debug)]
1538pub enum TableDataSource {
1539 TableWrites { defaults: Vec<Expr<Aug>> },
1541
1542 DataSource {
1545 desc: DataSourceDesc,
1546 timeline: Timeline,
1547 },
1548}
1549
1550#[derive(Clone, Debug)]
1551pub struct Table {
1552 pub create_sql: String,
1553 pub desc: VersionedRelationDesc,
1554 pub temporary: bool,
1555 pub compaction_window: Option<CompactionWindow>,
1556 pub data_source: TableDataSource,
1557}
1558
1559#[derive(Clone, Debug)]
1560pub struct Source {
1561 pub create_sql: String,
1562 pub data_source: DataSourceDesc,
1563 pub desc: RelationDesc,
1564 pub compaction_window: Option<CompactionWindow>,
1565}
1566
1567#[derive(Debug, Clone)]
1568pub enum DataSourceDesc {
1569 Ingestion(SourceDesc<ReferencedConnection>),
1571 OldSyntaxIngestion {
1573 desc: SourceDesc<ReferencedConnection>,
1574 progress_subsource: CatalogItemId,
1577 data_config: SourceExportDataConfig<ReferencedConnection>,
1578 details: SourceExportDetails,
1579 },
1580 IngestionExport {
1583 ingestion_id: CatalogItemId,
1584 external_reference: UnresolvedItemName,
1585 details: SourceExportDetails,
1586 data_config: SourceExportDataConfig<ReferencedConnection>,
1587 },
1588 Progress,
1590 Webhook {
1592 validate_using: Option<WebhookValidation>,
1593 body_format: WebhookBodyFormat,
1594 headers: WebhookHeaders,
1595 cluster_id: Option<StorageInstanceId>,
1597 },
1598}
1599
1600#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
1601pub struct WebhookValidation {
1602 pub expression: MirScalarExpr,
1604 pub relation_desc: RelationDesc,
1606 pub bodies: Vec<(usize, bool)>,
1608 pub headers: Vec<(usize, bool)>,
1610 pub secrets: Vec<WebhookValidationSecret>,
1612}
1613
1614impl WebhookValidation {
1615 const MAX_REDUCE_TIME: Duration = Duration::from_secs(60);
1616
1617 pub async fn reduce_expression(&mut self) -> Result<(), &'static str> {
1622 let WebhookValidation {
1623 expression,
1624 relation_desc,
1625 ..
1626 } = self;
1627
1628 let mut expression_ = expression.clone();
1630 let desc_ = relation_desc.clone();
1631 let reduce_task = mz_ore::task::spawn_blocking(
1632 || "webhook-validation-reduce",
1633 move || {
1634 let repr_col_types: Vec<ReprColumnType> = desc_
1635 .typ()
1636 .column_types
1637 .iter()
1638 .map(ReprColumnType::from)
1639 .collect();
1640 expression_.reduce(&repr_col_types);
1641 expression_
1642 },
1643 );
1644
1645 match tokio::time::timeout(Self::MAX_REDUCE_TIME, reduce_task).await {
1646 Ok(reduced_expr) => {
1647 *expression = reduced_expr;
1648 Ok(())
1649 }
1650 Err(_) => Err("timeout"),
1651 }
1652 }
1653}
1654
1655#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize)]
1656pub struct WebhookHeaders {
1657 pub header_column: Option<WebhookHeaderFilters>,
1659 pub mapped_headers: BTreeMap<usize, (String, bool)>,
1661}
1662
1663impl WebhookHeaders {
1664 pub fn num_columns(&self) -> usize {
1666 let header_column = self.header_column.as_ref().map(|_| 1).unwrap_or(0);
1667 let mapped_headers = self.mapped_headers.len();
1668
1669 header_column + mapped_headers
1670 }
1671}
1672
1673#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize)]
1674pub struct WebhookHeaderFilters {
1675 pub block: BTreeSet<String>,
1676 pub allow: BTreeSet<String>,
1677}
1678
1679#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Arbitrary)]
1680pub enum WebhookBodyFormat {
1681 Json { array: bool },
1682 Bytes,
1683 Text,
1684}
1685
1686impl From<WebhookBodyFormat> for SqlScalarType {
1687 fn from(value: WebhookBodyFormat) -> Self {
1688 match value {
1689 WebhookBodyFormat::Json { .. } => SqlScalarType::Jsonb,
1690 WebhookBodyFormat::Bytes => SqlScalarType::Bytes,
1691 WebhookBodyFormat::Text => SqlScalarType::String,
1692 }
1693 }
1694}
1695
1696#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
1697pub struct WebhookValidationSecret {
1698 pub id: CatalogItemId,
1700 pub column_idx: usize,
1702 pub use_bytes: bool,
1704}
1705
1706#[derive(Clone, Debug)]
1707pub struct Connection {
1708 pub create_sql: String,
1709 pub details: ConnectionDetails,
1710}
1711
1712#[derive(Clone, Debug, Serialize)]
1713pub enum ConnectionDetails {
1714 Kafka(KafkaConnection<ReferencedConnection>),
1715 Csr(CsrConnection<ReferencedConnection>),
1716 GlueSchemaRegistry(GlueSchemaRegistryConnection<ReferencedConnection>),
1717 Postgres(PostgresConnection<ReferencedConnection>),
1718 Ssh {
1719 connection: SshConnection,
1720 key_1: SshKey,
1721 key_2: SshKey,
1722 },
1723 Aws(AwsConnection),
1724 AwsPrivatelink(AwsPrivatelinkConnection),
1725 Gcp(GcpConnection),
1726 MySql(MySqlConnection<ReferencedConnection>),
1727 SqlServer(SqlServerConnectionDetails<ReferencedConnection>),
1728 IcebergCatalog(IcebergCatalogConnection<ReferencedConnection>),
1729}
1730
1731impl ConnectionDetails {
1732 pub fn to_connection(&self) -> mz_storage_types::connections::Connection<ReferencedConnection> {
1733 match self {
1734 ConnectionDetails::Kafka(c) => {
1735 mz_storage_types::connections::Connection::Kafka(c.clone())
1736 }
1737 ConnectionDetails::Csr(c) => mz_storage_types::connections::Connection::Csr(c.clone()),
1738 ConnectionDetails::GlueSchemaRegistry(c) => {
1739 mz_storage_types::connections::Connection::GlueSchemaRegistry(c.clone())
1740 }
1741 ConnectionDetails::Postgres(c) => {
1742 mz_storage_types::connections::Connection::Postgres(c.clone())
1743 }
1744 ConnectionDetails::Ssh { connection, .. } => {
1745 mz_storage_types::connections::Connection::Ssh(connection.clone())
1746 }
1747 ConnectionDetails::Aws(c) => mz_storage_types::connections::Connection::Aws(c.clone()),
1748 ConnectionDetails::AwsPrivatelink(c) => {
1749 mz_storage_types::connections::Connection::AwsPrivatelink(c.clone())
1750 }
1751 ConnectionDetails::Gcp(c) => mz_storage_types::connections::Connection::Gcp(c.clone()),
1752 ConnectionDetails::MySql(c) => {
1753 mz_storage_types::connections::Connection::MySql(c.clone())
1754 }
1755 ConnectionDetails::SqlServer(c) => {
1756 mz_storage_types::connections::Connection::SqlServer(c.clone())
1757 }
1758 ConnectionDetails::IcebergCatalog(c) => {
1759 mz_storage_types::connections::Connection::IcebergCatalog(c.clone())
1760 }
1761 }
1762 }
1763
1764 pub fn secret_content_guards(
1776 &self,
1777 ) -> Vec<(CatalogItemId, fn(&str) -> Result<(), anyhow::Error>)> {
1778 match self {
1779 ConnectionDetails::Gcp(gcp) => vec![(
1782 gcp.credentials_json,
1783 GcpServiceAccountKeyTokenUri::validate_json,
1784 )],
1785 _ => vec![],
1786 }
1787 }
1788}
1789
1790#[derive(Debug, Clone, Serialize, PartialEq, Eq, Ord, PartialOrd, Hash)]
1791pub struct NetworkPolicyRule {
1792 pub name: String,
1793 pub action: NetworkPolicyRuleAction,
1794 pub address: PolicyAddress,
1795 pub direction: NetworkPolicyRuleDirection,
1796}
1797
1798#[derive(
1799 Debug,
1800 Clone,
1801 Serialize,
1802 Deserialize,
1803 PartialEq,
1804 Eq,
1805 Ord,
1806 PartialOrd,
1807 Hash
1808)]
1809pub enum NetworkPolicyRuleAction {
1810 Allow,
1811}
1812
1813impl std::fmt::Display for NetworkPolicyRuleAction {
1814 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1815 match self {
1816 Self::Allow => write!(f, "allow"),
1817 }
1818 }
1819}
1820impl TryFrom<&str> for NetworkPolicyRuleAction {
1821 type Error = PlanError;
1822 fn try_from(value: &str) -> Result<Self, Self::Error> {
1823 match value.to_uppercase().as_str() {
1824 "ALLOW" => Ok(Self::Allow),
1825 _ => Err(PlanError::Unstructured(
1826 "Allow is the only valid option".into(),
1827 )),
1828 }
1829 }
1830}
1831
1832#[derive(Debug, Clone, Serialize, PartialEq, Eq, Ord, PartialOrd, Hash)]
1833pub enum NetworkPolicyRuleDirection {
1834 Ingress,
1835}
1836impl std::fmt::Display for NetworkPolicyRuleDirection {
1837 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1838 match self {
1839 Self::Ingress => write!(f, "ingress"),
1840 }
1841 }
1842}
1843impl TryFrom<&str> for NetworkPolicyRuleDirection {
1844 type Error = PlanError;
1845 fn try_from(value: &str) -> Result<Self, Self::Error> {
1846 match value.to_uppercase().as_str() {
1847 "INGRESS" => Ok(Self::Ingress),
1848 _ => Err(PlanError::Unstructured(
1849 "Ingress is the only valid option".into(),
1850 )),
1851 }
1852 }
1853}
1854
1855#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
1856pub struct PolicyAddress(pub IpNet);
1857impl std::fmt::Display for PolicyAddress {
1858 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1859 write!(f, "{}", &self.0.to_string())
1860 }
1861}
1862impl From<String> for PolicyAddress {
1863 fn from(value: String) -> Self {
1864 Self(IpNet::from_str(&value).expect("expected value to be IpNet"))
1865 }
1866}
1867impl TryFrom<&str> for PolicyAddress {
1868 type Error = PlanError;
1869 fn try_from(value: &str) -> Result<Self, Self::Error> {
1870 let net = IpNet::from_str(value)
1871 .map_err(|_| PlanError::Unstructured("Value must be valid IPV4 or IPV6 CIDR".into()))?;
1872 Ok(Self(net))
1873 }
1874}
1875
1876impl Serialize for PolicyAddress {
1877 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1878 where
1879 S: serde::Serializer,
1880 {
1881 serializer.serialize_str(&format!("{}", &self.0))
1882 }
1883}
1884
1885#[derive(Clone, Debug, Serialize)]
1886pub enum SshKey {
1887 PublicOnly(String),
1888 Both(SshKeyPair),
1889}
1890
1891impl SshKey {
1892 pub fn as_key_pair(&self) -> Option<&SshKeyPair> {
1893 match self {
1894 SshKey::PublicOnly(_) => None,
1895 SshKey::Both(key_pair) => Some(key_pair),
1896 }
1897 }
1898
1899 pub fn public_key(&self) -> String {
1900 match self {
1901 SshKey::PublicOnly(s) => s.into(),
1902 SshKey::Both(p) => p.ssh_public_key(),
1903 }
1904 }
1905}
1906
1907#[derive(Clone, Debug)]
1908pub struct Secret {
1909 pub create_sql: String,
1910 pub secret_as: MirScalarExpr,
1911}
1912
1913#[derive(Clone, Debug)]
1914pub struct Sink {
1915 pub create_sql: String,
1917 pub from: GlobalId,
1919 pub connection: StorageSinkConnection<ReferencedConnection>,
1921 pub envelope: SinkEnvelope,
1923 pub version: u64,
1924 pub commit_interval: Option<Duration>,
1925}
1926
1927#[derive(Clone, Debug)]
1928pub struct View {
1929 pub create_sql: String,
1931 pub expr: HirRelationExpr,
1933 pub dependencies: DependencyIds,
1935 pub column_names: Vec<ColumnName>,
1937 pub temporary: bool,
1939}
1940
1941#[derive(Clone, Debug)]
1942pub struct MaterializedView {
1943 pub create_sql: String,
1945 pub expr: HirRelationExpr,
1947 pub dependencies: DependencyIds,
1949 pub column_names: Vec<ColumnName>,
1951 pub replacement_target: Option<CatalogItemId>,
1952 pub cluster_id: ClusterId,
1954 pub target_replica: Option<ReplicaId>,
1956 pub non_null_assertions: Vec<usize>,
1957 pub compaction_window: Option<CompactionWindow>,
1958 pub refresh_schedule: Option<RefreshSchedule>,
1959 pub as_of: Option<Timestamp>,
1960}
1961
1962#[derive(Clone, Debug)]
1963pub struct Index {
1964 pub create_sql: String,
1966 pub on: GlobalId,
1968 pub keys: Vec<mz_expr::MirScalarExpr>,
1969 pub compaction_window: Option<CompactionWindow>,
1970 pub cluster_id: ClusterId,
1971}
1972
1973#[derive(Clone, Debug)]
1974pub struct Type {
1975 pub create_sql: String,
1976 pub inner: CatalogType<IdReference>,
1977}
1978
1979#[derive(Deserialize, Clone, Debug, PartialEq)]
1981pub enum QueryWhen {
1982 Immediately,
1985 FreshestTableWrite,
1988 AtTimestamp(Timestamp),
1993 AtLeastTimestamp(Timestamp),
1996}
1997
1998impl QueryWhen {
1999 pub fn advance_to_timestamp(&self) -> Option<Timestamp> {
2001 match self {
2002 QueryWhen::AtTimestamp(t) | QueryWhen::AtLeastTimestamp(t) => Some(t.clone()),
2003 QueryWhen::Immediately | QueryWhen::FreshestTableWrite => None,
2004 }
2005 }
2006 pub fn constrains_upper(&self) -> bool {
2010 match self {
2011 QueryWhen::AtTimestamp(_) => true,
2012 QueryWhen::AtLeastTimestamp(_)
2013 | QueryWhen::Immediately
2014 | QueryWhen::FreshestTableWrite => false,
2015 }
2016 }
2017 pub fn advance_to_since(&self) -> bool {
2019 match self {
2020 QueryWhen::Immediately
2021 | QueryWhen::AtLeastTimestamp(_)
2022 | QueryWhen::FreshestTableWrite => true,
2023 QueryWhen::AtTimestamp(_) => false,
2024 }
2025 }
2026 pub fn can_advance_to_upper(&self) -> bool {
2028 match self {
2029 QueryWhen::Immediately => true,
2030 QueryWhen::FreshestTableWrite
2031 | QueryWhen::AtTimestamp(_)
2032 | QueryWhen::AtLeastTimestamp(_) => false,
2033 }
2034 }
2035
2036 pub fn can_advance_to_timeline_ts(&self) -> bool {
2038 match self {
2039 QueryWhen::Immediately | QueryWhen::FreshestTableWrite => true,
2040 QueryWhen::AtTimestamp(_) | QueryWhen::AtLeastTimestamp(_) => false,
2041 }
2042 }
2043 pub fn must_advance_to_timeline_ts(&self) -> bool {
2045 match self {
2046 QueryWhen::FreshestTableWrite => true,
2047 QueryWhen::Immediately | QueryWhen::AtLeastTimestamp(_) | QueryWhen::AtTimestamp(_) => {
2048 false
2049 }
2050 }
2051 }
2052 pub fn is_transactional(&self) -> bool {
2054 match self {
2055 QueryWhen::Immediately | QueryWhen::FreshestTableWrite => true,
2056 QueryWhen::AtLeastTimestamp(_) | QueryWhen::AtTimestamp(_) => false,
2057 }
2058 }
2059}
2060
2061#[derive(Debug, Copy, Clone)]
2062pub enum MutationKind {
2063 Insert,
2064 Update,
2065 Delete,
2066}
2067
2068#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
2069pub enum CopyFormat {
2070 Text,
2071 Csv,
2072 Binary,
2073 Parquet,
2074}
2075
2076#[derive(Debug, Copy, Clone)]
2077pub enum ExecuteTimeout {
2078 None,
2079 Seconds(f64),
2080 WaitOnce,
2081}
2082
2083#[derive(Clone, Debug)]
2084pub enum IndexOption {
2085 RetainHistory(CompactionWindow),
2087}
2088
2089#[derive(Clone, Debug)]
2090pub enum TableOption {
2091 RetainHistory(CompactionWindow),
2093}
2094
2095#[derive(Clone, Debug)]
2096pub struct PlanClusterOption {
2097 pub availability_zones: AlterOptionParameter<Vec<String>>,
2098 pub introspection_debugging: AlterOptionParameter<bool>,
2099 pub introspection_interval: AlterOptionParameter<OptionalDuration>,
2100 pub managed: AlterOptionParameter<bool>,
2101 pub replicas: AlterOptionParameter<Vec<(String, ReplicaConfig)>>,
2102 pub replication_factor: AlterOptionParameter<u32>,
2103 pub size: AlterOptionParameter,
2104 pub schedule: AlterOptionParameter<ClusterSchedule>,
2105 pub workload_class: AlterOptionParameter<Option<String>>,
2106}
2107
2108impl Default for PlanClusterOption {
2109 fn default() -> Self {
2110 Self {
2111 availability_zones: AlterOptionParameter::Unchanged,
2112 introspection_debugging: AlterOptionParameter::Unchanged,
2113 introspection_interval: AlterOptionParameter::Unchanged,
2114 managed: AlterOptionParameter::Unchanged,
2115 replicas: AlterOptionParameter::Unchanged,
2116 replication_factor: AlterOptionParameter::Unchanged,
2117 size: AlterOptionParameter::Unchanged,
2118 schedule: AlterOptionParameter::Unchanged,
2119 workload_class: AlterOptionParameter::Unchanged,
2120 }
2121 }
2122}
2123
2124#[derive(Clone, Debug, PartialEq, Eq)]
2125pub enum AlterClusterPlanStrategy {
2126 None,
2127 For(Duration),
2128 UntilReady {
2129 on_timeout: Option<OnTimeoutAction>,
2132 timeout: Duration,
2133 },
2134}
2135
2136#[derive(
2137 Clone,
2138 Copy,
2139 Debug,
2140 Deserialize,
2141 Serialize,
2142 PartialOrd,
2143 PartialEq,
2144 Eq,
2145 Ord
2146)]
2147pub enum OnTimeoutAction {
2148 Commit,
2150 Rollback,
2152}
2153
2154impl TryFrom<&str> for OnTimeoutAction {
2155 type Error = PlanError;
2156 fn try_from(value: &str) -> Result<Self, Self::Error> {
2157 match value.to_uppercase().as_str() {
2158 "COMMIT" => Ok(Self::Commit),
2159 "ROLLBACK" => Ok(Self::Rollback),
2160 _ => Err(PlanError::Unstructured(
2161 "Valid options are COMMIT, ROLLBACK".into(),
2162 )),
2163 }
2164 }
2165}
2166
2167impl AlterClusterPlanStrategy {
2168 pub fn is_none(&self) -> bool {
2169 matches!(self, Self::None)
2170 }
2171 pub fn is_some(&self) -> bool {
2172 !matches!(self, Self::None)
2173 }
2174}
2175
2176impl TryFrom<ClusterAlterOptionExtracted> for AlterClusterPlanStrategy {
2177 type Error = PlanError;
2178
2179 fn try_from(value: ClusterAlterOptionExtracted) -> Result<Self, Self::Error> {
2180 Ok(match value.wait {
2181 Some(ClusterAlterOptionValue::For(d)) => Self::For(Duration::try_from_value(d)?),
2182 Some(ClusterAlterOptionValue::UntilReady(options)) => {
2183 let extracted = ClusterAlterUntilReadyOptionExtracted::try_from(options)?;
2184 Self::UntilReady {
2185 timeout: match extracted.timeout {
2186 Some(d) => d,
2187 None => Err(PlanError::UntilReadyTimeoutRequired)?,
2188 },
2189 on_timeout: match extracted.on_timeout {
2190 Some(v) => Some(OnTimeoutAction::try_from(v.as_str()).map_err(|e| {
2191 PlanError::InvalidOptionValue {
2192 option_name: "ON TIMEOUT".into(),
2193 err: Box::new(e),
2194 }
2195 })?),
2196 None => None,
2197 },
2198 }
2199 }
2200 None => Self::None,
2201 })
2202 }
2203}
2204
2205#[derive(Debug, Clone)]
2207pub struct Params {
2208 pub datums: Row,
2210 pub execute_types: Vec<SqlScalarType>,
2212 pub expected_types: Vec<SqlScalarType>,
2214}
2215
2216impl Params {
2217 pub fn empty() -> Params {
2219 Params {
2220 datums: Row::pack_slice(&[]),
2221 execute_types: vec![],
2222 expected_types: vec![],
2223 }
2224 }
2225}
2226
2227#[derive(
2229 Ord,
2230 PartialOrd,
2231 Clone,
2232 Debug,
2233 Eq,
2234 PartialEq,
2235 Serialize,
2236 Deserialize,
2237 Hash,
2238 Copy
2239)]
2240pub struct PlanContext {
2241 pub wall_time: DateTime<Utc>,
2242 pub ignore_if_exists_errors: bool,
2243}
2244
2245impl PlanContext {
2246 pub fn new(wall_time: DateTime<Utc>) -> Self {
2247 Self {
2248 wall_time,
2249 ignore_if_exists_errors: false,
2250 }
2251 }
2252
2253 pub fn zero() -> Self {
2257 PlanContext {
2258 wall_time: now::to_datetime(NOW_ZERO()),
2259 ignore_if_exists_errors: false,
2260 }
2261 }
2262
2263 pub fn with_ignore_if_exists_errors(mut self, value: bool) -> Self {
2264 self.ignore_if_exists_errors = value;
2265 self
2266 }
2267}