mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
COMMENT ON casts, conversions, languages, operator classes, and
large objects. Dump all these in pg_dump; also add code to pg_dump user-defined conversions. Make psql's large object code rely on the backend for inserting/deleting LOB comments, instead of trying to hack pg_description directly. Documentation and regression tests added. Christopher Kings-Lynne, code reviewed by Tom
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.93 2003/11/12 21:15:48 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.94 2003/11/21 22:32:48 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* See acl.h.
|
||||
@ -22,6 +22,7 @@
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_conversion.h"
|
||||
#include "catalog/pg_database.h"
|
||||
#include "catalog/pg_group.h"
|
||||
#include "catalog/pg_language.h"
|
||||
@ -1551,3 +1552,31 @@ pg_database_ownercheck(Oid db_oid, AclId userid)
|
||||
|
||||
return userid == dba;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ownership check for a conversion (specified by OID).
|
||||
*/
|
||||
bool
|
||||
pg_conversion_ownercheck(Oid conv_oid, AclId userid)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
AclId owner_id;
|
||||
|
||||
/* Superusers bypass all permission checking. */
|
||||
if (superuser_arg(userid))
|
||||
return true;
|
||||
|
||||
tuple = SearchSysCache(CONOID,
|
||||
ObjectIdGetDatum(conv_oid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("conversion with OID %u does not exist", conv_oid)));
|
||||
|
||||
owner_id = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
return userid == owner_id;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.73 2003/11/12 21:15:49 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.74 2003/11/21 22:32:48 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -21,6 +21,7 @@
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_constraint.h"
|
||||
#include "catalog/pg_description.h"
|
||||
#include "catalog/pg_largeobject.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_rewrite.h"
|
||||
#include "catalog/pg_trigger.h"
|
||||
@ -58,6 +59,11 @@ static void CommentProc(List *function, List *arguments, char *comment);
|
||||
static void CommentOperator(List *opername, List *arguments, char *comment);
|
||||
static void CommentTrigger(List *qualname, char *comment);
|
||||
static void CommentConstraint(List *qualname, char *comment);
|
||||
static void CommentConversion(List *qualname, char *comment);
|
||||
static void CommentLanguage(List *qualname, char *comment);
|
||||
static void CommentOpClass(List *qualname, List *arguments, char *comment);
|
||||
static void CommentLargeObject(List *qualname, char *comment);
|
||||
static void CommentCast(List *qualname, List *arguments, char *comment);
|
||||
|
||||
|
||||
/*
|
||||
@ -107,6 +113,21 @@ CommentObject(CommentStmt *stmt)
|
||||
case OBJECT_CONSTRAINT:
|
||||
CommentConstraint(stmt->objname, stmt->comment);
|
||||
break;
|
||||
case OBJECT_CONVERSION:
|
||||
CommentConversion(stmt->objname, stmt->comment);
|
||||
break;
|
||||
case OBJECT_LANGUAGE:
|
||||
CommentLanguage(stmt->objname, stmt->comment);
|
||||
break;
|
||||
case OBJECT_OPCLASS:
|
||||
CommentOpClass(stmt->objname, stmt->objargs, stmt->comment);
|
||||
break;
|
||||
case OBJECT_LARGEOBJECT:
|
||||
CommentLargeObject(stmt->objname, stmt->comment);
|
||||
break;
|
||||
case OBJECT_CAST:
|
||||
CommentCast(stmt->objname, stmt->objargs, stmt->comment);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unrecognized object type: %d",
|
||||
(int) stmt->objtype);
|
||||
@ -592,7 +613,10 @@ CommentRule(List *qualname, char *comment)
|
||||
PointerGetDatum(rulename),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cache lookup failed for rule \"%s\"", rulename);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("rule \"%s\" for relation \"%s\" does not exist",
|
||||
rulename, RelationGetRelationName(relation))));
|
||||
Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
|
||||
ruleoid = HeapTupleGetOid(tuple);
|
||||
ReleaseSysCache(tuple);
|
||||
@ -910,3 +934,297 @@ CommentConstraint(List *qualname, char *comment)
|
||||
heap_close(pg_constraint, AccessShareLock);
|
||||
heap_close(relation, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* CommentConversion --
|
||||
*
|
||||
* This routine is used to add/drop any user-comments a user might
|
||||
* have regarding a CONVERSION. The conversion is specified by name
|
||||
* and, if found, and the user has appropriate permissions, a
|
||||
* comment will be added/dropped using the CreateComments() routine.
|
||||
* The conversion's name and the comment are the parameters to this routine.
|
||||
*/
|
||||
static void
|
||||
CommentConversion(List *qualname, char *comment)
|
||||
{
|
||||
Oid conversionOid;
|
||||
Oid classoid;
|
||||
|
||||
conversionOid = FindConversionByName(qualname);
|
||||
if (!OidIsValid(conversionOid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("conversion \"%s\" does not exist",
|
||||
NameListToString(qualname))));
|
||||
|
||||
/* Check object security */
|
||||
if (!pg_conversion_ownercheck(conversionOid, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
|
||||
NameListToString(qualname));
|
||||
|
||||
/* pg_conversion doesn't have a hard-coded OID, so must look it up */
|
||||
classoid = get_system_catalog_relid(ConversionRelationName);
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
CreateComments(conversionOid, classoid, 0, comment);
|
||||
}
|
||||
|
||||
/*
|
||||
* CommentLanguage --
|
||||
*
|
||||
* This routine is used to add/drop any user-comments a user might
|
||||
* have regarding a LANGUAGE. The language is specified by name
|
||||
* and, if found, and the user has appropriate permissions, a
|
||||
* comment will be added/dropped using the CreateComments() routine.
|
||||
* The language's name and the comment are the parameters to this routine.
|
||||
*/
|
||||
static void
|
||||
CommentLanguage(List *qualname, char *comment)
|
||||
{
|
||||
Oid oid;
|
||||
Oid classoid;
|
||||
char *language;
|
||||
|
||||
if (length(qualname) != 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("language name may not be qualified")));
|
||||
language = strVal(lfirst(qualname));
|
||||
|
||||
oid = GetSysCacheOid(LANGNAME,
|
||||
CStringGetDatum(language),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(oid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
||||
errmsg("language \"%s\" does not exist", language)));
|
||||
|
||||
/* Check object security */
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to comment on procedural language")));
|
||||
|
||||
/* pg_language doesn't have a hard-coded OID, so must look it up */
|
||||
classoid = get_system_catalog_relid(LanguageRelationName);
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
CreateComments(oid, classoid, 0, comment);
|
||||
}
|
||||
|
||||
/*
|
||||
* CommentOpClass --
|
||||
*
|
||||
* This routine is used to allow a user to provide comments on an
|
||||
* operator class. The operator class for commenting is determined by both
|
||||
* its name and its argument list which defines the index method
|
||||
* the operator class is used for. The argument list is expected to contain
|
||||
* a single name (represented as a string Value node).
|
||||
*/
|
||||
static void
|
||||
CommentOpClass(List *qualname, List *arguments, char *comment)
|
||||
{
|
||||
char *amname;
|
||||
char *schemaname;
|
||||
char *opcname;
|
||||
Oid amID;
|
||||
Oid opcID;
|
||||
Oid classoid;
|
||||
HeapTuple tuple;
|
||||
|
||||
Assert(length(arguments) == 1);
|
||||
amname = strVal(lfirst(arguments));
|
||||
|
||||
/*
|
||||
* Get the access method's OID.
|
||||
*/
|
||||
amID = GetSysCacheOid(AMNAME,
|
||||
CStringGetDatum(amname),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(amID))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("access method \"%s\" does not exist",
|
||||
amname)));
|
||||
|
||||
/*
|
||||
* Look up the opclass.
|
||||
*/
|
||||
|
||||
/* deconstruct the name list */
|
||||
DeconstructQualifiedName(qualname, &schemaname, &opcname);
|
||||
|
||||
if (schemaname)
|
||||
{
|
||||
/* Look in specific schema only */
|
||||
Oid namespaceId;
|
||||
|
||||
namespaceId = LookupExplicitNamespace(schemaname);
|
||||
tuple = SearchSysCache(CLAAMNAMENSP,
|
||||
ObjectIdGetDatum(amID),
|
||||
PointerGetDatum(opcname),
|
||||
ObjectIdGetDatum(namespaceId),
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unqualified opclass name, so search the search path */
|
||||
opcID = OpclassnameGetOpcid(amID, opcname);
|
||||
if (!OidIsValid(opcID))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("operator class \"%s\" does not exist for access method \"%s\"",
|
||||
opcname, amname)));
|
||||
tuple = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(opcID),
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("operator class \"%s\" does not exist for access method \"%s\"",
|
||||
NameListToString(qualname), amname)));
|
||||
|
||||
opcID = HeapTupleGetOid(tuple);
|
||||
|
||||
/* Permission check: must own opclass */
|
||||
if (!pg_opclass_ownercheck(opcID, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
|
||||
NameListToString(qualname));
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
/* pg_opclass doesn't have a hard-coded OID, so must look it up */
|
||||
classoid = get_system_catalog_relid(OperatorClassRelationName);
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
CreateComments(opcID, classoid, 0, comment);
|
||||
}
|
||||
|
||||
/*
|
||||
* CommentLargeObject --
|
||||
*
|
||||
* This routine is used to add/drop any user-comments a user might
|
||||
* have regarding a LARGE OBJECT. The large object is specified by OID
|
||||
* and, if found, and the user has appropriate permissions, a
|
||||
* comment will be added/dropped using the CreateComments() routine.
|
||||
* The large object's OID and the comment are the parameters to this routine.
|
||||
*/
|
||||
static void
|
||||
CommentLargeObject(List *qualname, char *comment)
|
||||
{
|
||||
Oid loid;
|
||||
Oid classoid;
|
||||
Node *node;
|
||||
|
||||
Assert(length(qualname) == 1);
|
||||
node = (Node *) lfirst(qualname);
|
||||
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_Integer:
|
||||
loid = intVal(node);
|
||||
break;
|
||||
case T_Float:
|
||||
/*
|
||||
* Values too large for int4 will be represented as Float
|
||||
* constants by the lexer. Accept these if they are valid
|
||||
* OID strings.
|
||||
*/
|
||||
loid = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(strVal(node))));
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unrecognized node type: %d",
|
||||
(int) nodeTag(node));
|
||||
/* keep compiler quiet */
|
||||
loid = InvalidOid;
|
||||
}
|
||||
|
||||
/* check that the large object exists */
|
||||
if (!LargeObjectExists(loid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("large object %u does not exist", loid)));
|
||||
|
||||
/* pg_largeobject doesn't have a hard-coded OID, so must look it up */
|
||||
classoid = get_system_catalog_relid(LargeObjectRelationName);
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
CreateComments(loid, classoid, 0, comment);
|
||||
}
|
||||
|
||||
/*
|
||||
* CommentCast --
|
||||
*
|
||||
* This routine is used to add/drop any user-comments a user might
|
||||
* have regarding a CAST. The cast is specified by source and destination types
|
||||
* and, if found, and the user has appropriate permissions, a
|
||||
* comment will be added/dropped using the CreateComments() routine.
|
||||
* The cast's source type is passed as the "name", the destination type
|
||||
* as the "arguments".
|
||||
*/
|
||||
static void
|
||||
CommentCast(List *qualname, List *arguments, char *comment)
|
||||
{
|
||||
TypeName *sourcetype;
|
||||
TypeName *targettype;
|
||||
Oid sourcetypeid;
|
||||
Oid targettypeid;
|
||||
HeapTuple tuple;
|
||||
Oid castOid;
|
||||
Oid classoid;
|
||||
|
||||
Assert(length(qualname) == 1);
|
||||
sourcetype = (TypeName *) lfirst(qualname);
|
||||
Assert(IsA(sourcetype, TypeName));
|
||||
Assert(length(arguments) == 1);
|
||||
targettype = (TypeName *) lfirst(arguments);
|
||||
Assert(IsA(targettype, TypeName));
|
||||
|
||||
sourcetypeid = typenameTypeId(sourcetype);
|
||||
if (!OidIsValid(sourcetypeid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("source data type %s does not exist",
|
||||
TypeNameToString(sourcetype))));
|
||||
|
||||
targettypeid = typenameTypeId(targettype);
|
||||
if (!OidIsValid(targettypeid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("target data type %s does not exist",
|
||||
TypeNameToString(targettype))));
|
||||
|
||||
tuple = SearchSysCache(CASTSOURCETARGET,
|
||||
ObjectIdGetDatum(sourcetypeid),
|
||||
ObjectIdGetDatum(targettypeid),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("cast from type %s to type %s does not exist",
|
||||
TypeNameToString(sourcetype),
|
||||
TypeNameToString(targettype))));
|
||||
|
||||
/* Get the OID of the cast */
|
||||
castOid = HeapTupleGetOid(tuple);
|
||||
|
||||
/* Permission check */
|
||||
if (!pg_type_ownercheck(sourcetypeid, GetUserId())
|
||||
&& !pg_type_ownercheck(targettypeid, GetUserId()))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be owner of type %s or type %s",
|
||||
TypeNameToString(sourcetype),
|
||||
TypeNameToString(targettype))));
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
/* pg_cast doesn't have a hard-coded OID, so must look it up */
|
||||
classoid = get_system_catalog_relid(CastRelationName);
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
CreateComments(castOid, classoid, 0, comment);
|
||||
}
|
||||
|
@ -2,14 +2,15 @@
|
||||
*
|
||||
* functioncmds.c
|
||||
*
|
||||
* Routines for CREATE and DROP FUNCTION commands
|
||||
* Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
|
||||
* CAST commands.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.40 2003/11/12 21:15:50 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.41 2003/11/21 22:32:48 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* These routines take the parse tree and pick out the
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.437 2003/11/06 22:08:14 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.438 2003/11/21 22:32:49 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -363,7 +363,7 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
KEY
|
||||
|
||||
LANCOMPILER LANGUAGE LAST_P LEADING LEFT LEVEL LIKE LIMIT
|
||||
LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEFT LEVEL LIKE LIMIT
|
||||
LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
|
||||
LOCK_P
|
||||
|
||||
@ -373,7 +373,7 @@ static void doNegateFloat(Value *v);
|
||||
NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NULL_P
|
||||
NULLIF NUMERIC
|
||||
|
||||
OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR
|
||||
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR
|
||||
ORDER OUT_P OUTER_P OVERLAPS OVERLAY OWNER
|
||||
|
||||
PARTIAL PASSWORD PATH_P PENDANT PLACING POSITION
|
||||
@ -2519,11 +2519,15 @@ TruncateStmt:
|
||||
* The COMMENT ON statement can take different forms based upon the type of
|
||||
* the object associated with the comment. The form of the statement is:
|
||||
*
|
||||
* COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW ]
|
||||
* <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
|
||||
* <funcname> (arg1, arg2, ...) | OPERATOR <op>
|
||||
* (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
|
||||
* <relname> | RULE <rulename> ON <relname> ] IS 'text'
|
||||
* COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW |
|
||||
* CONVERSION | LANGUAGE | OPERATOR CLASS | LARGE OBJECT |
|
||||
* CAST ] <objname> |
|
||||
* AGGREGATE <aggname> (<aggtype>) |
|
||||
* FUNCTION <funcname> (arg1, arg2, ...) |
|
||||
* OPERATOR <op> (leftoperand_typ, rightoperand_typ) |
|
||||
* TRIGGER <triggername> ON <relname> |
|
||||
* RULE <rulename> ON <relname> ]
|
||||
* IS 'text'
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
@ -2603,6 +2607,42 @@ CommentStmt:
|
||||
n->comment = $8;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| COMMENT ON OPERATOR CLASS any_name USING access_method IS comment_text
|
||||
{
|
||||
CommentStmt *n = makeNode(CommentStmt);
|
||||
n->objtype = OBJECT_OPCLASS;
|
||||
n->objname = $5;
|
||||
n->objargs = makeList1(makeString($7));
|
||||
n->comment = $9;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| COMMENT ON LARGE_P OBJECT_P NumericOnly IS comment_text
|
||||
{
|
||||
CommentStmt *n = makeNode(CommentStmt);
|
||||
n->objtype = OBJECT_LARGEOBJECT;
|
||||
n->objname = makeList1($5);
|
||||
n->objargs = NIL;
|
||||
n->comment = $7;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| COMMENT ON CAST '(' Typename AS Typename ')' IS comment_text
|
||||
{
|
||||
CommentStmt *n = makeNode(CommentStmt);
|
||||
n->objtype = OBJECT_CAST;
|
||||
n->objname = makeList1($5);
|
||||
n->objargs = makeList1($7);
|
||||
n->comment = $10;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| COMMENT ON opt_procedural LANGUAGE any_name IS comment_text
|
||||
{
|
||||
CommentStmt *n = makeNode(CommentStmt);
|
||||
n->objtype = OBJECT_LANGUAGE;
|
||||
n->objname = $5;
|
||||
n->objargs = NIL;
|
||||
n->comment = $7;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
;
|
||||
|
||||
comment_type:
|
||||
@ -2615,6 +2655,7 @@ comment_type:
|
||||
| DOMAIN_P { $$ = OBJECT_TYPE; }
|
||||
| TYPE_P { $$ = OBJECT_TYPE; }
|
||||
| VIEW { $$ = OBJECT_VIEW; }
|
||||
| CONVERSION_P { $$ = OBJECT_CONVERSION; }
|
||||
;
|
||||
|
||||
comment_text:
|
||||
@ -7365,6 +7406,7 @@ unreserved_keyword:
|
||||
| KEY
|
||||
| LANCOMPILER
|
||||
| LANGUAGE
|
||||
| LARGE_P
|
||||
| LAST_P
|
||||
| LEVEL
|
||||
| LISTEN
|
||||
@ -7387,6 +7429,7 @@ unreserved_keyword:
|
||||
| NOCREATEUSER
|
||||
| NOTHING
|
||||
| NOTIFY
|
||||
| OBJECT_P
|
||||
| OF
|
||||
| OIDS
|
||||
| OPERATOR
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.142 2003/11/06 22:08:15 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.143 2003/11/21 22:32:49 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -177,6 +177,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"key", KEY},
|
||||
{"lancompiler", LANCOMPILER},
|
||||
{"language", LANGUAGE},
|
||||
{"large", LARGE_P},
|
||||
{"last", LAST_P},
|
||||
{"leading", LEADING},
|
||||
{"left", LEFT},
|
||||
@ -214,6 +215,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"null", NULL_P},
|
||||
{"nullif", NULLIF},
|
||||
{"numeric", NUMERIC},
|
||||
{"object", OBJECT_P},
|
||||
{"of", OF},
|
||||
{"off", OFF},
|
||||
{"offset", OFFSET},
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.100 2003/11/12 21:15:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.101 2003/11/21 22:32:49 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -31,12 +31,14 @@
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_largeobject.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/comment.h"
|
||||
#include "libpq/libpq-fs.h"
|
||||
#include "miscadmin.h"
|
||||
#include "storage/large_object.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
|
||||
static int32
|
||||
@ -174,8 +176,16 @@ inv_close(LargeObjectDesc *obj_desc)
|
||||
int
|
||||
inv_drop(Oid lobjId)
|
||||
{
|
||||
Oid classoid;
|
||||
|
||||
LargeObjectDrop(lobjId);
|
||||
|
||||
/* pg_largeobject doesn't have a hard-coded OID, so must look it up */
|
||||
classoid = get_system_catalog_relid(LargeObjectRelationName);
|
||||
|
||||
/* Delete any comments on the large object */
|
||||
DeleteComments(lobjId, classoid, 0);
|
||||
|
||||
/*
|
||||
* Advance command counter so that tuple removal will be seen by later
|
||||
* large-object operations in this transaction.
|
||||
|
Reference in New Issue
Block a user