1use super::{NullsOrder, ScalarExpr, SetOpKind};
10use crate::catalog::roles::RoleReference;
11
12const fn default_include_descendants() -> bool {
13 true
14}
15
16#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
22pub enum UnifiedPlan {
23 Query(Box<QueryPlan>),
24 Command(Box<CommandPlan>),
25}
26
27#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
29pub struct QueryPlan {
30 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
32 pub relations_bound: bool,
33 pub ctes: Vec<CtePlan>,
34 pub root: RelationalPlan,
35}
36
37#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
39pub struct CtePlan {
40 pub name: String,
41 pub columns: Vec<String>,
42 pub recursive: bool,
43 #[serde(default)]
44 pub materialization: crate::ast::CteMaterialization,
45 #[serde(default, skip_serializing_if = "Option::is_none")]
46 pub search: Option<CteSearchPlan>,
47 #[serde(default, skip_serializing_if = "Option::is_none")]
48 pub cycle: Option<CteCyclePlan>,
49 #[serde(flatten)]
50 pub body: CtePlanBody,
51}
52
53#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
55pub enum CtePlanBody {
56 #[serde(rename = "query")]
57 Query(Box<QueryPlan>),
58 #[serde(rename = "command")]
59 Command(Box<CommandPlan>),
60}
61
62impl CtePlanBody {
63 pub fn query(&self) -> Option<&QueryPlan> {
64 match self {
65 Self::Query(query) => Some(query),
66 Self::Command(_) => None,
67 }
68 }
69
70 pub fn query_mut(&mut self) -> Option<&mut QueryPlan> {
71 match self {
72 Self::Query(query) => Some(query),
73 Self::Command(_) => None,
74 }
75 }
76
77 pub const fn modifies_data(&self) -> bool {
78 matches!(self, Self::Command(_))
79 }
80
81 pub fn returns_rows(&self) -> bool {
83 match self {
84 Self::Query(_) => true,
85 Self::Command(command) => command
86 .returning()
87 .is_some_and(|returning| !returning.is_empty()),
88 }
89 }
90
91 pub fn into_plan(self) -> UnifiedPlan {
92 match self {
93 Self::Query(query) => UnifiedPlan::Query(query),
94 Self::Command(command) => UnifiedPlan::Command(command),
95 }
96 }
97}
98
99impl From<UnifiedPlan> for CtePlanBody {
100 fn from(plan: UnifiedPlan) -> Self {
101 match plan {
102 UnifiedPlan::Query(query) => Self::Query(query),
103 UnifiedPlan::Command(command) => Self::Command(command),
104 }
105 }
106}
107
108#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
110pub struct CteSearchPlan {
111 pub columns: Vec<String>,
112 pub breadth_first: bool,
113 pub sequence_column: String,
114}
115
116#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
118pub struct CteCyclePlan {
119 pub columns: Vec<String>,
120 pub mark_column: String,
121 pub mark_value: ScalarExpr,
122 pub mark_default: ScalarExpr,
123 pub path_column: String,
124}
125
126#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
129pub enum RelationalPlan {
130 QueryBlock(Box<QueryBlockPlan>),
133 SetOp {
136 kind: SetOpKind,
137 all: bool,
138 left: Box<QueryPlan>,
139 right: Box<QueryPlan>,
140 order_by: Vec<OrderPlan>,
141 limit: Option<Box<ScalarExpr>>,
142 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
143 with_ties: bool,
144 offset: Option<Box<ScalarExpr>>,
145 subqueries: Vec<QueryPlan>,
146 },
147 Values {
151 rows: Vec<Vec<ScalarExpr>>,
152 subqueries: Vec<QueryPlan>,
153 },
154}
155
156#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
159pub struct QueryBlockPlan {
160 #[serde(default, skip_serializing_if = "Vec::is_empty")]
162 pub windows: Vec<crate::ast::WindowDefinition<crate::ir::ScalarWindowSpec>>,
163 pub projections: Vec<ProjectionPlan>,
164 #[serde(default, skip_serializing_if = "std::collections::BTreeSet::is_empty")]
166 pub privilege_columns: std::collections::BTreeSet<crate::ColumnIdentity>,
167 pub from: Option<SourcePlan>,
168 pub r#where: Option<ScalarExpr>,
169 pub compute: ComputePlan,
170 pub group_by: Vec<ScalarExpr>,
171 pub grouping_sets: Vec<Vec<ScalarExpr>>,
172 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
173 pub group_distinct: bool,
174 pub having: Option<ScalarExpr>,
175 pub order_by: Vec<OrderPlan>,
176 pub limit: Option<ScalarExpr>,
177 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
178 pub with_ties: bool,
179 pub offset: Option<ScalarExpr>,
180 pub distinct: bool,
181 pub distinct_on: Vec<ScalarExpr>,
182 pub subqueries: Vec<QueryPlan>,
183 pub access: AccessPathPlan,
184 #[serde(default, skip_serializing_if = "Vec::is_empty")]
186 pub locking: Vec<crate::ast::LockingClause>,
187}
188
189#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
192pub enum AccessPathPlan {
193 Row,
195 OperatorTree {
197 score_limit_pushdown: bool,
200 },
201 Hybrid,
204}
205
206#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
214pub enum JoinExecutionStrategy {
215 #[default]
216 Auto,
217 Hash,
218}
219
220#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
222pub struct TableFunctionPlan {
223 pub name: String,
224 #[serde(default, skip_serializing_if = "Option::is_none")]
225 pub binding: Option<crate::ast::FunctionBinding>,
226 #[serde(default)]
227 pub output_name: String,
228 #[serde(default, skip_serializing_if = "Option::is_none")]
229 pub relations: Option<crate::ast::OperatorJoinRelations>,
230 pub args: Vec<ScalarExpr>,
231 pub column_aliases: Vec<String>,
232 pub column_types: Vec<String>,
233}
234
235#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
237pub enum SourcePlan {
238 Table {
239 name: String,
240 #[serde(default)]
241 qualifier: String,
242 alias: Option<String>,
243 #[serde(default, skip_serializing_if = "Vec::is_empty")]
244 column_aliases: Vec<String>,
245 #[serde(default, skip_serializing_if = "Option::is_none")]
246 bound_columns: Option<Vec<String>>,
247 #[serde(default = "default_include_descendants")]
248 include_descendants: bool,
249 },
250 Join {
251 left: Box<SourcePlan>,
252 right: Box<SourcePlan>,
253 kind: crate::ast::JoinKind,
254 on: Option<ScalarExpr>,
255 #[serde(default, skip_serializing_if = "Option::is_none")]
256 using: Option<crate::ast::JoinUsing>,
257 #[serde(default)]
258 natural: bool,
259 #[serde(default, skip_serializing_if = "Option::is_none")]
260 alias: Option<String>,
261 #[serde(default, skip_serializing_if = "Vec::is_empty")]
262 column_aliases: Vec<String>,
263 lateral: bool,
264 #[serde(default)]
265 strategy: JoinExecutionStrategy,
266 },
267 Values {
268 rows: Vec<Vec<ScalarExpr>>,
269 alias: Option<String>,
270 column_aliases: Vec<String>,
271 #[serde(default, skip_serializing_if = "Option::is_none")]
272 internal_relation: Option<crate::ast::InternalRelationId>,
273 #[serde(default, skip_serializing_if = "Vec::is_empty")]
274 internal_column_types: Vec<Option<crate::ast::ColumnType>>,
275 },
276 Function {
277 name: String,
278 #[serde(default, skip_serializing_if = "Option::is_none")]
279 binding: Option<crate::ast::FunctionBinding>,
280 #[serde(default)]
281 output_name: String,
282 #[serde(default, skip_serializing_if = "Option::is_none")]
283 relations: Option<crate::ast::OperatorJoinRelations>,
284 args: Vec<ScalarExpr>,
285 alias: Option<String>,
286 column_aliases: Vec<String>,
287 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
288 ordinality: bool,
289 column_types: Vec<String>,
290 },
291 FunctionGroup {
292 functions: Vec<TableFunctionPlan>,
293 alias: Option<String>,
294 column_aliases: Vec<String>,
295 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
296 ordinality: bool,
297 },
298 Subquery {
299 body: Box<QueryPlan>,
300 alias: Option<String>,
301 column_aliases: Vec<String>,
302 },
303}
304
305#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
307pub enum ComputePlan {
308 Project,
309 Aggregate,
310 Window,
311}
312
313#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
314pub struct ProjectionPlan {
315 pub expr: ScalarExpr,
316 pub alias: Option<String>,
317}
318
319#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
320pub struct OrderPlan {
321 pub expr: ScalarExpr,
322 pub descending: bool,
323 pub nulls: Option<NullsOrder>,
324}
325
326#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
328pub struct ExpressionPlan {
329 pub scalar: ScalarExpr,
330 pub subqueries: Vec<QueryPlan>,
331}
332
333#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
334pub struct AssignmentPlan {
335 #[serde(rename = "column")]
336 pub target: crate::ast::AssignmentTargets<ScalarExpr>,
337 pub value: ScalarExpr,
338}
339
340impl AssignmentPlan {
341 pub fn expressions(&self) -> impl Iterator<Item = &ScalarExpr> {
342 self.target
343 .expressions()
344 .chain(std::iter::once(&self.value))
345 }
346
347 pub fn expressions_mut(&mut self) -> impl Iterator<Item = &mut ScalarExpr> {
348 self.target
349 .expressions_mut()
350 .chain(std::iter::once(&mut self.value))
351 }
352}
353
354#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
355pub struct ViewCheckPlan {
356 pub view: String,
357 pub predicate: ScalarExpr,
358}
359
360#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
361pub struct ViewRuleReturningPlan {
362 pub relation: String,
363 pub target_qualifier: String,
364 pub returning: Vec<ProjectionPlan>,
365 pub aliases: crate::ast::ReturningAliases,
366 pub subqueries: Vec<QueryPlan>,
367}
368
369#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
370pub struct ViewRuleInsertPlan {
371 pub relation: String,
372 pub supplied_columns: Vec<String>,
373 pub input_columns: Vec<String>,
374}
375
376#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
377pub struct ViewRuleUpdatePlan {
378 pub relation: String,
379 pub assigned_columns: Vec<String>,
380 pub input_columns: Vec<String>,
381}
382
383#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
384pub struct InsertPlan {
385 pub table: String,
386 pub target_relation_bound: bool,
387 pub relations_bound: bool,
389 pub statement_privilege_subject: Option<RoleReference>,
391 pub target_privilege_subject: Option<RoleReference>,
393 pub target_qualifier: String,
394 #[serde(default)]
395 pub target_alias: Option<String>,
396 pub include_descendants: bool,
397 pub columns: Vec<crate::ast::AssignmentTarget<ScalarExpr>>,
398 #[serde(default, skip_serializing_if = "Option::is_none")]
399 pub overriding: Option<crate::ast::OverridingKind>,
400 pub ctes: Vec<CtePlan>,
401 pub rows: Vec<Vec<ScalarExpr>>,
402 pub source: Option<Box<QueryPlan>>,
403 pub on_conflict: Option<ConflictPlan>,
404 pub returning: Vec<ProjectionPlan>,
405 pub returning_aliases: crate::ast::ReturningAliases,
406 pub subqueries: Vec<QueryPlan>,
407 pub view_checks: Vec<ViewCheckPlan>,
408 pub view_rule_relations: Vec<String>,
409 pub view_rule_insert_plans: Vec<ViewRuleInsertPlan>,
410 pub view_rule_returning: Option<ViewRuleReturningPlan>,
411}
412
413#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
414pub struct ConflictPlan {
415 pub predicate: Option<Box<ScalarExpr>>,
416 pub constraint: Option<String>,
417 pub conflict_columns: Vec<String>,
418 pub expressions: Vec<ScalarExpr>,
419 pub action: ConflictActionPlan,
420}
421
422#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
423pub enum ConflictActionPlan {
424 Nothing,
425 Update {
426 assignments: Vec<AssignmentPlan>,
427 predicate: Option<Box<ScalarExpr>>,
428 },
429}
430
431#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
432pub struct UpdatePlan {
433 pub table: String,
434 pub target_relation_bound: bool,
435 pub relations_bound: bool,
437 pub statement_privilege_subject: Option<RoleReference>,
439 pub target_privilege_subject: Option<RoleReference>,
441 pub target_qualifier: String,
442 #[serde(default)]
443 pub target_alias: Option<String>,
444 pub include_descendants: bool,
445 pub assignments: Vec<AssignmentPlan>,
446 pub predicate: Option<ScalarExpr>,
447 pub ctes: Vec<CtePlan>,
448 pub source: Option<Box<SourcePlan>>,
449 pub returning: Vec<ProjectionPlan>,
450 pub returning_aliases: crate::ast::ReturningAliases,
451 pub subqueries: Vec<QueryPlan>,
452 pub view_checks: Vec<ViewCheckPlan>,
453 pub view_rule_relations: Vec<String>,
454 pub view_rule_update_plans: Vec<ViewRuleUpdatePlan>,
455 pub view_rule_returning: Option<ViewRuleReturningPlan>,
456}
457
458#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
459pub struct DeletePlan {
460 pub table: String,
461 pub target_relation_bound: bool,
462 pub relations_bound: bool,
464 pub statement_privilege_subject: Option<RoleReference>,
466 pub target_privilege_subject: Option<RoleReference>,
468 pub target_qualifier: String,
469 #[serde(default)]
470 pub target_alias: Option<String>,
471 pub include_descendants: bool,
472 pub predicate: Option<ScalarExpr>,
473 pub ctes: Vec<CtePlan>,
474 pub source: Option<Box<SourcePlan>>,
475 pub returning: Vec<ProjectionPlan>,
476 pub returning_aliases: crate::ast::ReturningAliases,
477 pub subqueries: Vec<QueryPlan>,
478 pub view_rule_relations: Vec<String>,
479 pub view_rule_returning: Option<ViewRuleReturningPlan>,
480}
481
482#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
483pub struct MergePlan {
484 #[serde(default)]
485 pub ctes: Vec<CtePlan>,
486 pub target: String,
487 pub statement_privilege_subject: Option<RoleReference>,
489 pub target_privilege_subject: Option<RoleReference>,
491 pub target_qualifier: String,
492 pub target_alias: Option<String>,
493 pub include_descendants: bool,
494 pub target_predicate: Option<ScalarExpr>,
495 pub source: Box<SourcePlan>,
496 pub join_condition: ScalarExpr,
497 pub when_clauses: Vec<MergeWhenPlan>,
498 pub returning: Vec<ProjectionPlan>,
499 pub returning_aliases: crate::ast::ReturningAliases,
500 pub subqueries: Vec<QueryPlan>,
501 pub view_checks: Vec<ViewCheckPlan>,
502}
503
504#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
505pub enum MergeWhenPlan {
506 UpdateMatched {
507 condition: Option<ScalarExpr>,
508 assignments: Vec<AssignmentPlan>,
509 },
510 DeleteMatched {
511 condition: Option<ScalarExpr>,
512 },
513 UpdateNotMatchedBySource {
514 condition: Option<ScalarExpr>,
515 assignments: Vec<AssignmentPlan>,
516 },
517 DeleteNotMatchedBySource {
518 condition: Option<ScalarExpr>,
519 },
520 InsertNotMatched {
521 condition: Option<ScalarExpr>,
522 columns: Vec<crate::ast::AssignmentTarget<ScalarExpr>>,
523 #[serde(default, skip_serializing_if = "Option::is_none")]
524 overriding: Option<crate::ast::OverridingKind>,
525 values: Vec<ScalarExpr>,
526 },
527 NothingMatched {
528 condition: Option<ScalarExpr>,
529 },
530 NothingNotMatched {
531 condition: Option<ScalarExpr>,
532 },
533 NothingNotMatchedBySource {
534 condition: Option<ScalarExpr>,
535 },
536}
537
538#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
542pub enum CommandPlan {
543 CreateTable(Box<crate::ast::CreateTable>),
544 CreateTableIfNotExists(crate::ast::DeferredCreateTable),
545 CreateIndex(crate::ast::CreateIndex),
546 RenameIndex(crate::ast::RenameIndexStmt),
547 Insert(Box<InsertPlan>),
548 Update(Box<UpdatePlan>),
549 Delete(Box<DeletePlan>),
550 Drop(crate::ast::DropStmt),
551 AlterTable(Box<crate::ast::AlterTableStmt>),
552 AlterView(crate::ast::AlterViewStmt),
553 CreateView {
554 name: String,
555 column_names: Vec<String>,
556 query: Box<QueryPlan>,
557 or_replace: bool,
558 persistence: crate::ast::RelationPersistence,
559 options: Vec<(String, String)>,
560 },
561 CreateMaterializedView {
562 name: String,
563 column_names: Vec<String>,
564 if_not_exists: bool,
565 with_no_data: bool,
566 options: Vec<(String, String)>,
567 query: Box<QueryPlan>,
568 },
569 RefreshMaterializedView {
570 name: String,
571 concurrently: bool,
572 with_no_data: bool,
573 },
574 CreateSchema {
575 name: Option<String>,
576 if_not_exists: bool,
577 #[serde(default, skip_serializing_if = "Option::is_none")]
578 authorization: Option<crate::ast::SchemaAuthorization>,
579 },
580 AlterSchemaOwner {
581 name: String,
582 new_owner: crate::ast::RoleSpecification,
583 },
584 RenameSchema {
585 name: String,
586 new_name: String,
587 },
588 Notify {
589 channel: String,
590 payload: String,
591 },
592 Listen {
593 channel: String,
594 },
595 Unlisten {
596 channel: Option<String>,
597 },
598 SetVariable {
599 name: String,
600 value: String,
601 #[serde(default)]
602 local: bool,
603 #[serde(default)]
604 is_default: bool,
605 },
606 ResetVariable {
607 name: String,
608 },
609 ResetAllVariables,
610 SetConstraints {
611 constraints: Vec<crate::ast::SetConstraintName>,
612 deferred: bool,
613 },
614 ShowVariable {
615 name: String,
616 },
617 Discard {
618 target: crate::ast::DiscardTarget,
619 },
620 Load {
621 library: String,
622 },
623 Explain {
624 analyze: bool,
625 verbose: bool,
626 format: Option<String>,
627 body: Box<UnifiedPlan>,
628 },
629 Analyze {
630 table: Option<String>,
631 },
632 Vacuum(crate::ast::VacuumStmt),
633 LockTable(crate::ast::LockTableStmt),
634 Truncate {
635 tables: Vec<crate::ast::TruncateTarget>,
636 cascade: bool,
637 restart_identity: bool,
638 },
639 Transaction(crate::ast::TransactionStmt),
640 DeclareCursor {
641 name: String,
642 binary: bool,
643 scroll: Option<bool>,
644 hold: bool,
645 query: Box<QueryPlan>,
646 },
647 FetchCursor(crate::ast::FetchCursorStmt),
648 CloseCursor {
649 name: Option<String>,
650 },
651 CreateSequence(crate::ast::CreateSequence),
652 CreateDomain(crate::ast::CreateDomain),
653 AlterDomain(crate::ast::AlterDomain),
654 CreateEnum(crate::ast::CreateEnum),
655 CreateCompositeType(crate::ast::CreateCompositeType),
656 AlterEnum(crate::ast::AlterEnum),
657 AlterTypeObject(crate::ast::AlterTypeObject),
658 GrantType(crate::ast::GrantTypeStmt),
659 AlterSequence(crate::ast::AlterSequence),
660 CreateTableAs {
661 name: String,
662 if_not_exists: bool,
663 column_names: Vec<String>,
664 with_no_data: bool,
665 #[serde(default)]
667 select_into: bool,
668 persistence: crate::ast::RelationPersistence,
669 on_commit: crate::ast::OnCommitAction,
670 query: Box<QueryPlan>,
671 },
672 Prepare {
673 name: String,
674 #[serde(default)]
675 parameter_types: Vec<crate::ast::ColumnType>,
676 body: Box<UnifiedPlan>,
677 },
678 Execute {
679 name: String,
680 params: Vec<ExpressionPlan>,
681 },
682 Deallocate {
683 name: Option<String>,
684 },
685 CreateForeignWrapper(crate::ast::CreateForeignWrapper),
686 CreateForeignServer(crate::ast::CreateForeignServer),
687 CreateForeignTable(crate::ast::CreateForeignTable),
688 #[serde(alias = "CreateForeignTableIfNotExists")]
689 CreateForeignTableDefinition(crate::ast::DeferredCreateForeignTable),
690 AlterForeignTable(crate::ast::AlterForeignTableStmt),
691 Merge(Box<MergePlan>),
692 CreateFunction(Box<crate::ast::CreateFunction>),
693 DropFunction(crate::ast::DropFunctionStmt),
694 AlterRoutine(crate::ast::AlterRoutineStmt),
695 AlterRoutineOwner(crate::ast::AlterRoutineOwnerStmt),
696 RenameRoutine(crate::ast::RenameRoutineStmt),
697 GrantRoutine(crate::ast::GrantRoutineStmt),
698 GrantTable(crate::ast::GrantTableStmt),
699 GrantSequence(crate::ast::GrantSequenceStmt),
700 GrantDatabase(crate::ast::GrantDatabaseStmt),
701 GrantSchema(crate::ast::GrantSchemaStmt),
702 GrantRole(crate::ast::GrantRoleStmt),
703 CreateRole(crate::ast::CreateRoleStmt),
704 AlterRole(crate::ast::AlterRoleStmt),
705 RenameRole(crate::ast::RenameRoleStmt),
706 DropRole(crate::ast::DropRoleStmt),
707 CreateTrigger(crate::ast::CreateTrigger),
708 DropTrigger(crate::ast::DropTrigger),
709 CreateRule(crate::ast::CreateRule),
710 DropRule(crate::ast::DropRule),
711 DoBlock {
712 language: String,
713 body: String,
714 },
715 Call {
716 name: String,
717 args: Vec<ExpressionPlan>,
718 },
719}
720
721pub trait AggregateClassifier {
725 fn is_registered_aggregate(&self, name: &str) -> bool;
726}
727
728impl<F> AggregateClassifier for F
729where
730 F: Fn(&str) -> bool,
731{
732 fn is_registered_aggregate(&self, name: &str) -> bool {
733 self(name)
734 }
735}
736
737pub(super) struct NoRegisteredAggregates;
738
739impl AggregateClassifier for NoRegisteredAggregates {
740 fn is_registered_aggregate(&self, _name: &str) -> bool {
741 false
742 }
743}