User-defined types are objects that create new data types that can be used by other objects in the database. In PostgreSQL, it's possible to configure four kinds of user-defined types, being them: base, enumeration, composite, and range. Each type has its own set of attributes and configuration complexity and in order to provide a better explanation about them, this section was subdivided into four sections which will detail each type separately.
Base or scalar types are elementary data types used in the same way as the PostgreSQL built-in ones. Creating base types is quite advanced and requires the use of C-based functions. Details about these functions will not be covered by this documentation.
In general, in order to create a base type, you will need to define at least two functions called, respectively, input and output. The input function converts the external textual representation of the type to its internal representation. The output function does the reverse operation, that is, converts the type from its internal representation to an external textual one. There are other optional attributes that can be assigned to the type and they are described in the table below.
Due to the number of attributes used to create base types, pgModeler separates them into two tabs:
Attributes. The first tab is used to configure the two mandatory functions as well as other optional ones, and the second tab is used to configure advanced attributes for the type. You seldom need to use the advanced attributes but they are present for those users intending to create a more elaborate data type.
|This function converts the external textual representation of the type to its internal representation. This function should have the signature:
any function(cstring, oid, integer).
|This function converts the internal representation of the type to its external textual representation. This function should have the signature:
|This function converts the external binary representation of the type to its internal representation. This function should have the signature:
any function(internal, oid, integer).
|This function converts the internal representation of the type to its external binary representation. This function should have the signature:
|This function validates the literal type modifier for the one being created. An example of a type modifier is the length for
varchar(20) or the base and precision for
numeric(10,2). The input for this function is a
cstring array and it should be internally processed by the function and the return should be a non-negative integer indicating the type modifier. This function should have the signature:
|This function converts the internal type modifier representation (single non-negative integer) back to the literal representation. This function should have the signature:
|This function is responsible to perform type-specific statistics collection for columns of the data type being created. This function must have the signature:
Continuing to detail the base type, the image below shows the advanced attributes used to create a more detailed data type. Most of them aren't often used, anyway, they all will be described.
|Defines the internal length of the type being configured. The default value 0 means that the type has a variable length.
|Specifies the storage mode for a variable-length type. Four modes are accepted:
plain mode indicates that the type is stored in-line and uncompressed. The
extended mode tells the system to try first to compress a long value or move this value out of the main table if it's still too long. The
external mode allows the value to be moved to the main table without trying to compress it. The
main mode allows value compression but discourages moving it to the main table.
|A set of optional flags assigned to the type.
By value indicates that values of the new type are passed only by value rather than by reference.
Preferred indicates that the type is preferred in its category. This parameter also helps the system to use implicit casts in case of ambiguity.
Collatable indicates that the type's operations can use collation information.
|Specifies in which category the new data type fits. Details about categories can be found in the official documentation.
|Defines the character used as the delimiter between values when this type is used as an array.
|Defines the default values for the data type.
|Specifies the storage alignment for the new type. Four values are accepted:
|Indicates a previously defined type from which the new type will have the same representation.
|Indicates the type of the elements when the newly configured type is an array.
Enumeration types are data types that are composed of a static set of literal values. This data type is equivalent to the
enum types existent in many of the programming languages. Its attributes are described below.
|This list controls the set of enumerations available for the type. To create a new element, use the field
|Creates a single enumeration in the type.
Composite types are objects which contain a set of named attributes each one with its own data type. These types resemble the
structs present in some programming languages. Additionally, a composite type is basically the same as a row data type of a table but the advantage of the former is that users don't need to explicitly create a table when all that is desired is to define a single type. Composite types can be quite useful as function arguments and return types.
|This group of fields reunites all attributes needed to configure a composite type.
|Name of an attribute of the type.
|Data type used by the attribute.
Range data types represent an interval of values of an element type (also known as range subtype). These types are very useful because they are capable to represent many element values in a single range value. In other words, range types can be used when you need to work with an interval of values without the need to create auxiliary columns to denote their start and end. For instance, let's say you need to create a range of
timestamp values, instead of using two columns like
end_date you can just use one column configured with the built-in type
tsrange (timestamp range). This type will handle all the operations needed to compare a single value against the entire range and many other features. A complete list of built-in range data types is available in PostgreSQL manuals.
|The name of the
btree operator class associated with the range subtype. This operator class is used to determine how values can be sorted.
|This function is used to convert the range internal values to a canonical form. It must have the signature:
any function(any). The function differs from the one stated in the PostgreSQL documentation, so refer to the note at the end of section Base types above to understand why this function is written this way.
Subtype Diff Func.
|This function compares two values of
Subtype and returns a
double precision value representing the difference between them. This provides better efficiency of GiST indexes associated with columns with this range data type.
|Configures the internal element type handled by the range type.
User-defined types DDL
Data type catogories
https://www.postgresql.org/docs/current/static/catalog-pg-type.html#CATALOG-TYPCATEGORY-TABLE <Br/><Br/> Enum types details
Range types details