@@ -1546,6 +1546,281 @@ impl fmt::Display for AlterPasswordPolicyOperation {
15461546 }
15471547}
15481548
1549+ /// The `PRIVATE` / `PUBLIC` access modifier on a semantic view fact or metric.
1550+ ///
1551+ /// See <https://docs.snowflake.com/en/sql-reference/sql/create-semantic-view>
1552+ #[ derive( Debug , Clone , Copy , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
1553+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
1554+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
1555+ pub enum SemanticViewColumnAccess {
1556+ /// `PRIVATE` — the fact or metric cannot be queried directly.
1557+ Private ,
1558+ /// `PUBLIC` — the default; the element can be queried.
1559+ Public ,
1560+ }
1561+
1562+ impl fmt:: Display for SemanticViewColumnAccess {
1563+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1564+ match self {
1565+ SemanticViewColumnAccess :: Private => write ! ( f, "PRIVATE" ) ,
1566+ SemanticViewColumnAccess :: Public => write ! ( f, "PUBLIC" ) ,
1567+ }
1568+ }
1569+ }
1570+
1571+ fn fmt_semantic_view_synonyms ( f : & mut fmt:: Formatter , synonyms : & [ String ] ) -> fmt:: Result {
1572+ write ! ( f, " WITH SYNONYMS (" ) ?;
1573+ for ( i, synonym) in synonyms. iter ( ) . enumerate ( ) {
1574+ if i > 0 {
1575+ write ! ( f, ", " ) ?;
1576+ }
1577+ write ! ( f, "'{}'" , escape_single_quote_string( synonym) ) ?;
1578+ }
1579+ write ! ( f, ")" )
1580+ }
1581+
1582+ /// A logical table in the `TABLES (...)` clause of a `CREATE SEMANTIC VIEW`.
1583+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
1584+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
1585+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
1586+ pub struct SemanticViewTable {
1587+ /// Optional `<alias> AS` used to refer to the table elsewhere.
1588+ pub alias : Option < Ident > ,
1589+ /// The physical table name.
1590+ pub name : ObjectName ,
1591+ /// `PRIMARY KEY ( ... )` columns (empty if absent).
1592+ pub primary_key : Vec < Ident > ,
1593+ /// Zero or more `UNIQUE ( ... )` column groups.
1594+ pub unique : Vec < Vec < Ident > > ,
1595+ /// `WITH SYNONYMS ( ... )` values (empty if absent).
1596+ pub synonyms : Vec < String > ,
1597+ /// `WITH TAG ( ... )` entries (empty if absent).
1598+ pub tags : Vec < Tag > ,
1599+ /// `COMMENT = '...'`.
1600+ pub comment : Option < String > ,
1601+ }
1602+
1603+ impl fmt:: Display for SemanticViewTable {
1604+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1605+ if let Some ( alias) = & self . alias {
1606+ write ! ( f, "{alias} AS " ) ?;
1607+ }
1608+ write ! ( f, "{}" , self . name) ?;
1609+ if !self . primary_key . is_empty ( ) {
1610+ write ! ( f, " PRIMARY KEY ({})" , display_comma_separated( & self . primary_key) ) ?;
1611+ }
1612+ for unique in & self . unique {
1613+ write ! ( f, " UNIQUE ({})" , display_comma_separated( unique) ) ?;
1614+ }
1615+ if !self . synonyms . is_empty ( ) {
1616+ fmt_semantic_view_synonyms ( f, & self . synonyms ) ?;
1617+ }
1618+ if !self . tags . is_empty ( ) {
1619+ write ! ( f, " WITH TAG ({})" , display_comma_separated( & self . tags) ) ?;
1620+ }
1621+ if let Some ( comment) = & self . comment {
1622+ write ! ( f, " COMMENT = '{}'" , escape_single_quote_string( comment) ) ?;
1623+ }
1624+ Ok ( ( ) )
1625+ }
1626+ }
1627+
1628+ /// A relationship in the `RELATIONSHIPS (...)` clause of a `CREATE SEMANTIC VIEW`.
1629+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
1630+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
1631+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
1632+ pub struct SemanticViewRelationship {
1633+ /// Optional `<identifier> AS` naming the relationship.
1634+ pub identifier : Option < Ident > ,
1635+ /// The referencing logical table alias.
1636+ pub table : Ident ,
1637+ /// The referencing columns.
1638+ pub columns : Vec < Ident > ,
1639+ /// The referenced logical table.
1640+ pub ref_table : ObjectName ,
1641+ /// The referenced columns (empty when omitted).
1642+ pub ref_columns : Vec < Ident > ,
1643+ }
1644+
1645+ impl fmt:: Display for SemanticViewRelationship {
1646+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1647+ if let Some ( identifier) = & self . identifier {
1648+ write ! ( f, "{identifier} AS " ) ?;
1649+ }
1650+ write ! (
1651+ f,
1652+ "{} ({}) REFERENCES {}" ,
1653+ self . table,
1654+ display_comma_separated( & self . columns) ,
1655+ self . ref_table
1656+ ) ?;
1657+ if !self . ref_columns . is_empty ( ) {
1658+ write ! ( f, " ({})" , display_comma_separated( & self . ref_columns) ) ?;
1659+ }
1660+ Ok ( ( ) )
1661+ }
1662+ }
1663+
1664+ /// A fact, dimension, or metric semantic expression in a `CREATE SEMANTIC VIEW`.
1665+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
1666+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
1667+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
1668+ pub struct SemanticViewExpr {
1669+ /// Optional `PRIVATE` / `PUBLIC` access modifier.
1670+ pub access : Option < SemanticViewColumnAccess > ,
1671+ /// The (optionally table-qualified) element name.
1672+ pub name : ObjectName ,
1673+ /// The `AS <sql_expr>` definition, when present.
1674+ pub expr : Option < Expr > ,
1675+ /// `WITH SYNONYMS ( ... )` values (empty if absent).
1676+ pub synonyms : Vec < String > ,
1677+ /// `WITH TAG ( ... )` entries (empty if absent).
1678+ pub tags : Vec < Tag > ,
1679+ /// `COMMENT = '...'`.
1680+ pub comment : Option < String > ,
1681+ }
1682+
1683+ impl fmt:: Display for SemanticViewExpr {
1684+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1685+ if let Some ( access) = & self . access {
1686+ write ! ( f, "{access} " ) ?;
1687+ }
1688+ write ! ( f, "{}" , self . name) ?;
1689+ if let Some ( expr) = & self . expr {
1690+ write ! ( f, " AS {expr}" ) ?;
1691+ }
1692+ if !self . synonyms . is_empty ( ) {
1693+ fmt_semantic_view_synonyms ( f, & self . synonyms ) ?;
1694+ }
1695+ if !self . tags . is_empty ( ) {
1696+ write ! ( f, " WITH TAG ({})" , display_comma_separated( & self . tags) ) ?;
1697+ }
1698+ if let Some ( comment) = & self . comment {
1699+ write ! ( f, " COMMENT = '{}'" , escape_single_quote_string( comment) ) ?;
1700+ }
1701+ Ok ( ( ) )
1702+ }
1703+ }
1704+
1705+ /// One clause of a `CREATE SEMANTIC VIEW`. The clauses are stored in
1706+ /// declaration order so the original ordering survives round-tripping.
1707+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
1708+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
1709+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
1710+ pub enum SemanticViewClause {
1711+ /// `TABLES ( ... )`
1712+ Tables ( Vec < SemanticViewTable > ) ,
1713+ /// `RELATIONSHIPS ( ... )`
1714+ Relationships ( Vec < SemanticViewRelationship > ) ,
1715+ /// `FACTS ( ... )`
1716+ Facts ( Vec < SemanticViewExpr > ) ,
1717+ /// `DIMENSIONS ( ... )`
1718+ Dimensions ( Vec < SemanticViewExpr > ) ,
1719+ /// `METRICS ( ... )`
1720+ Metrics ( Vec < SemanticViewExpr > ) ,
1721+ }
1722+
1723+ impl fmt:: Display for SemanticViewClause {
1724+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1725+ match self {
1726+ SemanticViewClause :: Tables ( items) => {
1727+ write ! ( f, "TABLES ({})" , display_comma_separated( items) )
1728+ }
1729+ SemanticViewClause :: Relationships ( items) => {
1730+ write ! ( f, "RELATIONSHIPS ({})" , display_comma_separated( items) )
1731+ }
1732+ SemanticViewClause :: Facts ( items) => {
1733+ write ! ( f, "FACTS ({})" , display_comma_separated( items) )
1734+ }
1735+ SemanticViewClause :: Dimensions ( items) => {
1736+ write ! ( f, "DIMENSIONS ({})" , display_comma_separated( items) )
1737+ }
1738+ SemanticViewClause :: Metrics ( items) => {
1739+ write ! ( f, "METRICS ({})" , display_comma_separated( items) )
1740+ }
1741+ }
1742+ }
1743+ }
1744+
1745+ /// The payload of a `CREATE [OR REPLACE] SEMANTIC VIEW` statement.
1746+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
1747+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
1748+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
1749+ pub struct CreateSemanticView {
1750+ /// `OR REPLACE` flag.
1751+ pub or_replace : bool ,
1752+ /// `IF NOT EXISTS` flag.
1753+ pub if_not_exists : bool ,
1754+ /// The semantic view name.
1755+ pub name : ObjectName ,
1756+ /// The clause lists in declaration order.
1757+ pub clauses : Vec < SemanticViewClause > ,
1758+ /// `COMMENT = '...'`.
1759+ pub comment : Option < String > ,
1760+ }
1761+
1762+ impl fmt:: Display for CreateSemanticView {
1763+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1764+ write ! (
1765+ f,
1766+ "CREATE {or_replace}SEMANTIC VIEW {if_not_exists}{name}" ,
1767+ or_replace = if self . or_replace { "OR REPLACE " } else { "" } ,
1768+ if_not_exists = if self . if_not_exists { "IF NOT EXISTS " } else { "" } ,
1769+ name = self . name,
1770+ ) ?;
1771+ for clause in & self . clauses {
1772+ write ! ( f, " {clause}" ) ?;
1773+ }
1774+ if let Some ( comment) = & self . comment {
1775+ write ! ( f, " COMMENT = '{}'" , escape_single_quote_string( comment) ) ?;
1776+ }
1777+ Ok ( ( ) )
1778+ }
1779+ }
1780+
1781+ /// An operation in an `ALTER SEMANTIC VIEW` statement.
1782+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
1783+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
1784+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
1785+ pub enum AlterSemanticViewOperation {
1786+ /// `RENAME TO <name>`
1787+ RenameTo {
1788+ /// The new semantic view name.
1789+ new_name : ObjectName ,
1790+ } ,
1791+ /// `SET COMMENT = '...'`
1792+ SetComment {
1793+ /// The comment value.
1794+ value : String ,
1795+ } ,
1796+ /// `UNSET COMMENT`
1797+ UnsetComment ,
1798+ /// `SET TAG <tag> = '<value>' [ , ... ]`
1799+ SetTags ( Vec < Tag > ) ,
1800+ /// `UNSET TAG <tag> [ , ... ]`
1801+ UnsetTags ( Vec < ObjectName > ) ,
1802+ }
1803+
1804+ impl fmt:: Display for AlterSemanticViewOperation {
1805+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1806+ match self {
1807+ AlterSemanticViewOperation :: RenameTo { new_name } => {
1808+ write ! ( f, "RENAME TO {new_name}" )
1809+ }
1810+ AlterSemanticViewOperation :: SetComment { value } => {
1811+ write ! ( f, "SET COMMENT = '{}'" , escape_single_quote_string( value) )
1812+ }
1813+ AlterSemanticViewOperation :: UnsetComment => write ! ( f, "UNSET COMMENT" ) ,
1814+ AlterSemanticViewOperation :: SetTags ( tags) => {
1815+ write ! ( f, "SET TAG {}" , display_comma_separated( tags) )
1816+ }
1817+ AlterSemanticViewOperation :: UnsetTags ( tags) => {
1818+ write ! ( f, "UNSET TAG {}" , display_comma_separated( tags) )
1819+ }
1820+ }
1821+ }
1822+ }
1823+
15491824/// An operation on a session policy in an `ALTER SESSION POLICY` statement.
15501825#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
15511826#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
0 commit comments