Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
/*{
** 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);
}
Esempio n. 4
0
/*{
** 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);
}
Esempio n. 5
0
/*{
** 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 = &blank;
	    }
	    
	    if (tc2 < endtc2)
	    {
		lc2 = tc2;
		CMnext(tc2);
	    }
	    else
	    {
		lc2 = &blank;
	    }
	    
	    /* 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);
}
Esempio n. 6
0
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 */
Esempio n. 7
0
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);
}