]> granicus.if.org Git - postgresql/commitdiff
Use TypeName to represent type names in certain commands
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 30 Dec 2014 16:57:23 +0000 (13:57 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Tue, 30 Dec 2014 16:57:23 +0000 (13:57 -0300)
In COMMENT, DROP, SECURITY LABEL, and the new pg_get_object_address
function, we were representing types as a list of names, same as other
objects; but types are special objects that require their own
representation to be totally accurate.  In the original COMMENT code we
had a note about fixing it which was lost in the course of c10575ff005.
Change all those places to use TypeName instead, as suggested by that
comment.

Right now the original coding doesn't cause any bugs, so no backpatch.
It is more problematic for proposed future code that operate with object
addresses from the SQL interface; type details such as array-ness are
lost when working with the degraded representation.

Thanks to Petr JelĂ­nek and Dimitri Fontaine for offlist help on finding
a solution to a shift/reduce grammar conflict.

src/backend/catalog/objectaddress.c
src/backend/commands/dropcmds.c
src/backend/parser/gram.y
src/test/regress/sql/object_address.sql

index 7cb46e127872cece1ef89bb22dd3068537a31fa3..9ca609d886881d93b8daac268699496b5e52a66b 100644 (file)
@@ -646,13 +646,11 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
                                break;
                        case OBJECT_DOMCONSTRAINT:
                                {
-                                       List               *domname;
                                        ObjectAddress   domaddr;
                                        char               *constrname;
 
-                                       domname = list_truncate(list_copy(objname), list_length(objname) - 1);
-                                       constrname = strVal(llast(objname));
-                                       domaddr = get_object_address_type(OBJECT_DOMAIN, domname, missing_ok);
+                                       domaddr = get_object_address_type(OBJECT_DOMAIN, objname, missing_ok);
+                                       constrname = strVal(linitial(objargs));
 
                                        address.classId = ConstraintRelationId;
                                        address.objectId = get_domain_constraint_oid(domaddr.objectId,
@@ -1291,14 +1289,13 @@ get_object_address_attrdef(ObjectType objtype, List *objname,
  * Find the ObjectAddress for a type or domain
  */
 static ObjectAddress
-get_object_address_type(ObjectType objtype,
-                                               List *objname, bool missing_ok)
+get_object_address_type(ObjectType objtype, List *objname, bool missing_ok)
 {
        ObjectAddress address;
        TypeName   *typename;
        Type            tup;
 
-       typename = makeTypeNameFromNameList(objname);
+       typename = (TypeName *) linitial(objname);
 
        address.classId = TypeRelationId;
        address.objectId = InvalidOid;
@@ -1428,27 +1425,8 @@ pg_get_object_address(PG_FUNCTION_ARGS)
         * given object type.  Most use a simple string Values list, but there
         * are some exceptions.
         */
-       if (type == OBJECT_TYPE || type == OBJECT_DOMAIN)
-       {
-               Datum   *elems;
-               bool    *nulls;
-               int             nelems;
-               TypeName *typname;
-
-               deconstruct_array(namearr, TEXTOID, -1, false, 'i',
-                                                 &elems, &nulls, &nelems);
-               if (nelems != 1)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                        errmsg("name list length must be exactly %d", 1)));
-               if (nulls[0])
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                        errmsg("name or argument lists may not contain nulls")));
-               typname = typeStringToTypeName(TextDatumGetCString(elems[0]));
-               name = typname->names;
-       }
-       else if (type == OBJECT_CAST)
+       if (type == OBJECT_TYPE || type == OBJECT_DOMAIN || type == OBJECT_CAST ||
+               type == OBJECT_DOMCONSTRAINT)
        {
                Datum   *elems;
                bool    *nulls;
@@ -1533,18 +1511,13 @@ pg_get_object_address(PG_FUNCTION_ARGS)
         */
        switch (type)
        {
-               case OBJECT_DOMCONSTRAINT:
-                       if (list_length(name) < 2)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                errmsg("name list length must be at least %d", 2)));
-                       break;
                case OBJECT_LARGEOBJECT:
                        if (list_length(name) != 1)
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                errmsg("name list length must be %d", 1)));
+                                                errmsg("name list length must be exactly %d", 1)));
                        break;
+               case OBJECT_DOMCONSTRAINT:
                case OBJECT_OPCLASS:
                case OBJECT_OPFAMILY:
                case OBJECT_CAST:
index 858358166d9ab0db7e15a51067e133b51cd1cdeb..21a2ae441a7e86f9f4d27b5176b801fd9c6f4fd0 100644 (file)
@@ -264,10 +264,14 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
        {
                case OBJECT_TYPE:
                case OBJECT_DOMAIN:
-                       if (!schema_does_not_exist_skipping(objname, &msg, &name))
                        {
-                               msg = gettext_noop("type \"%s\" does not exist, skipping");
-                               name = TypeNameToString(makeTypeNameFromNameList(objname));
+                               TypeName   *typ = linitial(objname);
+
+                               if (!schema_does_not_exist_skipping(typ->names, &msg, &name))
+                               {
+                                       msg = gettext_noop("type \"%s\" does not exist, skipping");
+                                       name = TypeNameToString(typ);
+                               }
                        }
                        break;
                case OBJECT_COLLATION:
index 6431601c6658554f2e5901ddc5a5a24224f9c490..eaaf2c23336bdfd25ac79b7d1b2f57603a322b06 100644 (file)
@@ -351,7 +351,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
                                opt_column_list columnList opt_name_list
                                sort_clause opt_sort_clause sortby_list index_params
                                name_list role_list from_clause from_list opt_array_bounds
-                               qualified_name_list any_name any_name_list
+                               qualified_name_list any_name any_name_list type_name_list
                                any_operator expr_list attrs
                                target_list opt_target_list insert_column_list set_target_list
                                set_clause_list set_clause multiple_set_clause
@@ -5471,6 +5471,46 @@ DropStmt:        DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
                                        n->concurrent = false;
                                        $$ = (Node *)n;
                                }
+                       | DROP TYPE_P type_name_list opt_drop_behavior
+                               {
+                                       DropStmt *n = makeNode(DropStmt);
+                                       n->removeType = OBJECT_TYPE;
+                                       n->missing_ok = FALSE;
+                                       n->objects = $3;
+                                       n->behavior = $4;
+                                       n->concurrent = false;
+                                       $$ = (Node *) n;
+                               }
+                       | DROP TYPE_P IF_P EXISTS type_name_list opt_drop_behavior
+                               {
+                                       DropStmt *n = makeNode(DropStmt);
+                                       n->removeType = OBJECT_TYPE;
+                                       n->missing_ok = TRUE;
+                                       n->objects = $5;
+                                       n->behavior = $6;
+                                       n->concurrent = false;
+                                       $$ = (Node *) n;
+                               }
+                       | DROP DOMAIN_P type_name_list opt_drop_behavior
+                               {
+                                       DropStmt *n = makeNode(DropStmt);
+                                       n->removeType = OBJECT_DOMAIN;
+                                       n->missing_ok = FALSE;
+                                       n->objects = $3;
+                                       n->behavior = $4;
+                                       n->concurrent = false;
+                                       $$ = (Node *) n;
+                               }
+                       | DROP DOMAIN_P IF_P EXISTS type_name_list opt_drop_behavior
+                               {
+                                       DropStmt *n = makeNode(DropStmt);
+                                       n->removeType = OBJECT_DOMAIN;
+                                       n->missing_ok = TRUE;
+                                       n->objects = $5;
+                                       n->behavior = $6;
+                                       n->concurrent = false;
+                                       $$ = (Node *) n;
+                               }
                        | DROP INDEX CONCURRENTLY any_name_list opt_drop_behavior
                                {
                                        DropStmt *n = makeNode(DropStmt);
@@ -5503,8 +5543,6 @@ drop_type:        TABLE                                                                   { $$ = OBJECT_TABLE; }
                        | INDEX                                                                 { $$ = OBJECT_INDEX; }
                        | FOREIGN TABLE                                                 { $$ = OBJECT_FOREIGN_TABLE; }
                        | EVENT TRIGGER                                                 { $$ = OBJECT_EVENT_TRIGGER; }
-                       | TYPE_P                                                                { $$ = OBJECT_TYPE; }
-                       | DOMAIN_P                                                              { $$ = OBJECT_DOMAIN; }
                        | COLLATION                                                             { $$ = OBJECT_COLLATION; }
                        | CONVERSION_P                                                  { $$ = OBJECT_CONVERSION; }
                        | SCHEMA                                                                { $$ = OBJECT_SCHEMA; }
@@ -5530,6 +5568,9 @@ attrs:            '.' attr_name
                                        { $$ = lappend($1, makeString($3)); }
                ;
 
+type_name_list:
+                       Typename                                                                { $$ = list_make1(list_make1($1)); }
+                       | type_name_list ',' Typename                   { $$ = lappend($1, list_make1($3)); }
 
 /*****************************************************************************
  *
@@ -5594,6 +5635,24 @@ CommentStmt:
                                        n->comment = $6;
                                        $$ = (Node *) n;
                                }
+                       | COMMENT ON TYPE_P Typename IS comment_text
+                               {
+                                       CommentStmt *n = makeNode(CommentStmt);
+                                       n->objtype = OBJECT_TYPE;
+                                       n->objname = list_make1($4);
+                                       n->objargs = NIL;
+                                       n->comment = $6;
+                                       $$ = (Node *) n;
+                               }
+                       | COMMENT ON DOMAIN_P Typename IS comment_text
+                               {
+                                       CommentStmt *n = makeNode(CommentStmt);
+                                       n->objtype = OBJECT_DOMAIN;
+                                       n->objname = list_make1($4);
+                                       n->objargs = NIL;
+                                       n->comment = $6;
+                                       $$ = (Node *) n;
+                               }
                        | COMMENT ON AGGREGATE func_name aggr_args IS comment_text
                                {
                                        CommentStmt *n = makeNode(CommentStmt);
@@ -5634,8 +5693,13 @@ CommentStmt:
                                {
                                        CommentStmt *n = makeNode(CommentStmt);
                                        n->objtype = OBJECT_DOMCONSTRAINT;
-                                       n->objname = lappend($7, makeString($4));
-                                       n->objargs = NIL;
+                                       /*
+                                        * should use Typename not any_name in the production, but
+                                        * there's a shift/reduce conflict if we do that, so fix it
+                                        * up here.
+                                        */
+                                       n->objname = list_make1(makeTypeNameFromNameList($7));
+                                       n->objargs = list_make1(makeString($4));
                                        n->comment = $9;
                                        $$ = (Node *) n;
                                }
@@ -5730,8 +5794,6 @@ comment_type:
                        | INDEX                                                         { $$ = OBJECT_INDEX; }
                        | SEQUENCE                                                      { $$ = OBJECT_SEQUENCE; }
                        | TABLE                                                         { $$ = OBJECT_TABLE; }
-                       | DOMAIN_P                                                      { $$ = OBJECT_DOMAIN; }
-                       | TYPE_P                                                        { $$ = OBJECT_TYPE; }
                        | VIEW                                                          { $$ = OBJECT_VIEW; }
                        | MATERIALIZED VIEW                                     { $$ = OBJECT_MATVIEW; }
                        | COLLATION                                                     { $$ = OBJECT_COLLATION; }
@@ -5776,6 +5838,28 @@ SecLabelStmt:
                                        n->label = $8;
                                        $$ = (Node *) n;
                                }
+                       | SECURITY LABEL opt_provider ON TYPE_P Typename
+                         IS security_label
+                               {
+                                       SecLabelStmt *n = makeNode(SecLabelStmt);
+                                       n->provider = $3;
+                                       n->objtype = OBJECT_TYPE;
+                                       n->objname = list_make1($6);
+                                       n->objargs = NIL;
+                                       n->label = $8;
+                                       $$ = (Node *) n;
+                               }
+                       | SECURITY LABEL opt_provider ON DOMAIN_P Typename
+                         IS security_label
+                               {
+                                       SecLabelStmt *n = makeNode(SecLabelStmt);
+                                       n->provider = $3;
+                                       n->objtype = OBJECT_TYPE;
+                                       n->objname = list_make1($6);
+                                       n->objargs = NIL;
+                                       n->label = $8;
+                                       $$ = (Node *) n;
+                               }
                        | SECURITY LABEL opt_provider ON AGGREGATE func_name aggr_args
                          IS security_label
                                {
@@ -5834,10 +5918,8 @@ security_label_type:
                        | SCHEMA                                                        { $$ = OBJECT_SCHEMA; }
                        | SEQUENCE                                                      { $$ = OBJECT_SEQUENCE; }
                        | TABLE                                                         { $$ = OBJECT_TABLE; }
-                       | DOMAIN_P                                                      { $$ = OBJECT_TYPE; }
                        | ROLE                                                          { $$ = OBJECT_ROLE; }
                        | TABLESPACE                                            { $$ = OBJECT_TABLESPACE; }
-                       | TYPE_P                                                        { $$ = OBJECT_TYPE; }
                        | VIEW                                                          { $$ = OBJECT_VIEW; }
                        | MATERIALIZED VIEW                                     { $$ = OBJECT_MATVIEW; }
                ;
index e5209b9e449545960c5b4b54ad167f28ec915391..dc55895d9325f7095049fa37b3ffdd2928c1a301 100644 (file)
@@ -132,7 +132,7 @@ WITH objects (type, name, args) AS (VALUES
                                ('cast', '{int8}', '{int4}'),
                                ('collation', '{default}', '{}'),
                                ('table constraint', '{addr_nsp, gentable, a_chk}', '{}'),
-                               ('domain constraint', '{addr_nsp, gendomain, domconstr}', '{}'),
+                               ('domain constraint', '{addr_nsp.gendomain}', '{domconstr}'),
                                ('conversion', '{pg_catalog, ascii_to_mic}', '{}'),
                                ('default value', '{addr_nsp, gentable, b}', '{}'),
                                ('language', '{plpgsql}', '{}'),