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"
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,
162164static void reportDependentObjects (const ObjectAddresses * targetObjects ,
163165 DropBehavior behavior ,
164166 int flags ,
165- const ObjectAddress * origObject );
167+ const ObjectAddress * origObject ,
168+ bool * refinddepobjects );
166169static void deleteOneObject (const ObjectAddress * object ,
167170 Relation * depRel , int32 flags );
168171static 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
11711217reportDependentObjects (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