8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-28 02:43:03 +01:00
firebird-mirror/src/jrd/pcmet.epp

336 lines
8.9 KiB
Plaintext
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Access Method
2003-12-31 06:36:12 +01:00
* MODULE: pcmet.epp
* DESCRIPTION: Meta data for expression indices
2001-05-23 15:26:42 +02:00
*
* 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"
2001-05-23 15:26:42 +02:00
#include <string.h>
2004-03-22 12:38:23 +01:00
#include "../jrd/common.h"
2003-11-08 17:40:17 +01:00
#include "../jrd/ibase.h"
2001-05-23 15:26:42 +02:00
#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/req.h"
#include "../jrd/exe.h"
#include "../jrd/met.h"
#include "../jrd/lck.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/tra_proto.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/lck_proto.h"
#include "../jrd/met_proto.h"
#include "../jrd/mov_proto.h"
#include "../jrd/pcmet_proto.h"
using namespace Jrd;
using namespace Firebird;
2001-05-23 15:26:42 +02:00
DATABASE DB = FILENAME "ODS.RDB";
2008-12-22 10:00:05 +01:00
bool PCMET_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tra* transaction)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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.
*
**************************************/
jrd_rel* relation;
index_desc idx;
2008-01-29 11:11:52 +01:00
MemoryPool* new_pool = NULL;
jrd_req* current_request, *request;
jrd_tra* current_transaction;
2001-05-23 15:26:42 +02:00
SET_TDBB(tdbb);
2008-01-29 11:11:52 +01:00
Database* dbb = tdbb->getDatabase();
2001-05-23 15:26:42 +02:00
switch (phase)
{
case 0:
MET_delete_dependencies(tdbb, work->dfw_name, obj_expression_index, transaction);
return false;
2008-12-18 11:57:12 +01:00
2001-05-23 15:26:42 +02:00
case 1:
case 2:
return true;
2001-05-23 15:26:42 +02:00
case 3:
2001-05-23 15:26:42 +02:00
relation = NULL;
MOVE_CLEAR(&idx, sizeof(index_desc));
2008-12-18 11:57:12 +01:00
request = CMP_find_request(tdbb, irq_c_exp_index, IRQ_REQUESTS);
/*
if (request)
{
EXE_unwind(tdbb, request);
}
*/
FOR(REQUEST_HANDLE request)
2001-05-23 15:26:42 +02:00
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.c_str()
2001-05-23 15:26:42 +02:00
if (!REQUEST(irq_c_exp_index))
{
REQUEST(irq_c_exp_index) = request;
}
if (!relation)
{
2001-05-23 15:26:42 +02:00
relation = MET_relation(tdbb, REL.RDB$RELATION_ID);
if (relation->rel_name.length() == 0) {
relation->rel_name = REL.RDB$RELATION_NAME;
}
if (IDX.RDB$INDEX_ID && IDX.RDB$STATISTICS < 0.0)
{
SelectivityList selectivity(*tdbb->getDefaultPool());
const USHORT id = IDX.RDB$INDEX_ID - 1;
IDX_statistics(tdbb, relation, id, selectivity);
2008-03-16 18:10:41 +01:00
DFW_update_index(work->dfw_name.c_str(), id, selectivity, transaction);
EXE_unwind(tdbb, request);
return false;
2001-05-23 15:26:42 +02:00
}
if (IDX.RDB$INDEX_ID)
{
2001-05-23 15:26:42 +02:00
IDX_delete_index(tdbb, relation, IDX.RDB$INDEX_ID - 1);
2008-12-18 11:57:12 +01:00
MET_delete_dependencies(tdbb, work->dfw_name, obj_expression_index, transaction);
2001-05-23 15:26:42 +02:00
MODIFY IDX
IDX.RDB$INDEX_ID.NULL = TRUE;
END_MODIFY;
}
if (IDX.RDB$INDEX_INACTIVE)
{
EXE_unwind(tdbb, request);
return false;
2001-05-23 15:26:42 +02:00
}
if (IDX.RDB$SEGMENT_COUNT)
2008-08-31 03:10:41 +02:00
{
/* Msg359: segments not allowed in expression index %s */
ERR_post(Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_no_segments_err) << Arg::Str(work->dfw_name));
2008-08-31 03:10:41 +02:00
}
2001-05-23 15:26:42 +02:00
if (IDX.RDB$UNIQUE_FLAG)
idx.idx_flags |= idx_unique;
if (IDX.RDB$INDEX_TYPE == 1)
idx.idx_flags |= idx_descending;
CompilerScratch* csb = 0;
2008-12-18 11:57:12 +01:00
/* allocate a new pool to contain the expression tree
2001-05-23 15:26:42 +02:00
for the expression index */
2008-01-29 11:11:52 +01:00
new_pool = dbb->createPool();
{
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_scan_relation(tdbb, relation);
2001-05-23 15:26:42 +02:00
2008-12-18 11:57:12 +01:00
if (!IDX.RDB$EXPRESSION_BLR.NULL)
{
MetaTmp(IDX.RDB$INDEX_NAME)
idx.idx_expression = MET_get_dependencies(tdbb, relation,
2008-12-18 11:57:12 +01:00
NULL, NULL,
&IDX.RDB$EXPRESSION_BLR,
&idx.idx_expression_request,
&csb, tmp,
obj_expression_index, 0,
transaction);
}
}
2001-05-23 15:26:42 +02:00
/* fake a description of the index */
idx.idx_count = 1;
idx.idx_flags |= idx_expressn;
2008-12-18 11:57:12 +01:00
CMP_get_desc(tdbb, csb, idx.idx_expression, &idx.idx_expression_desc);
2001-05-23 15:26:42 +02:00
idx.idx_rpt[0].idx_itype =
2008-03-18 14:04:05 +01:00
DFW_assign_index_type(tdbb, work,
2001-05-23 15:26:42 +02:00
idx.idx_expression_desc.dsc_dtype,
2005-05-28 00:45:31 +02:00
idx.idx_expression_desc.dsc_sub_type);
idx.idx_rpt[0].idx_selectivity = 0;
2008-12-18 11:57:12 +01:00
delete csb;
2001-05-23 15:26:42 +02:00
}
END_FOR;
if (!REQUEST(irq_c_exp_index))
{
REQUEST(irq_c_exp_index) = request;
}
2001-05-23 15:26:42 +02:00
if (!relation)
2008-07-01 03:12:02 +02:00
{
// Msg308: can't create index %s
ERR_post(Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_idx_create_err) << Arg::Str(work->dfw_name));
2008-07-01 03:12:02 +02:00
}
2001-05-23 15:26:42 +02:00
// Actually create the index
2001-05-23 15:26:42 +02:00
SelectivityList selectivity(*tdbb->getDefaultPool());
current_request = tdbb->getRequest();
current_transaction = tdbb->getTransaction();
2005-01-24 10:35:47 +01:00
TRA_attach_request(transaction, idx.idx_expression_request);
tdbb->setRequest(idx.idx_expression_request);
fb_assert(work->dfw_id <= dbb->dbb_max_idx);
idx.idx_id = work->dfw_id;
IDX_create_index(tdbb, relation, &idx, work->dfw_name.c_str(), &work->dfw_id,
transaction, selectivity);
fb_assert(work->dfw_id == idx.idx_id);
2005-01-24 10:35:47 +01:00
TRA_detach_request(idx.idx_expression_request);
tdbb->setRequest(current_request);
2008-12-18 11:57:12 +01:00
tdbb->setTransaction(current_transaction);
2008-03-16 18:10:41 +01:00
DFW_update_index(work->dfw_name.c_str(), idx.idx_id, selectivity, transaction);
2001-05-23 15:26:42 +02:00
// Get rid of the pool containing the expression tree
2001-05-23 15:26:42 +02:00
2008-01-29 11:11:52 +01:00
dbb->deletePool(new_pool);
2001-05-23 15:26:42 +02:00
break;
}
return false;
2001-05-23 15:26:42 +02:00
}
void PCMET_lookup_index(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* 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.
*
**************************************/
SET_TDBB(tdbb);
2008-01-29 11:11:52 +01:00
Database* dbb = tdbb->getDatabase();
2008-12-18 11:57:12 +01:00
// Check the index blocks for the relation to see if we
// have a cached block
2001-05-23 15:26:42 +02:00
IndexBlock* index_block;
2008-12-18 11:57:12 +01:00
for (index_block = relation->rel_index_blocks; index_block; index_block = index_block->idb_next)
2003-09-13 14:03:11 +02:00
{
if (index_block->idb_id == idx->idx_id)
break;
}
2001-05-23 15:26:42 +02:00
if (index_block && index_block->idb_expression)
{
2001-05-23 15:26:42 +02:00
idx->idx_expression = index_block->idb_expression;
idx->idx_expression_request = index_block->idb_expression_request;
memcpy(&idx->idx_expression_desc, &index_block->idb_expression_desc, sizeof(struct dsc));
2001-05-23 15:26:42 +02:00
return;
}
2008-12-18 11:57:12 +01:00
if (!(relation->rel_flags & REL_scanned) || (relation->rel_flags & REL_being_scanned))
2005-11-28 14:58:02 +01:00
{
MET_scan_relation(tdbb, relation);
}
CompilerScratch* csb = NULL;
jrd_req* request = CMP_find_request(tdbb, irq_l_exp_index, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request)
2001-05-23 15:26:42 +02:00
IDX IN RDB$INDICES WITH
IDX.RDB$RELATION_NAME EQ relation->rel_name.c_str() AND
2001-05-23 15:26:42 +02:00
IDX.RDB$INDEX_ID EQ idx->idx_id + 1
if (!REQUEST(irq_l_exp_index))
{
REQUEST(irq_l_exp_index) = request;
}
2001-05-23 15:26:42 +02:00
if (idx->idx_expression_request)
{
CMP_release(tdbb, idx->idx_expression_request);
idx->idx_expression_request = NULL;
}
2001-05-23 15:26:42 +02:00
2008-12-18 11:57:12 +01:00
/* parse the blr, making sure to create the resulting expression
2001-05-23 15:26:42 +02:00
tree and request in its own pool so that it may be cached
with the index block in the "permanent" metadata cache */
{
2008-01-29 11:11:52 +01:00
Jrd::ContextPoolHolder context(tdbb, dbb->createPool());
idx->idx_expression =
MET_parse_blob(tdbb, relation, &IDX.RDB$EXPRESSION_BLR, &csb,
&idx->idx_expression_request, false);
}
2001-05-23 15:26:42 +02:00
END_FOR;
if (!REQUEST(irq_l_exp_index))
{
REQUEST(irq_l_exp_index) = request;
}
if (csb)
{
2008-12-22 10:00:05 +01:00
CMP_get_desc(tdbb, csb, idx->idx_expression, &idx->idx_expression_desc);
2001-05-23 15:26:42 +02:00
}
delete csb;
2001-05-23 15:26:42 +02:00
/* 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(tdbb, index_block->idb_lock, LCK_SR, LCK_NO_WAIT))
2001-05-23 15:26:42 +02:00
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;
memcpy(&index_block->idb_expression_desc, &idx->idx_expression_desc, sizeof(struct dsc));
2001-05-23 15:26:42 +02:00
}
2003-12-31 06:36:12 +01:00