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 pub projections: Vec<ProjectionPlan>,
161 pub from: Option<SourcePlan>,
162 pub r#where: Option<ScalarExpr>,
163 pub compute: ComputePlan,
164 pub group_by: Vec<ScalarExpr>,
165 pub grouping_sets: Vec<Vec<ScalarExpr>>,
166 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
167 pub group_distinct: bool,
168 pub having: Option<ScalarExpr>,
169 pub order_by: Vec<OrderPlan>,
170 pub limit: Option<ScalarExpr>,
171 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
172 pub with_ties: bool,
173 pub offset: Option<ScalarExpr>,
174 pub distinct: bool,
175 pub distinct_on: Vec<ScalarExpr>,
176 pub subqueries: Vec<QueryPlan>,
177 pub access: AccessPathPlan,
178 #[serde(default, skip_serializing_if = "Vec::is_empty")]
180 pub locking: Vec<crate::ast::LockingClause>,
181}
182
183#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
186pub enum AccessPathPlan {
187 Row,
189 OperatorTree {
191 score_limit_pushdown: bool,
194 },
195 Hybrid,
198}
199
200#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
208pub enum JoinExecutionStrategy {
209 #[default]
210 Auto,
211 Hash,
212}
213
214#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
216pub struct TableFunctionPlan {
217 pub name: String,
218 #[serde(default, skip_serializing_if = "Option::is_none")]
219 pub binding: Option<crate::ast::FunctionBinding>,
220 #[serde(default)]
221 pub output_name: String,
222 #[serde(default, skip_serializing_if = "Option::is_none")]
223 pub relations: Option<crate::ast::OperatorJoinRelations>,
224 pub args: Vec<ScalarExpr>,
225 pub column_aliases: Vec<String>,
226 pub column_types: Vec<String>,
227}
228
229#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
231pub enum SourcePlan {
232 Table {
233 name: String,
234 #[serde(default)]
235 qualifier: String,
236 alias: Option<String>,
237 #[serde(default, skip_serializing_if = "Vec::is_empty")]
238 column_aliases: Vec<String>,
239 #[serde(default, skip_serializing_if = "Option::is_none")]
240 bound_columns: Option<Vec<String>>,
241 #[serde(default = "default_include_descendants")]
242 include_descendants: bool,
243 },
244 Join {
245 left: Box<SourcePlan>,
246 right: Box<SourcePlan>,
247 kind: crate::ast::JoinKind,
248 on: Option<ScalarExpr>,
249 #[serde(default, skip_serializing_if = "Option::is_none")]
250 using: Option<crate::ast::JoinUsing>,
251 #[serde(default)]
252 natural: bool,
253 #[serde(default, skip_serializing_if = "Option::is_none")]
254 alias: Option<String>,
255 #[serde(default, skip_serializing_if = "Vec::is_empty")]
256 column_aliases: Vec<String>,
257 lateral: bool,
258 #[serde(default)]
259 strategy: JoinExecutionStrategy,
260 },
261 Values {
262 rows: Vec<Vec<ScalarExpr>>,
263 alias: Option<String>,
264 column_aliases: Vec<String>,
265 #[serde(default, skip_serializing_if = "Option::is_none")]
266 internal_relation: Option<crate::ast::InternalRelationId>,
267 #[serde(default, skip_serializing_if = "Vec::is_empty")]
268 internal_column_types: Vec<Option<crate::ast::ColumnType>>,
269 },
270 Function {
271 name: String,
272 #[serde(default, skip_serializing_if = "Option::is_none")]
273 binding: Option<crate::ast::FunctionBinding>,
274 #[serde(default)]
275 output_name: String,
276 #[serde(default, skip_serializing_if = "Option::is_none")]
277 relations: Option<crate::ast::OperatorJoinRelations>,
278 args: Vec<ScalarExpr>,
279 alias: Option<String>,
280 column_aliases: Vec<String>,
281 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
282 ordinality: bool,
283 column_types: Vec<String>,
284 },
285 FunctionGroup {
286 functions: Vec<TableFunctionPlan>,
287 alias: Option<String>,
288 column_aliases: Vec<String>,
289 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
290 ordinality: bool,
291 },
292 Subquery {
293 body: Box<QueryPlan>,
294 alias: Option<String>,
295 column_aliases: Vec<String>,
296 },
297}
298
299#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
301pub enum ComputePlan {
302 Project,
303 Aggregate,
304 Window,
305}
306
307#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
308pub struct ProjectionPlan {
309 pub expr: ScalarExpr,
310 pub alias: Option<String>,
311}
312
313#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
314pub struct OrderPlan {
315 pub expr: ScalarExpr,
316 pub descending: bool,
317 pub nulls: Option<NullsOrder>,
318}
319
320#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
322pub struct ExpressionPlan {
323 pub scalar: ScalarExpr,
324 pub subqueries: Vec<QueryPlan>,
325}
326
327#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
328pub struct AssignmentPlan {
329 #[serde(rename = "column")]
330 pub target: crate::ast::AssignmentTarget<ScalarExpr>,
331 pub value: ScalarExpr,
332}
333
334impl AssignmentPlan {
335 pub fn expressions(&self) -> impl Iterator<Item = &ScalarExpr> {
336 self.target
337 .expressions()
338 .chain(std::iter::once(&self.value))
339 }
340
341 pub fn expressions_mut(&mut self) -> impl Iterator<Item = &mut ScalarExpr> {
342 self.target
343 .expressions_mut()
344 .chain(std::iter::once(&mut self.value))
345 }
346}
347
348#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
349pub struct ViewCheckPlan {
350 pub view: String,
351 pub predicate: ScalarExpr,
352}
353
354#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
355pub struct ViewRuleReturningPlan {
356 pub relation: String,
357 pub target_qualifier: String,
358 pub returning: Vec<ProjectionPlan>,
359 pub aliases: crate::ast::ReturningAliases,
360 pub subqueries: Vec<QueryPlan>,
361}
362
363#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
364pub struct ViewRuleInsertPlan {
365 pub relation: String,
366 pub supplied_columns: Vec<String>,
367 pub input_columns: Vec<String>,
368}
369
370#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
371pub struct ViewRuleUpdatePlan {
372 pub relation: String,
373 pub assigned_columns: Vec<String>,
374 pub input_columns: Vec<String>,
375}
376
377#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
378pub struct InsertPlan {
379 pub table: String,
380 pub target_relation_bound: bool,
381 pub relations_bound: bool,
383 pub statement_privilege_subject: Option<RoleReference>,
385 pub target_privilege_subject: Option<RoleReference>,
387 pub target_qualifier: String,
388 pub include_descendants: bool,
389 pub columns: Vec<crate::ast::AssignmentTarget<ScalarExpr>>,
390 #[serde(default, skip_serializing_if = "Option::is_none")]
391 pub overriding: Option<crate::ast::OverridingKind>,
392 pub ctes: Vec<CtePlan>,
393 pub rows: Vec<Vec<ScalarExpr>>,
394 pub source: Option<Box<QueryPlan>>,
395 pub on_conflict: Option<ConflictPlan>,
396 pub returning: Vec<ProjectionPlan>,
397 pub returning_aliases: crate::ast::ReturningAliases,
398 pub subqueries: Vec<QueryPlan>,
399 pub view_checks: Vec<ViewCheckPlan>,
400 pub view_rule_relations: Vec<String>,
401 pub view_rule_insert_plans: Vec<ViewRuleInsertPlan>,
402 pub view_rule_returning: Option<ViewRuleReturningPlan>,
403}
404
405#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
406pub struct ConflictPlan {
407 pub predicate: Option<Box<ScalarExpr>>,
408 pub constraint: Option<String>,
409 pub conflict_columns: Vec<String>,
410 pub expressions: Vec<ScalarExpr>,
411 pub action: ConflictActionPlan,
412}
413
414#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
415pub enum ConflictActionPlan {
416 Nothing,
417 Update {
418 assignments: Vec<AssignmentPlan>,
419 predicate: Option<Box<ScalarExpr>>,
420 },
421}
422
423#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
424pub struct UpdatePlan {
425 pub table: String,
426 pub target_relation_bound: bool,
427 pub relations_bound: bool,
429 pub statement_privilege_subject: Option<RoleReference>,
431 pub target_privilege_subject: Option<RoleReference>,
433 pub target_qualifier: String,
434 pub include_descendants: bool,
435 pub assignments: Vec<AssignmentPlan>,
436 pub predicate: Option<ScalarExpr>,
437 pub ctes: Vec<CtePlan>,
438 pub source: Option<Box<SourcePlan>>,
439 pub returning: Vec<ProjectionPlan>,
440 pub returning_aliases: crate::ast::ReturningAliases,
441 pub subqueries: Vec<QueryPlan>,
442 pub view_checks: Vec<ViewCheckPlan>,
443 pub view_rule_relations: Vec<String>,
444 pub view_rule_update_plans: Vec<ViewRuleUpdatePlan>,
445 pub view_rule_returning: Option<ViewRuleReturningPlan>,
446}
447
448#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
449pub struct DeletePlan {
450 pub table: String,
451 pub target_relation_bound: bool,
452 pub relations_bound: bool,
454 pub statement_privilege_subject: Option<RoleReference>,
456 pub target_privilege_subject: Option<RoleReference>,
458 pub target_qualifier: String,
459 pub include_descendants: bool,
460 pub predicate: Option<ScalarExpr>,
461 pub ctes: Vec<CtePlan>,
462 pub source: Option<Box<SourcePlan>>,
463 pub returning: Vec<ProjectionPlan>,
464 pub returning_aliases: crate::ast::ReturningAliases,
465 pub subqueries: Vec<QueryPlan>,
466 pub view_rule_relations: Vec<String>,
467 pub view_rule_returning: Option<ViewRuleReturningPlan>,
468}
469
470#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
471pub struct MergePlan {
472 #[serde(default)]
473 pub ctes: Vec<CtePlan>,
474 pub target: String,
475 pub statement_privilege_subject: Option<RoleReference>,
477 pub target_privilege_subject: Option<RoleReference>,
479 pub target_qualifier: String,
480 pub target_alias: Option<String>,
481 pub include_descendants: bool,
482 pub target_predicate: Option<ScalarExpr>,
483 pub source: Box<SourcePlan>,
484 pub join_condition: ScalarExpr,
485 pub when_clauses: Vec<MergeWhenPlan>,
486 pub returning: Vec<ProjectionPlan>,
487 pub returning_aliases: crate::ast::ReturningAliases,
488 pub subqueries: Vec<QueryPlan>,
489 pub view_checks: Vec<ViewCheckPlan>,
490}
491
492#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
493pub enum MergeWhenPlan {
494 UpdateMatched {
495 condition: Option<ScalarExpr>,
496 assignments: Vec<AssignmentPlan>,
497 },
498 DeleteMatched {
499 condition: Option<ScalarExpr>,
500 },
501 UpdateNotMatchedBySource {
502 condition: Option<ScalarExpr>,
503 assignments: Vec<AssignmentPlan>,
504 },
505 DeleteNotMatchedBySource {
506 condition: Option<ScalarExpr>,
507 },
508 InsertNotMatched {
509 condition: Option<ScalarExpr>,
510 columns: Vec<crate::ast::AssignmentTarget<ScalarExpr>>,
511 #[serde(default, skip_serializing_if = "Option::is_none")]
512 overriding: Option<crate::ast::OverridingKind>,
513 values: Vec<ScalarExpr>,
514 },
515 NothingMatched {
516 condition: Option<ScalarExpr>,
517 },
518 NothingNotMatched {
519 condition: Option<ScalarExpr>,
520 },
521 NothingNotMatchedBySource {
522 condition: Option<ScalarExpr>,
523 },
524}
525
526#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
530pub enum CommandPlan {
531 CreateTable(Box<crate::ast::CreateTable>),
532 CreateTableIfNotExists(crate::ast::DeferredCreateTable),
533 CreateIndex(crate::ast::CreateIndex),
534 RenameIndex(crate::ast::RenameIndexStmt),
535 Insert(Box<InsertPlan>),
536 Update(Box<UpdatePlan>),
537 Delete(Box<DeletePlan>),
538 Drop(crate::ast::DropStmt),
539 AlterTable(Box<crate::ast::AlterTableStmt>),
540 AlterView(crate::ast::AlterViewStmt),
541 CreateView {
542 name: String,
543 column_names: Vec<String>,
544 query: Box<QueryPlan>,
545 or_replace: bool,
546 persistence: crate::ast::RelationPersistence,
547 options: Vec<(String, String)>,
548 },
549 CreateMaterializedView {
550 name: String,
551 column_names: Vec<String>,
552 if_not_exists: bool,
553 with_no_data: bool,
554 options: Vec<(String, String)>,
555 query: Box<QueryPlan>,
556 },
557 RefreshMaterializedView {
558 name: String,
559 concurrently: bool,
560 with_no_data: bool,
561 },
562 CreateSchema {
563 name: Option<String>,
564 if_not_exists: bool,
565 #[serde(default, skip_serializing_if = "Option::is_none")]
566 authorization: Option<crate::ast::SchemaAuthorization>,
567 },
568 AlterSchemaOwner {
569 name: String,
570 new_owner: crate::ast::RoleSpecification,
571 },
572 Notify {
573 channel: String,
574 payload: String,
575 },
576 Listen {
577 channel: String,
578 },
579 Unlisten {
580 channel: Option<String>,
581 },
582 SetVariable {
583 name: String,
584 value: String,
585 #[serde(default)]
586 local: bool,
587 #[serde(default)]
588 is_default: bool,
589 },
590 ResetVariable {
591 name: String,
592 },
593 ResetAllVariables,
594 SetConstraints {
595 constraints: Vec<crate::ast::SetConstraintName>,
596 deferred: bool,
597 },
598 ShowVariable {
599 name: String,
600 },
601 Discard {
602 target: crate::ast::DiscardTarget,
603 },
604 Load {
605 library: String,
606 },
607 Explain {
608 analyze: bool,
609 verbose: bool,
610 format: Option<String>,
611 body: Box<UnifiedPlan>,
612 },
613 Analyze {
614 table: Option<String>,
615 },
616 Vacuum(crate::ast::VacuumStmt),
617 LockTable(crate::ast::LockTableStmt),
618 Truncate {
619 tables: Vec<crate::ast::TruncateTarget>,
620 cascade: bool,
621 restart_identity: bool,
622 },
623 Transaction(crate::ast::TransactionStmt),
624 DeclareCursor {
625 name: String,
626 binary: bool,
627 scroll: Option<bool>,
628 hold: bool,
629 query: Box<QueryPlan>,
630 },
631 FetchCursor(crate::ast::FetchCursorStmt),
632 CloseCursor {
633 name: Option<String>,
634 },
635 CreateSequence(crate::ast::CreateSequence),
636 CreateDomain(crate::ast::CreateDomain),
637 AlterSequence(crate::ast::AlterSequence),
638 CreateTableAs {
639 name: String,
640 if_not_exists: bool,
641 column_names: Vec<String>,
642 with_no_data: bool,
643 persistence: crate::ast::RelationPersistence,
644 on_commit: crate::ast::OnCommitAction,
645 query: Box<QueryPlan>,
646 },
647 Prepare {
648 name: String,
649 #[serde(default)]
650 parameter_types: Vec<crate::ast::ColumnType>,
651 body: Box<UnifiedPlan>,
652 },
653 Execute {
654 name: String,
655 params: Vec<ExpressionPlan>,
656 },
657 Deallocate {
658 name: Option<String>,
659 },
660 CreateForeignServer(crate::ast::CreateForeignServer),
661 CreateForeignTable(crate::ast::CreateForeignTable),
662 CreateForeignTableIfNotExists(crate::ast::DeferredCreateForeignTable),
663 AlterForeignTable(crate::ast::AlterForeignTableStmt),
664 Merge(Box<MergePlan>),
665 CreateFunction(Box<crate::ast::CreateFunction>),
666 DropFunction(crate::ast::DropFunctionStmt),
667 AlterRoutine(crate::ast::AlterRoutineStmt),
668 AlterRoutineOwner(crate::ast::AlterRoutineOwnerStmt),
669 RenameRoutine(crate::ast::RenameRoutineStmt),
670 GrantRoutine(crate::ast::GrantRoutineStmt),
671 GrantTable(crate::ast::GrantTableStmt),
672 GrantSequence(crate::ast::GrantSequenceStmt),
673 GrantDatabase(crate::ast::GrantDatabaseStmt),
674 GrantSchema(crate::ast::GrantSchemaStmt),
675 GrantRole(crate::ast::GrantRoleStmt),
676 CreateRole(crate::ast::CreateRoleStmt),
677 AlterRole(crate::ast::AlterRoleStmt),
678 RenameRole(crate::ast::RenameRoleStmt),
679 DropRole(crate::ast::DropRoleStmt),
680 CreateTrigger(crate::ast::CreateTrigger),
681 DropTrigger(crate::ast::DropTrigger),
682 CreateRule(crate::ast::CreateRule),
683 DropRule(crate::ast::DropRule),
684 DoBlock {
685 language: String,
686 body: String,
687 },
688 Call {
689 name: String,
690 args: Vec<ExpressionPlan>,
691 },
692}
693
694pub trait AggregateClassifier {
698 fn is_registered_aggregate(&self, name: &str) -> bool;
699}
700
701impl<F> AggregateClassifier for F
702where
703 F: Fn(&str) -> bool,
704{
705 fn is_registered_aggregate(&self, name: &str) -> bool {
706 self(name)
707 }
708}
709
710pub(super) struct NoRegisteredAggregates;
711
712impl AggregateClassifier for NoRegisteredAggregates {
713 fn is_registered_aggregate(&self, _name: &str) -> bool {
714 false
715 }
716}