diff --git a/src/jrd/dfw.epp b/src/jrd/dfw.epp index 080d9a9958..2c38d5283a 100644 --- a/src/jrd/dfw.epp +++ b/src/jrd/dfw.epp @@ -766,18 +766,15 @@ static bool add_file(thread_db* tdbb, SSHORT phase, DeferredWork* work, case 3: if (CCH_exclusive(tdbb, LCK_EX, WAIT_PERIOD)) - { return true; - } - else - { - ERR_post(isc_no_meta_update, - isc_arg_gds, isc_lock_timeout, - isc_arg_gds, isc_obj_in_use, - isc_arg_string, ERR_cstring(dbb->dbb_filename.c_str()), - 0); - return false; - } + + ERR_post(isc_no_meta_update, + isc_arg_gds, isc_lock_timeout, + isc_arg_gds, isc_obj_in_use, + isc_arg_string, ERR_cstring(dbb->dbb_filename.c_str()), + 0); + return false; + case 4: CCH_flush(tdbb, FLUSH_FINI, 0L); max = PageSpace::maxAlloc(dbb) + 1; @@ -1255,7 +1252,7 @@ static void check_dependencies(thread_db* tdbb, AND DEP.RDB$DEPENDED_ON_TYPE = dpdo_type AND DEP.RDB$FIELD_NAME EQ field_name REDUCED TO DEP.RDB$DEPENDENT_NAME - if (!REQUEST(irq_ch_f_dpd)) + if (!REQUEST(irq_ch_f_dpd)) REQUEST(irq_ch_f_dpd) = request; /* If the found object is also being deleted, there's no dependency */ @@ -1266,7 +1263,7 @@ static void check_dependencies(thread_db* tdbb, 0, transaction)) { - dep_counts[DEP.RDB$DEPENDENT_TYPE]++; + ++dep_counts[DEP.RDB$DEPENDENT_TYPE]; } END_FOR; @@ -1283,7 +1280,7 @@ static void check_dependencies(thread_db* tdbb, AND DEP.RDB$DEPENDED_ON_TYPE = dpdo_type REDUCED TO DEP.RDB$DEPENDENT_NAME - if (!REQUEST(irq_ch_dpd)) + if (!REQUEST(irq_ch_dpd)) REQUEST(irq_ch_dpd) = request; /* If the found object is also being deleted, there's no dependency */ @@ -1294,7 +1291,7 @@ static void check_dependencies(thread_db* tdbb, 0, transaction)) { - dep_counts[DEP.RDB$DEPENDENT_TYPE]++; + ++dep_counts[DEP.RDB$DEPENDENT_TYPE]; } END_FOR; @@ -1302,59 +1299,69 @@ static void check_dependencies(thread_db* tdbb, REQUEST(irq_ch_dpd) = request; } - for (i = 0; i < obj_type_MAX; i++) { - if (dep_counts[i]) + SLONG total = 0; + for (i = 0; i < obj_type_MAX; i++) + total += dep_counts[i]; + + if (!total) + return; + + if (field_name) + { + ERR_post( isc_no_meta_update, + isc_arg_gds, isc_no_delete, /* Msg353: can not delete */ + isc_arg_gds, isc_field_name, + isc_arg_string, ERR_cstring(field_name), + isc_arg_gds, isc_dependency, + isc_arg_number, total, + 0); /* Msg310: there are %ld dependencies */ + } + else + { + ISC_STATUS obj_type; + switch (dpdo_type) { - ISC_STATUS obj_type; - switch (dpdo_type) - { - case obj_relation: - obj_type = isc_table_name; - break; - case obj_procedure: - obj_type = isc_proc_name; - break; - case obj_collation: - obj_type = isc_collation_name; - break; - case obj_exception: - obj_type = isc_exception_name; - break; - case obj_field: - obj_type = isc_domain_name; - break; - case obj_generator: - obj_type = isc_generator_name; - break; - case obj_udf: - obj_type = isc_udf_name; - break; - case obj_index: - obj_type = isc_index_name; - break; - default: - fb_assert(FALSE); - break; - } - if (field_name) { - ERR_post( isc_no_meta_update, - isc_arg_gds, isc_no_delete, /* Msg353: can not delete */ - isc_arg_gds, isc_field_name, - isc_arg_string, ERR_cstring(field_name), - isc_arg_gds, isc_dependency, - isc_arg_number, dep_counts[i], - 0); /* Msg310: there are %ld dependencies */ - } - else { - ERR_post( isc_no_meta_update, - isc_arg_gds, isc_no_delete, /* can not delete */ - isc_arg_gds, obj_type, - isc_arg_string, ERR_cstring(dpdo_name), - isc_arg_gds, isc_dependency, - isc_arg_number, dep_counts[i], - 0); /* there are %ld dependencies */ - } + case obj_relation: + obj_type = isc_table_name; + break; + /* Currently we don't get this type due to an internal bug. + case obj_view: + obj_type = isc_view_name; + break; + */ + case obj_procedure: + obj_type = isc_proc_name; + break; + case obj_collation: + obj_type = isc_collation_name; + break; + case obj_exception: + obj_type = isc_exception_name; + break; + case obj_field: + obj_type = isc_domain_name; + break; + case obj_generator: + obj_type = isc_generator_name; + break; + case obj_udf: + obj_type = isc_udf_name; + break; + case obj_index: + obj_type = isc_index_name; + break; + default: + fb_assert(FALSE); + break; } + + ERR_post( isc_no_meta_update, + isc_arg_gds, isc_no_delete, /* can not delete */ + isc_arg_gds, obj_type, + isc_arg_string, ERR_cstring(dpdo_name), + isc_arg_gds, isc_dependency, + isc_arg_number, total, + 0); /* there are %ld dependencies */ } } @@ -2096,7 +2103,6 @@ static bool create_relation(thread_db* tdbb, lock->lck_type = LCK_relation; lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type); lock->lck_parent = dbb->dbb_lock; - lock->lck_owner = tdbb->getAttachment(); LCK_lock_non_blocking(tdbb, lock, LCK_EX, LCK_WAIT); @@ -4333,6 +4339,7 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, dbb->dbb_sys_trans, &REL.RDB$RUNTIME); jrd_req* request_fmtx = CMP_find_request(tdbb, irq_format2, IRQ_REQUESTS); + FOR(REQUEST_HANDLE request_fmtx) RFR IN RDB$RELATION_FIELDS CROSS FLD IN RDB$FIELDS WITH @@ -4511,7 +4518,7 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, if (!REQUEST(irq_format2)) REQUEST(irq_format2) = request_fmtx; - if (!physical_fields) + if (null_view && !physical_fields) { EXE_unwind(tdbb, request_fmt1); ERR_post(isc_no_meta_update, @@ -4580,6 +4587,7 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, relation->rel_flags &= ~REL_scanned; DFW_post_work(transaction, dfw_scan_relation, NULL, relation->rel_id); + break; } @@ -4649,7 +4657,7 @@ static bool modify_procedure( thread_db* tdbb, ERR_post(isc_no_meta_update, isc_arg_gds, isc_obj_in_use, isc_arg_string, ERR_cstring(work->dfw_name), - 0); + 0); } } @@ -4667,12 +4675,6 @@ static bool modify_procedure( thread_db* tdbb, try { -#ifdef SUPERSERVER - if (!(tdbb->getDatabase()->dbb_flags & DBB_sp_rec_mutex_init)) - { - THD_rec_mutex_init(&tdbb->getDatabase()->dbb_sp_rec_mutex); - tdbb->getDatabase()->dbb_flags |= DBB_sp_rec_mutex_init; - } THREAD_EXIT(); if (THD_rec_mutex_lock(&tdbb->getDatabase()->dbb_sp_rec_mutex)) { @@ -4680,7 +4682,7 @@ static bool modify_procedure( thread_db* tdbb, return false; } THREAD_ENTER(); -#endif /* SUPERSERVER */ + // Do not allow to modify procedure used by user requests if (procedure->prc_use_count && MET_procedure_in_use(tdbb, procedure)) { @@ -4715,9 +4717,7 @@ static bool modify_procedure( thread_db* tdbb, true, PRC_being_altered))) { -#ifdef SUPERSERVER THD_rec_mutex_unlock(&tdbb->getDatabase()->dbb_sp_rec_mutex); -#endif return false; } procedure->prc_alter_count = ++prc_alter_count; @@ -4771,16 +4771,11 @@ static bool modify_procedure( thread_db* tdbb, catch (const Firebird::Exception& ex) { Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); -#ifdef SUPERSERVER THD_rec_mutex_unlock(&tdbb->getDatabase()->dbb_sp_rec_mutex); -#endif ERR_punt(); } -#ifdef SUPERSERVER THD_rec_mutex_unlock(&tdbb->getDatabase()->dbb_sp_rec_mutex); -#endif - return true; case 5: @@ -5132,7 +5127,7 @@ static Lock* protect_relation(thread_db* tdbb, jrd_tra* transaction, jrd_rel* re * releaseLock set to true if there was no existing lock before * **************************************/ - Lock* relLock = RLCK_transaction_relation_lock(transaction, relation); + Lock* relLock = RLCK_transaction_relation_lock(tdbb, transaction, relation); releaseLock = (relLock->lck_logical == LCK_none); @@ -5489,9 +5484,7 @@ static bool validate_text_type(thread_db* tdbb, { return false; } - else { - return true; - } + + return true; } - diff --git a/src/jrd/dmp.cpp b/src/jrd/dmp.cpp index df431ed935..21f9b9e46f 100644 --- a/src/jrd/dmp.cpp +++ b/src/jrd/dmp.cpp @@ -897,16 +897,18 @@ static void dmp_pip(const page_inv_page* page, ULONG sequence) for (int n = 0; n < control->pgc_ppp;) { while (n < control->pgc_ppp) + { if (BIT(n)) break; - else - n++; + n++; + } fprintf(dbg_file, "%d - ", n); while (n < control->pgc_ppp) + { if (!BIT(n)) break; - else - n++; + n++; + } fprintf(dbg_file, "%d, ", n - 1); } diff --git a/src/jrd/dpm.epp b/src/jrd/dpm.epp index d3e68eeec9..9a9665d7d4 100644 --- a/src/jrd/dpm.epp +++ b/src/jrd/dpm.epp @@ -493,8 +493,7 @@ int DPM_compress( thread_db* tdbb, data_page* page) // This should also work just a little bit faster too. const SSHORT l = ROUNDUP(index->dpg_length, ODS_ALIGNMENT); space -= l; - MOVE_FAST((UCHAR *) page + index->dpg_offset, temp_page + space, - l); + MOVE_FAST((UCHAR *) page + index->dpg_offset, temp_page + space, l); index->dpg_offset = space; } } @@ -927,8 +926,7 @@ void DPM_delete_relation_pages(Jrd::thread_db* tdbb, Jrd::jrd_rel* relation, Jrd } CCH_RELEASE_TAIL(tdbb, &data_window); } - PAG_release_page(PageNumber(relPages->rel_pg_space_id, *page), - ZERO_PAGE_NUMBER); + PAG_release_page(PageNumber(relPages->rel_pg_space_id, *page), ZERO_PAGE_NUMBER); } const UCHAR pag_flags = ppage->ppg_header.pag_flags; CCH_RELEASE_TAIL(tdbb, &window); @@ -946,8 +944,7 @@ void DPM_delete_relation_pages(Jrd::thread_db* tdbb, Jrd::jrd_rel* relation, Jrd /* Now get rid of the index root page */ PAG_release_page( - PageNumber(relPages->rel_pg_space_id, relPages->rel_index_root), - ZERO_PAGE_NUMBER); + PageNumber(relPages->rel_pg_space_id, relPages->rel_index_root), ZERO_PAGE_NUMBER); relPages->rel_index_root = 0; } @@ -1381,8 +1378,7 @@ ULONG DPM_get_blob(thread_db* tdbb, let somebody else complain. */ pointer_page* ppage = get_pointer_page(tdbb, blob->blb_relation, - blob->blb_relation->getPages(tdbb), &rpb.getWindow(tdbb), pp_sequence, - LCK_read); + blob->blb_relation->getPages(tdbb), &rpb.getWindow(tdbb), pp_sequence, LCK_read); if (!ppage) { blob->blb_flags |= BLB_damaged; return 0UL; @@ -1464,10 +1460,8 @@ ULONG DPM_get_blob(thread_db* tdbb, if (blob->blb_level == 0) { blob->blb_space_remaining = length; - UCHAR* p = blob->blb_data; - if (length) { - MOVE_FASTER(q, p, length); - } + if (length) + memcpy(blob->getBuffer(), q, length); } else { vcl* vector = blob->blb_pages; @@ -1476,7 +1470,7 @@ ULONG DPM_get_blob(thread_db* tdbb, vcl::newVector(*blob->blb_transaction->tra_pool, 0); } vector->resize(length / sizeof(SLONG)); - MOVE_FASTER(q, vector->memPtr(), length); + memcpy(vector->memPtr(), q, length); } if (!delete_flag) { @@ -1734,7 +1728,8 @@ void DPM_pages( jrd_req* request = CMP_find_request(tdbb, irq_s_pages, IRQ_REQUESTS); STORE(REQUEST_HANDLE request) - X IN RDB$PAGES X.RDB$RELATION_ID = rel_id; + X IN RDB$PAGES + X.RDB$RELATION_ID = rel_id; X.RDB$PAGE_TYPE = type; X.RDB$PAGE_SEQUENCE = sequence; X.RDB$PAGE_NUMBER = page; @@ -2005,12 +2000,35 @@ RecordNumber DPM_store_blob(thread_db* tdbb, blb* blob, Record* record) USHORT length; const UCHAR* q; PageStack stack; + Firebird::Array buffer; - if (blob->blb_level == 0) { + if (blob->blb_level == 0) + { length = blob->blb_clump_size - blob->blb_space_remaining; - q = (UCHAR *) ((blob_page*) blob->blb_data)->blp_page; + + if (!blob->hasBuffer()) + { + if (blob->blb_temp_size > 0) + { + blob->blb_transaction->getTempSpace()->read( + blob->blb_temp_offset, buffer.getBuffer(blob->blb_temp_size), + blob->blb_temp_size); + q = buffer.begin(); + } + else + { + fb_assert(length == 0); + q = NULL; + } + } + else + q = blob->getBuffer(); + + if (q) + q = (UCHAR*) ((blob_page*) q)->blp_page; } - else { + else + { vector = blob->blb_pages; length = vector->count() * sizeof(SLONG); q = (UCHAR *) (vector->begin()); @@ -2050,11 +2068,9 @@ RecordNumber DPM_store_blob(thread_db* tdbb, blb* blob, Record* record) header->blh_sub_type = blob->blb_sub_type; if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original) >= ODS_11_1) header->blh_charset = blob->blb_charset; - UCHAR* p = (UCHAR *) header->blh_page; - if (length) { - MOVE_FASTER(q, p, length); - } + if (length) + memcpy(header->blh_page, q, length); data_page* page = (data_page*) rpb.getWindow(tdbb).win_buffer; if (blob->blb_level && !(page->dpg_header.pag_flags & dpg_large)) { @@ -2308,13 +2324,11 @@ static void delete_tail(thread_db* tdbb, rhdf* header, const USHORT page_space, const SLONG* const end2 = page2 + ((bpage->blp_length - BLP_SIZE) / sizeof(SLONG)); while (page2 < end2) { - PAG_release_page(PageNumber(page_space, *page2++), - ZERO_PAGE_NUMBER); + PAG_release_page(PageNumber(page_space, *page2++), ZERO_PAGE_NUMBER); } CCH_RELEASE_TAIL(tdbb, &window); } - PAG_release_page(PageNumber(page_space, *page1), - ZERO_PAGE_NUMBER); + PAG_release_page(PageNumber(page_space, *page1), ZERO_PAGE_NUMBER); } } @@ -2991,8 +3005,8 @@ static rhd* locate_space( locked, then give up on the assumption that things are really screwed up. */ UCHAR* space = 0; - USHORT i; - for (i = 0; i < 20; i++) { + int i; + for (i = 0; i < 20; ++i) { DPM_allocate(tdbb, window); extend_relation(tdbb, relation, window); space = find_space(tdbb, rpb, size, stack, record, type); @@ -3170,8 +3184,9 @@ static void store_big_record(thread_db* tdbb, record_param* rpb, /* Start by finding the last data compression control block and set up to start decompression from the end. */ - DataComprControl* dcc; - for (dcc = head_dcc; dcc->dcc_next; dcc = dcc->dcc_next); + DataComprControl* dcc = head_dcc; + while (dcc->dcc_next) + dcc = dcc->dcc_next; const SCHAR* control = dcc->dcc_end; const SCHAR* in = (SCHAR *) rpb->rpb_address + rpb->rpb_length; diff --git a/src/jrd/drq.h b/src/jrd/drq.h index e870e6a091..d86df73d22 100644 --- a/src/jrd/drq.h +++ b/src/jrd/drq.h @@ -131,13 +131,13 @@ const int drq_e_prcs = 81; /* erase procedure */ const int drq_e_prms = 82; /* erase all of procedure's parameters */ const int drq_s_prm_src = 83; /* store parameter global field */ const int drq_s_intl_info = 84; /* store RDB$CHARACTER_FIELDS */ -const int drq_m_prcs = 85; /* modify procedure */ +const int drq_m_prcs = 85; /* modify procedure */ const int drq_s_log_files = 86; /* store log files */ const int drq_s_cache = 87; /* store cache */ const int drq_e_prm = 88; /* erase a procedure parameter */ const int drq_s_xcp = 89; /* store an exception */ const int drq_m_xcp = 90; /* modify an exception */ -const int drq_e_prc_prvs = 91; /* erase user privileges on procedure */ +const int drq_e_prc_prvs = 91; /* erase user privileges on procedure */ const int drq_e_prc_prv = 92; /* erase procedure's privileges */ const int drq_e_trg_prv = 93; /* erase trigger's privileges */ const int drq_d_log = 94; /* drop log */ @@ -163,18 +163,18 @@ const int drq_gcg2 = 113; /* grantor_can_grant */ const int drq_gcg3 = 114; /* grantor_can_grant */ const int drq_gcg4 = 115; /* grantor_can_grant */ const int drq_gcg5 = 116; /* grantor_can_grant */ -const int drq_l_view_idx = 117; /* table is view? */ +const int drq_l_view_idx = 117; /* table is view? */ const int drq_role_gens = 118; /* store SQL role */ const int drq_get_role_nm = 119; /* get SQL role */ const int drq_get_role_au = 120; /* get SQL role auth */ -const int drq_del_role_1 = 121; /* delete SQL role from rdb$user_privilege */ +const int drq_del_role_1 = 121; /* delete SQL role from rdb$user_privilege */ const int drq_drop_role = 122; /* delete SQL role from rdb$roles */ const int drq_get_rel_owner = 123; /* get the owner of any relations */ const int drq_get_user_priv = 124; /* get the grantor of user privileges or the user who was granted the privileges */ const int drq_g_rel_constr_nm= 125; /* get relation constraint name */ const int drq_e_rel_const = 126; /* erase relation constraints */ -const int drq_e_gens = 127; /* erase generators */ +const int drq_e_gens = 127; /* erase generators */ const int drq_s_f_class = 128; /* set the security class name for a field */ const int drq_s_u_class = 129; /* find a unique security class name for a field */ const int drq_l_difference = 130; /* Look up a backup difference file */ @@ -203,6 +203,10 @@ const int drq_l_fld_coll = 152; // lookup field collation const int drq_l_prp_src = 153; // lookup a procedure parameter source const int drq_s_prms2 = 154; // store parameters (ODS 11.1) const int drq_l_prm_coll = 155; // lookup procedure parameter collation -const int drq_MAX = 156; +const int drq_s_prms3 = 156; // store parameters (ODS 11.2) +const int drq_d_gfields2 = 157; // drop a global field for procedure param (ODS 11.2) +const int drq_m_map = 158; // modify os=>db names mapping +const int drq_MAX = 159; #endif /* JRD_DRQ_H */ + diff --git a/src/jrd/dsc.cpp b/src/jrd/dsc.cpp index 4dc12db4c4..79be2adba8 100644 --- a/src/jrd/dsc.cpp +++ b/src/jrd/dsc.cpp @@ -835,20 +835,11 @@ bool DSC_make_descriptor(DSC* desc, break; case blr_double: -#ifndef VMS case blr_d_float: -#endif desc->dsc_length = sizeof(double); desc->dsc_dtype = dtype_double; break; -#ifdef VMS - case blr_d_float: - desc->dsc_length = sizeof(double); - desc->dsc_dtype = dtype_d_float; - break; -#endif - case blr_timestamp: desc->dsc_length = 2 * sizeof(SLONG); desc->dsc_dtype = dtype_timestamp; diff --git a/src/jrd/dsc.h b/src/jrd/dsc.h index 426bd3f392..a97f07f58c 100644 --- a/src/jrd/dsc.h +++ b/src/jrd/dsc.h @@ -57,16 +57,9 @@ inline bool DTYPE_IS_EXACT(UCHAR d) { return ((d == dtype_int64) || (d == dtype_long) || (d == dtype_short)); } -#ifdef VMS -inline bool DTYPE_IS_APPROX(UCHAR d) { - return ((d == dtype_double) || (d == dtype_real) || (d == dtype_d_float)); -} -#else inline bool DTYPE_IS_APPROX(UCHAR d) { return ((d == dtype_double) || (d == dtype_real)); } -#endif - inline bool DTYPE_IS_NUMERIC(UCHAR d) { return (((d >= dtype_byte) && (d <= dtype_d_float)) || (d == dtype_int64)); diff --git a/src/jrd/dsc2.h b/src/jrd/dsc2.h index c9c846c3bd..804e29eda7 100644 --- a/src/jrd/dsc2.h +++ b/src/jrd/dsc2.h @@ -130,9 +130,6 @@ struct dsc GDS_QUAD asQuad() const; float asReal() const; double asDouble() const; -#ifdef VMS - double asDFloat() const; -#endif GDS_DATE asSqlDate() const; GDS_TIME asSqlTime() const; GDS_TIMESTAMP asSqlTimestamp() const; @@ -427,23 +424,14 @@ inline bool dsc::isSqlDecimal() const // Floating point types? -#ifdef VMS -//#define DTYPE_IS_APPROX(d) (((d) == dtype_double) || -// ((d) == dtype_real) || -// ((d) == dtype_d_float)) -#else //#define DTYPE_IS_APPROX(d) (((d) == dtype_double) || // ((d) == dtype_real)) -#endif inline bool dsc::isApprox() const { switch (dsc_dtype) { case dtype_real: case dtype_double: -#ifdef VMS - case dtype_d_float: -#endif return true; default: return false; @@ -462,11 +450,7 @@ inline bool dsc::isApprox() const inline bool dsc::isANumber() const { return dsc_dtype >= dtype_byte -#ifdef VMS - && dsc_dtype <= dtype_d_float -#else && dsc_dtype <= dtype_double -#endif || dsc_dtype == dtype_int64; } @@ -648,15 +632,6 @@ inline double dsc::asDouble() const return 0; } -#ifdef VMS -inline double dsc::asDFloat() const -{ - if (dsc_dtype == dtype_d_float) - return *reinterpret_cast(dsc_address); - return 0; -} -#endif - inline GDS_DATE dsc::asSqlDate() const { if (dsc_dtype == dtype_sql_date) diff --git a/src/jrd/dyn.epp b/src/jrd/dyn.epp index 1b000863a3..091338e477 100644 --- a/src/jrd/dyn.epp +++ b/src/jrd/dyn.epp @@ -76,6 +76,10 @@ #include "../jrd/sch_proto.h" #include "../jrd/thread_proto.h" #include "../common/utils_proto.h" +#include "../jrd/jrd_pwd.h" +#include "../utilities/gsec/gsec.h" +#include "../utilities/gsec/secur_proto.h" +#include "../jrd/msg_encode.h" using MsgFormat::SafeArg; @@ -94,6 +98,7 @@ static void revoke_permission(Global*, const UCHAR**); static void store_privilege(Global*, const Firebird::MetaName&, const Firebird::MetaName&, const Firebird::MetaName&, const TEXT*, SSHORT, SSHORT, int); static void set_field_class_name(Global*, const Firebird::MetaName&, const Firebird::MetaName&); +static void dyn_user(Global*, const UCHAR**); void DYN_ddl(Attachment* attachment, jrd_tra* transaction, USHORT length, @@ -633,6 +638,14 @@ void DYN_execute(Global* gbl, DYN_modify_collation(gbl, ptr); break; + case isc_dyn_mapping: + DYN_modify_mapping(gbl, ptr); + break; + + case isc_dyn_user: + dyn_user(gbl, ptr); + break; + default: DYN_unsupported_verb(); break; @@ -753,6 +766,47 @@ USHORT DYN_get_string(const TEXT** ptr, Firebird::MetaName& field, size_t, bool } +USHORT DYN_get_string(const TEXT** ptr, Firebird::string& field, size_t, bool transliterate) +{ +/************************************** + * + * D Y N _ g e t _ s t r i n g + * + ************************************** + * + * Functional description + * Pick up an object name, move to a target. Return length of string. + * If destination field size is too small, punt. + * + **************************************/ + const TEXT* p = *ptr; + USHORT length = (UCHAR) *p++; + length |= ((USHORT) ((UCHAR) (*p++))) << 8; + + if (length > MAX_SQL_IDENTIFIER_LEN) + { + DYN_error_punt(false, 159); + // msg 159: Name longer than database field size + } + field.assign(p, length); + p += length; + + *ptr = p; + + if (transliterate) + { + TEXT temp[MAX_SQL_IDENTIFIER_LEN]; + + length = INTL_convert_bytes(JRD_get_thread_data(), + ttype_metadata, (BYTE*) temp, sizeof(temp), + ttype_dynamic, (const BYTE*) field.c_str(), field.length(), ERR_post); + field.assign(temp, length); + } + + return length; +} + + USHORT DYN_get_string(const TEXT** ptr, Firebird::PathName& field, size_t, bool transliterate) { /************************************** @@ -1513,7 +1567,8 @@ static bool grantor_can_grant(Global* gbl, /* no grant option for privilege .. on column .. of [base] table/view .. */ return false; } - else if (go_fld == -1) + + if (go_fld == -1) { if (go_rel == 0) { @@ -1525,7 +1580,8 @@ static bool grantor_can_grant(Global* gbl, /* no grant option for privilege .. on [base] table/view .. (for column ..) */ return false; } - else if (go_rel == -1) + + if (go_rel == -1) { DYN_error(false, (USHORT)(top_level ? 171 : 172), @@ -1545,7 +1601,8 @@ static bool grantor_can_grant(Global* gbl, /* no grant option for privilege .. on table/view .. */ return false; } - else if (go_rel == -1) + + if (go_rel == -1) { DYN_error(false, 174, SafeArg() << privilege << relation_name.c_str()); /* no .. privilege with grant option on table/view .. */ @@ -2129,3 +2186,162 @@ static void store_privilege(Global* gbl, /* msg 79: "STORE RDB$USER_PRIVILEGES failed in grant" */ } } + + +static void dyn_user(Global* gbl, const UCHAR** ptr) +{ +/************************************** + * + * d y n _ u s e r + * + ************************************** + * + * Functional description + * Implements CREATE/ALTER/DROP USER + * + **************************************/ +#if (defined BOOT_BUILD || defined EMBEDDED) + Firebird::status_exception::raise(isc_wish_list, isc_arg_end); +#else + thread_db* tdbb = JRD_get_thread_data(); + Database* dbb = tdbb->tdbb_database; + + char securityDatabaseName[MAXPATHLEN]; + SecurityDatabase::getPath(securityDatabaseName); + + Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1); + dpb.insertByte(isc_dpb_gsec_attach, TRUE); + dpb.insertString(isc_dpb_trusted_auth, tdbb->tdbb_attachment->att_user->usr_user_name); + + isc_db_handle securityDatabase = 0; + ISC_STATUS_ARRAY status; + try + { + THREAD_EXIT(); + isc_attach_database(status, 0, securityDatabaseName, &securityDatabase, + dpb.getBufferLength(), reinterpret_cast(dpb.getBuffer())); + THREAD_ENTER(); + if (status[1]) + { + Firebird::status_exception::raise(status); + } + + internal_user_data userData; + UCHAR verb; + while ((verb = *(*ptr)++) != isc_user_end) + { + Firebird::string text; + GET_STRING(ptr, text); + + switch(verb) + { + case isc_dyn_user_add: + userData.operation = ADD_OPER; + text.copyTo(userData.user_name, sizeof(userData.user_name)); + userData.user_name_entered = true; + break; + + case isc_dyn_user_mod: + userData.operation = MOD_OPER; + text.copyTo(userData.user_name, sizeof(userData.user_name)); + userData.user_name_entered = true; + break; + + case isc_dyn_user_del: + userData.operation = DEL_OPER; + text.copyTo(userData.user_name, sizeof(userData.user_name)); + userData.user_name_entered = true; + break; + + case isc_dyn_user_passwd: + if (text.isEmpty()) + { + Firebird::status_exception::raise(ENCODE_ISC_MSG(249, DYN_MSG_FAC), isc_arg_end); + // 249: Password should not be empty string + } + text.copyTo(userData.password, sizeof(userData.password)); + userData.password_entered = true; + break; + + case isc_dyn_user_first: + if (text.hasData()) + { + text.copyTo(userData.first_name, sizeof(userData.first_name)); + userData.first_name_entered = true; + } + else + { + userData.first_name_entered = false; + userData.first_name_specified = true; + } + break; + + case isc_dyn_user_middle: + if (text.hasData()) + { + text.copyTo(userData.middle_name, sizeof(userData.middle_name)); + userData.middle_name_entered = true; + } + else + { + userData.middle_name_entered = false; + userData.middle_name_specified = true; + } + break; + + case isc_dyn_user_last: + if (text.hasData()) + { + text.copyTo(userData.last_name, sizeof(userData.last_name)); + userData.last_name_entered = true; + } + else + { + userData.last_name_entered = false; + userData.last_name_specified = true; + } + break; + } + } + + THREAD_EXIT(); + int errcode = (! userData.user_name_entered) ? GsecMsg18 : + SECURITY_exec_line(status, securityDatabase, &userData, NULL, NULL); + THREAD_ENTER(); + + switch (errcode) + { + case 0: // nothing + break; + case GsecMsg22: + Firebird::status_exception::raise(ENCODE_ISC_MSG(errcode, GSEC_MSG_FAC), + isc_arg_string, ERR_cstring(userData.user_name), isc_arg_end); + default: + Firebird::status_exception::raise(ENCODE_ISC_MSG(errcode, GSEC_MSG_FAC), isc_arg_end); + } + + THREAD_EXIT(); + isc_detach_database(status, &securityDatabase); + THREAD_ENTER(); + if (status[1]) + { + securityDatabase = 0; + Firebird::status_exception::raise(status); + } + } + catch(const Firebird::Exception& e) + { + if (securityDatabase) + { + THREAD_EXIT(); + isc_detach_database(status, &securityDatabase); + THREAD_ENTER(); + } + e.stuff_exception(status); + memmove(&status[2], &status[0], sizeof(status) - 2 * sizeof(status[0])); + status[0] = isc_arg_gds; + status[1] = isc_no_meta_update; + Firebird::status_exception::raise(status); + } +#endif +} diff --git a/src/jrd/dyn.h b/src/jrd/dyn.h index c290668bdf..ef29b8eef0 100644 --- a/src/jrd/dyn.h +++ b/src/jrd/dyn.h @@ -66,16 +66,21 @@ public: const UCHAR* dyn_default_src; const UCHAR* dyn_default_val; bool dyn_drop_default; + const UCHAR* dyn_computed_src; + const UCHAR* dyn_computed_val; + bool dyn_drop_computed; public: explicit dyn_fld(MemoryPool& p) : dyn_null_flag(false), dyn_dtype(0), dyn_precision(0), dyn_charlen(0), dyn_collation(0), dyn_charset(0), dyn_fld_source(p), dyn_rel_name(p), dyn_fld_name(p), dyn_charbytelen(0), - dyn_default_src(0), dyn_default_val(0), dyn_drop_default(false) { } + dyn_default_src(0), dyn_default_val(0), dyn_drop_default(false), + dyn_computed_src(0), dyn_computed_val(0), dyn_drop_computed(false) { } dyn_fld() : dyn_null_flag(false), dyn_dtype(0), dyn_precision(0), dyn_charlen(0), dyn_collation(0), dyn_charset(0), dyn_charbytelen(0), - dyn_default_src(0), dyn_default_val(0), dyn_drop_default(false) { } + dyn_default_src(0), dyn_default_val(0), dyn_drop_default(false), + dyn_computed_src(0), dyn_computed_val(0), dyn_drop_computed(false) { } }; } //namespace Jrd @@ -88,6 +93,7 @@ void DYN_execute(Jrd::Global*, const UCHAR**, const Firebird::MetaName*, Firebir SLONG DYN_get_number(const UCHAR**); USHORT DYN_get_string(const TEXT**, Firebird::MetaName&, size_t, bool); USHORT DYN_get_string(const TEXT**, Firebird::PathName&, size_t, bool); +USHORT DYN_get_string(const TEXT**, Firebird::string&, size_t, bool); USHORT DYN_get_string(const TEXT**, Firebird::UCharBuffer&, size_t, bool); USHORT DYN_get_string(const TEXT**, TEXT*, size_t, bool); diff --git a/src/jrd/dyn_def.epp b/src/jrd/dyn_def.epp index 99c855b261..73eaa2db56 100644 --- a/src/jrd/dyn_def.epp +++ b/src/jrd/dyn_def.epp @@ -121,7 +121,6 @@ static const UCHAR who_blr[] = static void check_unique_name(thread_db*, Global*, const Firebird::MetaName&, bool); -static bool find_field_source(thread_db*, Global*, const Firebird::MetaName&, USHORT, const TEXT*, TEXT*); static bool get_who(thread_db*, Global*, Firebird::MetaName&); static bool is_it_user_name(Global*, const Firebird::MetaName&, thread_db*); @@ -514,13 +513,29 @@ void DYN_define_constraint(Global* gbl, // msg 127: "STORE RDB$REF_CONSTRAINTS failed" // msg 232: "%s cannot reference %s" switch (id) { - case drq_s_rel_con: number = 121; local_id = id; break; - case drq_s_ref_con: number = 127; local_id = id; break; - case drq_c_unq_nam: number = 121; break; - case drq_n_idx_seg: number = 124; break; - case drq_c_dup_con: number = 125; break; - case drq_l_rel_info: number = 232; break; - default: number = 125; break; + case drq_s_rel_con: + number = 121; + local_id = id; + break; + case drq_s_ref_con: + number = 127; + local_id = id; + break; + case drq_c_unq_nam: + number = 121; + break; + case drq_n_idx_seg: + number = 124; + break; + case drq_c_dup_con: + number = 125; + break; + case drq_l_rel_info: + number = 232; + break; + default: + number = 125; + break; } DYN_rundown_request(request, local_id); @@ -757,12 +772,26 @@ void DYN_define_constraint(Global* gbl, // msg 125: "Integrity constraint lookup failed" // msg 127: "STORE RDB$REF_CONSTRAINTS failed" switch (id) { - case drq_s_rel_con: number = 121; local_id = id; break; - case drq_s_ref_con: number = 127; local_id = id; break; - case drq_c_unq_nam: number = 121; break; - case drq_n_idx_seg: number = 124; break; - case drq_c_dup_con: number = 125; break; - default: number = 125; break; + case drq_s_rel_con: + number = 121; + local_id = id; + break; + case drq_s_ref_con: + number = 127; + local_id = id; + break; + case drq_c_unq_nam: + number = 121; + break; + case drq_n_idx_seg: + number = 124; + break; + case drq_c_dup_con: + number = 125; + break; + default: + number = 125; + break; } DYN_rundown_request(request, local_id); @@ -2567,7 +2596,6 @@ void DYN_define_local_field(Global* gbl, DYN_put_blr_blob(gbl, ptr, &RFR.RDB$DEFAULT_VALUE); break; - case isc_dyn_fld_default_source: has_default = true; RFR.RDB$DEFAULT_SOURCE.NULL = FALSE; @@ -2713,8 +2741,8 @@ void DYN_define_local_field(Global* gbl, if (!RFR.RDB$VIEW_CONTEXT.NULL) { fb_assert(relation_name); - find_field_source(tdbb, gbl, *relation_name, RFR.RDB$VIEW_CONTEXT, - RFR.RDB$BASE_FIELD, RFR.RDB$FIELD_SOURCE); + DYN_UTIL_find_field_source(tdbb, gbl, *relation_name, RFR.RDB$VIEW_CONTEXT, + RFR.RDB$BASE_FIELD, RFR.RDB$FIELD_SOURCE); } END_STORE; @@ -2787,7 +2815,7 @@ void DYN_define_parameter( Global* gbl, const UCHAR** ptr, Firebird::MetaName* p f_precision_null = f_charset_null = f_collation_null = f_notnull_null = TRUE; id = drq_s_prms; - Firebird::MetaName prc_name; + Firebird::MetaName prc_name, rel_name, fld_name; prm_mech_t mechanism = prm_mech_normal; bool explicit_domain = false; @@ -2941,6 +2969,14 @@ void DYN_define_parameter( Global* gbl, const UCHAR** ptr, Firebird::MetaName* p case isc_dyn_prm_mechanism: mechanism = (prm_mech_t) DYN_get_number(ptr); break; + + case isc_dyn_rel_name: + GET_STRING(ptr, rel_name); + break; + + case isc_dyn_fld_name: + GET_STRING(ptr, fld_name); + break; default: --(*ptr); @@ -2950,9 +2986,11 @@ void DYN_define_parameter( Global* gbl, const UCHAR** ptr, Firebird::MetaName* p if (P.RDB$FIELD_SOURCE.NULL) { /* Need to store dummy global field */ + jrd_req* old_request = request; id = drq_s_prm_src; - jrd_req* request2 = CMP_find_request(tdbb, drq_s_prm_src, DYN_REQUESTS); - STORE(REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction) + request = CMP_find_request(tdbb, drq_s_prm_src, DYN_REQUESTS); + + STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) PS IN RDB$FIELDS USING DYN_UTIL_generate_field_name(tdbb, gbl, PS.RDB$FIELD_NAME); strcpy(P.RDB$FIELD_SOURCE, PS.RDB$FIELD_NAME); @@ -2986,8 +3024,9 @@ void DYN_define_parameter( Global* gbl, const UCHAR** ptr, Firebird::MetaName* p } END_STORE; if (!DYN_REQUEST(drq_s_prm_src)) - DYN_REQUEST(drq_s_prm_src) = request2; + DYN_REQUEST(drq_s_prm_src) = request; id = drq_s_prms; + request = old_request; } END_STORE; @@ -2995,19 +3034,23 @@ void DYN_define_parameter( Global* gbl, const UCHAR** ptr, Firebird::MetaName* p DYN_REQUEST(drq_s_prms) = request; } + request = NULL; + id = -1; + if (explicit_domain) { if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original) >= ODS_11_1) { - jrd_req* request2 = CMP_find_request(tdbb, drq_s_prms2, DYN_REQUESTS); + request = CMP_find_request(tdbb, drq_s_prms2, DYN_REQUESTS); + id = drq_s_prms2; - FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction) + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) P IN RDB$PROCEDURE_PARAMETERS WITH P.RDB$PROCEDURE_NAME EQ prc_name.c_str() AND P.RDB$PARAMETER_NAME EQ parameter_name.c_str() if (!DYN_REQUEST(drq_s_prms2)) - DYN_REQUEST(drq_s_prms2) = request2; + DYN_REQUEST(drq_s_prms2) = request; MODIFY P USING P.RDB$COLLATION_ID.NULL = f_collation_null; @@ -3030,7 +3073,7 @@ void DYN_define_parameter( Global* gbl, const UCHAR** ptr, Firebird::MetaName* p END_FOR if (!DYN_REQUEST(drq_s_prms2)) - DYN_REQUEST(drq_s_prms2) = request2; + DYN_REQUEST(drq_s_prms2) = request; } else { @@ -3042,19 +3085,59 @@ void DYN_define_parameter( Global* gbl, const UCHAR** ptr, Firebird::MetaName* p } } + if (rel_name.hasData() && fld_name.hasData()) + { + if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original) >= ODS_11_2) + { + request = CMP_find_request(tdbb, drq_s_prms3, DYN_REQUESTS); + id = drq_s_prms3; + + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) + P IN RDB$PROCEDURE_PARAMETERS WITH + P.RDB$PROCEDURE_NAME EQ prc_name.c_str() AND + P.RDB$PARAMETER_NAME EQ parameter_name.c_str() + + if (!DYN_REQUEST(drq_s_prms3)) + DYN_REQUEST(drq_s_prms3) = request; + + MODIFY P USING + P.RDB$RELATION_NAME.NULL = FALSE; + strcpy(P.RDB$RELATION_NAME, rel_name.c_str()); + + P.RDB$FIELD_NAME.NULL = FALSE; + strcpy(P.RDB$FIELD_NAME, fld_name.c_str()); + END_MODIFY + END_FOR + + if (!DYN_REQUEST(drq_s_prms3)) + DYN_REQUEST(drq_s_prms3) = request; + } + else + { + request = NULL; + id = -1; + + ERR_post(isc_dsql_feature_not_supported_ods, + isc_arg_number, 11, + isc_arg_number, 2, + 0); // ODS_11_2 + } + } + } catch (const Firebird::Exception& ex) { Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); - if (id == drq_s_prms) { - DYN_rundown_request(request, drq_s_prms); + + if (id == -1 || id == drq_s_prms || id == drq_s_prm_src || + id == drq_s_prms2 || id == drq_s_prms3) + { + if (id != -1) + DYN_rundown_request(request, id); + DYN_error_punt(true, 136); - /* msg 163: "STORE RDB$PROCEDURE_PARAMETERS failed" */ - } - else if (id == drq_s_prm_src) { - DYN_rundown_request(request, drq_s_prm_src); - DYN_error_punt(true, 136); - /* msg 136: "STORE RDB$PROCEDURE_PARAMETERS failed" */ + // msg 136: "STORE RDB$PROCEDURE_PARAMETERS failed" } + DYN_rundown_request(request, -1); /* Control should never reach this point, @@ -4570,96 +4653,6 @@ local_punt_false_132: } -static bool find_field_source(thread_db* tdbb, - Global* gbl, - const Firebird::MetaName& view_name, - USHORT context, - const TEXT* local_name, - TEXT* output_field_name) -{ -/************************************** - * - * f i n d _ f i e l d _ s o u r c e - * - ************************************** - * - * Functional description - * Find the original source for a view field. - * - **************************************/ - - SET_TDBB(tdbb); - Database* dbb = tdbb->getDatabase(); - - jrd_req* request = NULL; - - /* CVC: It seems the logic of this function was changed over time. It's unlikely - it will cause a failure that leads to call DYN_error_punt(), unless the request finds - problems due to database corruption or unexpected ODS changes. Under normal - circumstances, it will return either true or false. When true, we found a field source - for the view's name/context/field and are loading this value in the last parameter, - that can be used against rdb$fields' rdb$field_name. */ - - bool found = false; - - try { - request = CMP_find_request(tdbb, drq_l_fld_src2, DYN_REQUESTS); - - FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) - VRL IN RDB$VIEW_RELATIONS CROSS - RFR IN RDB$RELATION_FIELDS OVER RDB$RELATION_NAME - WITH VRL.RDB$VIEW_NAME EQ view_name.c_str() AND - VRL.RDB$VIEW_CONTEXT EQ context AND - RFR.RDB$FIELD_NAME EQ local_name - - if (!DYN_REQUEST(drq_l_fld_src2)) { - DYN_REQUEST(drq_l_fld_src2) = request; - } - - found = true; - fb_utils::exact_name_limit(RFR.RDB$FIELD_SOURCE, sizeof(RFR.RDB$FIELD_SOURCE)); - strcpy(output_field_name, RFR.RDB$FIELD_SOURCE); - END_FOR; - if (!DYN_REQUEST(drq_l_fld_src2)) { - DYN_REQUEST(drq_l_fld_src2) = request; - } - - if (!found) - { - request = CMP_find_request(tdbb, drq_l_fld_src3, DYN_REQUESTS); - - FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) - VRL IN RDB$VIEW_RELATIONS CROSS - PPR IN RDB$PROCEDURE_PARAMETERS - WITH VRL.RDB$RELATION_NAME EQ PPR.RDB$PROCEDURE_NAME AND - VRL.RDB$VIEW_NAME EQ view_name.c_str() AND - VRL.RDB$VIEW_CONTEXT EQ context AND - PPR.RDB$PARAMETER_NAME EQ local_name - - if (!DYN_REQUEST(drq_l_fld_src3)) { - DYN_REQUEST(drq_l_fld_src3) = request; - } - - found = true; - fb_utils::exact_name_limit(PPR.RDB$FIELD_SOURCE, sizeof(PPR.RDB$FIELD_SOURCE)); - strcpy(output_field_name, PPR.RDB$FIELD_SOURCE); - END_FOR; - if (!DYN_REQUEST(drq_l_fld_src3)) { - DYN_REQUEST(drq_l_fld_src3) = request; - } - } - } - catch (const Firebird::Exception& ex) { - Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); - DYN_rundown_request(request, -1); - DYN_error_punt(true, 80); - /* msg 80: "Specified domain or source field does not exist" */ - } - - return found; -} - - static bool get_who( thread_db* tdbb, Global* gbl, Firebird::MetaName& output_name) { /************************************** diff --git a/src/jrd/dyn_del.epp b/src/jrd/dyn_del.epp index 9d10d59eb9..a068fa49af 100644 --- a/src/jrd/dyn_del.epp +++ b/src/jrd/dyn_del.epp @@ -987,8 +987,8 @@ void DYN_delete_parameter(Global* gbl, FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) PP IN RDB$PROCEDURE_PARAMETERS WITH PP.RDB$PROCEDURE_NAME EQ proc_name->c_str() AND PP.RDB$PARAMETER_NAME EQ name.c_str() - if (!DYN_REQUEST(drq_e_prm)) - DYN_REQUEST(drq_e_prm) = request; + if (!DYN_REQUEST(drq_e_prm)) + DYN_REQUEST(drq_e_prm) = request; found = true; /* get rid of parameters in rdb$fields */ @@ -1003,10 +1003,33 @@ void DYN_delete_parameter(Global* gbl, FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ PP.RDB$FIELD_SOURCE AND FLD.RDB$FIELD_NAME STARTING WITH IMPLICIT_DOMAIN_PREFIX - if (!DYN_REQUEST(drq_d_gfields)) - DYN_REQUEST(drq_d_gfields) = request; + if (!DYN_REQUEST(drq_d_gfields)) + DYN_REQUEST(drq_d_gfields) = request; - ERASE FLD; + bool erase = true; + + if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original) >= ODS_11_2) + { + jrd_req* request2 = CMP_find_request(tdbb, drq_d_gfields2, DYN_REQUESTS); + + FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction) + PP2 IN RDB$PROCEDURE_PARAMETERS + WITH PP2.RDB$PROCEDURE_NAME = PP.RDB$PROCEDURE_NAME AND + PP2.RDB$PARAMETER_NAME = PP.RDB$PARAMETER_NAME + + if (!DYN_REQUEST(drq_d_gfields2)) + DYN_REQUEST(drq_d_gfields2) = request2; + + if (!PP2.RDB$RELATION_NAME.NULL && !PP2.RDB$FIELD_NAME.NULL) + erase = false; + END_FOR; + + if (!DYN_REQUEST(drq_d_gfields2)) + DYN_REQUEST(drq_d_gfields2) = request2; + } + + if (erase) + ERASE FLD; END_FOR; if (!DYN_REQUEST(drq_d_gfields)) @@ -1104,7 +1127,26 @@ void DYN_delete_procedure( Global* gbl, const UCHAR** ptr) if (!DYN_REQUEST(drq_d_gfields)) DYN_REQUEST(drq_d_gfields) = request; - ERASE FLD; + bool erase = true; + + if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original) >= ODS_11_2) + { + jrd_req* request2 = NULL; + + FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction) + PP2 IN RDB$PROCEDURE_PARAMETERS + WITH PP2.RDB$PROCEDURE_NAME = PP.RDB$PROCEDURE_NAME AND + PP2.RDB$PARAMETER_NAME = PP.RDB$PARAMETER_NAME + + if (!PP2.RDB$RELATION_NAME.NULL && !PP2.RDB$FIELD_NAME.NULL) + erase = false; + END_FOR; + + CMP_release(tdbb, request2); + } + + if (erase) + ERASE FLD; END_FOR; if (!DYN_REQUEST(drq_d_gfields)) @@ -1474,15 +1516,33 @@ void DYN_delete_relation( Global* gbl, const UCHAR** ptr, const Firebird::MetaNa // msg 129: "ERASE RDB$RELATION_CONSTRAINTS failed" USHORT number; switch (id) { - case drq_e_rel_con2: number = 129; break; - case drq_e_rel_idxs: number = 57; break; - case drq_e_trg_msgs2: number = 65; break; - case drq_e_trigger2: number = 66; break; - case drq_e_rel_flds: number = 58; break; - case drq_e_view_rels: number = 59; break; - case drq_e_relation: number = 60; break; - case drq_e_sec_class: number = 74; break; - default: number = 62; break; + case drq_e_rel_con2: + number = 129; + break; + case drq_e_rel_idxs: + number = 57; + break; + case drq_e_trg_msgs2: + number = 65; + break; + case drq_e_trigger2: + number = 66; + break; + case drq_e_rel_flds: + number = 58; + break; + case drq_e_view_rels: + number = 59; + break; + case drq_e_relation: + number = 60; + break; + case drq_e_sec_class: + number = 74; + break; + default: + number = 62; + break; } DYN_error_punt(true, number); diff --git a/src/jrd/dyn_md_proto.h b/src/jrd/dyn_md_proto.h index 657ccc9c5d..ae54718f6e 100644 --- a/src/jrd/dyn_md_proto.h +++ b/src/jrd/dyn_md_proto.h @@ -42,6 +42,7 @@ void DYN_modify_trigger(Jrd::Global*, const UCHAR**); void DYN_modify_trigger_msg(Jrd::Global*, const UCHAR**, Firebird::MetaName*); void DYN_modify_sql_field(Jrd::Global*, const UCHAR**, const Firebird::MetaName*); void DYN_modify_view(Jrd::Global*, const UCHAR**); +void DYN_modify_mapping(Jrd::Global*, const UCHAR**); #endif // JRD_DYN_MD_PROTO_H diff --git a/src/jrd/dyn_mod.epp b/src/jrd/dyn_mod.epp index 61c2724404..9472644864 100644 --- a/src/jrd/dyn_mod.epp +++ b/src/jrd/dyn_mod.epp @@ -897,8 +897,8 @@ void DYN_modify_global_field(Global* gbl, /* msg 160: "Only one constraint allowed for a domain" */ break; } - else - single_validate = true; + + single_validate = true; break; case isc_dyn_fld_validation_blr: @@ -908,9 +908,8 @@ void DYN_modify_global_field(Global* gbl, /* msg 160: "Only one constraint allowed for a domain" */ break; } - else - single_validate = true; + single_validate = true; fldvald = *ptr; bfldvald = true; DYN_skip_attribute(ptr); @@ -1256,10 +1255,13 @@ void DYN_modify_local_field( **************************************/ USHORT position; Firebird::MetaName f, r; - TEXT *query_name, *edit_string, - *security_class, *new_name; - - const UCHAR *query_header, *description; + const UCHAR* query_name; + const UCHAR* edit_string; + const UCHAR* security_class; + const UCHAR* new_name; + const UCHAR* query_header; + const UCHAR* description; + const UCHAR* new_source = NULL; thread_db* tdbb = JRD_get_thread_data(); Database* dbb = tdbb->getDatabase(); @@ -1289,13 +1291,13 @@ void DYN_modify_local_field( break; case isc_dyn_new_fld_name: - new_name = (TEXT*) * ptr; + new_name = *ptr; nnflag = true; DYN_skip_attribute(ptr); break; case isc_dyn_fld_query_name: - query_name = (TEXT*) * ptr; + query_name = *ptr; qnflag = true; DYN_skip_attribute(ptr); break; @@ -1307,17 +1309,22 @@ void DYN_modify_local_field( break; case isc_dyn_fld_edit_string: - edit_string = (TEXT*) * ptr; + edit_string = *ptr; esflag = true; DYN_skip_attribute(ptr); break; case isc_dyn_security_class: - security_class = (TEXT*) * ptr; + security_class = *ptr; scflag = true; DYN_skip_attribute(ptr); break; + case isc_dyn_fld_source: + new_source = *ptr; + DYN_skip_attribute(ptr); + break; + case isc_dyn_description: description = *ptr; dflag = true; @@ -1365,8 +1372,10 @@ void DYN_modify_local_field( Firebird::MetaName new_fld; GET_STRING(&new_name, new_fld); if (new_fld.length() == 0) + { DYN_error_punt(false, 212); /* msg 212: "Zero length identifiers not allowed" */ + } check_view_dependency(tdbb, dbb, gbl, r, f); check_sptrig_dependency(tdbb, dbb, gbl, r, f); @@ -1400,6 +1409,10 @@ void DYN_modify_local_field( else FLD.RDB$SECURITY_CLASS.NULL = TRUE; } + + if (new_source) + GET_STRING(&new_source, FLD.RDB$FIELD_SOURCE); + if (dflag) { if (DYN_put_text_blob(gbl, &description, &FLD.RDB$DESCRIPTION)) FLD.RDB$DESCRIPTION.NULL = FALSE; @@ -1413,11 +1426,8 @@ void DYN_modify_local_field( DYN_REQUEST(drq_m_lfield) = request; if (npflag && found && position != existing_position) - modify_lfield_position(tdbb, dbb, gbl, r, f, position, - existing_position); - - - } + modify_lfield_position(tdbb, dbb, gbl, r, f, position, existing_position); + } // try catch (const Firebird::Exception& ex) { Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); DYN_rundown_request(request, -1); @@ -1529,8 +1539,6 @@ void DYN_modify_procedure( Global* gbl, const UCHAR** ptr) jrd_req* request = NULL; bool found = false; bool only_description = false; - prc_t prc_type = prc_legacy; - const UCHAR* debug_info_ptr = NULL; try { @@ -1570,6 +1578,15 @@ void DYN_modify_procedure( Global* gbl, const UCHAR** ptr) P.RDB$PROCEDURE_SOURCE.NULL = TRUE; P.RDB$PROCEDURE_INPUTS.NULL = TRUE; P.RDB$PROCEDURE_OUTPUTS.NULL = TRUE; + + // ODS_11_1 fields + P.RDB$DEBUG_INFO.NULL = TRUE; + + P.RDB$PROCEDURE_TYPE = prc_legacy; + P.RDB$PROCEDURE_TYPE.NULL = FALSE; + + P.RDB$VALID_BLR = TRUE; + P.RDB$VALID_BLR.NULL = FALSE; } UCHAR verb; @@ -1611,18 +1628,18 @@ void DYN_modify_procedure( Global* gbl, const UCHAR** ptr) P.RDB$PROCEDURE_OUTPUTS.NULL = FALSE; break; - case isc_dyn_prc_type: - prc_type = (prc_t) DYN_get_number(ptr); - break; - case isc_dyn_security_class: GET_STRING(ptr, P.RDB$SECURITY_CLASS); P.RDB$SECURITY_CLASS.NULL = FALSE; break; case isc_dyn_debug_info: - debug_info_ptr = *ptr; - DYN_skip_blr_blob(ptr); + DYN_put_blr_blob(gbl, ptr, &P.RDB$DEBUG_INFO); // ODS_11_1 field + P.RDB$DEBUG_INFO.NULL = FALSE; + break; + + case isc_dyn_prc_type: + P.RDB$PROCEDURE_TYPE = DYN_get_number(ptr); // ODS_11_1 field break; default: @@ -1635,33 +1652,6 @@ void DYN_modify_procedure( Global* gbl, const UCHAR** ptr) if (!DYN_REQUEST(drq_m_prcs)) DYN_REQUEST(drq_m_prcs) = request; - - if (!only_description) - { - if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original) >= ODS_11_1) - { - jrd_req* sub_request = NULL; - - FOR(REQUEST_HANDLE sub_request TRANSACTION_HANDLE gbl->gbl_transaction) - P IN RDB$PROCEDURES WITH P.RDB$PROCEDURE_NAME EQ procedure_name.c_str() - - MODIFY P USING - P.RDB$PROCEDURE_TYPE = prc_type; - P.RDB$PROCEDURE_TYPE.NULL = FALSE; - - P.RDB$VALID_BLR = TRUE; - P.RDB$VALID_BLR.NULL = FALSE; - - P.RDB$DEBUG_INFO.NULL = (debug_info_ptr == NULL) ? TRUE : FALSE; - if (debug_info_ptr) - DYN_put_blr_blob(gbl, &debug_info_ptr, &P.RDB$DEBUG_INFO); - END_MODIFY; - END_FOR; - - CMP_release(tdbb, sub_request); - } - } - } catch (const Firebird::Exception& ex) { Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); @@ -2695,8 +2685,11 @@ void DYN_modify_sql_field(Global* gbl, // Check to see if the field being altered is involved in any type of dependency. // If there is a dependency, call DYN_error_punt (inside the function). fb_assert(relation_name); - check_sptrig_dependency(tdbb, dbb, gbl, *relation_name, - orig_fld.dyn_fld_name); + + // ASF: check disabled to allow change of field type to be used + // with TYPE OF COLUMN table.column feature. + //check_sptrig_dependency(tdbb, dbb, gbl, *relation_name, + // orig_fld.dyn_fld_name); jrd_req* request = NULL; jrd_req* first_request = NULL; @@ -2705,20 +2698,31 @@ void DYN_modify_sql_field(Global* gbl, charset; dtype = scale = prec = subtype = charlen = collation = fldlen = nullflg = charset = false; - + int field_adjusted_count = 0; - + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) - RFR IN RDB$RELATION_FIELDS WITH RFR.RDB$RELATION_NAME = relation_name->c_str() - AND RFR.RDB$FIELD_NAME = orig_fld.dyn_fld_name.c_str() + RFR IN RDB$RELATION_FIELDS CROSS + REL IN RDB$RELATIONS WITH + REL.RDB$RELATION_NAME = RFR.RDB$RELATION_NAME AND + RFR.RDB$RELATION_NAME = relation_name->c_str() AND + RFR.RDB$FIELD_NAME = orig_fld.dyn_fld_name.c_str() first_request = request; request = NULL; found = true; + bool is_view = !REL.RDB$VIEW_BLR.NULL; bool has_dimensions = false; bool update_domain = false; bool domain_has_default = false; bool domain_is_computed = false; + SSHORT fld_position = 0; + bool fld_position_change = false; + SSHORT view_context = 0; + bool view_context_change = false; + Firebird::MetaName fld_base_field; + bool fld_base_field_change = false; + bool orig_computed = false; FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME = RFR.RDB$FIELD_SOURCE @@ -2739,6 +2743,7 @@ void DYN_modify_sql_field(Global* gbl, orig_fld.dyn_collation = FLD.RDB$COLLATION_ID; orig_fld.dyn_null_flag = FLD.RDB$NULL_FLAG != 0; orig_fld.dyn_fld_source = RFR.RDB$FIELD_SOURCE; + orig_computed = !FLD.RDB$COMPUTED_BLR.NULL; // If the original field type is an array, force its blr type to blr_blob if (FLD.RDB$DIMENSIONS != 0) @@ -2877,6 +2882,37 @@ void DYN_modify_sql_field(Global* gbl, new_fld.dyn_dtype = blr_blob; break; + case isc_dyn_fld_position: + fld_position = DYN_get_number(ptr); + fld_position_change = true; + break; + + case isc_dyn_fld_base_fld: + GET_STRING(ptr, fld_base_field); + fld_base_field_change = true; + break; + + case isc_dyn_view_context: + view_context = DYN_get_number(ptr); + view_context_change = true; + break; + + case isc_dyn_fld_computed_blr: + domain_is_computed = true; + new_fld.dyn_computed_val = *ptr; + DYN_skip_attribute(ptr); + break; + + case isc_dyn_fld_computed_source: + new_fld.dyn_computed_src = *ptr; + DYN_skip_attribute(ptr); + break; + + case isc_dyn_del_computed: + domain_is_computed = false; + new_fld.dyn_drop_computed = true; + break; + case isc_dyn_del_default: new_fld.dyn_drop_default = true; break; @@ -2901,9 +2937,8 @@ void DYN_modify_sql_field(Global* gbl, DYN_skip_attribute(ptr); break; - // These should only be defined for BLOB types and should not come through with - // any other types. BLOB types are detected above - + // These should only be defined for BLOB types and should not come through with + // any other types. BLOB types are detected above case isc_dyn_fld_segment_length: DYN_get_number(ptr); break; @@ -2914,17 +2949,44 @@ void DYN_modify_sql_field(Global* gbl, DYN_execute(gbl, ptr, relation_name, &tmp, NULL, NULL, NULL); } } + + if (fld_base_field_change && view_context_change) + { + fb_assert(is_view); + + if (fld_base_field.hasData()) + { + char field_name[MAX_SQL_IDENTIFIER_SIZE]; + DYN_UTIL_find_field_source(tdbb, gbl, RFR.RDB$RELATION_NAME, view_context, + fld_base_field.c_str(), field_name); + dom_fld.dyn_fld_source = field_name; + update_domain = true; + } + else + DYN_UTIL_generate_field_name(tdbb, gbl, new_fld.dyn_fld_source); + } END_FOR; // FLD in RDB$FIELDS CMP_release(tdbb, request); request = NULL; - const bool sourceIsInternalDomain = - fb_utils::implicit_domain(orig_fld.dyn_fld_source.c_str()); - - // Now that we have all of the information needed, let's check to see - // if the field type can be modifed + if (!is_view && + ((new_fld.dyn_computed_val && !orig_computed) || + (!new_fld.dyn_computed_val && orig_computed))) + { + // Cannot add or remove COMPUTED from column @1 + DYN_error_punt(false, 248, + SafeArg() << orig_fld.dyn_fld_name.c_str()); + } - if (update_domain) { + const bool sourceIsInternalDomain = + fb_utils::implicit_domain(orig_fld.dyn_fld_source.c_str()) && RFR.RDB$BASE_FIELD.NULL; + const bool changeComputed = new_fld.dyn_computed_val || new_fld.dyn_drop_computed; + + // Now that we have all of the information needed, let's check to see + // if the field type can be modified + + if (update_domain) + { // a1. Internal domain -> domain. // a2. Domain -> domain. @@ -2939,9 +3001,12 @@ void DYN_modify_sql_field(Global* gbl, dom_fld.dyn_charset, dom_fld.dyn_collation); */ - const ULONG retval = check_update_fld_type(orig_fld, dom_fld); - if (retval != FB_SUCCESS) - modify_err_punt(tdbb, retval, orig_fld, dom_fld); + if (!domain_is_computed && !is_view) + { + const ULONG retval = check_update_fld_type(orig_fld, dom_fld); + if (retval != FB_SUCCESS) + modify_err_punt(tdbb, retval, orig_fld, dom_fld); + } // If the original definition was a base field type, remove the entries from RDB$FIELDS if (sourceIsInternalDomain) @@ -2968,8 +3033,25 @@ void DYN_modify_sql_field(Global* gbl, END_MODIFY; first_request = request; request = NULL; + + if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original) >= ODS_11_2) + { + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) + PRM IN RDB$PROCEDURE_PARAMETERS + WITH PRM.RDB$RELATION_NAME = relation_name->c_str() AND + PRM.RDB$FIELD_NAME = orig_fld.dyn_fld_name.c_str() + + MODIFY PRM USING + strcpy(PRM.RDB$FIELD_SOURCE, dom_fld.dyn_fld_source.c_str()); + END_MODIFY; + END_FOR; + + CMP_release(tdbb, request); + request = NULL; + } } - else { + else + { // b1. Domain -> internal domain. // b2. Internal domain -> internal domain. @@ -2977,6 +3059,7 @@ void DYN_modify_sql_field(Global* gbl, const UCHAR* defSrc = new_fld.dyn_default_src; const bool dropDefault = new_fld.dyn_drop_default; const bool changeDefault = defVal || defSrc || dropDefault; + // If we are altering only the default, we need the old field settings. if (changeDefault && !new_fld.dyn_dsc.dsc_dtype) { @@ -2998,9 +3081,13 @@ void DYN_modify_sql_field(Global* gbl, new_fld.dyn_dsc.dsc_length, new_fld.dyn_dsc.dsc_sub_type, new_fld.dyn_charset, new_fld.dyn_collation); - const ULONG retval = check_update_fld_type(orig_fld, new_fld); - if (retval != FB_SUCCESS) - modify_err_punt(tdbb, retval, orig_fld, new_fld); + + if (!changeComputed && !orig_computed && !is_view) + { + const ULONG retval = check_update_fld_type(orig_fld, new_fld); + if (retval != FB_SUCCESS) + modify_err_punt(tdbb, retval, orig_fld, new_fld); + } // Check to see if the original data type for the field was based on a domain. If it // was (and now it isn't), remove the domain information and replace it with a generated @@ -3009,11 +3096,10 @@ void DYN_modify_sql_field(Global* gbl, if (!changeDefault && !sourceIsInternalDomain) { // b1. Domain -> internal domain. Not for changing DEFAULT value. - + request = first_request; MODIFY RFR USING - DYN_UTIL_generate_field_name(tdbb, gbl, - RFR.RDB$FIELD_SOURCE); + DYN_UTIL_generate_field_name(tdbb, gbl, RFR.RDB$FIELD_SOURCE); new_fld.dyn_fld_source = RFR.RDB$FIELD_SOURCE; END_MODIFY; first_request = request; @@ -3084,13 +3170,41 @@ void DYN_modify_sql_field(Global* gbl, FLD.RDB$FIELD_LENGTH = new_fld.dyn_dsc.dsc_length; FLD.RDB$FIELD_LENGTH.NULL = FALSE; } - + + if (new_fld.dyn_computed_val) + { + DYN_put_blr_blob(gbl, &new_fld.dyn_computed_val, &FLD.RDB$COMPUTED_BLR); + FLD.RDB$COMPUTED_BLR.NULL = FALSE; + } + + if (new_fld.dyn_computed_src) + { + DYN_put_text_blob(gbl, &new_fld.dyn_computed_src, &FLD.RDB$COMPUTED_SOURCE); + FLD.RDB$COMPUTED_SOURCE.NULL = FALSE; + } + // Copy the field name into RDB$FIELDS strcpy(FLD.RDB$FIELD_NAME, new_fld.dyn_fld_source.c_str()); END_STORE; CMP_release(tdbb, request); request = NULL; + + if (ENCODE_ODS(dbb->dbb_ods_version, dbb->dbb_minor_original) >= ODS_11_2) + { + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) + PRM IN RDB$PROCEDURE_PARAMETERS + WITH PRM.RDB$RELATION_NAME = relation_name->c_str() AND + PRM.RDB$FIELD_NAME = orig_fld.dyn_fld_name.c_str() + + MODIFY PRM USING + strcpy(PRM.RDB$FIELD_SOURCE, new_fld.dyn_fld_source.c_str()); + END_MODIFY; + END_FOR; + + CMP_release(tdbb, request); + request = NULL; + } } else if (changeDefault) { @@ -3199,17 +3313,23 @@ void DYN_modify_sql_field(Global* gbl, FLD.RDB$FIELD_LENGTH = new_fld.dyn_dsc.dsc_length; FLD.RDB$FIELD_LENGTH.NULL = FALSE; } - - // For now the test is redundant: we just can wipe out the - // computed part because we don't allow to change the - // computed expression or to turn a physical field into - // a computed one. Therefore, if we came here, - // it's to get rid of the computed part unconditionally. - if (domain_is_computed) + if (changeComputed) { - FLD.RDB$COMPUTED_BLR.NULL = TRUE; - FLD.RDB$COMPUTED_SOURCE.NULL = TRUE; + FLD.RDB$DEFAULT_SOURCE.NULL = TRUE; + FLD.RDB$DEFAULT_VALUE.NULL = TRUE; + + if (new_fld.dyn_computed_val) + { + DYN_put_blr_blob(gbl, &new_fld.dyn_computed_val, &FLD.RDB$COMPUTED_BLR); + FLD.RDB$COMPUTED_BLR.NULL = FALSE; + } + + if (new_fld.dyn_computed_src) + { + DYN_put_text_blob(gbl, &new_fld.dyn_computed_src, &FLD.RDB$COMPUTED_SOURCE); + FLD.RDB$COMPUTED_SOURCE.NULL = FALSE; + } } END_MODIFY; @@ -3228,7 +3348,23 @@ void DYN_modify_sql_field(Global* gbl, request = NULL; } } // else not a domain + request = first_request; + + if (fld_position_change || view_context_change || fld_base_field_change) + { + MODIFY RFR USING + if (fld_position_change) + RFR.RDB$FIELD_POSITION = fld_position; + if (view_context_change) + RFR.RDB$VIEW_CONTEXT = view_context; + if (fld_base_field_change) + { + RFR.RDB$BASE_FIELD.NULL = fld_base_field.isEmpty(); + strcpy(RFR.RDB$BASE_FIELD, fld_base_field.c_str()); + } + END_MODIFY; + } END_FOR; // RFR IN RDB$RELATION_FIELDS CMP_release(tdbb, request); request = NULL; @@ -3253,6 +3389,72 @@ void DYN_modify_sql_field(Global* gbl, } +// ************************************* +// D Y N _ m o d i f y _ m a p p i n g +// ************************************* +// It's purpose is to add/drop mapping from OS security name +// to DB security object +void DYN_modify_mapping(Global* gbl, const UCHAR** ptr) +{ + thread_db* tdbb = JRD_get_thread_data(); + Database* dbb = tdbb->tdbb_database; + + jrd_req* request = CMP_find_request(tdbb, drq_m_map, DYN_REQUESTS); + bool found = false; + + Firebird::string osName, dbName; + GET_STRING(ptr, osName); + const UCHAR op = *(*ptr)++; + GET_STRING(ptr, dbName); + + // This is FB 2.5 limited implementation! + // Later it should work with new system table, something like RDB$MAPPING. + + if (osName != DOMAIN_ADMINS || dbName != ADMIN_ROLE) + { + Firebird::status_exception::raise(isc_no_meta_update, isc_arg_gds, isc_wish_list, isc_arg_end); + } + + if (!(tdbb->tdbb_attachment && tdbb->tdbb_attachment->locksmith())) + ERR_post(isc_adm_task_denied, 0); + + found = false; + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) + X IN RDB$ROLES + WITH X.RDB$ROLE_NAME EQ dbName.c_str() + + if (!DYN_REQUEST(drq_m_map)) + DYN_REQUEST(drq_m_map) = request; + + found = true; + MODIFY X + switch (op) + { + case isc_dyn_map_role: + X.RDB$SYSTEM_FLAG = ROLE_FLAG_DBO | ROLE_FLAG_MAY_TRUST; + break; + + case isc_dyn_unmap_role: + X.RDB$SYSTEM_FLAG = ROLE_FLAG_DBO; + break; + + default: + DYN_unsupported_verb(); + } + END_MODIFY; + END_FOR; + + if (!DYN_REQUEST(drq_m_map)) + DYN_REQUEST(drq_m_map) = request; + + if (!found) + { + Firebird::status_exception::raise(isc_no_meta_update, isc_arg_gds, + isc_random, isc_arg_string, "Missing RDB$ADMIN role in the database", + isc_arg_end); + } +} + void get_domain_type(thread_db* tdbb, Database* dbb, Global* gbl, dyn_fld& dom_fld) { /************************************** @@ -3384,7 +3586,6 @@ static ULONG check_update_fld_type(const dyn_fld& orig_fld, return isc_dyn_dtype_invalid; /* Cannot change datatype for column %s. The operation cannot be performed on BLOB, or ARRAY columns. */ - break; /* DATE types */ case blr_sql_date: @@ -3448,7 +3649,6 @@ static ULONG check_update_fld_type(const dyn_fld& orig_fld, return isc_dyn_dtype_invalid; /* Cannot change datatype for column %s. The operation cannot be performed on BLOB, or ARRAY columns. */ - break; case blr_sql_date: case blr_sql_time: diff --git a/src/jrd/dyn_ut_proto.h b/src/jrd/dyn_ut_proto.h index 4e237949f5..c394f55c42 100644 --- a/src/jrd/dyn_ut_proto.h +++ b/src/jrd/dyn_ut_proto.h @@ -27,6 +27,8 @@ void DYN_UTIL_store_check_constraints(Jrd::thread_db*, Jrd::Global*, const Firebird::MetaName&, const Firebird::MetaName&); +bool DYN_UTIL_find_field_source(Jrd::thread_db* tdbb, Jrd::Global* gbl, const Firebird::MetaName& view_name, + USHORT context, const TEXT* local_name, TEXT* output_field_name); bool DYN_UTIL_get_prot(Jrd::thread_db*, Jrd::Global*, const SCHAR*, const SCHAR*, Jrd::SecurityClass::flags_t*); void DYN_UTIL_generate_trigger_name(Jrd::thread_db*, Jrd::Global*, Firebird::MetaName&); diff --git a/src/jrd/dyn_util.epp b/src/jrd/dyn_util.epp index 0550392edb..d1676f7d2e 100644 --- a/src/jrd/dyn_util.epp +++ b/src/jrd/dyn_util.epp @@ -56,6 +56,7 @@ #include "../jrd/isc_f_proto.h" #include "../jrd/thd.h" #include "../jrd/vio_proto.h" +#include "../common/utils_proto.h" using MsgFormat::SafeArg; @@ -468,6 +469,96 @@ void DYN_UTIL_generate_trigger_name( thread_db* tdbb, Global* gbl, Firebird::Met } +bool DYN_UTIL_find_field_source(thread_db* tdbb, + Global* gbl, + const Firebird::MetaName& view_name, + USHORT context, + const TEXT* local_name, + TEXT* output_field_name) +{ +/************************************** + * + * D Y N _U T I L _ f i n d _ f i e l d _ s o u r c e + * + ************************************** + * + * Functional description + * Find the original source for a view field. + * + **************************************/ + + SET_TDBB(tdbb); + Database* dbb = tdbb->tdbb_database; + + jrd_req* request = NULL; + + /* CVC: It seems the logic of this function was changed over time. It's unlikely + it will cause a failure that leads to call DYN_error_punt(), unless the request finds + problems due to database corruption or unexpected ODS changes. Under normal + circumstances, it will return either true or false. When true, we found a field source + for the view's name/context/field and are loading this value in the last parameter, + that can be used against rdb$fields' rdb$field_name. */ + + bool found = false; + + try { + request = CMP_find_request(tdbb, drq_l_fld_src2, DYN_REQUESTS); + + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) + VRL IN RDB$VIEW_RELATIONS CROSS + RFR IN RDB$RELATION_FIELDS OVER RDB$RELATION_NAME + WITH VRL.RDB$VIEW_NAME EQ view_name.c_str() AND + VRL.RDB$VIEW_CONTEXT EQ context AND + RFR.RDB$FIELD_NAME EQ local_name + + if (!DYN_REQUEST(drq_l_fld_src2)) { + DYN_REQUEST(drq_l_fld_src2) = request; + } + + found = true; + fb_utils::exact_name_limit(RFR.RDB$FIELD_SOURCE, sizeof(RFR.RDB$FIELD_SOURCE)); + strcpy(output_field_name, RFR.RDB$FIELD_SOURCE); + END_FOR; + if (!DYN_REQUEST(drq_l_fld_src2)) { + DYN_REQUEST(drq_l_fld_src2) = request; + } + + if (!found) + { + request = CMP_find_request(tdbb, drq_l_fld_src3, DYN_REQUESTS); + + FOR(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) + VRL IN RDB$VIEW_RELATIONS CROSS + PPR IN RDB$PROCEDURE_PARAMETERS + WITH VRL.RDB$RELATION_NAME EQ PPR.RDB$PROCEDURE_NAME AND + VRL.RDB$VIEW_NAME EQ view_name.c_str() AND + VRL.RDB$VIEW_CONTEXT EQ context AND + PPR.RDB$PARAMETER_NAME EQ local_name + + if (!DYN_REQUEST(drq_l_fld_src3)) { + DYN_REQUEST(drq_l_fld_src3) = request; + } + + found = true; + fb_utils::exact_name_limit(PPR.RDB$FIELD_SOURCE, sizeof(PPR.RDB$FIELD_SOURCE)); + strcpy(output_field_name, PPR.RDB$FIELD_SOURCE); + END_FOR; + if (!DYN_REQUEST(drq_l_fld_src3)) { + DYN_REQUEST(drq_l_fld_src3) = request; + } + } + } + catch (const Firebird::Exception& ex) { + Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); + DYN_rundown_request(request, -1); + DYN_error_punt(true, 80); + /* msg 80: "Specified domain or source field does not exist" */ + } + + return found; +} + + bool DYN_UTIL_get_prot(thread_db* tdbb, Global* gbl, const SCHAR* rname,