@@ -493,6 +493,7 @@ static void check_computed_dependencies(thread_db* tdbb, jrd_tra* transaction,
493493 const Firebird::MetaName& fieldName);
494494static void check_dependencies(thread_db*, const TEXT*, const TEXT*, const TEXT*, int, jrd_tra*);
495495static void check_filename(const Firebird::string&, bool);
496+ static void cleanup_index_creation(thread_db*, DeferredWork*, jrd_tra*);
496497static bool formatsAreEqual(const Format*, const Format*);
497498static bool find_depend_in_dfw(thread_db*, TEXT*, USHORT, USHORT, jrd_tra*);
498499static void get_array_desc(thread_db*, const TEXT*, Ods::InternalArrayDesc*);
@@ -1436,10 +1437,13 @@ void DFW_perform_work(thread_db* tdbb, jrd_tra* transaction)
14361437 {
14371438 more = false;
14381439 try {
1439- tdbb->tdbb_flags |= (TDBB_dont_post_dfw | TDBB_use_db_page_space);
1440+ tdbb->tdbb_flags |= (TDBB_dont_post_dfw | TDBB_use_db_page_space |
1441+ (phase == 0 ? TDBB_dfw_cleanup : 0));
1442+
14401443 for (const deferred_task* task = task_table; task->task_type != dfw_null; ++task)
14411444 {
1442- for (DeferredWork* work = transaction->tra_deferred_job->work; work; work = work->getNext())
1445+ for (DeferredWork* work = transaction->tra_deferred_job->work;
1446+ work; work = work->getNext())
14431447 {
14441448 if (work->dfw_type == task->task_type)
14451449 {
@@ -1454,17 +1458,20 @@ void DFW_perform_work(thread_db* tdbb, jrd_tra* transaction)
14541458 }
14551459 }
14561460 }
1461+
1462+ tdbb->tdbb_flags &= ~(TDBB_dont_post_dfw | TDBB_use_db_page_space | TDBB_dfw_cleanup);
1463+
14571464 if (!phase)
14581465 {
14591466 fb_utils::copyStatus(tdbb->tdbb_status_vector, &err_status);
14601467 ERR_punt();
14611468 }
1469+
14621470 ++phase;
1463- tdbb->tdbb_flags &= ~(TDBB_dont_post_dfw | TDBB_use_db_page_space);
14641471 }
14651472 catch (const Firebird::Exception& ex)
14661473 {
1467- tdbb->tdbb_flags &= ~(TDBB_dont_post_dfw | TDBB_use_db_page_space);
1474+ tdbb->tdbb_flags &= ~(TDBB_dont_post_dfw | TDBB_use_db_page_space | TDBB_dfw_cleanup );
14681475
14691476 // Do any necessary cleanup
14701477 if (!phase)
@@ -2606,6 +2613,7 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
26062613 switch (phase)
26072614 {
26082615 case 0:
2616+ cleanup_index_creation(tdbb, work, transaction);
26092617 MET_delete_dependencies(tdbb, work->dfw_name, obj_expression_index, transaction);
26102618 return false;
26112619
@@ -2949,6 +2957,64 @@ static void check_filename(const Firebird::string& name, bool shareExpand)
29492957}
29502958
29512959
2960+ static void cleanup_index_creation(thread_db* tdbb, DeferredWork* work, jrd_tra* transaction)
2961+ {
2962+ Database* const dbb = tdbb->getDatabase();
2963+
2964+ AutoRequest request;
2965+
2966+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) IDXN IN RDB$INDICES CROSS
2967+ IREL IN RDB$RELATIONS OVER RDB$RELATION_NAME
2968+ WITH IDXN.RDB$INDEX_NAME EQ work->dfw_name.c_str()
2969+ // dimitr: I have no idea why the condition below is required here
2970+ AND IREL.RDB$VIEW_BLR MISSING // views do not have indices
2971+ {
2972+ jrd_rel* const relation = MET_lookup_relation(tdbb, IDXN.RDB$RELATION_NAME);
2973+ RelationPages* const relPages = relation->getPages(tdbb, MAX_TRA_NUMBER, false);
2974+
2975+ if (relPages && relPages->rel_index_root)
2976+ {
2977+ // We need to special handle temp tables with ON PRESERVE ROWS only
2978+ const bool isTempIndex = (relation->rel_flags & REL_temp_conn) &&
2979+ (relPages->rel_instance_id != 0);
2980+
2981+ // Fetch the root index page and mark MUST_WRITE, and then
2982+ // delete the index. It will also clean the index slot.
2983+
2984+ if (work->dfw_id != dbb->dbb_max_idx)
2985+ {
2986+ WIN window(relPages->rel_pg_space_id, relPages->rel_index_root);
2987+ CCH_FETCH(tdbb, &window, LCK_write, pag_root);
2988+ CCH_MARK_MUST_WRITE(tdbb, &window);
2989+ const bool tree_exists = BTR_delete_index(tdbb, &window, work->dfw_id);
2990+
2991+ if (!isTempIndex) {
2992+ work->dfw_id = dbb->dbb_max_idx;
2993+ }
2994+ else if (tree_exists)
2995+ {
2996+ IndexLock* const idx_lock = CMP_get_index_lock(tdbb, relation, work->dfw_id);
2997+
2998+ if (idx_lock)
2999+ {
3000+ if (!--idx_lock->idl_count)
3001+ LCK_release(tdbb, idx_lock->idl_lock);
3002+ }
3003+ }
3004+ }
3005+
3006+ if (!IDXN.RDB$INDEX_ID.NULL)
3007+ {
3008+ MODIFY IDXN USING
3009+ IDXN.RDB$INDEX_ID.NULL = TRUE;
3010+ END_MODIFY
3011+ }
3012+ }
3013+ }
3014+ END_FOR
3015+ }
3016+
3017+
29523018static bool formatsAreEqual(const Format* old_format, const Format* new_format)
29533019{
29543020/**************************************
@@ -3150,7 +3216,6 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
31503216 jrd_rel* partner_relation;
31513217 index_desc idx;
31523218 int key_count;
3153- AutoRequest handle;
31543219
31553220 SET_TDBB(tdbb);
31563221 Jrd::Attachment* attachment = tdbb->getAttachment();
@@ -3159,65 +3224,7 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
31593224 switch (phase)
31603225 {
31613226 case 0:
3162- handle.reset();
3163-
3164- // Drop those indices at clean up time.
3165- FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction) IDXN IN RDB$INDICES CROSS
3166- IREL IN RDB$RELATIONS OVER RDB$RELATION_NAME
3167- WITH IDXN.RDB$INDEX_NAME EQ work->dfw_name.c_str()
3168- {
3169- // Views do not have indices
3170- if (IREL.RDB$VIEW_BLR.NULL)
3171- {
3172- relation = MET_lookup_relation(tdbb, IDXN.RDB$RELATION_NAME);
3173-
3174- RelationPages* relPages = relation->getPages(tdbb, MAX_TRA_NUMBER, false);
3175- if (!relPages) {
3176- return false;
3177- }
3178-
3179- // we need to special handle temp tables with ON PRESERVE ROWS only
3180- const bool isTempIndex = (relation->rel_flags & REL_temp_conn) &&
3181- (relPages->rel_instance_id != 0);
3182-
3183- // Fetch the root index page and mark MUST_WRITE, and then
3184- // delete the index. It will also clean the index slot. Note
3185- // that the previous fixed definition of MAX_IDX (64) has been
3186- // dropped in favor of a computed value saved in the Database
3187- if (relPages->rel_index_root)
3188- {
3189- if (work->dfw_id != dbb->dbb_max_idx)
3190- {
3191- WIN window(relPages->rel_pg_space_id, relPages->rel_index_root);
3192- CCH_FETCH(tdbb, &window, LCK_write, pag_root);
3193- CCH_MARK_MUST_WRITE(tdbb, &window);
3194- const bool tree_exists = BTR_delete_index(tdbb, &window, work->dfw_id);
3195-
3196- if (!isTempIndex) {
3197- work->dfw_id = dbb->dbb_max_idx;
3198- }
3199- else if (tree_exists)
3200- {
3201- IndexLock* idx_lock = CMP_get_index_lock(tdbb, relation, work->dfw_id);
3202- if (idx_lock)
3203- {
3204- if (!--idx_lock->idl_count) {
3205- LCK_release(tdbb, idx_lock->idl_lock);
3206- }
3207- }
3208- }
3209- }
3210- if (!IDXN.RDB$INDEX_ID.NULL)
3211- {
3212- MODIFY IDXN USING
3213- IDXN.RDB$INDEX_ID.NULL = TRUE;
3214- END_MODIFY
3215- }
3216- }
3217- }
3218- }
3219- END_FOR
3220-
3227+ cleanup_index_creation(tdbb, work, transaction);
32213228 return false;
32223229
32233230 case 1:
0 commit comments