Commit 30ec3160 authored by Tom Lane's avatar Tom Lane

Add code to extract dependencies from an expression tree, and use it

to build dependencies for rules, constraint expressions, and default
expressions.  Repair some problems in the original design of
recursiveDeletion() exposed by more complex dependency sets.  Fix
regression tests that were deleting things in illegal sequences.
parent 1e07ab78
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.207 2002/07/15 16:33:31 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.208 2002/07/16 05:53:33 tgl Exp $
*
*
* INTERFACE ROUTINES
......@@ -1157,10 +1157,15 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
colobject.objectSubId = attnum;
recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
/*
* Record dependencies on objects used in the expression, too.
*/
recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
}
/*
* Store a constraint expression for the given relation.
* Store a check-constraint expression for the given relation.
* The expression must be presented as a nodeToString() string.
*
* Caller is responsible for updating the count of constraints
......@@ -1191,6 +1196,10 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
/*
* Find columns of rel that are used in ccbin
*
* NB: pull_var_clause is okay here only because we don't allow
* subselects in check constraints; it would fail to examine the
* contents of subselects.
*/
varList = pull_var_clause(expr, false);
keycount = length(varList);
......@@ -1226,8 +1235,8 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
false, /* Is Deferrable */
false, /* Is Deferred */
RelationGetRelid(rel), /* relation */
attNos, /* List of attributes in the constraint */
keycount, /* # attributes in the constraint */
attNos, /* attrs in the constraint */
keycount, /* # attrs in the constraint */
InvalidOid, /* not a domain constraint */
InvalidOid, /* Foreign key fields */
NULL,
......@@ -1235,6 +1244,7 @@ StoreRelCheck(Relation rel, char *ccname, char *ccbin)
' ',
' ',
' ',
expr, /* Tree form check constraint */
ccbin, /* Binary form check constraint */
ccsrc); /* Source form check constraint */
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.183 2002/07/14 21:08:08 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.184 2002/07/16 05:53:33 tgl Exp $
*
*
* INTERFACE ROUTINES
......@@ -712,7 +712,8 @@ index_create(Oid heapRelationId,
' ',
' ',
' ',
NULL, /* Constraint Bin & Src */
NULL, /* no check constraint */
NULL,
NULL);
referenced.classId = get_system_catalog_relid(ConstraintRelationName);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.1 2002/07/12 18:43:15 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -52,6 +52,7 @@ CreateConstraintEntry(const char *constraintName,
char foreignUpdateType,
char foreignDeleteType,
char foreignMatchType,
Node *conExpr,
const char *conBin,
const char *conSrc)
{
......@@ -227,6 +228,24 @@ CreateConstraintEntry(const char *constraintName,
}
}
if (conExpr != NULL)
{
/*
* Register dependencies from constraint to objects mentioned
* in CHECK expression. We gin up a rather bogus rangetable
* list to handle any Vars in the constraint.
*/
RangeTblEntry rte;
MemSet(&rte, 0, sizeof(rte));
rte.type = T_RangeTblEntry;
rte.rtekind = RTE_RELATION;
rte.relid = relId;
recordDependencyOnExpr(&conobject, conExpr, makeList1(&rte),
DEPENDENCY_NORMAL);
}
return conOid;
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.1 2002/07/12 18:43:15 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -38,6 +38,19 @@ void
recordDependencyOn(const ObjectAddress *depender,
const ObjectAddress *referenced,
DependencyType behavior)
{
recordMultipleDependencies(depender, referenced, 1, behavior);
}
/*
* Record multiple dependencies (of the same kind) for a single dependent
* object. This has a little less overhead than recording each separately.
*/
void
recordMultipleDependencies(const ObjectAddress *depender,
const ObjectAddress *referenced,
int nreferenced,
DependencyType behavior)
{
Relation dependDesc;
HeapTuple tup;
......@@ -45,6 +58,10 @@ recordDependencyOn(const ObjectAddress *depender,
char nulls[Natts_pg_depend];
Datum values[Natts_pg_depend];
Relation idescs[Num_pg_depend_indices];
bool indices_opened = false;
if (nreferenced <= 0)
return; /* nothing to do */
/*
* During bootstrap, do nothing since pg_depend may not exist yet.
......@@ -55,44 +72,51 @@ recordDependencyOn(const ObjectAddress *depender,
dependDesc = heap_openr(DependRelationName, RowExclusiveLock);
/*
* If the referenced object is pinned by the system, there's no real
* need to record dependencies on it. This saves lots of space in
* pg_depend, so it's worth the time taken to check.
*/
if (!isObjectPinned(referenced, dependDesc))
memset(nulls, ' ', sizeof(nulls));
for (i = 0; i < nreferenced; i++, referenced++)
{
/*
* Record the Dependency. Note we don't bother to check for
* duplicate dependencies; there's no harm in them.
* If the referenced object is pinned by the system, there's no real
* need to record dependencies on it. This saves lots of space in
* pg_depend, so it's worth the time taken to check.
*/
for (i = 0; i < Natts_pg_depend; ++i)
if (!isObjectPinned(referenced, dependDesc))
{
nulls[i] = ' ';
values[i] = (Datum) 0;
/*
* Record the Dependency. Note we don't bother to check for
* duplicate dependencies; there's no harm in them.
*/
values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
values[Anum_pg_depend_deptype -1] = CharGetDatum((char) behavior);
tup = heap_formtuple(dependDesc->rd_att, values, nulls);
simple_heap_insert(dependDesc, tup);
/*
* Keep indices current
*/
if (!indices_opened)
{
CatalogOpenIndices(Num_pg_depend_indices, Name_pg_depend_indices, idescs);
indices_opened = true;
}
CatalogIndexInsert(idescs, Num_pg_depend_indices, dependDesc, tup);
heap_freetuple(tup);
}
}
values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
values[Anum_pg_depend_deptype -1] = CharGetDatum((char) behavior);
tup = heap_formtuple(dependDesc->rd_att, values, nulls);
simple_heap_insert(dependDesc, tup);
/*
* Keep indices current
*/
CatalogOpenIndices(Num_pg_depend_indices, Name_pg_depend_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_depend_indices, dependDesc, tup);
if (indices_opened)
CatalogCloseIndices(Num_pg_depend_indices, idescs);
}
heap_close(dependDesc, RowExclusiveLock);
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.21 2002/07/15 16:33:31 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.22 2002/07/16 05:53:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -2708,6 +2708,7 @@ createForeignKeyConstraint(Relation rel, Relation pkrel,
fkconstraint->fk_upd_action,
fkconstraint->fk_del_action,
fkconstraint->fk_matchtype,
NULL, /* no check constraint */
NULL,
NULL);
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.74 2002/07/12 18:43:17 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.75 2002/07/16 05:53:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -47,9 +47,11 @@ InsertRule(char *rulname,
Oid eventrel_oid,
AttrNumber evslot_index,
bool evinstead,
char *evqual,
char *actiontree)
Node *event_qual,
List *action)
{
char *evqual = nodeToString(event_qual);
char *actiontree = nodeToString((Node *) action);
int i;
Datum values[Natts_pg_rewrite];
char nulls[Natts_pg_rewrite];
......@@ -123,6 +125,21 @@ InsertRule(char *rulname,
recordDependencyOn(&myself, &referenced,
(evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);
/*
* Also install dependencies on objects referenced in action and qual.
*/
recordDependencyOnExpr(&myself, (Node *) action, NIL,
DEPENDENCY_NORMAL);
if (event_qual != NULL)
{
/* Find query containing OLD/NEW rtable entries */
Query *qry = (Query *) lfirst(action);
qry = getInsertSelectQuery(qry, NULL);
recordDependencyOnExpr(&myself, event_qual, qry->rtable,
DEPENDENCY_NORMAL);
}
heap_close(pg_rewrite_desc, RowExclusiveLock);
return rewriteObjectId;
......@@ -141,8 +158,6 @@ DefineQueryRewrite(RuleStmt *stmt)
Oid ruleId;
int event_attno;
Oid event_attype;
char *actionP,
*event_qualP;
List *l;
Query *query;
AclResult aclresult;
......@@ -342,16 +357,13 @@ DefineQueryRewrite(RuleStmt *stmt)
/* discard rule if it's null action and not INSTEAD; it's a no-op */
if (action != NIL || is_instead)
{
event_qualP = nodeToString(event_qual);
actionP = nodeToString(action);
ruleId = InsertRule(stmt->rulename,
event_type,
ev_relid,
event_attno,
is_instead,
event_qualP,
actionP);
event_qual,
action);
/*
* Set pg_class 'relhasrules' field TRUE for event relation. If
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: dependency.h,v 1.1 2002/07/12 18:43:19 tgl Exp $
* $Id: dependency.h,v 1.2 2002/07/16 05:53:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -83,10 +83,19 @@ typedef struct ObjectAddress
extern void performDeletion(const ObjectAddress *object,
DropBehavior behavior);
extern void recordDependencyOnExpr(const ObjectAddress *depender,
Node *expr, List *rtable,
DependencyType behavior);
/* in pg_depend.c */
extern void recordDependencyOn(const ObjectAddress *depender,
const ObjectAddress *referenced,
DependencyType behavior);
extern void recordMultipleDependencies(const ObjectAddress *depender,
const ObjectAddress *referenced,
int nreferenced,
DependencyType behavior);
#endif /* DEPENDENCY_H */
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_constraint.h,v 1.1 2002/07/12 18:43:19 tgl Exp $
* $Id: pg_constraint.h,v 1.2 2002/07/16 05:53:34 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -158,6 +158,7 @@ extern Oid CreateConstraintEntry(const char *constraintName,
char foreignUpdateType,
char foreignDeleteType,
char foreignMatchType,
Node *conExpr,
const char *conBin,
const char *conSrc);
......
......@@ -544,13 +544,19 @@ from (select oid from pg_class where relname = 'atest1') as t1;
\c regression
DROP FUNCTION testfunc2(int);
DROP FUNCTION testfunc4(boolean);
DROP TABLE atest1;
DROP TABLE atest2;
DROP TABLE atest3;
DROP VIEW atestv1;
DROP VIEW atestv2;
DROP VIEW atestv3;
-- this should cascade to drop atestv4
DROP VIEW atestv3 CASCADE;
NOTICE: Drop cascades to rule _RETURN on view atestv3
NOTICE: Drop cascades to rule _RETURN on view atestv4
NOTICE: Drop cascades to view atestv4
-- this should complain "does not exist"
DROP VIEW atestv4;
ERROR: view "atestv4" does not exist
DROP TABLE atest1;
DROP TABLE atest2;
DROP TABLE atest3;
DROP GROUP regressgroup1;
DROP GROUP regressgroup2;
DROP USER regressuser1;
......
......@@ -61,6 +61,7 @@ SELECT * FROM vw_getfoo;
(1 row)
-- sql, proretset = t, prorettype = b
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS setof int AS 'SELECT fooid FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
......@@ -70,7 +71,6 @@ SELECT * FROM getfoo(1) AS t1;
1
(2 rows)
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
getfoo
......@@ -80,6 +80,7 @@ SELECT * FROM vw_getfoo;
(2 rows)
-- sql, proretset = t, prorettype = b
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS setof text AS 'SELECT fooname FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
......@@ -89,7 +90,6 @@ SELECT * FROM getfoo(1) AS t1;
Ed
(2 rows)
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
getfoo
......@@ -99,6 +99,7 @@ SELECT * FROM vw_getfoo;
(2 rows)
-- sql, proretset = f, prorettype = c
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
......@@ -107,7 +108,6 @@ SELECT * FROM getfoo(1) AS t1;
1 | 1 | Joe
(1 row)
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
fooid | foosubid | fooname
......@@ -116,6 +116,7 @@ SELECT * FROM vw_getfoo;
(1 row)
-- sql, proretset = t, prorettype = c
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS setof foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
......@@ -125,7 +126,6 @@ SELECT * FROM getfoo(1) AS t1;
1 | 2 | Ed
(2 rows)
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
fooid | foosubid | fooname
......@@ -135,6 +135,7 @@ SELECT * FROM vw_getfoo;
(2 rows)
-- plpgsql, proretset = f, prorettype = b
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS int AS 'DECLARE fooint int; BEGIN SELECT fooid into fooint FROM foo WHERE fooid = $1; RETURN fooint; END;' LANGUAGE 'plpgsql';
SELECT * FROM getfoo(1) AS t1;
......@@ -143,7 +144,6 @@ SELECT * FROM getfoo(1) AS t1;
1
(1 row)
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
getfoo
......@@ -152,6 +152,7 @@ SELECT * FROM vw_getfoo;
(1 row)
-- plpgsql, proretset = f, prorettype = c
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS foo AS 'DECLARE footup foo%ROWTYPE; BEGIN SELECT * into footup FROM foo WHERE fooid = $1; RETURN footup; END;' LANGUAGE 'plpgsql';
SELECT * FROM getfoo(1) AS t1;
......@@ -160,7 +161,6 @@ SELECT * FROM getfoo(1) AS t1;
1 | 1 | Joe
(1 row)
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
fooid | foosubid | fooname
......@@ -168,11 +168,11 @@ SELECT * FROM vw_getfoo;
1 | 1 | Joe
(1 row)
DROP TABLE foo2;
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
DROP FUNCTION foot(int);
DROP TABLE foo2;
DROP TABLE foo;
DROP FUNCTION getfoo(int);
DROP VIEW vw_getfoo;
-- Rescan tests --
CREATE TABLE foorescan (fooid int, foosubid int, fooname text, primary key(fooid,foosubid));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'foorescan_pkey' for table 'foorescan'
......@@ -339,10 +339,10 @@ SELECT * FROM fooview2 AS fv WHERE fv.maxsubid = 5;
5008 | 5
(6 rows)
DROP TABLE foorescan;
DROP FUNCTION foorescan(int,int);
DROP VIEW vw_foorescan;
DROP TABLE barrescan;
DROP FUNCTION foorescan(int);
DROP VIEW fooview1;
DROP VIEW fooview2;
DROP FUNCTION foorescan(int,int);
DROP FUNCTION foorescan(int);
DROP TABLE foorescan;
DROP TABLE barrescan;
......@@ -292,15 +292,17 @@ from (select oid from pg_class where relname = 'atest1') as t1;
DROP FUNCTION testfunc2(int);
DROP FUNCTION testfunc4(boolean);
DROP TABLE atest1;
DROP TABLE atest2;
DROP TABLE atest3;
DROP VIEW atestv1;
DROP VIEW atestv2;
DROP VIEW atestv3;
-- this should cascade to drop atestv4
DROP VIEW atestv3 CASCADE;
-- this should complain "does not exist"
DROP VIEW atestv4;
DROP TABLE atest1;
DROP TABLE atest2;
DROP TABLE atest3;
DROP GROUP regressgroup1;
DROP GROUP regressgroup2;
......
......@@ -32,58 +32,58 @@ CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
-- sql, proretset = t, prorettype = b
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS setof int AS 'SELECT fooid FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
-- sql, proretset = t, prorettype = b
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS setof text AS 'SELECT fooname FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
-- sql, proretset = f, prorettype = c
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
-- sql, proretset = t, prorettype = c
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS setof foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1;
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
-- plpgsql, proretset = f, prorettype = b
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS int AS 'DECLARE fooint int; BEGIN SELECT fooid into fooint FROM foo WHERE fooid = $1; RETURN fooint; END;' LANGUAGE 'plpgsql';
SELECT * FROM getfoo(1) AS t1;
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
-- plpgsql, proretset = f, prorettype = c
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS foo AS 'DECLARE footup foo%ROWTYPE; BEGIN SELECT * into footup FROM foo WHERE fooid = $1; RETURN footup; END;' LANGUAGE 'plpgsql';
SELECT * FROM getfoo(1) AS t1;
DROP VIEW vw_getfoo;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo;
DROP TABLE foo2;
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
DROP FUNCTION foot(int);
DROP TABLE foo2;
DROP TABLE foo;
DROP FUNCTION getfoo(int);
DROP VIEW vw_getfoo;
-- Rescan tests --
CREATE TABLE foorescan (fooid int, foosubid int, fooname text, primary key(fooid,foosubid));
......@@ -172,10 +172,10 @@ SELECT * FROM fooview1 AS fv WHERE fv.fooid = 5004;
CREATE VIEW fooview2 AS SELECT b.fooid, max(f.foosubid) AS maxsubid FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) GROUP BY b.fooid ORDER BY 1,2;
SELECT * FROM fooview2 AS fv WHERE fv.maxsubid = 5;
DROP TABLE foorescan;
DROP FUNCTION foorescan(int,int);
DROP VIEW vw_foorescan;
DROP TABLE barrescan;
DROP FUNCTION foorescan(int);
DROP VIEW fooview1;
DROP VIEW fooview2;
DROP FUNCTION foorescan(int,int);
DROP FUNCTION foorescan(int);
DROP TABLE foorescan;
DROP TABLE barrescan;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment