github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/logictest/testdata/logic_test/enums (about)

     1  # LogicTest: !3node-tenant
     2  
     3  statement ok
     4  SET experimental_enable_enums=true;
     5  
     6  statement error pq: unimplemented: DROP TYPE
     7  DROP TYPE mytype
     8  
     9  statement error pq: unimplemented: DROP TYPE
    10  DROP TYPE IF EXISTS mytype
    11  
    12  statement ok
    13  CREATE TYPE t AS ENUM ()
    14  
    15  statement error pq: relation "t" does not exist
    16  SELECT * FROM t
    17  
    18  statement error pq: type "t" already exists
    19  CREATE TABLE t (x INT)
    20  
    21  statement error pq: type "t" already exists
    22  CREATE TYPE t AS ENUM ()
    23  
    24  statement ok
    25  CREATE TABLE torename (x INT)
    26  
    27  statement error pq: type "t" already exists
    28  ALTER TABLE torename RENAME TO t
    29  
    30  statement ok
    31  CREATE DATABASE db2;
    32  CREATE TYPE db2.t AS ENUM ()
    33  
    34  statement error pq: relation "db2.t" does not exist
    35  SELECT * FROM db2.t
    36  
    37  statement error pq: type "db2.public.t" already exists
    38  CREATE TYPE db2.t AS ENUM ()
    39  
    40  # Regression for #48537. Dropping a table with a type name caused a panic.
    41  statement error pq: relation "t" does not exist
    42  DROP TABLE t
    43  
    44  statement error pq: enum definition contains duplicate value "dup"
    45  CREATE TYPE bad AS ENUM ('dup', 'dup')
    46  
    47  # Duplicates with different casing count as different.
    48  statement ok
    49  CREATE TYPE notbad AS ENUM ('dup', 'DUP')
    50  
    51  # Test that we can create types that shadow builtin type names,
    52  # but in different schemas.
    53  statement ok
    54  CREATE TYPE int AS ENUM ('Z', 'S of int')
    55  
    56  statement error pq: could not parse "Z" as type int
    57  SELECT 'Z'::int
    58  
    59  query T
    60  SELECT 'Z'::public.int
    61  ----
    62  Z
    63  
    64  statement ok
    65  CREATE TYPE greeting AS ENUM ('hello', 'howdy', 'hi')
    66  
    67  # Test that we can only reference greeting with the right qualification.
    68  statement error pq: type "pg_catalog.greeting" does not exist
    69  SELECT 'hello'::pg_catalog.greeting
    70  
    71  query T
    72  SELECT 'hello'::public.greeting
    73  ----
    74  hello
    75  
    76  # Test some expression evaluation on enums.
    77  # These test should live in TestEval, but it is difficult to adjust the
    78  # test to handle creation of user defined types.
    79  query TTT
    80  SELECT 'hello'::greeting, 'howdy'::greeting, 'hi'::greeting
    81  ----
    82  hello howdy hi
    83  
    84  # Test type annotations.
    85  query TTT
    86  SELECT 'hello':::greeting, 'howdy':::greeting, 'hi':::greeting
    87  ----
    88  hello howdy hi
    89  
    90  statement error pq: invalid input value for enum greeting: "goodbye"
    91  SELECT 'goodbye'::greeting
    92  
    93  query T
    94  SELECT 'hello'::greeting::string
    95  ----
    96  hello
    97  
    98  query BBBBBBBBBBB
    99  SELECT 'hello'::greeting < 'howdy'::greeting,
   100         'howdy'::greeting < 'hi',
   101         'hi' > 'hello'::greeting,
   102         'howdy'::greeting < 'hello'::greeting,
   103         'hi'::greeting <= 'hi',
   104         NULL < 'hello'::greeting,
   105         'hi'::greeting < NULL,
   106         'hello'::greeting = 'hello'::greeting,
   107         'hello' != 'hi'::greeting,
   108         'howdy'::greeting IS NOT DISTINCT FROM NULL,
   109         'hello'::greeting IN ('hi'::greeting, 'howdy'::greeting, 'hello'::greeting)
   110  ----
   111  true true true false true NULL NULL true true false true
   112  
   113  statement ok
   114  CREATE TYPE farewell AS ENUM ('bye', 'seeya')
   115  
   116  statement error pq: unsupported comparison operator: <greeting> = <farewell>
   117  SELECT 'hello'::greeting = 'bye'::farewell
   118  
   119  statement error pq: unsupported comparison operator: <greeting> < <farewell>
   120  SELECT 'hello'::greeting < 'bye'::farewell
   121  
   122  statement error pq: unsupported comparison operator: <greeting> <= <farewell>
   123  SELECT 'hello'::greeting <= 'bye'::farewell
   124  
   125  query T
   126  SELECT 'hello'::greeting::greeting
   127  ----
   128  hello
   129  
   130  statement ok
   131  CREATE TYPE greeting2 AS ENUM ('hello')
   132  
   133  statement error pq: invalid cast: greeting -> greeting2
   134  SELECT 'hello'::greeting::greeting2
   135  
   136  # Ensure that we can perform a limited form of implicit casts for
   137  # the case of ENUM binary operations with strings.
   138  query BB
   139  SELECT 'hello'::greeting != 'howdy', 'hi' > 'hello'::greeting
   140  ----
   141  true true
   142  
   143  # Check that the implicit cast gives an appropriate error message
   144  # when firing but unable to complete the type check.
   145  statement error pq: invalid input value for enum greeting: "notagreeting"
   146  SELECT 'hello'::greeting = 'notagreeting'
   147  
   148  statement error pq: unimplemented: ALTER TYPE ADD VALUE unsupported
   149  ALTER TYPE greeting ADD VALUE 'hola' AFTER 'hello'
   150  
   151  statement error pq: unimplemented: ALTER TYPE RENAME VALUE unsupported
   152  ALTER TYPE greeting RENAME VALUE 'hello' TO 'helloooooo'
   153  
   154  statement error pq: unimplemented: ALTER TYPE RENAME unsupported
   155  ALTER TYPE greeting RENAME TO greetings
   156  
   157  statement error pq: unimplemented: ALTER TYPE SET SCHEMA unsupported
   158  ALTER TYPE greeting SET SCHEMA newschema
   159  
   160  # Tests for enum builtins.
   161  statement ok
   162  CREATE TYPE dbs AS ENUM ('postgres', 'mysql', 'spanner', 'cockroach')
   163  
   164  query TT
   165  SELECT enum_first('mysql'::dbs), enum_last('spanner'::dbs)
   166  ----
   167  postgres cockroach
   168  
   169  query T
   170  SELECT enum_range('cockroach'::dbs)
   171  ----
   172  {postgres,mysql,spanner,cockroach}
   173  
   174  query TT
   175  SELECT enum_range(NULL, 'mysql'::dbs), enum_range('spanner'::dbs, NULL)
   176  ----
   177  {postgres,mysql} {spanner,cockroach}
   178  
   179  query TT
   180  SELECT enum_range('postgres'::dbs, 'spanner'::dbs), enum_range('spanner'::dbs, 'cockroach'::dbs)
   181  ----
   182  {postgres,mysql,spanner} {spanner,cockroach}
   183  
   184  query T
   185  SELECT enum_range('cockroach'::dbs, 'cockroach'::dbs)
   186  ----
   187  {cockroach}
   188  
   189  query T
   190  SELECT enum_range('cockroach'::dbs, 'spanner'::dbs)
   191  ----
   192  {}
   193  
   194  query error pq: enum_range\(\): both arguments cannot be NULL
   195  SELECT enum_range(NULL::dbs, NULL::dbs)
   196  
   197  query error pq: enum_range\(\): mismatched types
   198  SELECT enum_range('cockroach'::dbs, 'hello'::greeting)
   199  
   200  # Test inserting and reading enum data from tables.
   201  statement ok
   202  CREATE TABLE greeting_table (x1 greeting, x2 greeting)
   203  
   204  statement error pq: invalid input value for enum greeting: "bye"
   205  INSERT INTO greeting_table VALUES ('bye', 'hi')
   206  
   207  statement ok
   208  INSERT INTO greeting_table VALUES ('hi', 'hello')
   209  
   210  query TT
   211  SELECT * FROM greeting_table
   212  ----
   213  hi hello
   214  
   215  query TT
   216  SELECT 'hello'::greeting, x1 FROM greeting_table
   217  ----
   218  hello hi
   219  
   220  query TB
   221  SELECT x1, x1 < 'hello' FROM greeting_table
   222  ----
   223  hi false
   224  
   225  query TT
   226  SELECT x1, enum_first(x1) FROM greeting_table
   227  ----
   228  hi hello
   229  
   230  statement ok
   231  CREATE TABLE t1 (x greeting, INDEX i (x));
   232  CREATE TABLE t2 (x greeting, INDEX i (x));
   233  INSERT INTO t1 VALUES ('hello');
   234  INSERT INTO t2 VALUES ('hello')
   235  
   236  query TT
   237  SELECT * FROM t1 INNER LOOKUP JOIN t2 ON t1.x = t2.x
   238  ----
   239  hello hello
   240  
   241  query TT
   242  SELECT * FROM t1 INNER HASH JOIN t2 ON t1.x = t2.x
   243  ----
   244  hello hello
   245  
   246  query TT
   247  SELECT * FROM t1 INNER MERGE JOIN t2 ON t1.x = t2.x
   248  ----
   249  hello hello
   250  
   251  statement ok
   252  INSERT INTO t2 VALUES ('hello'), ('hello'), ('howdy'), ('hi')
   253  
   254  query T rowsort
   255  SELECT DISTINCT x FROM t2
   256  ----
   257  hello
   258  howdy
   259  hi
   260  
   261  query T
   262  SELECT DISTINCT x FROM t2 ORDER BY x DESC
   263  ----
   264  hi
   265  howdy
   266  hello
   267  
   268  # Test out some subqueries.
   269  query T rowsort
   270  SELECT x FROM t2 WHERE x > (SELECT x FROM t1 ORDER BY x LIMIT 1)
   271  ----
   272  hi
   273  howdy
   274  
   275  # Test ordinality.
   276  query TI
   277  SELECT * FROM t2 WITH ORDINALITY ORDER BY x
   278  ----
   279  hello  1
   280  hello  2
   281  hello  3
   282  howdy  4
   283  hi     5
   284  
   285  # Test ordering with and without limits.
   286  statement ok
   287  INSERT INTO t1 VALUES ('hi'), ('hello'), ('howdy'), ('howdy'), ('howdy'), ('hello')
   288  
   289  query T
   290  SELECT x FROM t1 ORDER BY x DESC
   291  ----
   292  hi
   293  howdy
   294  howdy
   295  howdy
   296  hello
   297  hello
   298  hello
   299  
   300  query T
   301  SELECT x FROM t1 ORDER BY x ASC
   302  ----
   303  hello
   304  hello
   305  hello
   306  howdy
   307  howdy
   308  howdy
   309  hi
   310  
   311  query T
   312  SELECT x FROM t1 ORDER BY x ASC LIMIT 3
   313  ----
   314  hello
   315  hello
   316  hello
   317  
   318  query T
   319  SELECT x FROM t1 ORDER BY x DESC LIMIT 3
   320  ----
   321  hi
   322  howdy
   323  howdy
   324  
   325  # Test we can group on enums.
   326  query T rowsort
   327  (SELECT * FROM t1) UNION (SELECT * FROM t2)
   328  ----
   329  hello
   330  howdy
   331  hi
   332  
   333  statement ok
   334  CREATE TABLE enum_agg (x greeting, y INT);
   335  INSERT INTO enum_agg VALUES
   336    ('hello', 1),
   337    ('hello', 3),
   338    ('howdy', 5),
   339    ('howdy', 0),
   340    ('howdy', 1),
   341    ('hi', 10)
   342  
   343  query TIRI rowsort
   344  SELECT x, max(y), sum(y), min(y) FROM enum_agg GROUP BY x
   345  ----
   346  hello 3 4 1
   347  howdy 5 6 0
   348  hi 10 10 10
   349  
   350  # Test aggregations on ENUM columns.
   351  query TT
   352  SELECT max(x), min(x) FROM enum_agg
   353  ----
   354  hi hello
   355  
   356  # Test that enums without any members can still get an aggregate
   357  # resolved when distributing a flow.
   358  statement ok
   359  CREATE TYPE empty AS ENUM ();
   360  CREATE TABLE empty_enum (x empty)
   361  
   362  query TT
   363  SELECT max(x), min(x) FROM empty_enum
   364  ----
   365  NULL NULL
   366  
   367  # Regression to ensure that statistics jobs can be run on tables
   368  # with user defined types.
   369  statement ok
   370  CREATE TABLE greeting_stats (x greeting PRIMARY KEY);
   371  INSERT INTO greeting_stats VALUES ('hi');
   372  CREATE STATISTICS s FROM greeting_stats
   373  
   374  query T
   375  SELECT x FROM greeting_stats
   376  ----
   377  hi
   378  
   379  # Test that we can cast from bytes to enum.
   380  # Use a singleton enum so that the bytes encoding is simple.
   381  statement ok
   382  CREATE TYPE as_bytes AS ENUM ('bytes')
   383  
   384  query TT
   385  SELECT b'\x80'::as_bytes, b'\x80':::as_bytes
   386  ----
   387  bytes bytes
   388  
   389  query error pq: could not find \[255\] in enum representation
   390  SELECT b'\xFF'::as_bytes
   391  
   392  # Regression for #49300. Ensure that virtual tables have access to hydrated
   393  # type descriptors.
   394  query TT
   395  SHOW CREATE t1
   396  ----
   397  t1  CREATE TABLE t1 (
   398      x test.public.greeting NULL,
   399      INDEX i (x ASC),
   400      FAMILY "primary" (x, rowid)
   401  )
   402  
   403  # SHOW CREATE uses a virtual index, so also check the code path where a
   404  # descriptor scan is used.
   405  query T
   406  SELECT create_statement FROM crdb_internal.create_statements WHERE descriptor_name = 't1'
   407  ----
   408  CREATE TABLE t1 (
   409     x test.public.greeting NULL,
   410     INDEX i (x ASC),
   411     FAMILY "primary" (x, rowid)
   412  )
   413  
   414  # Test that the implicit array type has been created, and that we can use it.
   415  query TT
   416  SELECT ARRAY['hello']::_greeting, ARRAY['hello'::greeting]
   417  ----
   418  {hello} {hello}
   419  
   420  # Test that we can't mix enums in an array.
   421  query error pq: expected 'cockroach'::test.public.dbs to be of type greeting, found type dbs
   422  SELECT ARRAY['hello'::greeting, 'cockroach'::dbs]
   423  
   424  statement ok
   425  CREATE TABLE enum_array (x _greeting, y greeting[]);
   426  INSERT INTO enum_array VALUES (ARRAY['hello'], ARRAY['hello']), (ARRAY['howdy'], ARRAY['howdy'])
   427  
   428  query TT rowsort
   429  SELECT * FROM enum_array
   430  ----
   431  {hello} {hello}
   432  {howdy} {howdy}
   433  
   434  query TTT
   435  SELECT pg_typeof(x), pg_typeof(x[1]), pg_typeof(ARRAY['hello']::_greeting) FROM enum_array LIMIT 1
   436  ----
   437  test.public.greeting[] test.public.greeting test.public.greeting[]
   438  
   439  # Ensure that the implicitly created array type will tolerate collisions.
   440  # _collision will create __collision as its implicit array type, so the
   441  # creation of collision will have to retry twice before it finds the open
   442  # spot of ___collision for its implicit array type.
   443  statement ok
   444  CREATE TYPE _collision AS ENUM ();
   445  CREATE TYPE collision AS ENUM ();
   446  
   447  # _collision and __collision typelem and typarray should point back at each
   448  # other, and vice versa for collision and ___collision.
   449  query TOOO rowsort
   450  SELECT
   451    typname, oid, typelem, typarray
   452  FROM
   453    pg_type
   454  WHERE
   455    typname IN ('collision', '_collision', '__collision', '___collision')
   456  ----
   457  _collision    100082  0       100083
   458  __collision   100083  100082  0
   459  collision     100084  0       100085
   460  ___collision  100085  100084  0
   461  
   462  # Regression for #49756.
   463  query TT
   464  SELECT
   465    column_name, column_type
   466  FROM
   467    crdb_internal.table_columns
   468  WHERE
   469    descriptor_name = 'enum_array' AND column_name = 'x'
   470  ----
   471  x  family:ArrayFamily width:0 precision:0 locale:"" visible_type:0 oid:100064 array_contents:<InternalType:<family:EnumFamily width:0 precision:0 locale:"" visible_type:0 oid:100063 time_precision_is_set:false udt_metadata:<stable_type_id:63 stable_array_type_id:64 > > TypeMeta:<> > time_precision_is_set:false udt_metadata:<stable_type_id:64 stable_array_type_id:0 >
   472  
   473  # Test tables using enums in DEFAULT expressions.
   474  statement ok
   475  CREATE TABLE enum_default (
   476    x INT,
   477    y greeting DEFAULT 'hello',
   478    z BOOL DEFAULT ('hello':::greeting IS OF (greeting, greeting)),
   479    FAMILY (x, y, z)
   480  );
   481  INSERT INTO enum_default VALUES (1), (2)
   482  
   483  query ITB rowsort
   484  SELECT * FROM enum_default
   485  ----
   486  1 hello true
   487  2 hello true
   488  
   489  # Test that enum default values are formatted in human readable ways.
   490  query TT
   491  SHOW CREATE enum_default
   492  ----
   493  enum_default  CREATE TABLE enum_default (
   494                x INT8 NULL,
   495                y test.public.greeting NULL DEFAULT 'hello':::test.public.greeting,
   496                z BOOL NULL DEFAULT 'hello':::test.public.greeting IS OF (test.public.greeting, test.public.greeting),
   497                FAMILY fam_0_x_y_z_rowid (x, y, z, rowid)
   498  )
   499  
   500  # Test crdb_internal.table_columns.
   501  query TT
   502  SELECT
   503    column_name, default_expr
   504  FROM
   505    crdb_internal.table_columns
   506  WHERE
   507    descriptor_name='enum_default' AND (column_name = 'y' OR column_name = 'z')
   508  ORDER BY
   509    column_name
   510  ----
   511  y  'hello':::test.public.greeting
   512  z  'hello':::test.public.greeting IS OF (test.public.greeting, test.public.greeting)
   513  
   514  # Test information_schema.columns.
   515  query TT
   516  SELECT
   517    column_name, column_default
   518  FROM
   519    information_schema.columns
   520  WHERE
   521    table_name='enum_default' AND (column_name = 'y' OR column_name = 'z')
   522  ORDER BY
   523    column_name
   524  ----
   525  y  'hello':::test.public.greeting
   526  z  'hello':::test.public.greeting IS OF (test.public.greeting, test.public.greeting)
   527  
   528  # Test computed columns with enum values.
   529  statement ok
   530  CREATE TABLE enum_computed (
   531    x INT,
   532    y greeting AS ('hello') STORED,
   533    z BOOL AS (w = 'howdy') STORED,
   534    w greeting,
   535    FAMILY (x, y, z)
   536  );
   537  INSERT INTO enum_computed (x, w) VALUES (1, 'hello'), (2, 'hello')
   538  
   539  query ITBT rowsort
   540  SELECT * FROM enum_computed
   541  ----
   542  1 hello false hello
   543  2 hello false hello
   544  
   545  query TT
   546  SHOW CREATE enum_computed
   547  ----
   548  enum_computed  CREATE TABLE enum_computed (
   549                 x INT8 NULL,
   550                 y test.public.greeting NULL AS ('hello':::test.public.greeting) STORED,
   551                 z BOOL NULL AS (w = 'howdy':::test.public.greeting) STORED,
   552                 w test.public.greeting NULL,
   553                 FAMILY fam_0_x_y_z_w_rowid (x, y, z, w, rowid)
   554  )
   555  
   556  # Test information_schema.columns.
   557  query TT
   558  SELECT
   559    column_name, generation_expression
   560  FROM
   561    information_schema.columns
   562  WHERE
   563    table_name='enum_computed' AND (column_name = 'y' OR column_name = 'z')
   564  ORDER BY
   565    column_name
   566  ----
   567  y  'hello':::test.public.greeting
   568  z  w = 'howdy':::test.public.greeting
   569  
   570  # Test check constraints with enum values.
   571  statement ok
   572  CREATE TABLE enum_checks (
   573    x greeting,
   574    CHECK (x = 'hello'::greeting),
   575    CHECK ('hello':::greeting = 'hello':::greeting)
   576  );
   577  INSERT INTO enum_checks VALUES ('hello')
   578  
   579  query TT
   580  SHOW CREATE enum_checks
   581  ----
   582  enum_checks  CREATE TABLE enum_checks (
   583               x test.public.greeting NULL,
   584               FAMILY "primary" (x, rowid),
   585               CONSTRAINT check_x CHECK (x = 'hello':::test.public.greeting::test.public.greeting),
   586               CONSTRAINT "check" CHECK ('hello':::test.public.greeting = 'hello':::test.public.greeting)
   587  )