Skip to content

Commit c64be62

Browse files
committed
Oracle Force View Support.
1 parent a14b4aa commit c64be62

File tree

29 files changed

+1845
-264
lines changed

29 files changed

+1845
-264
lines changed

contrib/ivorysql_ora/src/sysview/sysview--1.0.sql

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,4 +1088,107 @@ SELECT
10881088
decode(bitand(s.flags, 64), 64, 'Y', 'N') AS session_flag,null AS keep_value
10891089
FROM PG_SEQUENCE s,pg_class c where s.seqrelid = c.oid and c.relowner::regrole = current_user::regrole;
10901090

1091+
CREATE OR REPLACE VIEW SYS.DBA_VIEWS AS
1092+
SELECT
1093+
SYS.ORA_CASE_TRANS(
1094+
PG_GET_USERBYID(C.RELOWNER)::VARCHAR2
1095+
)::VARCHAR2(128) AS OWNER,
1096+
SYS.ORA_CASE_TRANS(C.RELNAME::VARCHAR2)::VARCHAR2(128) AS VIEW_NAME,
1097+
LENGTH(pg_get_viewdef(C.OID))::NUMBER(38) AS TEXT_LENGTH,
1098+
SYS.ORA_CASE_TRANS(pg_get_viewdef(C.OID)::VARCHAR2)::TEXT AS TEXT,
1099+
SYS.ORA_CASE_TRANS(pg_get_viewdef(C.OID)::VARCHAR2)::VARCHAR2(4000) AS TEXT_VC,
1100+
NULL::NUMBER(38) AS TYPE_TEXT_LENGTH,
1101+
NULL::VARCHAR2(4000) AS TYPE_TEXT,
1102+
NULL::NUMBER(38) AS OID_TEXT_LENGTH,
1103+
NULL::VARCHAR2(4000) AS OID_TEXT,
1104+
NULL::VARCHAR2(128) AS VIEW_TYPE_OWNER,
1105+
NULL::VARCHAR2(128) AS VIEW_TYPE,
1106+
NULL::VARCHAR2(128) AS SUPERVIEW_NAME,
1107+
NULL::VARCHAR2(1) AS EDITIONING_VIEW,
1108+
NULL::VARCHAR2(1) AS READ_ONLY,
1109+
NULL::VARCHAR2(1) AS CONTAINER_DATA,
1110+
NULL::VARCHAR2(12) AS BEQUEATH,
1111+
0::VARCHAR2(256) AS ORIGIN_CON_ID,
1112+
NULL::VARCHAR2(100) AS DEFAULT_COLLATION,
1113+
NULL::VARCHAR2(3) AS CONTAINERS_DEFAULT,
1114+
NULL::VARCHAR2(3) AS CONTAINER_MAP,
1115+
NULL::VARCHAR2(3) AS EXTENDED_DATA_LINK,
1116+
NULL::VARCHAR2(3) AS EXTENDED_DATA_LINK_MAP,
1117+
NULL::VARCHAR2(3) AS HAS_SENSITIVE_COLUMN,
1118+
NULL::VARCHAR2(3) AS ADMIT_NULL,
1119+
NULL::VARCHAR2(3) AS PDB_LOCAL_ONLY
1120+
FROM
1121+
PG_CLASS AS C
1122+
WHERE
1123+
C.RELKIND = 'v';
1124+
GRANT SELECT ON SYS.DBA_VIEWS TO PUBLIC;
1125+
1126+
CREATE OR REPLACE VIEW SYS.ALL_VIEWS AS
1127+
SELECT
1128+
SYS.ORA_CASE_TRANS(
1129+
PG_GET_USERBYID(C.RELOWNER)::VARCHAR2
1130+
)::VARCHAR2(128) AS OWNER,
1131+
SYS.ORA_CASE_TRANS(C.RELNAME::VARCHAR2)::VARCHAR2(128) AS VIEW_NAME,
1132+
LENGTH(pg_get_viewdef(C.OID))::NUMBER(38) AS TEXT_LENGTH,
1133+
SYS.ORA_CASE_TRANS(pg_get_viewdef(C.OID)::VARCHAR2)::TEXT AS TEXT,
1134+
SYS.ORA_CASE_TRANS(pg_get_viewdef(C.OID)::VARCHAR2)::VARCHAR2(4000) AS TEXT_VC,
1135+
NULL::NUMBER(38) AS TYPE_TEXT_LENGTH,
1136+
NULL::VARCHAR2(4000) AS TYPE_TEXT,
1137+
NULL::NUMBER(38) AS OID_TEXT_LENGTH,
1138+
NULL::VARCHAR2(4000) AS OID_TEXT,
1139+
NULL::VARCHAR2(128) AS VIEW_TYPE_OWNER,
1140+
NULL::VARCHAR2(128) AS VIEW_TYPE,
1141+
NULL::VARCHAR2(128) AS SUPERVIEW_NAME,
1142+
NULL::VARCHAR2(1) AS EDITIONING_VIEW,
1143+
NULL::VARCHAR2(1) AS READ_ONLY,
1144+
NULL::VARCHAR2(1) AS CONTAINER_DATA,
1145+
NULL::VARCHAR2(12) AS BEQUEATH,
1146+
0::VARCHAR2(256) AS ORIGIN_CON_ID,
1147+
NULL::VARCHAR2(100) AS DEFAULT_COLLATION,
1148+
NULL::VARCHAR2(3) AS CONTAINERS_DEFAULT,
1149+
NULL::VARCHAR2(3) AS CONTAINER_MAP,
1150+
NULL::VARCHAR2(3) AS EXTENDED_DATA_LINK,
1151+
NULL::VARCHAR2(3) AS EXTENDED_DATA_LINK_MAP,
1152+
NULL::VARCHAR2(3) AS HAS_SENSITIVE_COLUMN,
1153+
NULL::VARCHAR2(3) AS ADMIT_NULL,
1154+
NULL::VARCHAR2(3) AS PDB_LOCAL_ONLY
1155+
FROM
1156+
PG_CLASS AS C
1157+
WHERE
1158+
C.RELKIND = 'v'
1159+
AND HAS_ANY_COLUMN_PRIVILEGE(C.OID, 'SELECT');
1160+
GRANT SELECT ON SYS.ALL_VIEWS TO PUBLIC;
1161+
1162+
CREATE OR REPLACE VIEW SYS.USER_VIEWS AS
1163+
SELECT
1164+
SYS.ORA_CASE_TRANS(C.RELNAME::VARCHAR2)::VARCHAR2(128) AS VIEW_NAME,
1165+
LENGTH(pg_get_viewdef(C.OID))::NUMBER(38) AS TEXT_LENGTH,
1166+
SYS.ORA_CASE_TRANS(pg_get_viewdef(C.OID)::VARCHAR2)::TEXT AS TEXT,
1167+
SYS.ORA_CASE_TRANS(pg_get_viewdef(C.OID)::VARCHAR2)::VARCHAR2(4000) AS TEXT_VC,
1168+
NULL::NUMBER(38) AS TYPE_TEXT_LENGTH,
1169+
NULL::VARCHAR2(4000) AS TYPE_TEXT,
1170+
NULL::NUMBER(38) AS OID_TEXT_LENGTH,
1171+
NULL::VARCHAR2(4000) AS OID_TEXT,
1172+
NULL::VARCHAR2(128) AS VIEW_TYPE_OWNER,
1173+
NULL::VARCHAR2(128) AS VIEW_TYPE,
1174+
NULL::VARCHAR2(128) AS SUPERVIEW_NAME,
1175+
NULL::VARCHAR2(1) AS EDITIONING_VIEW,
1176+
NULL::VARCHAR2(1) AS READ_ONLY,
1177+
NULL::VARCHAR2(1) AS CONTAINER_DATA,
1178+
NULL::VARCHAR2(12) AS BEQUEATH,
1179+
0::VARCHAR2(256) AS ORIGIN_CON_ID,
1180+
NULL::VARCHAR2(100) AS DEFAULT_COLLATION,
1181+
NULL::VARCHAR2(3) AS CONTAINERS_DEFAULT,
1182+
NULL::VARCHAR2(3) AS CONTAINER_MAP,
1183+
NULL::VARCHAR2(3) AS EXTENDED_DATA_LINK,
1184+
NULL::VARCHAR2(3) AS EXTENDED_DATA_LINK_MAP,
1185+
NULL::VARCHAR2(3) AS HAS_SENSITIVE_COLUMN,
1186+
NULL::VARCHAR2(3) AS ADMIT_NULL,
1187+
NULL::VARCHAR2(3) AS PDB_LOCAL_ONLY
1188+
FROM
1189+
PG_CLASS AS C
1190+
WHERE
1191+
C.RELKIND = 'v'
1192+
AND PG_GET_USERBYID(C.RELOWNER) = CURRENT_USER;
1193+
GRANT SELECT ON SYS.USER_VIEWS TO PUBLIC;
10911194

contrib/tsm_system_rows/expected/tsm_system_rows.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ SELECT * FROM vv;
7777
20
7878
(1 row)
7979

80-
DROP EXTENSION tsm_system_rows; -- fail, view depends on extension
80+
DROP EXTENSION tsm_system_rows; -- fail, view depends on extension ,but success in Oracle because of FORCE VIEW
8181
ERROR: cannot drop extension tsm_system_rows because other objects depend on it
8282
DETAIL: view vv depends on function system_rows(internal)
8383
HINT: Use DROP ... CASCADE to drop the dependent objects too.

contrib/tsm_system_rows/expected/tsm_system_rows_1.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ SELECT * FROM vv;
7777
20
7878
(1 row)
7979

80-
DROP EXTENSION tsm_system_rows; -- fail, view depends on extension
80+
DROP EXTENSION tsm_system_rows; -- fail, view depends on extension ,but success in Oracle because of FORCE VIEW
8181
ERROR: cannot drop extension tsm_system_rows because other objects depend on it
8282
DETAIL: view vv depends on function system_rows(internal)
8383
HINT: Use DROP ... CASCADE to drop the dependent objects too.

contrib/tsm_system_rows/sql/tsm_system_rows.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ CREATE VIEW vv AS
3636

3737
SELECT * FROM vv;
3838

39-
DROP EXTENSION tsm_system_rows; -- fail, view depends on extension
39+
DROP EXTENSION tsm_system_rows; -- fail, view depends on extension ,but success in Oracle because of FORCE VIEW

contrib/tsm_system_time/expected/tsm_system_time.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM vv;
9494
Sampling: system_time ('20'::double precision)
9595
(2 rows)
9696

97-
DROP EXTENSION tsm_system_time; -- fail, view depends on extension
97+
DROP EXTENSION tsm_system_time; -- fail, view depends on extension ,but success in Oracle because of FORCE VIEW
9898
ERROR: cannot drop extension tsm_system_time because other objects depend on it
9999
DETAIL: view vv depends on function system_time(internal)
100100
HINT: Use DROP ... CASCADE to drop the dependent objects too.

contrib/tsm_system_time/expected/tsm_system_time_1.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM vv;
9494
Sampling: system_time ('20'::pg_catalog.float8)
9595
(2 rows)
9696

97-
DROP EXTENSION tsm_system_time; -- fail, view depends on extension
97+
DROP EXTENSION tsm_system_time; -- fail, view depends on extension ,but success in Oracle because of FORCE VIEW
9898
ERROR: cannot drop extension tsm_system_time because other objects depend on it
9999
DETAIL: view vv depends on function system_time(internal)
100100
HINT: Use DROP ... CASCADE to drop the dependent objects too.

contrib/tsm_system_time/sql/tsm_system_time.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,4 @@ CREATE VIEW vv AS
4848

4949
EXPLAIN (COSTS OFF) SELECT * FROM vv;
5050

51-
DROP EXTENSION tsm_system_time; -- fail, view depends on extension
51+
DROP EXTENSION tsm_system_time; -- fail, view depends on extension ,but success in Oracle because of FORCE VIEW

src/backend/catalog/dependency.c

Lines changed: 141 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
#include "commands/sequence.h"
8080
#include "commands/trigger.h"
8181
#include "commands/typecmds.h"
82+
#include "commands/tablecmds.h"
83+
#include "commands/view.h"
8284
#include "funcapi.h"
8385
#include "miscadmin.h"
8486
#include "nodes/nodeFuncs.h"
@@ -89,9 +91,9 @@
8991
#include "utils/lsyscache.h"
9092
#include "utils/syscache.h"
9193
#include "utils/packagecache.h"
92-
#include "commands/tablecmds.h"
93-
#include "funcapi.h"
9494
#include "lib/qunique.h"
95+
#include "utils/ora_compatible.h"
96+
#include "utils/guc.h"
9597

9698

9799

@@ -162,7 +164,8 @@ static void findDependentObjects(const ObjectAddress *object,
162164
static void reportDependentObjects(const ObjectAddresses *targetObjects,
163165
DropBehavior behavior,
164166
int flags,
165-
const ObjectAddress *origObject);
167+
const ObjectAddress *origObject,
168+
bool *refinddepobjects);
166169
static void deleteOneObject(const ObjectAddress *object,
167170
Relation *depRel, int32 flags);
168171
static void doDeletion(const ObjectAddress *object, int flags);
@@ -284,6 +287,7 @@ performDeletion(const ObjectAddress *object,
284287
{
285288
Relation depRel;
286289
ObjectAddresses *targetObjects;
290+
bool need_refinddepobj = false;
287291

288292
/*
289293
* We save some cycles by opening pg_depend just once and passing the
@@ -317,7 +321,22 @@ performDeletion(const ObjectAddress *object,
317321
reportDependentObjects(targetObjects,
318322
behavior,
319323
flags,
320-
object);
324+
object,
325+
&need_refinddepobj);
326+
327+
if (ORA_PARSER == compatible_db && need_refinddepobj)
328+
{
329+
free_object_addresses(targetObjects);
330+
targetObjects = new_object_addresses();
331+
332+
findDependentObjects(object,
333+
DEPFLAG_ORIGINAL,
334+
flags,
335+
NULL, /* empty stack */
336+
targetObjects,
337+
NULL, /* no pendingObjects */
338+
&depRel);
339+
}
321340

322341
/* do the deed */
323342
deleteObjectsInList(targetObjects, &depRel, flags);
@@ -344,6 +363,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
344363
Relation depRel;
345364
ObjectAddresses *targetObjects;
346365
int i;
366+
bool need_refinddepobj = false;
347367

348368
/* No work if no objects... */
349369
if (objects->numrefs <= 0)
@@ -393,7 +413,33 @@ performMultipleDeletions(const ObjectAddresses *objects,
393413
reportDependentObjects(targetObjects,
394414
behavior,
395415
flags,
396-
(objects->numrefs == 1 ? objects->refs : NULL));
416+
(objects->numrefs == 1 ? objects->refs : NULL),
417+
&need_refinddepobj);
418+
419+
420+
if (ORA_PARSER == compatible_db && need_refinddepobj)
421+
{
422+
free_object_addresses(targetObjects);
423+
targetObjects = new_object_addresses();
424+
425+
for (i = 0; i < objects->numrefs; i++)
426+
{
427+
const ObjectAddress *thisobj = objects->refs + i;
428+
429+
/*
430+
* Obtain a deletion lock for every target object. (Preferably, this should have been handled by the caller, but in reality, many callers neglect to do so.)
431+
*/
432+
AcquireDeletionLock(thisobj, flags);
433+
434+
findDependentObjects(thisobj,
435+
DEPFLAG_ORIGINAL,
436+
flags,
437+
NULL, /* empty stack */
438+
targetObjects,
439+
objects,
440+
&depRel);
441+
}
442+
}
397443

398444
/* do the deed */
399445
deleteObjectsInList(targetObjects, &depRel, flags);
@@ -1065,7 +1111,7 @@ findDependentObjects(const ObjectAddress *object,
10651111
}
10661112

10671113
/*
1068-
* Find out the dependent funciton which uses %TYPE or %ROWTYPE
1114+
* Find out the dependent funciton which uses %TYPE or %ROWTYPE
10691115
* in parameters datatype or return datatype.
10701116
*/
10711117
for (int i = 0; i < numDependentFuncPkgOids; i++)
@@ -1171,7 +1217,8 @@ static void
11711217
reportDependentObjects(const ObjectAddresses *targetObjects,
11721218
DropBehavior behavior,
11731219
int flags,
1174-
const ObjectAddress *origObject)
1220+
const ObjectAddress *origObject,
1221+
bool *refinddepobj)
11751222
{
11761223
int msglevel = (flags & PERFORM_DELETION_QUIETLY) ? DEBUG2 : NOTICE;
11771224
bool ok = true;
@@ -1219,6 +1266,89 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
12191266
!message_level_is_interesting(msglevel))
12201267
return;
12211268

1269+
if (ORA_PARSER == compatible_db && behavior == DROP_RESTRICT)
1270+
{
1271+
/* Check if all dependencies that require CASCADE are views */
1272+
bool all_cascade_dep_is_view = true;
1273+
ObjectAddresses *viewObjects;
1274+
1275+
viewObjects = new_object_addresses();
1276+
1277+
for (i = targetObjects->numrefs - 1; i >= 0; i--)
1278+
{
1279+
const ObjectAddress *obj = &targetObjects->refs[i];
1280+
const ObjectAddressExtra *extra = &targetObjects->extras[i];
1281+
char *objDesc;
1282+
1283+
/* Skip the initial objects requested for deletion */
1284+
if (extra->flags & DEPFLAG_ORIGINAL)
1285+
continue;
1286+
1287+
/* Skip reporting for subcomponents, handled elsewhere */
1288+
if (extra->flags & DEPFLAG_SUBOBJECT)
1289+
continue;
1290+
1291+
objDesc = getObjectDescription(obj, false);
1292+
1293+
/* Ignore objects that are being dropped concurrently */
1294+
if (objDesc == NULL)
1295+
continue;
1296+
1297+
/*
1298+
* If the object was found via an automatic, internal, partition, or extension dependency,
1299+
* it is permitted to be removed even with RESTRICT.
1300+
*/
1301+
if (extra->flags & (DEPFLAG_AUTO |
1302+
DEPFLAG_INTERNAL |
1303+
DEPFLAG_PARTITION |
1304+
DEPFLAG_EXTENSION))
1305+
{
1306+
/*
1307+
* Log automatic cascades at DEBUG2 level for clarity.
1308+
*/
1309+
ereport(DEBUG2,
1310+
(errmsg_internal("drop auto-cascades to %s",
1311+
objDesc)));
1312+
}
1313+
else if (extra->flags & DEPFLAG_TYPE)
1314+
{
1315+
pfree(objDesc);
1316+
continue;
1317+
}
1318+
else
1319+
{
1320+
/* If any dependent object is not a view, set flag and exit loop */
1321+
if (get_rel_relkind(obj->objectId) != RELKIND_VIEW)
1322+
{
1323+
all_cascade_dep_is_view = false;
1324+
pfree(objDesc);
1325+
break;
1326+
}
1327+
else
1328+
add_exact_object_address(obj, viewObjects);
1329+
}
1330+
pfree(objDesc);
1331+
}
1332+
1333+
/* If all dependencies are views, mark them as invalid and trigger a recheck */
1334+
if (all_cascade_dep_is_view && viewObjects->numrefs > 0)
1335+
{
1336+
for (i = viewObjects->numrefs - 1; i >= 0; i--)
1337+
{
1338+
make_view_invalid(viewObjects->refs[i].objectId);
1339+
}
1340+
1341+
/*
1342+
* After invalidating views, re-evaluate dependencies to ensure consistency.
1343+
*/
1344+
if (refinddepobj)
1345+
*refinddepobj = true;
1346+
return;
1347+
}
1348+
1349+
free_object_addresses(viewObjects);
1350+
}
1351+
12221352
/*
12231353
* We limit the number of dependencies reported to the client to
12241354
* MAX_REPORTED_DEPS, since client software may not deal well with
@@ -1577,6 +1707,10 @@ doDeletion(const ObjectAddress *object, int flags)
15771707
*/
15781708
if (relKind == RELKIND_SEQUENCE)
15791709
DeleteSequenceTuple(object->objectId);
1710+
1711+
if (ORA_PARSER == compatible_db && relKind == RELKIND_VIEW)
1712+
DeleteForceView(object->objectId);
1713+
15801714
break;
15811715
}
15821716

0 commit comments

Comments
 (0)