Commit 3f88672a authored by Alvaro Herrera's avatar Alvaro Herrera

Use TypeName to represent type names in certain commands

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 c10575ff.
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.
parent 930fd684
......@@ -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:
......
......@@ -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:
......
......@@ -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; }
;
......
......@@ -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}', '{}'),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment