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:
parent
0a97cb37fc
commit
42ce74bf17
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.23 2003/09/09 18:28:52 tgl Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.24 2003/11/21 22:32:48 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -25,12 +25,17 @@ COMMENT ON
|
|||||||
TABLE <replaceable class="PARAMETER">object_name</replaceable> |
|
TABLE <replaceable class="PARAMETER">object_name</replaceable> |
|
||||||
COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
|
COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
|
||||||
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
|
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
|
||||||
|
CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>) |
|
||||||
CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> |
|
CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> |
|
||||||
|
CONVERSION <replaceable class="PARAMETER">object_name</replaceable> |
|
||||||
DATABASE <replaceable class="PARAMETER">object_name</replaceable> |
|
DATABASE <replaceable class="PARAMETER">object_name</replaceable> |
|
||||||
DOMAIN <replaceable class="PARAMETER">object_name</replaceable> |
|
DOMAIN <replaceable class="PARAMETER">object_name</replaceable> |
|
||||||
FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1_type</replaceable>, <replaceable class="PARAMETER">arg2_type</replaceable>, ...) |
|
FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1_type</replaceable>, <replaceable class="PARAMETER">arg2_type</replaceable>, ...) |
|
||||||
INDEX <replaceable class="PARAMETER">object_name</replaceable> |
|
INDEX <replaceable class="PARAMETER">object_name</replaceable> |
|
||||||
|
LARGE OBJECT <replaceable class="PARAMETER">large_object_oid</replaceable> |
|
||||||
OPERATOR <replaceable class="PARAMETER">op</replaceable> (<replaceable class="PARAMETER">leftoperand_type</replaceable>, <replaceable class="PARAMETER">rightoperand_type</replaceable>) |
|
OPERATOR <replaceable class="PARAMETER">op</replaceable> (<replaceable class="PARAMETER">leftoperand_type</replaceable>, <replaceable class="PARAMETER">rightoperand_type</replaceable>) |
|
||||||
|
OPERATOR CLASS <replaceable class="PARAMETER">object_name</replaceable> USING <replaceable class="parameter">index_method</replaceable> |
|
||||||
|
[ PROCEDURAL ] LANGUAGE <replaceable class="PARAMETER">object_name</replaceable> |
|
||||||
RULE <replaceable class="PARAMETER">rule_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> |
|
RULE <replaceable class="PARAMETER">rule_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> |
|
||||||
SCHEMA <replaceable class="PARAMETER">object_name</replaceable> |
|
SCHEMA <replaceable class="PARAMETER">object_name</replaceable> |
|
||||||
SEQUENCE <replaceable class="PARAMETER">object_name</replaceable> |
|
SEQUENCE <replaceable class="PARAMETER">object_name</replaceable> |
|
||||||
@ -70,7 +75,7 @@ COMMENT ON
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><replaceable class="parameter">object_name</replaceable></term>
|
<term><replaceable class="parameter">object_name</replaceable></term>
|
||||||
<term><replaceable class="parameter">table_name.column_name</replaceable></term>
|
<term><replaceable class="parameter">table_name.column_name</replaceable></term>
|
||||||
<term><replaceable class="parameter">aggname</replaceable></term>
|
<term><replaceable class="parameter">agg_name</replaceable></term>
|
||||||
<term><replaceable class="parameter">constraint_name</replaceable></term>
|
<term><replaceable class="parameter">constraint_name</replaceable></term>
|
||||||
<term><replaceable class="parameter">func_name</replaceable></term>
|
<term><replaceable class="parameter">func_name</replaceable></term>
|
||||||
<term><replaceable class="parameter">op</replaceable></term>
|
<term><replaceable class="parameter">op</replaceable></term>
|
||||||
@ -78,9 +83,56 @@ COMMENT ON
|
|||||||
<term><replaceable class="parameter">trigger_name</replaceable></term>
|
<term><replaceable class="parameter">trigger_name</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The name of the object to be be commented. Names of tables,
|
The name of the object to be commented. Names of tables,
|
||||||
aggregates, domains, functions, indexes, operators, sequences,
|
aggregates, domains, functions, indexes, operators, operator classes,
|
||||||
types, and views may be schema-qualified.
|
sequences, types, and views may be schema-qualified.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="parameter">agg_type</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The argument data type of the aggregate function, or
|
||||||
|
<literal>*</literal> if the function accepts any data type.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="parameter">large_object_oid</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The OID of the large object.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>PROCEDURAL</literal></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This is a noise word.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable>sourcetype</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The name of the source data type of the cast.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable>targettype</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The name of the target data type of the cast.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -93,12 +145,18 @@ COMMENT ON
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Notes</title>
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A comment for a database can only be created in that database,
|
||||||
|
and will only be visible in that database, not in other databases.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
There is presently no security mechanism for comments: any user
|
There is presently no security mechanism for comments: any user
|
||||||
connected to a database can see all the comments for objects in
|
connected to a database can see all the comments for objects in
|
||||||
@ -130,13 +188,18 @@ COMMENT ON TABLE mytable IS NULL;
|
|||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
COMMENT ON AGGREGATE my_aggregate (double precision) IS 'Computes sample variance';
|
COMMENT ON AGGREGATE my_aggregate (double precision) IS 'Computes sample variance';
|
||||||
|
COMMENT ON CAST (text AS int4) IS 'Allow casts from text to int4';
|
||||||
COMMENT ON COLUMN my_table.my_column IS 'Employee ID number';
|
COMMENT ON COLUMN my_table.my_column IS 'Employee ID number';
|
||||||
|
COMMENT ON CONVERSION my_conv IS 'Conversion to Unicode';
|
||||||
COMMENT ON DATABASE my_database IS 'Development Database';
|
COMMENT ON DATABASE my_database IS 'Development Database';
|
||||||
COMMENT ON DOMAIN my_domain IS 'Email Address Domain';
|
COMMENT ON DOMAIN my_domain IS 'Email Address Domain';
|
||||||
COMMENT ON FUNCTION my_function (timestamp) IS 'Returns Roman Numeral';
|
COMMENT ON FUNCTION my_function (timestamp) IS 'Returns Roman Numeral';
|
||||||
COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee ID';
|
COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee ID';
|
||||||
|
COMMENT ON LANGUAGE plpython IS 'Python support for stored procedures';
|
||||||
|
COMMENT ON LARGE OBJECT 346344 IS 'Planning document';
|
||||||
COMMENT ON OPERATOR ^ (text, text) IS 'Performs intersection of two texts';
|
COMMENT ON OPERATOR ^ (text, text) IS 'Performs intersection of two texts';
|
||||||
COMMENT ON OPERATOR ^ (NONE, text) IS 'This is a prefix operator on text';
|
COMMENT ON OPERATOR ^ (NONE, text) IS 'This is a prefix operator on text';
|
||||||
|
COMMENT ON OPERATOR CLASS int4ops USING btree IS '4 byte integer operators for btrees';
|
||||||
COMMENT ON RULE my_rule ON my_table IS 'Logs updates of employee records';
|
COMMENT ON RULE my_rule ON my_table IS 'Logs updates of employee records';
|
||||||
COMMENT ON SCHEMA my_schema IS 'Departmental data';
|
COMMENT ON SCHEMA my_schema IS 'Departmental data';
|
||||||
COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
|
COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* See acl.h.
|
* See acl.h.
|
||||||
@ -22,6 +22,7 @@
|
|||||||
#include "catalog/catname.h"
|
#include "catalog/catname.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
|
#include "catalog/pg_conversion.h"
|
||||||
#include "catalog/pg_database.h"
|
#include "catalog/pg_database.h"
|
||||||
#include "catalog/pg_group.h"
|
#include "catalog/pg_group.h"
|
||||||
#include "catalog/pg_language.h"
|
#include "catalog/pg_language.h"
|
||||||
@ -1551,3 +1552,31 @@ pg_database_ownercheck(Oid db_oid, AclId userid)
|
|||||||
|
|
||||||
return userid == dba;
|
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
|
* Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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/namespace.h"
|
||||||
#include "catalog/pg_constraint.h"
|
#include "catalog/pg_constraint.h"
|
||||||
#include "catalog/pg_description.h"
|
#include "catalog/pg_description.h"
|
||||||
|
#include "catalog/pg_largeobject.h"
|
||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_rewrite.h"
|
#include "catalog/pg_rewrite.h"
|
||||||
#include "catalog/pg_trigger.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 CommentOperator(List *opername, List *arguments, char *comment);
|
||||||
static void CommentTrigger(List *qualname, char *comment);
|
static void CommentTrigger(List *qualname, char *comment);
|
||||||
static void CommentConstraint(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:
|
case OBJECT_CONSTRAINT:
|
||||||
CommentConstraint(stmt->objname, stmt->comment);
|
CommentConstraint(stmt->objname, stmt->comment);
|
||||||
break;
|
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:
|
default:
|
||||||
elog(ERROR, "unrecognized object type: %d",
|
elog(ERROR, "unrecognized object type: %d",
|
||||||
(int) stmt->objtype);
|
(int) stmt->objtype);
|
||||||
@ -592,7 +613,10 @@ CommentRule(List *qualname, char *comment)
|
|||||||
PointerGetDatum(rulename),
|
PointerGetDatum(rulename),
|
||||||
0, 0);
|
0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
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);
|
Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
|
||||||
ruleoid = HeapTupleGetOid(tuple);
|
ruleoid = HeapTupleGetOid(tuple);
|
||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
@ -910,3 +934,297 @@ CommentConstraint(List *qualname, char *comment)
|
|||||||
heap_close(pg_constraint, AccessShareLock);
|
heap_close(pg_constraint, AccessShareLock);
|
||||||
heap_close(relation, NoLock);
|
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
|
* 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) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* DESCRIPTION
|
||||||
* These routines take the parse tree and pick out the
|
* These routines take the parse tree and pick out the
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -363,7 +363,7 @@ static void doNegateFloat(Value *v);
|
|||||||
|
|
||||||
KEY
|
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
|
LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
|
||||||
LOCK_P
|
LOCK_P
|
||||||
|
|
||||||
@ -373,7 +373,7 @@ static void doNegateFloat(Value *v);
|
|||||||
NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NULL_P
|
NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NULL_P
|
||||||
NULLIF NUMERIC
|
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
|
ORDER OUT_P OUTER_P OVERLAPS OVERLAY OWNER
|
||||||
|
|
||||||
PARTIAL PASSWORD PATH_P PENDANT PLACING POSITION
|
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 COMMENT ON statement can take different forms based upon the type of
|
||||||
* the object associated with the comment. The form of the statement is:
|
* the object associated with the comment. The form of the statement is:
|
||||||
*
|
*
|
||||||
* COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW ]
|
* COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW |
|
||||||
* <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
|
* CONVERSION | LANGUAGE | OPERATOR CLASS | LARGE OBJECT |
|
||||||
* <funcname> (arg1, arg2, ...) | OPERATOR <op>
|
* CAST ] <objname> |
|
||||||
* (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
|
* AGGREGATE <aggname> (<aggtype>) |
|
||||||
* <relname> | RULE <rulename> ON <relname> ] IS 'text'
|
* 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;
|
n->comment = $8;
|
||||||
$$ = (Node *) n;
|
$$ = (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:
|
comment_type:
|
||||||
@ -2615,6 +2655,7 @@ comment_type:
|
|||||||
| DOMAIN_P { $$ = OBJECT_TYPE; }
|
| DOMAIN_P { $$ = OBJECT_TYPE; }
|
||||||
| TYPE_P { $$ = OBJECT_TYPE; }
|
| TYPE_P { $$ = OBJECT_TYPE; }
|
||||||
| VIEW { $$ = OBJECT_VIEW; }
|
| VIEW { $$ = OBJECT_VIEW; }
|
||||||
|
| CONVERSION_P { $$ = OBJECT_CONVERSION; }
|
||||||
;
|
;
|
||||||
|
|
||||||
comment_text:
|
comment_text:
|
||||||
@ -7365,6 +7406,7 @@ unreserved_keyword:
|
|||||||
| KEY
|
| KEY
|
||||||
| LANCOMPILER
|
| LANCOMPILER
|
||||||
| LANGUAGE
|
| LANGUAGE
|
||||||
|
| LARGE_P
|
||||||
| LAST_P
|
| LAST_P
|
||||||
| LEVEL
|
| LEVEL
|
||||||
| LISTEN
|
| LISTEN
|
||||||
@ -7387,6 +7429,7 @@ unreserved_keyword:
|
|||||||
| NOCREATEUSER
|
| NOCREATEUSER
|
||||||
| NOTHING
|
| NOTHING
|
||||||
| NOTIFY
|
| NOTIFY
|
||||||
|
| OBJECT_P
|
||||||
| OF
|
| OF
|
||||||
| OIDS
|
| OIDS
|
||||||
| OPERATOR
|
| OPERATOR
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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},
|
{"key", KEY},
|
||||||
{"lancompiler", LANCOMPILER},
|
{"lancompiler", LANCOMPILER},
|
||||||
{"language", LANGUAGE},
|
{"language", LANGUAGE},
|
||||||
|
{"large", LARGE_P},
|
||||||
{"last", LAST_P},
|
{"last", LAST_P},
|
||||||
{"leading", LEADING},
|
{"leading", LEADING},
|
||||||
{"left", LEFT},
|
{"left", LEFT},
|
||||||
@ -214,6 +215,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||||||
{"null", NULL_P},
|
{"null", NULL_P},
|
||||||
{"nullif", NULLIF},
|
{"nullif", NULLIF},
|
||||||
{"numeric", NUMERIC},
|
{"numeric", NUMERIC},
|
||||||
|
{"object", OBJECT_P},
|
||||||
{"of", OF},
|
{"of", OF},
|
||||||
{"off", OFF},
|
{"off", OFF},
|
||||||
{"offset", OFFSET},
|
{"offset", OFFSET},
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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_opclass.h"
|
||||||
#include "catalog/pg_largeobject.h"
|
#include "catalog/pg_largeobject.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
|
#include "commands/comment.h"
|
||||||
#include "libpq/libpq-fs.h"
|
#include "libpq/libpq-fs.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "storage/large_object.h"
|
#include "storage/large_object.h"
|
||||||
#include "storage/smgr.h"
|
#include "storage/smgr.h"
|
||||||
#include "utils/fmgroids.h"
|
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/fmgroids.h"
|
||||||
|
#include "utils/lsyscache.h"
|
||||||
|
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
@ -174,8 +176,16 @@ inv_close(LargeObjectDesc *obj_desc)
|
|||||||
int
|
int
|
||||||
inv_drop(Oid lobjId)
|
inv_drop(Oid lobjId)
|
||||||
{
|
{
|
||||||
|
Oid classoid;
|
||||||
|
|
||||||
LargeObjectDrop(lobjId);
|
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
|
* Advance command counter so that tuple removal will be seen by later
|
||||||
* large-object operations in this transaction.
|
* large-object operations in this transaction.
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.75 2003/08/04 02:40:09 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.76 2003/11/21 22:32:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -61,6 +61,7 @@ dumpSchema(Archive *fout,
|
|||||||
int numAggregates;
|
int numAggregates;
|
||||||
int numOperators;
|
int numOperators;
|
||||||
int numOpclasses;
|
int numOpclasses;
|
||||||
|
int numConversions;
|
||||||
NamespaceInfo *nsinfo;
|
NamespaceInfo *nsinfo;
|
||||||
TypeInfo *tinfo;
|
TypeInfo *tinfo;
|
||||||
FuncInfo *finfo;
|
FuncInfo *finfo;
|
||||||
@ -69,6 +70,7 @@ dumpSchema(Archive *fout,
|
|||||||
InhInfo *inhinfo;
|
InhInfo *inhinfo;
|
||||||
OprInfo *oprinfo;
|
OprInfo *oprinfo;
|
||||||
OpclassInfo *opcinfo;
|
OpclassInfo *opcinfo;
|
||||||
|
ConvInfo *convinfo;
|
||||||
|
|
||||||
if (g_verbose)
|
if (g_verbose)
|
||||||
write_msg(NULL, "reading schemas\n");
|
write_msg(NULL, "reading schemas\n");
|
||||||
@ -94,6 +96,10 @@ dumpSchema(Archive *fout,
|
|||||||
write_msg(NULL, "reading user-defined operator classes\n");
|
write_msg(NULL, "reading user-defined operator classes\n");
|
||||||
opcinfo = getOpclasses(&numOpclasses);
|
opcinfo = getOpclasses(&numOpclasses);
|
||||||
|
|
||||||
|
if (g_verbose)
|
||||||
|
write_msg(NULL, "reading user-defined conversions\n");
|
||||||
|
convinfo = getConversions(&numConversions);
|
||||||
|
|
||||||
if (g_verbose)
|
if (g_verbose)
|
||||||
write_msg(NULL, "reading user-defined tables\n");
|
write_msg(NULL, "reading user-defined tables\n");
|
||||||
tblinfo = getTables(&numTables);
|
tblinfo = getTables(&numTables);
|
||||||
@ -190,6 +196,13 @@ dumpSchema(Archive *fout,
|
|||||||
dumpCasts(fout, finfo, numFuncs, tinfo, numTypes);
|
dumpCasts(fout, finfo, numFuncs, tinfo, numTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!dataOnly)
|
||||||
|
{
|
||||||
|
if (g_verbose)
|
||||||
|
write_msg(NULL, "dumping out user-defined conversions\n");
|
||||||
|
dumpConversions(fout, convinfo, numConversions);
|
||||||
|
}
|
||||||
|
|
||||||
*numTablesPtr = numTables;
|
*numTablesPtr = numTables;
|
||||||
return tblinfo;
|
return tblinfo;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* by PostgreSQL
|
* by PostgreSQL
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.355 2003/10/28 21:05:29 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.356 2003/11/21 22:32:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -105,6 +105,7 @@ static const char *convertRegProcReference(const char *proc);
|
|||||||
static const char *convertOperatorReference(const char *opr,
|
static const char *convertOperatorReference(const char *opr,
|
||||||
OprInfo *g_oprinfo, int numOperators);
|
OprInfo *g_oprinfo, int numOperators);
|
||||||
static void dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo);
|
static void dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo);
|
||||||
|
static void dumpOneConversion(Archive *fout, ConvInfo *convinfo);
|
||||||
static void dumpOneAgg(Archive *fout, AggInfo *agginfo);
|
static void dumpOneAgg(Archive *fout, AggInfo *agginfo);
|
||||||
static Oid findLastBuiltinOid_V71(const char *);
|
static Oid findLastBuiltinOid_V71(const char *);
|
||||||
static Oid findLastBuiltinOid_V70(void);
|
static Oid findLastBuiltinOid_V70(void);
|
||||||
@ -1689,6 +1690,79 @@ getOperators(int *numOprs)
|
|||||||
return oprinfo;
|
return oprinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getConversions:
|
||||||
|
* read all conversions in the system catalogs and return them in the
|
||||||
|
* ConvInfo* structure
|
||||||
|
*
|
||||||
|
* numConversions is set to the number of conversions read in
|
||||||
|
*/
|
||||||
|
ConvInfo *
|
||||||
|
getConversions(int *numConversions)
|
||||||
|
{
|
||||||
|
PGresult *res;
|
||||||
|
int ntups;
|
||||||
|
int i;
|
||||||
|
PQExpBuffer query = createPQExpBuffer();
|
||||||
|
ConvInfo *convinfo;
|
||||||
|
int i_oid;
|
||||||
|
int i_conname;
|
||||||
|
int i_connamespace;
|
||||||
|
int i_usename;
|
||||||
|
|
||||||
|
/* Conversions didn't exist pre-7.3 */
|
||||||
|
if (g_fout->remoteVersion < 70300) {
|
||||||
|
*numConversions = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find all conversions, including builtin conversions; we filter out
|
||||||
|
* system-defined conversions at dump-out time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Make sure we are in proper schema */
|
||||||
|
selectSourceSchema("pg_catalog");
|
||||||
|
|
||||||
|
appendPQExpBuffer(query, "SELECT pg_conversion.oid, conname, "
|
||||||
|
"connamespace, "
|
||||||
|
"(select usename from pg_user where conowner = usesysid) as usename "
|
||||||
|
"from pg_conversion");
|
||||||
|
|
||||||
|
res = PQexec(g_conn, query->data);
|
||||||
|
if (!res ||
|
||||||
|
PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
|
{
|
||||||
|
write_msg(NULL, "query to obtain list of conversions failed: %s", PQerrorMessage(g_conn));
|
||||||
|
exit_nicely();
|
||||||
|
}
|
||||||
|
|
||||||
|
ntups = PQntuples(res);
|
||||||
|
*numConversions = ntups;
|
||||||
|
|
||||||
|
convinfo = (ConvInfo *) malloc(ntups * sizeof(ConvInfo));
|
||||||
|
|
||||||
|
i_oid = PQfnumber(res, "oid");
|
||||||
|
i_conname = PQfnumber(res, "conname");
|
||||||
|
i_connamespace = PQfnumber(res, "connamespace");
|
||||||
|
i_usename = PQfnumber(res, "usename");
|
||||||
|
|
||||||
|
for (i = 0; i < ntups; i++)
|
||||||
|
{
|
||||||
|
convinfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
|
||||||
|
convinfo[i].conname = strdup(PQgetvalue(res, i, i_conname));
|
||||||
|
convinfo[i].connamespace = findNamespace(PQgetvalue(res, i, i_connamespace),
|
||||||
|
convinfo[i].oid);
|
||||||
|
convinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
|
||||||
|
}
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
destroyPQExpBuffer(query);
|
||||||
|
|
||||||
|
return convinfo;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getOpclasses:
|
* getOpclasses:
|
||||||
* read all opclasses in the system catalogs and return them in the
|
* read all opclasses in the system catalogs and return them in the
|
||||||
@ -3414,6 +3488,7 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
|
|||||||
tinfo->usename, "TYPE", NULL,
|
tinfo->usename, "TYPE", NULL,
|
||||||
q->data, delq->data, NULL, NULL, NULL);
|
q->data, delq->data, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
|
||||||
/* Dump Type Comments */
|
/* Dump Type Comments */
|
||||||
resetPQExpBuffer(q);
|
resetPQExpBuffer(q);
|
||||||
|
|
||||||
@ -3614,6 +3689,14 @@ dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs)
|
|||||||
NULL, lanacl, lanoid);
|
NULL, lanacl, lanoid);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dump Proc Lang Comments */
|
||||||
|
resetPQExpBuffer(defqry);
|
||||||
|
|
||||||
|
appendPQExpBuffer(defqry, "LANGUAGE %s", fmtId(lanname));
|
||||||
|
dumpComment(fout, defqry->data,
|
||||||
|
NULL, "",
|
||||||
|
lanoid, "pg_language", 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -4019,6 +4102,16 @@ dumpCasts(Archive *fout,
|
|||||||
"CAST", deps,
|
"CAST", deps,
|
||||||
defqry->data, delqry->data,
|
defqry->data, delqry->data,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* Dump Cast Comments */
|
||||||
|
resetPQExpBuffer(defqry);
|
||||||
|
appendPQExpBuffer(defqry, "CAST (%s AS %s)",
|
||||||
|
getFormattedTypeName(castsource, zeroAsNone),
|
||||||
|
getFormattedTypeName(casttarget, zeroAsNone));
|
||||||
|
dumpComment(fout, defqry->data,
|
||||||
|
NULL, "",
|
||||||
|
castoid, "pg_cast", 0, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -4490,7 +4583,8 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
opcintype = PQgetvalue(res, 0, i_opcintype);
|
opcintype = PQgetvalue(res, 0, i_opcintype);
|
||||||
opckeytype = PQgetvalue(res, 0, i_opckeytype);
|
opckeytype = PQgetvalue(res, 0, i_opckeytype);
|
||||||
opcdefault = PQgetvalue(res, 0, i_opcdefault);
|
opcdefault = PQgetvalue(res, 0, i_opcdefault);
|
||||||
amname = PQgetvalue(res, 0, i_amname);
|
/* amname will still be needed after we PQclear res */
|
||||||
|
amname = strdup(PQgetvalue(res, 0, i_amname));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DROP must be fully qualified in case same name appears in
|
* DROP must be fully qualified in case same name appears in
|
||||||
@ -4617,11 +4711,145 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
|
|||||||
q->data, delq->data,
|
q->data, delq->data,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* Dump Operator Class Comments */
|
||||||
|
resetPQExpBuffer(q);
|
||||||
|
appendPQExpBuffer(q, "OPERATOR CLASS %s",
|
||||||
|
fmtId(opcinfo->opcname));
|
||||||
|
appendPQExpBuffer(q, " USING %s",
|
||||||
|
fmtId(amname));
|
||||||
|
dumpComment(fout, q->data,
|
||||||
|
NULL, opcinfo->usename,
|
||||||
|
opcinfo->oid, "pg_opclass", 0, NULL);
|
||||||
|
|
||||||
|
free(amname);
|
||||||
destroyPQExpBuffer(query);
|
destroyPQExpBuffer(query);
|
||||||
destroyPQExpBuffer(q);
|
destroyPQExpBuffer(q);
|
||||||
destroyPQExpBuffer(delq);
|
destroyPQExpBuffer(delq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dumpConversions
|
||||||
|
* writes out to fout the queries to create all the user-defined conversions
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dumpConversions(Archive *fout, ConvInfo convinfo[], int numConvs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < numConvs; i++)
|
||||||
|
{
|
||||||
|
/* Dump only conversions in dumpable namespaces */
|
||||||
|
if (!convinfo[i].connamespace->dump)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dumpOneConversion(fout, &convinfo[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dumpOneConversion
|
||||||
|
* write out a single conversion definition
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
dumpOneConversion(Archive *fout, ConvInfo *convinfo)
|
||||||
|
{
|
||||||
|
PQExpBuffer query = createPQExpBuffer();
|
||||||
|
PQExpBuffer q = createPQExpBuffer();
|
||||||
|
PQExpBuffer delq = createPQExpBuffer();
|
||||||
|
PQExpBuffer details = createPQExpBuffer();
|
||||||
|
PGresult *res;
|
||||||
|
int ntups;
|
||||||
|
int i_conname;
|
||||||
|
int i_conforencoding;
|
||||||
|
int i_contoencoding;
|
||||||
|
int i_conproc;
|
||||||
|
int i_condefault;
|
||||||
|
const char *conname;
|
||||||
|
const char *conforencoding;
|
||||||
|
const char *contoencoding;
|
||||||
|
const char *conproc;
|
||||||
|
bool condefault;
|
||||||
|
|
||||||
|
/* Make sure we are in proper schema */
|
||||||
|
selectSourceSchema(convinfo->connamespace->nspname);
|
||||||
|
|
||||||
|
/* Get conversion-specific details */
|
||||||
|
appendPQExpBuffer(query, "SELECT conname,
|
||||||
|
pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding,
|
||||||
|
pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding,
|
||||||
|
conproc, condefault
|
||||||
|
FROM pg_catalog.pg_conversion c
|
||||||
|
WHERE c.oid = '%s'::pg_catalog.oid",
|
||||||
|
convinfo->oid);
|
||||||
|
|
||||||
|
res = PQexec(g_conn, query->data);
|
||||||
|
if (!res ||
|
||||||
|
PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
|
{
|
||||||
|
write_msg(NULL, "query to obtain conversion failed: %s",
|
||||||
|
PQerrorMessage(g_conn));
|
||||||
|
exit_nicely();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expecting a single result only */
|
||||||
|
ntups = PQntuples(res);
|
||||||
|
if (ntups != 1)
|
||||||
|
{
|
||||||
|
write_msg(NULL, "Got %d rows instead of one from: %s",
|
||||||
|
ntups, query->data);
|
||||||
|
exit_nicely();
|
||||||
|
}
|
||||||
|
|
||||||
|
i_conname = PQfnumber(res, "conname");
|
||||||
|
i_conforencoding = PQfnumber(res, "conforencoding");
|
||||||
|
i_contoencoding = PQfnumber(res, "contoencoding");
|
||||||
|
i_conproc = PQfnumber(res, "conproc");
|
||||||
|
i_condefault = PQfnumber(res, "condefault");
|
||||||
|
|
||||||
|
conname = PQgetvalue(res, 0, i_conname);
|
||||||
|
conforencoding = PQgetvalue(res, 0, i_conforencoding);
|
||||||
|
contoencoding = PQgetvalue(res, 0, i_contoencoding);
|
||||||
|
conproc = PQgetvalue(res, 0, i_conproc);
|
||||||
|
condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DROP must be fully qualified in case same name appears in
|
||||||
|
* pg_catalog
|
||||||
|
*/
|
||||||
|
appendPQExpBuffer(delq, "DROP CONVERSION %s",
|
||||||
|
fmtId(convinfo->connamespace->nspname));
|
||||||
|
appendPQExpBuffer(delq, ".%s;\n",
|
||||||
|
fmtId(convinfo->conname));
|
||||||
|
|
||||||
|
appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
|
||||||
|
(condefault) ? "DEFAULT " : "",
|
||||||
|
fmtId(convinfo->conname));
|
||||||
|
appendStringLiteral(q, conforencoding, true);
|
||||||
|
appendPQExpBuffer(q, " TO ");
|
||||||
|
appendStringLiteral(q, contoencoding, true);
|
||||||
|
/* regproc is automatically quoted in 7.3 and above */
|
||||||
|
appendPQExpBuffer(q, " FROM %s;\n", conproc);
|
||||||
|
|
||||||
|
ArchiveEntry(fout, convinfo->oid, convinfo->conname,
|
||||||
|
convinfo->connamespace->nspname, convinfo->usename,
|
||||||
|
"CONVERSION", NULL,
|
||||||
|
q->data, delq->data,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* Dump Conversion Comments */
|
||||||
|
resetPQExpBuffer(q);
|
||||||
|
appendPQExpBuffer(q, "CONVERSION %s", fmtId(convinfo->conname));
|
||||||
|
dumpComment(fout, q->data,
|
||||||
|
convinfo->connamespace->nspname, convinfo->usename,
|
||||||
|
convinfo->oid, "pg_conversion", 0, NULL);
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
destroyPQExpBuffer(query);
|
||||||
|
destroyPQExpBuffer(q);
|
||||||
|
destroyPQExpBuffer(delq);
|
||||||
|
destroyPQExpBuffer(details);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dumpAggs
|
* dumpAggs
|
||||||
@ -6573,8 +6801,10 @@ dumpRules(Archive *fout, TableInfo *tblinfo, int numTables)
|
|||||||
/* Dump rule comments */
|
/* Dump rule comments */
|
||||||
|
|
||||||
resetPQExpBuffer(query);
|
resetPQExpBuffer(query);
|
||||||
appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename)));
|
appendPQExpBuffer(query, "RULE %s",
|
||||||
appendPQExpBuffer(query, " ON %s", fmtId(tbinfo->relname));
|
fmtId(PQgetvalue(res, i, i_rulename)));
|
||||||
|
appendPQExpBuffer(query, " ON %s",
|
||||||
|
fmtId(tbinfo->relname));
|
||||||
dumpComment(fout, query->data,
|
dumpComment(fout, query->data,
|
||||||
tbinfo->relnamespace->nspname,
|
tbinfo->relnamespace->nspname,
|
||||||
tbinfo->usename,
|
tbinfo->usename,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: pg_dump.h,v 1.104 2003/08/08 04:52:21 momjian Exp $
|
* $Id: pg_dump.h,v 1.105 2003/11/21 22:32:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -95,6 +95,14 @@ typedef struct _opclassInfo
|
|||||||
char *usename;
|
char *usename;
|
||||||
} OpclassInfo;
|
} OpclassInfo;
|
||||||
|
|
||||||
|
typedef struct _convInfo
|
||||||
|
{
|
||||||
|
char *oid;
|
||||||
|
char *conname;
|
||||||
|
NamespaceInfo *connamespace; /* link to containing namespace */
|
||||||
|
char *usename;
|
||||||
|
} ConvInfo;
|
||||||
|
|
||||||
typedef struct _tableInfo
|
typedef struct _tableInfo
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -213,6 +221,7 @@ extern FuncInfo *getFuncs(int *numFuncs);
|
|||||||
extern AggInfo *getAggregates(int *numAggregates);
|
extern AggInfo *getAggregates(int *numAggregates);
|
||||||
extern OprInfo *getOperators(int *numOperators);
|
extern OprInfo *getOperators(int *numOperators);
|
||||||
extern OpclassInfo *getOpclasses(int *numOpclasses);
|
extern OpclassInfo *getOpclasses(int *numOpclasses);
|
||||||
|
extern ConvInfo *getConversions(int *numConversions);
|
||||||
extern TableInfo *getTables(int *numTables);
|
extern TableInfo *getTables(int *numTables);
|
||||||
extern InhInfo *getInherits(int *numInherits);
|
extern InhInfo *getInherits(int *numInherits);
|
||||||
|
|
||||||
@ -230,6 +239,8 @@ extern void dumpAggs(Archive *fout, AggInfo agginfo[], int numAggregates);
|
|||||||
extern void dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators);
|
extern void dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators);
|
||||||
extern void dumpOpclasses(Archive *fout,
|
extern void dumpOpclasses(Archive *fout,
|
||||||
OpclassInfo *opcinfo, int numOpclasses);
|
OpclassInfo *opcinfo, int numOpclasses);
|
||||||
|
extern void dumpConversions(Archive *fout,
|
||||||
|
ConvInfo *coninfo, int numConversions);
|
||||||
extern void dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
|
extern void dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
|
||||||
const bool aclsSkip,
|
const bool aclsSkip,
|
||||||
const bool schemaOnly, const bool dataOnly);
|
const bool schemaOnly, const bool dataOnly);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.29 2003/08/04 23:59:40 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.30 2003/11/21 22:32:49 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "large_obj.h"
|
#include "large_obj.h"
|
||||||
@ -165,9 +165,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* insert description if given */
|
/* insert description if given */
|
||||||
/* XXX don't try to hack pg_description if not superuser */
|
if (comment_arg)
|
||||||
/* XXX ought to replace this with some kind of COMMENT command */
|
|
||||||
if (comment_arg && is_superuser())
|
|
||||||
{
|
{
|
||||||
char *cmdbuf;
|
char *cmdbuf;
|
||||||
char *bufptr;
|
char *bufptr;
|
||||||
@ -177,9 +175,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
|
|||||||
if (!cmdbuf)
|
if (!cmdbuf)
|
||||||
return fail_lo_xact("\\lo_import", own_transaction);
|
return fail_lo_xact("\\lo_import", own_transaction);
|
||||||
sprintf(cmdbuf,
|
sprintf(cmdbuf,
|
||||||
"INSERT INTO pg_catalog.pg_description VALUES ('%u', "
|
"COMMENT ON LARGE OBJECT %u IS '",
|
||||||
"'pg_catalog.pg_largeobject'::regclass, "
|
|
||||||
"0, '",
|
|
||||||
loid);
|
loid);
|
||||||
bufptr = cmdbuf + strlen(cmdbuf);
|
bufptr = cmdbuf + strlen(cmdbuf);
|
||||||
for (i = 0; i < slen; i++)
|
for (i = 0; i < slen; i++)
|
||||||
@ -188,7 +184,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
|
|||||||
*bufptr++ = '\\';
|
*bufptr++ = '\\';
|
||||||
*bufptr++ = comment_arg[i];
|
*bufptr++ = comment_arg[i];
|
||||||
}
|
}
|
||||||
strcpy(bufptr, "')");
|
strcpy(bufptr, "'");
|
||||||
|
|
||||||
if (!(res = PSQLexec(cmdbuf, false)))
|
if (!(res = PSQLexec(cmdbuf, false)))
|
||||||
{
|
{
|
||||||
@ -219,10 +215,8 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
|
|||||||
bool
|
bool
|
||||||
do_lo_unlink(const char *loid_arg)
|
do_lo_unlink(const char *loid_arg)
|
||||||
{
|
{
|
||||||
PGresult *res;
|
|
||||||
int status;
|
int status;
|
||||||
Oid loid = atooid(loid_arg);
|
Oid loid = atooid(loid_arg);
|
||||||
char buf[256];
|
|
||||||
bool own_transaction;
|
bool own_transaction;
|
||||||
|
|
||||||
if (!start_lo_xact("\\lo_unlink", &own_transaction))
|
if (!start_lo_xact("\\lo_unlink", &own_transaction))
|
||||||
@ -235,20 +229,6 @@ do_lo_unlink(const char *loid_arg)
|
|||||||
return fail_lo_xact("\\lo_unlink", own_transaction);
|
return fail_lo_xact("\\lo_unlink", own_transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove the comment as well */
|
|
||||||
/* XXX don't try to hack pg_description if not superuser */
|
|
||||||
/* XXX ought to replace this with some kind of COMMENT command */
|
|
||||||
if (is_superuser())
|
|
||||||
{
|
|
||||||
snprintf(buf, sizeof(buf),
|
|
||||||
"DELETE FROM pg_catalog.pg_description WHERE objoid = '%u' "
|
|
||||||
"AND classoid = 'pg_catalog.pg_largeobject'::regclass",
|
|
||||||
loid);
|
|
||||||
if (!(res = PSQLexec(buf, false)))
|
|
||||||
return fail_lo_xact("\\lo_unlink", own_transaction);
|
|
||||||
PQclear(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!finish_lo_xact("\\lo_unlink", own_transaction))
|
if (!finish_lo_xact("\\lo_unlink", own_transaction))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parsenodes.h,v 1.248 2003/09/17 04:25:29 ishii Exp $
|
* $Id: parsenodes.h,v 1.249 2003/11/21 22:32:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -686,6 +686,7 @@ typedef enum ObjectType
|
|||||||
OBJECT_GROUP,
|
OBJECT_GROUP,
|
||||||
OBJECT_INDEX,
|
OBJECT_INDEX,
|
||||||
OBJECT_LANGUAGE,
|
OBJECT_LANGUAGE,
|
||||||
|
OBJECT_LARGEOBJECT,
|
||||||
OBJECT_OPCLASS,
|
OBJECT_OPCLASS,
|
||||||
OBJECT_OPERATOR,
|
OBJECT_OPERATOR,
|
||||||
OBJECT_RULE,
|
OBJECT_RULE,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: acl.h,v 1.63 2003/10/29 22:20:54 tgl Exp $
|
* $Id: acl.h,v 1.64 2003/11/21 22:32:49 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* An ACL array is simply an array of AclItems, representing the union
|
* An ACL array is simply an array of AclItems, representing the union
|
||||||
@ -245,5 +245,6 @@ extern bool pg_proc_ownercheck(Oid proc_oid, AclId userid);
|
|||||||
extern bool pg_namespace_ownercheck(Oid nsp_oid, AclId userid);
|
extern bool pg_namespace_ownercheck(Oid nsp_oid, AclId userid);
|
||||||
extern bool pg_opclass_ownercheck(Oid opc_oid, AclId userid);
|
extern bool pg_opclass_ownercheck(Oid opc_oid, AclId userid);
|
||||||
extern bool pg_database_ownercheck(Oid db_oid, AclId userid);
|
extern bool pg_database_ownercheck(Oid db_oid, AclId userid);
|
||||||
|
extern bool pg_conversion_ownercheck(Oid conv_oid, AclId userid);
|
||||||
|
|
||||||
#endif /* ACL_H */
|
#endif /* ACL_H */
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
-- add attribute
|
-- add attribute
|
||||||
--
|
--
|
||||||
CREATE TABLE tmp (initial int4);
|
CREATE TABLE tmp (initial int4);
|
||||||
|
COMMENT ON TABLE tmp_wrong IS 'table comment';
|
||||||
|
ERROR: relation "tmp_wrong" does not exist
|
||||||
|
COMMENT ON TABLE tmp IS 'table comment';
|
||||||
|
COMMENT ON TABLE tmp IS NULL;
|
||||||
ALTER TABLE tmp ADD COLUMN a int4;
|
ALTER TABLE tmp ADD COLUMN a int4;
|
||||||
ALTER TABLE tmp ADD COLUMN b name;
|
ALTER TABLE tmp ADD COLUMN b name;
|
||||||
ALTER TABLE tmp ADD COLUMN c text;
|
ALTER TABLE tmp ADD COLUMN c text;
|
||||||
|
@ -18,6 +18,11 @@ CREATE DEFAULT CONVERSION public.mydef FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_
|
|||||||
--
|
--
|
||||||
CREATE DEFAULT CONVERSION public.mydef2 FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_to_utf8;
|
CREATE DEFAULT CONVERSION public.mydef2 FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_to_utf8;
|
||||||
ERROR: default conversion for LATIN1 to UNICODE already exists
|
ERROR: default conversion for LATIN1 to UNICODE already exists
|
||||||
|
-- test comments
|
||||||
|
COMMENT ON CONVERSION myconv_bad IS 'foo';
|
||||||
|
ERROR: conversion "myconv_bad" does not exist
|
||||||
|
COMMENT ON CONVERSION myconv IS 'bar';
|
||||||
|
COMMENT ON CONVERSION myconv IS NULL;
|
||||||
--
|
--
|
||||||
-- drop user defined conversion
|
-- drop user defined conversion
|
||||||
--
|
--
|
||||||
|
@ -7,6 +7,11 @@ CREATE AGGREGATE newavg (
|
|||||||
finalfunc = numeric_avg,
|
finalfunc = numeric_avg,
|
||||||
initcond1 = '{0,0,0}'
|
initcond1 = '{0,0,0}'
|
||||||
);
|
);
|
||||||
|
-- test comments
|
||||||
|
COMMENT ON AGGREGATE newavg_wrong (int4) IS 'an agg comment';
|
||||||
|
ERROR: aggregate newavg_wrong(integer) does not exist
|
||||||
|
COMMENT ON AGGREGATE newavg (int4) IS 'an agg comment';
|
||||||
|
COMMENT ON AGGREGATE newavg (int4) IS NULL;
|
||||||
-- without finalfunc; test obsolete spellings 'sfunc1' etc
|
-- without finalfunc; test obsolete spellings 'sfunc1' etc
|
||||||
CREATE AGGREGATE newsum (
|
CREATE AGGREGATE newsum (
|
||||||
sfunc1 = int4pl, basetype = int4, stype1 = int4,
|
sfunc1 = int4pl, basetype = int4, stype1 = int4,
|
||||||
@ -17,3 +22,7 @@ CREATE AGGREGATE newcnt (
|
|||||||
sfunc = int4inc, basetype = 'any', stype = int4,
|
sfunc = int4inc, basetype = 'any', stype = int4,
|
||||||
initcond = '0'
|
initcond = '0'
|
||||||
);
|
);
|
||||||
|
COMMENT ON AGGREGATE nosuchagg (*) IS 'should fail';
|
||||||
|
ERROR: aggregate nosuchagg(*) does not exist
|
||||||
|
COMMENT ON AGGREGATE newcnt (*) IS 'an any agg comment';
|
||||||
|
COMMENT ON AGGREGATE newcnt (*) IS NULL;
|
||||||
|
@ -18,6 +18,11 @@ CREATE INDEX tenk2_hundred ON tenk2 USING btree(hundred int4_ops);
|
|||||||
CREATE INDEX rix ON road USING btree (name text_ops);
|
CREATE INDEX rix ON road USING btree (name text_ops);
|
||||||
CREATE INDEX iix ON ihighway USING btree (name text_ops);
|
CREATE INDEX iix ON ihighway USING btree (name text_ops);
|
||||||
CREATE INDEX six ON shighway USING btree (name text_ops);
|
CREATE INDEX six ON shighway USING btree (name text_ops);
|
||||||
|
-- test comments
|
||||||
|
COMMENT ON INDEX six_wrong IS 'bad index';
|
||||||
|
ERROR: relation "six_wrong" does not exist
|
||||||
|
COMMENT ON INDEX six IS 'good index';
|
||||||
|
COMMENT ON INDEX six IS NULL;
|
||||||
--
|
--
|
||||||
-- BTREE ascending/descending cases
|
-- BTREE ascending/descending cases
|
||||||
--
|
--
|
||||||
|
@ -26,3 +26,8 @@ CREATE OPERATOR #%# (
|
|||||||
leftarg = int4, -- right unary
|
leftarg = int4, -- right unary
|
||||||
procedure = int4fac
|
procedure = int4fac
|
||||||
);
|
);
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
|
||||||
|
ERROR: operator does not exist: integer ######
|
||||||
|
COMMENT ON OPERATOR #%# (int4, NONE) IS 'right unary';
|
||||||
|
COMMENT ON OPERATOR #%# (int4, NONE) IS NULL;
|
||||||
|
@ -71,6 +71,11 @@ SELECT * FROM get_default_test();
|
|||||||
zippo | 42
|
zippo | 42
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON TYPE bad IS 'bad comment';
|
||||||
|
ERROR: type "bad" does not exist
|
||||||
|
COMMENT ON TYPE default_test_row IS 'good comment';
|
||||||
|
COMMENT ON TYPE default_test_row IS NULL;
|
||||||
DROP TYPE default_test_row CASCADE;
|
DROP TYPE default_test_row CASCADE;
|
||||||
NOTICE: drop cascades to function get_default_test()
|
NOTICE: drop cascades to function get_default_test()
|
||||||
DROP TABLE default_test;
|
DROP TABLE default_test;
|
||||||
|
@ -15,6 +15,11 @@ CREATE VIEW iexit AS
|
|||||||
CREATE VIEW toyemp AS
|
CREATE VIEW toyemp AS
|
||||||
SELECT name, age, location, 12*salary AS annualsal
|
SELECT name, age, location, 12*salary AS annualsal
|
||||||
FROM emp;
|
FROM emp;
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON VIEW noview IS 'no view';
|
||||||
|
ERROR: relation "noview" does not exist
|
||||||
|
COMMENT ON VIEW toyemp IS 'is a view';
|
||||||
|
COMMENT ON VIEW toyemp IS NULL;
|
||||||
--
|
--
|
||||||
-- CREATE OR REPLACE VIEW
|
-- CREATE OR REPLACE VIEW
|
||||||
--
|
--
|
||||||
|
@ -64,6 +64,11 @@ CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1,
|
|||||||
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
|
||||||
CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, CONSTRAINT constrname FOREIGN KEY(ftest1, ftest2)
|
CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, CONSTRAINT constrname FOREIGN KEY(ftest1, ftest2)
|
||||||
REFERENCES PKTABLE MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL);
|
REFERENCES PKTABLE MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL);
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON CONSTRAINT constrname_wrong ON FKTABLE IS 'fk constraint comment';
|
||||||
|
ERROR: constraint "constrname_wrong" for table "fktable" does not exist
|
||||||
|
COMMENT ON CONSTRAINT constrname ON FKTABLE IS 'fk constraint comment';
|
||||||
|
COMMENT ON CONSTRAINT constrname ON FKTABLE IS NULL;
|
||||||
-- Insert test data into PKTABLE
|
-- Insert test data into PKTABLE
|
||||||
INSERT INTO PKTABLE VALUES (1, 2, 'Test1');
|
INSERT INTO PKTABLE VALUES (1, 2, 'Test1');
|
||||||
INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2');
|
INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2');
|
||||||
|
@ -264,6 +264,11 @@ begin
|
|||||||
return 0;
|
return 0;
|
||||||
end;
|
end;
|
||||||
' language 'plpgsql';
|
' language 'plpgsql';
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON FUNCTION tg_hub_adjustslots_wrong(bpchar, integer, integer) IS 'function with args';
|
||||||
|
ERROR: function tg_hub_adjustslots_wrong(character, integer, integer) does not exist
|
||||||
|
COMMENT ON FUNCTION tg_hub_adjustslots(bpchar, integer, integer) IS 'function with args';
|
||||||
|
COMMENT ON FUNCTION tg_hub_adjustslots(bpchar, integer, integer) IS NULL;
|
||||||
-- ************************************************************
|
-- ************************************************************
|
||||||
-- * BEFORE INSERT or UPDATE on HSlot
|
-- * BEFORE INSERT or UPDATE on HSlot
|
||||||
-- * - prevent from manual manipulation
|
-- * - prevent from manual manipulation
|
||||||
|
@ -17,6 +17,11 @@ create rule rtest_v1_upd as on update to rtest_v1 do instead
|
|||||||
where a = old.a;
|
where a = old.a;
|
||||||
create rule rtest_v1_del as on delete to rtest_v1 do instead
|
create rule rtest_v1_del as on delete to rtest_v1 do instead
|
||||||
delete from rtest_t1 where a = old.a;
|
delete from rtest_t1 where a = old.a;
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON RULE rtest_v1_bad ON rtest_v1 IS 'bad rule';
|
||||||
|
ERROR: rule "rtest_v1_bad" for relation "rtest_v1" does not exist
|
||||||
|
COMMENT ON RULE rtest_v1_del ON rtest_v1 IS 'delete rule';
|
||||||
|
COMMENT ON RULE rtest_v1_del ON rtest_v1 IS NULL;
|
||||||
--
|
--
|
||||||
-- Tables and rules for the constraint update/delete test
|
-- Tables and rules for the constraint update/delete test
|
||||||
--
|
--
|
||||||
|
@ -71,3 +71,8 @@ SELECT nextval('sequence_test2');
|
|||||||
5
|
5
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON SEQUENCE asdf IS 'won''t work';
|
||||||
|
ERROR: relation "asdf" does not exist
|
||||||
|
COMMENT ON SEQUENCE sequence_test2 IS 'will work';
|
||||||
|
COMMENT ON SEQUENCE sequence_test2 IS NULL;
|
||||||
|
@ -37,6 +37,11 @@ create trigger check_fkeys2_pkey_exist
|
|||||||
for each row
|
for each row
|
||||||
execute procedure
|
execute procedure
|
||||||
check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2');
|
check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2');
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON TRIGGER check_fkeys2_pkey_bad ON fkeys2 IS 'wrong';
|
||||||
|
ERROR: trigger "check_fkeys2_pkey_bad" for table "fkeys2" does not exist
|
||||||
|
COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS 'right';
|
||||||
|
COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS NULL;
|
||||||
--
|
--
|
||||||
-- For pkeys:
|
-- For pkeys:
|
||||||
-- ON DELETE/UPDATE (pkey1, pkey2) CASCADE:
|
-- ON DELETE/UPDATE (pkey1, pkey2) CASCADE:
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
|
|
||||||
CREATE TABLE tmp (initial int4);
|
CREATE TABLE tmp (initial int4);
|
||||||
|
|
||||||
|
COMMENT ON TABLE tmp_wrong IS 'table comment';
|
||||||
|
COMMENT ON TABLE tmp IS 'table comment';
|
||||||
|
COMMENT ON TABLE tmp IS NULL;
|
||||||
|
|
||||||
ALTER TABLE tmp ADD COLUMN a int4;
|
ALTER TABLE tmp ADD COLUMN a int4;
|
||||||
|
|
||||||
ALTER TABLE tmp ADD COLUMN b name;
|
ALTER TABLE tmp ADD COLUMN b name;
|
||||||
|
@ -16,6 +16,10 @@ CREATE DEFAULT CONVERSION public.mydef FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_
|
|||||||
-- cannot make default conversion with same shcema/for_encoding/to_encoding
|
-- cannot make default conversion with same shcema/for_encoding/to_encoding
|
||||||
--
|
--
|
||||||
CREATE DEFAULT CONVERSION public.mydef2 FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_to_utf8;
|
CREATE DEFAULT CONVERSION public.mydef2 FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_to_utf8;
|
||||||
|
-- test comments
|
||||||
|
COMMENT ON CONVERSION myconv_bad IS 'foo';
|
||||||
|
COMMENT ON CONVERSION myconv IS 'bar';
|
||||||
|
COMMENT ON CONVERSION myconv IS NULL;
|
||||||
--
|
--
|
||||||
-- drop user defined conversion
|
-- drop user defined conversion
|
||||||
--
|
--
|
||||||
|
@ -9,6 +9,11 @@ CREATE AGGREGATE newavg (
|
|||||||
initcond1 = '{0,0,0}'
|
initcond1 = '{0,0,0}'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- test comments
|
||||||
|
COMMENT ON AGGREGATE newavg_wrong (int4) IS 'an agg comment';
|
||||||
|
COMMENT ON AGGREGATE newavg (int4) IS 'an agg comment';
|
||||||
|
COMMENT ON AGGREGATE newavg (int4) IS NULL;
|
||||||
|
|
||||||
-- without finalfunc; test obsolete spellings 'sfunc1' etc
|
-- without finalfunc; test obsolete spellings 'sfunc1' etc
|
||||||
CREATE AGGREGATE newsum (
|
CREATE AGGREGATE newsum (
|
||||||
sfunc1 = int4pl, basetype = int4, stype1 = int4,
|
sfunc1 = int4pl, basetype = int4, stype1 = int4,
|
||||||
@ -21,3 +26,6 @@ CREATE AGGREGATE newcnt (
|
|||||||
initcond = '0'
|
initcond = '0'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
COMMENT ON AGGREGATE nosuchagg (*) IS 'should fail';
|
||||||
|
COMMENT ON AGGREGATE newcnt (*) IS 'an any agg comment';
|
||||||
|
COMMENT ON AGGREGATE newcnt (*) IS NULL;
|
||||||
|
@ -32,6 +32,11 @@ CREATE INDEX iix ON ihighway USING btree (name text_ops);
|
|||||||
|
|
||||||
CREATE INDEX six ON shighway USING btree (name text_ops);
|
CREATE INDEX six ON shighway USING btree (name text_ops);
|
||||||
|
|
||||||
|
-- test comments
|
||||||
|
COMMENT ON INDEX six_wrong IS 'bad index';
|
||||||
|
COMMENT ON INDEX six IS 'good index';
|
||||||
|
COMMENT ON INDEX six IS NULL;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- BTREE ascending/descending cases
|
-- BTREE ascending/descending cases
|
||||||
--
|
--
|
||||||
|
@ -32,3 +32,9 @@ CREATE OPERATOR #%# (
|
|||||||
procedure = int4fac
|
procedure = int4fac
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary';
|
||||||
|
COMMENT ON OPERATOR #%# (int4, NONE) IS 'right unary';
|
||||||
|
COMMENT ON OPERATOR #%# (int4, NONE) IS NULL;
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,6 +69,11 @@ CREATE FUNCTION get_default_test() RETURNS SETOF default_test_row AS '
|
|||||||
|
|
||||||
SELECT * FROM get_default_test();
|
SELECT * FROM get_default_test();
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON TYPE bad IS 'bad comment';
|
||||||
|
COMMENT ON TYPE default_test_row IS 'good comment';
|
||||||
|
COMMENT ON TYPE default_test_row IS NULL;
|
||||||
|
|
||||||
DROP TYPE default_test_row CASCADE;
|
DROP TYPE default_test_row CASCADE;
|
||||||
|
|
||||||
DROP TABLE default_test;
|
DROP TABLE default_test;
|
||||||
|
@ -19,6 +19,11 @@ CREATE VIEW toyemp AS
|
|||||||
SELECT name, age, location, 12*salary AS annualsal
|
SELECT name, age, location, 12*salary AS annualsal
|
||||||
FROM emp;
|
FROM emp;
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON VIEW noview IS 'no view';
|
||||||
|
COMMENT ON VIEW toyemp IS 'is a view';
|
||||||
|
COMMENT ON VIEW toyemp IS NULL;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- CREATE OR REPLACE VIEW
|
-- CREATE OR REPLACE VIEW
|
||||||
--
|
--
|
||||||
|
@ -50,6 +50,11 @@ CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1,
|
|||||||
CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, CONSTRAINT constrname FOREIGN KEY(ftest1, ftest2)
|
CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, CONSTRAINT constrname FOREIGN KEY(ftest1, ftest2)
|
||||||
REFERENCES PKTABLE MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL);
|
REFERENCES PKTABLE MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL);
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON CONSTRAINT constrname_wrong ON FKTABLE IS 'fk constraint comment';
|
||||||
|
COMMENT ON CONSTRAINT constrname ON FKTABLE IS 'fk constraint comment';
|
||||||
|
COMMENT ON CONSTRAINT constrname ON FKTABLE IS NULL;
|
||||||
|
|
||||||
-- Insert test data into PKTABLE
|
-- Insert test data into PKTABLE
|
||||||
INSERT INTO PKTABLE VALUES (1, 2, 'Test1');
|
INSERT INTO PKTABLE VALUES (1, 2, 'Test1');
|
||||||
INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2');
|
INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2');
|
||||||
|
@ -326,6 +326,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
' language 'plpgsql';
|
' language 'plpgsql';
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON FUNCTION tg_hub_adjustslots_wrong(bpchar, integer, integer) IS 'function with args';
|
||||||
|
COMMENT ON FUNCTION tg_hub_adjustslots(bpchar, integer, integer) IS 'function with args';
|
||||||
|
COMMENT ON FUNCTION tg_hub_adjustslots(bpchar, integer, integer) IS NULL;
|
||||||
|
|
||||||
-- ************************************************************
|
-- ************************************************************
|
||||||
-- * BEFORE INSERT or UPDATE on HSlot
|
-- * BEFORE INSERT or UPDATE on HSlot
|
||||||
|
@ -19,7 +19,10 @@ create rule rtest_v1_upd as on update to rtest_v1 do instead
|
|||||||
where a = old.a;
|
where a = old.a;
|
||||||
create rule rtest_v1_del as on delete to rtest_v1 do instead
|
create rule rtest_v1_del as on delete to rtest_v1 do instead
|
||||||
delete from rtest_t1 where a = old.a;
|
delete from rtest_t1 where a = old.a;
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON RULE rtest_v1_bad ON rtest_v1 IS 'bad rule';
|
||||||
|
COMMENT ON RULE rtest_v1_del ON rtest_v1 IS 'delete rule';
|
||||||
|
COMMENT ON RULE rtest_v1_del ON rtest_v1 IS NULL;
|
||||||
--
|
--
|
||||||
-- Tables and rules for the constraint update/delete test
|
-- Tables and rules for the constraint update/delete test
|
||||||
--
|
--
|
||||||
|
@ -37,3 +37,8 @@ SELECT nextval('sequence_test2');
|
|||||||
SELECT nextval('sequence_test2');
|
SELECT nextval('sequence_test2');
|
||||||
SELECT nextval('sequence_test2');
|
SELECT nextval('sequence_test2');
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON SEQUENCE asdf IS 'won''t work';
|
||||||
|
COMMENT ON SEQUENCE sequence_test2 IS 'will work';
|
||||||
|
COMMENT ON SEQUENCE sequence_test2 IS NULL;
|
||||||
|
|
||||||
|
@ -44,6 +44,11 @@ create trigger check_fkeys2_pkey_exist
|
|||||||
execute procedure
|
execute procedure
|
||||||
check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2');
|
check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2');
|
||||||
|
|
||||||
|
-- Test comments
|
||||||
|
COMMENT ON TRIGGER check_fkeys2_pkey_bad ON fkeys2 IS 'wrong';
|
||||||
|
COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS 'right';
|
||||||
|
COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS NULL;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- For pkeys:
|
-- For pkeys:
|
||||||
-- ON DELETE/UPDATE (pkey1, pkey2) CASCADE:
|
-- ON DELETE/UPDATE (pkey1, pkey2) CASCADE:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user