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