Support column-level privileges, as required by SQL standard.

Stephen Frost, with help from KaiGai Kohei and others
This commit is contained in:
Tom Lane 2009-01-22 20:16:10 +00:00
parent bf136cf6e3
commit 3cb5d6580a
59 changed files with 2314 additions and 722 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.190 2009/01/22 17:27:54 petere Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.191 2009/01/22 20:15:59 tgl Exp $ -->
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
-->
@ -1028,6 +1028,16 @@
</entry>
</row>
<row>
<entry><structfield>attacl</structfield></entry>
<entry><type>aclitem[]</type></entry>
<entry></entry>
<entry>
Column-level access privileges, if any have been granted specifically
on this column
</entry>
</row>
</tbody>
</tgroup>
</table>
@ -4250,6 +4260,17 @@
<entry>The OID of the specific dependent object</entry>
</row>
<row>
<entry><structfield>objsubid</structfield></entry>
<entry><type>int4</type></entry>
<entry></entry>
<entry>
For a table column, this is the column number (the
<structfield>objid</> and <structfield>classid</> refer to the
table itself). For all other object types, this column is zero
</entry>
</row>
<row>
<entry><structfield>refclassid</structfield></entry>
<entry><type>oid</type></entry>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.73 2008/12/19 16:25:16 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.74 2009/01/22 20:15:59 tgl Exp $
PostgreSQL documentation
-->
@ -26,6 +26,11 @@ GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( <replaceable class="PARAMETER">column</replaceable> [, ...] )
[,...] | ALL [ PRIVILEGES ] ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) }
ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { { USAGE | SELECT | UPDATE }
[,...] | ALL [ PRIVILEGES ] }
ON SEQUENCE <replaceable class="PARAMETER">sequencename</replaceable> [, ...]
@ -68,7 +73,7 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
<para>
The <command>GRANT</command> command has two basic variants: one
that grants privileges on a database object (table, view, sequence,
that grants privileges on a database object (table, column, view, sequence,
database, foreign-data wrapper, foreign server, function,
procedural language, schema, or tablespace), and one that grants
membership in a role. These variants are similar in many ways, but
@ -125,7 +130,8 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
<para>
Depending on the type of object, the initial default privileges might
include granting some privileges to <literal>PUBLIC</literal>.
The default is no public access for tables, schemas, and tablespaces;
The default is no public access for tables, columns, schemas, and
tablespaces;
<literal>CONNECT</> privilege and <literal>TEMP</> table creation privilege
for databases;
<literal>EXECUTE</> privilege for functions; and
@ -145,7 +151,8 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
<listitem>
<para>
Allows <xref linkend="sql-select" endterm="sql-select-title"> from
any column of the specified table, view, or sequence.
any column, or the specific columns listed, of the specified table,
view, or sequence.
Also allows the use of
<xref linkend="sql-copy" endterm="sql-copy-title"> TO.
This privilege is also needed to reference existing column values in
@ -162,7 +169,9 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
<listitem>
<para>
Allows <xref linkend="sql-insert" endterm="sql-insert-title"> of a new
row into the specified table.
row into the specified table. If specific columns are listed,
only those columns may be assigned to in the <command>INSERT</>
command (other columns will therefore receive default values).
Also allows <xref linkend="sql-copy" endterm="sql-copy-title"> FROM.
</para>
</listitem>
@ -173,14 +182,14 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
<listitem>
<para>
Allows <xref linkend="sql-update" endterm="sql-update-title"> of any
column of the specified table.
column, or the specific columns listed, of the specified table.
(In practice, any nontrivial <command>UPDATE</> command will require
<literal>SELECT</> privilege as well, since it must reference table
columns to determine which rows to update, and/or to compute new
values for columns.)
<literal>SELECT ... FOR UPDATE</literal>
and <literal>SELECT ... FOR SHARE</literal>
also require this privilege, in addition to the
also require this privilege on at least one column, in addition to the
<literal>SELECT</literal> privilege. For sequences, this
privilege allows the use of the <function>nextval</function> and
<function>setval</function> functions.
@ -217,7 +226,8 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
<para>
To create a foreign key constraint, it is
necessary to have this privilege on both the referencing and
referenced tables.
referenced columns. The privilege may be granted for all columns
of a table, or just specific columns.
</para>
</listitem>
</varlistentry>
@ -373,6 +383,14 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
to revoke access privileges.
</para>
<para>
A user may perform <command>SELECT</>, <command>INSERT</>, etc. on a
column if he holds that privilege for either the specific column or
its whole table. Granting the privilege at the table level and then
revoking it for one column will not do what you might wish: the
table-level grant is unaffected by a column-level operation.
</para>
<para>
When a non-owner of an object attempts to <command>GRANT</> privileges
on the object, the command will fail outright if the user has no
@ -428,33 +446,27 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
</para>
<para>
Granting permission on a table does not automatically extend
permissions to any sequences used by the table, including
sequences tied to <type>SERIAL</> columns. Permissions on
sequence must be set separately.
Granting permission on a table does not automatically extend
permissions to any sequences used by the table, including
sequences tied to <type>SERIAL</> columns. Permissions on
sequences must be set separately.
</para>
<para>
Currently, <productname>PostgreSQL</productname> does not support
granting or revoking privileges for individual columns of a table.
One possible workaround is to create a view having just the desired
columns and then grant privileges to that view.
</para>
<para>
Use <xref linkend="app-psql">'s <command>\z</command> command
to obtain information about existing privileges, for example:
Use <xref linkend="app-psql">'s <command>\dp</command> command
to obtain information about existing privileges for tables and
columns. For example:
<programlisting>
=&gt; \z mytable
Access privileges
Schema | Name | Type | Access privileges
--------+---------+-------+-----------------------
public | mytable | table | miriam=arwdDxt/miriam
: =r/miriam
: admin=arw/miriam
=&gt; \dp mytable
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+---------+-------+-----------------------+--------------------------
public | mytable | table | miriam=arwdDxt/miriam | col1:
: =r/miriam : miriam_rw=rw/miriam
: admin=arw/miriam
(1 row)
</programlisting>
The entries shown by <command>\z</command> are interpreted thus:
The entries shown by <command>\dp</command> are interpreted thus:
<programlisting>
rolename=xxxx -- privileges granted to a role
=xxxx -- privileges granted to PUBLIC
@ -471,7 +483,7 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
C -- CREATE
c -- CONNECT
T -- TEMPORARY
arwdDxt -- ALL PRIVILEGES (for tables)
arwdDxt -- ALL PRIVILEGES (for tables, varies for other objects)
* -- grant option for preceding privilege
/yyyy -- role that granted this privilege
@ -483,9 +495,15 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
<programlisting>
GRANT SELECT ON mytable TO PUBLIC;
GRANT SELECT, UPDATE, INSERT ON mytable TO admin;
GRANT SELECT (col1), UPDATE (col1) ON mytable TO miriam_rw;
</programlisting>
</para>
<para>
For non-table objects there are other <command>\d</> commands
that can display their privileges.
</para>
<para>
If the <quote>Access privileges</> column is empty for a given object,
it means the object has default privileges (that is, its privileges column
@ -495,7 +513,8 @@ GRANT SELECT, UPDATE, INSERT ON mytable TO admin;
<command>REVOKE</> on an object
will instantiate the default privileges (producing, for example,
<literal>{miriam=arwdDxt/miriam}</>) and then modify them per the
specified request.
specified request. Entries are shown in <quote>Column access
privileges</> only for columns with nondefault privileges.
</para>
<para>
@ -562,11 +581,6 @@ GRANT admins TO joe;
<quote>_SYSTEM</>, the owner cannot revoke these rights.
</para>
<para>
<productname>PostgreSQL</productname> does not support the SQL-standard
functionality of setting privileges for individual columns.
</para>
<para>
The SQL standard provides for a <literal>USAGE</literal> privilege
on other kinds of objects: character sets, collations,

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/insert.sgml,v 1.37 2008/11/14 10:22:47 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/insert.sgml,v 1.38 2009/01/22 20:15:59 tgl Exp $
PostgreSQL documentation
-->
@ -69,11 +69,14 @@ INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( <replaceable
<para>
You must have <literal>INSERT</literal> privilege on a table in
order to insert into it, and <literal>SELECT</> privilege on it to
use <literal>RETURNING</>. If you use the <replaceable
order to insert into it. If a column list is specified, you only
need <literal>INSERT</literal> privilege on the listed columns.
Use of the <literal>RETURNING</> clause requires <literal>SELECT</>
privilege on all columns mentioned in <literal>RETURNING</>.
If you use the <replaceable
class="PARAMETER">query</replaceable> clause to insert rows from a
query, you also need to have <literal>SELECT</literal> privilege on
any table used in the query.
query, you of course need to have <literal>SELECT</literal> privilege on
any table or column used in the query.
</para>
</refsect1>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.50 2008/12/19 16:25:16 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.51 2009/01/22 20:15:59 tgl Exp $
PostgreSQL documentation
-->
@ -28,6 +28,13 @@ REVOKE [ GRANT OPTION FOR ]
FROM { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | REFERENCES } ( <replaceable class="PARAMETER">column</replaceable> [, ...] )
[,...] | ALL [ PRIVILEGES ] ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) }
ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
FROM { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ { USAGE | SELECT | UPDATE }
[,...] | ALL [ PRIVILEGES ] }
@ -131,6 +138,11 @@ REVOKE [ ADMIN OPTION FOR ]
was also granted through other users.
</para>
<para>
When revoking privileges on a table, the corresponding column privileges
(if any) are automatically revoked on each column of the table, as well.
</para>
<para>
When revoking membership in a role, <literal>GRANT OPTION</> is instead
called <literal>ADMIN OPTION</>, but the behavior is similar.
@ -143,9 +155,11 @@ REVOKE [ ADMIN OPTION FOR ]
<title>Notes</title>
<para>
Use <xref linkend="app-psql">'s <command>\z</command> command to
display the privileges granted on existing objects. See <xref
linkend="sql-grant" endterm="sql-grant-title"> for information about the format.
Use <xref linkend="app-psql">'s <command>\dp</command> command to
display the privileges granted on existing tables and columns. See <xref
linkend="sql-grant" endterm="sql-grant-title"> for information about the
format. For non-table objects there are other <command>\d</> commands
that can display their privileges.
</para>
<para>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.117 2009/01/12 14:06:20 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/select.sgml,v 1.118 2009/01/22 20:15:59 tgl Exp $
PostgreSQL documentation
-->
@ -186,10 +186,11 @@ TABLE { [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] |
</para>
<para>
You must have <literal>SELECT</literal> privilege on a table to
read its values. The use of <literal>FOR UPDATE</literal> or
<literal>FOR SHARE</literal> requires
<literal>UPDATE</literal> privilege as well.
You must have <literal>SELECT</literal> privilege on each column used
in a <command>SELECT</> command. The use of <literal>FOR UPDATE</literal>
or <literal>FOR SHARE</literal> requires
<literal>UPDATE</literal> privilege as well (for at least one column
of each table so selected).
</para>
</refsect1>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.48 2008/11/16 17:34:28 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/update.sgml,v 1.49 2009/01/22 20:16:00 tgl Exp $
PostgreSQL documentation
-->
@ -66,9 +66,10 @@ UPDATE [ ONLY ] <replaceable class="PARAMETER">table</replaceable> [ [ AS ] <rep
</para>
<para>
You must have the <literal>UPDATE</literal> privilege on the table
to update it, as well as the <literal>SELECT</literal>
privilege to any table whose values are read in the
You must have the <literal>UPDATE</literal> privilege on the table,
or at least on the column(s) that are listed to be updated.
You must also have the <literal>SELECT</literal>
privilege on any column whose values are read in the
<replaceable class="parameter">expressions</replaceable> or
<replaceable class="parameter">condition</replaceable>.
</para>

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.124 2009/01/01 17:23:34 momjian Exp $
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.125 2009/01/22 20:16:00 tgl Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
@ -53,10 +53,14 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
* struct pointer alignment requirement, and hence we don't need to insert
* alignment padding between the struct and the array of attribute row
* pointers.
*
* Note: Only the fixed part of pg_attribute rows is included in tuple
* descriptors, so we only need ATTRIBUTE_FIXED_PART_SIZE space
* per attr. That might need alignment padding, however.
*/
attroffset = sizeof(struct tupleDesc) + natts * sizeof(Form_pg_attribute);
attroffset = MAXALIGN(attroffset);
stg = palloc(attroffset + natts * MAXALIGN(ATTRIBUTE_TUPLE_SIZE));
stg = palloc(attroffset + natts * MAXALIGN(ATTRIBUTE_FIXED_PART_SIZE));
desc = (TupleDesc) stg;
if (natts > 0)
@ -70,7 +74,7 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
for (i = 0; i < natts; i++)
{
attrs[i] = (Form_pg_attribute) stg;
stg += MAXALIGN(ATTRIBUTE_TUPLE_SIZE);
stg += MAXALIGN(ATTRIBUTE_FIXED_PART_SIZE);
}
}
else
@ -139,7 +143,7 @@ CreateTupleDescCopy(TupleDesc tupdesc)
for (i = 0; i < desc->natts; i++)
{
memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
desc->attrs[i]->attnotnull = false;
desc->attrs[i]->atthasdef = false;
}
@ -166,7 +170,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
for (i = 0; i < desc->natts; i++)
{
memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
}
if (constr)
@ -356,6 +360,7 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
return false;
if (attr1->attinhcount != attr2->attinhcount)
return false;
/* attacl is ignored, since it's not even present... */
}
if (tupdesc1->constr != NULL)
@ -471,6 +476,7 @@ TupleDescInitEntry(TupleDesc desc,
att->attisdropped = false;
att->attislocal = true;
att->attinhcount = 0;
/* attacl is not set because it's not present in tupledescs */
tuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(oidtypeid),

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.248 2009/01/01 17:23:36 momjian Exp $
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.249 2009/01/22 20:16:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -633,7 +633,7 @@ boot_openrel(char *relname)
closerel(NULL);
elog(DEBUG4, "open relation %s, attrsize %d",
relname, (int) ATTRIBUTE_TUPLE_SIZE);
relname, (int) ATTRIBUTE_FIXED_PART_SIZE);
boot_reldesc = heap_openrv(makeRangeVar(NULL, relname, -1), NoLock);
numattr = boot_reldesc->rd_rel->relnatts;
@ -643,7 +643,7 @@ boot_openrel(char *relname)
attrtypes[i] = AllocateAttribute();
memmove((char *) attrtypes[i],
(char *) boot_reldesc->rd_att->attrs[i],
ATTRIBUTE_TUPLE_SIZE);
ATTRIBUTE_FIXED_PART_SIZE);
{
Form_pg_attribute at = attrtypes[i];
@ -709,7 +709,7 @@ DefineAttr(char *name, char *type, int attnum)
if (attrtypes[attnum] == NULL)
attrtypes[attnum] = AllocateAttribute();
MemSet(attrtypes[attnum], 0, ATTRIBUTE_TUPLE_SIZE);
MemSet(attrtypes[attnum], 0, ATTRIBUTE_FIXED_PART_SIZE);
namestrcpy(&attrtypes[attnum]->attname, name);
elog(DEBUG4, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
@ -1017,16 +1017,19 @@ boot_get_type_io_data(Oid typid,
/* ----------------
* AllocateAttribute
*
* Note: bootstrap never sets any per-column ACLs, so we only need
* ATTRIBUTE_FIXED_PART_SIZE space per attribute.
* ----------------
*/
static Form_pg_attribute
AllocateAttribute(void)
{
Form_pg_attribute attribute = (Form_pg_attribute) malloc(ATTRIBUTE_TUPLE_SIZE);
Form_pg_attribute attribute = (Form_pg_attribute) malloc(ATTRIBUTE_FIXED_PART_SIZE);
if (!PointerIsValid(attribute))
elog(FATAL, "out of memory");
MemSet(attribute, 0, ATTRIBUTE_TUPLE_SIZE);
MemSet(attribute, 0, ATTRIBUTE_FIXED_PART_SIZE);
return attribute;
}

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.85 2009/01/01 17:23:36 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.86 2009/01/22 20:16:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -976,6 +976,13 @@ deleteOneObject(const ObjectAddress *object, Relation depRel)
systable_endscan(scan);
/*
* Delete shared dependency references related to this object. Again,
* if subId = 0, remove records for sub-objects too.
*/
deleteSharedDependencyRecordsFor(object->classId, object->objectId,
object->objectSubId);
/*
* Now delete the object itself, in an object-type-dependent way.
*/
@ -987,13 +994,6 @@ deleteOneObject(const ObjectAddress *object, Relation depRel)
*/
DeleteComments(object->objectId, object->classId, object->objectSubId);
/*
* Delete shared dependency references related to this object. Sub-objects
* (columns) don't have dependencies on global objects, so skip them.
*/
if (object->objectSubId == 0)
deleteSharedDependencyRecordsFor(object->classId, object->objectId);
/*
* CommandCounterIncrement here to ensure that preceding changes are all
* visible to the next deletion step.

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.349 2009/01/01 17:23:36 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.350 2009/01/22 20:16:01 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -112,37 +112,37 @@ static List *insert_ordered_unique_oid(List *list, Oid datum);
static FormData_pg_attribute a1 = {
0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
SelfItemPointerAttributeNumber, 0, -1, -1,
false, 'p', 's', true, false, false, true, 0
false, 'p', 's', true, false, false, true, 0, { 0 }
};
static FormData_pg_attribute a2 = {
0, {"oid"}, OIDOID, 0, sizeof(Oid),
ObjectIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
true, 'p', 'i', true, false, false, true, 0, { 0 }
};
static FormData_pg_attribute a3 = {
0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
MinTransactionIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
true, 'p', 'i', true, false, false, true, 0, { 0 }
};
static FormData_pg_attribute a4 = {
0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
MinCommandIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
true, 'p', 'i', true, false, false, true, 0, { 0 }
};
static FormData_pg_attribute a5 = {
0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
MaxTransactionIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
true, 'p', 'i', true, false, false, true, 0, { 0 }
};
static FormData_pg_attribute a6 = {
0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
MaxCommandIdAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
true, 'p', 'i', true, false, false, true, 0, { 0 }
};
/*
@ -154,7 +154,7 @@ static FormData_pg_attribute a6 = {
static FormData_pg_attribute a7 = {
0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
TableOidAttributeNumber, 0, -1, -1,
true, 'p', 'i', true, false, false, true, 0
true, 'p', 'i', true, false, false, true, 0, { 0 }
};
static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
@ -475,11 +475,13 @@ CheckAttributeType(const char *attname, Oid atttypid)
* Construct and insert a new tuple in pg_attribute.
*
* Caller has already opened and locked pg_attribute. new_attribute is the
* attribute to insert.
* attribute to insert (but we ignore its attacl, if indeed it has one).
*
* indstate is the index state for CatalogIndexInsert. It can be passed as
* NULL, in which case we'll fetch the necessary info. (Don't do this when
* inserting multiple attributes, because it's a tad more expensive.)
*
* We always initialize attacl to NULL (i.e., default permissions).
*/
void
InsertPgAttributeTuple(Relation pg_attribute_rel,
@ -512,6 +514,9 @@ InsertPgAttributeTuple(Relation pg_attribute_rel,
values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
/* start out with empty permissions */
nulls[Anum_pg_attribute_attacl - 1] = true;
tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
/* finally insert the new tuple, update the indexes, and clean up */

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.311 2009/01/01 17:23:37 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.312 2009/01/22 20:16:01 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -178,7 +178,7 @@ ConstructTupleDescriptor(Relation heapRelation,
* now that we've determined the "from", let's copy the tuple desc
* data...
*/
memcpy(to, from, ATTRIBUTE_TUPLE_SIZE);
memcpy(to, from, ATTRIBUTE_FIXED_PART_SIZE);
/*
* Fix the stuff that should not be the same as the underlying
@ -198,7 +198,7 @@ ConstructTupleDescriptor(Relation heapRelation,
/* Expressional index */
Node *indexkey;
MemSet(to, 0, ATTRIBUTE_TUPLE_SIZE);
MemSet(to, 0, ATTRIBUTE_FIXED_PART_SIZE);
if (indexpr_item == NULL) /* shouldn't happen */
elog(ERROR, "too few entries in indexprs list");

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_operator.c,v 1.107 2009/01/01 17:23:37 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/pg_operator.c,v 1.108 2009/01/22 20:16:01 tgl Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
@ -774,7 +774,7 @@ makeOperatorDependencies(HeapTuple tuple)
/* In case we are updating a shell, delete any existing entries */
deleteDependencyRecordsFor(myself.classId, myself.objectId);
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId);
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
/* Dependency on namespace */
if (OidIsValid(oper->oprnamespace))

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.160 2009/01/01 17:23:37 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.161 2009/01/22 20:16:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -499,7 +499,7 @@ ProcedureCreate(const char *procedureName,
if (is_update)
{
deleteDependencyRecordsFor(ProcedureRelationId, retval);
deleteSharedDependencyRecordsFor(ProcedureRelationId, retval);
deleteSharedDependencyRecordsFor(ProcedureRelationId, retval, 0);
}
myself.classId = ProcedureRelationId;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.30 2009/01/01 17:23:37 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.31 2009/01/22 20:16:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -55,15 +55,19 @@ static int getOidListDiff(Oid *list1, int nlist1, Oid *list2, int nlist2,
Oid **diff);
static Oid classIdGetDbId(Oid classId);
static void shdepLockAndCheckObject(Oid classId, Oid objectId);
static void shdepChangeDep(Relation sdepRel, Oid classid, Oid objid,
Oid refclassid, Oid refobjid,
SharedDependencyType deptype);
static void shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId,
Oid refclassId, Oid refobjId,
SharedDependencyType deptype);
static void shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId,
Oid refclassId, Oid refobjId,
SharedDependencyType deptype);
static void shdepChangeDep(Relation sdepRel,
Oid classid, Oid objid, int32 objsubid,
Oid refclassid, Oid refobjid,
SharedDependencyType deptype);
static void shdepAddDependency(Relation sdepRel,
Oid classId, Oid objectId, int32 objsubId,
Oid refclassId, Oid refobjId,
SharedDependencyType deptype);
static void shdepDropDependency(Relation sdepRel,
Oid classId, Oid objectId, int32 objsubId,
bool drop_subobjects,
Oid refclassId, Oid refobjId,
SharedDependencyType deptype);
static void storeObjectDescription(StringInfo descs, objectType type,
ObjectAddress *object,
SharedDependencyType deptype,
@ -111,6 +115,7 @@ recordSharedDependencyOn(ObjectAddress *depender,
sdepRel))
{
shdepAddDependency(sdepRel, depender->classId, depender->objectId,
depender->objectSubId,
referenced->classId, referenced->objectId,
deptype);
}
@ -163,14 +168,15 @@ recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
* locked.
*/
static void
shdepChangeDep(Relation sdepRel, Oid classid, Oid objid,
shdepChangeDep(Relation sdepRel,
Oid classid, Oid objid, int32 objsubid,
Oid refclassid, Oid refobjid,
SharedDependencyType deptype)
{
Oid dbid = classIdGetDbId(classid);
HeapTuple oldtup = NULL;
HeapTuple scantup;
ScanKeyData key[3];
ScanKeyData key[4];
SysScanDesc scan;
/*
@ -194,9 +200,13 @@ shdepChangeDep(Relation sdepRel, Oid classid, Oid objid,
Anum_pg_shdepend_objid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(objid));
ScanKeyInit(&key[3],
Anum_pg_shdepend_objsubid,
BTEqualStrategyNumber, F_INT4EQ,
Int32GetDatum(objsubid));
scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
SnapshotNow, 3, key);
SnapshotNow, 4, key);
while ((scantup = systable_getnext(scan)) != NULL)
{
@ -206,8 +216,8 @@ shdepChangeDep(Relation sdepRel, Oid classid, Oid objid,
/* Caller screwed up if multiple matches */
if (oldtup)
elog(ERROR,
"multiple pg_shdepend entries for object %u/%u deptype %c",
classid, objid, deptype);
"multiple pg_shdepend entries for object %u/%u/%d deptype %c",
classid, objid, objsubid, deptype);
oldtup = heap_copytuple(scantup);
}
@ -244,6 +254,7 @@ shdepChangeDep(Relation sdepRel, Oid classid, Oid objid,
values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(dbid);
values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classid);
values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objid);
values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubid);
values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassid);
values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjid);
@ -268,6 +279,9 @@ shdepChangeDep(Relation sdepRel, Oid classid, Oid objid,
* changeDependencyOnOwner
*
* Update the shared dependencies to account for the new owner.
*
* Note: we don't need an objsubid argument because only whole objects
* have owners.
*/
void
changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
@ -277,7 +291,8 @@ changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
/* Adjust the SHARED_DEPENDENCY_OWNER entry */
shdepChangeDep(sdepRel, classId, objectId,
shdepChangeDep(sdepRel,
classId, objectId, 0,
AuthIdRelationId, newOwnerId,
SHARED_DEPENDENCY_OWNER);
@ -300,7 +315,7 @@ changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
* to make the various ALTER OWNER routines each know about it.
*----------
*/
shdepDropDependency(sdepRel, classId, objectId,
shdepDropDependency(sdepRel, classId, objectId, 0, true,
AuthIdRelationId, newOwnerId,
SHARED_DEPENDENCY_ACL);
@ -368,7 +383,7 @@ getOidListDiff(Oid *list1, int nlist1, Oid *list2, int nlist2, Oid **diff)
* updateAclDependencies
* Update the pg_shdepend info for an object's ACL during GRANT/REVOKE.
*
* classId, objectId: identify the object whose ACL this is
* classId, objectId, objsubId: identify the object whose ACL this is
* ownerId: role owning the object
* isGrant: are we adding or removing ACL entries?
* noldmembers, oldmembers: array of roleids appearing in old ACL
@ -388,7 +403,8 @@ getOidListDiff(Oid *list1, int nlist1, Oid *list2, int nlist2, Oid **diff)
* before return.
*/
void
updateAclDependencies(Oid classId, Oid objectId, Oid ownerId, bool isGrant,
updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
Oid ownerId, bool isGrant,
int noldmembers, Oid *oldmembers,
int nnewmembers, Oid *newmembers)
{
@ -429,11 +445,12 @@ updateAclDependencies(Oid classId, Oid objectId, Oid ownerId, bool isGrant,
continue;
if (isGrant)
shdepAddDependency(sdepRel, classId, objectId,
shdepAddDependency(sdepRel, classId, objectId, objsubId,
AuthIdRelationId, roleid,
SHARED_DEPENDENCY_ACL);
else
shdepDropDependency(sdepRel, classId, objectId,
shdepDropDependency(sdepRel, classId, objectId, objsubId,
false, /* exact match on objsubId */
AuthIdRelationId, roleid,
SHARED_DEPENDENCY_ACL);
}
@ -533,7 +550,7 @@ checkSharedDependencies(Oid classId, Oid objectId,
object.classId = sdepForm->classid;
object.objectId = sdepForm->objid;
object.objectSubId = 0;
object.objectSubId = sdepForm->objsubid;
/*
* If it's a dependency local to this database or it's a shared
@ -755,7 +772,7 @@ dropDatabaseDependencies(Oid databaseId)
systable_endscan(scan);
/* Now delete all entries corresponding to the database itself */
shdepDropDependency(sdepRel, DatabaseRelationId, databaseId,
shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
InvalidOid, InvalidOid,
SHARED_DEPENDENCY_INVALID);
@ -768,15 +785,19 @@ dropDatabaseDependencies(Oid databaseId)
* Delete all pg_shdepend entries corresponding to an object that's being
* dropped or modified. The object is assumed to be either a shared object
* or local to the current database (the classId tells us which).
*
* If objectSubId is zero, we are deleting a whole object, so get rid of
* pg_shdepend entries for subobjects as well.
*/
void
deleteSharedDependencyRecordsFor(Oid classId, Oid objectId)
deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
{
Relation sdepRel;
sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
shdepDropDependency(sdepRel, classId, objectId,
shdepDropDependency(sdepRel, classId, objectId, objectSubId,
(objectSubId == 0),
InvalidOid, InvalidOid,
SHARED_DEPENDENCY_INVALID);
@ -791,7 +812,8 @@ deleteSharedDependencyRecordsFor(Oid classId, Oid objectId)
* locked.
*/
static void
shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId,
shdepAddDependency(Relation sdepRel,
Oid classId, Oid objectId, int32 objsubId,
Oid refclassId, Oid refobjId,
SharedDependencyType deptype)
{
@ -814,6 +836,7 @@ shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId,
values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));
values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);
values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);
values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId);
values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);
values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);
@ -835,20 +858,26 @@ shdepAddDependency(Relation sdepRel, Oid classId, Oid objectId,
* Internal workhorse for deleting entries from pg_shdepend.
*
* We drop entries having the following properties:
* dependent object is the one identified by classId/objectId
* dependent object is the one identified by classId/objectId/objsubId
* if refclassId isn't InvalidOid, it must match the entry's refclassid
* if refobjId isn't InvalidOid, it must match the entry's refobjid
* if deptype isn't SHARED_DEPENDENCY_INVALID, it must match entry's deptype
*
* If drop_subobjects is true, we ignore objsubId and consider all entries
* matching classId/objectId.
*
* sdepRel must be the pg_shdepend relation, already opened and suitably
* locked.
*/
static void
shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId,
shdepDropDependency(Relation sdepRel,
Oid classId, Oid objectId, int32 objsubId,
bool drop_subobjects,
Oid refclassId, Oid refobjId,
SharedDependencyType deptype)
{
ScanKeyData key[3];
ScanKeyData key[4];
int nkeys;
SysScanDesc scan;
HeapTuple tup;
@ -865,9 +894,19 @@ shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId,
Anum_pg_shdepend_objid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(objectId));
if (drop_subobjects)
nkeys = 3;
else
{
ScanKeyInit(&key[3],
Anum_pg_shdepend_objsubid,
BTEqualStrategyNumber, F_INT4EQ,
Int32GetDatum(objsubId));
nkeys = 4;
}
scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
SnapshotNow, 3, key);
SnapshotNow, nkeys, key);
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
@ -1067,7 +1106,7 @@ isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
*
* Drop the objects owned by any one of the given RoleIds. If a role has
* access to an object, the grant will be removed as well (but the object
* will not, of course.)
* will not, of course).
*
* We can revoke grants immediately while doing the scan, but drops are
* saved up and done all at once with performMultipleDeletions. This
@ -1131,10 +1170,9 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
while ((tuple = systable_getnext(scan)) != NULL)
{
ObjectAddress obj;
GrantObjectType objtype;
InternalGrant istmt;
Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
InternalGrant istmt;
ObjectAddress obj;
/* We only operate on objects in the current database */
if (sdepForm->dbid != MyDatabaseId)
@ -1172,14 +1210,13 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
default:
elog(ERROR, "unexpected object type %d",
sdepForm->classid);
/* keep compiler quiet */
objtype = (GrantObjectType) 0;
break;
}
istmt.is_grant = false;
istmt.objects = list_make1_oid(sdepForm->objid);
istmt.all_privs = true;
istmt.privileges = ACL_NO_RIGHTS;
istmt.col_privs = NIL;
istmt.grantees = list_make1_oid(roleid);
istmt.grant_option = false;
istmt.behavior = DROP_CASCADE;
@ -1190,7 +1227,7 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
/* Save it for deletion below */
obj.classId = sdepForm->classid;
obj.objectId = sdepForm->objid;
obj.objectSubId = 0;
obj.objectSubId = sdepForm->objsubid;
add_exact_object_address(&obj, deleteobjs);
break;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.123 2009/01/01 17:23:37 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.124 2009/01/22 20:16:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -482,7 +482,7 @@ GenerateTypeDependencies(Oid typeNamespace,
if (rebuild)
{
deleteDependencyRecordsFor(TypeRelationId, typeObjectId);
deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId);
deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
}
myself.classId = TypeRelationId;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.132 2009/01/06 23:46:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.133 2009/01/22 20:16:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -705,11 +705,12 @@ examine_attribute(Relation onerel, int attnum)
return NULL;
/*
* Create the VacAttrStats struct.
* Create the VacAttrStats struct. Note that we only have a copy of
* the fixed fields of the pg_attribute tuple.
*/
stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
stats->attr = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
memcpy(stats->attr, attr, ATTRIBUTE_TUPLE_SIZE);
stats->attr = (Form_pg_attribute) palloc(ATTRIBUTE_FIXED_PART_SIZE);
memcpy(stats->attr, attr, ATTRIBUTE_FIXED_PART_SIZE);
typtuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(attr->atttypid),
0, 0, 0);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.277 2009/01/12 08:54:26 petere Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.278 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -246,6 +246,7 @@ static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
static Oid transformFkeyCheckAttrs(Relation pkrel,
int numattrs, int16 *attnums,
Oid *opclasses);
static void checkFkeyPermissions(Relation rel, int16 *attnums, int natts);
static void validateForeignKeyConstraint(FkConstraint *fkconstraint,
Relation rel, Relation pkrel, Oid constraintOid);
static void createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
@ -3589,6 +3590,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
attribute.attisdropped = false;
attribute.attislocal = colDef->is_local;
attribute.attinhcount = colDef->inhcount;
/* attribute.attacl is handled by InsertPgAttributeTuple */
ReleaseSysCache(typeTuple);
@ -4473,15 +4475,14 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
* Add a foreign-key constraint to a single table
*
* Subroutine for ATExecAddConstraint. Must already hold exclusive
* lock on the rel, and have done appropriate validity/permissions checks
* for it.
* lock on the rel, and have done appropriate validity checks for it.
* We do permissions checks here, however.
*/
static void
ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
FkConstraint *fkconstraint)
{
Relation pkrel;
AclResult aclresult;
int16 pkattnum[INDEX_MAX_KEYS];
int16 fkattnum[INDEX_MAX_KEYS];
Oid pktypoid[INDEX_MAX_KEYS];
@ -4506,10 +4507,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
pkrel = heap_openrv(fkconstraint->pktable, AccessExclusiveLock);
/*
* Validity and permissions checks
*
* Note: REFERENCES permissions checks are redundant with CREATE TRIGGER,
* but we may as well error out sooner instead of later.
* Validity checks (permission checks wait till we have the column numbers)
*/
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
ereport(ERROR,
@ -4517,24 +4515,12 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
errmsg("referenced relation \"%s\" is not a table",
RelationGetRelationName(pkrel))));
aclresult = pg_class_aclcheck(RelationGetRelid(pkrel), GetUserId(),
ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(pkrel));
if (!allowSystemTableMods && IsSystemRelation(pkrel))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
RelationGetRelationName(pkrel))));
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
/*
* Disallow reference from permanent table to temp table or vice versa.
* (The ban on perm->temp is for fairly obvious reasons. The ban on
@ -4598,6 +4584,12 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
opclasses);
}
/*
* Now we can check permissions.
*/
checkFkeyPermissions(pkrel, pkattnum, numpks);
checkFkeyPermissions(rel, fkattnum, numfks);
/*
* Look up the equality operators to use in the constraint.
*
@ -5016,6 +5008,30 @@ transformFkeyCheckAttrs(Relation pkrel,
return indexoid;
}
/* Permissions checks for ADD FOREIGN KEY */
static void
checkFkeyPermissions(Relation rel, int16 *attnums, int natts)
{
Oid roleid = GetUserId();
AclResult aclresult;
int i;
/* Okay if we have relation-level REFERENCES permission */
aclresult = pg_class_aclcheck(RelationGetRelid(rel), roleid,
ACL_REFERENCES);
if (aclresult == ACLCHECK_OK)
return;
/* Else we must have REFERENCES on each column */
for (i = 0; i < natts; i++)
{
aclresult = pg_attribute_aclcheck(RelationGetRelid(rel), attnums[i],
roleid, ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
}
}
/*
* Scan the existing rows in a table to verify they meet a proposed FK
* constraint.
@ -5123,7 +5139,7 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
fk_trigger->constrrel = fkconstraint->pktable;
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid);
(void) CreateTrigger(fk_trigger, constraintOid, false);
/* Make changes-so-far visible */
CommandCounterIncrement();
@ -5204,7 +5220,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
}
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid);
(void) CreateTrigger(fk_trigger, constraintOid, false);
/* Make changes-so-far visible */
CommandCounterIncrement();
@ -5256,7 +5272,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
}
fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, constraintOid);
(void) CreateTrigger(fk_trigger, constraintOid, false);
}
/*

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.60 2009/01/20 18:59:37 heikki Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.61 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -455,7 +455,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
/*
* Remove dependency on owner.
*/
deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid);
deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid, 0);
/*
* Acquire TablespaceCreateLock to ensure that no TablespaceCreateDbspace

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.245 2009/01/22 19:16:31 heikki Exp $
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.246 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -74,11 +74,16 @@ static void AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event,
* be made to link the trigger to that constraint. constraintOid is zero when
* executing a user-entered CREATE TRIGGER command.
*
* If checkPermissions is true we require ACL_TRIGGER permissions on the
* relation. If not, the caller already checked permissions. (This is
* currently redundant with constraintOid being zero, but it's clearer to
* have a separate argument.)
*
* Note: can return InvalidOid if we decided to not create a trigger at all,
* but a foreign-key constraint. This is a kluge for backwards compatibility.
*/
Oid
CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid, bool checkPermissions)
{
int16 tgtype;
int2vector *tgattr;
@ -117,36 +122,26 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
errmsg("permission denied: \"%s\" is a system catalog",
RelationGetRelationName(rel))));
if (stmt->isconstraint && stmt->constrrel != NULL)
constrrelid = RangeVarGetRelid(stmt->constrrel, false);
/* permission checks */
if (stmt->isconstraint)
if (checkPermissions)
{
/* constraint trigger */
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
if (stmt->constrrel != NULL)
{
constrrelid = RangeVarGetRelid(stmt->constrrel, false);
aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
ACL_REFERENCES);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
get_rel_name(constrrelid));
}
}
else
{
/* regular trigger */
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
ACL_TRIGGER);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
RelationGetRelationName(rel));
if (OidIsValid(constrrelid))
{
aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
ACL_TRIGGER);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
get_rel_name(constrrelid));
}
}
/* Compute tgtype */

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.15 2009/01/01 17:23:40 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.16 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1255,7 +1255,7 @@ makeConfigurationDependencies(HeapTuple tuple, bool removeOld,
if (removeOld)
{
deleteDependencyRecordsFor(myself.classId, myself.objectId);
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId);
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
}
/*

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.184 2009/01/01 17:23:40 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.185 2009/01/22 20:16:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1123,9 +1123,17 @@ GrantRole(GrantRoleStmt *stmt)
*/
foreach(item, stmt->granted_roles)
{
char *rolename = strVal(lfirst(item));
Oid roleid = get_roleid_checked(rolename);
AccessPriv *priv = (AccessPriv *) lfirst(item);
char *rolename = priv->priv_name;
Oid roleid;
/* Must reject priv(columns) and ALL PRIVILEGES(columns) */
if (rolename == NULL || priv->cols != NIL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
roleid = get_roleid_checked(rolename);
if (stmt->is_grant)
AddRoleMems(rolename, roleid,
stmt->grantee_roles, grantee_ids,

View File

@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.320 2009/01/01 17:23:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.321 2009/01/22 20:16:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -34,6 +34,7 @@
#include "access/heapam.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/transam.h"
#include "access/xact.h"
#include "catalog/heap.h"
@ -453,8 +454,12 @@ static void
ExecCheckRTEPerms(RangeTblEntry *rte)
{
AclMode requiredPerms;
AclMode relPerms;
AclMode remainingPerms;
Oid relOid;
Oid userid;
Bitmapset *tmpset;
int col;
/*
* Only plain-relation RTEs need to be checked here. Function RTEs are
@ -484,12 +489,110 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
/*
* We must have *all* the requiredPerms bits, so use aclmask not aclcheck.
* We must have *all* the requiredPerms bits, but some of the bits can be
* satisfied from column-level rather than relation-level permissions.
* First, remove any bits that are satisfied by relation permissions.
*/
if (pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL)
!= requiredPerms)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
get_rel_name(relOid));
relPerms = pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL);
remainingPerms = requiredPerms & ~relPerms;
if (remainingPerms != 0)
{
/*
* If we lack any permissions that exist only as relation permissions,
* we can fail straight away.
*/
if (remainingPerms & ~(ACL_SELECT | ACL_INSERT | ACL_UPDATE))
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
get_rel_name(relOid));
/*
* Check to see if we have the needed privileges at column level.
*
* Note: failures just report a table-level error; it would be nicer
* to report a column-level error if we have some but not all of the
* column privileges.
*/
if (remainingPerms & ACL_SELECT)
{
/*
* When the query doesn't explicitly reference any columns (for
* example, SELECT COUNT(*) FROM table), allow the query if we
* have SELECT on any column of the rel, as per SQL spec.
*/
if (bms_is_empty(rte->selectedCols))
{
if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
ACLMASK_ANY) != ACLCHECK_OK)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
get_rel_name(relOid));
}
tmpset = bms_copy(rte->selectedCols);
while ((col = bms_first_member(tmpset)) >= 0)
{
/* remove the column number offset */
col += FirstLowInvalidHeapAttributeNumber;
if (col == InvalidAttrNumber)
{
/* Whole-row reference, must have priv on all cols */
if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
ACLMASK_ALL) != ACLCHECK_OK)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
get_rel_name(relOid));
}
else
{
if (pg_attribute_aclcheck(relOid, col, userid, ACL_SELECT)
!= ACLCHECK_OK)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
get_rel_name(relOid));
}
}
bms_free(tmpset);
}
/*
* Basically the same for the mod columns, with either INSERT or UPDATE
* privilege as specified by remainingPerms.
*/
remainingPerms &= ~ACL_SELECT;
if (remainingPerms != 0)
{
/*
* When the query doesn't explicitly change any columns, allow
* the query if we have permission on any column of the rel. This
* is to handle SELECT FOR UPDATE as well as possible corner cases
* in INSERT and UPDATE.
*/
if (bms_is_empty(rte->modifiedCols))
{
if (pg_attribute_aclcheck_all(relOid, userid, remainingPerms,
ACLMASK_ANY) != ACLCHECK_OK)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
get_rel_name(relOid));
}
tmpset = bms_copy(rte->modifiedCols);
while ((col = bms_first_member(tmpset)) >= 0)
{
/* remove the column number offset */
col += FirstLowInvalidHeapAttributeNumber;
if (col == InvalidAttrNumber)
{
/* whole-row reference can't happen here */
elog(ERROR, "whole-row update is not implemented");
}
else
{
if (pg_attribute_aclcheck(relOid, col, userid, remainingPerms)
!= ACLCHECK_OK)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
get_rel_name(relOid));
}
}
bms_free(tmpset);
}
}
}
/*

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.420 2009/01/16 13:27:23 heikki Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.421 2009/01/22 20:16:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1740,6 +1740,8 @@ _copyRangeTblEntry(RangeTblEntry *from)
COPY_SCALAR_FIELD(inFromCl);
COPY_SCALAR_FIELD(requiredPerms);
COPY_SCALAR_FIELD(checkAsUser);
COPY_BITMAPSET_FIELD(selectedCols);
COPY_BITMAPSET_FIELD(modifiedCols);
return newnode;
}
@ -2342,6 +2344,17 @@ _copyFuncWithArgs(FuncWithArgs *from)
return newnode;
}
static AccessPriv *
_copyAccessPriv(AccessPriv *from)
{
AccessPriv *newnode = makeNode(AccessPriv);
COPY_STRING_FIELD(priv_name);
COPY_NODE_FIELD(cols);
return newnode;
}
static GrantRoleStmt *
_copyGrantRoleStmt(GrantRoleStmt *from)
{
@ -4096,6 +4109,9 @@ copyObject(void *from)
case T_FuncWithArgs:
retval = _copyFuncWithArgs(from);
break;
case T_AccessPriv:
retval = _copyAccessPriv(from);
break;
case T_XmlSerialize:
retval = _copyXmlSerialize(from);
break;

View File

@ -22,7 +22,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.345 2009/01/16 13:27:23 heikki Exp $
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.346 2009/01/22 20:16:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1013,6 +1013,15 @@ _equalFuncWithArgs(FuncWithArgs *a, FuncWithArgs *b)
return true;
}
static bool
_equalAccessPriv(AccessPriv *a, AccessPriv *b)
{
COMPARE_STRING_FIELD(priv_name);
COMPARE_NODE_FIELD(cols);
return true;
}
static bool
_equalGrantRoleStmt(GrantRoleStmt *a, GrantRoleStmt *b)
{
@ -2122,6 +2131,8 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
COMPARE_SCALAR_FIELD(inFromCl);
COMPARE_SCALAR_FIELD(requiredPerms);
COMPARE_SCALAR_FIELD(checkAsUser);
COMPARE_BITMAPSET_FIELD(selectedCols);
COMPARE_BITMAPSET_FIELD(modifiedCols);
return true;
}
@ -2874,6 +2885,9 @@ equal(void *a, void *b)
case T_FuncWithArgs:
retval = _equalFuncWithArgs(a, b);
break;
case T_AccessPriv:
retval = _equalAccessPriv(a, b);
break;
case T_XmlSerialize:
retval = _equalXmlSerialize(a, b);
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.349 2009/01/01 17:23:43 momjian Exp $
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.350 2009/01/22 20:16:04 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@ -180,8 +180,6 @@ _outList(StringInfo str, List *node)
* converts a bitmap set of integers
*
* Note: the output format is "(b int int ...)", similar to an integer List.
* Currently bitmapsets do not appear in any node type that is stored in
* rules, so there is no support in readfuncs.c for reading this format.
*/
static void
_outBitmapset(StringInfo str, Bitmapset *bms)
@ -2060,6 +2058,8 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
WRITE_BOOL_FIELD(inFromCl);
WRITE_UINT_FIELD(requiredPerms);
WRITE_OID_FIELD(checkAsUser);
WRITE_BITMAPSET_FIELD(selectedCols);
WRITE_BITMAPSET_FIELD(modifiedCols);
}
static void

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.220 2009/01/01 17:23:43 momjian Exp $
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.221 2009/01/22 20:16:04 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
@ -114,6 +114,11 @@
token = pg_strtok(&length); /* skip :fldname */ \
local_node->fldname = nodeRead(NULL, 0)
/* Read a bitmapset field */
#define READ_BITMAPSET_FIELD(fldname) \
token = pg_strtok(&length); /* skip :fldname */ \
local_node->fldname = _readBitmapset()
/* Routine exit */
#define READ_DONE() \
return local_node
@ -137,6 +142,46 @@
static Datum readDatum(bool typbyval);
/*
* _readBitmapset
*/
static Bitmapset *
_readBitmapset(void)
{
Bitmapset *result = NULL;
READ_TEMP_LOCALS();
token = pg_strtok(&length);
if (token == NULL)
elog(ERROR, "incomplete Bitmapset structure");
if (length != 1 || token[0] != '(')
elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
token = pg_strtok(&length);
if (token == NULL)
elog(ERROR, "incomplete Bitmapset structure");
if (length != 1 || token[0] != 'b')
elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
for (;;)
{
int val;
char *endptr;
token = pg_strtok(&length);
if (token == NULL)
elog(ERROR, "unterminated Bitmapset structure");
if (length == 1 && token[0] == ')')
break;
val = (int) strtol(token, &endptr, 10);
if (endptr != token + length)
elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
result = bms_add_member(result, val);
}
return result;
}
/*
* _readQuery
@ -1102,6 +1147,8 @@ _readRangeTblEntry(void)
READ_BOOL_FIELD(inFromCl);
READ_UINT_FIELD(requiredPerms);
READ_OID_FIELD(checkAsUser);
READ_BITMAPSET_FIELD(selectedCols);
READ_BITMAPSET_FIELD(modifiedCols);
READ_DONE();
}

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.148 2009/01/01 17:23:44 momjian Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.149 2009/01/22 20:16:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -189,7 +189,8 @@ set_plan_references(PlannerGlobal *glob, Plan *plan, List *rtable)
* In the flat rangetable, we zero out substructure pointers that are not
* needed by the executor; this reduces the storage space and copying cost
* for cached plans. We keep only the alias and eref Alias fields, which
* are needed by EXPLAIN.
* are needed by EXPLAIN, and the selectedCols and modifiedCols bitmaps,
* which are needed for executor-startup permissions checking.
*/
foreach(lc, rtable)
{

View File

@ -17,13 +17,14 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.387 2009/01/08 13:42:33 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.388 2009/01/22 20:16:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/sysattr.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
@ -422,6 +423,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* bugs of just that nature...)
*/
sub_pstate->p_rtable = sub_rtable;
sub_pstate->p_joinexprs = NIL; /* sub_rtable has no joins */
sub_pstate->p_relnamespace = sub_relnamespace;
sub_pstate->p_varnamespace = sub_varnamespace;
@ -629,7 +631,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
/*
* Generate query's target list using the computed list of expressions.
* Also, mark all the target columns as needing insert permissions.
*/
rte = pstate->p_target_rangetblentry;
qry->targetList = NIL;
icols = list_head(icolumns);
attnos = list_head(attrnos);
@ -637,17 +641,22 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
{
Expr *expr = (Expr *) lfirst(lc);
ResTarget *col;
AttrNumber attr_num;
TargetEntry *tle;
col = (ResTarget *) lfirst(icols);
Assert(IsA(col, ResTarget));
attr_num = (AttrNumber) lfirst_int(attnos);
tle = makeTargetEntry(expr,
(AttrNumber) lfirst_int(attnos),
attr_num,
col->name,
false);
qry->targetList = lappend(qry->targetList, tle);
rte->modifiedCols = bms_add_member(rte->modifiedCols,
attr_num - FirstLowInvalidHeapAttributeNumber);
icols = lnext(icols);
attnos = lnext(attnos);
}
@ -1129,8 +1138,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
List *targetvars,
*targetnames,
*sv_relnamespace,
*sv_varnamespace,
*sv_rtable;
*sv_varnamespace;
int sv_rtable_length;
RangeTblEntry *jrte;
int tllen;
@ -1254,16 +1263,15 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
* "ORDER BY upper(foo)" will draw the right error message rather than
* "foo not found".
*/
jrte = addRangeTableEntryForJoin(NULL,
sv_rtable_length = list_length(pstate->p_rtable);
jrte = addRangeTableEntryForJoin(pstate,
targetnames,
JOIN_INNER,
targetvars,
NULL,
false);
sv_rtable = pstate->p_rtable;
pstate->p_rtable = list_make1(jrte);
sv_relnamespace = pstate->p_relnamespace;
pstate->p_relnamespace = NIL; /* no qualified names allowed */
@ -1283,7 +1291,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
&qry->targetList,
false /* no unknowns expected */ );
pstate->p_rtable = sv_rtable;
pstate->p_rtable = list_truncate(pstate->p_rtable, sv_rtable_length);
pstate->p_relnamespace = sv_relnamespace;
pstate->p_varnamespace = sv_varnamespace;
@ -1618,6 +1626,7 @@ static Query *
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
{
Query *qry = makeNode(Query);
RangeTblEntry *target_rte;
Node *qual;
ListCell *origTargetList;
ListCell *tl;
@ -1675,6 +1684,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
pstate->p_next_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
/* Prepare non-junk columns for assignment to target table */
target_rte = pstate->p_target_rangetblentry;
origTargetList = list_head(stmt->targetList);
foreach(tl, qry->targetList)
@ -1715,6 +1725,10 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
origTarget->indirection,
origTarget->location);
/* Mark the target column as requiring update permissions */
target_rte->modifiedCols = bms_add_member(target_rte->modifiedCols,
attrno - FirstLowInvalidHeapAttributeNumber);
origTargetList = lnext(origTargetList);
}
if (origTargetList != NULL)

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.655 2009/01/16 13:27:23 heikki Exp $
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.656 2009/01/22 20:16:05 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -94,6 +94,13 @@ extern List *parsetree; /* final parse result is delivered here */
static bool QueryIsRule = FALSE;
/* Private struct for the result of privilege_target production */
typedef struct PrivTarget
{
GrantObjectType objtype;
List *objs;
} PrivTarget;
/*
* If you need access to certain yacc-generated variables and find that
* they're static by default, uncomment the next line. (this is not a
@ -167,7 +174,8 @@ static TypeName *TableFuncTypeName(List *columns);
WithClause *with;
A_Indices *aind;
ResTarget *target;
PrivTarget *privtarget;
struct PrivTarget *privtarget;
AccessPriv *accesspriv;
InsertStmt *istmt;
VariableSetStmt *vsetstmt;
@ -254,7 +262,7 @@ static TypeName *TableFuncTypeName(List *columns);
%type <str> iso_level opt_encoding
%type <node> grantee
%type <list> grantee_list
%type <str> privilege
%type <accesspriv> privilege
%type <list> privileges privilege_list
%type <privtarget> privilege_target
%type <funwithargs> function_with_argtypes
@ -4210,12 +4218,11 @@ RevokeStmt:
/*
* A privilege list is represented as a list of strings; the validity of
* the privilege names gets checked at execution. This is a bit annoying
* but we have little choice because of the syntactic conflict with lists
* of role names in GRANT/REVOKE. What's more, we have to call out in
* the "privilege" production any reserved keywords that need to be usable
* as privilege names.
* Privilege names are represented as strings; the validity of the privilege
* names gets checked at execution. This is a bit annoying but we have little
* choice because of the syntactic conflict with lists of role names in
* GRANT/REVOKE. What's more, we have to call out in the "privilege"
* production any reserved keywords that need to be usable as privilege names.
*/
/* either ALL [PRIVILEGES] or a list of individual privileges */
@ -4225,18 +4232,54 @@ privileges: privilege_list
{ $$ = NIL; }
| ALL PRIVILEGES
{ $$ = NIL; }
| ALL '(' columnList ')'
{
AccessPriv *n = makeNode(AccessPriv);
n->priv_name = NULL;
n->cols = $3;
$$ = list_make1(n);
}
| ALL PRIVILEGES '(' columnList ')'
{
AccessPriv *n = makeNode(AccessPriv);
n->priv_name = NULL;
n->cols = $4;
$$ = list_make1(n);
}
;
privilege_list: privilege
{ $$ = list_make1(makeString($1)); }
| privilege_list ',' privilege
{ $$ = lappend($1, makeString($3)); }
privilege_list: privilege { $$ = list_make1($1); }
| privilege_list ',' privilege { $$ = lappend($1, $3); }
;
privilege: SELECT { $$ = pstrdup($1); }
| REFERENCES { $$ = pstrdup($1); }
| CREATE { $$ = pstrdup($1); }
| ColId { $$ = $1; }
privilege: SELECT opt_column_list
{
AccessPriv *n = makeNode(AccessPriv);
n->priv_name = pstrdup($1);
n->cols = $2;
$$ = n;
}
| REFERENCES opt_column_list
{
AccessPriv *n = makeNode(AccessPriv);
n->priv_name = pstrdup($1);
n->cols = $2;
$$ = n;
}
| CREATE opt_column_list
{
AccessPriv *n = makeNode(AccessPriv);
n->priv_name = pstrdup($1);
n->cols = $2;
$$ = n;
}
| ColId opt_column_list
{
AccessPriv *n = makeNode(AccessPriv);
n->priv_name = $1;
n->cols = $2;
$$ = n;
}
;
@ -4246,70 +4289,70 @@ privilege: SELECT { $$ = pstrdup($1); }
privilege_target:
qualified_name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_RELATION;
n->objs = $1;
$$ = n;
}
| TABLE qualified_name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_RELATION;
n->objs = $2;
$$ = n;
}
| SEQUENCE qualified_name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_SEQUENCE;
n->objs = $2;
$$ = n;
}
| FOREIGN DATA_P WRAPPER name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_FDW;
n->objs = $4;
$$ = n;
}
| FOREIGN SERVER name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_FOREIGN_SERVER;
n->objs = $3;
$$ = n;
}
| FUNCTION function_with_argtypes_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_FUNCTION;
n->objs = $2;
$$ = n;
}
| DATABASE name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_DATABASE;
n->objs = $2;
$$ = n;
}
| LANGUAGE name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_LANGUAGE;
n->objs = $2;
$$ = n;
}
| SCHEMA name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_NAMESPACE;
n->objs = $2;
$$ = n;
}
| TABLESPACE name_list
{
PrivTarget *n = makeNode(PrivTarget);
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
n->objtype = ACL_OBJECT_TABLESPACE;
n->objs = $2;
$$ = n;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.185 2009/01/01 17:23:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.186 2009/01/22 20:16:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,7 @@ static void extractRemainingColumns(List *common_colnames,
List *src_colnames, List *src_colvars,
List **res_colnames, List **res_colvars);
static Node *transformJoinUsingClause(ParseState *pstate,
RangeTblEntry *leftRTE, RangeTblEntry *rightRTE,
List *leftVars, List *rightVars);
static Node *transformJoinOnClause(ParseState *pstate, JoinExpr *j,
RangeTblEntry *l_rte,
@ -194,8 +195,7 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
*
* If we find an explicit reference to the rel later during parse
* analysis, we will add the ACL_SELECT bit back again; see
* scanRTEForColumn (for simple field references), ExpandColumnRefStar
* (for foo.*) and ExpandAllTables (for *).
* markVarForSelectPriv and its callers.
*/
rte->requiredPerms = requiredPerms;
@ -305,7 +305,9 @@ extractRemainingColumns(List *common_colnames,
* Result is a transformed qualification expression.
*/
static Node *
transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
transformJoinUsingClause(ParseState *pstate,
RangeTblEntry *leftRTE, RangeTblEntry *rightRTE,
List *leftVars, List *rightVars)
{
Node *result = NULL;
ListCell *lvars,
@ -315,17 +317,25 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
* We cheat a little bit here by building an untransformed operator tree
* whose leaves are the already-transformed Vars. This is OK because
* transformExpr() won't complain about already-transformed subnodes.
* However, this does mean that we have to mark the columns as requiring
* SELECT privilege for ourselves; transformExpr() won't do it.
*/
forboth(lvars, leftVars, rvars, rightVars)
{
Node *lvar = (Node *) lfirst(lvars);
Node *rvar = (Node *) lfirst(rvars);
Var *lvar = (Var *) lfirst(lvars);
Var *rvar = (Var *) lfirst(rvars);
A_Expr *e;
/* Require read access to the join variables */
markVarForSelectPriv(pstate, lvar, leftRTE);
markVarForSelectPriv(pstate, rvar, rightRTE);
/* Now create the lvar = rvar join condition */
e = makeSimpleA_Expr(AEXPR_OP, "=",
copyObject(lvar), copyObject(rvar),
-1);
/* And combine into an AND clause, if multiple join columns */
if (result == NULL)
result = (Node *) e;
else
@ -728,6 +738,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
*r_colvars,
*res_colvars;
RangeTblEntry *rte;
int k;
/*
* Recursively process the left and right subtrees
@ -912,6 +923,8 @@ transformFromClauseItem(ParseState *pstate, Node *n,
}
j->quals = transformJoinUsingClause(pstate,
l_rte,
r_rte,
l_usingvars,
r_usingvars);
}
@ -972,6 +985,12 @@ transformFromClauseItem(ParseState *pstate, Node *n,
*top_rte = rte;
*top_rti = j->rtindex;
/* make a matching link to the JoinExpr for later use */
for (k = list_length(pstate->p_joinexprs) + 1; k < j->rtindex; k++)
pstate->p_joinexprs = lappend(pstate->p_joinexprs, NULL);
pstate->p_joinexprs = lappend(pstate->p_joinexprs, j);
Assert(list_length(pstate->p_joinexprs) == j->rtindex);
/*
* Prepare returned namespace list. If the JOIN has an alias then it
* hides the contained RTEs as far as the relnamespace goes;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.239 2009/01/01 17:23:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.240 2009/01/22 20:16:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1977,6 +1977,9 @@ transformWholeRowRef(ParseState *pstate, char *schemaname, char *relname,
/* location is not filled in by makeVar */
result->location = location;
/* mark relation as requiring whole-row SELECT access */
markVarForSelectPriv(pstate, result, rte);
return (Node *) result;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.140 2009/01/01 17:23:46 momjian Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.141 2009/01/22 20:16:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -39,6 +39,8 @@ static RangeTblEntry *scanNameSpaceForRefname(ParseState *pstate,
const char *refname, int location);
static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid,
int location);
static void markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
int rtindex, AttrNumber col);
static bool isLockedRel(ParseState *pstate, char *refname);
static void expandRelation(Oid relid, Alias *eref,
int rtindex, int sublevels_up,
@ -435,14 +437,8 @@ GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, int rtelevelsup)
* If found, return an appropriate Var node, else return NULL.
* If the name proves ambiguous within this RTE, raise error.
*
* Side effect: if we find a match, mark the RTE as requiring read access.
* See comments in setTargetTable().
*
* NOTE: if the RTE is for a join, marking it as requiring read access does
* nothing. It might seem that we need to propagate the mark to all the
* contained RTEs, but that is not necessary. This is so because a join
* expression can only appear in a FROM clause, and any table named in
* FROM will be marked as requiring read access from the beginning.
* Side effect: if we find a match, mark the RTE as requiring read access
* for the column.
*/
Node *
scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname,
@ -450,6 +446,7 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname,
{
Node *result = NULL;
int attnum = 0;
Var *var;
ListCell *c;
/*
@ -476,9 +473,10 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname,
errmsg("column reference \"%s\" is ambiguous",
colname),
parser_errposition(pstate, location)));
result = (Node *) make_var(pstate, rte, attnum, location);
/* Require read access */
rte->requiredPerms |= ACL_SELECT;
var = make_var(pstate, rte, attnum, location);
/* Require read access to the column */
markVarForSelectPriv(pstate, var, rte);
result = (Node *) var;
}
}
@ -504,9 +502,10 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname,
Int16GetDatum(attnum),
0, 0))
{
result = (Node *) make_var(pstate, rte, attnum, location);
/* Require read access */
rte->requiredPerms |= ACL_SELECT;
var = make_var(pstate, rte, attnum, location);
/* Require read access to the column */
markVarForSelectPriv(pstate, var, rte);
result = (Node *) var;
}
}
}
@ -594,6 +593,122 @@ qualifiedNameToVar(ParseState *pstate,
return scanRTEForColumn(pstate, rte, colname, location);
}
/*
* markRTEForSelectPriv
* Mark the specified column of an RTE as requiring SELECT privilege
*
* col == InvalidAttrNumber means a "whole row" reference
*
* The caller should pass the actual RTE if it has it handy; otherwise pass
* NULL, and we'll look it up here. (This uglification of the API is
* worthwhile because nearly all external callers have the RTE at hand.)
*/
static void
markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte,
int rtindex, AttrNumber col)
{
if (rte == NULL)
rte = rt_fetch(rtindex, pstate->p_rtable);
if (rte->rtekind == RTE_RELATION)
{
/* Make sure the rel as a whole is marked for SELECT access */
rte->requiredPerms |= ACL_SELECT;
/* Must offset the attnum to fit in a bitmapset */
rte->selectedCols = bms_add_member(rte->selectedCols,
col - FirstLowInvalidHeapAttributeNumber);
}
else if (rte->rtekind == RTE_JOIN)
{
if (col == InvalidAttrNumber)
{
/*
* A whole-row reference to a join has to be treated as
* whole-row references to the two inputs.
*/
JoinExpr *j;
if (rtindex > 0 && rtindex <= list_length(pstate->p_joinexprs))
j = (JoinExpr *) list_nth(pstate->p_joinexprs, rtindex - 1);
else
j = NULL;
if (j == NULL)
elog(ERROR, "could not find JoinExpr for whole-row reference");
Assert(IsA(j, JoinExpr));
/* Note: we can't see FromExpr here */
if (IsA(j->larg, RangeTblRef))
{
int varno = ((RangeTblRef *) j->larg)->rtindex;
markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
}
else if (IsA(j->larg, JoinExpr))
{
int varno = ((JoinExpr *) j->larg)->rtindex;
markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
}
else
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(j->larg));
if (IsA(j->rarg, RangeTblRef))
{
int varno = ((RangeTblRef *) j->rarg)->rtindex;
markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
}
else if (IsA(j->rarg, JoinExpr))
{
int varno = ((JoinExpr *) j->rarg)->rtindex;
markRTEForSelectPriv(pstate, NULL, varno, InvalidAttrNumber);
}
else
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(j->rarg));
}
else
{
/*
* Regular join attribute, look at the alias-variable list.
*
* The aliasvar could be either a Var or a COALESCE expression,
* but in the latter case we should already have marked the two
* referent variables as being selected, due to their use in the
* JOIN clause. So we need only be concerned with the simple
* Var case.
*/
Var *aliasvar;
Assert(col > 0 && col <= list_length(rte->joinaliasvars));
aliasvar = (Var *) list_nth(rte->joinaliasvars, col - 1);
if (IsA(aliasvar, Var))
markVarForSelectPriv(pstate, aliasvar, NULL);
}
}
/* other RTE types don't require privilege marking */
}
/*
* markVarForSelectPriv
* Mark the RTE referenced by a Var as requiring SELECT privilege
*
* The caller should pass the Var's referenced RTE if it has it handy
* (nearly all do); otherwise pass NULL.
*/
void
markVarForSelectPriv(ParseState *pstate, Var *var, RangeTblEntry *rte)
{
Index lv;
Assert(IsA(var, Var));
/* Find the appropriate pstate if it's an uplevel Var */
for (lv = 0; lv < var->varlevelsup; lv++)
pstate = pstate->parentParseState;
markRTEForSelectPriv(pstate, rte, var->varno, var->varattno);
}
/*
* buildRelationAliases
* Construct the eref column name list for a relation RTE.
@ -838,6 +953,8 @@ addRangeTableEntry(ParseState *pstate,
rte->requiredPerms = ACL_SELECT;
rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
rte->selectedCols = NULL;
rte->modifiedCols = NULL;
/*
* Add completed RTE to pstate's range table list, but not to join list
@ -891,6 +1008,8 @@ addRangeTableEntryForRelation(ParseState *pstate,
rte->requiredPerms = ACL_SELECT;
rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
rte->selectedCols = NULL;
rte->modifiedCols = NULL;
/*
* Add completed RTE to pstate's range table list, but not to join list
@ -969,6 +1088,8 @@ addRangeTableEntryForSubquery(ParseState *pstate,
rte->requiredPerms = 0;
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
rte->modifiedCols = NULL;
/*
* Add completed RTE to pstate's range table list, but not to join list
@ -1101,6 +1222,8 @@ addRangeTableEntryForFunction(ParseState *pstate,
rte->requiredPerms = 0;
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
rte->modifiedCols = NULL;
/*
* Add completed RTE to pstate's range table list, but not to join list
@ -1168,8 +1291,11 @@ addRangeTableEntryForValues(ParseState *pstate,
*/
rte->inh = false; /* never true for values RTEs */
rte->inFromCl = inFromCl;
rte->requiredPerms = 0;
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
rte->modifiedCols = NULL;
/*
* Add completed RTE to pstate's range table list, but not to join list
@ -1239,6 +1365,8 @@ addRangeTableEntryForJoin(ParseState *pstate,
rte->requiredPerms = 0;
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
rte->modifiedCols = NULL;
/*
* Add completed RTE to pstate's range table list, but not to join list
@ -1320,6 +1448,8 @@ addRangeTableEntryForCTE(ParseState *pstate,
rte->requiredPerms = 0;
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
rte->modifiedCols = NULL;
/*
* Add completed RTE to pstate's range table list, but not to join list
@ -1803,6 +1933,7 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref,
* As with expandRTE, rtindex/sublevels_up determine the varno/varlevelsup
* fields of the Vars produced, and location sets their location.
* pstate->p_next_resno determines the resnos assigned to the TLEs.
* The referenced columns are marked as requiring SELECT access.
*/
List *
expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,
@ -1817,10 +1948,17 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,
expandRTE(rte, rtindex, sublevels_up, location, false,
&names, &vars);
/*
* Require read access to the table. This is normally redundant with the
* markVarForSelectPriv calls below, but not if the table has zero
* columns.
*/
rte->requiredPerms |= ACL_SELECT;
forboth(name, names, var, vars)
{
char *label = strVal(lfirst(name));
Node *varnode = (Node *) lfirst(var);
Var *varnode = (Var *) lfirst(var);
TargetEntry *te;
te = makeTargetEntry((Expr *) varnode,
@ -1828,6 +1966,9 @@ expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,
label,
false);
te_list = lappend(te_list, te);
/* Require read access to each column */
markVarForSelectPriv(pstate, varnode, rte);
}
Assert(name == NULL && var == NULL); /* lists not the same length? */

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.169 2009/01/01 17:23:46 momjian Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.170 2009/01/22 20:16:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -850,6 +850,8 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
* in a SELECT target list (where we want TargetEntry nodes in the result)
* and foo.* in a ROW() or VALUES() construct (where we want just bare
* expressions).
*
* The referenced columns are marked as requiring SELECT access.
*/
static List *
ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
@ -929,20 +931,37 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
makeRangeVar(schemaname, relname,
cref->location));
/* Require read access --- see comments in setTargetTable() */
rte->requiredPerms |= ACL_SELECT;
rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up);
if (targetlist)
{
/* expandRelAttrs handles permissions marking */
return expandRelAttrs(pstate, rte, rtindex, sublevels_up,
cref->location);
}
else
{
List *vars;
ListCell *l;
expandRTE(rte, rtindex, sublevels_up, cref->location, false,
NULL, &vars);
/*
* Require read access to the table. This is normally redundant
* with the markVarForSelectPriv calls below, but not if the table
* has zero columns.
*/
rte->requiredPerms |= ACL_SELECT;
/* Require read access to each column */
foreach(l, vars)
{
Var *var = (Var *) lfirst(l);
markVarForSelectPriv(pstate, var, rte);
}
return vars;
}
}
@ -956,6 +975,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
* varnamespace. We do not consider relnamespace because that would include
* input tables of aliasless JOINs, NEW/OLD pseudo-entries, implicit RTEs,
* etc.
*
* The referenced relations/columns are marked as requiring SELECT access.
*/
static List *
ExpandAllTables(ParseState *pstate, int location)
@ -975,9 +996,6 @@ ExpandAllTables(ParseState *pstate, int location)
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
int rtindex = RTERangeTablePosn(pstate, rte, NULL);
/* Require read access --- see comments in setTargetTable() */
rte->requiredPerms |= ACL_SELECT;
target = list_concat(target,
expandRelAttrs(pstate, rte, rtindex, 0,
location));

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.183 2009/01/22 17:27:54 petere Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.184 2009/01/22 20:16:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1178,9 +1178,13 @@ ApplyRetrieveRule(Query *parsetree,
Assert(subrte->relid == relation->rd_id);
subrte->requiredPerms = rte->requiredPerms;
subrte->checkAsUser = rte->checkAsUser;
subrte->selectedCols = rte->selectedCols;
subrte->modifiedCols = rte->modifiedCols;
rte->requiredPerms = 0; /* no permission check on subquery itself */
rte->checkAsUser = InvalidOid;
rte->selectedCols = NULL;
rte->modifiedCols = NULL;
/*
* FOR UPDATE/SHARE of view?

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.304 2009/01/01 17:23:48 momjian Exp $
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.305 2009/01/22 20:16:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -910,7 +910,7 @@ ProcessUtility(Node *parsetree,
break;
case T_CreateTrigStmt:
CreateTrigger((CreateTrigStmt *) parsetree, InvalidOid);
CreateTrigger((CreateTrigStmt *) parsetree, InvalidOid, true);
break;
case T_DropPropertyStmt:

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.145 2009/01/01 17:23:48 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.146 2009/01/22 20:16:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -366,6 +366,47 @@ allocacl(int n)
return new_acl;
}
/*
* Copy an ACL
*/
Acl *
aclcopy(const Acl *orig_acl)
{
Acl *result_acl;
result_acl = allocacl(ACL_NUM(orig_acl));
memcpy(ACL_DAT(result_acl),
ACL_DAT(orig_acl),
ACL_NUM(orig_acl) * sizeof(AclItem));
return result_acl;
}
/*
* Concatenate two ACLs
*
* This is a bit cheesy, since we may produce an ACL with redundant entries.
* Be careful what the result is used for!
*/
Acl *
aclconcat(const Acl *left_acl, const Acl *right_acl)
{
Acl *result_acl;
result_acl = allocacl(ACL_NUM(left_acl) + ACL_NUM(right_acl));
memcpy(ACL_DAT(result_acl),
ACL_DAT(left_acl),
ACL_NUM(left_acl) * sizeof(AclItem));
memcpy(ACL_DAT(result_acl) + ACL_NUM(left_acl),
ACL_DAT(right_acl),
ACL_NUM(right_acl) * sizeof(AclItem));
return result_acl;
}
/*
* Verify that an ACL array is acceptable (one-dimensional and has no nulls)
*/
@ -542,11 +583,17 @@ acldefault(GrantObjectType objtype, Oid ownerId)
{
AclMode world_default;
AclMode owner_default;
int nacl;
Acl *acl;
AclItem *aip;
switch (objtype)
{
case ACL_OBJECT_COLUMN:
/* by default, columns have no extra privileges */
world_default = ACL_NO_RIGHTS;
owner_default = ACL_NO_RIGHTS;
break;
case ACL_OBJECT_RELATION:
world_default = ACL_NO_RIGHTS;
owner_default = ACL_ALL_RIGHTS_RELATION;
@ -593,7 +640,13 @@ acldefault(GrantObjectType objtype, Oid ownerId)
break;
}
acl = allocacl((world_default != ACL_NO_RIGHTS) ? 2 : 1);
nacl = 0;
if (world_default != ACL_NO_RIGHTS)
nacl++;
if (owner_default != ACL_NO_RIGHTS)
nacl++;
acl = allocacl(nacl);
aip = ACL_DAT(acl);
if (world_default != ACL_NO_RIGHTS)
@ -614,9 +667,12 @@ acldefault(GrantObjectType objtype, Oid ownerId)
* "_SYSTEM"-like ACL entry, by internally special-casing the owner
* whereever we are testing grant options.
*/
aip->ai_grantee = ownerId;
aip->ai_grantor = ownerId;
ACLITEM_SET_PRIVS_GOPTIONS(*aip, owner_default, ACL_NO_RIGHTS);
if (owner_default != ACL_NO_RIGHTS)
{
aip->ai_grantee = ownerId;
aip->ai_grantor = ownerId;
ACLITEM_SET_PRIVS_GOPTIONS(*aip, owner_default, ACL_NO_RIGHTS);
}
return acl;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.281 2009/01/22 17:27:54 petere Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.282 2009/01/22 20:16:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -480,7 +480,7 @@ RelationBuildTupleDesc(Relation relation)
memcpy(relation->rd_att->attrs[attp->attnum - 1],
attp,
ATTRIBUTE_TUPLE_SIZE);
ATTRIBUTE_FIXED_PART_SIZE);
/* Update constraint/default info */
if (attp->attnotnull)
@ -1449,7 +1449,7 @@ formrdesc(const char *relationName, Oid relationReltype,
{
memcpy(relation->rd_att->attrs[i],
&att[i],
ATTRIBUTE_TUPLE_SIZE);
ATTRIBUTE_FIXED_PART_SIZE);
has_not_null |= att[i].attnotnull;
/* make sure attcacheoff is valid */
relation->rd_att->attrs[i]->attcacheoff = -1;
@ -2714,7 +2714,7 @@ BuildHardcodedDescriptor(int natts, Form_pg_attribute attrs, bool hasoids)
for (i = 0; i < natts; i++)
{
memcpy(result->attrs[i], &attrs[i], ATTRIBUTE_TUPLE_SIZE);
memcpy(result->attrs[i], &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
/* make sure attcacheoff is valid */
result->attrs[i]->attcacheoff = -1;
}
@ -3441,7 +3441,7 @@ load_relcache_init_file(void)
{
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
goto read_failed;
if (len != ATTRIBUTE_TUPLE_SIZE)
if (len != ATTRIBUTE_FIXED_PART_SIZE)
goto read_failed;
if ((nread = fread(rel->rd_att->attrs[i], 1, len, fp)) != len)
goto read_failed;
@ -3751,7 +3751,7 @@ write_relcache_init_file(void)
/* next, do all the attribute tuple form data entries */
for (i = 0; i < relform->relnatts; i++)
{
write_item(rel->rd_att->attrs[i], ATTRIBUTE_TUPLE_SIZE, fp);
write_item(rel->rd_att->attrs[i], ATTRIBUTE_FIXED_PART_SIZE, fp);
}
/* next, do the access method specific field */

View File

@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
* Portions taken from FreeBSD.
*
* $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.166 2009/01/01 17:23:53 momjian Exp $
* $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.167 2009/01/22 20:16:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1601,7 +1601,7 @@ setup_depend(void)
" FROM pg_ts_template;\n",
"INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
" FROM pg_ts_config;\n",
"INSERT INTO pg_shdepend SELECT 0, 0, 0, tableoid, oid, 'p' "
"INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' "
" FROM pg_authid;\n",
NULL
};

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.43 2009/01/01 17:23:54 momjian Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.44 2009/01/22 20:16:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -23,11 +23,13 @@
#define supports_grant_options(version) ((version) >= 70400)
static bool parseAclItem(const char *item, const char *type, const char *name,
int remoteVersion, PQExpBuffer grantee, PQExpBuffer grantor,
static bool parseAclItem(const char *item, const char *type,
const char *name, const char *subname, int remoteVersion,
PQExpBuffer grantee, PQExpBuffer grantor,
PQExpBuffer privs, PQExpBuffer privswgo);
static char *copyAclUserName(PQExpBuffer output, char *input);
static void AddAcl(PQExpBuffer aclbuf, const char *keyword);
static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
const char *subname);
/*
@ -384,6 +386,7 @@ parsePGArray(const char *atext, char ***itemarray, int *nitems)
* Build GRANT/REVOKE command(s) for an object.
*
* name: the object name, in the form to use in the commands (already quoted)
* subname: the sub-object name, if any (already quoted); NULL if none
* type: the object type (as seen in GRANT command: must be one of
* TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, or TABLESPACE)
* acls: the ACL string fetched from the database
@ -394,12 +397,12 @@ parsePGArray(const char *atext, char ***itemarray, int *nitems)
* Returns TRUE if okay, FALSE if could not parse the acl string.
* The resulting commands (if any) are appended to the contents of 'sql'.
*
* Note: beware of passing fmtId() result as 'name', since this routine
* uses fmtId() internally.
* Note: beware of passing a fmtId() result directly as 'name' or 'subname',
* since this routine uses fmtId() internally.
*/
bool
buildACLCommands(const char *name, const char *type,
const char *acls, const char *owner,
buildACLCommands(const char *name, const char *subname,
const char *type, const char *acls, const char *owner,
int remoteVersion,
PQExpBuffer sql)
{
@ -448,8 +451,10 @@ buildACLCommands(const char *name, const char *type,
* wire-in knowledge about the default public privileges for different
* kinds of objects.
*/
appendPQExpBuffer(firstsql, "REVOKE ALL ON %s %s FROM PUBLIC;\n",
type, name);
appendPQExpBuffer(firstsql, "REVOKE ALL");
if (subname)
appendPQExpBuffer(firstsql, "(%s)", subname);
appendPQExpBuffer(firstsql, " ON %s %s FROM PUBLIC;\n", type, name);
/*
* We still need some hacking though to cover the case where new default
@ -468,7 +473,7 @@ buildACLCommands(const char *name, const char *type,
/* Scan individual ACL items */
for (i = 0; i < naclitems; i++)
{
if (!parseAclItem(aclitems[i], type, name, remoteVersion,
if (!parseAclItem(aclitems[i], type, name, subname, remoteVersion,
grantee, grantor, privs, privswgo))
return false;
@ -491,15 +496,19 @@ buildACLCommands(const char *name, const char *type,
? strcmp(privswgo->data, "ALL") != 0
: strcmp(privs->data, "ALL") != 0)
{
appendPQExpBuffer(firstsql, "REVOKE ALL ON %s %s FROM %s;\n",
type, name,
fmtId(grantee->data));
appendPQExpBuffer(firstsql, "REVOKE ALL");
if (subname)
appendPQExpBuffer(firstsql, "(%s)", subname);
appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n",
type, name, fmtId(grantee->data));
if (privs->len > 0)
appendPQExpBuffer(firstsql, "GRANT %s ON %s %s TO %s;\n",
appendPQExpBuffer(firstsql,
"GRANT %s ON %s %s TO %s;\n",
privs->data, type, name,
fmtId(grantee->data));
if (privswgo->len > 0)
appendPQExpBuffer(firstsql, "GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
appendPQExpBuffer(firstsql,
"GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
privswgo->data, type, name,
fmtId(grantee->data));
}
@ -553,8 +562,13 @@ buildACLCommands(const char *name, const char *type,
* If we didn't find any owner privs, the owner must have revoked 'em all
*/
if (!found_owner_privs && owner)
appendPQExpBuffer(firstsql, "REVOKE ALL ON %s %s FROM %s;\n",
{
appendPQExpBuffer(firstsql, "REVOKE ALL");
if (subname)
appendPQExpBuffer(firstsql, "(%s)", subname);
appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n",
type, name, fmtId(owner));
}
destroyPQExpBuffer(grantee);
destroyPQExpBuffer(grantor);
@ -587,8 +601,9 @@ buildACLCommands(const char *name, const char *type,
* appropriate.
*/
static bool
parseAclItem(const char *item, const char *type, const char *name,
int remoteVersion, PQExpBuffer grantee, PQExpBuffer grantor,
parseAclItem(const char *item, const char *type,
const char *name, const char *subname, int remoteVersion,
PQExpBuffer grantee, PQExpBuffer grantor,
PQExpBuffer privs, PQExpBuffer privswgo)
{
char *buf;
@ -626,12 +641,12 @@ do { \
{ \
if (*(pos + 1) == '*') \
{ \
AddAcl(privswgo, keywd); \
AddAcl(privswgo, keywd, subname); \
all_without_go = false; \
} \
else \
{ \
AddAcl(privs, keywd); \
AddAcl(privs, keywd, subname); \
all_with_go = false; \
} \
} \
@ -654,13 +669,18 @@ do { \
/* table only */
CONVERT_PRIV('a', "INSERT");
if (remoteVersion >= 70200)
{
CONVERT_PRIV('d', "DELETE");
CONVERT_PRIV('x', "REFERENCES");
CONVERT_PRIV('t', "TRIGGER");
/* rest are not applicable to columns */
if (subname == NULL)
{
if (remoteVersion >= 70200)
{
CONVERT_PRIV('d', "DELETE");
CONVERT_PRIV('t', "TRIGGER");
}
if (remoteVersion >= 80400)
CONVERT_PRIV('D', "TRUNCATE");
}
if (remoteVersion >= 80400)
CONVERT_PRIV('D', "TRUNCATE");
}
/* UPDATE */
@ -700,11 +720,15 @@ do { \
{
resetPQExpBuffer(privs);
printfPQExpBuffer(privswgo, "ALL");
if (subname)
appendPQExpBuffer(privswgo, "(%s)", subname);
}
else if (all_without_go)
{
resetPQExpBuffer(privswgo);
printfPQExpBuffer(privs, "ALL");
if (subname)
appendPQExpBuffer(privs, "(%s)", subname);
}
free(buf);
@ -757,11 +781,13 @@ copyAclUserName(PQExpBuffer output, char *input)
* Append a privilege keyword to a keyword list, inserting comma if needed.
*/
static void
AddAcl(PQExpBuffer aclbuf, const char *keyword)
AddAcl(PQExpBuffer aclbuf, const char *keyword, const char *subname)
{
if (aclbuf->len > 0)
appendPQExpBufferChar(aclbuf, ',');
appendPQExpBuffer(aclbuf, "%s", keyword);
if (subname)
appendPQExpBuffer(aclbuf, "(%s)", subname);
}

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.22 2009/01/01 17:23:54 momjian Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.h,v 1.23 2009/01/22 20:16:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -28,8 +28,8 @@ extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
const char *dqprefix);
extern int parse_version(const char *versionString);
extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems);
extern bool buildACLCommands(const char *name, const char *type,
const char *acls, const char *owner,
extern bool buildACLCommands(const char *name, const char *subname,
const char *type, const char *acls, const char *owner,
int remoteVersion,
PQExpBuffer sql);
extern void processSQLNamePattern(PGconn *conn, PQExpBuffer buf,

View File

@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.515 2009/01/22 17:27:54 petere Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.516 2009/01/22 20:16:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -165,7 +165,7 @@ static void dumpUserMappings(Archive *fout, const char *target,
const char *owner, CatalogId catalogId, DumpId dumpId);
static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
const char *type, const char *name,
const char *type, const char *name, const char *subname,
const char *tag, const char *nspname, const char *owner,
const char *acls);
@ -5929,7 +5929,7 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
qnspname, nspinfo->dobj.name, NULL,
qnspname, NULL, nspinfo->dobj.name, NULL,
nspinfo->rolname, nspinfo->nspacl);
free(qnspname);
@ -6786,7 +6786,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
if (plang->lanpltrusted)
dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
qlanname, plang->dobj.name,
qlanname, NULL, plang->dobj.name,
lanschema,
plang->lanowner, plang->lanacl);
@ -7342,7 +7342,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
finfo->dobj.catId, 0, finfo->dobj.dumpId);
dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION",
funcsig, funcsig_tag,
funcsig, NULL, funcsig_tag,
finfo->dobj.namespace->dobj.name,
finfo->rolname, finfo->proacl);
@ -8828,7 +8828,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
"FUNCTION",
aggsig, aggsig_tag,
aggsig, NULL, aggsig_tag,
agginfo->aggfn.dobj.namespace->dobj.name,
agginfo->aggfn.rolname, agginfo->aggfn.proacl);
@ -9227,7 +9227,7 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
namecopy = strdup(fmtId(fdwinfo->dobj.name));
dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
"FOREIGN DATA WRAPPER",
namecopy, fdwinfo->dobj.name,
namecopy, NULL, fdwinfo->dobj.name,
NULL, fdwinfo->rolname,
fdwinfo->fdwacl);
free(namecopy);
@ -9305,7 +9305,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
namecopy = strdup(fmtId(srvinfo->dobj.name));
dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
"SERVER",
namecopy, srvinfo->dobj.name,
namecopy, NULL, srvinfo->dobj.name,
NULL, srvinfo->rolname,
srvinfo->srvacl);
free(namecopy);
@ -9412,6 +9412,7 @@ dumpUserMappings(Archive *fout, const char *target,
* 'objDumpId' is the dump ID of the underlying object.
* 'type' must be TABLE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, or TABLESPACE.
* 'name' is the formatted name of the object. Must be quoted etc. already.
* 'subname' is the formatted name of the sub-object, if any. Must be quoted.
* 'tag' is the tag for the archive entry (typ. unquoted name of object).
* 'nspname' is the namespace the object is in (NULL if none).
* 'owner' is the owner, NULL if there is no owner (for languages).
@ -9421,7 +9422,7 @@ dumpUserMappings(Archive *fout, const char *target,
*/
static void
dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
const char *type, const char *name,
const char *type, const char *name, const char *subname,
const char *tag, const char *nspname, const char *owner,
const char *acls)
{
@ -9433,7 +9434,7 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
sql = createPQExpBuffer();
if (!buildACLCommands(name, type, acls, owner, fout->remoteVersion, sql))
if (!buildACLCommands(name, subname, type, acls, owner, fout->remoteVersion, sql))
{
write_msg(NULL, "could not parse ACL list (%s) for object \"%s\" (%s)\n",
acls, name, type);
@ -9459,10 +9460,10 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
static void
dumpTable(Archive *fout, TableInfo *tbinfo)
{
char *namecopy;
if (tbinfo->dobj.dump)
{
char *namecopy;
if (tbinfo->relkind == RELKIND_SEQUENCE)
dumpSequence(fout, tbinfo);
else if (!dataOnly)
@ -9472,9 +9473,51 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
namecopy = strdup(fmtId(tbinfo->dobj.name));
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
(tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE",
namecopy, tbinfo->dobj.name,
namecopy, NULL, tbinfo->dobj.name,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tbinfo->relacl);
/*
* Handle column ACLs, if any. Note: we pull these with a separate
* query rather than trying to fetch them during getTableAttrs, so
* that we won't miss ACLs on system columns.
*/
if (g_fout->remoteVersion >= 80400)
{
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
int i;
appendPQExpBuffer(query,
"SELECT attname, attacl FROM pg_catalog.pg_attribute "
"WHERE attrelid = '%u' AND NOT attisdropped AND attacl IS NOT NULL "
"ORDER BY attnum",
tbinfo->dobj.catId.oid);
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
for (i = 0; i < PQntuples(res); i++)
{
char *attname = PQgetvalue(res, i, 0);
char *attacl = PQgetvalue(res, i, 1);
char *attnamecopy;
char *acltag;
attnamecopy = strdup(fmtId(attname));
acltag = malloc(strlen(tbinfo->dobj.name) + strlen(attname) + 2);
sprintf(acltag, "%s.%s", tbinfo->dobj.name, attname);
/* Column's GRANT type is always TABLE */
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
namecopy, attnamecopy, acltag,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
attacl);
free(attnamecopy);
free(acltag);
}
PQclear(res);
destroyPQExpBuffer(query);
}
free(namecopy);
}
}

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.112 2009/01/06 18:01:57 momjian Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.113 2009/01/22 20:16:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -882,7 +882,7 @@ dumpTablespaces(PGconn *conn)
appendPQExpBuffer(buf, ";\n");
if (!skip_acls &&
!buildACLCommands(fspcname, "TABLESPACE", spcacl, spcowner,
!buildACLCommands(fspcname, NULL, "TABLESPACE", spcacl, spcowner,
server_version, buf))
{
fprintf(stderr, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"),
@ -1075,7 +1075,7 @@ dumpCreateDB(PGconn *conn)
}
if (!skip_acls &&
!buildACLCommands(fdbname, "DATABASE", dbacl, dbowner,
!buildACLCommands(fdbname, NULL, "DATABASE", dbacl, dbowner,
server_version, buf))
{
fprintf(stderr, _("%s: could not parse ACL list (%s) for database \"%s\"\n"),

View File

@ -8,7 +8,7 @@
*
* Copyright (c) 2000-2009, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.197 2009/01/20 02:13:42 momjian Exp $
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.198 2009/01/22 20:16:08 tgl Exp $
*/
#include "postgres_fe.h"
@ -519,7 +519,7 @@ listAllDbs(bool verbose)
/*
* List Tables Grant/Revoke Permissions
* List Tables' Grant/Revoke Permissions
* \z (now also \dp -- perhaps more mnemonic)
*/
bool
@ -528,7 +528,7 @@ permissionsList(const char *pattern)
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
static const bool translate_columns[] = {false, false, true, false};
static const bool translate_columns[] = {false, false, true, false, false};
initPQExpBuffer(&buf);
@ -544,7 +544,18 @@ permissionsList(const char *pattern)
gettext_noop("Name"),
gettext_noop("table"), gettext_noop("view"), gettext_noop("sequence"),
gettext_noop("Type"));
printACLColumn(&buf, "c.relacl");
if (pset.sversion >= 80400)
appendPQExpBuffer(&buf,
",\n pg_catalog.array_to_string(ARRAY(\n"
" SELECT attname || E':\\n ' || pg_catalog.array_to_string(attacl, E'\\n ')\n"
" FROM pg_catalog.pg_attribute a\n"
" WHERE attrelid = c.oid AND NOT attisdropped AND attacl IS NOT NULL\n"
" ), E'\\n') AS \"%s\"",
gettext_noop("Column access privileges"));
appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_class c\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
"WHERE c.relkind IN ('r', 'v', 'S')\n");
@ -1907,7 +1918,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
static const bool translate_columns[] = {false, false, true, false, false, false};
static const bool translate_columns[] = {false, false, true, false, false, false, false};
if (!(showTables || showIndexes || showViews || showSeq))
showTables = showViews = showSeq = true;
@ -1965,7 +1976,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
if (showSeq)
appendPQExpBuffer(&buf, "'S',");
if (showSystem)
appendPQExpBuffer(&buf, "'s',"); /* was RELKIND_SPECIAL in <= 8.1.X */
appendPQExpBuffer(&buf, "'s',"); /* was RELKIND_SPECIAL in <= 8.1 */
appendPQExpBuffer(&buf, "''"); /* dummy */
appendPQExpBuffer(&buf, ")\n");

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.518 2009/01/16 13:27:24 heikki Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.519 2009/01/22 20:16:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200901161
#define CATALOG_VERSION_NO 200901221
#endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.38 2009/01/01 17:23:56 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.39 2009/01/22 20:16:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -108,7 +108,7 @@ typedef struct ObjectAddress
{
Oid classId; /* Class Id from pg_class */
Oid objectId; /* OID of the object */
int32 objectSubId; /* Subitem within the object (column of table) */
int32 objectSubId; /* Subitem within object (eg column), or 0 */
} ObjectAddress;
/* expansible list of ObjectAddresses (private in dependency.c) */
@ -221,14 +221,15 @@ extern void recordSharedDependencyOn(ObjectAddress *depender,
ObjectAddress *referenced,
SharedDependencyType deptype);
extern void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId);
extern void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId,
int32 objectSubId);
extern void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner);
extern void changeDependencyOnOwner(Oid classId, Oid objectId,
Oid newOwnerId);
extern void updateAclDependencies(Oid classId, Oid objectId,
extern void updateAclDependencies(Oid classId, Oid objectId, int32 objectSubId,
Oid ownerId, bool isGrant,
int noldmembers, Oid *oldmembers,
int nnewmembers, Oid *newmembers);

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.105 2009/01/01 17:23:56 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.106 2009/01/22 20:16:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -202,7 +202,7 @@ DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, on pg_rewrite using bt
#define RewriteRelRulenameIndexId 2693
/* This following index is not used for a cache and is not unique */
DECLARE_INDEX(pg_shdepend_depender_index, 1232, on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops));
DECLARE_INDEX(pg_shdepend_depender_index, 1232, on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops));
#define SharedDependDependerIndexId 1232
/* This following index is not used for a cache and is not unique */
DECLARE_INDEX(pg_shdepend_reference_index, 1233, on pg_shdepend using btree(refclassid oid_ops, refobjid oid_ops));

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.145 2009/01/01 17:23:56 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.146 2009/01/22 20:16:08 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -144,14 +144,24 @@ CATALOG(pg_attribute,1249) BKI_BOOTSTRAP BKI_WITHOUT_OIDS
/* Number of times inherited from direct parent relation(s) */
int4 attinhcount;
/*
* VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
*
* NOTE: the following fields are not present in tuple descriptors!
*/
/* Column-level access permissions */
aclitem attacl[1];
} FormData_pg_attribute;
/*
* someone should figure out how to do this properly. (The problem is
* the size of the C struct is not the same as the size of the tuple
* because of alignment padding at the end of the struct.)
* ATTRIBUTE_FIXED_PART_SIZE is the size of the fixed-layout,
* guaranteed-not-null part of a pg_attribute row. This is in fact as much
* of the row as gets copied into tuple descriptors, so don't expect you
* can access fields beyond attinhcount except in a real tuple!
*/
#define ATTRIBUTE_TUPLE_SIZE \
#define ATTRIBUTE_FIXED_PART_SIZE \
(offsetof(FormData_pg_attribute,attinhcount) + sizeof(int4))
/* ----------------
@ -166,7 +176,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
* ----------------
*/
#define Natts_pg_attribute 17
#define Natts_pg_attribute 18
#define Anum_pg_attribute_attrelid 1
#define Anum_pg_attribute_attname 2
#define Anum_pg_attribute_atttypid 3
@ -184,24 +194,9 @@ typedef FormData_pg_attribute *Form_pg_attribute;
#define Anum_pg_attribute_attisdropped 15
#define Anum_pg_attribute_attislocal 16
#define Anum_pg_attribute_attinhcount 17
#define Anum_pg_attribute_attacl 18
/* ----------------
* SCHEMA_ macros for declaring hardcoded tuple descriptors.
* these are used in utils/cache/relcache.c
* ----------------
#define SCHEMA_NAME(x) CppConcat(Name_,x)
#define SCHEMA_DESC(x) CppConcat(Desc_,x)
#define SCHEMA_NATTS(x) CppConcat(Natts_,x)
#define SCHEMA_DEF(x) \
FormData_pg_attribute \
SCHEMA_DESC(x) [ SCHEMA_NATTS(x) ] = \
{ \
CppConcat(Schema_,x) \
}
*/
/* ----------------
* initial contents of pg_attribute
*
@ -217,244 +212,246 @@ typedef FormData_pg_attribute *Form_pg_attribute;
* ----------------
*/
#define Schema_pg_type \
{ 1247, {"typname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typlen"}, 21, -1, 2, 4, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1247, {"typbyval"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typtype"}, 18, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typcategory"}, 18, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typispreferred"},16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typisdefined"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typdelim"}, 18, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typrelid"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typelem"}, 26, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typarray"}, 26, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typinput"}, 24, -1, 4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typoutput"}, 24, -1, 4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typreceive"}, 24, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typsend"}, 24, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typmodin"}, 24, -1, 4, 18, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typmodout"}, 24, -1, 4, 19, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typanalyze"}, 24, -1, 4, 20, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typalign"}, 18, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typstorage"}, 18, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typnotnull"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1247, {"typbasetype"}, 26, -1, 4, 24, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typtypmod"}, 23, -1, 4, 25, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typndims"}, 23, -1, 4, 26, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1247, {"typdefaultbin"}, 25, -1, -1, 27, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1247, {"typdefault"}, 25, -1, -1, 28, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
{ 1247, {"typname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typlen"}, 21, -1, 2, 4, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typbyval"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typtype"}, 18, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typcategory"}, 18, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typispreferred"},16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typisdefined"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typdelim"}, 18, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typrelid"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typelem"}, 26, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typarray"}, 26, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typinput"}, 24, -1, 4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typoutput"}, 24, -1, 4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typreceive"}, 24, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typsend"}, 24, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typmodin"}, 24, -1, 4, 18, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typmodout"}, 24, -1, 4, 19, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typanalyze"}, 24, -1, 4, 20, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typalign"}, 18, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typstorage"}, 18, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typnotnull"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typbasetype"}, 26, -1, 4, 24, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typtypmod"}, 23, -1, 4, 25, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typndims"}, 23, -1, 4, 26, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1247, {"typdefaultbin"}, 25, -1, -1, 27, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1247, {"typdefault"}, 25, -1, -1, 28, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }
DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0));
DATA(insert ( 1247 typnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typowner 26 -1 4 3 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typlen 21 -1 2 4 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1247 typbyval 16 -1 1 5 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typtype 18 -1 1 6 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typcategory 18 -1 1 7 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typispreferred 16 -1 1 8 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typisdefined 16 -1 1 9 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typdelim 18 -1 1 10 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typrelid 26 -1 4 11 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typelem 26 -1 4 12 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typarray 26 -1 4 13 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typinput 24 -1 4 14 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typoutput 24 -1 4 15 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typreceive 24 -1 4 16 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typsend 24 -1 4 17 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typmodin 24 -1 4 18 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typmodout 24 -1 4 19 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typanalyze 24 -1 4 20 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typalign 18 -1 1 21 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typstorage 18 -1 1 22 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typnotnull 16 -1 1 23 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1247 typbasetype 26 -1 4 24 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typtypmod 23 -1 4 25 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typndims 23 -1 4 26 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typdefaultbin 25 -1 -1 27 0 -1 -1 f x i f f f t 0));
DATA(insert ( 1247 typdefault 25 -1 -1 28 0 -1 -1 f x i f f f t 0));
DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0 _null_));
DATA(insert ( 1247 typnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typowner 26 -1 4 3 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typlen 21 -1 2 4 0 -1 -1 t p s t f f t 0 _null_));
DATA(insert ( 1247 typbyval 16 -1 1 5 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typtype 18 -1 1 6 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typcategory 18 -1 1 7 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typispreferred 16 -1 1 8 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typisdefined 16 -1 1 9 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typdelim 18 -1 1 10 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typrelid 26 -1 4 11 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typelem 26 -1 4 12 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typarray 26 -1 4 13 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typinput 24 -1 4 14 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typoutput 24 -1 4 15 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typreceive 24 -1 4 16 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typsend 24 -1 4 17 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typmodin 24 -1 4 18 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typmodout 24 -1 4 19 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typanalyze 24 -1 4 20 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typalign 18 -1 1 21 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typstorage 18 -1 1 22 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typnotnull 16 -1 1 23 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1247 typbasetype 26 -1 4 24 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typtypmod 23 -1 4 25 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typndims 23 -1 4 26 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 typdefaultbin 25 -1 -1 27 0 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1247 typdefault 25 -1 -1 28 0 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0 _null_));
DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 _null_));
/* ----------------
* pg_proc
* ----------------
*/
#define Schema_pg_proc \
{ 1255, {"proname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0 }, \
{ 1255, {"pronamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"proowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"prolang"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"procost"}, 700, -1, 4, 5, 0, -1, -1, FLOAT4PASSBYVAL, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"prorows"}, 700, -1, 4, 6, 0, -1, -1, FLOAT4PASSBYVAL, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"provariadic"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"proisagg"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1255, {"proiswindow"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1255, {"prosecdef"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1255, {"proisstrict"}, 16, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1255, {"proretset"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1255, {"provolatile"}, 18, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1255, {"pronargs"}, 21, -1, 2, 14, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1255, {"pronargdefaults"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1255, {"prorettype"}, 26, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"proargtypes"}, 30, -1, -1, 17, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
{ 1255, {"proallargtypes"}, 1028, -1, -1, 18, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"proargmodes"}, 1002, -1, -1, 19, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"proargnames"}, 1009, -1, -1, 20, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"proargdefaults"}, 25, -1, -1, 21, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"prosrc"}, 25, -1, -1, 22, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"probin"}, 17, -1, -1, 23, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"proconfig"}, 1009, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1255, {"proacl"}, 1034, -1, -1, 25, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
{ 1255, {"proname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1255, {"pronamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1255, {"proowner"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1255, {"prolang"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1255, {"procost"}, 700, -1, 4, 5, 0, -1, -1, FLOAT4PASSBYVAL, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1255, {"prorows"}, 700, -1, 4, 6, 0, -1, -1, FLOAT4PASSBYVAL, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1255, {"provariadic"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1255, {"proisagg"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1255, {"proiswindow"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1255, {"prosecdef"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1255, {"proisstrict"}, 16, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1255, {"proretset"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1255, {"provolatile"}, 18, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1255, {"pronargs"}, 21, -1, 2, 14, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, { 0 } }, \
{ 1255, {"pronargdefaults"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, { 0 } }, \
{ 1255, {"prorettype"}, 26, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1255, {"proargtypes"}, 30, -1, -1, 17, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1255, {"proallargtypes"}, 1028, -1, -1, 18, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1255, {"proargmodes"}, 1002, -1, -1, 19, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1255, {"proargnames"}, 1009, -1, -1, 20, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1255, {"proargdefaults"}, 25, -1, -1, 21, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1255, {"prosrc"}, 25, -1, -1, 22, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1255, {"probin"}, 17, -1, -1, 23, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1255, {"proconfig"}, 1009, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1255, {"proacl"}, 1034, -1, -1, 25, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }
DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0));
DATA(insert ( 1255 pronamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 proowner 26 -1 4 3 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 prolang 26 -1 4 4 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 procost 700 -1 4 5 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0));
DATA(insert ( 1255 prorows 700 -1 4 6 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0));
DATA(insert ( 1255 provariadic 26 -1 4 7 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 proisagg 16 -1 1 8 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1255 proiswindow 16 -1 1 9 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1255 prosecdef 16 -1 1 10 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1255 proisstrict 16 -1 1 11 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1255 proretset 16 -1 1 12 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1255 provolatile 18 -1 1 13 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1255 pronargs 21 -1 2 14 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1255 pronargdefaults 21 -1 2 15 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1255 prorettype 26 -1 4 16 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 proargtypes 30 -1 -1 17 1 -1 -1 f p i t f f t 0));
DATA(insert ( 1255 proallargtypes 1028 -1 -1 18 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 proargmodes 1002 -1 -1 19 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 proargnames 1009 -1 -1 20 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 proargdefaults 25 -1 -1 21 0 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 prosrc 25 -1 -1 22 0 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 probin 17 -1 -1 23 0 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 proconfig 1009 -1 -1 24 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 proacl 1034 -1 -1 25 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0 _null_));
DATA(insert ( 1255 pronamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 proowner 26 -1 4 3 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 prolang 26 -1 4 4 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 procost 700 -1 4 5 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0 _null_));
DATA(insert ( 1255 prorows 700 -1 4 6 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0 _null_));
DATA(insert ( 1255 provariadic 26 -1 4 7 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 proisagg 16 -1 1 8 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1255 proiswindow 16 -1 1 9 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1255 prosecdef 16 -1 1 10 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1255 proisstrict 16 -1 1 11 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1255 proretset 16 -1 1 12 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1255 provolatile 18 -1 1 13 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1255 pronargs 21 -1 2 14 0 -1 -1 t p s t f f t 0 _null_));
DATA(insert ( 1255 pronargdefaults 21 -1 2 15 0 -1 -1 t p s t f f t 0 _null_));
DATA(insert ( 1255 prorettype 26 -1 4 16 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 proargtypes 30 -1 -1 17 1 -1 -1 f p i t f f t 0 _null_));
DATA(insert ( 1255 proallargtypes 1028 -1 -1 18 1 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1255 proargmodes 1002 -1 -1 19 1 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1255 proargnames 1009 -1 -1 20 1 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1255 proargdefaults 25 -1 -1 21 0 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1255 prosrc 25 -1 -1 22 0 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1255 probin 17 -1 -1 23 0 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1255 proconfig 1009 -1 -1 24 1 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1255 proacl 1034 -1 -1 25 1 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0 _null_));
DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 _null_));
/* ----------------
* pg_attribute
* ----------------
*/
#define Schema_pg_attribute \
{ 1249, {"attrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0 }, \
{ 1249, {"atttypid"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1249, {"attstattarget"}, 23, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1249, {"attlen"}, 21, -1, 2, 5, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1249, {"attnum"}, 21, -1, 2, 6, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1249, {"attndims"}, 23, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1249, {"attcacheoff"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1249, {"atttypmod"}, 23, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1249, {"attbyval"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1249, {"attstorage"}, 18, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1249, {"attalign"}, 18, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1249, {"attnotnull"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1249, {"atthasdef"}, 16, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1249, {"attisdropped"}, 16, -1, 1, 15, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1249, {"attislocal"}, 16, -1, 1, 16, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1249, {"attinhcount"}, 23, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }
{ 1249, {"attrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1249, {"atttypid"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attstattarget"}, 23, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attlen"}, 21, -1, 2, 5, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attnum"}, 21, -1, 2, 6, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attndims"}, 23, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attcacheoff"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1249, {"atttypmod"}, 23, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attbyval"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attstorage"}, 18, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attalign"}, 18, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attnotnull"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1249, {"atthasdef"}, 16, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attisdropped"}, 16, -1, 1, 15, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attislocal"}, 16, -1, 1, 16, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attinhcount"}, 23, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1249, {"attacl"}, 1034, -1, -1, 18, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }
DATA(insert ( 1249 attrelid 26 -1 4 1 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p c t f f t 0));
DATA(insert ( 1249 atttypid 26 -1 4 3 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 attstattarget 23 -1 4 4 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 attlen 21 -1 2 5 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1249 attnum 21 -1 2 6 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1249 attndims 23 -1 4 7 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 attcacheoff 23 -1 4 8 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 atttypmod 23 -1 4 9 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 attbyval 16 -1 1 10 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1249 attstorage 18 -1 1 11 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1249 attalign 18 -1 1 12 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1249 attnotnull 16 -1 1 13 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1249 atthasdef 16 -1 1 14 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1249 attisdropped 16 -1 1 15 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1249 attislocal 16 -1 1 16 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1249 attinhcount 23 -1 4 17 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
DATA(insert ( 1249 attrelid 26 -1 4 1 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p c t f f t 0 _null_));
DATA(insert ( 1249 atttypid 26 -1 4 3 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 attstattarget 23 -1 4 4 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 attlen 21 -1 2 5 0 -1 -1 t p s t f f t 0 _null_));
DATA(insert ( 1249 attnum 21 -1 2 6 0 -1 -1 t p s t f f t 0 _null_));
DATA(insert ( 1249 attndims 23 -1 4 7 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 attcacheoff 23 -1 4 8 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 atttypmod 23 -1 4 9 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 attbyval 16 -1 1 10 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1249 attstorage 18 -1 1 11 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1249 attalign 18 -1 1 12 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1249 attnotnull 16 -1 1 13 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1249 atthasdef 16 -1 1 14 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1249 attisdropped 16 -1 1 15 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1249 attislocal 16 -1 1 16 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1249 attinhcount 23 -1 4 17 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 attacl 1034 -1 -1 18 1 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1249 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0 _null_));
/* no OIDs in pg_attribute */
DATA(insert ( 1249 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1249 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 _null_));
/* ----------------
* pg_class
* ----------------
*/
#define Schema_pg_class \
{ 1259, {"relname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"reltype"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relowner"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relam"}, 26, -1, 4, 5, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relfilenode"}, 26, -1, 4, 6, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"reltablespace"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relpages"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"reltuples"}, 700, -1, 4, 9, 0, -1, -1, FLOAT4PASSBYVAL, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"reltoastrelid"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"reltoastidxid"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relhasindex"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relisshared"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relkind"}, 18, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relnatts"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1259, {"relchecks"}, 21, -1, 2, 16, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 1259, {"relhasoids"}, 16, -1, 1, 17, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhaspkey"}, 16, -1, 1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhasrules"}, 16, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhastriggers"},16, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhassubclass"},16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relfrozenxid"}, 28, -1, 4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relacl"}, 1034, -1, -1, 23, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1259, {"reloptions"}, 1009, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
{ 1259, {"relname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relnamespace"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"reltype"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relowner"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relam"}, 26, -1, 4, 5, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relfilenode"}, 26, -1, 4, 6, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"reltablespace"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relpages"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"reltuples"}, 700, -1, 4, 9, 0, -1, -1, FLOAT4PASSBYVAL, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"reltoastrelid"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"reltoastidxid"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relhasindex"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relisshared"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relkind"}, 18, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relnatts"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relchecks"}, 21, -1, 2, 16, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relhasoids"}, 16, -1, 1, 17, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relhaspkey"}, 16, -1, 1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relhasrules"}, 16, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relhastriggers"},16, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relhassubclass"},16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relfrozenxid"}, 28, -1, 4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 1259, {"relacl"}, 1034, -1, -1, 23, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 1259, {"reloptions"}, 1009, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }
DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0));
DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 reltype 26 -1 4 3 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relowner 26 -1 4 4 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relam 26 -1 4 5 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relfilenode 26 -1 4 6 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 reltablespace 26 -1 4 7 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relpages 23 -1 4 8 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 reltuples 700 -1 4 9 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0));
DATA(insert ( 1259 reltoastrelid 26 -1 4 10 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 reltoastidxid 26 -1 4 11 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relhasindex 16 -1 1 12 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relisshared 16 -1 1 13 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relkind 18 -1 1 14 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relnatts 21 -1 2 15 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1259 relchecks 21 -1 2 16 0 -1 -1 t p s t f f t 0));
DATA(insert ( 1259 relhasoids 16 -1 1 17 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhaspkey 16 -1 1 18 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhasrules 16 -1 1 19 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhastriggers 16 -1 1 20 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhassubclass 16 -1 1 21 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relfrozenxid 28 -1 4 22 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relacl 1034 -1 -1 23 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 reloptions 1009 -1 -1 24 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p c t f f t 0 _null_));
DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 reltype 26 -1 4 3 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 relowner 26 -1 4 4 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 relam 26 -1 4 5 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 relfilenode 26 -1 4 6 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 reltablespace 26 -1 4 7 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 relpages 23 -1 4 8 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 reltuples 700 -1 4 9 0 -1 -1 FLOAT4PASSBYVAL p i t f f t 0 _null_));
DATA(insert ( 1259 reltoastrelid 26 -1 4 10 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 reltoastidxid 26 -1 4 11 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 relhasindex 16 -1 1 12 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1259 relisshared 16 -1 1 13 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1259 relkind 18 -1 1 14 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1259 relnatts 21 -1 2 15 0 -1 -1 t p s t f f t 0 _null_));
DATA(insert ( 1259 relchecks 21 -1 2 16 0 -1 -1 t p s t f f t 0 _null_));
DATA(insert ( 1259 relhasoids 16 -1 1 17 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1259 relhaspkey 16 -1 1 18 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1259 relhasrules 16 -1 1 19 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1259 relhastriggers 16 -1 1 20 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1259 relhassubclass 16 -1 1 21 0 -1 -1 t p c t f f t 0 _null_));
DATA(insert ( 1259 relfrozenxid 28 -1 4 22 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 relacl 1034 -1 -1 23 1 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1259 reloptions 1009 -1 -1 24 1 -1 -1 f x i f f f t 0 _null_));
DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0 _null_));
DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 _null_));
DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 _null_));
/* ----------------
* pg_index
@ -465,19 +462,19 @@ DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
* ----------------
*/
#define Schema_pg_index \
{ 0, {"indexrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indrelid"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indnatts"}, 21, -1, 2, 3, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
{ 0, {"indisunique"}, 16, -1, 1, 4, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indisprimary"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indisclustered"}, 16, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indisvalid"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indcheckxmin"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indisready"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 0, {"indkey"}, 22, -1, -1, 10, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indclass"}, 30, -1, -1, 11, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indoption"}, 22, -1, -1, 12, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
{ 0, {"indexprs"}, 25, -1, -1, 13, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 0, {"indpred"}, 25, -1, -1, 14, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
{ 0, {"indexrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 0, {"indrelid"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 0, {"indnatts"}, 21, -1, 2, 3, 0, -1, -1, true, 'p', 's', true, false, false, true, 0, { 0 } }, \
{ 0, {"indisunique"}, 16, -1, 1, 4, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 0, {"indisprimary"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 0, {"indisclustered"}, 16, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 0, {"indisvalid"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 0, {"indcheckxmin"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 0, {"indisready"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0, { 0 } }, \
{ 0, {"indkey"}, 22, -1, -1, 10, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 0, {"indclass"}, 30, -1, -1, 11, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 0, {"indoption"}, 22, -1, -1, 12, 1, -1, -1, false, 'p', 'i', true, false, false, true, 0, { 0 } }, \
{ 0, {"indexprs"}, 25, -1, -1, 13, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \
{ 0, {"indpred"}, 25, -1, -1, 14, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }
#endif /* PG_ATTRIBUTE_H */

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.111 2009/01/01 17:23:56 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.112 2009/01/22 20:16:09 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -123,7 +123,7 @@ typedef FormData_pg_class *Form_pg_class;
/* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 28 0 t f f f f 3 _null_ _null_ ));
DESCR("");
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 f f f f f 3 _null_ _null_ ));
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 18 0 f f f f f 3 _null_ _null_ ));
DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 25 0 t f f f f 3 _null_ _null_ ));
DESCR("");

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_shdepend.h,v 1.8 2009/01/01 17:23:58 momjian Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_shdepend.h,v 1.9 2009/01/22 20:16:09 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -39,10 +39,12 @@ CATALOG(pg_shdepend,1214) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
Oid dbid; /* OID of database containing object */
Oid classid; /* OID of table containing object */
Oid objid; /* OID of object itself */
int4 objsubid; /* column number, or 0 if not used */
/*
* Identification of the independent (referenced) object. This is always
* a shared object, so we need no database ID field.
* a shared object, so we need no database ID field. We don't bother
* with a sub-object ID either.
*/
Oid refclassid; /* OID of table containing object */
Oid refobjid; /* OID of object itself */
@ -65,13 +67,14 @@ typedef FormData_pg_shdepend *Form_pg_shdepend;
* compiler constants for pg_shdepend
* ----------------
*/
#define Natts_pg_shdepend 6
#define Natts_pg_shdepend 7
#define Anum_pg_shdepend_dbid 1
#define Anum_pg_shdepend_classid 2
#define Anum_pg_shdepend_objid 3
#define Anum_pg_shdepend_refclassid 4
#define Anum_pg_shdepend_refobjid 5
#define Anum_pg_shdepend_deptype 6
#define Anum_pg_shdepend_objsubid 4
#define Anum_pg_shdepend_refclassid 5
#define Anum_pg_shdepend_refobjid 6
#define Anum_pg_shdepend_deptype 7
/*

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.71 2009/01/22 19:16:31 heikki Exp $
* $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.72 2009/01/22 20:16:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -104,7 +104,8 @@ extern PGDLLIMPORT int SessionReplicationRole;
#define TRIGGER_FIRES_ON_REPLICA 'R'
#define TRIGGER_DISABLED 'D'
extern Oid CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid);
extern Oid CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid,
bool checkPermissions);
extern void DropTrigger(Oid relid, const char *trigname,
DropBehavior behavior, bool missing_ok);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.218 2009/01/01 17:24:00 momjian Exp $
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.219 2009/01/22 20:16:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -369,7 +369,7 @@ typedef enum NodeTag
T_FkConstraint,
T_PrivGrantee,
T_FuncWithArgs,
T_PrivTarget,
T_AccessPriv,
T_CreateOpClassItem,
T_InhRelation,
T_FunctionParameter,

View File

@ -13,13 +13,14 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.388 2009/01/16 13:27:24 heikki Exp $
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.389 2009/01/22 20:16:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSENODES_H
#define PARSENODES_H
#include "nodes/bitmapset.h"
#include "nodes/primnodes.h"
#include "nodes/value.h"
@ -622,6 +623,15 @@ typedef struct XmlSerialize
* then do the permissions checks using the access rights of that user,
* not the current effective user ID. (This allows rules to act as
* setuid gateways.)
*
* For SELECT/INSERT/UPDATE permissions, if the user doesn't have
* table-wide permissions then it is sufficient to have the permissions
* on all columns identified in selectedCols (for SELECT) and/or
* modifiedCols (for INSERT/UPDATE; we can tell which from the query type).
* selectedCols and modifiedCols are bitmapsets, which cannot have negative
* integer members, so we subtract FirstLowInvalidHeapAttributeNumber from
* column numbers before storing them in these fields. A whole-row Var
* reference is represented by setting the bit for InvalidAttrNumber.
*--------------------
*/
typedef enum RTEKind
@ -644,7 +654,7 @@ typedef struct RangeTblEntry
/*
* XXX the fields applicable to only some rte kinds should be merged into
* a union. I didn't do this yet because the diffs would impact a lot of
* code that is being actively worked on. FIXME later.
* code that is being actively worked on. FIXME someday.
*/
/*
@ -705,6 +715,8 @@ typedef struct RangeTblEntry
bool inFromCl; /* present in FROM clause? */
AclMode requiredPerms; /* bitmask of required access permissions */
Oid checkAsUser; /* if valid, check access as this role */
Bitmapset *selectedCols; /* columns needing SELECT permission */
Bitmapset *modifiedCols; /* columns needing INSERT/UPDATE permission */
} RangeTblEntry;
/*
@ -1168,6 +1180,7 @@ typedef struct AlterDomainStmt
*/
typedef enum GrantObjectType
{
ACL_OBJECT_COLUMN, /* column */
ACL_OBJECT_RELATION, /* table, view */
ACL_OBJECT_SEQUENCE, /* sequence */
ACL_OBJECT_DATABASE, /* database */
@ -1186,8 +1199,8 @@ typedef struct GrantStmt
GrantObjectType objtype; /* kind of object being operated on */
List *objects; /* list of RangeVar nodes, FuncWithArgs nodes,
* or plain names (as Value strings) */
List *privileges; /* list of privilege names (as Strings) */
/* privileges == NIL denotes "all privileges" */
List *privileges; /* list of AccessPriv nodes */
/* privileges == NIL denotes ALL PRIVILEGES */
List *grantees; /* list of PrivGrantee nodes */
bool grant_option; /* grant or revoke grant option */
DropBehavior behavior; /* drop behavior (for REVOKE) */
@ -1211,18 +1224,27 @@ typedef struct FuncWithArgs
List *funcargs; /* list of Typename nodes */
} FuncWithArgs;
/* This is only used internally in gram.y. */
typedef struct PrivTarget
/*
* An access privilege, with optional list of column names
* priv_name == NULL denotes ALL PRIVILEGES (only used with a column list)
* cols == NIL denotes "all columns"
* Note that simple "ALL PRIVILEGES" is represented as a NIL list, not
* an AccessPriv with both fields null.
*/
typedef struct AccessPriv
{
NodeTag type;
GrantObjectType objtype;
List *objs;
} PrivTarget;
char *priv_name; /* string name of privilege */
List *cols; /* list of Value strings */
} AccessPriv;
/* ----------------------
* Grant/Revoke Role Statement
*
* Note: the lists of roles are lists of names, as Value strings
* Note: because of the parsing ambiguity with the GRANT <privileges>
* statement, granted_roles is a list of AccessPriv; the execution code
* should complain if any column lists appear. grantee_roles is a list
* of role names, as Value strings.
* ----------------------
*/
typedef struct GrantRoleStmt

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.60 2009/01/01 17:24:00 momjian Exp $
* $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.61 2009/01/22 20:16:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -33,6 +33,10 @@
* Note that neither relname nor refname of these entries are necessarily
* unique; searching the rtable by name is a bad idea.
*
* p_joinexprs: list of JoinExpr nodes associated with p_rtable entries.
* This is one-for-one with p_rtable, but contains NULLs for non-join
* RTEs, and may be shorter than p_rtable if the last RTE(s) aren't joins.
*
* p_joinlist: list of join items (RangeTblRef and JoinExpr nodes) that
* will become the fromlist of the query's top-level FromExpr node.
*
@ -77,6 +81,7 @@ typedef struct ParseState
struct ParseState *parentParseState; /* stack link */
const char *p_sourcetext; /* source text, or NULL if not available */
List *p_rtable; /* range table so far */
List *p_joinexprs; /* JoinExprs for RTE_JOIN p_rtable entries */
List *p_joinlist; /* join items so far (will become FromExpr
* node's fromlist) */
List *p_relnamespace; /* current namespace for relations */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.62 2009/01/01 17:24:00 momjian Exp $
* $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.63 2009/01/22 20:16:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -46,6 +46,8 @@ extern Node *qualifiedNameToVar(ParseState *pstate,
char *colname,
bool implicitRTEOK,
int location);
extern void markVarForSelectPriv(ParseState *pstate, Var *var,
RangeTblEntry *rte);
extern Relation parserOpenTable(ParseState *pstate, const RangeVar *relation,
int lockmode);
extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.106 2009/01/01 17:24:02 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.107 2009/01/22 20:16:09 tgl Exp $
*
* NOTES
* An ACL array is simply an array of AclItems, representing the union
@ -143,6 +143,7 @@ typedef ArrayType Acl;
/*
* Bitmasks defining "all rights" for each supported object type
*/
#define ACL_ALL_RIGHTS_COLUMN (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_REFERENCES)
#define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER)
#define ACL_ALL_RIGHTS_SEQUENCE (ACL_USAGE|ACL_SELECT|ACL_UPDATE)
#define ACL_ALL_RIGHTS_DATABASE (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
@ -172,6 +173,7 @@ typedef enum
/* currently it's only used to tell aclcheck_error what to say */
typedef enum AclObjectKind
{
ACL_KIND_COLUMN, /* pg_attribute */
ACL_KIND_CLASS, /* pg_class */
ACL_KIND_SEQUENCE, /* pg_sequence */
ACL_KIND_DATABASE, /* pg_database */
@ -195,9 +197,14 @@ typedef enum AclObjectKind
* The information about one Grant/Revoke statement, in internal format: object
* and grantees names have been turned into Oids, the privilege list is an
* AclMode bitmask. If 'privileges' is ACL_NO_RIGHTS (the 0 value) and
* all_privs is true, it will be internally turned into the right kind of
* all_privs is true, 'privileges' will be internally set to the right kind of
* ACL_ALL_RIGHTS_*, depending on the object type (NB - this will modify the
* InternalGrant struct!)
*
* Note: 'all_privs' and 'privileges' represent object-level privileges only.
* There might also be column-level privilege specifications, which are
* represented in col_privs (this is a list of untransformed AccessPriv nodes).
* Column privileges are only valid for objtype ACL_OBJECT_RELATION.
*/
typedef struct
{
@ -206,6 +213,7 @@ typedef struct
List *objects;
bool all_privs;
AclMode privileges;
List *col_privs;
List *grantees;
bool grant_option;
DropBehavior behavior;
@ -218,6 +226,8 @@ extern Acl *acldefault(GrantObjectType objtype, Oid ownerId);
extern Acl *aclupdate(const Acl *old_acl, const AclItem *mod_aip,
int modechg, Oid ownerId, DropBehavior behavior);
extern Acl *aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId);
extern Acl *aclcopy(const Acl *orig_acl);
extern Acl *aclconcat(const Acl *left_acl, const Acl *right_acl);
extern AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId,
AclMode mask, AclMaskHow how);
@ -253,6 +263,8 @@ extern Datum hash_aclitem(PG_FUNCTION_ARGS);
extern void ExecuteGrantStmt(GrantStmt *stmt);
extern void ExecGrantStmt_oids(InternalGrant *istmt);
extern AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum,
Oid roleid, AclMode mask, AclMaskHow how);
extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
AclMode mask, AclMaskHow how);
extern AclMode pg_database_aclmask(Oid db_oid, Oid roleid,
@ -270,6 +282,10 @@ extern AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
extern AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
AclMode mask, AclMaskHow how);
extern AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
Oid roleid, AclMode mode);
extern AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid,
AclMode mode, AclMaskHow how);
extern AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode);
extern AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode);
extern AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode);
@ -282,6 +298,9 @@ extern AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mod
extern void aclcheck_error(AclResult aclerr, AclObjectKind objectkind,
const char *objectname);
extern void aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind,
const char *objectname, const char *colname);
/* ownercheck routines just return true (owner) or false (not) */
extern bool pg_class_ownercheck(Oid class_oid, Oid roleid);
extern bool pg_type_ownercheck(Oid type_oid, Oid roleid);

View File

@ -68,21 +68,21 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "deptest_pkey" fo
GRANT ALL ON deptest1 TO regression_user2;
RESET SESSION AUTHORIZATION;
\z deptest1
Access privileges
Schema | Name | Type | Access privileges
--------+----------+-------+--------------------------------------------------
public | deptest1 | table | regression_user0=arwdDxt/regression_user0
: regression_user1=a*r*w*d*D*x*t*/regression_user0
: regression_user2=arwdDxt/regression_user1
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+----------+-------+--------------------------------------------------+--------------------------
public | deptest1 | table | regression_user0=arwdDxt/regression_user0 |
: regression_user1=a*r*w*d*D*x*t*/regression_user0
: regression_user2=arwdDxt/regression_user1
(1 row)
DROP OWNED BY regression_user1;
-- all grants revoked
\z deptest1
Access privileges
Schema | Name | Type | Access privileges
--------+----------+-------+-------------------------------------------
public | deptest1 | table | regression_user0=arwdDxt/regression_user0
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+----------+-------+-------------------------------------------+--------------------------
public | deptest1 | table | regression_user0=arwdDxt/regression_user0 |
(1 row)
-- table was dropped

View File

@ -246,6 +246,147 @@ SELECT * FROM atest2; -- ok
SELECT * FROM atestv2; -- fail (even though regressuser2 can access underlying atest2)
ERROR: permission denied for relation atest2
-- Test column level permissions
SET SESSION AUTHORIZATION regressuser1;
CREATE TABLE atest5 (one int, two int, three int);
CREATE TABLE atest6 (one int, two int, blue int);
GRANT SELECT (one), INSERT (two), UPDATE (three) ON atest5 TO regressuser4;
GRANT ALL (one) ON atest5 TO regressuser3;
INSERT INTO atest5 VALUES (1,2,3);
SET SESSION AUTHORIZATION regressuser4;
SELECT * FROM atest5; -- fail
ERROR: permission denied for relation atest5
SELECT one FROM atest5; -- ok
one
-----
1
(1 row)
SELECT two FROM atest5; -- fail
ERROR: permission denied for relation atest5
SELECT atest5 FROM atest5; -- fail
ERROR: permission denied for relation atest5
SELECT 1 FROM atest5; -- ok
?column?
----------
1
(1 row)
SELECT 1 FROM atest5 a JOIN atest5 b USING (one); -- ok
?column?
----------
1
(1 row)
SELECT 1 FROM atest5 a JOIN atest5 b USING (two); -- fail
ERROR: permission denied for relation atest5
SELECT 1 FROM atest5 a NATURAL JOIN atest5 b; -- fail
ERROR: permission denied for relation atest5
SELECT (j.*) IS NULL FROM (atest5 a JOIN atest5 b USING (one)) j; -- fail
ERROR: permission denied for relation atest5
SELECT 1 FROM atest5 WHERE two = 2; -- fail
ERROR: permission denied for relation atest5
SELECT * FROM atest1, atest5; -- fail
ERROR: permission denied for relation atest5
SELECT atest1.* FROM atest1, atest5; -- ok
a | b
---+-----
1 | two
1 | two
(2 rows)
SELECT atest1.*,atest5.one FROM atest1, atest5; -- ok
a | b | one
---+-----+-----
1 | two | 1
1 | two | 1
(2 rows)
SELECT atest1.*,atest5.one FROM atest1 JOIN atest5 ON (atest1.a = atest5.two); -- fail
ERROR: permission denied for relation atest5
SELECT atest1.*,atest5.one FROM atest1 JOIN atest5 ON (atest1.a = atest5.one); -- ok
a | b | one
---+-----+-----
1 | two | 1
1 | two | 1
(2 rows)
SELECT one, two FROM atest5; -- fail
ERROR: permission denied for relation atest5
SET SESSION AUTHORIZATION regressuser1;
GRANT SELECT (one,two) ON atest6 TO regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT one, two FROM atest5 NATURAL JOIN atest6; -- fail still
ERROR: permission denied for relation atest5
SET SESSION AUTHORIZATION regressuser1;
GRANT SELECT (two) ON atest5 TO regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT one, two FROM atest5 NATURAL JOIN atest6; -- ok now
one | two
-----+-----
(0 rows)
-- test column-level privileges for INSERT and UPDATE
INSERT INTO atest5 (two) VALUES (3); -- ok
INSERT INTO atest5 (three) VALUES (4); -- fail
ERROR: permission denied for relation atest5
INSERT INTO atest5 VALUES (5,5,5); -- fail
ERROR: permission denied for relation atest5
UPDATE atest5 SET three = 10; -- ok
UPDATE atest5 SET one = 8; -- fail
ERROR: permission denied for relation atest5
UPDATE atest5 SET three = 5, one = 2; -- fail
ERROR: permission denied for relation atest5
SET SESSION AUTHORIZATION regressuser1;
REVOKE ALL (one) ON atest5 FROM regressuser4;
GRANT SELECT (one,two,blue) ON atest6 TO regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT one FROM atest5; -- fail
ERROR: permission denied for relation atest5
UPDATE atest5 SET one = 1; -- fail
ERROR: permission denied for relation atest5
SELECT atest6 FROM atest6; -- ok
atest6
--------
(0 rows)
-- test column-level privileges when involved with DELETE
SET SESSION AUTHORIZATION regressuser1;
ALTER TABLE atest6 ADD COLUMN three integer;
GRANT DELETE ON atest5 TO regressuser3;
GRANT SELECT (two) ON atest5 TO regressuser3;
REVOKE ALL (one) ON atest5 FROM regressuser3;
GRANT SELECT (one) ON atest5 TO regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT atest6 FROM atest6; -- fail
ERROR: permission denied for relation atest6
SELECT one FROM atest5 NATURAL JOIN atest6; -- fail
ERROR: permission denied for relation atest5
SET SESSION AUTHORIZATION regressuser1;
ALTER TABLE atest6 DROP COLUMN three;
SET SESSION AUTHORIZATION regressuser4;
SELECT atest6 FROM atest6; -- ok
atest6
--------
(0 rows)
SELECT one FROM atest5 NATURAL JOIN atest6; -- ok
one
-----
(0 rows)
SET SESSION AUTHORIZATION regressuser1;
ALTER TABLE atest6 DROP COLUMN two;
REVOKE SELECT (one,blue) ON atest6 FROM regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT * FROM atest6; -- fail
ERROR: permission denied for relation atest6
SELECT 1 FROM atest6; -- fail
ERROR: permission denied for relation atest6
SET SESSION AUTHORIZATION regressuser3;
DELETE FROM atest5 WHERE one = 1; -- fail
ERROR: permission denied for relation atest5
DELETE FROM atest5 WHERE two = 2; -- ok
-- privileges on functions, languages
-- switch to superuser
\c -
@ -642,6 +783,8 @@ DROP TABLE atest1;
DROP TABLE atest2;
DROP TABLE atest3;
DROP TABLE atest4;
DROP TABLE atest5;
DROP TABLE atest6;
DROP GROUP regressgroup1;
DROP GROUP regressgroup2;
REVOKE USAGE ON LANGUAGE sql FROM regressuser1;

View File

@ -171,6 +171,93 @@ SELECT * FROM atestv4; -- ok (even though regressuser2 cannot access underlying
SELECT * FROM atest2; -- ok
SELECT * FROM atestv2; -- fail (even though regressuser2 can access underlying atest2)
-- Test column level permissions
SET SESSION AUTHORIZATION regressuser1;
CREATE TABLE atest5 (one int, two int, three int);
CREATE TABLE atest6 (one int, two int, blue int);
GRANT SELECT (one), INSERT (two), UPDATE (three) ON atest5 TO regressuser4;
GRANT ALL (one) ON atest5 TO regressuser3;
INSERT INTO atest5 VALUES (1,2,3);
SET SESSION AUTHORIZATION regressuser4;
SELECT * FROM atest5; -- fail
SELECT one FROM atest5; -- ok
SELECT two FROM atest5; -- fail
SELECT atest5 FROM atest5; -- fail
SELECT 1 FROM atest5; -- ok
SELECT 1 FROM atest5 a JOIN atest5 b USING (one); -- ok
SELECT 1 FROM atest5 a JOIN atest5 b USING (two); -- fail
SELECT 1 FROM atest5 a NATURAL JOIN atest5 b; -- fail
SELECT (j.*) IS NULL FROM (atest5 a JOIN atest5 b USING (one)) j; -- fail
SELECT 1 FROM atest5 WHERE two = 2; -- fail
SELECT * FROM atest1, atest5; -- fail
SELECT atest1.* FROM atest1, atest5; -- ok
SELECT atest1.*,atest5.one FROM atest1, atest5; -- ok
SELECT atest1.*,atest5.one FROM atest1 JOIN atest5 ON (atest1.a = atest5.two); -- fail
SELECT atest1.*,atest5.one FROM atest1 JOIN atest5 ON (atest1.a = atest5.one); -- ok
SELECT one, two FROM atest5; -- fail
SET SESSION AUTHORIZATION regressuser1;
GRANT SELECT (one,two) ON atest6 TO regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT one, two FROM atest5 NATURAL JOIN atest6; -- fail still
SET SESSION AUTHORIZATION regressuser1;
GRANT SELECT (two) ON atest5 TO regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT one, two FROM atest5 NATURAL JOIN atest6; -- ok now
-- test column-level privileges for INSERT and UPDATE
INSERT INTO atest5 (two) VALUES (3); -- ok
INSERT INTO atest5 (three) VALUES (4); -- fail
INSERT INTO atest5 VALUES (5,5,5); -- fail
UPDATE atest5 SET three = 10; -- ok
UPDATE atest5 SET one = 8; -- fail
UPDATE atest5 SET three = 5, one = 2; -- fail
SET SESSION AUTHORIZATION regressuser1;
REVOKE ALL (one) ON atest5 FROM regressuser4;
GRANT SELECT (one,two,blue) ON atest6 TO regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT one FROM atest5; -- fail
UPDATE atest5 SET one = 1; -- fail
SELECT atest6 FROM atest6; -- ok
-- test column-level privileges when involved with DELETE
SET SESSION AUTHORIZATION regressuser1;
ALTER TABLE atest6 ADD COLUMN three integer;
GRANT DELETE ON atest5 TO regressuser3;
GRANT SELECT (two) ON atest5 TO regressuser3;
REVOKE ALL (one) ON atest5 FROM regressuser3;
GRANT SELECT (one) ON atest5 TO regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT atest6 FROM atest6; -- fail
SELECT one FROM atest5 NATURAL JOIN atest6; -- fail
SET SESSION AUTHORIZATION regressuser1;
ALTER TABLE atest6 DROP COLUMN three;
SET SESSION AUTHORIZATION regressuser4;
SELECT atest6 FROM atest6; -- ok
SELECT one FROM atest5 NATURAL JOIN atest6; -- ok
SET SESSION AUTHORIZATION regressuser1;
ALTER TABLE atest6 DROP COLUMN two;
REVOKE SELECT (one,blue) ON atest6 FROM regressuser4;
SET SESSION AUTHORIZATION regressuser4;
SELECT * FROM atest6; -- fail
SELECT 1 FROM atest6; -- fail
SET SESSION AUTHORIZATION regressuser3;
DELETE FROM atest5 WHERE one = 1; -- fail
DELETE FROM atest5 WHERE two = 2; -- ok
-- privileges on functions, languages
@ -369,6 +456,8 @@ DROP TABLE atest1;
DROP TABLE atest2;
DROP TABLE atest3;
DROP TABLE atest4;
DROP TABLE atest5;
DROP TABLE atest6;
DROP GROUP regressgroup1;
DROP GROUP regressgroup2;