/* * PROGRAM: JRD Access Method * MODULE: exe.h * DESCRIPTION: Execution block definitions * * 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.28: Added rse_skip to class RecordSelExpr to support LIMIT. * 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced * exception handling in SPs/triggers, * implemented ROWS_AFFECTED system variable * 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks * 2002.10.29 Nickolay Samofatov: Added support for savepoints * Adriano dos Santos Fernandes */ #ifndef JRD_EXE_H #define JRD_EXE_H #include "../jrd/blb.h" #include "../jrd/Relation.h" #include "../common/classes/array.h" #include "../common/classes/MetaName.h" #include "../common/classes/NestConst.h" #include "gen/iberror.h" #include "../common/dsc.h" #include "../jrd/rse.h" #include "../jrd/err_proto.h" #include "../jrd/scl.h" #include "../jrd/sbm.h" #include "../jrd/sort.h" #include "../jrd/DebugInterface.h" #include "../jrd/BlrReader.h" #include "../dsql/Nodes.h" #include "../dsql/Visitors.h" // This macro enables DSQL tracing code //#define CMP_DEBUG #ifdef CMP_DEBUG DEFINE_TRACE_ROUTINE(cmp_trace); #define CMP_TRACE(args) cmp_trace args #else #define CMP_TRACE(args) // nothing #endif class VaryingString; struct dsc; namespace Jrd { class jrd_rel; class Sort; struct sort_key_def; template class vec; class jrd_prc; class Collation; struct index_desc; struct IndexDescAlloc; class Format; class Cursor; class DeclareVariableNode; class MessageNode; class PlanNode; class RecordSource; // Types of nulls placement for each column in sort order const int rse_nulls_default = 0; const int rse_nulls_first = 1; const int rse_nulls_last = 2; // Aggregate Sort Block (for DISTINCT aggregates) class AggregateSort : protected Firebird::PermanentStorage { public: explicit AggregateSort(Firebird::MemoryPool& p) : PermanentStorage(p), length(0), intl(false), impure(0), keyItems(p) { desc.clear(); } dsc desc; USHORT length; bool intl; ULONG impure; Firebird::HalfStaticArray keyItems; }; // Inversion (i.e. nod_index) impure area struct impure_inversion { RecordBitmap* inv_bitmap; }; // AggregateSort impure area struct impure_agg_sort { Sort* iasb_sort; }; // index (in CompoundStmtNode) for external procedure blr const int e_extproc_input_message = 0; const int e_extproc_output_message = 1; const int e_extproc_input_message2 = 2; const int e_extproc_output_message2 = 3; const int e_extproc_input_assign = 4; const int e_extproc_output_assign = 5; // Request resources struct Resource { enum rsc_s { rsc_relation, rsc_procedure, rsc_index, rsc_collation, rsc_function }; rsc_s rsc_type; USHORT rsc_id; // Id of the resource jrd_rel* rsc_rel; // Relation block jrd_prc* rsc_prc; // Procedure block Collation* rsc_coll; // Collation block Function* rsc_fun; // Function block static bool greaterThan(const Resource& i1, const Resource& i2) { // A few places of the engine depend on fact that rsc_type // is the first field in ResourceList ordering if (i1.rsc_type != i2.rsc_type) return i1.rsc_type > i2.rsc_type; if (i1.rsc_type == rsc_index) { // Sort by relation ID for now if (i1.rsc_rel->rel_id != i2.rsc_rel->rel_id) return i1.rsc_rel->rel_id > i2.rsc_rel->rel_id; } return i1.rsc_id > i2.rsc_id; } Resource(rsc_s type, USHORT id, jrd_rel* rel, jrd_prc* prc, Collation* coll) : rsc_type(type), rsc_id(id), rsc_rel(rel), rsc_prc(prc), rsc_coll(coll) { } }; typedef Firebird::SortedArray, Resource, Firebird::DefaultKeyValue, Resource> ResourceList; // Access items // In case we start to use MetaName with required pool parameter, // access item to be reworked! // This struct seems better located in scl.h. struct AccessItem { Firebird::MetaName acc_security_name; SLONG acc_view_id; Firebird::MetaName acc_name, acc_r_name; SLONG acc_type; SecurityClass::flags_t acc_mask; static bool greaterThan(const AccessItem& i1, const AccessItem& i2) { int v; /* CVC: Disabled this horrible hack. // Relations and procedures should be sorted before // columns, hence such a tricky inverted condition if ((v = -strcmp(i1.acc_type, i2.acc_type)) != 0) return v > 0; */ if (i1.acc_type != i2.acc_type) return i1.acc_type > i2.acc_type; if ((v = i1.acc_security_name.compare(i2.acc_security_name)) != 0) return v > 0; if (i1.acc_view_id != i2.acc_view_id) return i1.acc_view_id > i2.acc_view_id; if (i1.acc_mask != i2.acc_mask) return i1.acc_mask > i2.acc_mask; if ((v = i1.acc_name.compare(i2.acc_name)) != 0) return v > 0; if ((v = i1.acc_r_name.compare(i2.acc_r_name)) != 0) return v > 0; return false; // Equal } AccessItem(const Firebird::MetaName& security_name, SLONG view_id, const Firebird::MetaName& name, SLONG type, SecurityClass::flags_t mask, const Firebird::MetaName& relName) : acc_security_name(security_name), acc_view_id(view_id), acc_name(name), acc_r_name(relName), acc_type(type), acc_mask(mask) {} }; typedef Firebird::SortedArray, AccessItem, Firebird::DefaultKeyValue, AccessItem> AccessItemList; // Triggers and procedures the request accesses struct ExternalAccess { enum exa_act { exa_procedure, exa_function, exa_insert, exa_update, exa_delete }; exa_act exa_action; USHORT exa_prc_id; USHORT exa_fun_id; USHORT exa_rel_id; USHORT exa_view_id; // Procedure ExternalAccess(exa_act action, USHORT id) : exa_action(action), exa_prc_id(action == exa_procedure ? id : 0), exa_fun_id(action == exa_function ? id : 0), exa_rel_id(0), exa_view_id(0) { } // Trigger ExternalAccess(exa_act action, USHORT rel_id, USHORT view_id) : exa_action(action), exa_prc_id(0), exa_fun_id(0), exa_rel_id(rel_id), exa_view_id(view_id) { } static bool greaterThan(const ExternalAccess& i1, const ExternalAccess& i2) { if (i1.exa_action != i2.exa_action) return i1.exa_action > i2.exa_action; if (i1.exa_prc_id != i2.exa_prc_id) return i1.exa_prc_id > i2.exa_prc_id; if (i1.exa_fun_id != i2.exa_fun_id) return i1.exa_fun_id > i2.exa_fun_id; if (i1.exa_rel_id != i2.exa_rel_id) return i1.exa_rel_id > i2.exa_rel_id; if (i1.exa_view_id != i2.exa_view_id) return i1.exa_view_id > i2.exa_view_id; return false; // Equal } }; typedef Firebird::SortedArray, ExternalAccess, Firebird::DefaultKeyValue, ExternalAccess> ExternalAccessList; // The three structs below are used for domains DEFAULT and constraints in PSQL struct Item { enum Type { TYPE_VARIABLE, TYPE_PARAMETER, TYPE_CAST }; Item(Type aType, UCHAR aSubType, USHORT aIndex) : type(aType), subType(aSubType), index(aIndex) { } Item(Type aType, USHORT aIndex = 0) : type(aType), subType(0), index(aIndex) { } Type type; UCHAR subType; USHORT index; bool operator >(const Item& x) const { if (type == x.type) { if (subType == x.subType) return index > x.index; return subType > x.subType; } return type > x.type; } }; struct FieldInfo { FieldInfo() : nullable(false), defaultValue(NULL), validationExpr(NULL), validationStmt(NULL) {} bool nullable; NestConst defaultValue; NestConst validationExpr; NestConst validationStmt; }; struct ItemInfo { ItemInfo(MemoryPool& p, const ItemInfo& o) : name(p, o.name), field(p, o.field), nullable(o.nullable), explicitCollation(o.explicitCollation), fullDomain(o.fullDomain) { } explicit ItemInfo(MemoryPool& p) : name(p), field(p), nullable(true), explicitCollation(false), fullDomain(false) { } ItemInfo() : name(), field(), nullable(true), explicitCollation(false), fullDomain(false) { } bool isSpecial() const { return !nullable || fullDomain; } Firebird::MetaName name; Firebird::MetaNamePair field; bool nullable; bool explicitCollation; bool fullDomain; }; struct RseOrExprNode { RseOrExprNode(ExprNode* aExprNode) : exprNode(aExprNode), rseNode(NULL) { } RseOrExprNode(RseNode* aRseNode) : exprNode(NULL), rseNode(aRseNode) { } ExprNode* exprNode; RseNode* rseNode; }; typedef Firebird::GenericMap > > MapFieldInfo; typedef Firebird::GenericMap > > MapItemInfo; // Compile scratch block class CompilerScratch : public pool_alloc { CompilerScratch(MemoryPool& p, size_t len, const Firebird::MetaName& domain_validation) : /*csb_node(0), csb_variables(0), csb_dependencies(0), csb_count(0), csb_n_stream(0), csb_msg_number(0), csb_impure(0), csb_g_flags(0),*/ #ifdef CMP_DEBUG csb_dump(p), #endif csb_external(p), csb_access(p), csb_resources(p), csb_dependencies(p), csb_fors(p), csb_invariants(p), csb_current_nodes(p), csb_pool(p), csb_dbg_info(p), csb_map_field_info(p), csb_map_item_info(p), csb_message_pad(p), csb_domain_validation(domain_validation), csb_rpt(p, len) {} public: struct Dependency { explicit Dependency(int aObjType) { memset(this, 0, sizeof(*this)); objType = aObjType; } int objType; union { jrd_rel* relation; const Function* function; const jrd_prc* procedure; const Firebird::MetaName* name; SLONG number; }; const Firebird::MetaName* subName; SLONG subNumber; }; static CompilerScratch* newCsb(MemoryPool& p, size_t len, const Firebird::MetaName& domain_validation = Firebird::MetaName()) { return FB_NEW(p) CompilerScratch(p, len, domain_validation); } USHORT nextStream(bool check = true) { if (csb_n_stream >= MAX_STREAMS && check) { ERR_post(Firebird::Arg::Gds(isc_too_many_contexts)); } return csb_n_stream++; } #ifdef CMP_DEBUG void dump(const char* format, ...) { va_list params; va_start(params, format); Firebird::string s; s.vprintf(format, params); va_end(params); csb_dump += s; } Firebird::string csb_dump; #endif BlrReader csb_blr_reader; DmlNode* csb_node; ExternalAccessList csb_external; // Access to outside procedures/triggers to be checked AccessItemList csb_access; // Access items to be checked vec* csb_variables; // Vector of variables, if any ResourceList csb_resources; // Resources (relations and indexes) Firebird::Array csb_dependencies; // objects that this statement depends upon Firebird::Array csb_fors; // record sources Firebird::Array csb_invariants; // stack of pointer to nodes invariant offsets Firebird::Array csb_current_nodes; // RseNode's and other invariant // candidates within whose scope we are USHORT csb_n_stream; // Next available stream USHORT csb_msg_number; // Highest used message number ULONG csb_impure; // Next offset into impure area USHORT csb_g_flags; MemoryPool& csb_pool; // Memory pool to be used by csb Firebird::DbgInfo csb_dbg_info; // Debug information MapFieldInfo csb_map_field_info; // Map field name to field info MapItemInfo csb_map_item_info; // Map item to item info // Map of message number to field number to pad for external routines. Firebird::GenericMap > > csb_message_pad; Firebird::MetaName csb_domain_validation; // Parsing domain constraint in PSQL // used in cmp.cpp/pass1 jrd_rel* csb_view; USHORT csb_view_stream; bool csb_validate_expr; USHORT csb_remap_variable; struct csb_repeat { // We must zero-initialize this one csb_repeat() : csb_stream(0), csb_view_stream(0), csb_flags(0), csb_indices(0), csb_relation(0), csb_alias(0), csb_procedure(0), csb_view(0), csb_idx(0), csb_message(0), csb_format(0), csb_internal_format(0), csb_fields(0), csb_cardinality(0.0), // TMN: Non-natural cardinality?! csb_plan(0), csb_map(0), csb_rsb_ptr(0) {} UCHAR csb_stream; // Map user context to internal stream UCHAR csb_view_stream; // stream number for view relation, below USHORT csb_flags; USHORT csb_indices; // Number of indices jrd_rel* csb_relation; Firebird::string* csb_alias; // SQL alias name for this instance of relation jrd_prc* csb_procedure; jrd_rel* csb_view; // parent view IndexDescAlloc* csb_idx; // Packed description of indices MessageNode* csb_message; // Msg for send/receive const Format* csb_format; // Default Format for stream Format* csb_internal_format; // Statement internal format UInt32Bitmap* csb_fields; // Fields referenced double csb_cardinality; // Cardinality of relation PlanNode* csb_plan; // user-specified plan for this relation UCHAR* csb_map; // Stream map for views RecordSource** csb_rsb_ptr; // point to rsb for nod_stream }; typedef csb_repeat* rpt_itr; typedef const csb_repeat* rpt_const_itr; Firebird::HalfStaticArray csb_rpt; }; const int csb_internal = 1; // "csb_g_flag" switch const int csb_get_dependencies = 2; // we are retrieving dependencies const int csb_ignore_perm = 4; // ignore permissions checks const int csb_blr_version4 = 8; // the BLR is of version 4 const int csb_pre_trigger = 16; // this is a BEFORE trigger const int csb_post_trigger = 32; // this is an AFTER trigger const int csb_validation = 64; // we're in a validation expression (RDB hack) const int csb_reuse_context = 128; // allow context reusage const int csb_active = 1; // stream is active const int csb_used = 2; // context has already been defined (BLR parsing only) const int csb_view_update = 4; // view update w/wo trigger is in progress const int csb_trigger = 8; // NEW or OLD context in trigger const int csb_no_dbkey = 16; // stream doesn't have a dbkey const int csb_store = 32; // we are processing a store statement const int csb_modify = 64; // we are processing a modify const int csb_sub_stream = 128; // a sub-stream of the RSE being processed const int csb_erase = 256; // we are processing an erase const int csb_unmatched = 512; // stream has conjuncts unmatched by any index const int csb_update = 1024; // erase or modify for relation class StatusXcp { ISC_STATUS_ARRAY status; public: StatusXcp(); void clear(); void init(const ISC_STATUS*); void copyTo(ISC_STATUS*) const; bool success() const; SLONG as_gdscode() const; SLONG as_sqlcode() const; void as_sqlstate(char*) const; }; // must correspond to the size of RDB$EXCEPTIONS.RDB$MESSAGE // minus size of vary::vary_length (USHORT) since RDB$MESSAGE // declared as varchar const int XCP_MESSAGE_LENGTH = 1023 - sizeof(USHORT); } // namespace Jrd #endif // JRD_EXE_H