📄 pass1.c
字号:
{ return FALSE; }invalid = FALSE;if (node->nod_type == nod_field) { FLD field; CTX context; NOD reference; if (!list) return TRUE; field = (FLD) node->nod_arg[e_fld_field]; context = (CTX) node->nod_arg[e_fld_context]; DEV_BLKCHK (field, type_fld); DEV_BLKCHK (context, type_ctx); for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) { DEV_BLKCHK (*ptr, type_nod); reference = *ptr; if ((*ptr)->nod_type == nod_cast) { reference = (*ptr)->nod_arg[e_cast_source]; } DEV_BLKCHK (reference, type_nod); if (reference->nod_type == nod_field && field == (FLD) reference->nod_arg[e_fld_field] && context == (CTX) reference->nod_arg[e_fld_context]) return FALSE; } return TRUE; }else if (node->nod_type == nod_dbkey) { CTX context; NOD reference, rel_node; if (!list) return TRUE; rel_node = (NOD) node->nod_arg [0]; context = (CTX) rel_node->nod_arg [0]; DEV_BLKCHK (context, type_ctx); for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) { DEV_BLKCHK (*ptr, type_nod); reference = *ptr; if ((*ptr)->nod_type == nod_cast) { reference = (*ptr)->nod_arg[e_cast_source]; } DEV_BLKCHK (reference, type_nod); if (reference->nod_type == nod_dbkey && rel_node == (NOD) reference->nod_arg [0] && context == (CTX) rel_node->nod_arg [0]) return FALSE; } return TRUE; }else { if ((node->nod_type == nod_gen_id) || (node->nod_type == nod_gen_id2) || (node->nod_type == nod_cast)) { if (node->nod_count == 2) invalid |= invalid_reference (node->nod_arg [1], list); } else if (node->nod_type == nod_udf) { /* does this udf appear in list of group by */ NOD reference; STR udf_name1; STR udf_name2; if (!list) return TRUE; for (ptr = list->nod_arg, end = ptr + list->nod_count; ptr < end; ptr++) { DEV_BLKCHK(*ptr, type_nod); reference = *ptr; if ((*ptr)->nod_type == nod_cast) { reference = (*ptr)->nod_arg[e_cast_source]; } DEV_BLKCHK(reference, type_nod); if (reference->nod_type == nod_udf) { udf_name1 = (STR)(node->nod_arg[0]); udf_name2 = (STR)(reference->nod_arg[0]); if ((udf_name1->str_length == udf_name2->str_length) && (strncmp(udf_name1->str_data, udf_name2->str_data, udf_name1->str_length) == 0)) { if (node->nod_count == 2) { if (node_match (node, reference) == TRUE) { invalid = FALSE; } else { invalid = TRUE; } return invalid; } else return FALSE; } } } return TRUE; } #ifdef CHECK_HAVING/******************************************************* taken out to fix a more serious bug*******************************************************/ else if (node->nod_type == nod_map) { MAP map; map = (MAP) node->nod_arg [e_map_map]; DEV_BLKCHK (map, type_map); invalid |= invalid_reference (map->map_node, list); }#endif else switch (node->nod_type) { default: ASSERT_FAIL; /* FALLINTO */ case nod_add: case nod_concatenate: case nod_divide: case nod_multiply: case nod_negate: case nod_substr: case nod_subtract: case nod_upcase: case nod_extract: case nod_add2: case nod_divide2: case nod_multiply2: case nod_subtract2: case nod_eql: case nod_neq: case nod_gtr: case nod_geq: case nod_leq: case nod_lss: case nod_eql_any: case nod_neq_any: case nod_gtr_any: case nod_geq_any: case nod_leq_any: case nod_lss_any: case nod_eql_all: case nod_neq_all: case nod_gtr_all: case nod_geq_all: case nod_leq_all: case nod_lss_all: case nod_between: case nod_like: case nod_missing: case nod_and: case nod_or: case nod_any: case nod_ansi_any: case nod_ansi_all: case nod_not: case nod_unique: case nod_containing: case nod_starting: case nod_rse: case nod_list: case nod_via: for (ptr = node->nod_arg, end = ptr + node->nod_count; ptr < end; ptr++) invalid |= invalid_reference (*ptr, list); break; case nod_alias: invalid |= invalid_reference (node->nod_arg [e_alias_value], list); break; /* An embedded aggregate, even of an expression, is OK */ case nod_agg_average: case nod_agg_count: case nod_agg_max: case nod_agg_min: case nod_agg_total: case nod_agg_average2: case nod_agg_total2: /* Fall into ... */ /* misc other stuff */ case nod_aggregate: case nod_map: case nod_relation: case nod_variable: case nod_constant: case nod_null: case nod_current_date: case nod_current_time: case nod_current_timestamp: case nod_user_name: case nod_current_role: return FALSE; } }return invalid;}static void mark_ctx_outer_join ( NOD node){/************************************** * * m a r k _ c t x _ o u t e r _ j o i n * ************************************** * * Functional description * Mark the context blocks of relations in an RSE as * participating in an Outer Join of some sort. * This is important when we are deciding whether * a particular field reference can be NULL or not. * If the field is declared NOT NULL, it normally cannot * be NULL - however, if the base relation reference is * within the "outside" part of an outer join rse, * it CAN be null. * * Our input RSE can be either a relation (table, view, or proc) * reference or a JOIN expression. * **************************************/CTX context;DEV_BLKCHK (node, type_nod);switch (node->nod_type) { case nod_relation: context = (CTX) node->nod_arg [e_rel_context]; DEV_BLKCHK (context, type_ctx); assert (context); context->ctx_flags |= CTX_outer_join; break; case nod_join: mark_ctx_outer_join (node->nod_arg [e_join_left_rel]); mark_ctx_outer_join (node->nod_arg [e_join_rght_rel]); break; default: ASSERT_FAIL; /* only join & relation expected */ break; }}static BOOLEAN node_match ( NOD node1, NOD node2){/************************************** * * n o d e _ m a t c h * ************************************** * * Functional description * Compare two nodes for equality of value. * **************************************/NOD *ptr1, *ptr2, *end;MAP map1, map2;USHORT l;UCHAR *p1, *p2;DEV_BLKCHK (node1, type_nod);DEV_BLKCHK (node2, type_nod);if ((!node1) && (!node2)) return TRUE;if ((!node1) || (!node2) || (node1->nod_type != node2->nod_type) || (node1->nod_count != node2->nod_count)) return FALSE;/* This is to get rid of assertion failures when trying to node_match nod_aggregate's children. This was happening because not all of the chilren are of type "struct nod". Pointer to the first child (argument) is actually a pointer to context structure. To compare two nodes of type nod_aggregate we need first to see if they both refer to same context structure. If they do not they are different nodes, if they point to the same context they are the same (because nod_aggregate is created for an rse that have aggregate expression, group by or having clause and each rse has its own context). But just in case we compare two other subtrees.*/if (node1->nod_type == nod_aggregate) if (node1->nod_arg[e_agg_context] != node2->nod_arg[e_agg_context]) return FALSE; else return (node_match (node1->nod_arg[e_agg_group], node2->nod_arg[e_agg_group]) && node_match (node1->nod_arg[e_agg_rse], node2->nod_arg[e_agg_rse]));if (node1->nod_type == nod_alias) return node_match (node1->nod_arg [e_alias_value], node2);if (node2->nod_type == nod_alias) return node_match (node1, node2->nod_arg [e_alias_value]);if (node1->nod_type == nod_field) { if (node1->nod_arg [e_fld_field] != node2->nod_arg [e_fld_field] || node1->nod_arg [e_fld_context] != node2->nod_arg [e_fld_context]) return FALSE; if (node1->nod_arg [e_fld_indices] || node2->nod_arg [e_fld_indices]) return node_match (node1->nod_arg [e_fld_indices], node2->nod_arg [e_fld_indices]); return TRUE; }if (node1->nod_type == nod_constant) { if (node1->nod_desc.dsc_dtype != node2->nod_desc.dsc_dtype || node1->nod_desc.dsc_length != node2->nod_desc.dsc_length || node1->nod_desc.dsc_scale != node2->nod_desc.dsc_scale) return FALSE; p1 = node1->nod_desc.dsc_address; p2 = node2->nod_desc.dsc_address; for (l = node1->nod_desc.dsc_length; l > 0; l--) if (*p1++ != *p2++) return FALSE; return TRUE; }if (node1->nod_type == nod_map) { map1 = (MAP) node1->nod_arg [e_map_map]; map2 = (MAP) node2->nod_arg [e_map_map]; DEV_BLKCHK (map1, type_map); DEV_BLKCHK (map2, type_map); return node_match (map1->map_node, map2->map_node); }if ((node1->nod_type == nod_gen_id) || (node1->nod_type == nod_gen_id2) || (node1->nod_type == nod_udf) || (node1->nod_type == nod_cast)) { if (node1->nod_arg [0] != node2->nod_arg [0]) return FALSE; if (node1->nod_count == 2) return node_match (node1->nod_arg [1], node2->nod_arg [1]); else return TRUE; }if ((node1->nod_type == nod_agg_count) || (node1->nod_type == nod_agg_total) || (node1->nod_type == nod_agg_total2) || (node1->nod_type == nod_agg_average2) || (node1->nod_type == nod_agg_average)) { if ((node1->nod_flags & NOD_AGG_DISTINCT) != (node2->nod_flags & NOD_AGG_DISTINCT)) return FALSE; }if (node1->nod_type == nod_variable) { VAR var1, var2; if (node1->nod_type != node2->nod_type) return FALSE; var1 = node1->nod_arg [e_var_variable]; var2 = node2->nod_arg [e_var_variable]; DEV_BLKCHK (var1, type_var); DEV_BLKCHK (var2, type_var); if ( (strcmp (var1->var_name, var2->var_name)) || (var1->var_field != var2->var_field) || (var1->var_variable_number != var2->var_variable_number) || (var1->var_msg_item != var2->var_msg_item) || (var1->var_msg_number != var2->var_msg_number) ) return FALSE; return TRUE; }ptr1 = node1->nod_arg;ptr2 = node2->nod_arg;for (end = ptr1 + node1->nod_count; ptr1 < end; ptr1++, ptr2++) if (!node_match (*ptr1, *ptr2)) return FALSE;return TRUE;}static NOD pass1_any ( REQ request, NOD input, NOD_TYPE ntype){/************************************** * * p a s s 1 _ a n y * ************************************** * * Functional description * Compile a parsed request into something more interesting. * **************************************/NOD node, temp, rse, select;LLS base;DEV_BLKCHK (request, type_req);DEV_BLKCHK (input, type_nod);select = input->nod_arg [1];base = request->req_context;temp = MAKE_node (input->nod_type, 2);temp->nod_arg [0] = PASS1_node (request, input->nod_arg [0], 0);node = MAKE_node (ntype, 1);node->nod_arg [0] = rse = PASS1_rse (request, select, NULL);/* adjust the scope level back to the sub-rse, so that the fields in the select list will be properly recognized */request->req_scope_level++;request->req_in_select_list++;temp->nod_arg [1] = PASS1_node (request, select->nod_arg [e_sel_list]->nod_arg[0], 0);request->req_in_select_list--;request->req_scope_level--;rse->nod_arg [e_rse_boolean] = compose (rse->nod_arg [e_rse_boolean], temp, nod_and);while (request->req_context != base) LLS_POP (&request->req_context);return node;}static void pass1_blob ( REQ request, NOD input){/************************************** * * p a s s 1 _ b l o b * ************************************** * * Functional description * Process a blob get or put segment. * **************************************/NOD field, list;BLB blob;PAR parameter;TSQL tdsql;USHORT fcount;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -