STATUS adu_sc930prtdataval( i4 msg_type, char *parameter_name, i4 parameter_no, DB_DATA_VALUE *db_dv, ADF_CB *tzcb, PTR file) { char num_buf[64]; i2 flt_wid; f8 f8_tmp; AD_NEWDTNTRNL dateval; AD_NEWDTNTRNL *datep=&dateval; DB_TAB_LOGKEY_INTERNAL *tab_logkey; DB_OBJ_LOGKEY_INTERNAL *obj_logkey; DB_DT_ID bdt; DB_STATUS db_stat; i4 blen; i4 prec; char *data; char fmt[16]; i4 tmp; i4 tcnt; i4 i; i4 res_wid; f4 f4_tmp; i4 i4_tmp; i2 i2_tmp, i2_tmp2; i1 i1_tmp; u_char u_tmp_i1; char stbuf[SC930_DATAVAL_BUFSIZE]; AD_DTUNION *dp; i8 i8_tmp; char *c_tmp,*c_buf_end; if (db_dv == NULL) { SIfprintf(file, "< Pointer to DB_DATA_VALUE is NULL >\n"); return E_DB_ERROR; } if (parameter_name) { STprintf(stbuf,"%d:%d(%s)=", db_dv->db_datatype, parameter_no, parameter_name); } else { STprintf(stbuf,"%d:%d=", db_dv->db_datatype, parameter_no); } /* output the PARM/PARMEXEC 'header' to the trace file */ switch (msg_type) { case SC930_LTYPE_PARM: SIfprintf(file,"PARM:%s",stbuf); break; case SC930_LTYPE_PARMEXEC: SIfprintf(file,"PARMEXEC:%s",stbuf); break; default: SIfprintf(file,"UNKNOWN:%s",stbuf); } bdt = abs(db_dv->db_datatype); blen = db_dv->db_length - (db_dv->db_datatype < 0); prec = db_dv->db_prec; data = db_dv->db_data; if (data == NULL) { SIfprintf(file, "< pointer to data is NULL >\n"); return E_DB_ERROR; } else if (ADI_ISNULL_MACRO(db_dv)) { SIfprintf(file, "< NULL >\n"); return OK; } else { switch (bdt) { case DB_LOGKEY_TYPE: obj_logkey = (DB_OBJ_LOGKEY_INTERNAL *) data; SIfprintf(file, "olk_high_id = %x\tolk_low_id = %x\t" "olk_rel_id = %d\tolk_db_id = %d\n" , obj_logkey->olk_high_id, obj_logkey->olk_low_id, obj_logkey->olk_rel_id, obj_logkey->olk_db_id); break; case DB_TABKEY_TYPE: tab_logkey = (DB_TAB_LOGKEY_INTERNAL *) data; SIfprintf(file, "tlk_high_id = %x\ttlk_low_id = %x\n", tab_logkey->tlk_high_id, tab_logkey->tlk_low_id); break; case DB_CHA_TYPE: case DB_CHR_TYPE: if (blen == 0) SIfprintf(file, "''\n"); else SIfprintf(file, "'%*s'\n", blen, (u_char *) data); break; case DB_DTE_TYPE: db_stat = adu_6to_dtntrnl (tzcb, db_dv, datep); if (datep->dn_status == 0) { SIfprintf(file, "''\n"); break; } SIfprintf(file, "(%s) %d/%d/%d %d:%d:%d.%.3d (%d)\n", (datep->dn_status & AD_DN_ABSOLUTE)? ((datep->dn_status & AD_DN_TIMESPEC)?"DATETIME":"DATE") :"INTERVAL", (i2)datep->dn_year,(i2)datep->dn_month,datep->dn_day, datep->dn_seconds / AD_39DTE_ISECPERHOUR, (datep->dn_seconds / AD_10DTE_ISECPERMIN) % 60, datep->dn_seconds % 60, (datep->dn_nsecond % AD_29DTE_NSPERMS), AD_TZ_OFFSETNEW(datep)); break; case DB_ADTE_TYPE: dp = (AD_DTUNION*)data; SIfprintf(file,"%d/%d/%d\n", dp->adate.dn_year, dp->adate.dn_month, dp->adate.dn_day); break; case DB_TMWO_TYPE: case DB_TMW_TYPE: case DB_TME_TYPE: dp = (AD_DTUNION*)data; SIfprintf(file,"%d,%d +/- %d\n", dp->atime.dn_seconds, dp->atime.dn_nsecond, AD_TZ_OFFSET(&dp->atime)); break; case DB_INYM_TYPE: dp = (AD_DTUNION*)data; SIfprintf(file,"%d %d\n",dp->aintym.dn_years, dp->aintym.dn_months); break; case DB_INDS_TYPE: dp = (AD_DTUNION*)data; SIfprintf(file,"%d %d %d\n", dp->aintds.dn_days, dp->aintds.dn_seconds, dp->aintds.dn_nseconds); break; case DB_TSWO_TYPE: case DB_TSW_TYPE: case DB_TSTMP_TYPE: dp = (AD_DTUNION*)data; SIfprintf(file,"%d/%d/%d %d %d (%d)\n", dp->atimestamp.dn_year, dp->atimestamp.dn_month, dp->atimestamp.dn_day, dp->atimestamp.dn_seconds, dp->atimestamp.dn_nsecond, AD_TZ_OFFSET(&dp->atimestamp)); break; case DB_DEC_TYPE: CVpka(data, (i4)DB_P_DECODE_MACRO(prec), (i4)DB_S_DECODE_MACRO(prec), '.', (i4)DB_P_DECODE_MACRO(prec) + 5, (i4)DB_S_DECODE_MACRO(prec), CV_PKLEFTJUST, num_buf, &res_wid); tmp = res_wid; i = 0; fmt[i++] = '%'; if (tmp >= 10) { fmt[i++] = (tmp / 10) + '0'; tmp = tmp % 10; } fmt[i++] = tmp + '0'; fmt[i++] = 's'; fmt[i++] = '\n'; fmt[i] = EOS; SIfprintf(file, fmt, num_buf); break; case DB_FLT_TYPE: if (blen == 4) { F4ASSIGN_MACRO(*data, f4_tmp); f8_tmp = f4_tmp; } else F8ASSIGN_MACRO(*data, f8_tmp); CVfa(f8_tmp, (i4) sizeof(num_buf), (i4) 4, 'f', '.', num_buf, &flt_wid); SIfprintf(file, "%*s\n", flt_wid, (u_char *) num_buf); break; case DB_INT_TYPE: if (blen == 4) { I4ASSIGN_MACRO(*data, i4_tmp); } else if (blen == 2) { I2ASSIGN_MACRO(*data, i2_tmp); i4_tmp = i2_tmp; } else if (blen == 1) { i4_tmp = I1_CHECK_MACRO(*(i1 *)data); } else /* blen == 8 */ { I8ASSIGN_MACRO(*data,i8_tmp); CVla8(i8_tmp,num_buf); SIfprintf(file, "%s\n", num_buf); break; } SIfprintf(file, "%d\n", i4_tmp); break; case DB_MNY_TYPE: f8_tmp = ((AD_MONEYNTRNL *) data)->mny_cents / 100.0; CVfa(f8_tmp, 32, 2, 'f', '.', num_buf, &flt_wid); tmp = flt_wid; i = 0; fmt[i++] = '%'; if (flt_wid >= 100) { fmt[i++] = (tmp / 100) + '0'; tmp = tmp % 100; } if (flt_wid >= 10) { fmt[i++] = (tmp / 10) + '0'; tmp = tmp % 10; } fmt[i++] = tmp + '0'; fmt[i++] = 's'; fmt[i++] = '\n'; fmt[i] = EOS; SIfprintf(file, fmt, num_buf); break; case DB_VCH_TYPE: case DB_TXT_TYPE: case DB_LTXT_TYPE: I2ASSIGN_MACRO(((DB_TEXT_STRING *)data)->db_t_count, i2_tmp); if (i2_tmp == 0) { SIfprintf(file, "''\n"); } else { SIfprintf(file, "'%*s'\n", i2_tmp, ((DB_TEXT_STRING *) data)->db_t_text); } break; case DB_BOO_TYPE: if (*((bool *) data)) SIfprintf(file,"TRUE\n"); else SIfprintf(file,"FALSE\n"); break; case DB_VBYTE_TYPE: I2ASSIGN_MACRO(((DB_TEXT_STRING *)data)->db_t_count, i2_tmp); blen=i2_tmp; data = ((DB_TEXT_STRING *)data)->db_t_text; case DB_BYTE_TYPE: c_tmp=stbuf; c_buf_end=c_tmp + SC930_DATAVAL_BUFSIZE - 10; STprintf(c_tmp,"%d:",blen); c_tmp += STlength(c_tmp); for(i=0; i< blen; i++) { u_tmp_i1=(u_char) data[i]; STprintf(c_tmp,"%02x ", u_tmp_i1); c_tmp += 3; if (c_tmp > c_buf_end ) { SIfprintf(file,stbuf); c_tmp=stbuf; stbuf[0]=EOS; } } SIfprintf(file,"%s\n",stbuf); break; case DB_NCHR_TYPE: stbuf[0] = EOS; c_tmp = stbuf; c_buf_end=c_tmp + SC930_DATAVAL_BUFSIZE - 10; for(i=0; i< blen/2; i++) { I2ASSIGN_MACRO(data[2*i], i2_tmp); i4_tmp = i2_tmp; STprintf(c_tmp,"%x ", i4_tmp); c_tmp += STlength(c_tmp); if (c_tmp > c_buf_end ) { SIfprintf(file,stbuf); c_tmp=stbuf; stbuf[0]=EOS; } } SIfprintf(file,"%s\n",stbuf); break; case DB_NVCHR_TYPE: I2ASSIGN_MACRO(((DB_NVCHR_STRING *)data)->count, i2_tmp); stbuf[0] = EOS; c_tmp = stbuf; c_buf_end=c_tmp + SC930_DATAVAL_BUFSIZE - 10; for(i=0; i< i2_tmp; i++) { I2ASSIGN_MACRO(((DB_NVCHR_STRING *)data)->element_array[i], i2_tmp2); i4_tmp = i2_tmp2; STprintf(c_tmp,"%x ", i4_tmp); c_tmp += STlength(c_tmp); if (c_tmp > c_buf_end ) { SIfprintf(file,stbuf); c_tmp=stbuf; stbuf[0]=EOS; } } SIfprintf(file,"%s\n",stbuf); break; case DB_LVCH_TYPE: case DB_LBYTE_TYPE: case DB_GEOM_TYPE: case DB_POINT_TYPE: case DB_MPOINT_TYPE: case DB_LINE_TYPE: case DB_MLINE_TYPE: case DB_POLY_TYPE: case DB_MPOLY_TYPE: case DB_GEOMC_TYPE: case DB_LNVCHR_TYPE: { ADP_PERIPHERAL *p = (ADP_PERIPHERAL *) data; ADP_COUPON *cpn; DB_DATA_VALUE dv_work; char tmp_val[DB_MAXSTRING + 1] = {0}; i4 i; dv_work.db_datatype = DB_CHA_TYPE; dv_work.db_length = DB_MAXSTRING; dv_work.db_data = tmp_val; adu_lvch_move(tzcb, db_dv, &dv_work); i = DB_MAXSTRING; while (dv_work.db_data[i] == ' ') dv_work.db_data[i--] = EOS; SIfprintf(file, "(%d/%d):'%s'\n",p->per_length0,p->per_length1, dv_work.db_data); } break; default: SIfprintf(file, "< unknown type: don't know how to interpret data >\n"); return E_DB_ERROR; } } return OK; }
VOID adu_2prvalue( i4 (*fcn)(char *, ...), DB_DATA_VALUE *db_dv) { char num_buf[64]; i2 flt_wid; f8 f8_tmp; AD_DTUNION *dp; DB_TAB_LOGKEY_INTERNAL *tab_logkey; DB_OBJ_LOGKEY_INTERNAL *obj_logkey; DB_DT_ID bdt; i4 blen; i4 prec; char *data; char fmt[16]; i4 tmp; i4 tcnt; i4 i; i4 res_wid; i8 i8_tmp; f4 f4_tmp; i4 i4_tmp; i2 i2_tmp, i2_tmp2; i1 i1_tmp; char stbuf[2048]; if (db_dv == NULL) { (*fcn)(STprintf(stbuf,"< Pointer to DB_DATA_VALUE is NULL >\n")); return; } bdt = abs(db_dv->db_datatype); blen = db_dv->db_length - (db_dv->db_datatype < 0); prec = db_dv->db_prec; data = db_dv->db_data; dp = (AD_DTUNION*)data; if (data == NULL) { (*fcn)(STprintf(stbuf,"< pointer to data is NULL >\n")); } else if (ADI_ISNULL_MACRO(db_dv)) { (*fcn)(STprintf(stbuf,"< NULL >\n")); } else { switch (bdt) { case DB_LOGKEY_TYPE: obj_logkey = (DB_OBJ_LOGKEY_INTERNAL *) data; (*fcn)(STprintf(stbuf, "olk_db_id = %x\tolk_rel_id = %x\n", obj_logkey->olk_db_id, obj_logkey->olk_rel_id)); (*fcn)(STprintf(stbuf, "olk_high_id = %x\tolk_low_id = %x\n", obj_logkey->olk_high_id, obj_logkey->olk_low_id)); break; case DB_TABKEY_TYPE: tab_logkey = (DB_TAB_LOGKEY_INTERNAL *) data; (*fcn)(STprintf(stbuf, "tlk_high_id = %x\ttlk_low_id = %x\n", tab_logkey->tlk_high_id, tab_logkey->tlk_low_id)); break; case DB_CHA_TYPE: case DB_CHR_TYPE: case DB_BYTE_TYPE: if (blen == 0) { (*fcn)(STprintf(stbuf,"''")); break; } (*fcn)(STprintf(stbuf, "'%*s'", blen, (u_char *) data)); break; case DB_DTE_TYPE: (*fcn)(STprintf(stbuf, "dn_status = %x\tdn_highday = %d\tdn_time = %d\n", dp->ing_date.dn_status, dp->ing_date.dn_highday, dp->ing_date.dn_time)); (*fcn)(STprintf(stbuf, "dn_year = %d\tdn_month = %d\tdn_lowday = %d", dp->ing_date.dn_year, dp->ing_date.dn_month, dp->ing_date.dn_lowday)); break; case DB_ADTE_TYPE: (*fcn)(STprintf(stbuf,"dn_year = %d\tdn_month = %d\tdn_day = %d\n", dp->adate.dn_year, dp->adate.dn_month, dp->adate.dn_day)); break; case DB_TMWO_TYPE: case DB_TMW_TYPE: case DB_TME_TYPE: (*fcn)(STprintf(stbuf,"dn_seconds = %d\tdn_nsecond = %d\n", dp->atime.dn_seconds, dp->atime.dn_nsecond)); (*fcn)(STprintf(stbuf,"dn_tzoffset = %d\n", AD_TZ_OFFSET(&dp->atime))); break; case DB_INYM_TYPE: (*fcn)(STprintf(stbuf,"dn_years = %d\tdn_months = %d\n", dp->aintym.dn_years, dp->aintym.dn_months)); break; case DB_INDS_TYPE: (*fcn)(STprintf(stbuf,"dn_days = %d\tdn_seconds = %d\tdn_nseconds = %d\n", dp->aintds.dn_days, dp->aintds.dn_seconds, dp->aintds.dn_nseconds)); break; case DB_TSWO_TYPE: case DB_TSW_TYPE: case DB_TSTMP_TYPE: (*fcn)(STprintf(stbuf,"dn_year = %d\tdn_month = %d\tdn_day = %d\n", dp->atimestamp.dn_year, dp->atimestamp.dn_month, dp->atimestamp.dn_day)); (*fcn)(STprintf(stbuf,"dn_seconds = %d\tdn_nsecond = %d\n", dp->atimestamp.dn_seconds, dp->atimestamp.dn_nsecond)); (*fcn)(STprintf(stbuf,"dn_tzoffset = %d\n", AD_TZ_OFFSET(&dp->atimestamp))); break; case DB_DEC_TYPE: CVpka(data, (i4)DB_P_DECODE_MACRO(prec), (i4)DB_S_DECODE_MACRO(prec), '.', (i4)DB_P_DECODE_MACRO(prec) + 5, (i4)DB_S_DECODE_MACRO(prec), CV_PKLEFTJUST, num_buf, &res_wid); tmp = res_wid; i = 0; fmt[i++] = '%'; if (tmp >= 10) { fmt[i++] = (tmp / 10) + '0'; tmp = tmp % 10; } fmt[i++] = tmp + '0'; fmt[i++] = 's'; fmt[i] = EOS; (*fcn)(STprintf(stbuf, fmt, num_buf)); break; case DB_FLT_TYPE: if (blen == 4) { F4ASSIGN_MACRO(*data, f4_tmp); f8_tmp = f4_tmp; } else F8ASSIGN_MACRO(*data, f8_tmp); CVfa(f8_tmp, (i4) sizeof(num_buf), (i4) 4, 'f', '.', num_buf, &flt_wid); (*fcn)(STprintf(stbuf, "%*s", flt_wid, (u_char *)num_buf)); break; case DB_INT_TYPE: if (blen == 4) { I4ASSIGN_MACRO(*data, i4_tmp); } else if (blen == 2) { I2ASSIGN_MACRO(*data, i2_tmp); i4_tmp = i2_tmp; } else if (blen == 1) { i4_tmp = I1_CHECK_MACRO(*(i1 *)data); } else /* blen == 8 */ { /* Depending on host, printing i8's might be %ld (lp64) ** or %lld (lpi32). Avoid issues by converting to string. */ I8ASSIGN_MACRO(*data,i8_tmp); CVla8(i8_tmp,&num_buf[0]); (*fcn)(num_buf); break; } (*fcn)(STprintf(stbuf, "%d", i4_tmp)); break; case DB_MNY_TYPE: f8_tmp = ((AD_MONEYNTRNL *) data)->mny_cents / 100.0; CVfa(f8_tmp, 32, 2, 'f', '.', num_buf, &flt_wid); tmp = flt_wid; i = 0; fmt[i++] = '%'; if (flt_wid >= 100) { fmt[i++] = (tmp / 100) + '0'; tmp = tmp % 100; } if (flt_wid >= 10) { fmt[i++] = (tmp / 10) + '0'; tmp = tmp % 10; } fmt[i++] = tmp + '0'; fmt[i++] = 's'; fmt[i] = EOS; (*fcn)(STprintf(stbuf, fmt, num_buf)); break; case DB_VCH_TYPE: case DB_TXT_TYPE: case DB_LTXT_TYPE: case DB_VBYTE_TYPE: I2ASSIGN_MACRO(((DB_TEXT_STRING *)data)->db_t_count, i2_tmp); if (i2_tmp == 0) { (*fcn)(STprintf(stbuf,"''")); break; } (*fcn)(STprintf(stbuf, "'%*s'", i2_tmp, ((DB_TEXT_STRING *) data)->db_t_text)); break; case DB_BOO_TYPE: if (*((bool *) data)) (*fcn)(STprintf(stbuf,"TRUE")); else (*fcn)(STprintf(stbuf,"FALSE")); break; case DB_NCHR_TYPE: for(i=0; i< blen/2; i++) { I2ASSIGN_MACRO(data[2*i], i2_tmp); i4_tmp = i2_tmp; (*fcn)(STprintf(stbuf,"%x ", i4_tmp)); } break; case DB_NVCHR_TYPE: case DB_PAT_TYPE: I2ASSIGN_MACRO(((DB_NVCHR_STRING *)data)->count, i2_tmp); if (bdt == DB_PAT_TYPE) i2_tmp = 4; for(i=0; i< i2_tmp; i++) { I2ASSIGN_MACRO(((DB_NVCHR_STRING *)data)->element_array[i], i2_tmp2); i4_tmp = i2_tmp2; (*fcn)(STprintf(stbuf,"%x ", i4_tmp)); } break; case DB_LVCH_TYPE: case DB_LBYTE_TYPE: case DB_GEOM_TYPE: case DB_POINT_TYPE: case DB_MPOINT_TYPE: case DB_LINE_TYPE: case DB_MLINE_TYPE: case DB_POLY_TYPE: case DB_MPOLY_TYPE: case DB_GEOMC_TYPE: case DB_LNVCHR_TYPE: { ADP_PERIPHERAL *p = (ADP_PERIPHERAL *) data; ADP_COUPON *cpn; (*fcn)(STprintf(stbuf, "%s/length = (%d., %0d.): ", (p->per_tag == ADP_P_COUPON ? "ADP_P_COUPON" : "ADP_P_DATA"), p->per_length0, p->per_length1)); if (p->per_tag == ADP_P_COUPON) { cpn = &p->per_value.val_coupon; #if defined(axp_osf) || defined(ris_u64) || defined(LP64) || \ defined(axp_lnx) (*fcn)(STprintf(stbuf, "(%d.,%d.,%d.,%d.,%d.,%d.)", cpn->cpn_id[0],cpn->cpn_id[1], cpn->cpn_id[2],cpn->cpn_id[3], cpn->cpn_id[4],cpn->cpn_id[5])); #else (*fcn)(STprintf(stbuf, "(%d.,%d.,%d.,%d.,%d.)", cpn->cpn_id[0],cpn->cpn_id[1], cpn->cpn_id[2],cpn->cpn_id[3], cpn->cpn_id[4])); #endif } else { (*fcn)(STprintf(stbuf, "(first %d. of value) '%t'", min(100, p->per_length1), min(100, p->per_length1), p->per_value.val_value)); } } break; default: (*fcn)(STprintf(stbuf, "< unknown type: don't know how to interpret data >")); break; } } return; }
/*{ ** 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: adt_utf8comp() - Compare 2 c/text/char/varchar values in UTF8 server ** ** Description: ** This routine compares two string data values. Before they are compared, ** they must be coerced to UCS2 and the comparison is done according to ** the Unicode Collation Algorithm. This necessitates a call to ** adu_nvchr_utf8comp() to perform the setup and comparison. This function ** presents the values as DB_DATA_VALUE structures, as expected by ** adu_nvchr_utf8comp(). ** ** 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. ** atr_bdt Data type to be compared. ** atr_len Length of comparands. ** d1 Pointer to first value. ** d2 Pointer to second value. ** ** 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. ** status Status returned from ** adu_mvchr_utf8comp(), if called. ** ** The following DB_STATUS codes may be returned by ** adu_nvchr_utf8comp(): ** 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. ** E_AD2005_BAD_DTLEN Internal length is illegal for ** the given datatype. ** (Others not yet defined) ** ** Returns: ** i4 < 0 if 1st < 2nd ** = 0 if 1st = 2nd ** > 0 if 1st > 2nd ** ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 10-may-2007 (dougi) ** Written for UTF8-enabled server. ** 05-nov-2007 (gupsh01) ** pass in default for quel pattern matching to ** adu_nvchr_utf8comp. ** 19-mar-2008 (gupsh01) ** Use an aligned buffer for varchar and text types. ** 20-mar-2008 (gupsh01) ** Start with an aligned buffer to work with. ** 12-jul-2008 (gupsh01) ** Fix the size allocated for aligned buffer. */ static i4 adt_utf8comp( ADF_CB *adf_scb, DB_ATTS *atr, i4 atr_bdt, i2 atr_len, char *d1, /* Ptr to 1st value */ char *d2, /* Ptr to 2nd value */ DB_STATUS *status) /* Status from adc_compare */ { i4 cur_cmp; /* Result of latest attr cmp */ DB_DATA_VALUE dv1; DB_DATA_VALUE dv2; ALIGN_RESTRICT temp_dv1[2048 / sizeof(ALIGN_RESTRICT)]; ALIGN_RESTRICT temp_dv2[2048 / sizeof(ALIGN_RESTRICT)]; char *dv1data = d1; char *dv2data = d2; u_char *tc1, *tc2, *dc1, *dc2; bool getdv1mem = FALSE; bool getdv2mem = FALSE; i4 reqlen; /* If varchar/text then use the aligned buffer */ if ((abs(atr_bdt) == DB_VCH_TYPE) || (abs(atr_bdt) == DB_TXT_TYPE)) { STATUS stat; /* ** Check for alignment */ reqlen = atr_len + DB_CNTSIZE + sizeof(ALIGN_RESTRICT); if(ME_ALIGN_MACRO((PTR)d1, sizeof(ALIGN_RESTRICT)) !=d1) { if (reqlen > sizeof(temp_dv1)) { dv1data = (char *)MEreqmem(0, reqlen, FALSE, &stat); if ((dv1data == NULL) || (stat != OK)) return (adu_error(adf_scb, E_AD2042_MEMALLOC_FAIL, 2, 0, (i4) sizeof(stat), (i4 *)&stat)); getdv1mem = TRUE; } else dv1data = (char *)&temp_dv1[0]; I2ASSIGN_MACRO(((DB_TEXT_STRING *)d1)->db_t_count, ((DB_TEXT_STRING *)dv1data)->db_t_count); tc1 = (u_char *)d1 + DB_CNTSIZE; dc1 = (u_char *)dv1data + DB_CNTSIZE; MEcopy ( tc1, atr_len, dc1); } if(ME_ALIGN_MACRO((PTR)d2, sizeof(ALIGN_RESTRICT)) !=d2) { if (reqlen > sizeof(temp_dv2)) { dv2data = (char *)MEreqmem(0, reqlen , FALSE, &stat); if ((dv2data == NULL) || (stat != OK)) return (adu_error(adf_scb, E_AD2042_MEMALLOC_FAIL, 2, 0, (i4) sizeof(stat), (i4 *)&stat)); getdv2mem = TRUE; } else dv2data = (char *)&temp_dv2[0]; I2ASSIGN_MACRO(((DB_TEXT_STRING *)d2)->db_t_count, ((DB_TEXT_STRING *)dv2data)->db_t_count); tc2 = (u_char *)d2 + DB_CNTSIZE; dc2 = (u_char *)dv2data + DB_CNTSIZE; MEcopy ( tc2, atr_len, dc2); } } /* Set up DB_DATA_VALUEs. */ dv1.db_datatype = dv2.db_datatype = (DB_DT_ID)atr_bdt; dv1.db_prec = dv2.db_prec = atr->precision; dv1.db_length = dv2.db_length = atr_len; dv1.db_collID = dv2.db_collID = atr->collID; dv1.db_data = dv1data; dv2.db_data = dv2data; *status = adu_nvchr_utf8comp(adf_scb, 0, &dv1, &dv2, &cur_cmp); if (getdv1mem && dv1data) MEfree (dv1data); if (getdv2mem && dv2data) MEfree (dv2data); return(cur_cmp); }
/*{ ** Name: adt_compare() - Compare 2 data values. ** ** Description: ** This routine compares two data values. This will tell the caller if the ** supplied values are equal, or if not, which one is "greater than" the ** other. ** ** This routine exists as a performance boost for DMF. DMF is not allowed ** to know how to compare data values for the various datatypes. ** Therefore, if this routine did not exist, DMF would have to make a ** function call to "adc_compare()" for every attribute in the tuples ** being compared. Even though tuples are constructs that seem a level ** above what ADF logically handles, the performance improvement in this ** case justifies this routine. ** ** To avoid the overhead of an adc_compare call, ** this routine has built into it the semantics for ** comparing several of the most common datatypes supported by INGRES. ** ** If the routine does run across a datatype that is not in this list, it ** will call the general routine "adc_compare()", thereby guaranteeing ** that it will function (perhaps slower), for ALL datatypes, even future ** user defined ADTs. ** ** When NULL values are involved, this routine will use the same semantics ** that "adc_compare()" uses: a NULL value will be considered greater ** than any other value, and equal to another NULL value. ** ** PLEASE NOTE: As with "adc_compare()", no pattern matching for ** ----------- the string datatypes is done within this routine. ** ** ** 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. ** atr Pointer to DB_ATTR. ** d1 Pointer to first value. ** d2 Pointer to second value. ** ** 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. ** status Status returned from ** adc_compare(), if called. ** ** The following DB_STATUS codes may be returned by adc_compare(): ** 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. ** E_AD2005_BAD_DTLEN Internal length is illegal for ** the given datatype. ** (Others not yet defined) ** ** Returns: ** i4 < 0 if 1st < 2nd ** = 0 if 1st = 2nd ** > 0 if 1st > 2nd ** ** Exceptions: ** none ** ** Side Effects: ** none ** ** History: ** 10-Feb-86 (thurston) ** Initial creation. ** 03-apr-86 (thurston) ** Initial coding. Also, added two more return statuses (stati?): ** E_AD2004_BAD_DTID and E_AD2005_BAD_DTLEN. ** 11-jun-86 (jennifer) ** Fixed bug compare result asigned to adt_cmp_result instead ** of indirect through this pointer, i.e. *adt_cmp_result. ** 11-jun-86 (jennifer) ** Fixed bug where the first entry of attribute array (0) ** was being used. This entry is always garbage since ** attributes are numbered from 1. ** 27-jul-86 (ericj) ** Converted for new ADF error handling. ** 19-nov-86 (thurston) ** Fixed the comparison for text. ** 22-sep-88 (thurston) ** Added bit representation check as a first pass on each attr. Also, ** added code to deal with nullable types here ... this could be a big ** win, since all nullable types were going through adc_compare(), now ** they need not. Also, added cases for CHAR and VARCHAR. ** 21-oct-88 (thurston) ** Got rid of all of the `#ifdef BYTE_ALIGN' stuff by using the ** appropriate [I2,I4,F4,F8]ASSIGN_MACROs. This also avoids a bunch ** of MEcopy() calls on BYTE_ALIGN machines. ** 21-Apr-89 (anton) ** Added local collation support ** 17-Jun-89 (anton) ** Moved local collation routines to ADU from CL ** 25-jul-89 (jrb) ** Added support for decimal datatype. ** 02-jan-90 (jrb) ** Fix alignment problem. ** 08-aug-91 (seg) ** "d1" and "d2" are dereferenced too often with the assumption ** that (PTR) == (char *) to fix. Made them (char *). ** 28-mar-2001 (abbjo03) ** Add support for DB_NCHR_TYPE and DB_NVCHR_TYPE. ** 16-dec-04 (inkdo01) ** Add collation ID parm to aduucmp() calls. ** 02-Feb-2005 (jenjo02) ** Consolidated from the nine adt functions which duplicated ** this "compare" code. Runs the most optimal compare ** based on datatype for a single attribute. ** ** Optimized CHA/VCH compares to use MEcmp rather than ** CMcmpcase loop when possible. ** ** Replace giant switch statement with if-then-else ** ordered most likely to least likely, more or less. ** The switch was consuming 27% of the CPU used by this ** function. ** ** Added DB_STATUS *status as a function parameter so ** if adc_compare returns an error, it will be returned ** to the caller rather than as a bogus compare "result". ** 27-Apr-2005 (jenjo02 for stial01) ** Replaced computing compare value using arithmetic ** (d1 - d2) with logical compares ( d1 < d2...) as ** the arithmetic may over/underflow and return the ** wrong result. ** 13-May-2005 (thaju02) ** For differing length vchar, return value based on ** comparison of longer length vchar to blank. (B114514) ** 19-Jun-2006 (gupsh01) ** Added support for new date/time types. ** 3-may-2007 (dougi) ** Tweak slightly to allow MEcmp() on collation/double byte ** if they're bytewise equal. ** 10-may-2007 (dougi) ** Add logic to handle ordering of c/text/char/varchar in UTF8 ** server. ** 25-jul-2007 (gupsh01) ** Although UTF8 is multibyte it is meant to be processed through ** UTF8 comparison code utilizing unicode comparison. ** 17-Aug-2007 (gupsh01) ** Fix the UTF8 handling. */ i4 adt_compare( ADF_CB *adf_scb, DB_ATTS *atr, /* Attribute in question */ char *d1, /* Ptr to 1st value */ char *d2, /* Ptr to 2nd value */ DB_STATUS *status) /* Status from adc_compare */ { i4 cur_cmp; /* Result of latest attr cmp */ i4 vi1, vi2; /* Temp i4's used to cmp ints */ i8 lli1, lli2; /* Compare i8's */ f8 vf1, vf2; /* Temp f8's used to cmp flts */ u_char *lc1, *lc2; u_char blank; i4 atr_bdt; /* Base datatype of attr */ i2 atr_len; /* Length of cur attribute */ i4 d1_isnull, d2_isnull; DB_DATA_VALUE dv1, dv2; /* Data value structs for call ** to adc_compare(), if that is ** necessary. */ u_char *tc1, *tc2; /* Temps used for string compare */ u_char *endtc1, *endtc2; UCS2 *tn1, *tn2; /* Temps used for Nstring compare */ UCS2 *endtn1, *endtn2; /* ** The following four lines provide temp storage to solve ** byte allignment problems on some archictectures. */ i2 i2_t1, i2_t2; i4 i4_t1, i4_t2; f4 f4_t1, f4_t2; f8 f8_t1, f8_t2; #define ADT_LT (i4)-1 #define ADT_EQ (i4)0 #define ADT_GT (i4)1 *status = E_DB_OK; atr_len = atr->length; if ( (atr_bdt = atr->type) < 0 ) { /* Nullable datatype */ d1_isnull = (*((char *)d1 + atr_len - 1) & ADF_NVL_BIT); d2_isnull = (*((char *)d2 + atr_len - 1) & ADF_NVL_BIT); if ( !d1_isnull && !d2_isnull ) { /* Neither is the Null value, look at data */ atr_bdt = -atr_bdt; atr_len--; } else if (d1_isnull && d2_isnull) return(ADT_EQ); /* both are Null values; 1st = 2nd */ else if (d1_isnull) return(ADT_GT); /* 1st is Null value; 1st > 2nd */ else return(ADT_LT); /* 2nd is Null value; 1st < 2nd */ } /* "if then else" consumes ~27% less CPU than "switch" */ if ( atr_bdt == DB_INT_TYPE ) { /* If both operands aligned... */ /* Extra casts to shut up compilers -- only care about low bits */ if ( (((i4)(SCALARP)d1 | (i4)(SCALARP)d2) & atr_len-1) == 0 ) { if ( atr_len == 4 ) { if (*(i4*)d1 < *(i4*)d2) return(ADT_LT); else if (*(i4*)d1 > *(i4*)d2) return(ADT_GT); else return(ADT_EQ); } if ( atr_len == 8 ) { if (*(i8*)d1 < *(i8*)d2) return(ADT_LT); else if (*(i8*)d1 > *(i8*)d2) return(ADT_GT); else return(ADT_EQ); } if ( atr_len == 2 ) { if (*(i2*)d1 < *(i2*)d2) return(ADT_LT); else if (*(i2*)d1 > *(i2*)d2) return(ADT_GT); else return(ADT_EQ); } if (*(i1*)d1 < *(i1*)d2) return(ADT_LT); else if (*(i1*)d1 > *(i1*)d2) return(ADT_GT); else return(ADT_EQ); } /* One or both not aligned... */ if (atr_len == 4) { I4ASSIGN_MACRO(*d1, i4_t1); I4ASSIGN_MACRO(*d2, i4_t2); if (i4_t1 < i4_t2) return(ADT_LT); else if (i4_t1 > i4_t2) return(ADT_GT); else return(ADT_EQ); } if (atr_len == 8) { I8ASSIGN_MACRO(*d1, lli1); I8ASSIGN_MACRO(*d2, lli2); if (lli1 < lli2) return(ADT_LT); else if (lli1 > lli2) return(ADT_GT); else return(ADT_EQ); } if (atr_len == 2) { I2ASSIGN_MACRO(*d1, i2_t1); I2ASSIGN_MACRO(*d2, i2_t2); if (i2_t1 < i2_t2) return(ADT_LT); else if (i2_t1 > i2_t2) return(ADT_GT); else return(ADT_EQ); } if (*(i1*)d1 < *(i1*)d2) return(ADT_LT); else if (*(i1*)d1 > *(i1*)d2) return(ADT_GT); else return(ADT_EQ); } if ( atr_bdt == DB_FLT_TYPE || atr_bdt == DB_MNY_TYPE ) { /* If both operands aligned... */ /* Extra casts to shut up compilers, only care about low bits */ if ( (((i4)(SCALARP)d1 | (i4)(SCALARP)d2) & atr_len-1) == 0 ) { if ( atr_len == 8 ) { if (*(f8*)d1 < *(f8*)d2) return(ADT_LT); else if (*(f8*)d1 > *(f8*)d2) return(ADT_GT); else return(ADT_EQ); } if (*(f4*)d1 < *(f4*)d2) return(ADT_LT); else if (*(f4*)d1 > *(f4*)d2) return(ADT_GT); else return(ADT_EQ); } /* One or both not aligned... */ if ( atr_len == 8 ) { F8ASSIGN_MACRO(*d1, f8_t1); F8ASSIGN_MACRO(*d2, f8_t2); if (f8_t1 < f8_t2) return(ADT_LT); else if (f8_t1 > f8_t2) return(ADT_GT); else return(ADT_EQ); } F4ASSIGN_MACRO(*d1, f4_t1); F4ASSIGN_MACRO(*d2, f4_t2); if (f4_t1 < f4_t2) return(ADT_LT); else if (f4_t1 > f4_t2) return(ADT_GT); else return(ADT_EQ); } if ( atr_bdt == DB_BYTE_TYPE || atr_bdt == DB_TABKEY_TYPE || atr_bdt == DB_LOGKEY_TYPE ) { return(MEcmp(d1, d2, atr_len)); } if ( atr_bdt == DB_CHA_TYPE || atr_bdt == DB_VCH_TYPE ) { if ( atr_bdt == DB_CHA_TYPE ) { /* Try the turbo compare. */ cur_cmp = MEcmp(d1, d2, atr_len); /* If not equal and UTF8-enabled ... */ if (cur_cmp && (adf_scb->adf_utf8_flag & AD_UTF8_ENABLED)) return(adt_utf8comp(adf_scb, atr, atr_bdt, atr_len, d1, d2, status)); /* If neither collation nor doublebyte or if byte-wise equal ... */ if ( !(adf_scb->adf_collation || Adf_globs->Adi_status & ADI_DBLBYTE) || cur_cmp == 0) { return(cur_cmp); } tc1 = (u_char *) d1; tc2 = (u_char *) d2; endtc1 = tc1 + atr_len; endtc2 = tc2 + atr_len; } else { I2ASSIGN_MACRO(((DB_TEXT_STRING *)d1)->db_t_count, i2_t1); I2ASSIGN_MACRO(((DB_TEXT_STRING *)d2)->db_t_count, i2_t2); tc1 = (u_char *)d1 + DB_CNTSIZE; tc2 = (u_char *)d2 + DB_CNTSIZE; /* Try the turbo compare on the prefix. */ cur_cmp = MEcmp((char *)tc1, (char *)tc2, min(i2_t1, i2_t2)); /* If neither collation nor doublebyte... */ if ( !(adf_scb->adf_collation || Adf_globs->Adi_status & ADI_DBLBYTE) || (adf_scb->adf_utf8_flag & AD_UTF8_ENABLED)) { i2 diff = i2_t1 - i2_t2; /* If not equal or lengths differ and UTF8-enabled ... */ if ((diff || cur_cmp) && (adf_scb->adf_utf8_flag & AD_UTF8_ENABLED)) return(adt_utf8comp(adf_scb, atr, atr_bdt, atr_len, d1, d2, status)); /* If short compare produces inequality or lengths are ** the same ... */ if ( cur_cmp || diff == 0 ) { return(cur_cmp); } /* ** Equal for shorter length. ** If longer trails all blanks, they're equal */ if ( diff > 0 ) { /* tc1 is longer */ tc1 += i2_t2; while ( *(tc1++) == MIN_CHAR && --diff > 0 ); if (!diff) return( ADT_EQ ); else { tc1--; if (*tc1 > MIN_CHAR) return(ADT_GT); else return(ADT_LT); } } else { /* tc2 is longer */ tc2 += i2_t1; while ( *(tc2++) == MIN_CHAR && ++diff < 0 ); if (!diff) return( ADT_EQ ); else { tc2--; if (MIN_CHAR > *tc2) return(ADT_GT); else return(ADT_LT); } } } else if (i2_t1 == i2_t2 && cur_cmp == 0) return(cur_cmp); /* byte wise compare returns "=" */ endtc1 = tc1 + i2_t1; endtc2 = tc2 + i2_t2; } if (adf_scb->adf_collation) return(adugcmp((ADULTABLE *)adf_scb->adf_collation, ADUL_BLANKPAD, tc1, endtc1, tc2, endtc2)); /* Doublebyte is rather more tedious */ blank = (u_char)MIN_CHAR; cur_cmp = ADT_EQ; while ( cur_cmp == ADT_EQ ) { if (tc1 < endtc1) { lc1 = tc1; CMnext(tc1); } else { lc1 = ␣ } if (tc2 < endtc2) { lc2 = tc2; CMnext(tc2); } else { lc2 = ␣ } /* if both pointing to blank or we happen to be comparing ** a string to itself then break */ if (lc1 == lc2) break; cur_cmp = CMcmpcase(lc1, lc2); } return(cur_cmp); } if ( atr_bdt == DB_NCHR_TYPE || atr_bdt == DB_NVCHR_TYPE ) { if ( atr_bdt == DB_NCHR_TYPE ) { tn1 = (UCS2 *)d1; tn2 = (UCS2 *)d2; endtn1 = tn1 + atr_len / sizeof(UCS2); endtn2 = tn2 + atr_len / sizeof(UCS2); } else { tn1 = ((DB_NVCHR_STRING *)d1)->element_array; tn2 = ((DB_NVCHR_STRING *)d2)->element_array; I2ASSIGN_MACRO(((DB_NVCHR_STRING *)d1)->count, i2_t1); I2ASSIGN_MACRO(((DB_NVCHR_STRING *)d2)->count, i2_t2); endtn1 = tn1 + i2_t1; endtn2 = tn2 + i2_t2; } *status = aduucmp(adf_scb, ADUL_BLANKPAD, tn1, endtn1, tn2, endtn2, &cur_cmp, atr->collID); return (cur_cmp); } if ( atr_bdt == DB_CHR_TYPE ) { if (adf_scb->adf_utf8_flag & AD_UTF8_ENABLED) return(adt_utf8comp(adf_scb, atr, atr_bdt, atr_len, d1, d2, status)); if (adf_scb->adf_collation) return(adugcmp((ADULTABLE *)adf_scb->adf_collation, ADUL_SKIPBLANK, (u_char *)d1, atr_len + (u_char *)d1, (u_char *)d2, atr_len + (u_char *)d2)); return(STscompare((char *)d1, atr_len, (char *)d2, atr_len)); } if ( atr_bdt == DB_TXT_TYPE ) { if (adf_scb->adf_utf8_flag & AD_UTF8_ENABLED) return(adt_utf8comp(adf_scb, atr, atr_bdt, atr_len, d1, d2, status)); I2ASSIGN_MACRO(((DB_TEXT_STRING *)d1)->db_t_count, i2_t1); I2ASSIGN_MACRO(((DB_TEXT_STRING *)d2)->db_t_count, i2_t2); tc1 = (u_char *)d1 + DB_CNTSIZE; tc2 = (u_char *)d2 + DB_CNTSIZE; endtc1 = tc1 + i2_t1; endtc2 = tc2 + i2_t2; if (adf_scb->adf_collation) return(adugcmp((ADULTABLE *)adf_scb->adf_collation, 0, tc1, endtc1, tc2, endtc2)); cur_cmp = ADT_EQ; while (cur_cmp == ADT_EQ && tc1 < endtc1 && tc2 < endtc2) { if ( (cur_cmp = CMcmpcase(tc1, tc2)) == ADT_EQ ) { CMnext(tc1); CMnext(tc2); } } /* If equal up to shorter, short strings < long */ return( (cur_cmp) ? cur_cmp : (endtc1 - tc1) - (endtc2 - tc2) ); } if ( atr_bdt == DB_DEC_TYPE ) { /* See if the bit representation is identical. */ if ( MEcmp(d1, d2, atr_len) ) { i4 pr; i4 sc; pr = DB_P_DECODE_MACRO(atr->precision); sc = DB_S_DECODE_MACRO(atr->precision); return(MHpkcmp((PTR)d1, pr, sc, (PTR)d2, pr, sc)); } return(ADT_EQ); } /* Bit-equivalent dates we can handle here */ if (( atr_bdt == DB_DTE_TYPE || atr_bdt == DB_ADTE_TYPE || atr_bdt == DB_TMWO_TYPE || atr_bdt == DB_TMW_TYPE || atr_bdt == DB_TME_TYPE || atr_bdt == DB_TSWO_TYPE || atr_bdt == DB_TSW_TYPE || atr_bdt == DB_TSTMP_TYPE || atr_bdt == DB_INYM_TYPE || atr_bdt == DB_INDS_TYPE ) && MEcmp(d1, d2, (u_i2)atr_len) == 0 ) { return(ADT_EQ); } /* Will have to do it the slow way */ dv1.db_datatype = dv2.db_datatype = (DB_DT_ID)atr_bdt; dv1.db_prec = dv2.db_prec = atr->precision; dv1.db_length = dv2.db_length = atr_len; dv1.db_collID = dv2.db_collID = atr->collID; dv1.db_data = d1; dv2.db_data = d2; *status = adc_compare(adf_scb, &dv1, &dv2, &cur_cmp); return(cur_cmp); }
DB_STATUS dm1ch_compress( DMP_ROWACCESS *rac, char *rec, i4 rec_size, char *crec, i4 *crec_size) { u_char *pIn; u_char *pOut; i4 iInSize; i4 iOutSize; BIT_FILE BitFile; i2 Character; u_i2 StringCode; u_i2 index; i4 rc; DICTCONTROL DictCtrl; DICTIONARY Dict[TABLE_SIZE]; i4 i; i2 att_ln, str_ln; i2 type; i2 abs_type; i4 dt_bits; DB_ATTS *att; DB_ATTS **attpp; ADF_CB adf_scb; MEfill(sizeof(ADF_CB),0,(PTR)&adf_scb); adf_scb.adf_maxstring = DB_MAXSTRING; /* preen the input record of garbage */ pIn = (u_char *)rec; attpp = rac->att_ptrs; i = rac->att_count; while (--i >= 0) { att = *attpp++; att_ln = att->length; type = att->type; if (att->ver_dropped > att->ver_added) continue; /* ** Obtain info about the data type. ** It's used to check for coupons then later for variable len */ abs_type = (type < 0) ? -type: type; adi_dtinfo(&adf_scb, abs_type, &dt_bits); if ((type < 0) && !(dt_bits & AD_PERIPHERAL)) { /* nullable */ if (pIn[--att_ln] & ADF_NVL_BIT) { /* it is null so zap the value */ MEfill(att_ln, 0x00, pIn); pIn += att->length; continue; } type = (-type); } /* ** either not a nullable datatype or ** nullable but not null right now */ switch (type) { /* ** currently only interested in variable length ** attributes ; it is these which potentially have ** garbage past their end - all others are either complete ** or blank padded already */ case DB_VCH_TYPE: case DB_TXT_TYPE: case DB_VBYTE_TYPE: /* get length and adjust */ I2ASSIGN_MACRO(((DB_TEXT_STRING *)pIn)->db_t_count, str_ln); str_ln += DB_CNTSIZE; if (str_ln < att_ln) MEfill((att_ln - str_ln), 0x00, (pIn + str_ln)); break; case DB_NVCHR_TYPE: /* get length and adjust */ I2ASSIGN_MACRO(((DB_TEXT_STRING *)pIn)->db_t_count, str_ln); str_ln = str_ln * sizeof(UCS2) + DB_CNTSIZE; if (str_ln < att_ln) MEfill((att_ln - str_ln), 0x00, (pIn + str_ln)); break; default: break; } /* point to next attribute */ pIn += att->length; } /* now compress the preened record */ pIn = (u_char*)rec; pOut = (u_char*)crec; iInSize = rec_size; /* write compression indicator */ *pOut++ = (char)TRUE; dm1ch_InitDictionary(&Dict[0], &DictCtrl); BitFile.pDataPtr = pOut; BitFile.cbDataLen = (u_i2)(rec_size); BitFile.cResidual = 0; BitFile.Residual = 0L; StringCode = pIn[0]; pIn++; iInSize--; while (iInSize > 0) { Character = pIn[0]; pIn++; iInSize--; index = dm1ch_FindChildNode(&Dict[0], StringCode, Character); if (Dict[index].CodeValue != UNUSED) { StringCode = Dict[index].CodeValue; } else { Dict[index].CodeValue = DictCtrl.NextCode++; Dict[index].ParentCode = StringCode; Dict[index].Character = (char) Character; rc = dm1ch_OutputBits(&BitFile, (u_i4) StringCode, DictCtrl.CurrentCodeBits); if (rc == -1) break; /* Compression didn't compress */ StringCode = Character; if (DictCtrl.NextCode > (u_i2) MAX_CODE) { rc = dm1ch_OutputBits(&BitFile, (u_i4) FLUSH_CODE, DictCtrl.CurrentCodeBits); if (rc == -1) break; /* Compression didn't compress */ dm1ch_InitDictionary(&Dict[0], &DictCtrl); } /* Dictionary has filled up */ else if (DictCtrl.NextCode > DictCtrl.NextBumpCode) { rc = dm1ch_OutputBits(&BitFile, (u_i4) BUMP_CODE, DictCtrl.CurrentCodeBits); if (rc == -1) break; /* Compression didn't compress */ DictCtrl.CurrentCodeBits++; DictCtrl.NextBumpCode <<= 1; DictCtrl.NextBumpCode |= 1; } /* Increase the number of code bits */ } } if (rc == 0) rc = dm1ch_OutputBits(&BitFile, (u_i4) StringCode, DictCtrl.CurrentCodeBits); if (rc == 0) rc = dm1ch_OutputBits(&BitFile, (u_i4) END_OF_STREAM, DictCtrl.CurrentCodeBits); if (rc == 0) rc = dm1ch_CloseBitFile(&BitFile); if (rc == 0) { iOutSize = rec_size - BitFile.cbDataLen + 1; } else /* compression failed to reduce the size, so use original */ { /* write compression indicator */ pOut = (u_char*)crec; *pOut++ = (char)FALSE; /* write original data */ MEcopy(rec, rec_size, pOut); iOutSize = rec_size + 1; } *crec_size = iOutSize; /* Return the size of compressed data */ return(E_DB_OK); } /* dm1ch_compress */
DB_STATUS adu_dbconst( ADF_CB *adf_scb, ADK_MAP *kmap, DB_DATA_VALUE *rdv) { ADK_CONST_BLK *k = adf_scb->adf_constants; bool kcalced = FALSE; PTR kptr = NULL; DB_ERROR err; ADF_DBMSINFO *dbi = kmap->adk_dbi; i4 kbit = kmap->adk_kbit; DB_STATUS db_stat; bool datetimetype = FALSE; DB_DT_ID date_dt; u_i4 val; /* Beware that some of the dbmsinfo functions care not about ** caller lengths and will update the DBV regardless so ** we arrange to get the constants written directy and if ** need be, we conver on return. */ DB_DATA_VALUE tmp_rdv = *rdv; i8 tmp_buf[1024/sizeof(i8)]; /* Make temporary aligned */ switch (kbit) /* look for datetime constants */ { case ADK_CURR_DATE: /* _current_date */ datetimetype = TRUE; date_dt = DB_ADTE_TYPE; break; case ADK_CURR_TIME: /* _current_time */ datetimetype = TRUE; date_dt = DB_TMW_TYPE; break; case ADK_CURR_TSTMP: /* _current_timestamp */ datetimetype = TRUE; date_dt = DB_TSW_TYPE; break; case ADK_LOCAL_TIME: /* _local_time*/ datetimetype = TRUE; date_dt = DB_TME_TYPE; break; case ADK_LOCAL_TSTMP: /* _local_timestamp */ datetimetype = TRUE; date_dt = DB_TSTMP_TYPE; break; } if (k != NULL) { switch (kbit) /* switch on known query constants */ { case ADK_BINTIM: /* _bintim */ tmp_rdv.db_data = (PTR) &k->adk_bintim; tmp_rdv.db_length = sizeof(k->adk_bintim); break; case ADK_CPU_MS: /* _cpu_ms */ tmp_rdv.db_data = (PTR) &k->adk_cpu_ms; tmp_rdv.db_length = sizeof(k->adk_cpu_ms); break; case ADK_ET_SEC: /* _et_sec */ tmp_rdv.db_data = (PTR) &k->adk_et_sec; tmp_rdv.db_length = sizeof(k->adk_et_sec); break; case ADK_DIO_CNT: /* _dio_cnt */ tmp_rdv.db_data = (PTR) &k->adk_dio_cnt; tmp_rdv.db_length = sizeof(k->adk_dio_cnt); break; case ADK_BIO_CNT: /* _bio_cnt */ tmp_rdv.db_data = (PTR) &k->adk_bio_cnt; tmp_rdv.db_length = sizeof(k->adk_bio_cnt); break; case ADK_PFAULT_CNT: /* _pfault_cnt */ tmp_rdv.db_data = (PTR) &k->adk_pfault_cnt; tmp_rdv.db_length = sizeof(k->adk_pfault_cnt); break; case ADK_CURR_DATE: /* _current_date */ tmp_rdv.db_data = (PTR) &k->adk_curr_date; tmp_rdv.db_length = sizeof(k->adk_curr_date); break; case ADK_CURR_TIME: /* _current_time */ tmp_rdv.db_data = (PTR) &k->adk_curr_time; tmp_rdv.db_length = sizeof(k->adk_curr_time); break; case ADK_CURR_TSTMP: /* _current_timestamp */ tmp_rdv.db_data = (PTR) &k->adk_curr_tstmp; tmp_rdv.db_length = sizeof(k->adk_curr_tstmp); break; case ADK_LOCAL_TIME: /* _local_time*/ tmp_rdv.db_data = (PTR) &k->adk_local_time; tmp_rdv.db_length = sizeof(k->adk_local_time); break; case ADK_LOCAL_TSTMP: /* _local_timestamp */ tmp_rdv.db_data = (PTR) &k->adk_local_tstmp; tmp_rdv.db_length = sizeof(k->adk_local_tstmp); break; default: return (adu_error (adf_scb, E_AD9998_INTERNAL_ERROR, 2, 0, "dbmsinfo kbit")); } if (k->adk_set_mask & kbit) /* Has this value been calculated yet? */ kcalced = TRUE; } else tmp_rdv.db_data = (PTR)tmp_buf; if (!kcalced) { /* Must calculate value from scratch */ if (datetimetype) { AD_NEWDTNTRNL dn; struct timevect tv; DB_STATUS db_stat; i4 sec_time_zone; HRSYSTIME hrsystime; TMhrnow(&hrsystime); MEfill ((u_i2) sizeof(i4)*10, NULLCHAR, (PTR) &tv); adu_cvtime((i4) hrsystime.tv_sec, (i4)hrsystime.tv_nsec, &tv); MEfill((u_i2) sizeof(AD_NEWDTNTRNL), NULLCHAR, (PTR) &dn); /* Interpret the time vector */ dn.dn_year = (i2)tv.tm_year + 1900; dn.dn_month = (i2)tv.tm_mon + 1; dn.dn_day = tv.tm_mday; dn.dn_seconds = tv.tm_hour * 3600 + tv.tm_min * 60 + tv.tm_sec; dn.dn_nsecond = tv.tm_nsec; dn.dn_dttype = date_dt; sec_time_zone = TMtz_search(adf_scb->adf_tzcb, TM_TIMETYPE_GMT, (i4) hrsystime.tv_sec); AD_TZ_SETNEW(&dn, sec_time_zone); dn.dn_status = AD_DN_ABSOLUTE; switch (date_dt) { case DB_ADTE_TYPE: /* _current_date */ dn.dn_seconds = 0; dn.dn_nsecond = 0; dn.dn_status2 |= AD_DN2_ADTE_TZ; dn.dn_status |= AD_DN_YEARSPEC|AD_DN_MONTHSPEC|AD_DN_DAYSPEC; break; case DB_TME_TYPE: /* _local_time*/ dn.dn_status2 |= AD_DN2_TZ_OFF_LCL; /*FALLTHROUGH*/ case DB_TMW_TYPE: /* _current_time */ dn.dn_status |= AD_DN_TIMESPEC; dn.dn_status2 |= AD_DN2_NO_DATE; break; case DB_TSTMP_TYPE: /* _local_timestamp */ dn.dn_status2 |= AD_DN2_TZ_OFF_LCL; /*FALLTHROUGH*/ case DB_TSW_TYPE: /* _current_timestamp */ dn.dn_status |= AD_DN_YEARSPEC|AD_DN_MONTHSPEC|AD_DN_DAYSPEC; dn.dn_status |= AD_DN_TIMESPEC; break; } /* Convert straight into constant data area */ if (db_stat = adu_7from_dtntrnl (adf_scb, &tmp_rdv, &dn)) return (db_stat); } else if (dbi == NULL || dbi->dbi_func == NULL) { /* If no function ptr in dbmsinfo array, set default value */ if (db_stat = adc_getempty(adf_scb, &tmp_rdv)) return (db_stat); } else { /* Get the value from the proper dbmsinfo function */ /* ** NOTE: If the dbmsinfo routines ever change the size of ** of the returned object, it will be assumed that the length ** will match the adk_* buffer length. If not, there will ** be a risk of uninitialised data slipping in. */ if (db_stat = (*dbi->dbi_func)(dbi, NULL, &tmp_rdv, &err)) return (db_stat); } /* We now have the calculated result written directly to the ** constant buffers if they exist or to the tmp_buf. ** Either way, we don't need to write the constant again, we just ** need to convert out to the return buffer/dbv. */ /* Don't forget to set the `already calculated' bit */ if (k) k->adk_set_mask |= kbit; } /* We have the value requested, so just set result and return */ if (rdv->db_datatype == DB_INT_TYPE) { /* Currently, all query constants are uints or dates */ u_i8 val; switch (tmp_rdv.db_length) { case 8: val = (u_i8)*(u_i8*)tmp_rdv.db_data; break; case 4: val = (u_i8)*(u_i4*)tmp_rdv.db_data; break; case 2: val = (u_i8)*(u_i2*)tmp_rdv.db_data; break; case 1: val = (u_i8)*(u_i1*)tmp_rdv.db_data; break; } switch (rdv->db_length) { case 8: I8ASSIGN_MACRO(val, *(u_i8 *)rdv->db_data); break; case 4: { u_i4 val4 = (u_i4)val; I4ASSIGN_MACRO(val4, *(u_i4 *)rdv->db_data); } break; case 2: { u_i2 val2 = (u_i2)val; I2ASSIGN_MACRO(val2, *(i2*)rdv->db_data); } break; case 1: *(u_i1 *)rdv->db_data = (u_i1)val; break; default: return (adu_error (adf_scb, E_AD9998_INTERNAL_ERROR, 2, 0, "dbmsinfo isz")); } } else if (tmp_rdv.db_length != rdv->db_length) { return (adu_error (adf_scb, E_AD9998_INTERNAL_ERROR, 2, 0, "dbmsinfo len")); } else { MEcopy(tmp_rdv.db_data, rdv->db_length, rdv->db_data); } return (E_DB_OK); }