📄 exe.c
字号:
old_env = (JMP_BUF*) tdbb->tdbb_setjmp;tdbb->tdbb_setjmp = (UCHAR*) env;if (SETJMP (env)) { tdbb->tdbb_setjmp = (UCHAR*) old_env; if (vector != *triggers) release_triggers (tdbb, vector); if (!trigger) LONGJMP (old_env, -1); else return trigger; }for (ptr = (REQ*) vector->vec_object, end = ptr + vector->vec_count; ptr < end; ptr++) { trigger = EXE_find_request (tdbb, *ptr, FALSE); trigger->req_rpb [0].rpb_record = old_rec; trigger->req_rpb [1].rpb_record = new_rec; trigger->req_timestamp = tdbb->tdbb_request->req_timestamp; EXE_start (tdbb, trigger, transaction); trigger->req_attachment = NULL; trigger->req_flags &= ~req_in_use; trigger->req_timestamp = 0; if (trigger->req_operation == req_unwind) { result = trigger; break; } }tdbb->tdbb_setjmp = (UCHAR*) old_env;if (vector != *triggers) release_triggers (tdbb, vector);return result;}#endif#ifndef GATEWAY#ifdef PC_ENGINEstatic NOD find ( TDBB tdbb, register NOD node){/************************************** * * f i n d * ************************************** * * Functional description * Find the given key value in a stream. * Assume that the stream is open. * **************************************/register REQ request;RSB rsb;USHORT operator, direction;SET_TDBB (tdbb);request = tdbb->tdbb_request;BLKCHK (node, type_nod);if (request->req_operation == req_evaluate) { rsb = *((RSB*) node->nod_arg [e_find_rsb]); operator = (USHORT) MOV_get_long (EVL_expr (tdbb, node->nod_arg[e_find_operator]), 0); if (operator != blr_eql && operator != blr_leq && operator != blr_lss && operator != blr_geq && operator != blr_gtr) ERR_post (gds__invalid_operator, 0); direction = (USHORT) MOV_get_long(EVL_expr(tdbb, node->nod_arg[e_find_direction]), 0); if (direction != blr_backward && direction != blr_forward && direction != blr_backward_starting && direction != blr_forward_starting) ERR_post (gds__invalid_direction, 0); /* try to find the record; the position is defined to be on a crack regardless of whether we are at BOF or EOF; also be sure to perpetuate the forced crack (bug #7024) */ if (!(RSE_find_record (tdbb, rsb, operator, direction, node->nod_arg [e_find_args]))) if (EXE_crack (tdbb, rsb, irsb_bof | irsb_eof | irsb_crack)) if (EXE_crack (tdbb, rsb, irsb_forced_crack)) EXE_mark_crack (tdbb, rsb, irsb_crack | irsb_forced_crack); else if (EXE_crack (tdbb, rsb, irsb_bof)) EXE_mark_crack (tdbb, rsb, irsb_bof); else if (EXE_crack (tdbb, rsb, irsb_eof)) EXE_mark_crack (tdbb, rsb, irsb_eof); else EXE_mark_crack (tdbb, rsb, irsb_crack); request->req_operation = req_return; }return node->nod_parent;}#endif#endif#ifndef GATEWAY#ifdef PC_ENGINEstatic NOD find_dbkey ( TDBB tdbb, register NOD node){/************************************** * * f i n d _ d b k e y * ************************************** * * Functional description * Find the given dbkey in a navigational stream, * resetting the position of the stream to that record. * **************************************/register REQ request;RSB rsb;SET_TDBB (tdbb);request = tdbb->tdbb_request;BLKCHK (node, type_nod);if (request->req_operation == req_evaluate) { rsb = *((RSB*) node->nod_arg [e_find_dbkey_rsb]); if (!(RSE_find_dbkey (tdbb, rsb, node->nod_arg [e_find_dbkey_dbkey], node->nod_arg [e_find_dbkey_version]))) EXE_mark_crack (tdbb, rsb, irsb_crack); request->req_operation = req_return; }return node->nod_parent;}#endif#endif#ifdef PC_ENGINEstatic LCK implicit_record_lock ( TRA transaction, RPB *rpb){/************************************** * * i m p l i c i t _ r e c o r d _ l o c k * ************************************** * * Functional description * An update to a record is being attempted and * record locking has been initiated. Take out * an implicit record lock to prevent updating * a record that someone has explicitly locked. * **************************************/LCK lock, record_locking;REL relation;TDBB tdbb;tdbb = GET_THREAD_DATA;DEV_BLKCHK (transaction, type_tra);relation = rpb->rpb_relation;record_locking = relation->rel_record_locking;/* occasionally we should check whether we really still need to do record locking; this is defined as RECORD_LOCK_CHECK_INTERVAL-- if we can get a PR on the record locking lock there is no need to do implicit locking anymore */if ((record_locking->lck_physical == LCK_none) && !(relation->rel_lock_total % RECORD_LOCK_CHECK_INTERVAL) && LCK_lock_non_blocking (tdbb, record_locking, LCK_PR, FALSE)) return NULL;if (!(lock = RLCK_lock_record_implicit (transaction, rpb, LCK_SW, NULL_PTR, NULL_PTR))) ERR_post (gds__record_lock, 0);return lock;}#endifstatic NOD looper ( TDBB tdbb, REQ request, NOD in_node){/************************************** * * l o o p e r * ************************************** * * Functional description * Cycle thru request execution tree. Return next node for * execution on stall or request complete. * **************************************/DBB dbb;STA impure;SSHORT error_pending;SLONG save_point_number;SSHORT which_erase_trig = 0, which_sto_trig = 0, which_mod_trig = 0;REQ old_request;VOLATILE NOD node, top_node = NULL, prev_node;TRA transaction;JMP_BUF env, *old_env;struct plb *old_pool;#if defined(DEBUG_GDS_ALLOC) && FALSEint node_type;#endif/* If an error happens during the backout of a savepoint, then the transaction must be marked 'dead' because that is the only way to clean up after a failed backout. The easiest way to do this is to kill the application by calling bugcheck. To facilitate catching errors during VIO_verb_cleanup, the following define is used. */#define VERB_CLEANUP \ { \ JMP_BUF env2, *old_env2; \ old_env2 = (JMP_BUF*) tdbb->tdbb_setjmp; \ tdbb->tdbb_setjmp = (UCHAR*) env2; \ if (!SETJMP (env2)) \ { \ VIO_verb_cleanup (tdbb, transaction); \ tdbb->tdbb_setjmp = (UCHAR*) old_env2; /* restore old env */\ } \ else \ { \ /* Cause bugcheck to longjmp out of looper. */ \ tdbb->tdbb_setjmp = (UCHAR*) old_env; \ if (dbb->dbb_flags & DBB_bugcheck) \ LONGJMP (old_env, (int) tdbb->tdbb_status_vector [1]); \ else \ BUGCHECK (290); /* msg 290 error during savepoint backout */\ } \ }#ifdef WINDOWS_ONLY// try and avoid a stack overflowif (_SP < 0x1000) ERR_post (gds__req_depth_exceeded, gds_arg_string, "looper stack about to overflow", 0 );#endifif (!(transaction = request->req_transaction)) ERR_post (gds__req_no_trans, 0);SET_TDBB (tdbb);dbb = tdbb->tdbb_database;BLKCHK (in_node, type_nod);/* Save the old pool and request to restore on exit */old_pool = tdbb->tdbb_default;tdbb->tdbb_default = request->req_pool;old_request = tdbb->tdbb_request;tdbb->tdbb_request = request;tdbb->tdbb_transaction = transaction;save_point_number = (transaction->tra_save_point) ? transaction->tra_save_point->sav_number : 0;node = in_node;/* Catch errors so we can unwind cleanly */old_env = (JMP_BUF*) tdbb->tdbb_setjmp;tdbb->tdbb_setjmp = (UCHAR*) env;error_pending = FALSE;if (SETJMP (env)) { /* If the database is already bug-checked, then get out. */ if (dbb->dbb_flags & DBB_bugcheck) LONGJMP (old_env, (int) tdbb->tdbb_status_vector [1]);#ifdef GATEWAY /* Unwind request from connected DBMS's point of view. Set up special error handling in case something happens there. */ if (!SETJMP (env)) FRGN_unwind (request); /* Continue with normal JRD unwind */#endif /* Since an error happened, the current savepoint needs to be undone. */ if (transaction != dbb->dbb_sys_trans) { ++transaction->tra_save_point->sav_verb_count; VERB_CLEANUP; } error_pending = TRUE; tdbb->tdbb_setjmp = (UCHAR*) old_env; request->req_operation = req_unwind; request->req_label = 0; }/* Execute stuff until we drop */while (node && !(request->req_flags & req_stall)) {#ifdef MULTI_THREAD if (request->req_operation == req_evaluate && (--tdbb->tdbb_quantum < 0) && !tdbb->tdbb_inhibit) (void) JRD_reschedule (tdbb, 0, TRUE);#endif#if defined(DEBUG_GDS_ALLOC) && FALSE node_type = node->nod_type;#endif switch (node->nod_type) { case nod_asn_list: if (request->req_operation == req_evaluate) { VOLATILE NOD *ptr, *end; for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end; ptr++) EXE_assignment (tdbb, *ptr); request->req_operation = req_return; } node = node->nod_parent; break; case nod_assignment: if (request->req_operation == req_evaluate) EXE_assignment (tdbb, node); node = node->nod_parent; break; case nod_dcl_variable: { VLU variable; variable = (VLU) ((SCHAR*) request + node->nod_impure); variable->vlu_desc = *(DSC*) (node->nod_arg + e_dcl_desc); variable->vlu_desc.dsc_flags = 0; variable->vlu_desc.dsc_address = (UCHAR*) &variable->vlu_misc; if (variable->vlu_desc.dsc_dtype <= dtype_varying && !variable->vlu_string) { variable->vlu_string = (STR) ALLOCDV (type_str, variable->vlu_desc.dsc_length); variable->vlu_string->str_length = variable->vlu_desc.dsc_length; variable->vlu_desc.dsc_address = variable->vlu_string->str_data; } request->req_operation = req_return; node = node->nod_parent; } break; case nod_erase: if ((request->req_operation == req_return) && (node->nod_arg[e_erase_sub_erase])) { if (!top_node) { top_node = node; which_erase_trig = PRE_TRIG; } prev_node = node; node = erase (tdbb, node, which_erase_trig); if (which_erase_trig == PRE_TRIG) { node = prev_node->nod_arg[e_erase_sub_erase]; node->nod_parent = prev_node; } if (top_node == prev_node && which_erase_trig == POST_TRIG) { top_node = NULL; which_erase_trig = ALL_TRIGS; } else request->req_operation = req_evaluate; } else { prev_node = node; node = erase (tdbb, node, ALL_TRIGS); if (!(prev_node->nod_arg[e_erase_sub_erase]) && which_erase_trig == PRE_TRIG) which_erase_trig = POST_TRIG; } break; case nod_exec_proc: if (request->req_operation == req_unwind) { node = node->nod_parent; break; } execute_procedure (tdbb, node); node = node->nod_parent; request->req_operation = req_return; break; case nod_for: switch (request->req_operation) { case req_evaluate: RSE_open (tdbb, (RSB) node->nod_arg [e_for_rsb]); case req_return: if (node->nod_arg [e_for_stall]) { node = node->nod_arg [e_for_stall]; break; } case req_sync: if (RSE_get_record (tdbb, (RSB) node->nod_arg [e_for_rsb], #ifdef SCROLLABLE_CURSORSRSE_get_next))#elseRSE_get_forward))#endif { node = node->nod_arg [e_for_statement]; request->req_operation = req_evaluate; break; } request->req_operation = req_return; default: RSE_close (tdbb, (RSB) node->nod_arg [e_for_rsb]); node = node->nod_parent; } break; case nod_abort: switch (request->req_operation) { case req_evaluate: set_error (tdbb, node->nod_arg [0]); default: node = node->nod_parent; } break; case nod_start_savepoint: switch (request->req_operation) { case req_evaluate: /* Start a save point */ if (transaction != dbb->dbb_sys_trans) VIO_start_save_point (tdbb, transaction); default: node = node->nod_parent; request->req_operation = req_return; } break; case nod_end_savepoint: switch (request->req_operation) { case req_evaluate: case req_unwind: /* If any requested modify/delete/insert ops have completed, forget them */ if (transaction != dbb->dbb_sys_trans) { /* If an error is still pending when the savepoint is supposed to end, then the application didn't handle the error and the savepoint should be undone. */ if (error_pending) ++transaction->tra_save_point->sav_verb_count; VERB_CLEANUP; } default: node = node->nod_parent; request->req_operation = req_return; } break; case nod_handler: switch (request->req_operation) { case req_evaluate: node = node->nod_arg [0]; break; case req_unwind: if (!request->req_label) request->req_operation = req_return; default: node = node->nod_parent; } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -