mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:03:02 +01:00
Partial indices: DDL, ODS, dependencies, metadata
This commit is contained in:
parent
8e641c4497
commit
02efe138cd
@ -420,6 +420,30 @@ void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relati
|
||||
value.assign(dsqlScratch->getBlrData());
|
||||
}
|
||||
|
||||
void definePartial(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relation,
|
||||
BoolSourceClause* clause, BlrDebugWriter::BlrData& value)
|
||||
{
|
||||
// Get the table node and set up correct context.
|
||||
dsqlScratch->resetContextStack();
|
||||
|
||||
PASS1_make_context(dsqlScratch, relation);
|
||||
|
||||
const auto input = Node::doDsqlPass(dsqlScratch, clause->value);
|
||||
|
||||
// Generate the blr expression.
|
||||
|
||||
dsqlScratch->getBlrData().clear();
|
||||
dsqlScratch->getDebugData().clear();
|
||||
dsqlScratch->appendUChar(dsqlScratch->isVersion4() ? blr_version4 : blr_version5);
|
||||
|
||||
GEN_expr(dsqlScratch, input);
|
||||
dsqlScratch->appendUChar(blr_eoc);
|
||||
|
||||
dsqlScratch->resetContextStack();
|
||||
|
||||
value.assign(dsqlScratch->getBlrData());
|
||||
}
|
||||
|
||||
// Delete a record from RDB$RELATION_CONSTRAINTS based on a constraint name.
|
||||
//
|
||||
// On deleting from RDB$RELATION_CONSTRAINTS, 2 system triggers fire:
|
||||
@ -9794,6 +9818,31 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
|
||||
IDX.RDB$SEGMENT_COUNT = SSHORT(definition.columns.getCount());
|
||||
}
|
||||
END_STORE
|
||||
|
||||
if (!definition.conditionBlr.isEmpty() || !definition.conditionSource.isEmpty())
|
||||
{
|
||||
AutoRequest request;
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
IDX IN RDB$INDICES
|
||||
WITH IDX.RDB$INDEX_NAME EQ name.c_str()
|
||||
{
|
||||
MODIFY IDX
|
||||
if (!definition.conditionBlr.isEmpty())
|
||||
{
|
||||
IDX.RDB$CONDITION_BLR.NULL = FALSE;
|
||||
IDX.RDB$CONDITION_BLR = definition.conditionBlr;
|
||||
}
|
||||
|
||||
if (!definition.conditionSource.isEmpty())
|
||||
{
|
||||
IDX.RDB$CONDITION_SOURCE.NULL = FALSE;
|
||||
IDX.RDB$CONDITION_SOURCE = definition.conditionSource;
|
||||
}
|
||||
END_MODIFY
|
||||
}
|
||||
END_FOR
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9860,6 +9909,21 @@ void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||
attachment->storeBinaryBlob(tdbb, transaction, &definition.expressionBlr, computedValue);
|
||||
}
|
||||
|
||||
if (partial)
|
||||
{
|
||||
const auto dbb = tdbb->getDatabase();
|
||||
if (dbb->getEncodedOdsVersion() < ODS_13_1)
|
||||
ERR_post(Arg::Gds(isc_wish_list));
|
||||
|
||||
BlrDebugWriter::BlrData partialValue;
|
||||
definePartial(dsqlScratch, relation, partial, partialValue);
|
||||
|
||||
attachment->storeMetaDataBlob(tdbb, transaction,
|
||||
&definition.conditionSource, partial->source);
|
||||
attachment->storeBinaryBlob(tdbb, transaction,
|
||||
&definition.conditionBlr, partialValue);
|
||||
}
|
||||
|
||||
store(tdbb, transaction, name, definition);
|
||||
|
||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_INDEX,
|
||||
|
@ -1719,6 +1719,8 @@ public:
|
||||
{
|
||||
expressionBlr.clear();
|
||||
expressionSource.clear();
|
||||
conditionBlr.clear();
|
||||
conditionSource.clear();
|
||||
}
|
||||
|
||||
MetaName relation;
|
||||
@ -1729,6 +1731,8 @@ public:
|
||||
SSHORT type;
|
||||
bid expressionBlr;
|
||||
bid expressionSource;
|
||||
bid conditionBlr;
|
||||
bid conditionSource;
|
||||
MetaName refRelation;
|
||||
Firebird::ObjectsArray<MetaName> refColumns;
|
||||
};
|
||||
@ -1739,15 +1743,16 @@ public:
|
||||
name(p, aName),
|
||||
unique(false),
|
||||
descending(false),
|
||||
relation(NULL),
|
||||
columns(NULL),
|
||||
computed(NULL)
|
||||
relation(nullptr),
|
||||
columns(nullptr),
|
||||
computed(nullptr),
|
||||
partial(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static void store(thread_db* tdbb, jrd_tra* transaction, MetaName& name,
|
||||
const Definition& definition, MetaName* referredIndexName = NULL);
|
||||
const Definition& definition, MetaName* referredIndexName = nullptr);
|
||||
|
||||
public:
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
@ -1767,6 +1772,7 @@ public:
|
||||
NestConst<RelationSourceNode> relation;
|
||||
NestConst<ValueListNode> columns;
|
||||
NestConst<ValueSourceClause> computed;
|
||||
NestConst<BoolSourceClause> partial;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1635,6 +1635,14 @@ unique_opt
|
||||
|
||||
%type index_definition(<createIndexNode>)
|
||||
index_definition($createIndexNode)
|
||||
: index_column_expr($createIndexNode) index_condition_opt
|
||||
{
|
||||
$createIndexNode->partial = $2;
|
||||
}
|
||||
;
|
||||
|
||||
%type index_column_expr(<createIndexNode>)
|
||||
index_column_expr($createIndexNode)
|
||||
: column_list
|
||||
{ $createIndexNode->columns = $1; }
|
||||
| column_parens
|
||||
@ -1647,6 +1655,18 @@ index_definition($createIndexNode)
|
||||
}
|
||||
;
|
||||
|
||||
%type <boolSourceClause> index_condition_opt
|
||||
index_condition_opt
|
||||
: /* nothing */
|
||||
{ $$ = nullptr; }
|
||||
| WHERE search_condition
|
||||
{
|
||||
auto clause = newNode<BoolSourceClause>();
|
||||
clause->value = $2;
|
||||
clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2));
|
||||
$$ = clause;
|
||||
}
|
||||
;
|
||||
|
||||
// CREATE SHADOW
|
||||
%type <createShadowNode> shadow_clause
|
||||
|
@ -339,6 +339,18 @@ Statement* Statement::makeStatement(thread_db* tdbb, CompilerScratch* csb, bool
|
||||
return statement;
|
||||
}
|
||||
|
||||
Statement* Statement::makeBoolExpression(thread_db* tdbb, BoolExprNode*& node,
|
||||
CompilerScratch* csb, bool internalFlag)
|
||||
{
|
||||
fb_assert(csb->csb_node->getKind() == DmlNode::KIND_BOOLEAN);
|
||||
|
||||
return makeStatement(tdbb, csb, internalFlag,
|
||||
[&]
|
||||
{
|
||||
node = static_cast<BoolExprNode*>(csb->csb_node);
|
||||
});
|
||||
}
|
||||
|
||||
Statement* Statement::makeValueExpression(thread_db* tdbb, ValueExprNode*& node, dsc& desc,
|
||||
CompilerScratch* csb, bool internalFlag)
|
||||
{
|
||||
|
@ -49,6 +49,9 @@ public:
|
||||
static Statement* makeStatement(thread_db* tdbb, CompilerScratch* csb, bool internalFlag,
|
||||
std::function<void ()> beforeCsbRelease = nullptr);
|
||||
|
||||
static Statement* makeBoolExpression(thread_db* tdbb, BoolExprNode*& node,
|
||||
CompilerScratch* csb, bool internalFlag);
|
||||
|
||||
static Statement* makeValueExpression(thread_db* tdbb, ValueExprNode*& node, dsc& desc,
|
||||
CompilerScratch* csb, bool internalFlag);
|
||||
|
||||
|
@ -509,13 +509,15 @@ bool BTR_description(thread_db* tdbb, jrd_rel* relation, index_root_page* root,
|
||||
idx->idx_count = irt_desc->irt_keys;
|
||||
idx->idx_flags = irt_desc->irt_flags;
|
||||
idx->idx_runtime_flags = 0;
|
||||
idx->idx_foreign_primaries = NULL;
|
||||
idx->idx_foreign_relations = NULL;
|
||||
idx->idx_foreign_indexes = NULL;
|
||||
idx->idx_foreign_primaries = nullptr;
|
||||
idx->idx_foreign_relations = nullptr;
|
||||
idx->idx_foreign_indexes = nullptr;
|
||||
idx->idx_primary_relation = 0;
|
||||
idx->idx_primary_index = 0;
|
||||
idx->idx_expression = NULL;
|
||||
idx->idx_expression_statement = NULL;
|
||||
idx->idx_expression = nullptr;
|
||||
idx->idx_expression_statement = nullptr;
|
||||
idx->idx_condition = nullptr;
|
||||
idx->idx_condition_statement = nullptr;
|
||||
|
||||
// pick up field ids and type descriptions for each of the fields
|
||||
const UCHAR* ptr = (UCHAR*) root + irt_desc->irt_desc;
|
||||
@ -530,31 +532,95 @@ bool BTR_description(thread_db* tdbb, jrd_rel* relation, index_root_page* root,
|
||||
}
|
||||
idx->idx_selectivity = idx_desc->idx_selectivity;
|
||||
|
||||
if (idx->idx_flags & idx_expressn)
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
MET_lookup_index_expression(tdbb, relation, idx);
|
||||
fb_assert(idx->idx_expression != NULL);
|
||||
fb_assert(idx->idx_expression);
|
||||
}
|
||||
|
||||
if (idx->idx_flags & idx_condition)
|
||||
{
|
||||
MET_lookup_index_condition(tdbb, relation, idx);
|
||||
fb_assert(idx->idx_condition);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record* record)
|
||||
{
|
||||
if (!(idx->idx_flags & idx_condition))
|
||||
return true;
|
||||
|
||||
fb_assert(idx->idx_condition);
|
||||
|
||||
Request* const orgRequest = tdbb->getRequest();
|
||||
Request* const conditionRequest = idx->idx_condition_statement->findRequest(tdbb);
|
||||
|
||||
fb_assert(conditionRequest != orgRequest);
|
||||
|
||||
fb_assert(!conditionRequest->req_caller);
|
||||
conditionRequest->req_caller = orgRequest;
|
||||
|
||||
conditionRequest->req_flags &= req_in_use;
|
||||
conditionRequest->req_flags |= req_active;
|
||||
TRA_attach_request(tdbb->getTransaction(), conditionRequest);
|
||||
tdbb->setRequest(conditionRequest);
|
||||
|
||||
fb_assert(conditionRequest->req_transaction);
|
||||
|
||||
conditionRequest->req_rpb[0].rpb_record = record;
|
||||
conditionRequest->req_rpb[0].rpb_number.setValue(BOF_NUMBER);
|
||||
conditionRequest->req_rpb[0].rpb_number.setValid(true);
|
||||
conditionRequest->req_flags &= ~req_null;
|
||||
|
||||
FbLocalStatus status;
|
||||
bool result = false;
|
||||
|
||||
try
|
||||
{
|
||||
Jrd::ContextPoolHolder context(tdbb, conditionRequest->req_pool);
|
||||
|
||||
if (orgRequest)
|
||||
conditionRequest->setGmtTimeStamp(orgRequest->getGmtTimeStamp());
|
||||
else
|
||||
conditionRequest->validateTimeStamp();
|
||||
|
||||
result = idx->idx_condition->execute(tdbb, conditionRequest);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(&status);
|
||||
}
|
||||
|
||||
EXE_unwind(tdbb, conditionRequest);
|
||||
conditionRequest->req_flags &= ~req_in_use;
|
||||
conditionRequest->req_attachment = nullptr;
|
||||
|
||||
tdbb->setRequest(orgRequest);
|
||||
|
||||
status.check();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& notNull)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
fb_assert(idx->idx_expression != NULL);
|
||||
fb_assert(idx->idx_expression);
|
||||
|
||||
// check for resursive expression evaluation
|
||||
// check for recursive expression evaluation
|
||||
Request* const org_request = tdbb->getRequest();
|
||||
Request* const expr_request = idx->idx_expression_statement->findRequest(tdbb, true);
|
||||
|
||||
if (expr_request == NULL)
|
||||
if (!expr_request)
|
||||
ERR_post(Arg::Gds(isc_random) << "Attempt to evaluate index expression recursively");
|
||||
|
||||
fb_assert(expr_request != org_request);
|
||||
|
||||
fb_assert(expr_request->req_caller == NULL);
|
||||
fb_assert(!expr_request->req_caller);
|
||||
expr_request->req_caller = org_request;
|
||||
|
||||
expr_request->req_flags &= req_in_use;
|
||||
@ -1241,7 +1307,7 @@ idx_e BTR_key(thread_db* tdbb, jrd_rel* relation, Record* record, index_desc* id
|
||||
{
|
||||
bool isNull;
|
||||
// for expression indices, compute the value of the expression
|
||||
if (idx->idx_flags & idx_expressn)
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
bool notNull;
|
||||
desc_ptr = BTR_eval_expression(tdbb, idx, record, notNull);
|
||||
@ -1437,9 +1503,9 @@ USHORT BTR_key_length(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (idx->idx_flags & idx_expressn)
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
fb_assert(idx->idx_expression != NULL);
|
||||
fb_assert(idx->idx_expression);
|
||||
length = idx->idx_expression_desc.dsc_length;
|
||||
if (idx->idx_expression_desc.dsc_dtype == dtype_varying)
|
||||
{
|
||||
@ -1756,7 +1822,7 @@ void BTR_make_null_key(thread_db* tdbb, const index_desc* idx, temporary_key* ke
|
||||
const index_desc::idx_repeat* tail = idx->idx_rpt;
|
||||
|
||||
// If the index is a single segment index, don't sweat the compound stuff
|
||||
if ((idx->idx_count == 1) || (idx->idx_flags & idx_expressn))
|
||||
if ((idx->idx_count == 1) || (idx->idx_flags & idx_expression))
|
||||
{
|
||||
compress(tdbb, &null_desc, key, tail->idx_itype, true, descending, INTL_KEY_SORT);
|
||||
}
|
||||
@ -6144,7 +6210,7 @@ string print_key(thread_db* tdbb, jrd_rel* relation, index_desc* idx, Record* re
|
||||
|
||||
try
|
||||
{
|
||||
if (idx->idx_flags & idx_expressn)
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
bool notNull = false;
|
||||
const dsc* const desc = BTR_eval_expression(tdbb, idx, record, notNull);
|
||||
|
@ -66,9 +66,11 @@ struct index_desc
|
||||
vec<int>* idx_foreign_primaries; // ids for primary/unique indexes with partners
|
||||
vec<int>* idx_foreign_relations; // ids for foreign key partner relations
|
||||
vec<int>* idx_foreign_indexes; // ids for foreign key partner indexes
|
||||
ValueExprNode* idx_expression; // node tree for indexed expresssion
|
||||
ValueExprNode* idx_expression; // node tree for indexed expression
|
||||
dsc idx_expression_desc; // descriptor for expression result
|
||||
Statement* idx_expression_statement; // stored statement for expression evaluation
|
||||
BoolExprNode* idx_condition; // node tree for index condition
|
||||
Statement* idx_condition_statement; // stored statement for index condition
|
||||
// This structure should exactly match IRTD structure for current ODS
|
||||
struct idx_repeat
|
||||
{
|
||||
@ -114,7 +116,8 @@ const int idx_descending = 2;
|
||||
const int idx_in_progress = 4;
|
||||
const int idx_foreign = 8;
|
||||
const int idx_primary = 16;
|
||||
const int idx_expressn = 32;
|
||||
const int idx_expression = 32;
|
||||
const int idx_condition = 64;
|
||||
|
||||
// these flags are for idx_runtime_flags
|
||||
|
||||
|
@ -34,6 +34,7 @@ void BTR_complement_key(Jrd::temporary_key*);
|
||||
void BTR_create(Jrd::thread_db*, Jrd::IndexCreation&, Jrd::SelectivityList&);
|
||||
bool BTR_delete_index(Jrd::thread_db*, Jrd::win*, USHORT);
|
||||
bool BTR_description(Jrd::thread_db*, Jrd::jrd_rel*, Ods::index_root_page*, Jrd::index_desc*, USHORT);
|
||||
bool BTR_check_condition(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*);
|
||||
DSC* BTR_eval_expression(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*, bool&);
|
||||
void BTR_evaluate(Jrd::thread_db*, const Jrd::IndexRetrieval*, Jrd::RecordBitmap**, Jrd::RecordBitmap*);
|
||||
UCHAR* BTR_find_leaf(Ods::btree_page*, Jrd::temporary_key*, UCHAR*, USHORT*, bool, bool);
|
||||
|
139
src/jrd/dfw.epp
139
src/jrd/dfw.epp
@ -1235,7 +1235,6 @@ static const deferred_task task_table[] =
|
||||
{ dfw_add_file, add_file },
|
||||
{ dfw_add_shadow, add_shadow },
|
||||
{ dfw_delete_index, modify_index },
|
||||
{ dfw_delete_expression_index, modify_index },
|
||||
{ dfw_delete_rfr, delete_rfr },
|
||||
{ dfw_delete_relation, delete_relation },
|
||||
{ dfw_delete_shadow, delete_shadow },
|
||||
@ -2744,7 +2743,8 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
{
|
||||
case 0:
|
||||
cleanup_index_creation(tdbb, work, transaction);
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, obj_expression_index, transaction);
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, obj_index_expression, transaction);
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, obj_index_condition, transaction);
|
||||
return false;
|
||||
|
||||
case 1:
|
||||
@ -2753,14 +2753,14 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
|
||||
case 3:
|
||||
{
|
||||
jrd_rel* relation = NULL;
|
||||
jrd_rel* relation = nullptr;
|
||||
CompilerScratch* csb = nullptr;
|
||||
MemoryPool* new_pool = nullptr;
|
||||
|
||||
const auto dbb = tdbb->getDatabase();
|
||||
const auto attachment = tdbb->getAttachment();
|
||||
|
||||
index_desc idx;
|
||||
MemoryPool* new_pool = NULL;
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
|
||||
MOVE_CLEAR(&idx, sizeof(index_desc));
|
||||
|
||||
AutoCacheRequest request(tdbb, irq_c_exp_index, IRQ_REQUESTS);
|
||||
@ -2774,9 +2774,8 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
if (!relation)
|
||||
{
|
||||
relation = MET_relation(tdbb, REL.RDB$RELATION_ID);
|
||||
if (relation->rel_name.length() == 0) {
|
||||
if (relation->rel_name.length() == 0)
|
||||
relation->rel_name = REL.RDB$RELATION_NAME;
|
||||
}
|
||||
|
||||
if (IDX.RDB$INDEX_ID && IDX.RDB$STATISTICS < 0.0)
|
||||
{
|
||||
@ -2791,7 +2790,8 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
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, transaction);
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, obj_index_expression, transaction);
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, obj_index_condition, transaction);
|
||||
MODIFY IDX
|
||||
IDX.RDB$INDEX_ID.NULL = TRUE;
|
||||
END_MODIFY
|
||||
@ -2811,35 +2811,30 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
if (IDX.RDB$INDEX_TYPE == 1)
|
||||
idx.idx_flags |= idx_descending;
|
||||
|
||||
CompilerScratch* csb = NULL;
|
||||
// allocate a new pool to contain the expression tree for the expression index
|
||||
MET_scan_relation(tdbb, relation);
|
||||
|
||||
// Allocate a new pool to contain the expression tree
|
||||
// for index expression / condition
|
||||
new_pool = attachment->createPool();
|
||||
{ // scope
|
||||
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
||||
MET_scan_relation(tdbb, relation);
|
||||
|
||||
if (!IDX.RDB$EXPRESSION_BLR.NULL)
|
||||
{
|
||||
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$EXPRESSION_BLR,
|
||||
nullptr, &csb, work->dfw_name, obj_expression_index, 0,
|
||||
transaction);
|
||||
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
||||
|
||||
idx.idx_expression_statement = Statement::makeValueExpression(tdbb,
|
||||
idx.idx_expression, idx.idx_expression_desc, csb, false);
|
||||
}
|
||||
} // end scope
|
||||
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$EXPRESSION_BLR,
|
||||
nullptr, &csb, work->dfw_name, obj_index_expression, 0,
|
||||
transaction);
|
||||
|
||||
idx.idx_expression_statement = Statement::makeValueExpression(tdbb,
|
||||
idx.idx_expression, idx.idx_expression_desc, csb, false);
|
||||
|
||||
// fake a description of the index
|
||||
|
||||
idx.idx_count = 1;
|
||||
idx.idx_flags |= idx_expressn;
|
||||
idx.idx_flags |= idx_expression;
|
||||
idx.idx_rpt[0].idx_itype =
|
||||
DFW_assign_index_type(tdbb, work->dfw_name,
|
||||
idx.idx_expression_desc.dsc_dtype,
|
||||
idx.idx_expression_desc.dsc_sub_type);
|
||||
idx.idx_rpt[0].idx_selectivity = 0;
|
||||
|
||||
delete csb;
|
||||
}
|
||||
}
|
||||
END_FOR
|
||||
@ -2854,6 +2849,34 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
Arg::Gds(isc_idx_create_err) << Arg::Str(work->dfw_name));
|
||||
}
|
||||
|
||||
idx.idx_condition = nullptr;
|
||||
idx.idx_condition_statement = nullptr;
|
||||
|
||||
if (dbb->getEncodedOdsVersion() >= ODS_13_1)
|
||||
{
|
||||
AutoCacheRequest request(tdbb, irq_c_cond_index, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE request)
|
||||
IDX IN RDB$INDICES WITH
|
||||
IDX.RDB$CONDITION_BLR NOT MISSING AND
|
||||
IDX.RDB$INDEX_NAME EQ work->dfw_name.c_str()
|
||||
{
|
||||
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
||||
|
||||
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$CONDITION_BLR,
|
||||
nullptr, &csb, work->dfw_name, obj_index_condition, 0,
|
||||
transaction);
|
||||
|
||||
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
|
||||
idx.idx_condition, csb, false);
|
||||
|
||||
idx.idx_flags |= idx_condition;
|
||||
}
|
||||
END_FOR
|
||||
}
|
||||
|
||||
delete csb;
|
||||
|
||||
// Actually create the index
|
||||
|
||||
// Protect relation from modification to create consistent index
|
||||
@ -2878,8 +2901,10 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
tdbb->setTransaction(current_transaction);
|
||||
tdbb->setRequest(current_request);
|
||||
|
||||
// Get rid of the expression statement.
|
||||
// Get rid of the expression/condition statements
|
||||
idx.idx_expression_statement->release(tdbb);
|
||||
if (idx.idx_condition_statement)
|
||||
idx.idx_condition_statement->release(tdbb);
|
||||
|
||||
throw;
|
||||
}
|
||||
@ -2889,8 +2914,10 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
|
||||
DFW_update_index(work->dfw_name.c_str(), idx.idx_id, selectivity, transaction);
|
||||
|
||||
// Get rid of the expression statement.
|
||||
// Get rid of the expression/condition statements
|
||||
idx.idx_expression_statement->release(tdbb);
|
||||
if (idx.idx_condition_statement)
|
||||
idx.idx_condition_statement->release(tdbb);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3294,7 +3321,6 @@ static bool modify_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
break;
|
||||
|
||||
case dfw_delete_index :
|
||||
case dfw_delete_expression_index :
|
||||
task_routine = delete_index;
|
||||
is_create = false;
|
||||
break;
|
||||
@ -3590,6 +3616,39 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
// Msg308: can't create index %s
|
||||
}
|
||||
|
||||
idx.idx_condition = nullptr;
|
||||
idx.idx_condition_statement = nullptr;
|
||||
|
||||
if (dbb->getEncodedOdsVersion() >= ODS_13_1)
|
||||
{
|
||||
// Allocate a new pool to contain the expression tree
|
||||
// for index condition
|
||||
const auto new_pool = attachment->createPool();
|
||||
CompilerScratch* csb = nullptr;
|
||||
|
||||
AutoCacheRequest request(tdbb, irq_c_cond_index, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE request)
|
||||
IDX IN RDB$INDICES WITH
|
||||
IDX.RDB$CONDITION_BLR NOT MISSING AND
|
||||
IDX.RDB$INDEX_NAME EQ work->dfw_name.c_str()
|
||||
{
|
||||
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
||||
|
||||
MET_get_dependencies(tdbb, relation, nullptr, 0, nullptr, &IDX.RDB$CONDITION_BLR,
|
||||
nullptr, &csb, work->dfw_name, obj_index_condition, 0,
|
||||
transaction);
|
||||
|
||||
idx.idx_condition_statement = Statement::makeBoolExpression(tdbb,
|
||||
idx.idx_condition, csb, false);
|
||||
|
||||
idx.idx_flags |= idx_condition;
|
||||
}
|
||||
END_FOR
|
||||
|
||||
delete csb;
|
||||
}
|
||||
|
||||
// Actually create the index
|
||||
|
||||
partner_relation = NULL;
|
||||
@ -3660,6 +3719,9 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
fb_assert(work->dfw_id == idx.idx_id);
|
||||
DFW_update_index(work->dfw_name.c_str(), idx.idx_id, selectivity, transaction);
|
||||
|
||||
if (idx.idx_condition_statement)
|
||||
idx.idx_condition_statement->release(tdbb);
|
||||
|
||||
if (partner_relation)
|
||||
{
|
||||
// signal to other processes about new constraint
|
||||
@ -4707,10 +4769,8 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
if (isTempIndex)
|
||||
return false;
|
||||
|
||||
if (work->dfw_type == dfw_delete_expression_index)
|
||||
{
|
||||
MET_delete_dependencies(tdbb, arg->dfw_name, obj_expression_index, transaction);
|
||||
}
|
||||
MET_delete_dependencies(tdbb, arg->dfw_name, obj_index_expression, transaction);
|
||||
MET_delete_dependencies(tdbb, arg->dfw_name, obj_index_condition, transaction);
|
||||
|
||||
// if index was bound to deleted FK constraint
|
||||
// then work->dfw_args was set in VIO_erase
|
||||
@ -5309,8 +5369,9 @@ static bool find_depend_in_dfw(thread_db* tdbb,
|
||||
case obj_procedure:
|
||||
dfw_type = dfw_delete_procedure;
|
||||
break;
|
||||
case obj_expression_index:
|
||||
dfw_type = dfw_delete_expression_index;
|
||||
case obj_index_expression:
|
||||
case obj_index_condition:
|
||||
dfw_type = dfw_delete_index;
|
||||
break;
|
||||
case obj_package_header:
|
||||
dfw_type = dfw_drop_package_header;
|
||||
@ -5350,7 +5411,7 @@ static bool find_depend_in_dfw(thread_db* tdbb,
|
||||
}
|
||||
}
|
||||
|
||||
if (work->dfw_type == dfw_type && dfw_type == dfw_delete_expression_index)
|
||||
if (work->dfw_type == dfw_type && dfw_type == dfw_delete_index)
|
||||
{
|
||||
for (FB_SIZE_T i = 0; i < work->dfw_args.getCount(); ++i)
|
||||
{
|
||||
|
@ -618,6 +618,9 @@ bool IndexCreateTask::handler(WorkItem& _item)
|
||||
{
|
||||
Record* record = stack.pop();
|
||||
|
||||
if (!BTR_check_condition(tdbb, idx, record))
|
||||
continue;
|
||||
|
||||
result = BTR_key(tdbb, relation, record, idx, &key,
|
||||
((idx->idx_flags & idx_unique) ? INTL_KEY_UNIQUE : INTL_KEY_SORT));
|
||||
|
||||
@ -1155,6 +1158,9 @@ void IDX_garbage_collect(thread_db* tdbb, record_param* rpb, RecordStack& going,
|
||||
{
|
||||
Record* const rec1 = stack1.object();
|
||||
|
||||
if (!BTR_check_condition(tdbb, &idx, rec1))
|
||||
continue;
|
||||
|
||||
idx_e result = BTR_key(tdbb, rpb->rpb_relation, rec1, &idx, &key1,
|
||||
((idx.idx_flags & idx_unique) ? INTL_KEY_UNIQUE : INTL_KEY_SORT));
|
||||
|
||||
@ -1269,6 +1275,9 @@ void IDX_modify(thread_db* tdbb,
|
||||
|
||||
while (BTR_next_index(tdbb, org_rpb->rpb_relation, transaction, &idx, &window))
|
||||
{
|
||||
if (!BTR_check_condition(tdbb, &idx, new_rpb->rpb_record))
|
||||
continue;
|
||||
|
||||
IndexErrorContext context(new_rpb->rpb_relation, &idx);
|
||||
idx_e error_code;
|
||||
|
||||
@ -1345,6 +1354,8 @@ void IDX_modify_check_constraints(thread_db* tdbb,
|
||||
continue;
|
||||
}
|
||||
|
||||
fb_assert(!(idx.idx_flags & idx_condition));
|
||||
|
||||
IndexErrorContext context(new_rpb->rpb_relation, &idx);
|
||||
idx_e error_code;
|
||||
|
||||
@ -1494,6 +1505,9 @@ void IDX_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
|
||||
while (BTR_next_index(tdbb, rpb->rpb_relation, transaction, &idx, &window))
|
||||
{
|
||||
if (!BTR_check_condition(tdbb, &idx, rpb->rpb_record))
|
||||
continue;
|
||||
|
||||
IndexErrorContext context(rpb->rpb_relation, &idx);
|
||||
idx_e error_code;
|
||||
|
||||
@ -1532,11 +1546,11 @@ static bool cmpRecordKeys(thread_db* tdbb,
|
||||
HalfStaticArray<UCHAR, 256> tmp;
|
||||
DSC desc1, desc2;
|
||||
|
||||
if (idx2->idx_flags & idx_expressn)
|
||||
if (idx2->idx_flags & idx_expression)
|
||||
{
|
||||
// Remove assertion below if\when expression index will participate in FK,
|
||||
// currently it is impossible.
|
||||
fb_assert((idx1->idx_flags & idx_expressn) != 0);
|
||||
fb_assert(idx1->idx_flags & idx_expression);
|
||||
|
||||
bool flag_idx;
|
||||
const dsc* desc_idx = BTR_eval_expression(tdbb, idx2, rec2, flag_idx);
|
||||
@ -1812,6 +1826,9 @@ static idx_e check_partner_index(thread_db* tdbb,
|
||||
BUGCHECK(175); // msg 175 partner index description not found
|
||||
}
|
||||
|
||||
fb_assert(!(idx->idx_flags & idx_condition));
|
||||
fb_assert(!(partner_idx.idx_flags & idx_condition));
|
||||
|
||||
bool starting = false;
|
||||
USHORT segment;
|
||||
|
||||
@ -2063,11 +2080,19 @@ static void release_index_block(thread_db* tdbb, IndexBlock* index_block)
|
||||
*
|
||||
**************************************/
|
||||
if (index_block->idb_expression_statement)
|
||||
{
|
||||
index_block->idb_expression_statement->release(tdbb);
|
||||
index_block->idb_expression_statement = nullptr;
|
||||
}
|
||||
index_block->idb_expression = nullptr;
|
||||
index_block->idb_expression_desc.clear();
|
||||
|
||||
index_block->idb_expression_statement = NULL;
|
||||
index_block->idb_expression = NULL;
|
||||
MOVE_CLEAR(&index_block->idb_expression_desc, sizeof(dsc));
|
||||
if (index_block->idb_condition_statement)
|
||||
{
|
||||
index_block->idb_condition_statement->release(tdbb);
|
||||
index_block->idb_condition_statement = nullptr;
|
||||
}
|
||||
index_block->idb_condition = nullptr;
|
||||
|
||||
LCK_release(tdbb, index_block->idb_lock);
|
||||
}
|
||||
|
@ -85,6 +85,8 @@ enum irq_type_t
|
||||
irq_c_exp_index, // create expression index
|
||||
irq_l_exp_index, // lookup expression index
|
||||
irq_l_exp_index_blr, // lookup expression index BLR
|
||||
irq_c_cond_index, // create condition index
|
||||
irq_l_cond_index, // lookup condition index
|
||||
|
||||
irq_l_rel_id, // lookup relation id
|
||||
irq_l_procedure, // lookup procedure name
|
||||
|
@ -312,6 +312,8 @@ public:
|
||||
ValueExprNode* idb_expression; // node tree for index expression
|
||||
Statement* idb_expression_statement; // statement for index expression evaluation
|
||||
dsc idb_expression_desc; // descriptor for expression result
|
||||
BoolExprNode* idb_condition; // node tree for index condition
|
||||
Statement* idb_condition_statement; // statement for index condition evaluation
|
||||
Lock* idb_lock; // lock to synchronize changes to index
|
||||
USHORT idb_id;
|
||||
};
|
||||
|
@ -2560,6 +2560,98 @@ SLONG MET_lookup_index_name(thread_db* tdbb,
|
||||
}
|
||||
|
||||
|
||||
void MET_lookup_index_condition(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* M E T _ l o o k u p _ i n d e x _ c o n d i t i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Lookup information about an index, in
|
||||
* the metadata cache if possible.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
const auto attachment = tdbb->getAttachment();
|
||||
|
||||
// Check the index blocks for the relation to see if we have a cached block
|
||||
|
||||
IndexBlock* index_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_condition)
|
||||
{
|
||||
idx->idx_condition = index_block->idb_condition;
|
||||
idx->idx_condition_statement = index_block->idb_condition_statement;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto dbb = tdbb->getDatabase();
|
||||
if (dbb->getEncodedOdsVersion() < ODS_13_1)
|
||||
return;
|
||||
|
||||
if (!(relation->rel_flags & REL_scanned) || (relation->rel_flags & REL_being_scanned))
|
||||
MET_scan_relation(tdbb, relation);
|
||||
|
||||
CompilerScratch* csb = nullptr;
|
||||
AutoCacheRequest request(tdbb, irq_l_cond_index, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE request)
|
||||
IDX IN RDB$INDICES WITH
|
||||
IDX.RDB$RELATION_NAME EQ relation->rel_name.c_str() AND
|
||||
IDX.RDB$INDEX_ID EQ idx->idx_id + 1
|
||||
{
|
||||
if (idx->idx_condition_statement)
|
||||
{
|
||||
idx->idx_condition_statement->release(tdbb);
|
||||
idx->idx_condition_statement = nullptr;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
{ // scope
|
||||
Jrd::ContextPoolHolder context(tdbb, attachment->createPool());
|
||||
|
||||
MET_parse_blob(tdbb, relation, &IDX.RDB$CONDITION_BLR, &csb, nullptr, false, false);
|
||||
|
||||
idx->idx_condition_statement = Statement::makeBoolExpression(tdbb,
|
||||
idx->idx_condition, csb, false);
|
||||
} // end scope
|
||||
}
|
||||
END_FOR
|
||||
|
||||
delete 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(tdbb, index_block->idb_lock, LCK_SR, LCK_NO_WAIT))
|
||||
{
|
||||
// clear lock error from status vector
|
||||
fb_utils::init_status(tdbb->tdbb_status_vector);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill in the cached information about the index
|
||||
|
||||
index_block->idb_condition = idx->idx_condition;
|
||||
index_block->idb_condition_statement = idx->idx_condition_statement;
|
||||
}
|
||||
|
||||
|
||||
void MET_lookup_index_expression(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
|
||||
{
|
||||
/**************************************
|
||||
|
@ -107,6 +107,7 @@ SLONG MET_lookup_generator(Jrd::thread_db*, const Jrd::MetaName&, bool* sysGen
|
||||
bool MET_lookup_generator_id(Jrd::thread_db*, SLONG, Jrd::MetaName&, bool* sysGen = 0);
|
||||
void MET_update_generator_increment(Jrd::thread_db* tdbb, SLONG gen_id, SLONG step);
|
||||
void MET_lookup_index(Jrd::thread_db*, Jrd::MetaName&, const Jrd::MetaName&, USHORT);
|
||||
void MET_lookup_index_condition(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*);
|
||||
void MET_lookup_index_expression(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*);
|
||||
bool MET_lookup_index_expression_blr(Jrd::thread_db* tdbb, const Jrd::MetaName& index_name, Jrd::bid& blob_id);
|
||||
SLONG MET_lookup_index_name(Jrd::thread_db*, const Jrd::MetaName&, SLONG*, Jrd::IndexStatus* status);
|
||||
|
@ -44,6 +44,8 @@ NAME("RDB$COLLATION_NAME", nam_collate_name)
|
||||
NAME("RDB$COMPLEX_NAME", nam_cpx_name)
|
||||
NAME("RDB$COMPUTED_BLR", nam_computed)
|
||||
NAME("RDB$COMPUTED_SOURCE", nam_c_source)
|
||||
NAME("RDB$CONDITION_BLR", nam_cond_blr)
|
||||
NAME("RDB$CONDITION_SOURCE", nam_cond_source)
|
||||
NAME("RDB$CONSTRAINT_NAME", nam_con_name)
|
||||
NAME("RDB$CONSTRAINT_TYPE", nam_con_type)
|
||||
NAME("RDB$CONST_NAME_UQ", nam_con_uq)
|
||||
|
@ -36,7 +36,7 @@ const ObjectType obj_trigger = 2;
|
||||
const ObjectType obj_computed = 3;
|
||||
const ObjectType obj_validation = 4;
|
||||
const ObjectType obj_procedure = 5;
|
||||
const ObjectType obj_expression_index = 6;
|
||||
const ObjectType obj_index_expression = 6;
|
||||
const ObjectType obj_exception = 7;
|
||||
const ObjectType obj_user = 8;
|
||||
const ObjectType obj_field = 9;
|
||||
@ -72,8 +72,9 @@ const ObjectType obj_filters = 33;
|
||||
const ObjectType obj_jobs = 34;
|
||||
const ObjectType obj_tablespace = 35;
|
||||
const ObjectType obj_tablespaces = 36;
|
||||
const ObjectType obj_index_condition = 37;
|
||||
|
||||
const ObjectType obj_type_MAX = 37;
|
||||
const ObjectType obj_type_MAX = 38;
|
||||
|
||||
// used in the parser only / no relation with obj_type_MAX (should be greater)
|
||||
const ObjectType obj_user_or_role= 100;
|
||||
|
@ -435,7 +435,7 @@ void Retrieval::analyzeNavigation(const InversionCandidateList& inversions)
|
||||
|
||||
// only a single-column ORDER BY clause can be mapped to
|
||||
// an expression index
|
||||
if (idx->idx_flags & idx_expressn)
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
if (sort->expressions.getCount() != 1)
|
||||
continue;
|
||||
@ -498,7 +498,7 @@ void Retrieval::analyzeNavigation(const InversionCandidateList& inversions)
|
||||
|
||||
for (const auto node : nodes)
|
||||
{
|
||||
if (idx->idx_flags & idx_expressn)
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
if (!checkExpressionIndex(csb, idx, node, stream))
|
||||
continue;
|
||||
@ -1477,7 +1477,7 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
|
||||
|
||||
const auto idx = indexScratch->index;
|
||||
|
||||
if (idx->idx_flags & idx_expressn)
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
// see if one side or the other is matchable to the index expression
|
||||
|
||||
@ -1553,7 +1553,7 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
|
||||
|
||||
const auto fieldNode = nodeAs<FieldNode>(match);
|
||||
|
||||
if (!(idx->idx_flags & idx_expressn))
|
||||
if (!(idx->idx_flags & idx_expression))
|
||||
fb_assert(fieldNode);
|
||||
|
||||
const bool isDesc = (idx->idx_flags & idx_descending);
|
||||
@ -1565,7 +1565,7 @@ bool Retrieval::matchBoolean(IndexScratch* indexScratch,
|
||||
|
||||
for (unsigned i = 0; i < idx->idx_count; i++)
|
||||
{
|
||||
if (!(idx->idx_flags & idx_expressn) &&
|
||||
if (!(idx->idx_flags & idx_expression) &&
|
||||
fieldNode->fieldId != idx->idx_rpt[i].idx_field)
|
||||
{
|
||||
continue;
|
||||
@ -2106,7 +2106,7 @@ bool Retrieval::validateStarts(IndexScratch* indexScratch,
|
||||
|
||||
const auto idx = indexScratch->index;
|
||||
|
||||
if (idx->idx_flags & idx_expressn)
|
||||
if (idx->idx_flags & idx_expression)
|
||||
{
|
||||
// AB: What if the expression contains a number/float etc.. and
|
||||
// we use starting with against it? Is that allowed?
|
||||
|
@ -99,6 +99,8 @@ RELATION(nam_indices, rel_indices, ODS_8_0, rel_persistent)
|
||||
FIELD(f_idx_exp_blr, nam_exp_blr, fld_value, 1, ODS_8_0)
|
||||
FIELD(f_idx_exp_source, nam_exp_source, fld_source, 1, ODS_8_0)
|
||||
FIELD(f_idx_statistics, nam_statistics, fld_statistics, 1, ODS_8_0)
|
||||
FIELD(f_idx_cond_blr, nam_cond_blr, fld_value, 1, ODS_13_1)
|
||||
FIELD(f_idx_cond_source, nam_cond_source, fld_source, 1, ODS_13_1)
|
||||
END_RELATION
|
||||
|
||||
// Relation 5 (RDB$RELATION_FIELDS)
|
||||
|
@ -490,7 +490,6 @@ enum dfw_t {
|
||||
dfw_revoke,
|
||||
dfw_scan_relation,
|
||||
dfw_create_expression_index,
|
||||
dfw_delete_expression_index,
|
||||
dfw_create_procedure,
|
||||
dfw_modify_procedure,
|
||||
dfw_delete_procedure,
|
||||
@ -517,7 +516,7 @@ enum dfw_t {
|
||||
dfw_change_repl_state,
|
||||
|
||||
// deferred works argument types
|
||||
dfw_arg_index_name, // index name for dfw_delete_expression_index, mandatory
|
||||
dfw_arg_index_name, // index name for dfw_delete_index, mandatory
|
||||
dfw_arg_partner_rel_id, // partner relation id for dfw_delete_index if index is FK, optional
|
||||
dfw_arg_proc_name, // procedure name for dfw_delete_prm, mandatory
|
||||
dfw_arg_force_computed, // we need to drop dependencies from a field that WAS computed
|
||||
|
@ -86,7 +86,7 @@ TYPE("TRIGGER", obj_trigger, nam_obj_type)
|
||||
TYPE("COMPUTED_FIELD", obj_computed, nam_obj_type)
|
||||
TYPE("VALIDATION", obj_validation, nam_obj_type)
|
||||
TYPE("PROCEDURE", obj_procedure, nam_obj_type)
|
||||
TYPE("EXPRESSION_INDEX", obj_expression_index, nam_obj_type)
|
||||
TYPE("INDEX_EXPRESSION", obj_index_expression, nam_obj_type)
|
||||
TYPE("EXCEPTION", obj_exception, nam_obj_type)
|
||||
TYPE("USER", obj_user, nam_obj_type)
|
||||
TYPE("FIELD", obj_field, nam_obj_type)
|
||||
@ -100,6 +100,7 @@ TYPE("BLOB_FILTER", obj_blob_filter, nam_obj_type)
|
||||
TYPE("COLLATION", obj_collation, nam_obj_type)
|
||||
TYPE("PACKAGE", obj_package_header, nam_obj_type)
|
||||
TYPE("PACKAGE BODY", obj_package_body, nam_obj_type)
|
||||
TYPE("INDEX_CONDITION", obj_index_condition, nam_obj_type)
|
||||
|
||||
TYPE("LIMBO", 1, nam_trans_state)
|
||||
TYPE("COMMITTED", 2, nam_trans_state)
|
||||
|
@ -2088,12 +2088,7 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
// hvlad: lets add index name to the DFW item even if we add it again later within
|
||||
// additional argument. This is needed to make DFW work items different for different
|
||||
// indexes dropped at the same transaction and to not merge them at DFW_merge_work.
|
||||
if (EVL_field(0, rpb->rpb_record, f_idx_exp_blr, &desc2)) {
|
||||
work = DFW_post_work(transaction, dfw_delete_expression_index, &idx_name, r2->rel_id);
|
||||
}
|
||||
else {
|
||||
work = DFW_post_work(transaction, dfw_delete_index, &idx_name, r2->rel_id);
|
||||
}
|
||||
work = DFW_post_work(transaction, dfw_delete_index, &idx_name, r2->rel_id);
|
||||
|
||||
// add index id and name (the latter is required to delete dependencies correctly)
|
||||
DFW_post_work_arg(transaction, work, &idx_name, id, dfw_arg_index_name);
|
||||
|
Loading…
Reference in New Issue
Block a user