1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* indexing.c
|
2002-08-05 05:29:17 +02:00
|
|
|
* This file contains routines to support indexes defined on system
|
1997-09-07 07:04:48 +02:00
|
|
|
* catalogs.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2017-01-03 19:48:53 +01:00
|
|
|
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/catalog/indexing.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1998-04-27 06:08:07 +02:00
|
|
|
#include "postgres.h"
|
|
|
|
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
1998-04-27 06:08:07 +02:00
|
|
|
#include "catalog/index.h"
|
|
|
|
#include "catalog/indexing.h"
|
2002-08-05 05:29:17 +02:00
|
|
|
#include "executor/executor.h"
|
2011-02-23 18:18:09 +01:00
|
|
|
#include "utils/rel.h"
|
This patch implements ORACLE's COMMENT SQL command.
>From the ORACLE 7 SQL Language Reference Manual:
-----------------------------------------------------
COMMENT
Purpose:
To add a comment about a table, view, snapshot, or
column into the data dictionary.
Prerequisites:
The table, view, or snapshot must be in your own
schema
or you must have COMMENT ANY TABLE system privilege.
Syntax:
COMMENT ON [ TABLE table ] |
[ COLUMN table.column] IS 'text'
You can effectively drop a comment from the database
by setting it to the empty string ''.
-----------------------------------------------------
Example:
COMMENT ON TABLE workorders IS
'Maintains base records for workorder information';
COMMENT ON COLUMN workorders.hours IS
'Number of hours the engineer worked on the task';
to drop a comment:
COMMENT ON COLUMN workorders.hours IS '';
The current patch will simply perform the insert into
pg_description, as per the TODO. And, of course, when
the table is dropped, any comments relating to it
or any of its attributes are also dropped. I haven't
looked at the ODBC source yet, but I do know from
an ODBC client standpoint that the standard does
support the notion of table and column comments.
Hopefully the ODBC driver is already fetching these
values from pg_description, but if not, it should be
trivial.
Hope this makes the grade,
Mike Mascari
(mascarim@yahoo.com)
1999-10-15 03:49:49 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
2002-08-05 05:29:17 +02:00
|
|
|
* CatalogOpenIndexes - open the indexes on a system catalog.
|
|
|
|
*
|
|
|
|
* When inserting or updating tuples in a system catalog, call this
|
|
|
|
* to prepare to update the indexes for the catalog.
|
|
|
|
*
|
|
|
|
* In the current implementation, we share code for opening/closing the
|
|
|
|
* indexes with execUtils.c. But we do not use ExecInsertIndexTuples,
|
|
|
|
* because we don't want to create an EState. This implies that we
|
2009-12-07 06:22:23 +01:00
|
|
|
* do not support partial or expressional indexes on system catalogs,
|
|
|
|
* nor can we support generalized exclusion constraints.
|
2003-05-28 18:04:02 +02:00
|
|
|
* This could be fixed with localized changes here if we wanted to pay
|
|
|
|
* the extra overhead of building an EState.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2002-08-05 05:29:17 +02:00
|
|
|
CatalogIndexState
|
|
|
|
CatalogOpenIndexes(Relation heapRel)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2002-08-05 05:29:17 +02:00
|
|
|
ResultRelInfo *resultRelInfo;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-08-05 05:29:17 +02:00
|
|
|
resultRelInfo = makeNode(ResultRelInfo);
|
|
|
|
resultRelInfo->ri_RangeTableIndex = 1; /* dummy */
|
|
|
|
resultRelInfo->ri_RelationDesc = heapRel;
|
2002-09-04 22:31:48 +02:00
|
|
|
resultRelInfo->ri_TrigDesc = NULL; /* we don't fire triggers */
|
2002-08-05 05:29:17 +02:00
|
|
|
|
Add support for INSERT ... ON CONFLICT DO NOTHING/UPDATE.
The newly added ON CONFLICT clause allows to specify an alternative to
raising a unique or exclusion constraint violation error when inserting.
ON CONFLICT refers to constraints that can either be specified using a
inference clause (by specifying the columns of a unique constraint) or
by naming a unique or exclusion constraint. DO NOTHING avoids the
constraint violation, without touching the pre-existing row. DO UPDATE
SET ... [WHERE ...] updates the pre-existing tuple, and has access to
both the tuple proposed for insertion and the existing tuple; the
optional WHERE clause can be used to prevent an update from being
executed. The UPDATE SET and WHERE clauses have access to the tuple
proposed for insertion using the "magic" EXCLUDED alias, and to the
pre-existing tuple using the table name or its alias.
This feature is often referred to as upsert.
This is implemented using a new infrastructure called "speculative
insertion". It is an optimistic variant of regular insertion that first
does a pre-check for existing tuples and then attempts an insert. If a
violating tuple was inserted concurrently, the speculatively inserted
tuple is deleted and a new attempt is made. If the pre-check finds a
matching tuple the alternative DO NOTHING or DO UPDATE action is taken.
If the insertion succeeds without detecting a conflict, the tuple is
deemed inserted.
To handle the possible ambiguity between the excluded alias and a table
named excluded, and for convenience with long relation names, INSERT
INTO now can alias its target table.
Bumps catversion as stored rules change.
Author: Peter Geoghegan, with significant contributions from Heikki
Linnakangas and Andres Freund. Testing infrastructure by Jeff Janes.
Reviewed-By: Heikki Linnakangas, Andres Freund, Robert Haas, Simon Riggs,
Dean Rasheed, Stephen Frost and many others.
2015-05-08 05:31:36 +02:00
|
|
|
ExecOpenIndices(resultRelInfo, false);
|
2002-08-05 05:29:17 +02:00
|
|
|
|
|
|
|
return resultRelInfo;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2002-08-05 05:29:17 +02:00
|
|
|
* CatalogCloseIndexes - clean up resources allocated by CatalogOpenIndexes
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
2002-08-05 05:29:17 +02:00
|
|
|
CatalogCloseIndexes(CatalogIndexState indstate)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2002-08-05 05:29:17 +02:00
|
|
|
ExecCloseIndices(indstate);
|
|
|
|
pfree(indstate);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2002-08-05 05:29:17 +02:00
|
|
|
* CatalogIndexInsert - insert index entries for one catalog tuple
|
2000-07-15 00:18:02 +02:00
|
|
|
*
|
2002-08-05 05:29:17 +02:00
|
|
|
* This should be called for each inserted or updated catalog tuple.
|
2000-07-15 00:18:02 +02:00
|
|
|
*
|
2002-08-05 05:29:17 +02:00
|
|
|
* This is effectively a cut-down version of ExecInsertIndexTuples.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2017-02-01 23:18:36 +01:00
|
|
|
static void
|
2002-08-05 05:29:17 +02:00
|
|
|
CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2002-08-05 05:29:17 +02:00
|
|
|
int i;
|
|
|
|
int numIndexes;
|
|
|
|
RelationPtr relationDescs;
|
|
|
|
Relation heapRelation;
|
2005-03-16 22:38:10 +01:00
|
|
|
TupleTableSlot *slot;
|
2002-08-05 05:29:17 +02:00
|
|
|
IndexInfo **indexInfoArray;
|
2005-03-21 02:24:04 +01:00
|
|
|
Datum values[INDEX_MAX_KEYS];
|
|
|
|
bool isnull[INDEX_MAX_KEYS];
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2007-09-20 19:56:33 +02:00
|
|
|
/* HOT update does not require index inserts */
|
|
|
|
if (HeapTupleIsHeapOnly(heapTuple))
|
|
|
|
return;
|
|
|
|
|
2002-08-05 05:29:17 +02:00
|
|
|
/*
|
2005-03-16 22:38:10 +01:00
|
|
|
* Get information from the state structure. Fall out if nothing to do.
|
2002-08-05 05:29:17 +02:00
|
|
|
*/
|
|
|
|
numIndexes = indstate->ri_NumIndices;
|
2005-03-16 22:38:10 +01:00
|
|
|
if (numIndexes == 0)
|
|
|
|
return;
|
2002-08-05 05:29:17 +02:00
|
|
|
relationDescs = indstate->ri_IndexRelationDescs;
|
|
|
|
indexInfoArray = indstate->ri_IndexRelationInfo;
|
|
|
|
heapRelation = indstate->ri_RelationDesc;
|
2005-03-16 22:38:10 +01:00
|
|
|
|
|
|
|
/* Need a slot to hold the tuple being examined */
|
|
|
|
slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
|
|
|
|
ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-08-05 05:29:17 +02:00
|
|
|
/*
|
|
|
|
* for each index, form and insert the index tuple
|
|
|
|
*/
|
|
|
|
for (i = 0; i < numIndexes; i++)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-15 00:18:02 +02:00
|
|
|
IndexInfo *indexInfo;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-08-05 05:29:17 +02:00
|
|
|
indexInfo = indexInfoArray[i];
|
1999-05-25 18:15:34 +02:00
|
|
|
|
2007-09-20 19:56:33 +02:00
|
|
|
/* If the index is marked as read-only, ignore it */
|
|
|
|
if (!indexInfo->ii_ReadyForInserts)
|
|
|
|
continue;
|
|
|
|
|
2003-05-28 18:04:02 +02:00
|
|
|
/*
|
|
|
|
* Expressional and partial indexes on system catalogs are not
|
2009-12-07 06:22:23 +01:00
|
|
|
* supported, nor exclusion constraints, nor deferred uniqueness
|
2003-05-28 18:04:02 +02:00
|
|
|
*/
|
|
|
|
Assert(indexInfo->ii_Expressions == NIL);
|
2002-08-05 05:29:17 +02:00
|
|
|
Assert(indexInfo->ii_Predicate == NIL);
|
2009-12-07 06:22:23 +01:00
|
|
|
Assert(indexInfo->ii_ExclusionOps == NULL);
|
|
|
|
Assert(relationDescs[i]->rd_index->indimmediate);
|
2002-08-05 05:29:17 +02:00
|
|
|
|
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* FormIndexDatum fills in its values and isnull parameters with the
|
|
|
|
* appropriate values for the column(s) of the index.
|
2002-08-05 05:29:17 +02:00
|
|
|
*/
|
2000-07-15 00:18:02 +02:00
|
|
|
FormIndexDatum(indexInfo,
|
2005-03-16 22:38:10 +01:00
|
|
|
slot,
|
2003-05-28 18:04:02 +02:00
|
|
|
NULL, /* no expression eval to do */
|
2005-03-21 02:24:04 +01:00
|
|
|
values,
|
|
|
|
isnull);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-08-05 05:29:17 +02:00
|
|
|
/*
|
|
|
|
* The index AM does the rest.
|
|
|
|
*/
|
2005-03-21 02:24:04 +01:00
|
|
|
index_insert(relationDescs[i], /* index relation */
|
2005-10-15 04:49:52 +02:00
|
|
|
values, /* array of index Datums */
|
|
|
|
isnull, /* is-null flags */
|
2005-03-21 02:24:04 +01:00
|
|
|
&(heapTuple->t_self), /* tid of heap tuple */
|
|
|
|
heapRelation,
|
2009-07-29 22:56:21 +02:00
|
|
|
relationDescs[i]->rd_index->indisunique ?
|
Allow index AMs to cache data across aminsert calls within a SQL command.
It's always been possible for index AMs to cache data across successive
amgettuple calls within a single SQL command: the IndexScanDesc.opaque
field is meant for precisely that. However, no comparable facility
exists for amortizing setup work across successive aminsert calls.
This patch adds such a feature and teaches GIN, GIST, and BRIN to use it
to amortize catalog lookups they'd previously been doing on every call.
(The other standard index AMs keep everything they need in the relcache,
so there's little to improve there.)
For GIN, the overall improvement in a statement that inserts many rows
can be as much as 10%, though it seems a bit less for the other two.
In addition, this makes a really significant difference in runtime
for CLOBBER_CACHE_ALWAYS tests, since in those builds the repeated
catalog lookups are vastly more expensive.
The reason this has been hard up to now is that the aminsert function is
not passed any useful place to cache per-statement data. What I chose to
do is to add suitable fields to struct IndexInfo and pass that to aminsert.
That's not widening the index AM API very much because IndexInfo is already
within the ken of ambuild; in fact, by passing the same info to aminsert
as to ambuild, this is really removing an inconsistency in the AM API.
Discussion: https://postgr.es/m/27568.1486508680@sss.pgh.pa.us
2017-02-09 17:52:12 +01:00
|
|
|
UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
|
|
|
|
indexInfo);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2005-03-16 22:38:10 +01:00
|
|
|
|
|
|
|
ExecDropSingleTupleTableSlot(slot);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2002-08-05 05:29:17 +02:00
|
|
|
|
|
|
|
/*
|
2017-01-31 22:42:24 +01:00
|
|
|
* CatalogTupleInsert - do heap and indexing work for a new catalog tuple
|
2002-08-05 05:29:17 +02:00
|
|
|
*
|
2017-02-01 23:18:36 +01:00
|
|
|
* Insert the tuple data in "tup" into the specified catalog relation.
|
|
|
|
* The Oid of the inserted tuple is returned.
|
|
|
|
*
|
2017-01-31 22:42:24 +01:00
|
|
|
* This is a convenience routine for the common case of inserting a single
|
|
|
|
* tuple in a system catalog; it inserts a new heap tuple, keeping indexes
|
2017-02-01 23:18:36 +01:00
|
|
|
* current. Avoid using it for multiple tuples, since opening the indexes
|
|
|
|
* and building the index info structures is moderately expensive.
|
|
|
|
* (Use CatalogTupleInsertWithInfo in such cases.)
|
2017-01-31 22:42:24 +01:00
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
CatalogTupleInsert(Relation heapRel, HeapTuple tup)
|
|
|
|
{
|
|
|
|
CatalogIndexState indstate;
|
2017-02-01 23:18:36 +01:00
|
|
|
Oid oid;
|
2017-01-31 22:42:24 +01:00
|
|
|
|
|
|
|
indstate = CatalogOpenIndexes(heapRel);
|
|
|
|
|
|
|
|
oid = simple_heap_insert(heapRel, tup);
|
|
|
|
|
|
|
|
CatalogIndexInsert(indstate, tup);
|
|
|
|
CatalogCloseIndexes(indstate);
|
|
|
|
|
|
|
|
return oid;
|
|
|
|
}
|
|
|
|
|
2017-02-01 23:18:36 +01:00
|
|
|
/*
|
|
|
|
* CatalogTupleInsertWithInfo - as above, but with caller-supplied index info
|
|
|
|
*
|
|
|
|
* This should be used when it's important to amortize CatalogOpenIndexes/
|
|
|
|
* CatalogCloseIndexes work across multiple insertions. At some point we
|
|
|
|
* might cache the CatalogIndexState data somewhere (perhaps in the relcache)
|
|
|
|
* so that callers needn't trouble over this ... but we don't do so today.
|
|
|
|
*/
|
|
|
|
Oid
|
|
|
|
CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
|
|
|
|
CatalogIndexState indstate)
|
|
|
|
{
|
|
|
|
Oid oid;
|
|
|
|
|
|
|
|
oid = simple_heap_insert(heapRel, tup);
|
|
|
|
|
|
|
|
CatalogIndexInsert(indstate, tup);
|
|
|
|
|
|
|
|
return oid;
|
|
|
|
}
|
|
|
|
|
2017-01-31 22:42:24 +01:00
|
|
|
/*
|
|
|
|
* CatalogTupleUpdate - do heap and indexing work for updating a catalog tuple
|
|
|
|
*
|
2017-02-01 23:18:36 +01:00
|
|
|
* Update the tuple identified by "otid", replacing it with the data in "tup".
|
|
|
|
*
|
2017-01-31 22:42:24 +01:00
|
|
|
* This is a convenience routine for the common case of updating a single
|
2017-02-01 23:18:36 +01:00
|
|
|
* tuple in a system catalog; it updates one heap tuple, keeping indexes
|
|
|
|
* current. Avoid using it for multiple tuples, since opening the indexes
|
|
|
|
* and building the index info structures is moderately expensive.
|
|
|
|
* (Use CatalogTupleUpdateWithInfo in such cases.)
|
2002-08-05 05:29:17 +02:00
|
|
|
*/
|
|
|
|
void
|
2017-01-31 22:42:24 +01:00
|
|
|
CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
|
2002-08-05 05:29:17 +02:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
CatalogIndexState indstate;
|
2002-08-05 05:29:17 +02:00
|
|
|
|
|
|
|
indstate = CatalogOpenIndexes(heapRel);
|
2017-01-31 22:42:24 +01:00
|
|
|
|
|
|
|
simple_heap_update(heapRel, otid, tup);
|
|
|
|
|
|
|
|
CatalogIndexInsert(indstate, tup);
|
2002-08-05 05:29:17 +02:00
|
|
|
CatalogCloseIndexes(indstate);
|
|
|
|
}
|
2017-02-01 22:13:30 +01:00
|
|
|
|
2017-02-01 23:18:36 +01:00
|
|
|
/*
|
|
|
|
* CatalogTupleUpdateWithInfo - as above, but with caller-supplied index info
|
|
|
|
*
|
|
|
|
* This should be used when it's important to amortize CatalogOpenIndexes/
|
|
|
|
* CatalogCloseIndexes work across multiple updates. At some point we
|
|
|
|
* might cache the CatalogIndexState data somewhere (perhaps in the relcache)
|
|
|
|
* so that callers needn't trouble over this ... but we don't do so today.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup,
|
|
|
|
CatalogIndexState indstate)
|
|
|
|
{
|
|
|
|
simple_heap_update(heapRel, otid, tup);
|
|
|
|
|
|
|
|
CatalogIndexInsert(indstate, tup);
|
|
|
|
}
|
|
|
|
|
2017-02-01 22:13:30 +01:00
|
|
|
/*
|
|
|
|
* CatalogTupleDelete - do heap and indexing work for deleting a catalog tuple
|
|
|
|
*
|
2017-02-01 23:18:36 +01:00
|
|
|
* Delete the tuple identified by "tid" in the specified catalog.
|
2017-02-01 22:13:30 +01:00
|
|
|
*
|
|
|
|
* With Postgres heaps, there is no index work to do at deletion time;
|
|
|
|
* cleanup will be done later by VACUUM. However, callers of this function
|
|
|
|
* shouldn't have to know that; we'd like a uniform abstraction for all
|
|
|
|
* catalog tuple changes. Hence, provide this currently-trivial wrapper.
|
2017-02-01 23:18:36 +01:00
|
|
|
*
|
|
|
|
* The abstraction is a bit leaky in that we don't provide an optimized
|
|
|
|
* CatalogTupleDeleteWithInfo version, because there is currently nothing to
|
|
|
|
* optimize. If we ever need that, rather than touching a lot of call sites,
|
|
|
|
* it might be better to do something about caching CatalogIndexState.
|
2017-02-01 22:13:30 +01:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
CatalogTupleDelete(Relation heapRel, ItemPointer tid)
|
|
|
|
{
|
|
|
|
simple_heap_delete(heapRel, tid);
|
|
|
|
}
|