From: <di...@us...> - 2014-11-09 16:41:00
|
Revision: 60183 http://sourceforge.net/p/firebird/code/60183 Author: dimitr Date: 2014-11-09 16:40:52 +0000 (Sun, 09 Nov 2014) Log Message: ----------- Relaxed system tables protection for cases UPDATE ... SET RDB$*_SOURCE = NULL. So far nullification is allowed for views/packages/procedures/functions/triggers only. I'm not sure somebody really needs hiding sources for defaults and check constraints, but this can be supported later, if required. This is a temporary solution, intended to be replaced with something more clever (e.g. special permissions or new DDL command) in v4. Modified Paths: -------------- firebird/trunk/src/jrd/vio.cpp Modified: firebird/trunk/src/jrd/vio.cpp =================================================================== --- firebird/trunk/src/jrd/vio.cpp 2014-11-09 14:47:08 UTC (rev 60182) +++ firebird/trunk/src/jrd/vio.cpp 2014-11-09 16:40:52 UTC (rev 60183) @@ -95,6 +95,7 @@ using namespace Firebird; static void check_class(thread_db*, jrd_tra*, record_param*, record_param*, USHORT); +static bool check_nullify_source(record_param*, record_param*, USHORT); static void check_owner(thread_db*, jrd_tra*, record_param*, record_param*, USHORT); static bool check_user(thread_db*, const dsc*); static int check_precommitted(const jrd_tra*, const record_param*); @@ -2501,7 +2502,8 @@ break; case rel_relations: - protect_system_table_delupd(tdbb, relation, "UPDATE"); + if (!check_nullify_source(org_rpb, new_rpb, f_rel_source)) + protect_system_table_delupd(tdbb, relation, "UPDATE"); EVL_field(0, org_rpb->rpb_record, f_rel_name, &desc1); SCL_check_relation(tdbb, &desc1, SCL_alter); check_class(tdbb, transaction, org_rpb, new_rpb, f_rel_class); @@ -2510,7 +2512,8 @@ break; case rel_packages: - protect_system_table_delupd(tdbb, relation, "UPDATE"); + if (!check_nullify_source(org_rpb, new_rpb, f_pkg_header_source)) + protect_system_table_delupd(tdbb, relation, "UPDATE"); if (EVL_field(0, org_rpb->rpb_record, f_pkg_name, &desc1)) SCL_check_package(tdbb, &desc1, SCL_alter); check_class(tdbb, transaction, org_rpb, new_rpb, f_pkg_class); @@ -2518,7 +2521,8 @@ break; case rel_procedures: - protect_system_table_delupd(tdbb, relation, "UPDATE"); + if (!check_nullify_source(org_rpb, new_rpb, f_prc_source)) + protect_system_table_delupd(tdbb, relation, "UPDATE"); EVL_field(0, org_rpb->rpb_record, f_prc_name, &desc1); if (EVL_field(0, org_rpb->rpb_record, f_prc_pkg_name, &desc2)) @@ -2543,7 +2547,8 @@ break; case rel_funs: - protect_system_table_delupd(tdbb, relation, "UPDATE"); + if (!check_nullify_source(org_rpb, new_rpb, f_fun_source)) + protect_system_table_delupd(tdbb, relation, "UPDATE"); EVL_field(0, org_rpb->rpb_record, f_fun_name, &desc1); if (EVL_field(0, org_rpb->rpb_record, f_fun_pkg_name, &desc2)) @@ -2670,7 +2675,8 @@ break; case rel_triggers: - protect_system_table_delupd(tdbb, relation, "UPDATE"); + if (!check_nullify_source(org_rpb, new_rpb, f_trg_source)) + protect_system_table_delupd(tdbb, relation, "UPDATE"); EVL_field(0, new_rpb->rpb_record, f_trg_rname, &desc1); SCL_check_relation(tdbb, &desc1, SCL_control); @@ -4057,6 +4063,45 @@ } +/************************************** + * + * c h e c k _ n u l l i f y _ s o u r c e + * + ************************************** + * + * Functional description + * A record in a system relation containing a source blob is + * being changed. Check to see if only the source blob has changed, + * and if so, validate whether it was an assignment to NULL. + * + **************************************/ +static bool check_nullify_source(record_param* org_rpb, record_param* new_rpb, USHORT field_id) +{ + bool nullify_found = false; + + dsc org_desc, new_desc; + for (USHORT iter = 0; iter < org_rpb->rpb_record->rec_format->fmt_count; ++iter) + { + const bool org_null = !EVL_field(NULL, org_rpb->rpb_record, iter, &org_desc); + const bool new_null = !EVL_field(NULL, new_rpb->rpb_record, iter, &new_desc); + + if (iter == field_id && new_null) + { + fb_assert(org_desc.dsc_dtype == dtype_blob); + fb_assert(new_desc.dsc_dtype == dtype_blob); + + nullify_found = true; + continue; + } + + if (org_null != new_null || MOV_compare(&org_desc, &new_desc)) + return false; + } + + return nullify_found; +} + + static void check_owner(thread_db* tdbb, jrd_tra* transaction, record_param* old_rpb, record_param* new_rpb, USHORT id) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |