Support column-level privileges, as required by SQL standard.
Stephen Frost, with help from KaiGai Kohei and others
This commit is contained in:
parent
bf136cf6e3
commit
3cb5d6580a
@ -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>
|
||||
|
@ -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>
|
||||
=> \z mytable
|
||||
Access privileges
|
||||
Schema | Name | Type | Access privileges
|
||||
--------+---------+-------+-----------------------
|
||||
public | mytable | table | miriam=arwdDxt/miriam
|
||||
: =r/miriam
|
||||
: admin=arw/miriam
|
||||
=> \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,
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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),
|
||||
|
@ -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
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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? */
|
||||
|
@ -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));
|
||||
|
@ -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?
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
12
src/backend/utils/cache/relcache.c
vendored
12
src/backend/utils/cache/relcache.c
vendored
@ -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 */
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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"),
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
|
@ -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("");
|
||||
|
@ -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
|
||||
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user