void rf_att_dflt(i4 NumRels, char *RelList[]) { FE_ATT_QBLK qblk; FE_ATT_INFO attinfo; FE_REL_INFO relinfo; register ATTRIB id; i4 i = 0; bool RepeatedField; char ColName [FE_MAXNAME + 1]; i4 ins = 0; FE_RSLV_NAME *rfa_ferslv[MQ_MAXRELS]; RFCOLDESC *coldesc; ATT *attptr; char *cname; ATTRIB did; i4 real_cols; char dsply_name[(FE_UNRML_MAXNAME + 1)]; /* ** If the user went through the choose columns path, we will ** use that information to create the structures since we ** alredy have all the needed information. */ if (IIRFcccount != 0) { En_n_attribs = IIRFcccount; real_cols = IIRFcccount - IIRFcdcount; /* Allocate memory for the ATT array. */ if ((Ptr_att_top = (ATT *)FEreqmem((u_i4)Rst4_tag, (u_i4)(IIRFcccount*(sizeof(ATT))), TRUE, (STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - Ptr_att_top")); } /* ** Step through the set of column names. Deleted ones are ** placed at the end of the array. We need to keep them ** around so that the user can add them back in the layout ** frame. */ for (i = 0, id = 0, did = real_cols, coldesc = IIRFcollist; i < IIRFcccount; i++, coldesc++) { if (coldesc->deleted) { attptr = &(Ptr_att_top[did++]); attptr->pre_deleted = TRUE; } else { attptr = &(Ptr_att_top[id++]); } cname = coldesc->name; attptr->att_name = FEtsalloc(Rst4_tag, cname); /* check if attribute name is a keyword */ if (!St_silent && (r_gt_pcode(cname) != PC_ERROR || r_gt_wcode(cname) != A_ERROR || r_gt_vcode(cname) != VC_NONE || r_gt_cagg(cname) || STcompare(cname, NAM_REPORT) == 0 || STcompare(cname, NAM_PAGE) == 0 || STcompare(cname, NAM_DETAIL) == 0)) { IIUGmsg(ERget(S_RF0047_Column_name_keyword), (bool) FALSE, 1, cname); } /* set up the data type field */ attptr->att_value.db_datatype = coldesc->datatype; attptr->att_prev_val.db_datatype = coldesc->datatype; attptr->att_value.db_length = coldesc->length; attptr->att_prev_val.db_length = coldesc->length; attptr->att_value.db_prec = coldesc->prec; attptr->att_prev_val.db_prec = coldesc->prec; /* ** Do not allocate value buffers for un-supported datatypes. ** We already let the user know that they're being ignored ** when we passed through ChooseColumns, so don't do it again! */ if (!IIAFfedatatype(&attptr->att_value)) { attptr->att_value.db_data = (PTR)NULL; attptr->att_prev_val.db_data = (PTR)NULL; } else { if ((attptr->att_value.db_data = (PTR)FEreqmem((u_i4)Rst4_tag, (u_i4)(attptr->att_value.db_length), TRUE, (STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - db_data")); } if ((attptr->att_prev_val.db_data = (PTR)FEreqmem((u_i4)Rst4_tag, (u_i4)(attptr->att_prev_val.db_length), TRUE, (STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - prev db_data")); } } /* flag to indicate when done */ attptr->att_position = 0; attptr->att_lac = NULL; } return; } /* ** determine number of attributes in base table: */ for (i = 0; i < NumRels; i ++) { /* ** Decompose any owner.tablename, validate the components, ** and normalize them for later use. */ if ((rfa_ferslv[i] = (FE_RSLV_NAME *)MEreqmem((u_i4)0, (u_i4)sizeof(FE_RSLV_NAME),TRUE, (STATUS *)NULL)) == (FE_RSLV_NAME *)NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - rfa_ferslv")); } if ((rfa_ferslv[i]->name_dest = (char *)MEreqmem((u_i4)0, (u_i4)(FE_UNRML_MAXNAME+1),TRUE,(STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - name_dest")); } if ((rfa_ferslv[i]->owner_dest = (char *)MEreqmem((u_i4)0, (u_i4)(FE_UNRML_MAXNAME+1),TRUE,(STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - owner_dest")); } rfa_ferslv[i]->name = RelList[i]; rfa_ferslv[i]->is_nrml = FALSE; FE_decompose(rfa_ferslv[i]); if ((rfa_ferslv[i]->owner_spec) && (((STcompare(IIUIcsl_CommonSQLLevel(),UI_LEVEL_65) < 0) && (IIUIdcd_dist() == FALSE) || IIUIdcd_dist() == TRUE && (STcompare(IIUIcsl_CommonSQLLevel(), UI_LEVEL_61) < 0)))) { continue; } if ((IIUGdlm_ChkdlmBEobject(rfa_ferslv[i]->name_dest, rfa_ferslv[i]->name_dest, rfa_ferslv[i]->is_nrml) == UI_BOGUS_ID) || ((rfa_ferslv[i]->owner_spec) && ((IIUGdlm_ChkdlmBEobject(rfa_ferslv[i]->owner_dest, rfa_ferslv[i]->owner_dest, rfa_ferslv[i]->is_nrml) == UI_BOGUS_ID) && STcompare(rfa_ferslv[i]->owner_dest, UI_FE_CAT_ID_65)))) { continue; } if (FE_resolve(rfa_ferslv[i],rfa_ferslv[i]->name_dest, rfa_ferslv[i]->owner_dest)) { En_n_attribs += FEnumatts(rfa_ferslv[i]->name_dest, rfa_ferslv[i]->owner_dest); } } /* ** Allocate array of ATT structures: */ if ((Ptr_att_top = (ATT *)FEreqmem((u_i4)Rst4_tag, (u_i4)(En_n_attribs*(sizeof(ATT))), TRUE, (STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - Ptr_att_top")); } /* ** For each relation fill out the ATT structures: */ id = 0; if (En_SrcTyp == JDRepSrc) _VOID_ r_JDMaintTabList(JD_TAB_INIT_INS_CNT, NULL, NULL, NULL, NULL); for (i = 0; i < NumRels; i ++) { /* ** open access to base table */ /* ** Fill out relinfo with table information, including table owner. */ FErel_ffetch(rfa_ferslv[i]->name_dest,rfa_ferslv[i]->owner_dest, &relinfo); MEfree((PTR)rfa_ferslv[i]->name_dest); MEfree((PTR)rfa_ferslv[i]->owner_dest); MEfree((PTR)rfa_ferslv[i]); FEatt_fopen(&qblk, &relinfo); if (En_SrcTyp == JDRepSrc) _VOID_ r_JDMaintTabList(JD_TAB_TAB_ADV_INS_CNT, NULL, relinfo.name, relinfo.owner, &ins); /* ** For each attribute in table, fill ATT structure ** (make sure no DB access will take place in this loop!) */ while (FEatt_fetch(&qblk, &attinfo) == OK) { register ATT *r_att; register ATTRIB chk_id; register char *attname; attname = attinfo.column_name; /* ** Check for duplicate column names. If found one, and ** the source of data is not a JoinDef we have a problem, ** Bug #5952: */ RepeatedField = FALSE; chk_id = id - 1; while ((--chk_id >= 0) && (!RepeatedField)) { register ATT *chk_p = &(Ptr_att_top[chk_id]); if (STcompare(chk_p->att_name, attname) == 0) RepeatedField = TRUE; } if ((RepeatedField) && (En_SrcTyp == TabRepSrc)) { r_error(0x2C8, FATAL, attname, NULL); } /* ** Make sure that if the source of data is a JoinDef ** the attribute is being used, and if it's being used ** in more than one table get the constructed name for ** it. Be sure and include the owner in the table look-up! */ if (En_SrcTyp == JDRepSrc) { i4 cnt = 0; /* ** If we can't find the field then it's not being used so ** skip it: */ if (!r_JDMaintAttrList(JD_ATT_GET_FIELD_CNT, r_JDTabNameToRv(relinfo.name, relinfo.owner, ins), attname, &cnt)) continue; if (cnt > 1) { _VOID_ r_JDMaintAttrList(JD_ATT_GET_ATTR_NAME, r_JDTabNameToRv(relinfo.name, relinfo.owner, ins), attname, &ColName [0]); attname = ColName; } } r_att = &(Ptr_att_top[id++]); r_att->att_name = FEtsalloc(Rst4_tag, attname); /* check if attribute name is a keyword */ if (!St_silent && (r_gt_pcode(attname) != PC_ERROR || r_gt_wcode(attname) != A_ERROR || r_gt_vcode(attname) != VC_NONE || r_gt_cagg(attname) || STcompare(attname, NAM_REPORT) == 0 || STcompare(attname, NAM_PAGE) == 0 || STcompare(attname, NAM_DETAIL) == 0)) { IIUGmsg(ERget(S_RF0047_Column_name_keyword), (bool) FALSE, 1, attname); } /* set up the data type field */ r_att->att_value.db_datatype = attinfo.adf_type; r_att->att_prev_val.db_datatype = attinfo.adf_type; r_att->att_value.db_length = attinfo.intern_length; r_att->att_prev_val.db_length = attinfo.intern_length; r_att->att_value.db_prec = attinfo.intern_prec; r_att->att_prev_val.db_prec = attinfo.intern_prec; /* ** Do not allocate value buffers for un-supported datatypes. ** Let the user know that they're being ignored. */ if (!IIAFfedatatype(&r_att->att_value)) { _VOID_ IIUGxri_id(&attinfo.column_name[0], &dsply_name[0]); IIUGerr(E_RW1414_ignored_attrib, UG_ERR_ERROR,1,&dsply_name[0]); r_att->att_value.db_data = (PTR)NULL; r_att->att_prev_val.db_data = (PTR)NULL; } else { if ((r_att->att_value.db_data = (PTR)FEreqmem((u_i4)Rst4_tag, (u_i4)(r_att->att_value.db_length), TRUE, (STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - db_data")); } if ((r_att->att_prev_val.db_data = (PTR)FEreqmem((u_i4)Rst4_tag, (u_i4)(r_att->att_prev_val.db_length), TRUE, (STATUS *)NULL)) == NULL) { IIUGbmaBadMemoryAllocation(ERx("rf_att_dflt - prev db_data")); } } r_att->att_position = 0; /* flag to indicate when done */ r_att->att_lac = NULL; } FEatt_close(&qblk); } /* for */ /* ** Just in case if we have skipped any attributes, ** we're leaking memory though: Note that unsupported ** datatypes will not be reflected as skipped as far as the ** id count is concerned! */ En_n_attribs = id; return; }
bool rFqur_set() { /* internal declarations */ i4 sequence; /* current seq in QUR array */ register QUR *qur; /* fast ptr to QUR array */ i4 rfq_parse_state; /* ** Scanning state for where ** clause. */ i4 type; /* Token type returned */ bool rfq_error; /* TRUE if parse error occurs*/ i4 ord; /* ordinal of attribute */ COPT *copt; /* Copt structure */ char *qual; /* Pointer to qualification */ char *n_qual; /* ** Pointer to qualification ** after skip to any parens ** for JoinDef */ char chk_char; /* ** Hold current char to check ** for comments. */ char rvar[FE_UNRML_MAXNAME+1]; /* Range Var name in where */ char attname[FE_UNRML_MAXNAME+1]; /* Attribute name in where */ char ColName[FE_MAXNAME+1]; /* RBF Internal column name */ FE_RSLV_NAME rfq_ferslv; /* ** Work struct to decompose ** compound identifiers. */ /* start of routine */ # ifdef xRTR1 if (TRgettrace(200,0)) { SIprintf(ERx("rFqur_set: entry.\r\n")); } # endif qual = NULL; for (sequence = 1,qur = Ptr_qur_arr; sequence <= En_qcount; qur++,sequence++) { CVlower(qur->qur_section); if (STcompare(qur->qur_section,NAM_WHERE) == 0) { _VOID_ rfNextQueryLine(&qual, qur->qur_text); } } /* ** If we are here when creating a new report, we don't have ** any selection criteria to look for. */ if (qual == NULL) { return(TRUE); } if (*qual == EOS) { _VOID_ MEfree((PTR)qual); return(TRUE); } /* ** If the source of data is a JoinDef, we need to skip over ** the part of the qualification that defines the join. So, find ** any open parenthesis - if none, then no selection criteria exist. ** Otherwise, reset the qual pointer to the open parens. */ n_qual = qual; if ((En_SrcTyp == JDRepSrc) && ((n_qual = STindex(qual,ERx("("),0)) == NULL)) { return(TRUE); } r_g_set(n_qual); rfq_error = FALSE; rfq_parse_state = FIND_OPAREN; /* ** Note that the parse state won't change until we first see ** an open parens. */ while ((!rfq_error) && ((type = r_g_skip()) != TK_ENDSTRING)) { switch(type) { case(TK_ALPHA): case(TK_QUOTE): if (type == TK_QUOTE) { /* ** Check for QUEL string constant first, ** then check for disallowed delimited ** identifier. */ if (En_qlang == FEDMLQUEL) { _VOID_ MEfree((PTR)r_g_string( TK_QUOTE)); break; } else if (!Rbf_xns_given) { rfq_error = TRUE; break; } } rfq_ferslv.name = r_g_ident(TRUE); /* ** Handle the relation operator 'LIKE' if ** that's what we're looking for. Note that ** for it to be a valid identifier, it would have ** to be in quotes! */ if ((rfq_parse_state == FIND_GREATER) && (STbcompare(rfq_ferslv.name, STlength(rfq_ferslv.name), ERx("like"), STlength(ERx("like")),TRUE) == 0)) { rfq_parse_state = FIND_OPAREN; _VOID_ MEfree((PTR)rfq_ferslv.name); break; } /* ** Handle the start of the UNION SELECT clause - ** it means that we're all done. However, unless the ** state is FIND_OPAREN, then we have an error which ** the subsequent identifier check will catch (failed ** for the identifier being a reserved word). Note ** that for it to be a valid identifier, it would have ** to be in quotes! */ if ((rfq_parse_state == FIND_OPAREN) && (STbcompare(rfq_ferslv.name, STlength(rfq_ferslv.name), ERx("union"), STlength(ERx("union")),TRUE) == 0)) { _VOID_ MEfree((PTR)rfq_ferslv.name); _VOID_ MEfree((PTR)qual); return(TRUE); } /* ** Keep skipping unless we're looking for an ** identifier. This will handle LOGICALS like ** AND, OR, etc., as well as right side expressions. */ if (rfq_parse_state != FIND_IDENT) { _VOID_ MEfree((PTR)rfq_ferslv.name); break; } rfq_ferslv.name_dest = &attname[0]; rfq_ferslv.owner_dest = &rvar[0]; rfq_ferslv.is_nrml = FALSE; FE_decompose(&rfq_ferslv); if ((IIUGdlm_ChkdlmBEobject(rfq_ferslv.name_dest, rfq_ferslv.name_dest, rfq_ferslv.is_nrml) == UI_BOGUS_ID) || ((rfq_ferslv.owner_spec) && (IIUGdlm_ChkdlmBEobject(rfq_ferslv.owner_dest, rfq_ferslv.owner_dest, rfq_ferslv.is_nrml) == UI_BOGUS_ID))) { rfq_error = TRUE; _VOID_ MEfree((PTR)rfq_ferslv.name); break; } if (En_SrcTyp == JDRepSrc) { if (!r_JDMaintAttrList(JD_ATT_GET_ATTR_NAME, &rvar[0],&attname[0], &ColName[0])) { /* ** Why doesn't this result in the fatal error ** that a parse failure would? The 6.4 version ** would actually fail here if a UNION SELECT ** was present and return - rFdisplay() does ** not check the return code. Since we now ** handle the end of the WHERE clause in a more ** sane manner, maybe this should be a fatal ** error ... */ _VOID_ MEfree((PTR)rfq_ferslv.name); _VOID_ MEfree((PTR)qual); return(FALSE); } STcopy(&ColName[0],&attname[0]); } ord = r_mtch_att(&attname[0]); if (ord < 0) { /* Bad attribute name */ IIUGerr(E_RF003A_rFqur_set__Bad_attrib, UG_ERR_FATAL,1,&attname[0]); } /* ** Set the column options of the attribute. We assume ** its a value until/unless we find a range indicator. */ copt = rFgt_copt(ord); copt->copt_select = 'v'; rfq_parse_state = FIND_GREATER; _VOID_ MEfree((PTR)rfq_ferslv.name); break; case(TK_OPAREN): CMnext(Tokchar); /* Skip the paren */ if (rfq_parse_state == FIND_OPAREN) { rfq_parse_state = FIND_IDENT; break; } /* ** Ignore open parens unless we're specifically ** looking for them. This handles instances of ** min(), max(), etc. */ break; case(TK_CPAREN): CMnext(Tokchar); /* Skip the paren */ if ((rfq_parse_state == FIND_CPAREN) && (copt != (COPT *)NULL) && (copt->copt_select == 'r')) { rfq_parse_state = FIND_2CPAREN; copt = (COPT *)NULL; break; } if (rfq_parse_state == FIND_2CPAREN) { rfq_parse_state = FIND_OPAREN; break; } /* ** Ignore closing parens unless we're specifically ** looking for them. This also handles instances of ** min(), max(), etc. */ break; case(TK_EQUALS): case(TK_RELOP): CMnext(Tokchar); /* Skip the relation operator */ /* ** Handle '!=', '>=', '<=' compound operators */ if (*Tokchar == '=') { CMnext(Tokchar); } if (rfq_parse_state == FIND_GREATER) { if (type == TK_RELOP) { /* Must be a range of values */ copt->copt_select = 'r'; rfq_parse_state = FIND_CPAREN; } else { rfq_parse_state = FIND_OPAREN; } } break; case(TK_SQUOTE): CMnext(Tokchar); /* ** Handle single quoted string values atomically so ** we don't get confused by their containing parens, ** etc. */ _VOID_ MEfree((PTR)r_g_string(TK_SQUOTE)); break; case(TK_DOLLAR): CMnext(Tokchar); /* ** Handle variables independently from identifiers so ** we don't get confused by something like '$like'. ** Additionally, allow compound constructs so we don't ** get confused by something like "$abc.columnname". ** Note that this compound construct should only result ** from user modifications, and is detrimental only ** when the state is FIND_IDENT - we won't assign any ** ColumnOptions to columnname. */ _VOID_ MEfree((PTR)r_g_ident(TRUE)); break; default: /* ** We should only really be here if we see the start ** of a comment ... */ chk_char = *Tokchar; CMnext(Tokchar); if ((chk_char == '/') && (*Tokchar == '*')) { /* ** Note the implication that a comment may not ** "interrupt" the WHERE clause. If we ** allowed one to, then we'd have to add ** comment recognition to the entire parse ** loop to avoid being confused! */ _VOID_ MEfree((PTR)qual); return(TRUE); } break; } } if ((rfq_error) || (rfq_parse_state != FIND_OPAREN)) { IIUGerr(E_RF003B_rFqur_set__Bad_where_,UG_ERR_FATAL,0); } _VOID_ MEfree((PTR)qual); return(TRUE); }