@@ -2002,22 +2002,47 @@ impl fmt::Display for DropBehavior {
20022002#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
20032003#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
20042004pub enum UserDefinedTypeRepresentation {
2005+ /// Composite type: `CREATE TYPE name AS (attributes)`
20052006 Composite {
20062007 attributes : Vec < UserDefinedTypeCompositeAttributeDef > ,
20072008 } ,
2009+ /// Enum type: `CREATE TYPE name AS ENUM (labels)`
2010+ ///
20082011 /// Note: this is PostgreSQL-specific. See <https://www.postgresql.org/docs/current/sql-createtype.html>
2009- Enum { labels : Vec < Ident > } ,
2012+ Enum {
2013+ labels : Vec < Ident >
2014+ } ,
2015+ /// Range type: `CREATE TYPE name AS RANGE (options)`
2016+ Range {
2017+ options : Vec < UserDefinedTypeRangeOption > ,
2018+ } ,
2019+ /// Base type (SQL definition): `CREATE TYPE name (options)`
2020+ ///
2021+ /// Note the lack of `AS` keyword
2022+ SqlDefinition {
2023+ options : Vec < UserDefinedTypeSqlDefinitionOption > ,
2024+ } ,
2025+ /// When the representation of the type is not specified.
2026+ /// This is used in `CREATE TYPE <name>;` statements.
2027+ None ,
20102028}
20112029
20122030impl fmt:: Display for UserDefinedTypeRepresentation {
20132031 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
20142032 match self {
2015- UserDefinedTypeRepresentation :: Composite { attributes } => {
2016- write ! ( f, "({})" , display_comma_separated( attributes) )
2033+ Self :: Composite { attributes } => {
2034+ write ! ( f, "AS ({})" , display_comma_separated( attributes) )
2035+ }
2036+ Self :: Enum { labels } => {
2037+ write ! ( f, "AS ENUM ({})" , display_comma_separated( labels) )
2038+ }
2039+ Self :: Range { options } => {
2040+ write ! ( f, "AS RANGE ({})" , display_comma_separated( options) )
20172041 }
2018- UserDefinedTypeRepresentation :: Enum { labels } => {
2019- write ! ( f, "ENUM ({})" , display_comma_separated( labels ) )
2042+ Self :: SqlDefinition { options } => {
2043+ write ! ( f, "({})" , display_comma_separated( options ) )
20202044 }
2045+ Self :: None => Ok ( ( ) ) ,
20212046 }
20222047 }
20232048}
@@ -2042,6 +2067,272 @@ impl fmt::Display for UserDefinedTypeCompositeAttributeDef {
20422067 }
20432068}
20442069
2070+ /// Internal length specification for PostgreSQL user-defined base types.
2071+ ///
2072+ /// Specifies the internal length in bytes of the new type's internal representation.
2073+ /// The default assumption is that it is variable-length.
2074+ ///
2075+ /// # PostgreSQL Documentation
2076+ /// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2077+ ///
2078+ /// # Examples
2079+ /// ```sql
2080+ /// CREATE TYPE mytype (
2081+ /// INPUT = in_func,
2082+ /// OUTPUT = out_func,
2083+ /// INTERNALLENGTH = 16 -- Fixed 16-byte length
2084+ /// );
2085+ ///
2086+ /// CREATE TYPE mytype2 (
2087+ /// INPUT = in_func,
2088+ /// OUTPUT = out_func,
2089+ /// INTERNALLENGTH = VARIABLE -- Variable length
2090+ /// );
2091+ /// ```
2092+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2093+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2094+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2095+ pub enum UserDefinedTypeInternalLength {
2096+ /// Fixed internal length: `INTERNALLENGTH = <number>`
2097+ Fixed ( u64 ) ,
2098+ /// Variable internal length: `INTERNALLENGTH = VARIABLE`
2099+ Variable ,
2100+ }
2101+
2102+ impl fmt:: Display for UserDefinedTypeInternalLength {
2103+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2104+ match self {
2105+ UserDefinedTypeInternalLength :: Fixed ( n) => write ! ( f, "{}" , n) ,
2106+ UserDefinedTypeInternalLength :: Variable => write ! ( f, "VARIABLE" ) ,
2107+ }
2108+ }
2109+ }
2110+
2111+ /// Alignment specification for PostgreSQL user-defined base types.
2112+ ///
2113+ /// Specifies the storage alignment requirement for values of the data type.
2114+ /// The allowed values equate to alignment on 1, 2, 4, or 8 byte boundaries.
2115+ /// Note that variable-length types must have an alignment of at least 4, since
2116+ /// they necessarily contain an int4 as their first component.
2117+ ///
2118+ /// # PostgreSQL Documentation
2119+ /// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2120+ ///
2121+ /// # Examples
2122+ /// ```sql
2123+ /// CREATE TYPE mytype (
2124+ /// INPUT = in_func,
2125+ /// OUTPUT = out_func,
2126+ /// ALIGNMENT = int4 -- 4-byte alignment
2127+ /// );
2128+ /// ```
2129+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2130+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2131+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2132+ pub enum Alignment {
2133+ /// Single-byte alignment: `ALIGNMENT = char`
2134+ Char ,
2135+ /// 2-byte alignment: `ALIGNMENT = int2`
2136+ Int2 ,
2137+ /// 4-byte alignment: `ALIGNMENT = int4`
2138+ Int4 ,
2139+ /// 8-byte alignment: `ALIGNMENT = double`
2140+ Double ,
2141+ }
2142+
2143+ impl fmt:: Display for Alignment {
2144+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2145+ match self {
2146+ Alignment :: Char => write ! ( f, "char" ) ,
2147+ Alignment :: Int2 => write ! ( f, "int2" ) ,
2148+ Alignment :: Int4 => write ! ( f, "int4" ) ,
2149+ Alignment :: Double => write ! ( f, "double" ) ,
2150+ }
2151+ }
2152+ }
2153+
2154+ /// Storage specification for PostgreSQL user-defined base types.
2155+ ///
2156+ /// Specifies the storage strategy for values of the data type:
2157+ /// - `plain`: Prevents compression and out-of-line storage (for fixed-length types)
2158+ /// - `external`: Allows out-of-line storage but not compression
2159+ /// - `extended`: Allows both compression and out-of-line storage (default for most types)
2160+ /// - `main`: Allows compression but discourages out-of-line storage
2161+ ///
2162+ /// # PostgreSQL Documentation
2163+ /// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2164+ ///
2165+ /// # Examples
2166+ /// ```sql
2167+ /// CREATE TYPE mytype (
2168+ /// INPUT = in_func,
2169+ /// OUTPUT = out_func,
2170+ /// STORAGE = plain
2171+ /// );
2172+ /// ```
2173+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2174+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2175+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2176+ pub enum UserDefinedTypeStorage {
2177+ /// No compression or out-of-line storage: `STORAGE = plain`
2178+ Plain ,
2179+ /// Out-of-line storage allowed, no compression: `STORAGE = external`
2180+ External ,
2181+ /// Both compression and out-of-line storage allowed: `STORAGE = extended`
2182+ Extended ,
2183+ /// Compression allowed, out-of-line discouraged: `STORAGE = main`
2184+ Main ,
2185+ }
2186+
2187+ impl fmt:: Display for UserDefinedTypeStorage {
2188+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2189+ match self {
2190+ UserDefinedTypeStorage :: Plain => write ! ( f, "plain" ) ,
2191+ UserDefinedTypeStorage :: External => write ! ( f, "external" ) ,
2192+ UserDefinedTypeStorage :: Extended => write ! ( f, "extended" ) ,
2193+ UserDefinedTypeStorage :: Main => write ! ( f, "main" ) ,
2194+ }
2195+ }
2196+ }
2197+
2198+ /// Options for PostgreSQL `CREATE TYPE ... AS RANGE` statement.
2199+ ///
2200+ /// Range types are data types representing a range of values of some element type
2201+ /// (called the range's subtype). These options configure the behavior of the range type.
2202+ ///
2203+ /// # PostgreSQL Documentation
2204+ /// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2205+ ///
2206+ /// # Examples
2207+ /// ```sql
2208+ /// CREATE TYPE int4range AS RANGE (
2209+ /// SUBTYPE = int4,
2210+ /// SUBTYPE_OPCLASS = int4_ops,
2211+ /// CANONICAL = int4range_canonical,
2212+ /// SUBTYPE_DIFF = int4range_subdiff
2213+ /// );
2214+ /// ```
2215+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2216+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2217+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2218+ pub enum UserDefinedTypeRangeOption {
2219+ /// The element type that the range type will represent: `SUBTYPE = subtype`
2220+ Subtype ( DataType ) ,
2221+ /// The operator class for the subtype: `SUBTYPE_OPCLASS = subtype_operator_class`
2222+ SubtypeOpClass ( ObjectName ) ,
2223+ /// Collation to use for ordering the subtype: `COLLATION = collation`
2224+ Collation ( ObjectName ) ,
2225+ /// Function to convert range values to canonical form: `CANONICAL = canonical_function`
2226+ Canonical ( ObjectName ) ,
2227+ /// Function to compute the difference between two subtype values: `SUBTYPE_DIFF = subtype_diff_function`
2228+ SubtypeDiff ( ObjectName ) ,
2229+ /// Name of the corresponding multirange type: `MULTIRANGE_TYPE_NAME = multirange_type_name`
2230+ MultirangeTypeName ( ObjectName ) ,
2231+ }
2232+
2233+ impl fmt:: Display for UserDefinedTypeRangeOption {
2234+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2235+ match self {
2236+ UserDefinedTypeRangeOption :: Subtype ( dt) => write ! ( f, "SUBTYPE = {}" , dt) ,
2237+ UserDefinedTypeRangeOption :: SubtypeOpClass ( name) => write ! ( f, "SUBTYPE_OPCLASS = {}" , name) ,
2238+ UserDefinedTypeRangeOption :: Collation ( name) => write ! ( f, "COLLATION = {}" , name) ,
2239+ UserDefinedTypeRangeOption :: Canonical ( name) => write ! ( f, "CANONICAL = {}" , name) ,
2240+ UserDefinedTypeRangeOption :: SubtypeDiff ( name) => write ! ( f, "SUBTYPE_DIFF = {}" , name) ,
2241+ UserDefinedTypeRangeOption :: MultirangeTypeName ( name) => write ! ( f, "MULTIRANGE_TYPE_NAME = {}" , name) ,
2242+ }
2243+ }
2244+ }
2245+
2246+ /// Options for PostgreSQL `CREATE TYPE ... (<options>)` statement (base type definition).
2247+ ///
2248+ /// Base types are the lowest-level data types in PostgreSQL. To define a new base type,
2249+ /// you must specify functions that convert it to and from text representation, and optionally
2250+ /// binary representation and other properties.
2251+ ///
2252+ /// Note: This syntax uses parentheses directly after the type name, without the `AS` keyword.
2253+ ///
2254+ /// # PostgreSQL Documentation
2255+ /// See: <https://www.postgresql.org/docs/current/sql-createtype.html>
2256+ ///
2257+ /// # Examples
2258+ /// ```sql
2259+ /// CREATE TYPE complex (
2260+ /// INPUT = complex_in,
2261+ /// OUTPUT = complex_out,
2262+ /// INTERNALLENGTH = 16,
2263+ /// ALIGNMENT = double
2264+ /// );
2265+ /// ```
2266+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
2267+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
2268+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
2269+ pub enum UserDefinedTypeSqlDefinitionOption {
2270+ /// Function to convert from external text representation to internal: `INPUT = input_function`
2271+ Input ( ObjectName ) ,
2272+ /// Function to convert from internal to external text representation: `OUTPUT = output_function`
2273+ Output ( ObjectName ) ,
2274+ /// Function to convert from external binary representation to internal: `RECEIVE = receive_function`
2275+ Receive ( ObjectName ) ,
2276+ /// Function to convert from internal to external binary representation: `SEND = send_function`
2277+ Send ( ObjectName ) ,
2278+ /// Function to convert type modifiers from text array to internal form: `TYPMOD_IN = type_modifier_input_function`
2279+ TypmodIn ( ObjectName ) ,
2280+ /// Function to convert type modifiers from internal to text form: `TYPMOD_OUT = type_modifier_output_function`
2281+ TypmodOut ( ObjectName ) ,
2282+ /// Function to compute statistics for the data type: `ANALYZE = analyze_function`
2283+ Analyze ( ObjectName ) ,
2284+ /// Function to handle subscripting operations: `SUBSCRIPT = subscript_function`
2285+ Subscript ( ObjectName ) ,
2286+ /// Internal storage size in bytes, or VARIABLE for variable-length: `INTERNALLENGTH = { internallength | VARIABLE }`
2287+ InternalLength ( UserDefinedTypeInternalLength ) ,
2288+ /// Indicates values are passed by value rather than by reference: `PASSEDBYVALUE`
2289+ PassedByValue ,
2290+ /// Storage alignment requirement (1, 2, 4, or 8 bytes): `ALIGNMENT = alignment`
2291+ Alignment ( Alignment ) ,
2292+ /// Storage strategy for varlena types: `STORAGE = storage`
2293+ Storage ( UserDefinedTypeStorage ) ,
2294+ /// Copy properties from an existing type: `LIKE = like_type`
2295+ Like ( ObjectName ) ,
2296+ /// Type category for implicit casting rules (single char): `CATEGORY = category`
2297+ Category ( char ) ,
2298+ /// Whether this type is preferred within its category: `PREFERRED = preferred`
2299+ Preferred ( bool ) ,
2300+ /// Default value for the type: `DEFAULT = default`
2301+ Default ( Expr ) ,
2302+ /// Element type for array types: `ELEMENT = element`
2303+ Element ( DataType ) ,
2304+ /// Delimiter character for array value display: `DELIMITER = delimiter`
2305+ Delimiter ( String ) ,
2306+ /// Whether the type supports collation: `COLLATABLE = collatable`
2307+ Collatable ( bool ) ,
2308+ }
2309+
2310+ impl fmt:: Display for UserDefinedTypeSqlDefinitionOption {
2311+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
2312+ match self {
2313+ UserDefinedTypeSqlDefinitionOption :: Input ( name) => write ! ( f, "INPUT = {}" , name) ,
2314+ UserDefinedTypeSqlDefinitionOption :: Output ( name) => write ! ( f, "OUTPUT = {}" , name) ,
2315+ UserDefinedTypeSqlDefinitionOption :: Receive ( name) => write ! ( f, "RECEIVE = {}" , name) ,
2316+ UserDefinedTypeSqlDefinitionOption :: Send ( name) => write ! ( f, "SEND = {}" , name) ,
2317+ UserDefinedTypeSqlDefinitionOption :: TypmodIn ( name) => write ! ( f, "TYPMOD_IN = {}" , name) ,
2318+ UserDefinedTypeSqlDefinitionOption :: TypmodOut ( name) => write ! ( f, "TYPMOD_OUT = {}" , name) ,
2319+ UserDefinedTypeSqlDefinitionOption :: Analyze ( name) => write ! ( f, "ANALYZE = {}" , name) ,
2320+ UserDefinedTypeSqlDefinitionOption :: Subscript ( name) => write ! ( f, "SUBSCRIPT = {}" , name) ,
2321+ UserDefinedTypeSqlDefinitionOption :: InternalLength ( len) => write ! ( f, "INTERNALLENGTH = {}" , len) ,
2322+ UserDefinedTypeSqlDefinitionOption :: PassedByValue => write ! ( f, "PASSEDBYVALUE" ) ,
2323+ UserDefinedTypeSqlDefinitionOption :: Alignment ( align) => write ! ( f, "ALIGNMENT = {}" , align) ,
2324+ UserDefinedTypeSqlDefinitionOption :: Storage ( storage) => write ! ( f, "STORAGE = {}" , storage) ,
2325+ UserDefinedTypeSqlDefinitionOption :: Like ( name) => write ! ( f, "LIKE = {}" , name) ,
2326+ UserDefinedTypeSqlDefinitionOption :: Category ( c) => write ! ( f, "CATEGORY = '{}'" , c) ,
2327+ UserDefinedTypeSqlDefinitionOption :: Preferred ( b) => write ! ( f, "PREFERRED = {}" , b) ,
2328+ UserDefinedTypeSqlDefinitionOption :: Default ( expr) => write ! ( f, "DEFAULT = {}" , expr) ,
2329+ UserDefinedTypeSqlDefinitionOption :: Element ( dt) => write ! ( f, "ELEMENT = {}" , dt) ,
2330+ UserDefinedTypeSqlDefinitionOption :: Delimiter ( s) => write ! ( f, "DELIMITER = '{}'" , escape_single_quote_string( s) ) ,
2331+ UserDefinedTypeSqlDefinitionOption :: Collatable ( b) => write ! ( f, "COLLATABLE = {}" , b) ,
2332+ }
2333+ }
2334+ }
2335+
20452336/// PARTITION statement used in ALTER TABLE et al. such as in Hive and ClickHouse SQL.
20462337/// For example, ClickHouse's OPTIMIZE TABLE supports syntax like PARTITION ID 'partition_id' and PARTITION expr.
20472338/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
0 commit comments