Skip to content

Commit ffa832f

Browse files
R4hul04Rahul Parande
authored andcommitted
Support for weak binding views to allow dropping of underlying objects BABEL_4_X_DEV (babelfish-for-postgresql#3965)
* Support for weak binding views to allow dropping of underlying objects.This commit introduces support for both strong and weak view binding in Babelfish, aligning more closely with SQL Server's default behavior while maintaining flexibility. (babelfish-for-postgresql#3806) Description Currently, Babelfish only supports strong binding for views, which prevents dropping or altering referenced objects when views depend on them. This behavior differs from SQL Server, which by default allows dropping underlying tables or views unless WITH SCHEMABINDING is explicitly specified. With this change, Babelfish now supports configurable view binding modes: Strong binding (default): Prevents dropping referenced objects if views depend on them Weak binding: Allows dropping of referenced objects This feature aligns Babelfish more closely with SQL Server's behavior, providing greater flexibility Key aspects include: A new GUC parameter babelfishpg_tsql.weak_view_binding to control the default binding behavior (default is false) Support for explicit WITH SCHEMABINDING to create strongly bound views regardless of the GUC setting Ability to create weakly bound views by default when the GUC is enabled Proper handling of ALTER VIEW operations in both binding modes In SQL Server, views are weakly bound by default, allowing underlying objects to be dropped or altered. With our implementation, users can now choose between SQL Server's default behavior (weak binding) or the previously enforced behavior (strong binding). Important Limitation : This implementation currently only addresses DROP operations on tables, views, functions, procedures as well as ALTER operations on views when these objects are bound by dependent views. ALTER TABLE/ ALTER FUNCTION operations (such as dropping columns or changing data types) are still restricted when dependent views exist, regardless of binding mode. This differs from SQL Server's behavior, where weak binding also allows ALTER operations on referenced objects. When the same underlying object is recreated, its broken child view will get repaired only if it follows postgresql restrictions for CREATE OR REPLACE VIEW. [The new query must generate the same columns that were generated by the existing view query (that is, the same column names in the same order and with the same data types), but it may add additional columns to the end of the list] https://www.postgresql.org/docs/current/sql-createview.html#:~:text=The%20new%20query,be%20completely%20different. Issues Resolved BABEL-1660 * Fix crash during tuple update for broken view by registering an active transaction snapshot --------- Signed-off-by: Rahul Parande <rparande@amazon.com> Co-authored-by: Rahul Parande <rparande@amazon.com>
1 parent 61f1675 commit ffa832f

39 files changed

+5085
-33
lines changed

contrib/babelfishpg_tsql/runtime/functions.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4482,8 +4482,14 @@ objectproperty_internal(PG_FUNCTION_ARGS)
44824482
*/
44834483
if (pg_strcasecmp(property, "isschemabound") == 0)
44844484
{
4485+
bool is_weak_view = false;
4486+
bool is_view = (type == OBJECT_TYPE_VIEW);
4487+
4488+
if (is_view)
4489+
check_is_tsql_view(object_id, &is_weak_view);
4490+
44854491
pfree(property);
4486-
PG_RETURN_INT32(0);
4492+
PG_RETURN_INT32(is_view ? ((int) !is_weak_view) : 0);
44874493
}
44884494
/*
44894495
* For ExecIsQuotedIdentOn and ExecIsAnsiNullsOn, we hardcoded it to 1

contrib/babelfishpg_tsql/src/catalog.c

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,17 +1198,40 @@ get_bbf_view_def_idx_oid()
11981198
}
11991199

12001200
HeapTuple
1201-
search_bbf_view_def(Relation bbf_view_def_rel, int16 dbid, const char *logical_schema_name, const char *view_name)
1201+
search_bbf_view_def(Relation bbf_view_def_rel, Oid viewOid)
12021202
{
12031203

12041204
ScanKeyData scanKey[3];
12051205
SysScanDesc scan;
12061206
HeapTuple scantup,
12071207
oldtup;
1208+
Oid schema_id;
1209+
char *schema_name = NULL;
1210+
char *view_name = NULL;
1211+
const char *logical_schema_name = NULL;
1212+
int16 dbid = InvalidDbid;
12081213

1209-
if (!DbidIsValid(dbid) || logical_schema_name == NULL || view_name == NULL)
1214+
if (!OidIsValid(viewOid))
12101215
return NULL;
12111216

1217+
schema_id = get_rel_namespace(viewOid);
1218+
schema_name = get_namespace_name(schema_id);
1219+
view_name = get_rel_name(viewOid);
1220+
1221+
if (!schema_name)
1222+
return NULL;
1223+
1224+
logical_schema_name = get_logical_schema_name(schema_name, true);
1225+
dbid = get_dbid_from_physical_schema_name(schema_name, true);
1226+
1227+
if (!DbidIsValid(dbid) || logical_schema_name == NULL || view_name == NULL)
1228+
{
1229+
pfree(view_name);
1230+
pfree(schema_name);
1231+
if (logical_schema_name)
1232+
pfree((char *) logical_schema_name);
1233+
return NULL;
1234+
}
12121235

12131236
/* Search and drop the definition */
12141237
ScanKeyInit(&scanKey[0],
@@ -1238,7 +1261,7 @@ search_bbf_view_def(Relation bbf_view_def_rel, int16 dbid, const char *logical_s
12381261

12391262
/* Checks if it is view created during v2.2.0 or after that */
12401263
bool
1241-
check_is_tsql_view(Oid relid)
1264+
check_is_tsql_view(Oid relid, bool *is_weak_view)
12421265
{
12431266
Oid schema_oid;
12441267
Relation bbf_view_def_rel;
@@ -1248,10 +1271,17 @@ check_is_tsql_view(Oid relid)
12481271
int16 logical_dbid;
12491272
const char *logical_schema_name;
12501273
bool is_tsql_view = false;
1274+
bool bisnull;
1275+
Datum flag_values_datum;
1276+
uint64 flag_values;
12511277

12521278
view_name = get_rel_name(relid);
12531279
schema_oid = get_rel_namespace(relid);
12541280
schema_name = get_namespace_name(schema_oid);
1281+
1282+
if (is_weak_view != NULL)
1283+
*is_weak_view = false;
1284+
12551285
if (view_name == NULL || schema_name == NULL || is_shared_schema(schema_name))
12561286
{
12571287
if (view_name)
@@ -1272,12 +1302,27 @@ check_is_tsql_view(Oid relid)
12721302
}
12731303
/* Fetch the relation */
12741304
bbf_view_def_rel = table_open(get_bbf_view_def_oid(), AccessShareLock);
1275-
1276-
scantup = search_bbf_view_def(bbf_view_def_rel, logical_dbid, logical_schema_name, view_name);
1305+
scantup = search_bbf_view_def(bbf_view_def_rel, relid);
12771306

12781307
if (HeapTupleIsValid(scantup))
12791308
{
12801309
is_tsql_view = true;
1310+
1311+
/* Check if the view is a weak bound view */
1312+
if (is_weak_view != NULL)
1313+
{
1314+
flag_values_datum = heap_getattr(scantup,
1315+
Anum_bbf_view_def_flag_values,
1316+
RelationGetDescr(bbf_view_def_rel),
1317+
&bisnull);
1318+
1319+
if (!bisnull)
1320+
{
1321+
flag_values = DatumGetUInt64(flag_values_datum);
1322+
*is_weak_view = (flag_values & BBF_VIEW_DEF_FLAG_IS_WEAK_VIEW) != 0;
1323+
}
1324+
}
1325+
12811326
heap_freetuple(scantup);
12821327
}
12831328
table_close(bbf_view_def_rel, AccessShareLock);

contrib/babelfishpg_tsql/src/catalog.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,18 +201,22 @@ typedef FormData_authid_user_ext *Form_authid_user_ext;
201201
#define Anum_bbf_view_def_schema_name 2
202202
#define Anum_bbf_view_def_object_name 3
203203
#define Anum_bbf_view_def_definition 4
204+
#define Anum_bbf_view_def_flag_validity 5
205+
#define Anum_bbf_view_def_flag_values 6
204206
#define BBF_VIEW_DEF_NUM_COLS 8
205207
#define BBF_VIEW_DEF_FLAG_IS_ANSI_NULLS_ON (1<<0)
206208
#define BBF_VIEW_DEF_FLAG_USES_QUOTED_IDENTIFIER (1<<1)
207209
#define BBF_VIEW_DEF_FLAG_CREATED_IN_OR_AFTER_2_4 (0<<2)
210+
#define BBF_VIEW_DEF_FLAG_IS_WEAK_VIEW (1<<3)
211+
#define BBF_VIEW_DEF_FLAG_IS_BROKEN (1<<4)
212+
208213
extern Oid bbf_view_def_oid;
209214
extern Oid bbf_view_def_idx_oid;
210215

211216
extern Oid get_bbf_view_def_oid(void);
212217
extern Oid get_bbf_view_def_idx_oid(void);
213-
extern HeapTuple search_bbf_view_def(Relation bbf_view_def_rel, int16 dbid,
214-
const char *logical_schema_name, const char *view_name);
215-
extern bool check_is_tsql_view(Oid relid);
218+
extern HeapTuple search_bbf_view_def(Relation bbf_view_def_rel, Oid viewOid);
219+
extern bool check_is_tsql_view(Oid relid, bool *is_weak_view);
216220
extern void clean_up_bbf_view_def(int16 dbid);
217221
extern void drop_bbf_schema_permission_entries(int16 dbid);
218222

contrib/babelfishpg_tsql/src/guc.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define PLTSQL_DEFAULT_LANGUAGE "us_english"
1919

2020
static int migration_mode = SINGLE_DB;
21+
bool pltsql_weak_view_binding = false;
2122
bool enable_ownership_structure = false;
2223

2324
bool enable_metadata_inconsistency_check = true;
@@ -630,6 +631,16 @@ define_custom_variables(void)
630631
GUC_NO_RESET_ALL,
631632
NULL, NULL, NULL);
632633

634+
DefineCustomBoolVariable("babelfishpg_tsql.weak_view_binding",
635+
gettext_noop("Sets the default binding mode for views."),
636+
gettext_noop("When set to false (default), views will bind to the schema of its underlying tables or other objects"
637+
"When set to true, views created will have weak binding and are no longer bound to schema of its underlying"
638+
"objects unless explicitly declared in create/alter DDL"),
639+
&pltsql_weak_view_binding,
640+
false, /* Default is strong binding (false) */
641+
PGC_USERSET,
642+
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_DISALLOW_IN_AUTO_FILE,
643+
NULL, NULL, NULL);
633644

634645
/* ANTLR parser */
635646
DefineCustomBoolVariable("babelfishpg_tsql.dump_antlr_query_graph",

contrib/babelfishpg_tsql/src/guc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern bool pltsql_enable_create_alter_view_from_pg;
2020
extern bool pltsql_enable_linked_servers;
2121
extern bool pltsql_allow_windows_login;
2222
extern bool pltsql_allow_fulltext_parser;
23+
extern bool pltsql_weak_view_binding;
2324
extern char *pltsql_psql_logical_babelfish_db_name;
2425
extern int pltsql_isolation_level_repeatable_read;
2526
extern int pltsql_isolation_level_serializable;

0 commit comments

Comments
 (0)