2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
2003-12-31 06:36:12 +01:00
|
|
|
* MODULE: pcmet.epp
|
2006-01-31 08:18:03 +01:00
|
|
|
* 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): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
2001-07-29 19:42:23 +02:00
|
|
|
#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"
|
2004-12-07 02:19:55 +01:00
|
|
|
#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"
|
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
using namespace Jrd;
|
2008-08-27 14:20:47 +02:00
|
|
|
using namespace Firebird;
|
2004-03-20 15:57:40 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
DATABASE DB = FILENAME "ODS.RDB";
|
|
|
|
|
|
|
|
|
2010-01-30 10:58:01 +01:00
|
|
|
void PCMET_expression_index(thread_db* tdbb, const MetaName& name, USHORT id, 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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2010-02-26 10:02:22 +01:00
|
|
|
jrd_rel* relation = NULL;
|
2004-03-28 11:10:30 +02:00
|
|
|
index_desc idx;
|
2008-01-29 11:11:52 +01:00
|
|
|
MemoryPool* new_pool = NULL;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2008-01-29 11:11:52 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
MOVE_CLEAR(&idx, sizeof(index_desc));
|
2004-08-19 20:41:19 +02:00
|
|
|
|
2010-02-26 10:02:22 +01:00
|
|
|
jrd_req* request = CMP_find_request(tdbb, irq_c_exp_index, IRQ_REQUESTS);
|
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
FOR(REQUEST_HANDLE request)
|
|
|
|
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 name.c_str()
|
|
|
|
|
|
|
|
if (!REQUEST(irq_c_exp_index))
|
2004-08-19 20:41:19 +02:00
|
|
|
{
|
2009-09-29 12:35:16 +02:00
|
|
|
REQUEST(irq_c_exp_index) = request;
|
2004-08-19 20:41:19 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2010-01-26 09:29:03 +01:00
|
|
|
if (!relation)
|
|
|
|
{
|
2009-09-29 12:35:16 +02:00
|
|
|
relation = MET_relation(tdbb, REL.RDB$RELATION_ID);
|
|
|
|
if (relation->rel_name.length() == 0) {
|
|
|
|
relation->rel_name = REL.RDB$RELATION_NAME;
|
2004-08-19 20:41:19 +02:00
|
|
|
}
|
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
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);
|
|
|
|
DFW_update_index(name.c_str(), id, selectivity, transaction);
|
2008-06-26 12:48:28 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
EXE_unwind(tdbb, request);
|
|
|
|
return;
|
|
|
|
}
|
2003-11-30 22:14:30 +01:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
if (IDX.RDB$INDEX_ID)
|
|
|
|
{
|
|
|
|
IDX_delete_index(tdbb, relation, IDX.RDB$INDEX_ID - 1);
|
|
|
|
MET_delete_dependencies(tdbb, name, obj_expression_index, transaction);
|
|
|
|
MODIFY IDX
|
|
|
|
IDX.RDB$INDEX_ID.NULL = TRUE;
|
|
|
|
END_MODIFY;
|
|
|
|
}
|
2008-06-26 12:48:28 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
if (IDX.RDB$INDEX_INACTIVE)
|
|
|
|
{
|
|
|
|
EXE_unwind(tdbb, request);
|
|
|
|
return;
|
|
|
|
}
|
2008-06-26 12:48:28 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
if (IDX.RDB$SEGMENT_COUNT)
|
|
|
|
{
|
2009-11-23 09:35:42 +01:00
|
|
|
// Msg359: segments not allowed in expression index %s
|
2009-09-29 12:35:16 +02:00
|
|
|
ERR_post(Arg::Gds(isc_no_meta_update) <<
|
|
|
|
Arg::Gds(isc_no_segments_err) << Arg::Str(name));
|
|
|
|
}
|
|
|
|
if (IDX.RDB$UNIQUE_FLAG)
|
|
|
|
idx.idx_flags |= idx_unique;
|
|
|
|
if (IDX.RDB$INDEX_TYPE == 1)
|
|
|
|
idx.idx_flags |= idx_descending;
|
|
|
|
|
|
|
|
CompilerScratch* csb = 0;
|
2009-11-23 09:35:42 +01:00
|
|
|
// allocate a new pool to contain the expression tree for the expression index
|
2009-09-29 12:35:16 +02:00
|
|
|
new_pool = dbb->createPool();
|
2009-11-23 09:35:42 +01:00
|
|
|
{ // scope
|
2009-09-29 12:35:16 +02:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
|
|
|
MET_scan_relation(tdbb, relation);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
if (!IDX.RDB$EXPRESSION_BLR.NULL)
|
2008-08-31 03:10:41 +02:00
|
|
|
{
|
2010-01-24 16:16:23 +01:00
|
|
|
idx.idx_expression = MET_get_dependencies(tdbb, relation,
|
|
|
|
NULL, 0, NULL,
|
|
|
|
&IDX.RDB$EXPRESSION_BLR,
|
|
|
|
&idx.idx_expression_request,
|
2010-01-26 09:29:03 +01:00
|
|
|
&csb, name,
|
2010-01-24 16:16:23 +01:00
|
|
|
obj_expression_index, 0,
|
|
|
|
transaction);
|
2008-08-31 03:10:41 +02:00
|
|
|
}
|
2009-11-23 09:35:42 +01:00
|
|
|
} // end scope
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-23 09:35:42 +01:00
|
|
|
// fake a description of the index
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
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(tdbb, name,
|
|
|
|
idx.idx_expression_desc.dsc_dtype,
|
|
|
|
idx.idx_expression_desc.dsc_sub_type);
|
|
|
|
idx.idx_rpt[0].idx_selectivity = 0;
|
2004-08-19 20:41:19 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
delete csb;
|
2008-07-01 03:12:02 +02:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
END_FOR;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
if (!REQUEST(irq_c_exp_index))
|
|
|
|
{
|
|
|
|
REQUEST(irq_c_exp_index) = request;
|
|
|
|
}
|
2003-11-30 22:14:30 +01:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
if (!relation)
|
|
|
|
{
|
|
|
|
// Msg308: can't create index %s
|
|
|
|
ERR_post(Arg::Gds(isc_no_meta_update) <<
|
|
|
|
Arg::Gds(isc_idx_create_err) << Arg::Str(name));
|
|
|
|
}
|
2007-08-28 22:17:36 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
// Actually create the index
|
2007-08-28 22:17:36 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
SelectivityList selectivity(*tdbb->getDefaultPool());
|
2008-12-18 11:57:12 +01:00
|
|
|
|
2010-02-26 10:02:22 +01:00
|
|
|
jrd_tra* const current_transaction = tdbb->getTransaction();
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
fb_assert(id <= dbb->dbb_max_idx);
|
|
|
|
idx.idx_id = id;
|
2009-09-30 08:09:05 +02:00
|
|
|
IDX_create_index(tdbb, relation, &idx, name.c_str(), &id, transaction, selectivity);
|
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
fb_assert(id == idx.idx_id);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
tdbb->setTransaction(current_transaction);
|
|
|
|
|
|
|
|
DFW_update_index(name.c_str(), idx.idx_id, selectivity, transaction);
|
|
|
|
|
|
|
|
// Get rid of the pool containing the expression tree
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-09-29 12:35:16 +02:00
|
|
|
dbb->deletePool(new_pool);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-19 20:41:19 +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.
|
|
|
|
*
|
|
|
|
**************************************/
|
2004-08-19 20:41:19 +02:00
|
|
|
SET_TDBB(tdbb);
|
2010-04-02 23:48:15 +02:00
|
|
|
Jrd::Attachment* attachment = tdbb->getAttachment();
|
2008-01-29 11:11:52 +01:00
|
|
|
Database* dbb = tdbb->getDatabase();
|
2004-08-19 20:41:19 +02:00
|
|
|
|
2009-11-23 09:35:42 +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
|
|
|
|
2004-03-19 07:14:53 +01: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
|
|
|
|
2004-08-19 20:41:19 +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;
|
2008-02-02 18:04:06 +01:00
|
|
|
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);
|
2005-11-25 16:39:48 +01:00
|
|
|
}
|
|
|
|
|
2006-01-14 08:00:44 +01:00
|
|
|
CompilerScratch* csb = NULL;
|
2004-08-19 20:41:19 +02:00
|
|
|
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
|
2005-05-12 20:28:04 +02:00
|
|
|
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
|
|
|
|
|
2004-08-19 20:41:19 +02:00
|
|
|
if (!REQUEST(irq_l_exp_index))
|
|
|
|
{
|
|
|
|
REQUEST(irq_l_exp_index) = request;
|
|
|
|
}
|
|
|
|
|
2010-01-26 09:29:03 +01:00
|
|
|
if (idx->idx_expression_request)
|
|
|
|
{
|
2004-08-19 20:41:19 +02:00
|
|
|
CMP_release(tdbb, idx->idx_expression_request);
|
|
|
|
idx->idx_expression_request = NULL;
|
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-23 09:35:42 +01:00
|
|
|
// 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
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-23 09:35:42 +01:00
|
|
|
{ // scope
|
2008-01-29 11:11:52 +01:00
|
|
|
Jrd::ContextPoolHolder context(tdbb, dbb->createPool());
|
2004-08-30 20:11:08 +02:00
|
|
|
idx->idx_expression =
|
|
|
|
MET_parse_blob(tdbb, relation, &IDX.RDB$EXPRESSION_BLR, &csb,
|
2005-03-28 23:52:55 +02:00
|
|
|
&idx->idx_expression_request, false);
|
2009-11-23 09:35:42 +01:00
|
|
|
} // end scope
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
END_FOR;
|
|
|
|
|
2004-08-19 20:41:19 +02:00
|
|
|
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
|
|
|
}
|
2004-08-19 20:41:19 +02:00
|
|
|
delete csb;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2009-11-23 09:35:42 +01:00
|
|
|
// if there is no existing index block for this index, create
|
|
|
|
// one and link it in with the index blocks for this relation
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (!index_block)
|
|
|
|
index_block = IDX_create_index_block(tdbb, relation, idx->idx_id);
|
|
|
|
|
2009-11-23 09:35:42 +01:00
|
|
|
// if we can't get the lock, no big deal: just give up on caching the index info
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2008-01-26 14:17:19 +01:00
|
|
|
if (!LCK_lock(tdbb, index_block->idb_lock, LCK_SR, LCK_NO_WAIT))
|
2001-05-23 15:26:42 +02:00
|
|
|
return;
|
|
|
|
|
2009-11-23 09:35:42 +01:00
|
|
|
// whether the index block already existed or was just created,
|
|
|
|
// fill in the cached information about the index
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
index_block->idb_expression = idx->idx_expression;
|
|
|
|
index_block->idb_expression_request = idx->idx_expression_request;
|
2008-02-02 18:04:06 +01:00
|
|
|
memcpy(&index_block->idb_expression_desc, &idx->idx_expression_desc, sizeof(struct dsc));
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|