473,605 Members | 2,590 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Bug with updateable Views and inherited tables?

Hello all,

i have a view defined as a simple select of a table.
This table is inherited by a couple of others.
All entries belong to the child-tables.

I also have an unconditional update rule on the view.
If i do an update to the view, the update is rewritten
to update the father-table.

And now a strange thing is happening:
If i do an update, this update is done correctly only
on the first defined child-table. If it applies to
one of the other 8 child-tables nothing happens at all.

If i update the father-table directly everything is
working like expected (the update is "directed" to the
right table).

Is this a known limitation with views, rules and
inherited tables i haven't heard of? Or is it a bug?

My Postgres is version 7.4.5.

Thanks in advance

Sebastian
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org

Nov 23 '05 #1
4 1442
=?ISO-8859-1?Q?Sebastian_B =F6ck?= <se************ @freenet.de> writes:
Is this a known limitation with views, rules and
inherited tables i haven't heard of? Or is it a bug?


When you haven't shown us any details, it's impossible to tell.
Let's see the actual table, view, and rule definitions. (pg_dump -s
output would be good.)

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://archives.postgresql.org

Nov 23 '05 #2
Tom Lane wrote:
=?ISO-8859-1?Q?Sebastian_B =F6ck?= <se************ @freenet.de> writes:
Is this a known limitation with views, rules and
inherited tables i haven't heard of? Or is it a bug?

When you haven't shown us any details, it's impossible to tell.
Let's see the actual table, view, and rule definitions. (pg_dump -s
output would be good.)


Since my first attempt to send this message seems to be caught
by spamfilters, i'll repost it.

Sorry for the delay.
I investigated a little bit further and can be more precisely
about the whole thing. This (wrong) behaviour only occurs, if
the view has an order by clause.

To repoduce, simply run the attached script.

Sebastian
CREATE TABLE id (
id SERIAL PRIMARY KEY,
name TEXT
);

CREATE TABLE test_1 (
id INTEGER PRIMARY KEY,
name TEXT
) INHERITS (id);

CREATE TABLE test_2 (
id INTEGER PRIMARY KEY,
name TEXT
) INHERITS (id);

CREATE TABLE test_3 (
id INTEGER PRIMARY KEY,
name TEXT
) INHERITS (id);

CREATE VIEW working AS SELECT * FROM id;
CREATE RULE update_working AS ON UPDATE TO working
DO INSTEAD UPDATE id SET name = NEW.name WHERE id = OLD.id;

CREATE VIEW not_working AS SELECT * FROM id ORDER BY id;
CREATE RULE update_not_work ing AS ON UPDATE TO not_working
DO INSTEAD UPDATE id SET name = NEW.name WHERE id = OLD.id;

INSERT INTO test_1 (name) VALUES ('Test 1');
INSERT INTO test_1 (name) VALUES ('Test 2');
INSERT INTO test_2 (name) VALUES ('Test 3');
INSERT INTO test_2 (name) VALUES ('Test 4');
INSERT INTO test_3 (name) VALUES ('Test 5');
INSERT INTO test_3 (name) VALUES ('Test 6');

SELECT * FROM working;
UPDATE working SET name = 'working' WHERE id = '1';
UPDATE working SET name = 'working' WHERE id = '3';
UPDATE working SET name = 'working' WHERE id = '5';
SELECT * FROM working;
SELECT * FROM not_working;
UPDATE not_working SET name = 'should work' WHERE id = '2';
UPDATE not_working SET name = 'should work' WHERE id = '4';
UPDATE not_working SET name = 'should work' WHERE id = '5';
SELECT * FROM not_working;
---------------------------(end of broadcast)---------------------------
TIP 7: don't forget to increase your free space map settings

Nov 23 '05 #3
=?ISO-8859-1?Q?Sebastian_B =F6ck?= <se************ @freenet.de> writes:
I investigated a little bit further and can be more precisely
about the whole thing. This (wrong) behaviour only occurs, if
the view has an order by clause.


The bug is triggered by the combination of an inherited UPDATE target
and an unflattenable sub-Query. I verified that it's been broken for
as long as we've had such features :-(.

I've applied the attached patch to 8.0. You could probably adapt it for
7.4, but I'm hesitant to put such a nontrivial change into a stable
branch without a lot more testing.

regards, tom lane

*** src/backend/optimizer/path/allpaths.c.orig Sun Aug 29 09:55:03 2004
--- src/backend/optimizer/path/allpaths.c Sat Oct 2 17:23:54 2004
***************
*** 124,131 ****
/* RangeFunction --- generate a separate plan for it */
set_function_pa thlist(root, rel, rte);
}
! else if ((inheritlist = expand_inherite d_rtentry(root, rti, true))
! != NIL)
{
/* Relation is root of an inheritance tree, process specially */
set_inherited_r el_pathlist(roo t, rel, rti, rte, inheritlist);
--- 124,130 ----
/* RangeFunction --- generate a separate plan for it */
set_function_pa thlist(root, rel, rte);
}
! else if ((inheritlist = expand_inherite d_rtentry(root, rti)) != NIL)
{
/* Relation is root of an inheritance tree, process specially */
set_inherited_r el_pathlist(roo t, rel, rti, rte, inheritlist);
***************
*** 222,234 ****
ereport(ERROR,
(errcode(ERRCOD E_FEATURE_NOT_S UPPORTED),
errmsg("SELECT FOR UPDATE is not supported for inheritance queries")));
-
- /*
- * The executor will check the parent table's access permissions when
- * it examines the parent's inheritlist entry. There's no need to
- * check twice, so turn off access check bits in the original RTE.
- */
- rte->requiredPerm s = 0;

/*
* Initialize to compute size estimates for whole inheritance tree
--- 221,226 ----
*** src/backend/optimizer/plan/planner.c.orig Sun Aug 29 22:57:31 2004
--- src/backend/optimizer/plan/planner.c Sat Oct 2 17:57:29 2004
***************
*** 320,327 ****
* grouping_planne r.
*/
if (parse->resultRelati on &&
! (lst = expand_inherite d_rtentry(parse , parse->resultRelation ,
! false)) != NIL)
plan = inheritance_pla nner(parse, lst);
else
plan = grouping_planne r(parse, tuple_fraction) ;
--- 320,326 ----
* grouping_planne r.
*/
if (parse->resultRelati on &&
! (lst = expand_inherite d_rtentry(parse , parse->resultRelation )) != NIL)
plan = inheritance_pla nner(parse, lst);
else
plan = grouping_planne r(parse, tuple_fraction) ;
***************
*** 513,519 ****
{
int childRTindex = lfirst_int(l);
Oid childOID = getrelid(childR Tindex, parse->rtable);
- int subrtlength;
Query *subquery;
Plan *subplan;

--- 512,517 ----
***************
*** 526,547 ****
subplans = lappend(subplan s, subplan);

/*
! * It's possible that additional RTEs got added to the rangetable
! * due to expansion of inherited source tables (see allpaths.c).
! * If so, we must copy 'em back to the main parse tree's rtable.
*
! * XXX my goodness this is ugly. Really need to think about ways to
! * rein in planner's habit of scribbling on its input.
*/
! subrtlength = list_length(sub query->rtable);
! if (subrtlength > mainrtlength)
{
! List *subrt;

! subrt = list_copy_tail( subquery->rtable, mainrtlength);
! parse->rtable = list_concat(par se->rtable, subrt);
! mainrtlength = subrtlength;
}
/* Save preprocessed tlist from first rel for use in Append */
if (tlist == NIL)
tlist = subplan->targetlist;
--- 524,563 ----
subplans = lappend(subplan s, subplan);

/*
! * XXX my goodness this next bit is ugly. Really need to think about
! * ways to rein in planner's habit of scribbling on its input.
*
! * Planning of the subquery might have modified the rangetable,
! * either by addition of RTEs due to expansion of inherited source
! * tables, or by changes of the Query structures inside subquery
! * RTEs. We have to ensure that this gets propagated back to the
! * master copy. However, if we aren't done planning yet, we also
! * need to ensure that subsequent calls to grouping_planne r have
! * virgin sub-Queries to work from. So, if we are at the last
! * list entry, just copy the subquery rangetable back to the master
! * copy; if we are not, then extend the master copy by adding
! * whatever the subquery added. (We assume these added entries
! * will go untouched by the future grouping_planne r calls. We are
! * also effectively assuming that sub-Queries will get planned
! * identically each time, or at least that the impacts on their
! * rangetables will be the same each time. Did I say this is ugly?)
*/
! if (lnext(l) == NULL)
! parse->rtable = subquery->rtable;
! else
{
! int subrtlength = list_length(sub query->rtable);

! if (subrtlength > mainrtlength)
! {
! List *subrt;
!
! subrt = list_copy_tail( subquery->rtable, mainrtlength);
! parse->rtable = list_concat(par se->rtable, subrt);
! mainrtlength = subrtlength;
! }
}
+
/* Save preprocessed tlist from first rel for use in Append */
if (tlist == NIL)
tlist = subplan->targetlist;
*** src/backend/optimizer/prep/prepunion.c.ori g Sun Aug 29 09:55:05 2004
--- src/backend/optimizer/prep/prepunion.c Sat Oct 2 17:24:22 2004
***************
*** 705,728 ****
* whole inheritance set (parent and children).
* If not, return NIL.
*
! * When dup_parent is false, the initially given RT index is part of the
! * returned list (if any). When dup_parent is true, the given RT index
! * is *not* in the returned list; a duplicate RTE will be made for the
! * parent table.
*
* A childless table is never considered to be an inheritance set; therefore
* the result will never be a one-element list. It'll be either empty
* or have two or more elements.
*
! * NOTE: after this routine executes, the specified RTE will always have
! * its inh flag cleared, whether or not there were any children. This
! * ensures we won't expand the same RTE twice, which would otherwise occur
! * for the case of an inherited UPDATE/DELETE target relation.
! *
! * XXX probably should convert the result type to Relids?
*/
List *
! expand_inherite d_rtentry(Query *parse, Index rti, bool dup_parent)
{
RangeTblEntry *rte = rt_fetch(rti, parse->rtable);
Oid parentOID;
--- 705,727 ----
* whole inheritance set (parent and children).
* If not, return NIL.
*
! * Note that the original RTE is considered to represent the whole
! * inheritance set. The first member of the returned list is an RTE
! * for the same table, but with inh = false, to represent the parent table
! * in its role as a simple member of the set. The original RT index is
! * never a member of the returned list.
*
* A childless table is never considered to be an inheritance set; therefore
* the result will never be a one-element list. It'll be either empty
* or have two or more elements.
*
! * Note: there are cases in which this routine will be invoked multiple
! * times on the same RTE. We will generate a separate set of child RTEs
! * for each invocation. This is somewhat wasteful but seems not worth
! * trying to avoid.
*/
List *
! expand_inherite d_rtentry(Query *parse, Index rti)
{
RangeTblEntry *rte = rt_fetch(rti, parse->rtable);
Oid parentOID;
***************
*** 734,745 ****
if (!rte->inh)
return NIL;
Assert(rte->rtekind == RTE_RELATION);
- /* Always clear the parent's inh flag, see above comments */
- rte->inh = false;
/* Fast path for common case of childless table */
parentOID = rte->relid;
if (!has_subclass( parentOID))
return NIL;
/* Scan for all members of inheritance set */
inhOIDs = find_all_inheri tors(parentOID) ;

--- 733,746 ----
if (!rte->inh)
return NIL;
Assert(rte->rtekind == RTE_RELATION);
/* Fast path for common case of childless table */
parentOID = rte->relid;
if (!has_subclass( parentOID))
+ {
+ /* Clear flag to save repeated tests if called again */
+ rte->inh = false;
return NIL;
+ }
/* Scan for all members of inheritance set */
inhOIDs = find_all_inheri tors(parentOID) ;

***************
*** 749,784 ****
* table once had a child but no longer does.
*/
if (list_length(in hOIDs) < 2)
return NIL;
! /* OK, it's an inheritance set; expand it */
! if (dup_parent)
! inhRTIs = NIL;
! else
! inhRTIs = list_make1_int( rti); /* include original RTE in result */

foreach(l, inhOIDs)
{
Oid childOID = lfirst_oid(l);
RangeTblEntry *childrte;
Index childRTindex;

- /* parent will be in the list too; skip it if not dup requested */
- if (childOID == parentOID && !dup_parent)
- continue;
-
/*
* Build an RTE for the child, and attach to query's rangetable
* list. We copy most fields of the parent's RTE, but replace
! * relation real name and OID. Note that inh will be false at
! * this point.
*/
childrte = copyObject(rte) ;
childrte->relid = childOID;
parse->rtable = lappend(parse->rtable, childrte);
childRTindex = list_length(par se->rtable);
-
inhRTIs = lappend_int(inh RTIs, childRTindex);
}

return inhRTIs;
}
--- 750,790 ----
* table once had a child but no longer does.
*/
if (list_length(in hOIDs) < 2)
+ {
+ /* Clear flag to save repeated tests if called again */
+ rte->inh = false;
return NIL;
! }

+ /* OK, it's an inheritance set; expand it */
+ inhRTIs = NIL;
foreach(l, inhOIDs)
{
Oid childOID = lfirst_oid(l);
RangeTblEntry *childrte;
Index childRTindex;

/*
* Build an RTE for the child, and attach to query's rangetable
* list. We copy most fields of the parent's RTE, but replace
! * relation OID, and set inh = false.
*/
childrte = copyObject(rte) ;
childrte->relid = childOID;
+ childrte->inh = false;
parse->rtable = lappend(parse->rtable, childrte);
childRTindex = list_length(par se->rtable);
inhRTIs = lappend_int(inh RTIs, childRTindex);
}
+
+ /*
+ * The executor will check the parent table's access permissions when
+ * it examines the parent's inheritlist entry. There's no need to
+ * check twice, so turn off access check bits in the original RTE.
+ * (If we are invoked more than once, extra copies of the child RTEs
+ * will also not cause duplicate permission checks.)
+ */
+ rte->requiredPerm s = 0;

return inhRTIs;
}
*** src/backend/optimizer/util/clauses.c.orig Sun Aug 29 09:55:06 2004
--- src/backend/optimizer/util/clauses.c Sat Oct 2 15:41:30 2004
***************
*** 3254,3263 ****
--- 3254,3273 ----
CHECKFLATCOPY(n ewrte->subquery, rte->subquery, Query);
MUTATE(newrte->subquery, newrte->subquery, Query *);
}
+ else
+ {
+ /* else, copy RT subqueries as-is */
+ newrte->subquery = copyObject(rte->subquery);
+ }
break;
case RTE_JOIN:
if (!(flags & QTW_IGNORE_JOIN ALIASES))
MUTATE(newrte->joinaliasvar s, rte->joinaliasvar s, List *);
+ else
+ {
+ /* else, copy join aliases as-is */
+ newrte->joinaliasvar s = copyObject(rte->joinaliasvars) ;
+ }
break;
case RTE_FUNCTION:
MUTATE(newrte->funcexpr, rte->funcexpr, Node *);
*** src/include/optimizer/prep.h.orig Sun Aug 29 09:56:05 2004
--- src/include/optimizer/prep.h Sat Oct 2 17:23:45 2004
***************
*** 52,59 ****

extern List *find_all_inher itors(Oid parentrel);

! extern List *expand_inherit ed_rtentry(Quer y *parse, Index rti,
! bool dup_parent);

extern Node *adjust_inherit ed_attrs(Node *node,
Index old_rt_index, Oid old_relid,
--- 52,58 ----

extern List *find_all_inher itors(Oid parentrel);

! extern List *expand_inherit ed_rtentry(Quer y *parse, Index rti);

extern Node *adjust_inherit ed_attrs(Node *node,
Index old_rt_index, Oid old_relid,

---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/docs/faqs/FAQ.html

Nov 23 '05 #4
Tom Lane wrote:
=?ISO-8859-1?Q?Sebastian_B =F6ck?= <se************ @freenet.de> writes:
I investigated a little bit further and can be more precisely
about the whole thing. This (wrong) behaviour only occurs, if
the view has an order by clause.

The bug is triggered by the combination of an inherited UPDATE target
and an unflattenable sub-Query. I verified that it's been broken for
as long as we've had such features :-(.

I've applied the attached patch to 8.0.


Thank you!
You could probably adapt it for
7.4, but I'm hesitant to put such a nontrivial change into a stable
branch without a lot more testing.


It isn't that necessary for me, just wondered 'bout the
strange behaviour.

Sebastian

---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Nov 23 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
15228
by: Mike N. | last post by:
Hello: I am new to T-SQL programing, and relativly new to SQL statements in general, although I have a good understanding of database theory. I'm a little confused as to the fundamental differences between a view and a query, or rather, when it is more appropriate to use one vs. the other. It seems to me that most select queries can be implemented as views, and I can't see the downside to doing so.
2
1667
by: abefuzzleduser2 | last post by:
I am using sql 2000 (mdb) with linked tables on SQL 2000. I need to use views to limit users records, instead of direct table access. I setup a single talbe view in sql and tested update and inserting the view using query analyzer. But when I add that view as a "linked" table in access (windows db security dsn-less). Access does not allow me to edit the data from view. Table has Pk have tried indexing view but we use several ntext...
1
2468
by: Edward | last post by:
I've recently migrated the back end of one of my client's applications from Access to SQL Server. One of the forms is based on an Access query thus: SELECT dbo_tblDistributionDetail.*, dbo_tblDistributionMaster.fldDocumentType, dbo_tblDistributionMaster.fldDocumentID, dbo_tblDistributionMaster.ts FROM dbo_tblDistributionMaster INNER JOIN dbo_tblDistributionDetail ON dbo_tblDistributionMaster.fldDistributionID =
3
1694
by: CSN | last post by:
Just wondering, is updateable views slated for a future version of Postgresql? In addition to using rules that is. CSN __________________________________ Do you Yahoo!?
8
2997
by: Jim in Arizona | last post by:
I've been using an example out of a book to be able to edit the rows in a database. I am getting the following error: ======================================================== ======================================================== Server Error in '/' Application. -------------------------------------------------------------------------------- Operation must use an updateable query. Description: An unhandled exception occurred during...
11
3108
by: JC | last post by:
I created an updateable view, which joins two tables, in a DB2 UDB database. The view was made updateable by the creation of an "instead of" trigger. I'd like to use this view for updates via QMF for Windows or DB2 Table Editor. However, when I try to update from either of these tools, I receive an SQL0150 error. Is there anything I can do to allow the updates, such as update the READONLY value for the view in the catalog table? ...
33
6638
by: Peter | last post by:
People are telling me it is bad to put select * from <atable> in a view. I better should list all fields of the table inside the definition of the view. I dont know exactly why but some say: A select * from makes sql server does a table scan.
4
4961
by: othellomy | last post by:
How do I make a view non updateable? I want to create a view so that I will not be able to update, insert or delete the view so that base table is not affected (except dropping the view itself). Thanks.
1
1428
by: kia.martin | last post by:
I have a sql database connected with access, but when I try to run macros which basically just transfer information from tables for approval an error comes up with "time key is not updateable". I have found a quick fix in which I can delete the time key from the table and everything will run fine, but when end users try to change records it will not allow them. It comes up with an error that they cannot save changes and must copy to the...
0
7934
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
6743
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
5886
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5445
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3912
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
3958
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2438
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1541
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1271
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.