📄 par.c
字号:
NOD plan, access_type, relation_node, *arg;USHORT node_type, count;SET_TDBB (tdbb);node_type = (USHORT) BLR_BYTE; /* a join type indicates a cross of two or more streams */if (node_type == blr_join || node_type == blr_merge) { count = (USHORT) BLR_BYTE; plan = PAR_make_node (tdbb, count); plan->nod_type = (NOD_T) (USHORT) blr_table [node_type]; for (arg = plan->nod_arg; count--;) *arg++ = par_plan (tdbb, csb); return plan; }/* we have hit a stream; parse the context number and access type */if (node_type == blr_retrieve) { TEXT name [32], *p; SSHORT stream, n; SLONG index_id, relation_id; REL relation; plan = PAR_make_node (tdbb, e_retrieve_length); plan->nod_type = (NOD_T) (USHORT) blr_table [node_type]; /* parse the relation name and context--the relation itself is redundant except in the case of a view, in which case the base relation (and alias) must be specified */ n = BLR_BYTE; if (n != blr_relation && n != blr_relation2 && n != blr_rid && n != blr_rid2) syntax_error (*csb, elements [RELATION]); /* don't have par_relation() parse the context, because this would add a new context; while this is a reference to an existing context */ relation_node = par_relation (tdbb, csb, n, FALSE); plan->nod_arg [e_retrieve_relation] = relation_node; relation = (REL) relation_node->nod_arg [e_rel_relation]; n = BLR_BYTE; if (n >= (*csb)->csb_count) error (*csb, gds__ctxnotdef, 0); stream = (*csb)->csb_rpt [n].csb_stream; relation_node->nod_arg [e_rel_stream] = (NOD) (SLONG) stream; relation_node->nod_arg [e_rel_context] = (NOD) (SLONG) n; /* Access plan types (sequential is default) */ node_type = (USHORT) BLR_BYTE; if (node_type == blr_navigational) { SSHORT idx_status; access_type = plan->nod_arg [e_retrieve_access_type] = PAR_make_node (tdbb, 3); access_type->nod_type = nod_navigational; /* pick up the index name and look up the appropriate ids */ par_name (csb, name); /* CVC: We can't do that. Index names are identifiers. for (p = name; *p; *p++) *p = UPPER (*p); */ index_id = MET_lookup_index_name (tdbb, name, &relation_id, &idx_status); if (idx_status == MET_object_unknown || idx_status == MET_object_inactive) if (tdbb->tdbb_attachment->att_flags & ATT_gbak_attachment) warning (*csb, gds__indexname, gds_arg_string, ERR_cstring (name), gds_arg_string, relation->rel_name, 0); else error (*csb, gds__indexname, gds_arg_string, ERR_cstring (name), gds_arg_string, relation->rel_name, 0); /* save both the relation id and the index id, since the relation could be a base relation of a view; save the index name also, for convenience */ access_type->nod_arg [0] = (NOD) relation_id; access_type->nod_arg [1] = (NOD) index_id; access_type->nod_arg [2] = (NOD) ALL_cstring (name); } else if (node_type == blr_indices) { SSHORT idx_status; count = (USHORT) BLR_BYTE; access_type = plan->nod_arg [e_retrieve_access_type] = PAR_make_node (tdbb, count * 3); access_type->nod_type = nod_indices; /* pick up the index names and look up the appropriate ids */ for (arg = access_type->nod_arg; count--;) { par_name (csb, name); for (p = name; *p; *p++) *p = UPPER (*p); index_id = MET_lookup_index_name (tdbb, name, &relation_id, &idx_status); if (idx_status == MET_object_unknown || idx_status == MET_object_inactive) if (tdbb->tdbb_attachment->att_flags & ATT_gbak_attachment) warning (*csb, gds__indexname, gds_arg_string, ERR_cstring (name), gds_arg_string, relation->rel_name, 0); else error (*csb, gds__indexname, gds_arg_string, ERR_cstring (name), gds_arg_string, relation->rel_name, 0); /* save both the relation id and the index id, since the relation could be a base relation of a view; save the index name also, for convenience */ *arg++ = (NOD) relation_id; *arg++ = (NOD) index_id; *arg++ = (NOD) ALL_cstring (name); } } else if (node_type != blr_sequential) syntax_error (*csb, "access type"); return plan; }syntax_error (*csb, "plan item");return ((NOD) 0); /* Added to remove compiler warning */}static NOD par_procedure ( TDBB tdbb, CSB *csb, SSHORT _operator){/************************************** * * p a r _ p r o c e d u r e * ************************************** * * Functional description * Parse an procedural view reference. * **************************************/NOD node;PRC procedure;USHORT stream;SET_TDBB (tdbb);{TEXT name [32];SSHORT pid;if (_operator == blr_procedure) { par_name (csb, name); procedure = MET_lookup_procedure (tdbb, name); }else { pid = BLR_WORD; if (!(procedure = MET_lookup_procedure_id (tdbb, pid, FALSE, 0))) sprintf (name, "id %d", pid); }if (!procedure) error (*csb, gds__prcnotdef, gds_arg_string, ERR_cstring (name), 0);}node = PAR_make_node (tdbb, e_prc_length);node->nod_type = nod_procedure;node->nod_count = count_table [blr_procedure];node->nod_arg [e_prc_procedure] = (NOD) procedure;stream = par_context (csb, NULL_PTR);node->nod_arg [e_prc_stream] = (NOD) (SLONG) stream;(*csb)->csb_rpt [stream].csb_procedure = procedure;par_procedure_parms (tdbb, csb, procedure, &node->nod_arg [e_prc_in_msg], &node->nod_arg [e_prc_inputs], TRUE);if ((*csb)->csb_g_flags & csb_get_dependencies) par_dependency (tdbb, csb, stream, (SSHORT) -1, NULL_PTR);return node;}static void par_procedure_parms ( TDBB tdbb, CSB *csb, PRC procedure, NOD *message_ptr, NOD *parameter_ptr, USHORT input_flag){/************************************** * * p a r _ p r o c e d u r e _ p a r m s * ************************************** * * Functional description * Parse some procedure parameters. * **************************************/NOD message, list, *ptr, asgn, prm, prm_f;FMT format;USHORT count, n, i, asgn_arg1, asgn_arg2;struct csb_repeat *tail;BOOLEAN mismatch = FALSE;SET_TDBB (tdbb);count = BLR_WORD ;/** Check to see if the parameter count matches **/if (count != (input_flag ? procedure->prc_inputs : procedure->prc_outputs)) { /** They don't match...Hmmm...Its OK if we were dropping the procedure **/ if (!(tdbb->tdbb_flags & TDBB_prc_being_dropped)) error (*csb, gds__prcmismat, gds_arg_string, ERR_cstring (procedure->prc_name->str_data), 0); else mismatch = TRUE; }if (count) { /** We have a few parameters. Get on with creating the message block **/ if ((n = ++(*csb)->csb_msg_number) < 2) (*csb)->csb_msg_number = n = 2; tail = CMP_csb_element (csb, n); tail->csb_message = message = PAR_make_node (tdbb, e_msg_length); message->nod_type = nod_message; message->nod_count = count_table [blr_message]; *message_ptr = message; message->nod_count = 0; message->nod_arg [e_msg_number] = (NOD) (SLONG) n; format = input_flag ? procedure->prc_input_fmt : procedure->prc_output_fmt; message->nod_arg [e_msg_format] = (NOD) format; if (!mismatch) n = format->fmt_count / 2; else /* There was a parameter mismatch hence can't depend upon the format's fmt_count. Use count instead. */ n = count; list = *parameter_ptr = PAR_make_node (tdbb, n); list->nod_type = nod_list; list->nod_count = n; ptr = list->nod_arg; if (input_flag) { asgn_arg1 = e_asgn_from; asgn_arg2 = e_asgn_to; } else { asgn_arg1 = e_asgn_to; asgn_arg2 = e_asgn_from; } for (i = 0; count; count--) { asgn = PAR_make_node (tdbb, e_asgn_length); *ptr++ = asgn; asgn->nod_type = nod_assignment; asgn->nod_count = count_table [blr_assignment]; asgn->nod_arg [asgn_arg1] = parse (tdbb, csb, VALUE); prm = asgn->nod_arg [asgn_arg2] = PAR_make_node (tdbb, e_arg_length); prm->nod_type = nod_argument; prm->nod_count = 1; prm->nod_arg [e_arg_message] = message; prm->nod_arg [e_arg_number] = (NOD) i++; prm_f = prm->nod_arg [e_arg_flag] = PAR_make_node (tdbb, e_arg_length); prm_f->nod_type = nod_argument; prm_f->nod_count = 0; prm_f->nod_arg [e_arg_message] = message; prm_f->nod_arg [e_arg_number] = (NOD) i++; } }else if ((input_flag ? procedure->prc_inputs : procedure->prc_outputs) && !mismatch) error (*csb, gds__prcmismat, gds_arg_string, ERR_cstring (procedure->prc_name->str_data), 0);}static NOD par_relation ( TDBB tdbb, CSB *csb, SSHORT _operator, BOOLEAN parse_context){/************************************** * * p a r _ r e l a t i o n * ************************************** * * Functional description * Parse a relation reference. * **************************************/#ifdef GATEWAYDBB dbb;#endifNOD node;REL relation;TEXT name[32];STR alias_string = NULL;SSHORT id, stream, length, context; SET_TDBB (tdbb);#ifdef GATEWAYdbb = tdbb->tdbb_database;#endif/* Make a relation reference node */node = PAR_make_node (tdbb, e_rel_length);node->nod_count = 0;/* Find relation either by id or by name */if (_operator == blr_rid || _operator == blr_rid2) { id = BLR_WORD; if (_operator == blr_rid2) { length = BLR_PEEK; alias_string = (STR) ALLOCDV (type_str, length + 1); alias_string->str_length = length; par_name (csb, alias_string->str_data); }#ifndef GATEWAY if (!(relation = MET_lookup_relation_id (tdbb, id, FALSE))) { sprintf (name, "id %d", id); error (*csb, gds__relnotdef, gds_arg_string, ERR_cstring (name), 0); }#else /* To use rid, the relation slot must already have been filled in */ if (id >= dbb->dbb_relations->vec_count || !dbb->dbb_relations->vec_object [id]) error (*csb, gds__ctxnotdef, 0); relation = MET_relation (tdbb, id);#endif }else if (_operator == blr_relation || _operator == blr_relation2) { par_name (csb, name); if (_operator == blr_relation2) { length = BLR_PEEK; alias_string = (STR) ALLOCDV (type_str, length + 1); alias_string->str_length = length; par_name (csb, alias_string->str_data); } if (!(relation = MET_lookup_relation (tdbb, name))) error (*csb, gds__relnotdef, gds_arg_string, ERR_cstring (name), 0); }/* if an alias was passed, store with the relation */if (alias_string) node->nod_arg [e_rel_alias] = (NOD) alias_string;/* Scan the relation if it hasn't already been scanned for meta data */if ((!(relation->rel_flags & REL_scanned) || (relation->rel_flags & REL_being_scanned)) && ((relation->rel_flags & REL_force_scan) || !((*csb)->csb_g_flags & csb_internal))) { relation->rel_flags &= ~REL_force_scan; MET_scan_relation (tdbb, relation); }else if (relation->rel_flags & REL_sys_triggers) MET_parse_sys_trigger (tdbb, relation);/* generate a stream for the relation reference, assuming it is a real reference */if (parse_context) { stream = par_context (csb, &context); node->nod_arg [e_rel_stream] = (NOD) (SLONG) stream; node->nod_arg [e_rel_context] = (NOD) (SLONG) context; (*csb)->csb_rpt [stream].csb_relation = relation; (*csb)->csb_rpt [stream].csb_alias = alias_string; if ((*csb)->csb_g_flags & csb_get_dependencies) par_dependency (tdbb, csb, stream, (SSHORT) -1, NULL_PTR); }node->nod_arg [e_rel_relation] = (NOD) relation;return node;}static NOD par_rse ( TDBB tdbb, CSB *csb, SSHORT rse_op){/************************************** * * p a r _ r s e * ************************************** * * Functional description * Parse a record selection expression. * **************************************/register RSE rse;NOD *ptr;register SSHORT count;USHORT jointype;UCHAR op;SET_TDBB (tdbb);count = (unsigned int) BLR_BYTE;rse = (RSE) PAR_make_node (tdbb, count + rse_delta + 2);rse->nod_count = 0;rse->rse_count = count;ptr = rse->rse_relation;while (--count >= 0) *ptr++ = parse (tdbb, csb, RELATION);while (TRUE) switch (op = BLR_BYTE) { case blr_boolean: rse->rse_boolean = parse (tdbb, csb, BOOL); break; case blr_first: if (rse_op == blr_rs_stream) syntax_error (*csb, "rse stream clause"); rse->rse_first = parse (tdbb, csb, VALUE); break; case blr_skip: if (rse_op == blr_rs_stream) syntax_error (*csb, "rse stream clause"); rse->rse_skip = parse (tdbb, csb, VALUE); break; case blr_sort: if (rse_op == blr_rs_stream) syntax_error (*csb, "rse stream clause"); rse->rse_sorted = par_sort (tdbb, csb, TRUE); break; case blr_project: if (rse_op == blr_rs_stream) syntax_error (*csb, "rse stream clause"); rse->rse_projection = par_sort (tdbb, csb, FALSE); break; case blr_join_type: if ((rse->rse_jointype = jointype = (USHORT) BLR_BYTE) != blr_inner && jointype != blr_left && jointype != blr_right && jointype != blr_full) syntax_error (*csb, "join type clause"); break; case blr_plan: rse->rse_plan = par_plan (tdbb, csb); break; #ifdef SCROLLABLE_CURSORS /* if a receive is seen here, then it is intended to be an asynchronous receive which can happen at any time during the scope of the rse-- this is intended to be a more efficient mechanism for scrolling through a record stream, to prevent having to send a message to the engine for each record */ case blr_receive: BLR_PUSH; rse->rse_async_message = parse (tdbb, csb, STATEMENT); break;#endif default: if (op == (UCHAR) blr_end) { /* An outer join is only allowed when the stream count is 2 and a boolean expression has been supplied */ if (!rse->rse_jointype || (rse->rse_count == 2 && rse->rse_boolean)) return (NOD) rse; } syntax_error (*csb, (rse_op == blr_rs_stream) ? "rse stream clause" : "record selection expression clause"); }}static NOD par_sort ( TDBB tdbb, CSB *csb, BOOLEAN flag){/************************************** * * p a r _ s o r t * ************************************** * * Functional description * Parse a sort clause (sans header byte). This is used for * BLR_SORT, BLR_PROJECT, and BLR_GROUP. * **************************************/NOD clause, *ptr, *ptr2;SSHORT count;SET_TDBB (tdbb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -