📄 gen.c
字号:
} }STUFF (blr_assignment);STUFF (blr_literal);STUFF (blr_short);STUFF (0);if (eos_flag) STUFF_WORD (0);else STUFF_WORD (1);STUFF (blr_parameter);STUFF (1);STUFF_WORD (2 * outputs);STUFF (blr_end);if (!eos_flag) { STUFF (blr_stall); STUFF (blr_end); }}static void gen_rse ( REQ request, NOD rse){/************************************** * * g e n _ r s e * ************************************** * * Functional description * Generate a record selection expression. * **************************************/NOD node, list, *ptr, *end;PAR parameter;if (rse->nod_arg [e_rse_singleton] && !(request->req_dbb->dbb_flags & DBB_v3)) STUFF (blr_singular);STUFF (blr_rse);list = rse->nod_arg [e_rse_streams];/* Handle source streams */if (list->nod_type == nod_union) { STUFF (1); gen_union (request, rse); }else if (list->nod_type == nod_list) { STUFF (list->nod_count); for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) { node = *ptr; if (node->nod_type == nod_relation || node->nod_type == nod_aggregate || node->nod_type == nod_join) GEN_expr (request, node); } }else { STUFF (1); GEN_expr (request, list); }if ((node = rse->nod_arg [e_rse_first]) != NULL) { STUFF (blr_first); GEN_expr (request, node); }if ((node = rse->nod_arg [e_rse_skip]) != NULL) { STUFF (blr_skip); GEN_expr (request, node); }if ((node = rse->nod_arg [e_rse_boolean]) != NULL) { STUFF (blr_boolean); GEN_expr (request, node); }if ((list = rse->nod_arg [e_rse_sort]) != NULL) gen_sort (request, list);if ((list = rse->nod_arg [e_rse_reduced]) != NULL) { STUFF (blr_project); STUFF (list->nod_count); for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) GEN_expr (request, *ptr); }/* if the user specified an access plan to use, add it here */if ((node = rse->nod_arg [e_rse_plan]) != NULL) { STUFF (blr_plan); gen_plan (request, node); }#ifdef SCROLLABLE_CURSORS/* generate a statement to be executed if the user scrolls in a direction other than forward; a message is sent outside the normal send/receive protocol to specify the direction and offset to scroll; note that we do this only on a SELECT type statement and only when talking to a 4.1 engine or greater */if (request->req_type == REQ_SELECT && request->req_dbb->dbb_base_level >= 5) { STUFF (blr_receive); STUFF (request->req_async->msg_number); STUFF (blr_seek); parameter = request->req_async->msg_parameters; gen_parameter (request, parameter->par_next); gen_parameter (request, parameter); }#endifSTUFF (blr_end);}static void gen_select ( REQ request, NOD rse){/************************************** * * g e n _ s e l e c t * ************************************** * * Functional description * Generate BLR for a SELECT statement. * **************************************/NOD list, *ptr, *end, item, alias, map_node;PAR parameter;MSG message;FLD field;DSC constant_desc;DSQL_REL relation;UDF udf;CTX context;STR string;SSHORT constant;MAP map;constant_desc.dsc_dtype = dtype_short;constant_desc.dsc_scale = 0;constant_desc.dsc_sub_type = 0;constant_desc.dsc_flags = 0;constant_desc.dsc_length = sizeof (SSHORT);constant_desc.dsc_address = (UCHAR*) &constant;/* Set up parameter for things in the select list */list = rse->nod_arg [e_rse_items];for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++){ item = *ptr; parameter = MAKE_parameter (request->req_receive, TRUE, TRUE); parameter->par_node = item; MAKE_desc (¶meter->par_desc, item); if (item->nod_type == nod_field) { field = (FLD) item->nod_arg [e_fld_field]; parameter->par_name = parameter->par_alias = field->fld_name; context = (CTX) item->nod_arg [e_fld_context]; if (context->ctx_relation) { parameter->par_rel_name = context->ctx_relation->rel_name; parameter->par_owner_name = context->ctx_relation->rel_owner; } else if (context->ctx_procedure) { parameter->par_rel_name = context->ctx_procedure->prc_name; parameter->par_owner_name = context->ctx_procedure->prc_owner; } } else if (item->nod_type == nod_dbkey) { parameter->par_name = parameter->par_alias = db_key_name; context = (CTX) item->nod_arg [0]->nod_arg [0]; parameter->par_rel_name = context->ctx_relation->rel_name; parameter->par_owner_name = context->ctx_relation->rel_owner; } else if (item->nod_type == nod_alias) { string = (STR) item->nod_arg [e_alias_alias]; parameter->par_alias = (TEXT*) string->str_data; alias = item->nod_arg [e_alias_value]; if (alias->nod_type == nod_field) { field = (FLD) alias->nod_arg [e_fld_field]; parameter->par_name = field->fld_name; context = (CTX) alias->nod_arg [e_fld_context]; if (context->ctx_relation) { parameter->par_rel_name = context->ctx_relation->rel_name; parameter->par_owner_name = context->ctx_relation->rel_owner; } else if (context->ctx_procedure) { parameter->par_rel_name = context->ctx_procedure->prc_name; parameter->par_owner_name = context->ctx_procedure->prc_owner; } } else if (alias->nod_type == nod_dbkey) { parameter->par_name = db_key_name; context = (CTX) alias->nod_arg [0]->nod_arg[0]; parameter->par_rel_name = context->ctx_relation->rel_name; parameter->par_owner_name = context->ctx_relation->rel_owner; } } else if (item->nod_type == nod_map) { map = (MAP) item->nod_arg [e_map_map]; map_node = map->map_node; while (map_node->nod_type == nod_map) { /* skip all the nod_map nodes */ map = (MAP) map_node->nod_arg [e_map_map]; map_node = map->map_node; } if (map_node->nod_type == nod_field) { field = (FLD) map_node->nod_arg [e_fld_field]; parameter->par_name = parameter->par_alias = field->fld_name; } else if (map_node->nod_type == nod_alias) { string = (STR) map_node->nod_arg [e_alias_alias]; parameter->par_alias = (TEXT*) string->str_data; alias = map_node->nod_arg [e_alias_value]; if (alias->nod_type == nod_field) { field = (FLD) alias->nod_arg [e_fld_field]; parameter->par_name = field->fld_name; } } else if (map_node->nod_type == nod_agg_count) parameter->par_name = parameter->par_alias = "COUNT"; else if (map_node->nod_type == nod_agg_total) parameter->par_name = parameter->par_alias = "SUM"; else if (map_node->nod_type == nod_agg_average) parameter->par_name = parameter->par_alias = "AVG"; else if (map_node->nod_type == nod_agg_total2) parameter->par_name = parameter->par_alias = "SUM"; else if (map_node->nod_type == nod_agg_average2) parameter->par_name = parameter->par_alias = "AVG"; else if (map_node->nod_type == nod_agg_min) parameter->par_name = parameter->par_alias = "MIN"; else if (map_node->nod_type == nod_agg_max) parameter->par_name = parameter->par_alias = "MAX"; } else if (item->nod_type == nod_udf) { udf = (UDF) item->nod_arg [0]; parameter->par_name = parameter->par_alias = udf->udf_name; } else if (item->nod_type == nod_gen_id) parameter->par_name = parameter->par_alias = "GEN_ID"; else if (item->nod_type == nod_gen_id2) parameter->par_name = parameter->par_alias = "GEN_ID"; else if (item->nod_type == nod_user_name) parameter->par_name = parameter->par_alias = "USER"; else if (item->nod_type == nod_current_role) parameter->par_name = parameter->par_alias = "ROLE"; else if (item->nod_type == nod_substr) { /* CVC: SQL starts at 1 but C starts at zero. */ /*NOD node = item->nod_arg [e_substr_start]; --(*(SLONG *) (node->nod_desc.dsc_address)); FIXED IN PARSE.Y; here it doesn't catch expressions: Bug 450301. */ parameter->par_name = parameter->par_alias = "SUBSTRING"; } else if (item->nod_type == nod_cast) parameter->par_name = parameter->par_alias = "CAST";} /* for *//* Set up parameter to handle EOF */request->req_eof = parameter = MAKE_parameter (request->req_receive, FALSE, FALSE);parameter->par_desc.dsc_dtype = dtype_short;parameter->par_desc.dsc_scale = 0;parameter->par_desc.dsc_length = sizeof (SSHORT);/* Save DBKEYs for possible update later */list = rse->nod_arg [e_rse_streams];if (!rse->nod_arg [e_rse_reduced]) { for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) if ((item = *ptr) && (item->nod_type == nod_relation)) { context = (CTX) item->nod_arg [e_rel_context]; if (relation = context->ctx_relation) { /* Set up dbkey */ parameter = MAKE_parameter (request->req_receive, FALSE, FALSE); parameter->par_dbkey_ctx = context; parameter->par_desc.dsc_dtype = dtype_text; parameter->par_desc.dsc_ttype = ttype_binary; parameter->par_desc.dsc_length = relation->rel_dbkey_length; /* Set up record version - for post v33 databases */ if (!(request->req_dbb->dbb_flags & DBB_v3)) { parameter = MAKE_parameter (request->req_receive, FALSE, FALSE); parameter->par_rec_version_ctx = context; parameter->par_desc.dsc_dtype = dtype_text; parameter->par_desc.dsc_ttype = ttype_binary; parameter->par_desc.dsc_length = relation->rel_dbkey_length/2; } } } }#ifdef SCROLLABLE_CURSORS/* define the parameters for the scrolling message--offset and direction, in that order to make it easier to generate the request */if (request->req_type == REQ_SELECT && request->req_dbb->dbb_base_level >= 5) { parameter = MAKE_parameter (request->req_async, FALSE, FALSE); parameter->par_desc.dsc_dtype = dtype_short; parameter->par_desc.dsc_length = sizeof (USHORT); parameter->par_desc.dsc_scale = 0; parameter->par_desc.dsc_flags = 0; parameter->par_desc.dsc_sub_type = 0; parameter = MAKE_parameter (request->req_async, FALSE, FALSE); parameter->par_desc.dsc_dtype = dtype_long; parameter->par_desc.dsc_length = sizeof (ULONG); parameter->par_desc.dsc_scale = 0; parameter->par_desc.dsc_flags = 0; parameter->par_desc.dsc_sub_type = 0; }#endif/* Generate definitions for the messages */GEN_port (request, request->req_receive);message = request->req_send;if (message->msg_parameter) GEN_port (request, message);else request->req_send = NULL;#ifdef SCROLLABLE_CURSORSif (request->req_type == REQ_SELECT && request->req_dbb->dbb_base_level >= 5) GEN_port (request, request->req_async);#endif/* If there is a send message, build a RECEIVE */if ((message = request->req_send) != NULL) { STUFF (blr_receive); STUFF (message->msg_number); }/* Generate FOR loop */message = request->req_receive;STUFF (blr_for);if (!(request->req_dbb->dbb_flags & DBB_v3)) STUFF (blr_stall);gen_rse (request, rse);STUFF (blr_send);STUFF (message->msg_number);STUFF (blr_begin);/* Build body of FOR loop */STUFF (blr_assignment);constant = 1;gen_constant (request, &constant_desc, USE_VALUE);gen_parameter (request, request->req_eof);for (parameter = message->msg_parameters; parameter; parameter = parameter->par_next) { if (parameter->par_node) { STUFF (blr_assignment); GEN_expr (request, parameter->par_node); gen_parameter (request, parameter); } if (context = parameter->par_dbkey_ctx) { STUFF (blr_assignment); STUFF (blr_dbkey); STUFF (context->ctx_context); gen_parameter (request, parameter); } if (context = parameter->par_rec_version_ctx) { STUFF (blr_assignment); STUFF (blr_record_version); STUFF (context->ctx_context); gen_parameter (request, parameter); } }STUFF (blr_end);STUFF (blr_send);STUFF (message->msg_number);STUFF (blr_assignment);constant = 0;gen_constant (request, &constant_desc, USE_VALUE);gen_parameter (request, request->req_eof);}static void gen_sort ( REQ request, NOD list){/************************************** * * g e n _ s o r t * ************************************** * * Functional description * Generate a sort clause. * **************************************/NOD *ptr, *end;STUFF (blr_sort);STUFF (list->nod_count);for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) { if ((*ptr)->nod_arg [1]) STUFF (blr_descending); else STUFF (blr_ascending); GEN_expr (request, (*ptr)->nod_arg [0]); }}static void gen_table_lock ( REQ request, NOD tbl_lock, USHORT lock_level){/************************************** * * g e n _ t a b l e _ l o c k * ************************************** * * Functional description * Generate tpb for table lock. * If lock level is specified, it overrrides the transaction lock level. * **************************************/NOD tbl_names, *ptr, *end;STR temp;SSHORT flags;USHORT lock_mode;if ((!tbl_lock) || (tbl_lock->nod_type != nod_table_lock)) return;tbl_names = tbl_lock->nod_arg [e_lock_tables];flags = 0;if (tbl_lock->nod_arg [e_lock_mode]) flags = tbl_lock->nod_arg [e_lock_mode]->nod_flags;if (flags & NOD_PROTECTED) lock_level = gds__tpb_protected;else if (flags & NOD_SHARED) lock_level = gds__tpb_shared;lock_mode = (flags & NOD_WRITE) ? gds__tpb_lock_write : gds__tpb_lock_read;for (ptr = tbl_names->nod_arg, end = ptr + tbl_names->nod_count; ptr < end; ptr++) { if ((*ptr)->nod_type != nod_relation_name) continue; STUFF (lock_mode); /* stuff table name */ temp = (STR) ((*ptr)->nod_arg [e_rln_name]); stuff_cstring (request, temp->str_data); STUFF (lock_level); }}static void gen_udf ( REQ request, NOD node){/************************************** * * g e n _ u d f * ************************************** * * Functional description * Generate a user defined function. * **************************************/UDF udf;NOD list, *ptr, *end;udf = (UDF) node->nod_arg [0];STUFF (blr_function);STUFF_CSTRING (udf->udf_name);if ((node->nod_count == 2) && (list = node->nod_arg [1])) { STUFF (list->nod_count); for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) GEN_expr (request, *ptr); }else STUFF (0);}static void gen_union ( REQ request, NOD union_node){/************************************** * * g e n _ u n i o n * ************************************** * * Functional description * Generate a union of substreams. * **************************************/NOD sub_rse, *ptr, *end, streams;NOD items, *iptr, *iend;USHORT count;CTX union_context;STUFF (blr_union);/* Obtain the context for UNION from the first MAP node */items = union_node->nod_arg[e_rse_items];union_context = (CTX) items->nod_arg[0]->nod_arg[e_map_context];STUFF (union_context->ctx_context);streams = union_node->nod_arg [e_rse_streams];STUFF (streams->nod_count); /* number of substreams */for (ptr = streams->nod_arg, end = ptr + streams->nod_count; ptr < end; ptr++) { sub_rse = *ptr; gen_rse (request, sub_rse); items = sub_rse->nod_arg [e_rse_items]; STUFF (blr_map); STUFF_WORD (items->nod_count); count = 0; for (iptr = items->nod_arg, iend = iptr + items->nod_count; iptr < iend; iptr++) { STUFF_WORD (count); GEN_expr (request, *iptr); count++; } }}static void stuff_cstring ( REQ request, UCHAR *string){/************************************** * * s t u f f _ c s t r i n g * ************************************** * * Functional description * Write out a string with one byte of length. * **************************************/UCHAR c;STUFF (strlen (string));while ((c = *string++) != NULL) STUFF (c);}static void stuff_word ( REQ request, USHORT word){/************************************** * * s t u f f _ w o r d * ************************************** * * Functional description * Cram a word into the blr buffer. If the buffer is getting * ready to overflow, expand it. * **************************************/STUFF (word);STUFF (word >> 8);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -