DB_STATUS adi_ficoerce( ADF_CB *adf_scb, DB_DT_ID adi_from_did, DB_DT_ID adi_into_did, ADI_FI_ID *adi_fid) { DB_DT_ID from_bdt = abs(adi_from_did); DB_DT_ID into_bdt = abs(adi_into_did); DB_DT_ID minto_bdt; DB_DT_ID mfrom_bdt; ADI_DATATYPE *dt; ADI_COERC_ENT *cent; i4 found = FALSE; mfrom_bdt = ADI_DT_MAP_MACRO(from_bdt); minto_bdt = ADI_DT_MAP_MACRO(into_bdt); for (;;) { /* Check the validity of the datatype ids */ if ( (mfrom_bdt <= 0 || mfrom_bdt > ADI_MXDTS) || (minto_bdt <= 0 || minto_bdt > ADI_MXDTS) || Adf_globs->Adi_dtptrs[minto_bdt] == NULL || (dt = Adf_globs->Adi_dtptrs[mfrom_bdt]) == NULL ) { return (adu_error(adf_scb, E_AD2004_BAD_DTID, 0)); } /* First check the datatypes table to see if a coercion exists */ if (!BTtest((i4) minto_bdt, adf_scb->adf_qlang == DB_SQL ? (char *) &dt->adi_dtcoerce_sql : (char *) &dt->adi_dtcoerce_quel)) return (adu_error(adf_scb, E_AD2009_NOCOERCION, 0)); /* Search for the appropriate function instance id */ for (cent = dt->adi_coerc_ents; cent->adi_from_dt == from_bdt; cent++) { if (cent->adi_into_dt == into_bdt) { *adi_fid = cent->adi_fid_coerc; found = TRUE; break; } } break; } /* end of for(;;) stmt */ if (!found) return (adu_error(adf_scb, E_AD2009_NOCOERCION, 0)); else return (E_DB_OK); }
DB_STATUS adc_getempty( ADF_CB *adf_scb, DB_DATA_VALUE *adc_emptydv) /* Ptr to empty/null data value */ { i4 bdt = abs((i4) adc_emptydv->db_datatype); i4 bdtv; DB_STATUS db_stat; /* Does the datatype exist? */ bdtv = ADI_DT_MAP_MACRO(bdt); if (bdtv <= 0 || bdtv > ADI_MXDTS || Adf_globs->Adi_dtptrs[bdtv] == NULL) return(adu_error(adf_scb, E_AD2004_BAD_DTID, 0)); /* ** If datatype is non-nullable, call the function associated with this ** datatype to initialize a data value to be "empty". Currently, this is ** only one function for the RTI known datatypes. This level of indirection ** is provided for the implementation of user-defined datatypes in the ** future. ** ** If datatype is nullable, we can set the null value right here since it ** will be done the same way for all nullable datatypes. */ if (adc_emptydv->db_datatype > 0) /* non-nullable */ { db_stat = (*Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]-> adi_dt_com_vect.adp_getempty_addr) (adf_scb, adc_emptydv); } else { ADF_SETNULL_MACRO(adc_emptydv); /* ** If the datatype is peripheral, then we clear its length as ** well. This is because ADF guarantees that the lengths are ** always correct for peripheral datatypes */ if (Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]-> adi_dtstat_bits & AD_PERIPHERAL) { ((ADP_PERIPHERAL *) adc_emptydv->db_data)->per_length0 = 0; ((ADP_PERIPHERAL *) adc_emptydv->db_data)->per_length1 = 0; ((ADP_PERIPHERAL *) adc_emptydv->db_data)->per_tag = ADP_P_COUPON; } db_stat = E_DB_OK; } return(db_stat); }
DB_STATUS adi_per_under( ADF_CB *adf_scb, DB_DT_ID dtid, DB_DATA_VALUE *under_dv) { DB_STATUS status; DB_DT_ID mapped_id; ADP_POP_CB pop_cb; for (;;) { mapped_id = ADI_DT_MAP_MACRO(abs(dtid)); if ( mapped_id <= 0 || mapped_id > ADI_MXDTS || Adf_globs->Adi_dtptrs[mapped_id] == NULL || !(Adf_globs->Adi_dtptrs[mapped_id]->adi_dtstat_bits & AD_PERIPHERAL) || Adf_globs->Adi_dtptrs[mapped_id]->adi_under_dt == 0) { status = adu_error(adf_scb, E_AD2004_BAD_DTID, 0); break; } under_dv->db_prec = 0; under_dv->db_length = 0; under_dv->db_datatype = Adf_globs->Adi_dtptrs[mapped_id]->adi_under_dt; if (Adf_globs->Adi_fexi[ADI_01PERIPH_FEXI].adi_fcn_fexi == NULL) { status = adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0); break; } pop_cb.pop_type = (ADP_POP_TYPE); pop_cb.pop_length = sizeof(ADP_POP_CB); pop_cb.pop_ascii_id = ADP_POP_ASCII_ID; pop_cb.pop_underdv = under_dv; status = (*Adf_globs->Adi_fexi[ADI_01PERIPH_FEXI].adi_fcn_fexi) (ADP_INFORMATION, &pop_cb); if (status) { status = adu_error(adf_scb, E_AD7000_ADP_BAD_INFO, 0); break; } status = adc_seglen(adf_scb, dtid, under_dv); break; } return(status); }
DB_STATUS adi_dtinfo( ADF_CB *adf_scb, DB_DT_ID dtid, i4 *dtinfo) { dtid = abs(dtid); dtid = ADI_DT_MAP_MACRO(dtid); if ( dtid <= 0 || dtid > ADI_MXDTS || Adf_globs->Adi_dtptrs[dtid] == NULL ) return(adu_error(adf_scb, E_AD2004_BAD_DTID, 0)); *dtinfo = Adf_globs->Adi_dtptrs[dtid]->adi_dtstat_bits; return(E_DB_OK); }
DB_STATUS adu_hash( ADF_CB *adf_scb, DB_DATA_VALUE *dv1, DB_DATA_VALUE *rdv) { i4 in_len; i4 res_len; char *tmp; u_i4 *out_p = ((u_i4 *)rdv->db_data); DB_STATUS db_stat; /* Don't support long data types */ if ( Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(dv1->db_datatype)]-> adi_dtstat_bits & AD_PERIPHERAL ) return (adu_error(adf_scb, E_AD2090_BAD_DT_FOR_STRFUNC, 0)); switch (dv1->db_datatype) { /* call lenaddr for the stringish types - it gets varying length ** lengths, among other things. */ case DB_CHA_TYPE: case DB_CHR_TYPE: case DB_BYTE_TYPE: case DB_VCH_TYPE: case DB_TXT_TYPE: case DB_LTXT_TYPE: case DB_VBYTE_TYPE: case DB_NCHR_TYPE: case DB_NVCHR_TYPE: if (db_stat = adu_lenaddr(adf_scb, dv1, &in_len, &tmp)) return(db_stat); break; default: /* all the others */ in_len = dv1->db_length; /* fixed length */ tmp = dv1->db_data; break; } *out_p = -1; HSH_CRC32(tmp, in_len, out_p); return(E_DB_OK); }
/*{ ** Name: adu_rdm1_setup - Setup for Redeem an ADF_COUPON ** ** Description: ** This routine performs the initialization for the redeeming of ** a coupon. This amount primarily to initializing the ** ADP_LO_WKSP function instance private and shared (adw_fip & ** adw_shared, respectively). This routine also moves the ** appropriate peripheral header into the output area. ** ** Since this routine moves the peripheral header to the output ** area, in the case where the original call to this routine has ** insufficient space for the output header, this routine may be ** called more than once. We note this since it is "unusual" for ** the initialization routine to be called more than one time for ** an object. In the case where the original space is of ** insufficent size, then this routine will return an indication ** that the output area is full, and will move nothing into it. ** Thus, this routine considers it a call-protocol error to be ** called a second time with insufficient space. ** ** Inputs: ** adf_scb The session's control block (ptr). ** result_dv Pointer to DB_DATA_VALUE for ** result. ** coupon_dv Pointer to DB_DATA_VALUE ** describing the input coupon to ** be redeemed. ** workspace_dv Pointer to DB_DATA_VALUE ** describing redeem's workspace. ** continuation Continuation indicator. 0 ** indicates the first call, else ** not the first call. ** ** Outputs: ** adf_scb->adf_error Filled as appropriate. ** *result_dv->db_data Setup with beginning of peripheral ** data type. ** *workspace_dv->db_data Initialized for ongoing redeem work. ** Returns: ** DB_STATUS ** Exceptions: ** None. ** ** Side Effects: ** None. ** ** History: ** 02-dec-1992 (fred) ** Coded. Created from adu_redeem prototype in support of ** OME large objects. ** 8-Apr-1993 (fred) ** Fixed bug in zero length large object handling. For large ** objects of zero length which are not nullable, the length ** should not include the null-value-byte. ** 12-Oct-1993 (fred) ** Removed call to ADP_INFORMATION -- subsumed by ** adi_per_under(). ** 10-sep-1998 (schte01) ** Modified I4ASSIGN for axp_osf to pass the value, not the address ** of the value, to be assigned. This worked under the -oldc ** compiler option and got compile errors under -newc. ** 28-jul-1999 (thaju02) ** If the coupon stipulates that the data is not null, then ** the minimum result buffer length must be large enough to ** hold one byte of data along with all necessary info ** (ADP_HDR_SIZE + nextsegmarker(i4) + 2byteseglenindicator ** + 1byteofdata). Given a buffer with only 18 bytes of space ** available, 12 bytes are filled with peripheral header info ** in adu_rdm1_setup and 4 bytes are filled with the next ** segment marker in adu_redeem. In adc_lvch_xform, the 2 ** byte segment length indicator is initially set to zero ** in the result buffer. If there is no space left in the ** result buffer for segment data, we flush the buffer. In ** the front end, upon receiving this result buffer, the ** next segment marker indicates that there is data following, ** yet the length is zero; terminal monitor infinitely loops. ** (b98104) ** 12-aug-99 (stial01) ** adu_rdm1_setup() 'blob_work' arg to adi_per_under should be ** NULL before redeem. ** 24-may-2000 (stial01) ** adu_rdm1_setup() clear null indicator if not null (B101656) ** [@history_template@]... */ DB_STATUS static adu_rdm1_setup(ADF_CB *adf_scb, DB_DATA_VALUE *result_dv, DB_DATA_VALUE *coupon_dv, ADP_LO_WKSP *work, i4 for_gca) { DB_STATUS status; ADP_PERIPHERAL *p = (ADP_PERIPHERAL *) result_dv->db_data; DB_DT_ID dtid = ADI_DT_MAP_MACRO(abs(result_dv->db_datatype)); i4 min_size; bool isnull = 0; if (coupon_dv->db_datatype < 0) work->adw_fip.fip_null_bytes = 1; else work->adw_fip.fip_null_bytes = 0; if (ult_check_macro(&Adf_globs->Adf_trvect, ADF_011_RDM_TO_V_STYLE, &dummy1, &dummy2)) { work->adw_fip.fip_test_mode = 1; work->adw_fip.fip_test_length = ADP_TST_VLENGTH + work->adw_fip.fip_null_bytes; work->adw_fip.fip_test_sent = 0; } else { work->adw_fip.fip_test_mode = 0; } work->adw_shared.shd_exp_action = ADW_START; work->adw_fip.fip_done = FALSE; /* ** Fool the main routine into getting us an input segment. Make ** look like the input segement is all used up. */ work->adw_shared.shd_type = coupon_dv->db_datatype; work->adw_shared.shd_i_area = (char *) 0; work->adw_shared.shd_i_used = work->adw_shared.shd_i_length = 0; work->adw_shared.shd_o_used = ADP_HDR_SIZE; work->adw_shared.shd_o_length = result_dv->db_length; work->adw_shared.shd_o_area = (char *) result_dv->db_data; if (work->adw_shared.shd_o_length > MAXI2) { TRdisplay("adu_rdm1_setup shd_o_length %d MAX %d\n", work->adw_shared.shd_o_length, MAXI2); return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0)); } work->adw_shared.shd_l0_check = work->adw_shared.shd_l1_check = 0; work->adw_fip.fip_pop_cb.pop_continuation = ADP_C_BEGIN_MASK; work->adw_fip.fip_pop_cb.pop_user_arg = (PTR) 0; work->adw_fip.fip_pop_cb.pop_type = (ADP_POP_TYPE); work->adw_fip.fip_pop_cb.pop_length = sizeof(ADP_POP_CB); work->adw_fip.fip_pop_cb.pop_ascii_id = ADP_POP_ASCII_ID; work->adw_fip.fip_pop_cb.pop_temporary = ADP_POP_PERMANENT; work->adw_fip.fip_pop_cb.pop_coupon = coupon_dv; work->adw_fip.fip_pop_cb.pop_segment = &work->adw_fip.fip_seg_dv; work->adw_fip.fip_pop_cb.pop_underdv = &work->adw_fip.fip_under_dv; status = adi_per_under(adf_scb, result_dv->db_datatype, &work->adw_fip.fip_under_dv); if (status) { return(adu_error(adf_scb, E_AD7000_ADP_BAD_INFO, 0)); } STRUCT_ASSIGN_MACRO(work->adw_fip.fip_under_dv, work->adw_fip.fip_seg_dv); work->adw_fip.fip_seg_dv.db_data = (char *) ((char *) work + sizeof(ADP_LO_WKSP)); if (ADI_ISNULL_MACRO(coupon_dv) || ((((ADP_PERIPHERAL *)coupon_dv->db_data)->per_length0 == 0) && (((ADP_PERIPHERAL *) coupon_dv->db_data)->per_length1 == 0))) isnull = 1; if (isnull) /* hdr + segment indicator + sizeof(null byte) */ min_size = ADP_HDR_SIZE + sizeof(i4) + work->adw_fip.fip_null_bytes; else /* hdr + segment indicator + segment length + segment single byte */ min_size = ADP_HDR_SIZE + sizeof(i4) + sizeof(i2) + sizeof(char); if (result_dv->db_length >= min_size) { if (for_gca) work->adw_shared.shd_out_tag = ADP_P_GCA; else work->adw_shared.shd_out_tag = ADP_P_DATA; I4ASSIGN_MACRO(work->adw_shared.shd_out_tag, p->per_tag); work->adw_shared.shd_out_segmented = (work->adw_shared.shd_out_tag != ADP_P_DATA); I4ASSIGN_MACRO( ((ADP_PERIPHERAL *) coupon_dv->db_data)->per_tag, work->adw_shared.shd_inp_tag); work->adw_shared.shd_inp_segmented = (work->adw_shared.shd_inp_tag != ADP_P_DATA); I4ASSIGN_MACRO( ((ADP_PERIPHERAL *) coupon_dv->db_data)->per_length0, p->per_length0); I4ASSIGN_MACRO(p->per_length0, work->adw_fip.fip_l0_value); I4ASSIGN_MACRO(((ADP_PERIPHERAL *) coupon_dv->db_data)->per_length1, p->per_length1); I4ASSIGN_MACRO(p->per_length1, work->adw_fip.fip_l1_value); work->adw_fip.fip_state = ADW_F_RUNNING; } else if (work->adw_fip.fip_state != ADW_F_STARTING) { work->adw_fip.fip_state = ADW_F_STARTING; result_dv->db_length = 0; adf_scb->adf_errcb.ad_errcode = E_AD0002_INCOMPLETE; return(E_DB_INFO); } else { return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0)); } if (isnull) { if (work->adw_fip.fip_test_mode) { ((DB_TEXT_STRING *) p)->db_t_count = (i2) 0; if (result_dv->db_length >= (work->adw_fip.fip_test_length - work->adw_fip.fip_test_sent)) { result_dv->db_length = work->adw_fip.fip_test_length - work->adw_fip.fip_test_sent; work->adw_fip.fip_test_sent = work->adw_fip.fip_test_length; } else { work->adw_fip.fip_state = ADW_F_DONE_NEED_NULL; work->adw_fip.fip_test_sent += result_dv->db_length; adf_scb->adf_errcb.ad_errcode = E_AD0002_INCOMPLETE; return(E_DB_INFO); } } else { i4 zero = 0; /* ** Insert GCA mark that says there is no segment. */ #if defined(axp_osf) || defined(ris_u64) || defined(LP64) || \ defined(axp_lnx) /* ** We want to init the GCA field after the header, but ** on axp_osf this is not the same as the start of the ** coupon, because 8-byte alignment causes a slack 4-byte ** integer to be between the header and the coupon. See ** adu_redeem above for a different way this field is set ** to 1 when we have real data (not null). The addressing ** of this field should really be standardized in such a ** way that contiguous layout of 4-byte aligned fields is ** not assumed. */ I4ASSIGN_MACRO(zero,*((char *)p + ADP_HDR_SIZE)); #endif I4ASSIGN_MACRO(zero, p->per_value); result_dv->db_length = ADP_NULL_PERIPH_SIZE; if (work->adw_shared.shd_type > 0) result_dv->db_length -= 1; } if (ADI_ISNULL_MACRO(coupon_dv)) ADF_SETNULL_MACRO(result_dv); else ADF_CLRNULL_MACRO(result_dv); adf_scb->adf_errcb.ad_errcode = E_DB_OK; work->adw_fip.fip_done = TRUE; return(E_DB_OK); } if (work->adw_fip.fip_test_mode) { i4 segment_count; i4 length1; i2 count; I4ASSIGN_MACRO(p->per_length1, length1); I4ASSIGN_MACRO(p->per_length0, segment_count); if (!segment_count) segment_count = ADP_TST_SEG_CNT; count = min( ADP_TST_VLENGTH, (i2) (length1 + (segment_count * (sizeof(i4) + sizeof(i2))) + sizeof(i4) /* no more segments */ + work->adw_shared.shd_o_used) ) - sizeof(i2); I2ASSIGN_MACRO(count, ((DB_TEXT_STRING *) p)->db_t_count); } return(E_DB_OK); }
/* ** { ** Name: adu_redeem - Redeem an ADF_COUPON ** ** Description: ** This routine redeems an ADF_COUPON, i.e. it materializes the object ** represented by the coupon. Since objects represented by coupons ** may not fit in memory, this routine must deal with returning partial ** results. In such cases, it will store its partial status in its fourth ** argument, which is to be returned for each call. ** ** Inputs: ** adf_scb Standard ADF session control block ** result_dv Ptr to DB_DATA_VALUE into which to ** place the result. ** coupon_dv Ptr to DB_DATA_VALUE which contains ** the input to redeem. ** workspace_dv Ptr to DB_DATA_VALUE which points to ** the workspace. This workspace is ** expected to be maintained across ** calls to this routine for any given ** coupon. (I.e. it can be "new" only ** when "continuation" (next param) is ** zero. ** continuation Is this a continuation of a previous ** call. ** ** Outputs: ** adf_scb->adf_errcb Filled as appropriate. ** result_dv->db_length Filled with the length of the result ** area actually used. ** *workspace->db_data Filled with info to be used by ** subsequent invocations of this routine. ** Returns: ** E_DB_ERROR In case of error ** E_DB_INFO/E_AD0002_INCOMPLETE ** When more calls are necessary ** E_DB_OK When complete. ** ** Exceptions: ** None. ** ** Side Effects: ** None. ** ** History: ** 07-dec-1989 (fred) ** Prototyped. ** 06-oct-1992 (fred) ** Altered to work with timezone integration. As a temporary measure, ** this routine was using the ADF_CB.adf_4rsvd field to store ** some context across calls. In that this field disappeared, a new, ** more appropriately named field was added (adf_lo_context). This ** new ADF_CB field is now used in this file. ** 30-Oct-1992 (fred) ** Fixed to correctly handle being called with a length too short ** for the original header. ** 20-Nov-1992 (fred) ** Rewritten for better clarity & better delineation of ** function in support of OME large objects. ** 18-Oct-1993 (fred) ** Moved check for FEXI function so that STAR, which has ** none, can send null blobs sometimes. It helps get a tiny ** bit of support in to STAR. ** 13-Apr-1994 (fred) ** Altered to hand status from FEXI call straight back. By ** not losing the actual status, interrupts may avoid logging ** too much stuff. ** 14-Sep-1995 (shust01/thaju02) ** fixed problem of endless loop when we are finished, but we ** come in just to get the NULL byte. work->adw_shared.shd_o_used ** had old size (which was max value), so we never end. Set ** work->adw_shared.shd_o_used = 0. ** 24-Oct-2001 (thaju02) ** If adc_lvch_xform() was unable to fit the 2-byte segment ** length in the result buffer, decrement result length ** with unused byte and flush segment. (B104122) [@history_template@]... */ DB_STATUS adu_redeem( ADF_CB *adf_scb, DB_DATA_VALUE *result_dv, DB_DATA_VALUE *coupon_dv, DB_DATA_VALUE *workspace_dv, i4 continuation) { ADP_LO_WKSP *work = (ADP_LO_WKSP *) workspace_dv->db_data; DB_DT_ID dtid; ADP_PERIPHERAL *p = (ADP_PERIPHERAL *) result_dv->db_data; DB_STATUS status; i4 done = FALSE; i4 flush; i4 for_gca = 1; i4 loop_around; if (result_dv->db_datatype != coupon_dv->db_datatype) return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0)); dtid = ADI_DT_MAP_MACRO(abs(result_dv->db_datatype)); if ( dtid <= 0 || dtid > ADI_MXDTS || Adf_globs->Adi_dtptrs[dtid] == NULL || !Adf_globs->Adi_dtptrs[dtid]->adi_under_dt ) return(adu_error(adf_scb, E_AD2004_BAD_DTID, 0)); if ((!continuation) || (work->adw_fip.fip_state == ADW_F_STARTING)) { if (!continuation) work->adw_fip.fip_state = ADW_F_INITIAL; status = adu_rdm1_setup(adf_scb, result_dv, coupon_dv, work, for_gca); if (status || work->adw_fip.fip_done) return(status); } else if (work->adw_fip.fip_state == ADW_F_DONE_NEED_NULL) { /* ** This is an indication that we finished, but didn't ** send the NULL byte, and must do so now... */ work->adw_shared.shd_o_used = 0; status = adu_rdm2_finish(adf_scb, result_dv, coupon_dv, work, for_gca); return(status); } else { if (Adf_globs->Adi_fexi[ADI_01PERIPH_FEXI].adi_fcn_fexi == NULL) return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0)); work->adw_shared.shd_o_used = 0; work->adw_shared.shd_o_length = result_dv->db_length; work->adw_shared.shd_o_area = (char *) result_dv->db_data; work->adw_fip.fip_pop_cb.pop_continuation = 0; work->adw_fip.fip_pop_cb.pop_coupon = coupon_dv; } for (flush = 0; !done && (!flush) && (work->adw_shared.shd_l1_check < work->adw_fip.fip_l1_value); /* No update action */) { switch (work->adw_shared.shd_exp_action) { case ADW_FLUSH_SEGMENT: case ADW_START: if (for_gca) { /* ** Since we got a segment back, insert the `here ** comes another segment indicator'. */ i4 one = 1; if ( (work->adw_shared.shd_o_length - work->adw_shared.shd_o_used) < sizeof(one)) { /* Then the next segment marker won't fit. Dump */ /* the current segment and move on... */ /* fix_me -- better error... */ return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0)); } I4ASSIGN_MACRO(one, work->adw_shared.shd_o_area[work->adw_shared.shd_o_used]); work->adw_shared.shd_o_used += sizeof(one); } /* Fall thru -- if out of input data, get some */ case ADW_FLSH_SEG_NOFIT_LIND: case ADW_NEXT_SEGMENT: if ( (work->adw_shared.shd_exp_action == ADW_NEXT_SEGMENT) && (work->adw_shared.shd_inp_tag == ADP_P_COUPON)) { /* ** For [DBMS style] coupons, each segment is in a row ** unto itself, regardless of the length of the row. ** Since this routine is datatype independent, it ** cannot tell when a segment is up, and thus must ** rely on the called routine. Thus, if the callee ** asks for a new segment when processing a DBMS ** coupon, this routine will assume that the current ** set of data has been all used up... */ work->adw_shared.shd_i_used = work->adw_shared.shd_i_length; } /* Fall thru... */ case ADW_GET_DATA: if (work->adw_shared.shd_i_used == work->adw_shared.shd_i_length) { /* ** If no unmoved segment data, then get some more. */ if (work->adw_fip.fip_done) { done = TRUE; status = E_DB_OK; } else { status = (*Adf_globs->Adi_fexi[ADI_01PERIPH_FEXI].adi_fcn_fexi) (ADP_GET, &work->adw_fip.fip_pop_cb); if (status) { if (work->adw_fip.fip_pop_cb.pop_error.err_code == E_AD7001_ADP_NONEXT) { work->adw_fip.fip_done = TRUE; if (status == E_DB_WARN) status = E_DB_OK; else break; } else { return(adu_error(adf_scb, work->adw_fip.fip_pop_cb.pop_error.err_code, 0)); } } work->adw_shared.shd_i_used = 0; work->adw_shared.shd_i_length = work->adw_fip.fip_seg_dv.db_length; work->adw_shared.shd_i_area = work->adw_fip.fip_seg_dv.db_data; } } break; case ADW_CONTINUE: /* This shouldn't happen */ default: /* Nor should anything else */ return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0)); break; } if (done) break; status = adc_xform(adf_scb, (PTR)work); if (DB_FAILURE_MACRO(status)) { return(adu_error(adf_scb, E_AD7003_ADP_BAD_RECON, 0)); } if (work->adw_shared.shd_exp_action == ADW_FLUSH_SEGMENT) { flush = 1; } /* B104122 */ if (work->adw_shared.shd_exp_action == ADW_FLSH_SEG_NOFIT_LIND) { result_dv->db_length = work->adw_shared.shd_o_used; flush = 1; } /* B?????? */ if (work->adw_shared.shd_exp_action == ADW_FLUSH_INCOMPLETE_SEGMENT) { result_dv->db_length = work->adw_shared.shd_o_used; work->adw_shared.shd_exp_action = ADW_FLUSH_SEGMENT; flush = 1; } work->adw_fip.fip_pop_cb.pop_continuation = 0; } if (work->adw_shared.shd_l1_check == work->adw_fip.fip_l1_value) { done = TRUE; } if (work->adw_fip.fip_test_mode) { work->adw_fip.fip_test_sent += work->adw_shared.shd_o_used; if ((work->adw_fip.fip_test_length - work->adw_fip.fip_test_sent - work->adw_fip.fip_null_bytes - (for_gca * sizeof(i4))) <= 0) { /* ** Then, for test purposes, we've sent all that we can. ** Emulate completion. */ work->adw_fip.fip_done = done = TRUE; work->adw_shared.shd_i_used = work->adw_shared.shd_i_length; work->adw_shared.shd_l1_check = work->adw_fip.fip_l1_value; work->adw_shared.shd_o_used = work->adw_fip.fip_test_length - work->adw_fip.fip_test_sent - sizeof(i4) /* end marker */ - work->adw_fip.fip_null_bytes; /* null indicator */ work->adw_fip.fip_test_sent = work->adw_fip.fip_test_length - sizeof(i4) - work->adw_fip.fip_null_bytes; } } if (done && ((work->adw_shared.shd_exp_action == ADW_NEXT_SEGMENT) || (work->adw_shared.shd_exp_action == ADW_FLUSH_SEGMENT))) { /* ** If we think we are done and have used all the input,... */ status = adu_rdm2_finish(adf_scb, result_dv, coupon_dv, work, for_gca); } else { /* ** Otherwise, if we are surpassing the amount of data which ** be available... */ if (work->adw_shared.shd_l1_check > work->adw_fip.fip_l1_value) { /* ** FIX_ME -- better error message... ** Then we would be sending an inconsistent blob. ** That would be bad. */ return(adu_error(adf_scb, E_AD7004_ADP_BAD_BLOB,0)); } adf_scb->adf_errcb.ad_errcode = E_AD0002_INCOMPLETE; status = E_DB_INFO; } return(status); }
/*{ ** Name: adc_1dbtoev_ingres - Dbtoev for Ingres datatypes ** ** Description: ** This routine, given an input datatype, determines which type to send to ** output. It is assumed that a coercion exists for this datatype ** transformation. ** ** If the datatype is exportable (AD_NOEXPORT is not set), then the result ** datatype is identical with the input. Otherwise, a call is made to the ** dbtoev routine specified in the datatype com vector. ** ** If the input is nullable, then the output is nullable as well. ** ** Inputs: ** adf_scb Pointer to an ADF session control block. ** .adf_errcb ADF_ERROR struct. ** .ad_ebuflen The length, in bytes, of the buffer ** pointed to by ad_errmsgp. ** .ad_errmsgp Pointer to a buffer to put formatted ** error message in, if necessary. ** db_value Ptr to db_data_value for database ** type/prec/length ** ev_value Pointer to DB_DATA_VALUE for exported type ** ** Outputs: ** adf_scb Pointer to an ADF session control block. ** .adf_errcb ADF_ERROR struct. If an ** error occurs the following fields will ** be set. NOTE: if .ad_ebuflen = 0 or ** .ad_errmsgp = NULL, no error message ** will be formatted. ** .ad_errcode ADF error code for the error. ** .ad_errclass Signifies the ADF error class. ** .ad_usererr If .ad_errclass is ADF_USER_ERROR, ** this field is set to the corresponding ** user error which will either map to ** an ADF error code or a user-error code. ** .ad_emsglen The length, in bytes, of the resulting ** formatted error message. ** .adf_errmsgp Pointer to the formatted error message. ** *ev_value Filled appropriately. ** ** Returns: ** The following DB_STATUS codes may be returned: ** E_DB_OK, E_DB_WARN, E_DB_ERROR, E_DB_SEVERE, E_DB_FATAL ** ** If a DB_STATUS code other than E_DB_OK is returned, the caller ** can look in the field adf_scb.adf_errcb.ad_errcode to determine ** the ADF error code. The following is a list of possible ADF error ** codes that can be returned by this routine: ** ** E_AD0000_OK Operation succeeded. ** E_AD2004_BAD_DTID Datatype id unknown to ADF. ** ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 09-apr-93 (fred) ** Created. ** 12-Jul-1993 (fred) ** For the bit datatypes, since they are being output as ** varchar, we need to increase the size of the ** aforementioned varchar element by DB_CNTSIZE. This is ** necessary since the number of characters needed is given ** by adu_bitsize, but we need space for the count. [@history_template@]... */ DB_STATUS adc_1dbtoev_ingres( ADF_CB *adf_scb, DB_DATA_VALUE *db_value, DB_DATA_VALUE *ev_value) { DB_DT_ID bdt = abs(db_value->db_datatype); DB_DT_ID bdtv; DB_STATUS status = E_DB_OK; DB_DATA_VALUE local_dv; i4 must_coerce; must_coerce = Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]->adi_dtstat_bits & AD_NOEXPORT; bdtv = ADI_DT_MAP_MACRO(bdt); switch (bdt) { case DB_BYTE_TYPE: ev_value->db_length = db_value->db_length; ev_value->db_datatype = db_value->db_datatype; ev_value->db_prec = db_value->db_prec; ev_value->db_collID = db_value->db_collID; if ( (must_coerce) ||( ((adf_scb->adf_proto_level & AD_BYTE_PROTO) == 0) && (Adf_globs->Adi_dtptrs[bdtv]->adi_dtstat_bits & AD_CONDEXPORT) ) ) { ev_value->db_datatype = DB_CHA_TYPE; } break; case DB_VBYTE_TYPE: STRUCT_ASSIGN_MACRO(*db_value, *ev_value); ev_value->db_length = db_value->db_length; ev_value->db_datatype = db_value->db_datatype; ev_value->db_prec = db_value->db_prec; ev_value->db_collID = db_value->db_collID; if ( (must_coerce) ||( ((adf_scb->adf_proto_level & AD_BYTE_PROTO) == 0) && (Adf_globs->Adi_dtptrs[bdtv]->adi_dtstat_bits & AD_CONDEXPORT) ) ) { ev_value->db_datatype = DB_VCH_TYPE; } break; case DB_LBYTE_TYPE: ev_value->db_length = db_value->db_length; ev_value->db_datatype = db_value->db_datatype; ev_value->db_prec = db_value->db_prec; ev_value->db_collID = db_value->db_collID; if ( (must_coerce) ||( ((adf_scb->adf_proto_level & AD_BYTE_PROTO) == 0) && (Adf_globs->Adi_dtptrs[bdtv]->adi_dtstat_bits & AD_CONDEXPORT) ) ) { ev_value->db_datatype = DB_LVCH_TYPE; } break; case DB_BIT_TYPE: case DB_VBIT_TYPE: ev_value->db_length = db_value->db_length; ev_value->db_datatype = db_value->db_datatype; ev_value->db_prec = db_value->db_prec; ev_value->db_collID = db_value->db_collID; if ( (must_coerce) ||( ((adf_scb->adf_proto_level & AD_BIT_PROTO) == 0) && (Adf_globs->Adi_dtptrs[bdtv]->adi_dtstat_bits & AD_CONDEXPORT) ) ) { ev_value->db_datatype = DB_VCH_TYPE; /* send them back as varchar, size appropriate to datatype */ local_dv.db_datatype = DB_INT_TYPE; local_dv.db_length = sizeof(ev_value->db_length); local_dv.db_prec = 0; local_dv.db_data = (char *) &ev_value->db_length; status = adu_bitsize(adf_scb, db_value, &local_dv); ev_value->db_length += DB_CNTSIZE; } break; default: status = adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0); break; } return(status); }
/*{ ** Name: adc_dbtoev - Determine which type to export ** ** Description: ** This routine, given an input datatype, determines which type to send to ** output. It is assumed that a coercion exists for this datatype ** transformation. ** ** If the datatype is exportable (AD_NOEXPORT is not set), then the result ** datatype is identical with the input. Otherwise, a call is made to the ** dbtoev routine specified in the datatype com vector. ** ** If the input is nullable, then the output is nullable as well. ** ** Inputs: ** adf_scb Pointer to an ADF session control block. ** .adf_errcb ADF_ERROR struct. ** .ad_ebuflen The length, in bytes, of the buffer ** pointed to by ad_errmsgp. ** .ad_errmsgp Pointer to a buffer to put formatted ** error message in, if necessary. ** db_value Ptr to db_data_value for database ** type/prec/length ** ev_value Pointer to DB_DATA_VALUE for exported type ** ** Outputs: ** adf_scb Pointer to an ADF session control block. ** .adf_errcb ADF_ERROR struct. If an ** error occurs the following fields will ** be set. NOTE: if .ad_ebuflen = 0 or ** .ad_errmsgp = NULL, no error message ** will be formatted. ** .ad_errcode ADF error code for the error. ** .ad_errclass Signifies the ADF error class. ** .ad_usererr If .ad_errclass is ADF_USER_ERROR, ** this field is set to the corresponding ** user error which will either map to ** an ADF error code or a user-error code. ** .ad_emsglen The length, in bytes, of the resulting ** formatted error message. ** .adf_errmsgp Pointer to the formatted error message. ** *ev_value Filled appropriately. ** ** Returns: ** The following DB_STATUS codes may be returned: ** E_DB_OK, E_DB_WARN, E_DB_ERROR, E_DB_SEVERE, E_DB_FATAL ** ** If a DB_STATUS code other than E_DB_OK is returned, the caller ** can look in the field adf_scb.adf_errcb.ad_errcode to determine ** the ADF error code. The following is a list of possible ADF error ** codes that can be returned by this routine: ** ** E_AD0000_OK Operation succeeded. ** E_AD2004_BAD_DTID Datatype id unknown to ADF. ** ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 07-apr-89 (fred) ** Created. ** 11-jul-89 (jrb) ** Removed unused variables. ** 29-oct-1992 (stevet) ** Added check for protocol level support to see if decimal data ** can be exported. [@history_template@]... */ DB_STATUS adc_dbtoev( ADF_CB *adf_scb, DB_DATA_VALUE *db_value, DB_DATA_VALUE *ev_value) { DB_DT_ID bdt = abs(db_value->db_datatype); DB_DT_ID bdtv; DB_STATUS status = E_DB_OK; bdtv = ADI_DT_MAP_MACRO(bdt); if ( bdtv <= 0 || bdtv > ADI_MXDTS || Adf_globs->Adi_dtptrs[bdtv] == NULL ) return(adu_error(adf_scb, E_AD2004_BAD_DTID, 0)); if (Adf_globs->Adi_dtptrs[bdtv]->adi_dtstat_bits & (AD_NOEXPORT | AD_CONDEXPORT)) { if( bdt == DB_DEC_TYPE) { if(adf_scb->adf_proto_level & AD_DECIMAL_PROTO) { ev_value->db_datatype = db_value->db_datatype; ev_value->db_length = db_value->db_length; ev_value->db_prec = db_value->db_prec; ev_value->db_collID = db_value->db_collID; } else return(adu_error(adf_scb, E_AD101A_DT_NOT_SUPPORTED, 2, (i4) sizeof(SystemProductName), (i4 *) &SystemProductName)); } else { if (Adf_globs->Adi_dtptrs[bdtv]->adi_dt_com_vect.adp_dbtoev_addr) { if (db_value->db_datatype >= 0) { status = (*Adf_globs->Adi_dtptrs[bdtv]-> adi_dt_com_vect.adp_dbtoev_addr) (adf_scb, db_value, ev_value); } else { DB_DATA_VALUE tmp_db; DB_DATA_VALUE tmp_ev; /* Datatype is nullable -- adjust length & datatype for */ /* underlying code */ tmp_db.db_length = db_value->db_length - 1; tmp_db.db_prec = db_value->db_prec; tmp_db.db_collID = db_value->db_collID; tmp_db.db_datatype = bdt; status = (*Adf_globs->Adi_dtptrs[bdtv]-> adi_dt_com_vect.adp_dbtoev_addr) (adf_scb, &tmp_db, &tmp_ev); ev_value->db_datatype = -(abs(tmp_ev.db_datatype)); ev_value->db_length = tmp_ev.db_length + 1; ev_value->db_prec = tmp_ev.db_prec; ev_value->db_prec = tmp_ev.db_collID; } } else { return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0)); } } } else { status = E_DB_WARN; STRUCT_ASSIGN_MACRO(*db_value, *ev_value); } return(status); }
DB_STATUS adi_cpficoerce( ADF_CB *adf_scb, DB_DT_ID adi_from_did, DB_DT_ID adi_into_did, ADI_FI_ID *adi_fid) { DB_DT_ID from_bdt = abs(adi_from_did); DB_DT_ID into_bdt = abs(adi_into_did); ADI_FI_DESC *fi_desc_ptr; i4 found = FALSE; DB_STATUS db_stat; DB_DT_ID minto_bdt; DB_DT_ID mfrom_bdt; mfrom_bdt = ADI_DT_MAP_MACRO(from_bdt); minto_bdt = ADI_DT_MAP_MACRO(into_bdt); for (;;) { /* Check the validity of the datatype ids */ if ( (mfrom_bdt <= 0 || mfrom_bdt > ADI_MXDTS) || (minto_bdt <= 0 || minto_bdt > ADI_MXDTS) || Adf_globs->Adi_dtptrs[mfrom_bdt] == NULL || Adf_globs->Adi_dtptrs[minto_bdt] == NULL ) { return (adu_error(adf_scb, E_AD2004_BAD_DTID, 0)); } /* Search for the appropriate COPY COERCION function instance id */ for (fi_desc_ptr = (ADI_FI_DESC *)&Adf_globs->Adi_fis[Adf_globs-> Adi_copy_coercion_fis]; ( fi_desc_ptr->adi_fitype == ADI_COPY_COERCION && fi_desc_ptr->adi_finstid != ADFI_ENDTAB ); fi_desc_ptr++ ) { if (fi_desc_ptr->adi_finstid == ADI_NOFI) continue; /* Hole in fitab ... skip this one. */ if (fi_desc_ptr->adi_dtresult == into_bdt && fi_desc_ptr->adi_dt[0] == from_bdt ) { *adi_fid = fi_desc_ptr->adi_finstid; found = TRUE; return (E_DB_OK); } } break; } /* end of for(;;) stmt */ /* Attempt to find normal COERCION function instance ID */ if (db_stat = adi_ficoerce(adf_scb, from_bdt, into_bdt, adi_fid)) { if (adf_scb->adf_errcb.ad_errcode == E_AD2009_NOCOERCION) db_stat = adu_error(adf_scb, E_AD200A_NOCOPYCOERCION, 0); } return (db_stat); }
DB_STATUS adc_hg_dtln( ADF_CB *adf_scb, DB_DATA_VALUE *adc_fromdv, DB_DATA_VALUE *adc_hgdv) { DB_STATUS db_stat; i4 bdt = abs((i4) adc_fromdv->db_datatype); i4 bdtv; i4 dtinfo; /* Data type status bits for this type */ for (;;) { /* Check the consistency of the input datatype id */ bdtv = ADI_DT_MAP_MACRO(bdt); if (bdtv <= 0 || bdtv > ADI_MXDTS || Adf_globs->Adi_dtptrs[bdtv] == NULL) { db_stat = adu_error(adf_scb, E_AD2004_BAD_DTID, 0); break; } /* Return error for datatypes that cannot be used in a relation or ** do not support histograms */ /* Get datatype status bits into dtinfo */ db_stat = adi_dtinfo(adf_scb, adc_fromdv->db_datatype, &dtinfo); if (!(dtinfo & AD_INDB) || (dtinfo & AD_NOHISTOGRAM)) { /* This datatype can't be used in a relation or doesn't support ** histograms */ db_stat = adu_error(adf_scb, E_AD3011_BAD_HG_DTID, 0); break; } #ifdef xDEBUG /* Check the consistency of adc_fromdv's length */ if (db_stat = adc_lenchk(adf_scb, FALSE, adc_fromdv, NULL)) break; #endif /* xDEBUG */ /* ** Now call the low-level routine to do the work. Note that if the ** datatype is nullable, we use a temp DV_DATA_VALUE which gets set ** to the corresponding base datatype and length. */ if (adc_fromdv->db_datatype > 0) /* non-nullable */ { db_stat = (*Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]-> adi_dt_com_vect.adp_hg_dtln_addr) (adf_scb, adc_fromdv, adc_hgdv); } else /* nullable */ { DB_DATA_VALUE tmp_dv = *adc_fromdv; tmp_dv.db_datatype = bdt; tmp_dv.db_length--; db_stat = (*Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]-> adi_dt_com_vect.adp_hg_dtln_addr) (adf_scb, &tmp_dv, adc_hgdv); } break; } /* end of for stmt */ return(db_stat); }