Skip to content

Commit 7149fc4

Browse files
author
Rahul Parande
committed
Support for weak binding views to allow dropping of underlying objects
Signed-off-by: Rahul Parande <[email protected]>
1 parent ed82740 commit 7149fc4

File tree

5 files changed

+104
-47
lines changed

5 files changed

+104
-47
lines changed

src/backend/commands/dropcmds.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
#include "catalog/dependency.h"
2020
#include "catalog/namespace.h"
2121
#include "catalog/objectaddress.h"
22+
#include "catalog/pg_depend_d.h"
2223
#include "catalog/pg_namespace.h"
2324
#include "catalog/pg_proc.h"
2425
#include "commands/defrem.h"
26+
#include "commands/tablecmds.h"
2527
#include "miscadmin.h"
2628
#include "parser/parser.h"
2729
#include "parser/parse_type.h"
@@ -131,6 +133,20 @@ RemoveObjects(DropStmt *stmt)
131133
table_close(relation, NoLock);
132134

133135
add_exact_object_address(&address, objects);
136+
137+
/* Check for strong views and handle weak views */
138+
if ((stmt->removeType == OBJECT_FUNCTION) && view_dependency_hook)
139+
{
140+
Relation depRel = table_open(DependRelationId, AccessShareLock);
141+
142+
if (!(*view_dependency_hook)(&address, depRel, NULL))
143+
{
144+
table_close(depRel, AccessShareLock);
145+
continue;
146+
}
147+
148+
table_close(depRel, AccessShareLock);
149+
}
134150
}
135151

136152
/* Here we really delete them. */

src/backend/commands/tablecmds.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ InvokePreDropColumnHook_type InvokePreDropColumnHook = NULL;
138138
check_extended_attoptions_hook_type check_extended_attoptions_hook = NULL;
139139
find_attr_by_name_from_column_def_list_hook_type
140140
find_attr_by_name_from_column_def_list_hook = NULL;
141+
view_dependency_hook_type view_dependency_hook = NULL;
141142

142143
/*
143144
* State information for ALTER TABLE
@@ -1676,6 +1677,20 @@ RemoveRelations(DropStmt *drop)
16761677
{
16771678
InvokeObjectDropHook(RelationRelationId,relOid,0);
16781679
}
1680+
1681+
/* Check for strong views and handle weak views */
1682+
if ((drop->removeType == OBJECT_TABLE || drop->removeType == OBJECT_VIEW) && view_dependency_hook)
1683+
{
1684+
Relation depRel = table_open(DependRelationId, AccessShareLock);
1685+
1686+
if (!(*view_dependency_hook)(&obj, depRel, NULL))
1687+
{
1688+
table_close(depRel, AccessShareLock);
1689+
continue;
1690+
}
1691+
1692+
table_close(depRel, AccessShareLock);
1693+
}
16791694
}
16801695

16811696
performMultipleDeletions(objects, drop->behavior, flags);

src/backend/rewrite/rewriteHandler.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "utils/rel.h"
4848

4949
bbfViewHasInsteadofTrigger_hook_type bbfViewHasInsteadofTrigger_hook = NULL; /** BBF Hook to check Instead Of trigger on View */
50+
view_repair_hook_type view_repair_hook = NULL;
5051

5152
/* We use a list of these to detect recursion in RewriteQuery */
5253
typedef struct rewrite_event
@@ -4403,7 +4404,6 @@ RewriteQuery(Query *parsetree, List *rewrite_events, int orig_rt_length)
44034404
return rewritten;
44044405
}
44054406

4406-
44074407
/*
44084408
* QueryRewrite -
44094409
* Primary entry point to the query rewriter.
@@ -4431,6 +4431,14 @@ QueryRewrite(Query *parsetree)
44314431
Assert(parsetree->canSetTag);
44324432

44334433
/*
4434+
* Step 0 (Babelfish extension)
4435+
*
4436+
* If this is a view with broken rules, try to repair it
4437+
* using the definition from babelfish_view_def
4438+
*/
4439+
if (view_repair_hook)
4440+
(*view_repair_hook)(parsetree);
4441+
/*
44344442
* Step 1
44354443
*
44364444
* Apply all non-SELECT rules possibly getting 0 or many queries

src/bin/pg_dump/pg_dump.c

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15822,52 +15822,6 @@ dumpTable(Archive *fout, const TableInfo *tbinfo)
1582215822
free(namecopy);
1582315823
}
1582415824

15825-
/*
15826-
* Create the AS clause for a view or materialized view. The semicolon is
15827-
* stripped because a materialized view must add a WITH NO DATA clause.
15828-
*
15829-
* This returns a new buffer which must be freed by the caller.
15830-
*/
15831-
static PQExpBuffer
15832-
createViewAsClause(Archive *fout, const TableInfo *tbinfo)
15833-
{
15834-
PQExpBuffer query = createPQExpBuffer();
15835-
PQExpBuffer result = createPQExpBuffer();
15836-
PGresult *res;
15837-
int len;
15838-
15839-
/* Fetch the view definition */
15840-
appendPQExpBuffer(query,
15841-
"SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef",
15842-
tbinfo->dobj.catId.oid);
15843-
15844-
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
15845-
15846-
if (PQntuples(res) != 1)
15847-
{
15848-
if (PQntuples(res) < 1)
15849-
pg_fatal("query to obtain definition of view \"%s\" returned no data",
15850-
tbinfo->dobj.name);
15851-
else
15852-
pg_fatal("query to obtain definition of view \"%s\" returned more than one definition",
15853-
tbinfo->dobj.name);
15854-
}
15855-
15856-
len = PQgetlength(res, 0, 0);
15857-
15858-
if (len == 0)
15859-
pg_fatal("definition of view \"%s\" appears to be empty (length zero)",
15860-
tbinfo->dobj.name);
15861-
15862-
/* Strip off the trailing semicolon so that other things may follow. */
15863-
Assert(PQgetvalue(res, 0, 0)[len - 1] == ';');
15864-
appendBinaryPQExpBuffer(result, PQgetvalue(res, 0, 0), len - 1);
15865-
15866-
PQclear(res);
15867-
destroyPQExpBuffer(query);
15868-
15869-
return result;
15870-
}
1587115825

1587215826
/*
1587315827
* Create a dummy AS clause for a view. This is used when the real view
@@ -15913,6 +15867,66 @@ createDummyViewAsClause(Archive *fout, const TableInfo *tbinfo)
1591315867
return result;
1591415868
}
1591515869

15870+
/*
15871+
* Create the AS clause for a view or materialized view. The semicolon is
15872+
* stripped because a materialized view must add a WITH NO DATA clause.
15873+
*
15874+
* This returns a new buffer which must be freed by the caller.
15875+
*/
15876+
static PQExpBuffer
15877+
createViewAsClause(Archive *fout, const TableInfo *tbinfo)
15878+
{
15879+
PQExpBuffer query = createPQExpBuffer();
15880+
PQExpBuffer result = createPQExpBuffer();
15881+
PGresult *res;
15882+
int len;
15883+
15884+
/* Fetch the view definition */
15885+
appendPQExpBuffer(query,
15886+
"SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef",
15887+
tbinfo->dobj.catId.oid);
15888+
15889+
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
15890+
15891+
if (PQntuples(res) != 1)
15892+
{
15893+
if (PQntuples(res) < 1)
15894+
pg_fatal("query to obtain definition of view \"%s\" returned no data",
15895+
tbinfo->dobj.name);
15896+
else
15897+
pg_fatal("query to obtain definition of view \"%s\" returned more than one definition",
15898+
tbinfo->dobj.name);
15899+
}
15900+
15901+
len = PQgetlength(res, 0, 0);
15902+
15903+
if (len == 0)
15904+
{
15905+
/*
15906+
* Handle broken views (with empty definitions)
15907+
* Instead of failing, create a dummy SELECT that preserves the structure
15908+
*/
15909+
PQclear(res);
15910+
destroyPQExpBuffer(query);
15911+
15912+
/* Use createDummyViewAsClause to generate a compatible structure */
15913+
PQExpBuffer dummyResult = createDummyViewAsClause(fout, tbinfo);
15914+
appendPQExpBuffer(result, "%s", dummyResult->data);
15915+
destroyPQExpBuffer(dummyResult);
15916+
15917+
return result;
15918+
}
15919+
15920+
/* Strip off the trailing semicolon so that other things may follow. */
15921+
Assert(PQgetvalue(res, 0, 0)[len - 1] == ';');
15922+
appendBinaryPQExpBuffer(result, PQgetvalue(res, 0, 0), len - 1);
15923+
15924+
PQclear(res);
15925+
destroyPQExpBuffer(query);
15926+
15927+
return result;
15928+
}
15929+
1591615930
/*
1591715931
* dumpTableSchema
1591815932
* write the declaration (not data) of one user-defined table or view

src/include/commands/tablecmds.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,8 @@ typedef int (*find_attr_by_name_from_column_def_list_hook_type) (
122122
extern PGDLLEXPORT find_attr_by_name_from_column_def_list_hook_type
123123
find_attr_by_name_from_column_def_list_hook;
124124

125+
/* Hook for handling view dependencies during table drops */
126+
typedef bool (*view_dependency_hook_type) (const ObjectAddress *droppedObject, Relation depRel, ViewStmt *viewstmt);
127+
extern PGDLLIMPORT view_dependency_hook_type view_dependency_hook;
128+
125129
#endif /* TABLECMDS_H */

0 commit comments

Comments
 (0)