/* * PROGRAM: JRD Access Method * MODULE: pcmet.e * DESCRIPTION: Meta data for PC_ENGINE * * The contents of this file are subject to the Interbase Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy * of the License at http://www.Inprise.com/IPL.html * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express * or implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code was created by Inprise Corporation * and its predecessors. Portions created by Inprise Corporation are * Copyright (C) Inprise Corporation. * * All Rights Reserved. * Contributor(s): ______________________________________. */ #include "firebird.h" #include #include "../jrd/gds.h" #include "../jrd/jrd.h" #include "../jrd/irq.h" #include "../jrd/tra.h" #include "../jrd/val.h" #include "../jrd/ods.h" #include "../jrd/btr.h" #include "../jrd/all.h" #include "../jrd/req.h" #include "../jrd/exe.h" #include "../jrd/met.h" #include "../jrd/lck.h" #include "../jrd/all_proto.h" #include "../jrd/cmp_proto.h" #include "../jrd/dfw_proto.h" #include "../jrd/err_proto.h" #include "../jrd/exe_proto.h" #include "../jrd/gds_proto.h" #include "../jrd/idx_proto.h" #include "../jrd/lck_proto.h" #include "../jrd/met_proto.h" #include "../jrd/mov_proto.h" #include "../jrd/pcmet_proto.h" #include "../jrd/thd_proto.h" DATABASE DB = FILENAME "ODS.RDB"; #ifdef EXPRESSION_INDICES int PCMET_expression_index( TDBB tdbb, SSHORT phase, DFW work, JRD_TRA transaction) { /************************************** * * P C M E T _ e x p r e s s i o n _ i n d e x * ************************************** * * Functional description * Create a new expression index. * **************************************/ DBB dbb; JRD_REL relation; IDX idx; float selectivity; PLB default_pool, new_pool = NULL; CSB csb; JRD_REQ current_request; SET_TDBB(tdbb); dbb = tdbb->tdbb_database; switch (phase) { case 1: case 2: return TRUE; case 3: relation = NULL; MOVE_CLEAR(&idx, sizeof(struct idx)); if (REQUEST(irq_c_exp_index)) EXE_unwind(tdbb, REQUEST(irq_c_exp_index)); FOR(REQUEST_HANDLE REQUEST(irq_c_exp_index)) IDX IN RDB$INDICES CROSS REL IN RDB$RELATIONS OVER RDB$RELATION_NAME WITH IDX.RDB$EXPRESSION_BLR NOT MISSING AND IDX.RDB$INDEX_NAME EQ work->dfw_name if (!relation) { relation = MET_relation(tdbb, REL.RDB$RELATION_ID); if (!relation->rel_name) { relation->rel_name = MET_save_name(tdbb, REL.RDB$RELATION_NAME); relation->rel_length = strlen(relation->rel_name); } if (IDX.RDB$INDEX_ID && IDX.RDB$STATISTICS < 0.0) { MODIFY IDX IDX.RDB$STATISTICS = IDX_statistics(tdbb, relation, IDX.RDB$INDEX_ID - 1); END_MODIFY; EXE_unwind(tdbb, REQUEST(irq_c_exp_index)); return FALSE; } if (IDX.RDB$INDEX_ID) { IDX_delete_index(tdbb, relation, IDX.RDB$INDEX_ID - 1); MET_delete_dependencies(tdbb, work->dfw_name, obj_expression_index); MODIFY IDX IDX.RDB$INDEX_ID.NULL = TRUE; END_MODIFY; } if (IDX.RDB$INDEX_INACTIVE) { EXE_unwind(tdbb, REQUEST(irq_c_exp_index)); return FALSE; } if (IDX.RDB$SEGMENT_COUNT) ERR_post(gds__no_meta_update, gds_arg_gds, gds__no_segments_err, gds_arg_string, ERR_cstring(work->dfw_name), 0); /* Msg359: segments not allowed in expression index %s */ if (IDX.RDB$UNIQUE_FLAG) idx.idx_flags |= idx_unique; if (IDX.RDB$INDEX_TYPE == 1) idx.idx_flags |= idx_descending; /* allocate a new pool to contain the expression tree for the expression index */ default_pool = tdbb->tdbb_default; tdbb->tdbb_default = new_pool = ALL_pool(&jrd_alloc_info); MET_scan_relation(tdbb, relation); if (!IDX.RDB$EXPRESSION_BLR.NULL) idx.idx_expression = MET_get_dependencies(tdbb, relation, NULL_PTR, NULL_PTR, &IDX. RDB$EXPRESSION_BLR, &idx. idx_expression_request, &csb, IDX. RDB$INDEX_NAME, obj_expression_index); tdbb->tdbb_default = default_pool; /* fake a description of the index */ idx.idx_count = 1; idx.idx_flags |= idx_expressn; CMP_get_desc(tdbb, csb, idx.idx_expression, &idx.idx_expression_desc); idx.idx_rpt[0].idx_itype = DFW_assign_index_type(work, idx.idx_expression_desc.dsc_dtype, 0); ALL_release(csb); } END_FOR; if (!relation) ERR_post(gds__no_meta_update, gds_arg_gds, gds__idx_create_err, gds_arg_string, ERR_cstring(work->dfw_name), 0); /* Msg308: can't create index %s */ /* Actually create the index */ current_request = tdbb->tdbb_request; tdbb->tdbb_request = idx.idx_expression_request; IDX_create_index(tdbb, relation, &idx, work->dfw_name, NULL_PTR, transaction, &selectivity); tdbb->tdbb_request = current_request; DFW_update_index(work, idx.idx_id, selectivity); /* get rid of the pool containing the expression tree */ if (new_pool) ALL_rlpool(new_pool); break; } return FALSE; } #endif #ifdef EXPRESSION_INDICES void PCMET_lookup_index( JRD_REL relation, IDX * idx) { /************************************** * * P C M E T _ l o o k u p _ i n d e x * ************************************** * * Functional description * Lookup information about an index, in * the metadata cache if possible. * **************************************/ TDBB tdbb; DBB dbb; CSB csb = NULL; IDB index_block; PLB old_pool; tdbb = GET_THREAD_DATA; dbb = tdbb->tdbb_database; /* check the index blocks for the relation to see if we have a cached block */ for (index_block = relation->rel_index_blocks; index_block; index_block = index_block->idb_next) if (index_block->idb_id == idx->idx_id) break; if (index_block && index_block->idb_expression) { idx->idx_expression = index_block->idb_expression; idx->idx_expression_request = index_block->idb_expression_request; MOVE_FAST(&index_block->idb_expression_desc, &idx->idx_expression_desc, sizeof(struct dsc)); return; } FOR(REQUEST_HANDLE REQUEST(irq_l_exp_index)) IDX IN RDB$INDICES WITH IDX.RDB$RELATION_NAME EQ relation->rel_name AND IDX.RDB$INDEX_ID EQ idx->idx_id + 1 if (idx->idx_expression_request) CMP_release(tdbb, idx->idx_expression_request); idx->idx_expression_request = NULL; /* parse the blr, making sure to create the resulting expression tree and request in its own pool so that it may be cached with the index block in the "permanent" metadata cache */ old_pool = tdbb->tdbb_default; tdbb->tdbb_default = ALL_pool(&jrd_alloc_info); idx->idx_expression = MET_parse_blob(tdbb, relation, &IDX.RDB$EXPRESSION_BLR, &csb, &idx->idx_expression_request, FALSE, FALSE); tdbb->tdbb_default = old_pool; END_FOR; if (csb) { CMP_get_desc(tdbb, csb, idx->idx_expression, &idx->idx_expression_desc); ALL_release(csb); } /* if there is no existing index block for this index, create one and link it in with the index blocks for this relation */ if (!index_block) index_block = IDX_create_index_block(tdbb, relation, idx->idx_id); /* if we can't get the lock, no big deal: just give up on caching the index info */ if (!LCK_lock_non_blocking(tdbb, index_block->idb_lock, LCK_SR, FALSE)) return; /* whether the index block already existed or was just created, fill in the cached information about the index */ index_block->idb_expression = idx->idx_expression; index_block->idb_expression_request = idx->idx_expression_request; MOVE_FAST(&idx->idx_expression_desc, &index_block->idb_expression_desc, sizeof(struct dsc)); } #endif