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 pub ctes: Vec<CtePlan>,
391 pub rows: Vec<Vec<ScalarExpr>>,
392 pub source: Option<Box<QueryPlan>>,
393 pub on_conflict: Option<ConflictPlan>,
394 pub returning: Vec<ProjectionPlan>,
395 pub returning_aliases: crate::ast::ReturningAliases,
396 pub subqueries: Vec<QueryPlan>,
397 pub view_checks: Vec<ViewCheckPlan>,
398 pub view_rule_relations: Vec<String>,
399 pub view_rule_insert_plans: Vec<ViewRuleInsertPlan>,
400 pub view_rule_returning: Option<ViewRuleReturningPlan>,
401}
402
403#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
404pub struct ConflictPlan {
405 pub predicate: Option<Box<ScalarExpr>>,
406 pub constraint: Option<String>,
407 pub conflict_columns: Vec<String>,
408 pub expressions: Vec<ScalarExpr>,
409 pub action: ConflictActionPlan,
410}
411
412#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
413pub enum ConflictActionPlan {
414 Nothing,
415 Update {
416 assignments: Vec<AssignmentPlan>,
417 predicate: Option<Box<ScalarExpr>>,
418 },
419}
420
421#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
422pub struct UpdatePlan {
423 pub table: String,
424 pub target_relation_bound: bool,
425 pub relations_bound: bool,
427 pub statement_privilege_subject: Option<RoleReference>,
429 pub target_privilege_subject: Option<RoleReference>,
431 pub target_qualifier: String,
432 pub include_descendants: bool,
433 pub assignments: Vec<AssignmentPlan>,
434 pub predicate: Option<ScalarExpr>,
435 pub ctes: Vec<CtePlan>,
436 pub source: Option<Box<SourcePlan>>,
437 pub returning: Vec<ProjectionPlan>,
438 pub returning_aliases: crate::ast::ReturningAliases,
439 pub subqueries: Vec<QueryPlan>,
440 pub view_checks: Vec<ViewCheckPlan>,
441 pub view_rule_relations: Vec<String>,
442 pub view_rule_update_plans: Vec<ViewRuleUpdatePlan>,
443 pub view_rule_returning: Option<ViewRuleReturningPlan>,
444}
445
446#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
447pub struct DeletePlan {
448 pub table: String,
449 pub target_relation_bound: bool,
450 pub relations_bound: bool,
452 pub statement_privilege_subject: Option<RoleReference>,
454 pub target_privilege_subject: Option<RoleReference>,
456 pub target_qualifier: String,
457 pub include_descendants: bool,
458 pub predicate: Option<ScalarExpr>,
459 pub ctes: Vec<CtePlan>,
460 pub source: Option<Box<SourcePlan>>,
461 pub returning: Vec<ProjectionPlan>,
462 pub returning_aliases: crate::ast::ReturningAliases,
463 pub subqueries: Vec<QueryPlan>,
464 pub view_rule_relations: Vec<String>,
465 pub view_rule_returning: Option<ViewRuleReturningPlan>,
466}
467
468#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
469pub struct MergePlan {
470 #[serde(default)]
471 pub ctes: Vec<CtePlan>,
472 pub target: String,
473 pub statement_privilege_subject: Option<RoleReference>,
475 pub target_privilege_subject: Option<RoleReference>,
477 pub target_qualifier: String,
478 pub target_alias: Option<String>,
479 pub include_descendants: bool,
480 pub target_predicate: Option<ScalarExpr>,
481 pub source: Box<SourcePlan>,
482 pub join_condition: ScalarExpr,
483 pub when_clauses: Vec<MergeWhenPlan>,
484 pub returning: Vec<ProjectionPlan>,
485 pub returning_aliases: crate::ast::ReturningAliases,
486 pub subqueries: Vec<QueryPlan>,
487 pub view_checks: Vec<ViewCheckPlan>,
488}
489
490#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
491pub enum MergeWhenPlan {
492 UpdateMatched {
493 condition: Option<ScalarExpr>,
494 assignments: Vec<AssignmentPlan>,
495 },
496 DeleteMatched {
497 condition: Option<ScalarExpr>,
498 },
499 UpdateNotMatchedBySource {
500 condition: Option<ScalarExpr>,
501 assignments: Vec<AssignmentPlan>,
502 },
503 DeleteNotMatchedBySource {
504 condition: Option<ScalarExpr>,
505 },
506 InsertNotMatched {
507 condition: Option<ScalarExpr>,
508 columns: Vec<crate::ast::AssignmentTarget<ScalarExpr>>,
509 values: Vec<ScalarExpr>,
510 },
511 NothingMatched {
512 condition: Option<ScalarExpr>,
513 },
514 NothingNotMatched {
515 condition: Option<ScalarExpr>,
516 },
517 NothingNotMatchedBySource {
518 condition: Option<ScalarExpr>,
519 },
520}
521
522#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
526pub enum CommandPlan {
527 CreateTable(Box<crate::ast::CreateTable>),
528 CreateTableIfNotExists(crate::ast::DeferredCreateTable),
529 CreateIndex(crate::ast::CreateIndex),
530 RenameIndex(crate::ast::RenameIndexStmt),
531 Insert(Box<InsertPlan>),
532 Update(Box<UpdatePlan>),
533 Delete(Box<DeletePlan>),
534 Drop(crate::ast::DropStmt),
535 AlterTable(Box<crate::ast::AlterTableStmt>),
536 AlterView(crate::ast::AlterViewStmt),
537 CreateView {
538 name: String,
539 column_names: Vec<String>,
540 query: Box<QueryPlan>,
541 or_replace: bool,
542 persistence: crate::ast::RelationPersistence,
543 options: Vec<(String, String)>,
544 },
545 CreateMaterializedView {
546 name: String,
547 column_names: Vec<String>,
548 if_not_exists: bool,
549 with_no_data: bool,
550 options: Vec<(String, String)>,
551 query: Box<QueryPlan>,
552 },
553 RefreshMaterializedView {
554 name: String,
555 concurrently: bool,
556 with_no_data: bool,
557 },
558 CreateSchema {
559 name: Option<String>,
560 if_not_exists: bool,
561 #[serde(default, skip_serializing_if = "Option::is_none")]
562 authorization: Option<crate::ast::SchemaAuthorization>,
563 },
564 AlterSchemaOwner {
565 name: String,
566 new_owner: crate::ast::RoleSpecification,
567 },
568 Notify {
569 channel: String,
570 payload: String,
571 },
572 Listen {
573 channel: String,
574 },
575 Unlisten {
576 channel: Option<String>,
577 },
578 SetVariable {
579 name: String,
580 value: String,
581 #[serde(default)]
582 local: bool,
583 #[serde(default)]
584 is_default: bool,
585 },
586 ResetVariable {
587 name: String,
588 },
589 ResetAllVariables,
590 SetConstraints {
591 constraints: Vec<crate::ast::SetConstraintName>,
592 deferred: bool,
593 },
594 ShowVariable {
595 name: String,
596 },
597 Discard {
598 target: crate::ast::DiscardTarget,
599 },
600 Load {
601 library: String,
602 },
603 Explain {
604 analyze: bool,
605 verbose: bool,
606 format: Option<String>,
607 body: Box<UnifiedPlan>,
608 },
609 Analyze {
610 table: Option<String>,
611 },
612 Vacuum(crate::ast::VacuumStmt),
613 LockTable(crate::ast::LockTableStmt),
614 Truncate {
615 tables: Vec<crate::ast::TruncateTarget>,
616 cascade: bool,
617 restart_identity: bool,
618 },
619 Transaction(crate::ast::TransactionStmt),
620 DeclareCursor {
621 name: String,
622 binary: bool,
623 scroll: Option<bool>,
624 hold: bool,
625 query: Box<QueryPlan>,
626 },
627 FetchCursor(crate::ast::FetchCursorStmt),
628 CloseCursor {
629 name: Option<String>,
630 },
631 CreateSequence(crate::ast::CreateSequence),
632 CreateDomain(crate::ast::CreateDomain),
633 AlterSequence(crate::ast::AlterSequence),
634 CreateTableAs {
635 name: String,
636 if_not_exists: bool,
637 column_names: Vec<String>,
638 with_no_data: bool,
639 persistence: crate::ast::RelationPersistence,
640 on_commit: crate::ast::OnCommitAction,
641 query: Box<QueryPlan>,
642 },
643 Prepare {
644 name: String,
645 #[serde(default)]
646 parameter_types: Vec<crate::ast::ColumnType>,
647 body: Box<UnifiedPlan>,
648 },
649 Execute {
650 name: String,
651 params: Vec<ExpressionPlan>,
652 },
653 Deallocate {
654 name: Option<String>,
655 },
656 CreateForeignServer(crate::ast::CreateForeignServer),
657 CreateForeignTable(crate::ast::CreateForeignTable),
658 CreateForeignTableIfNotExists(crate::ast::DeferredCreateForeignTable),
659 AlterForeignTable(crate::ast::AlterForeignTableStmt),
660 Merge(Box<MergePlan>),
661 CreateFunction(Box<crate::ast::CreateFunction>),
662 DropFunction(crate::ast::DropFunctionStmt),
663 AlterRoutine(crate::ast::AlterRoutineStmt),
664 AlterRoutineOwner(crate::ast::AlterRoutineOwnerStmt),
665 RenameRoutine(crate::ast::RenameRoutineStmt),
666 GrantRoutine(crate::ast::GrantRoutineStmt),
667 GrantTable(crate::ast::GrantTableStmt),
668 GrantSequence(crate::ast::GrantSequenceStmt),
669 GrantDatabase(crate::ast::GrantDatabaseStmt),
670 GrantSchema(crate::ast::GrantSchemaStmt),
671 GrantRole(crate::ast::GrantRoleStmt),
672 CreateRole(crate::ast::CreateRoleStmt),
673 AlterRole(crate::ast::AlterRoleStmt),
674 RenameRole(crate::ast::RenameRoleStmt),
675 DropRole(crate::ast::DropRoleStmt),
676 CreateTrigger(crate::ast::CreateTrigger),
677 DropTrigger(crate::ast::DropTrigger),
678 CreateRule(crate::ast::CreateRule),
679 DropRule(crate::ast::DropRule),
680 DoBlock {
681 language: String,
682 body: String,
683 },
684 Call {
685 name: String,
686 args: Vec<ExpressionPlan>,
687 },
688}
689
690pub trait AggregateClassifier {
694 fn is_registered_aggregate(&self, name: &str) -> bool;
695}
696
697impl<F> AggregateClassifier for F
698where
699 F: Fn(&str) -> bool,
700{
701 fn is_registered_aggregate(&self, name: &str) -> bool {
702 self(name)
703 }
704}
705
706pub(super) struct NoRegisteredAggregates;
707
708impl AggregateClassifier for NoRegisteredAggregates {
709 fn is_registered_aggregate(&self, _name: &str) -> bool {
710 false
711 }
712}