Skip to content

Commit a3519a2

Browse files
author
Hiroshi Inoue
committed
Allow
CREATE VIEW as SELECT CTID, .... SELECT currtid( a view, ..).
1 parent 7942084 commit a3519a2

File tree

2 files changed

+99
-33
lines changed

2 files changed

+99
-33
lines changed

src/backend/catalog/heap.c

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.201 2002/05/21 22:05:53 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.202 2002/05/22 07:46:58 inoue Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -353,7 +353,7 @@ heap_storage_create(Relation rel)
353353
* --------------------------------
354354
*/
355355
static void
356-
CheckAttributeNames(TupleDesc tupdesc, bool relhasoids)
356+
CheckAttributeNames(TupleDesc tupdesc, bool relhasoids, int relkind)
357357
{
358358
int i;
359359
int j;
@@ -365,17 +365,18 @@ CheckAttributeNames(TupleDesc tupdesc, bool relhasoids)
365365
* also, warn user if attribute to be created has an unknown typid
366366
* (usually as a result of a 'retrieve into' - jolly
367367
*/
368-
for (i = 0; i < natts; i++)
369-
{
370-
if (SystemAttributeByName(NameStr(tupdesc->attrs[i]->attname),
368+
if (relkind != RELKIND_VIEW)
369+
for (i = 0; i < natts; i++)
370+
{
371+
if (SystemAttributeByName(NameStr(tupdesc->attrs[i]->attname),
371372
relhasoids) != NULL)
372-
elog(ERROR, "name of column \"%s\" conflicts with an existing system column",
373+
elog(ERROR, "name of column \"%s\" conflicts with an existing system column",
373374
NameStr(tupdesc->attrs[i]->attname));
374-
if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
375-
elog(WARNING, "Attribute '%s' has an unknown type"
375+
if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
376+
elog(WARNING, "Attribute '%s' has an unknown type"
376377
"\n\tProceeding with relation creation anyway",
377378
NameStr(tupdesc->attrs[i]->attname));
378-
}
379+
}
379380

380381
/*
381382
* next check for repeated attribute names
@@ -402,7 +403,8 @@ CheckAttributeNames(TupleDesc tupdesc, bool relhasoids)
402403
static void
403404
AddNewAttributeTuples(Oid new_rel_oid,
404405
TupleDesc tupdesc,
405-
bool relhasoids)
406+
bool relhasoids,
407+
int relkind)
406408
{
407409
Form_pg_attribute *dpp;
408410
int i;
@@ -453,36 +455,36 @@ AddNewAttributeTuples(Oid new_rel_oid,
453455
* next we add the system attributes. Skip OID if rel has no OIDs.
454456
*/
455457
dpp = SysAtt;
456-
for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
457-
{
458-
if (relhasoids || (*dpp)->attnum != ObjectIdAttributeNumber)
458+
if (relkind != RELKIND_VIEW)
459+
for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
459460
{
460-
Form_pg_attribute attStruct;
461+
if (relhasoids || (*dpp)->attnum != ObjectIdAttributeNumber)
462+
{
463+
Form_pg_attribute attStruct;
461464

462-
tup = heap_addheader(Natts_pg_attribute,
465+
tup = heap_addheader(Natts_pg_attribute,
463466
ATTRIBUTE_TUPLE_SIZE,
464467
(void *) *dpp);
465468

466-
/* Fill in the correct relation OID in the copied tuple */
467-
attStruct = (Form_pg_attribute) GETSTRUCT(tup);
468-
attStruct->attrelid = new_rel_oid;
469+
/* Fill in the correct relation OID in the copied tuple */
470+
attStruct = (Form_pg_attribute) GETSTRUCT(tup);
471+
attStruct->attrelid = new_rel_oid;
469472

470-
/*
471-
* Unneeded since they should be OK in the constant data
472-
* anyway
473-
*/
474-
/* attStruct->attstattarget = 0; */
475-
/* attStruct->attcacheoff = -1; */
473+
/*
474+
* Unneeded since they should be OK in the constant data
475+
* anyway
476+
*/
477+
/* attStruct->attstattarget = 0; */
478+
/* attStruct->attcacheoff = -1; */
476479

477-
simple_heap_insert(rel, tup);
480+
simple_heap_insert(rel, tup);
478481

479-
if (hasindex)
480-
CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
482+
if (hasindex)
483+
CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
481484

482-
heap_freetuple(tup);
485+
heap_freetuple(tup);
486+
}
483487
}
484-
dpp++;
485-
}
486488

487489
/*
488490
* close pg_attribute indices
@@ -664,7 +666,7 @@ heap_create_with_catalog(const char *relname,
664666
elog(ERROR, "Number of columns is out of range (1 to %d)",
665667
MaxHeapAttributeNumber);
666668

667-
CheckAttributeNames(tupdesc, relhasoids);
669+
CheckAttributeNames(tupdesc, relhasoids, relkind);
668670

669671
if (get_relname_relid(relname, relnamespace))
670672
elog(ERROR, "Relation '%s' already exists", relname);
@@ -717,7 +719,7 @@ heap_create_with_catalog(const char *relname,
717719
* now add tuples to pg_attribute for the attributes in our new
718720
* relation.
719721
*/
720-
AddNewAttributeTuples(new_rel_oid, new_rel_desc->rd_att, relhasoids);
722+
AddNewAttributeTuples(new_rel_oid, new_rel_desc->rd_att, relhasoids, relkind);
721723

722724
/*
723725
* store constraints and defaults passed in the tupdesc, if any.

src/backend/utils/adt/tid.c

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.29 2002/03/30 01:02:41 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.30 2002/05/22 07:46:58 inoue Exp $
1212
*
1313
* NOTES
1414
* input routine largely stolen from boxin().
@@ -21,6 +21,7 @@
2121
#include "access/heapam.h"
2222
#include "catalog/namespace.h"
2323
#include "utils/builtins.h"
24+
#include "catalog/pg_type.h"
2425

2526
#define DatumGetItemPointer(X) ((ItemPointer) DatumGetPointer(X))
2627
#define ItemPointerGetDatum(X) PointerGetDatum(X)
@@ -133,6 +134,65 @@ setLastTid(const ItemPointer tid)
133134
Current_last_tid = *tid;
134135
}
135136

137+
/*
138+
* Handle CTIDs of views.
139+
* CTID should be defined in the view and it must
140+
* correspond to the CTID of a base relation.
141+
*/
142+
static Datum
143+
currtid_for_view(Relation viewrel, ItemPointer tid)
144+
{
145+
TupleDesc att = RelationGetDescr(viewrel);
146+
RuleLock *rulelock;
147+
RewriteRule *rewrite;
148+
int i, natts = att->natts, tididx = -1;
149+
150+
for (i = 0; i < natts ; i++)
151+
{
152+
if (strcasecmp(NameStr(att->attrs[i]->attname), "ctid") == 0)
153+
{
154+
if (att->attrs[i]->atttypid != TIDOID)
155+
elog(ERROR, "ctid isn't of type TID");
156+
tididx = i;
157+
}
158+
}
159+
if (tididx < 0)
160+
elog(ERROR, "currtid can't handle views with no CTID");
161+
if (rulelock = viewrel->rd_rules, !rulelock)
162+
elog(ERROR, "the view has no rules");
163+
for (i = 0; i < rulelock->numLocks; i++)
164+
{
165+
rewrite = rulelock->rules[i];
166+
if (rewrite->event == CMD_SELECT)
167+
{
168+
Query *query;
169+
TargetEntry *tle;
170+
171+
if (length(rewrite->actions) != 1)
172+
elog(ERROR, "only one select rule is allowed in views");
173+
query = (Query *) lfirst(rewrite->actions);
174+
tle = (TargetEntry *) nth(tididx, query->targetList);
175+
if (tle && tle->expr && nodeTag(tle->expr) == T_Var)
176+
{
177+
Var *var = (Var *) tle->expr;
178+
RangeTblEntry *rte;
179+
if (var->varno > 0 && var->varno < INNER && var->varattno == SelfItemPointerAttributeNumber)
180+
{
181+
rte = (RangeTblEntry *) nth(var->varno - 1, query->rtable);
182+
if (rte)
183+
{
184+
heap_close(viewrel, AccessShareLock);
185+
return DirectFunctionCall2(currtid_byreloid, ObjectIdGetDatum(rte->relid), PointerGetDatum(tid));
186+
}
187+
}
188+
}
189+
break;
190+
}
191+
}
192+
elog(ERROR, "currtid can't handle this view");
193+
return (Datum) 0;
194+
}
195+
136196
Datum
137197
currtid_byreloid(PG_FUNCTION_ARGS)
138198
{
@@ -149,6 +209,8 @@ currtid_byreloid(PG_FUNCTION_ARGS)
149209
}
150210

151211
rel = heap_open(reloid, AccessShareLock);
212+
if (rel->rd_rel->relkind == RELKIND_VIEW)
213+
return currtid_for_view(rel, tid);
152214

153215
ItemPointerCopy(tid, result);
154216
heap_get_latest_tid(rel, SnapshotNow, result);
@@ -170,6 +232,8 @@ currtid_byrelname(PG_FUNCTION_ARGS)
170232
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
171233
"currtid_byrelname"));
172234
rel = heap_openrv(relrv, AccessShareLock);
235+
if (rel->rd_rel->relkind == RELKIND_VIEW)
236+
return currtid_for_view(rel, tid);
173237

174238
result = (ItemPointer) palloc(sizeof(ItemPointerData));
175239
ItemPointerCopy(tid, result);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy