Skip to main content

rudb_catalog/
view.rs

1//! A view: a name, the query it stands for, and the names its columns answer to.
2//!
3//! The body is text rather than anything bound. A view in DuckDB follows the tables underneath it,
4//! which was measured: a view over `SELECT * FROM t` picks up a column that `ALTER TABLE t ADD
5//! COLUMN` added after the view was created, and a view over a table that was then dropped is an
6//! error when it is selected from rather than when the table went. Neither of those is possible if
7//! what the catalog keeps is a plan, because a plan has the columns of the day it was built baked
8//! into it. So the catalog keeps the query and the binder binds it again at every reference.
9
10use crate::name::QualifiedName;
11
12/// One view.
13#[derive(Debug, Clone)]
14pub struct View {
15    name: QualifiedName,
16    sql: String,
17    aliases: Vec<String>,
18}
19
20impl View {
21    /// A view over `sql`, whose columns answer to `aliases` as far as that list goes.
22    #[must_use]
23    pub fn new(name: QualifiedName, sql: String, aliases: Vec<String>) -> Self {
24        Self { name, sql, aliases }
25    }
26
27    /// The three part name.
28    #[must_use]
29    pub fn name(&self) -> &QualifiedName {
30        &self.name
31    }
32
33    /// The body, as the text that was written.
34    #[must_use]
35    pub fn sql(&self) -> &str {
36        &self.sql
37    }
38
39    /// The column names the statement gave, which rename a prefix of what the body produces.
40    ///
41    /// Shorter than the body's output, or empty, is the ordinary case. `CREATE VIEW v (a) AS SELECT
42    /// 1, 2` answers under `a` and `2`, which was measured, so a short list is a rename of the front
43    /// of the list and not a projection down to it. Longer is refused by the binder before a view
44    /// is ever made.
45    #[must_use]
46    pub fn aliases(&self) -> &[String] {
47        &self.aliases
48    }
49}