Ejemplo n.º 1
0
/*{
** Name: opz_addatts	- add joinop attributes to the array
**
** Description:
**      This routine will add or find the appropriate joinop attribute 
**      to the joinop attributes array given the 
**      (range variable, range variable attribute number) pair.
**
**	The exception to this rule occurs with function attributes which
**      always results in a new joinop  attribute being allocated.  A
**      function attribute uses "OPZ_FANUM" as the input attribute number.
**
** Inputs:
**      subquery                        ptr to subquery being analyzed
**      joinopvar                       index into joinop range table
**      dmfattr			        dmf attribute number
**      datatype                        ptr to ADT datatype
**
** Outputs:
**	Returns:
**	    joinop attribute number
**	Exceptions:
**	    none
**
** Side Effects:
**	    An entry may be allocated in the joinop attributes array 
**	    (OPS_SUBQUERY->ops_attrs)
**
** History:
**	20-apr-86 (seputis)
**          initial creation addatts
**      06-nov-89 (fred)
**          Added support for non-histogrammable datatypes.  This support
**	    entails providing a simple, coordinated replacement for this
**	    histogram.  In our case, the datatype & length will be varchar,
**	    minimum & maximum being those for varchar, and adc_helem()
**	    replacement will be the histogram for "nohistos".
**           
**          This code is done in OPF as opposed to ADF because I think it
**	    desirable that OPF manage the histogram replacement.  ADF will not
**	    know the appropriate values.  Furthermore, it is more desirable to
**	    teach OPF to manage w/out histograms;  however, that change is
**	    beyond the scope of this project.
**	26-dec-90 (seputis)
**	    init mask of booleans associated with attribute descriptor
**	18-jan-93 (rganski)
**	    Character Histogram Enhancements project:
**	    Initialize attr_ptr->opz_histogram.oph_dataval.db_length to 8
**	    before call to adc_hg_dtln(), which has been changed; this gives
**	    old behavior (limit for char types was 8). This length may be
**	    changed later when RDF gets info from iistatistics.
**	24-may-93 (rganski)
**	    Character Histograms Enhancements project:
**	    Initialize attr_ptr->opz_histogram.oph_dataval.db_length to 0
**	    before call to adc_hg_dtln(), which causes histogram value to be
**	    same length as attribute. This is necessary because otherwise the
**	    histogram value, which is used to determine selectivity of boolean
**	    factors, is truncated; this removes the benefits of having long
**	    histogram values. The histogram value length is adjusted in
**	    oph_catalog(), which reads the actual length from iistatistics (or
**	    truncates to 8, for old histograms).
**	6-dec-93 (ed)
**	    - bug 56139 - project union view before it is instantiated
**	09-oct-98 (matbe01)
**	    Added NO_OPTIM for NCR to eliminate runtime error that produces the
**	    message:  E_OP0889 Eqc is not available at a CO node.
**	 6-sep-04 (hayke02)
**	    Add OPZ_COLLATT attribute if OPS_COLLATION is on (resdom list,
**	    collation sequence). This change fixes problem INGSRV 2940, bug
**	    112873.
**	 8-nov-05 (hayke02)
**	    Add OPZ_VAREQVAR if OPS_VAREQVAR is on. Return if OPZ_VAREQVAR is
**	    not set and the attribute is found. This ensures that the fix for
**	    110675 is limited to OPZ_VAREQVAR PST_BOP nodes. This change
**	    fixes bug 115420 problem INGSRV 3465.
**       15-aug-2007 (huazh01)
**          ensure the datatype/length info of a created attribute matches 
**          the corresponding column type/length info on the user table. 
**          bug 117316.
**
[@history_line@]...
*/
OPZ_IATTS
opz_addatts(
	OPS_SUBQUERY       *subquery,
	OPV_IVARS	   joinopvar,
	OPZ_DMFATTR        dmfattr,
	DB_DATA_VALUE      *datatype)
{
	OPZ_IATTS              attribute;   /* used to save joinop attribute
					    ** number if found by opz_findatt
                                            */
        RDR_INFO		*rel;
   
        /* FIXME - need to deal with unsigned compare problem here */
	if ( (dmfattr != OPZ_FANUM) 
	     &&
             (dmfattr != OPZ_SNUM)
	     && 
             (dmfattr != OPZ_CORRELATED)
	     && 
	     (attribute = opz_findatt(subquery, joinopvar, dmfattr)) >= 0
	     &&
	     !(subquery->ops_attrs.opz_base->opz_attnums[attribute]->opz_mask &
								OPZ_VAREQVAR
	     &&
	     subquery->ops_mask2 & OPS_COLLATION
	     &&
	     (abs(datatype->db_datatype) == DB_CHA_TYPE
	     ||
	     abs(datatype->db_datatype) == DB_VCH_TYPE
	     ||
	     abs(datatype->db_datatype) == DB_CHR_TYPE
	     ||
	     abs(datatype->db_datatype) == DB_TXT_TYPE)) )
	    return( attribute );	    /* if this (joinopvar,dmfattr) pair 
					    ** exists and is not a function 
					    ** attribute, or subselect attribute
                                            ** then return
					    */

    {	/* create new joinop attribute */

	OPZ_IATTS		    nextattr; /* next available joinop attribute
                                            ** number
                                            */
	OPS_STATE                   *global; /* ptr to global state variable */

        global = subquery->ops_global;	    /* get ptr to global state variable 
                                            */
	if ( (nextattr = subquery->ops_attrs.opz_av++) >= OPZ_MAXATT)
	    opx_error(E_OP0300_ATTRIBUTE_OVERFLOW); /* exit with error
					    ** if no more room in attributes
                                            ** array
                                            */
	{
	    OPZ_ATTS               *attr_ptr;   /* ptr to newly created joinop 
					    ** attribute element */
	    OPV_VARS               *var_ptr; /* ptr to respective joinop
                                            ** variable containing attribute */

            var_ptr = subquery->ops_vars.opv_base->opv_rt[joinopvar];

	    /* allocate new joinop attribute structure and initialize */
	    subquery->ops_attrs.opz_base->opz_attnums[nextattr] = attr_ptr = 
		(OPZ_ATTS *) opu_memory( global, (i4) sizeof(OPZ_ATTS));
	    MEfill(sizeof(*attr_ptr), (u_char)0, (PTR)attr_ptr);


            /* b117316:
            **
            ** the fix to b109879 set PST_VAR node under the RESDOM to 
            ** to nullable and increase the db_length by one, though
            ** the column corresponds to PST_VAR is defined as not null.
            ** Need to reset them to not null in order to prevent
            ** wrong db_type and db_length being used during query
            ** execution. e.g., wrong db_type and db_length could cause OPC
            ** to generate a set of ADF code which materialize tuples
            ** using incorrect offset and cause wrong result. 
            **
            */
            rel = var_ptr->opv_grv->opv_relation;
            if (datatype->db_datatype < 0 && 
                dmfattr > 0 && 
                rel && 
                rel->rdr_attr[dmfattr]->att_type * -1 == datatype->db_datatype &&
                rel->rdr_attr[dmfattr]->att_width + 1 == datatype->db_length)
            {
                datatype->db_datatype = rel->rdr_attr[dmfattr]->att_type; 
                datatype->db_length = rel->rdr_attr[dmfattr]->att_width;
            }

	    attr_ptr->opz_varnm = joinopvar; /* index into local range table */
            BTset( (i4)nextattr, (char *)&var_ptr->opv_attrmap); /* indicate 
					    ** that this joinop
                                            ** attribute belongs to this range
                                            ** variable */
	    attr_ptr->opz_gvar = var_ptr->opv_gvar; /* move global range
                                            ** variable number to attribute */
	    attr_ptr->opz_attnm.db_att_id = dmfattr;/* dmf attribute of 
                                            ** range variable  */
	    STRUCT_ASSIGN_MACRO((* datatype), attr_ptr->opz_dataval);
	    attr_ptr->opz_equcls = OPE_NOEQCLS; /* this attribute has not been
                                            ** assigned an equivalence class yet
                                            */
	    attr_ptr->opz_func_att = OPZ_NOFUNCATT; /* this indicates that a
                                            ** function attribute is not
                                            ** associated with this joinop
                                            ** attribute element
                                            */
	    if ((dmfattr != OPZ_FANUM) 
		&&
		(dmfattr != OPZ_SNUM)
		&& 
		(dmfattr != OPZ_CORRELATED)
		&&
		(attribute >= 0))
		attr_ptr->opz_mask |= OPZ_COLLATT;
	    if (subquery->ops_mask2 & OPS_VAREQVAR)
		attr_ptr->opz_mask |= OPZ_VAREQVAR;
	    if ((var_ptr->opv_grv->opv_gmask & OPV_UVPROJECT)
		&&
		(dmfattr >= 0))
	    {	/* if union view exists in which a projection is possible 
		** (i.e. a UNION ALL view) then
		** mark the attribute which are referenced in the union view*/
		BTset((i4)dmfattr, (char *)var_ptr->opv_grv->opv_attrmap);
	    }
	    {
		/* initialize the histogram information associated with this
		** attribute
		*/
		DB_STATUS	hgstatus;	/* ADT return status */
		i4		dt_bits;

		hgstatus = adi_dtinfo(global->ops_adfcb,
					    datatype->db_datatype, &dt_bits);

		if ((hgstatus == E_AD0000_OK) && (dt_bits & AD_NOHISTOGRAM))
		{
		    attr_ptr->opz_histogram.oph_dataval.db_datatype =
							    OPH_NH_TYPE;
		    attr_ptr->opz_histogram.oph_dataval.db_prec =
							    OPH_NH_PREC;
		    attr_ptr->opz_histogram.oph_dataval.db_length =
							    OPH_NH_LENGTH;
		}
		else
		{
		    attr_ptr->opz_histogram.oph_dataval.db_length = 0;
		    hgstatus = adc_hg_dtln(global->ops_adfcb, datatype, 
			&attr_ptr->opz_histogram.oph_dataval );
		}
# ifdef E_OP0780_ADF_HISTOGRAM
		if ((hgstatus != E_AD0000_OK)
		    ||
		    (attr_ptr->opz_histogram.oph_dataval.db_datatype < 0)
					    /* do not expect a nullable
                                            ** histogram datatype */
		   )
		    opx_verror( hgstatus, E_OP0780_ADF_HISTOGRAM, 
			global->ops_adfcb->adf_errcb.ad_errcode); /*
                                            ** abort if unexpected error occurs
                                            */
# endif
		attr_ptr->opz_histogram.oph_dataval.db_data = NULL; /* init the
                                            ** data value ptr */
		attr_ptr->opz_histogram.oph_numcells = OPH_NOCELLS; /* histogram
                                            ** has not been fetched so no cells
                                            ** exist at this point
                                            */
		attr_ptr->opz_histogram.oph_histmm = NULL; /* no histogram
                                            ** exists at this point
					    */
                attr_ptr->opz_histogram.oph_mindomain = NULL; /* no minimum
                                            ** value for this histogram yet */
                attr_ptr->opz_histogram.oph_maxdomain = NULL; /* no maximum
					    ** value for this histogram yet */
	    }
	    if (dmfattr == DB_IMTID)
	    {
		/* implicit TID found so an equivalence class needs to be
                ** created ... so we know the equivalence class of the
                ** implicit TID for this (since the implicit TID is referenced
                ** by an index or explicitly in the qualification)
		*/
		var_ptr->opv_primary.opv_tid 
		    = ope_neweqcls( subquery, nextattr );
	    }
	}
    return( nextattr );			/* return joinop attribute which has
                                        ** been assigned
                                        */
    }
}
Ejemplo n.º 2
0
/*
** Name:    pst_rsdm_dt_resolve - determine type, length, precision to be stored
**				  in RESDOM node based on those found in its
**				  right child
**
** Description:
**	If the right child of RESDOM exists, copy the child's type, length, and
**	precision into the descriptor for the RESDOM node; if adi_dtinfo()
**	indicates that this type cannot be sent to FE, call adc_dbtoev() to
**	obtain an translate it into an "exportable" data type.
**	If the right child does not exist, then simply set type to DB_NODT and
**	length and precision to 0.
**
** Input:
**	right		    right child of the RESDOM node; NULL if none exists
**	cb		    PSF session CB
**	    pss_qualdepth   if set to 1, the resdom represents an element of a
**			    target list which will be returned to FE
**	psq_cb		    PSF request CB
**	    psq_mode	    mode of the query
**
** Output:
**	coldesc		    type/length,precision descriptor will be filled in
**	    att_type	    data type
**	    att_width	    length
**	    att_prec	    precision
**
** Side effects:
**	none
**
** Returns:
**	E_DB_{OK,ERROR}
**
** History:
**
**	08-jan-92 (andre)
**	    broke off from the body of pst_adresdom() to enable psl_p_tlist() to
**	    correctly process UDTs found in the target list
**	06-oct-92 (andre)
**	    we should not call adc_dbtoev() when processing INSERT ... SELECT.
**	    this can be determined by checking if 
**	    (!cb->pss_resrng || !cb->pss_resrng->pss_used ||
**	    cb->pss_resrng->pss_rgno < 0)
**	21-jun-93 (robf)
**	    we should be doing adc_dbtoev in QUEL retrieve (x.all), where
**	    pss_qualdepth is 0, so changed 
**		&& (cb->pss_qualdepth ==1)
**  	    to
**		&& (cb->pss_qualdepth <=1)
**	15-apr-05 (inkdo01)
**	    Add collation ID support.
**      29-Oct-2007 (hanal04) Bug 119368
**          If the front end does not have GCA i8 support then cast the
**          RESDOMs as i4s.
**      26-Nov-2009 (hanal04) Bug 122938
**          If the front end does not support the maximum precision
**          for decimals downgrade/convert to the supported maximum
**          precision level.
**       7-Dec-2009 (hanal04) Bug 123019, 122938
**          Adjust previous change for Bug 122938. Scale only needs to be
**          adjusted if it is greater than the new precision. This prevents
**          negative scale values seen in replicator testing.
**      25-Feb-2010 (hanal04) Bug 123291
**          Remove downgrade of decimal RESDOMs, old clients can display
**          precision in excess of 31, they just can't use them in ascii
**          copy.
**	22-Mar-2010 (toumi01) SIR 122403
**	    Init new encryption variables.
*/
DB_STATUS
pst_rsdm_dt_resolve(
	PST_QNODE	*right,
	DMT_ATT_ENTRY	*coldesc,
	PSS_SESBLK	*cb,
	PSQ_CB		*psq_cb)
{
    DB_STATUS	    status;
    ADF_CB          *adf_scb;
    i2              null_adjust = 0;

    if (right != (PST_QNODE *) NULL)
    {
	coldesc->att_type = right->pst_sym.pst_dataval.db_datatype;
	coldesc->att_width = right->pst_sym.pst_dataval.db_length;
	coldesc->att_prec = right->pst_sym.pst_dataval.db_prec;
	coldesc->att_collID = right->pst_sym.pst_dataval.db_collID;
	/*
	** Internally some nodes have their type resolved later (ie, aggs)
	** and may enter here with DB_NODT as the type.  To avoid errors
	** from adi_dtinfo, we do not call if the type is DB_NODT.
	*/
	if (coldesc->att_type != DB_NODT)
	{
	    i4		dt_status;
	    ADF_CB	*adf_scb;

	    adf_scb = (ADF_CB *) cb->pss_adfcb;

	    status = adi_dtinfo(adf_scb, coldesc->att_type, &dt_status);
	    if (DB_FAILURE_MACRO(status))
	    {
		adf_scb->adf_errcb.ad_errclass = ADF_USER_ERROR;
		psf_adf_error(&adf_scb->adf_errcb, &psq_cb->psq_error, cb);
		return(status);
	    }

	    if (   (dt_status & (AD_NOEXPORT | AD_CONDEXPORT))
		&& ((psq_cb->psq_mode == PSQ_RETRIEVE) ||
		    (psq_cb->psq_mode == PSQ_DEFCURS))
		&& (cb->pss_qualdepth <=1)
		/* make sure we are not processing INSERT ... SELECT */
		&& (   !cb->pss_resrng	    
		    || !cb->pss_resrng->pss_used
		    || cb->pss_resrng->pss_rgno < 0
		   )
		)
	    {
		DB_DATA_VALUE		db_value;
		DB_DATA_VALUE		ev_value;

		db_value.db_datatype = coldesc->att_type;
		db_value.db_length = coldesc->att_width;
		db_value.db_prec = coldesc->att_prec;
		db_value.db_collID = coldesc->att_collID;
		status = adc_dbtoev(adf_scb, &db_value, &ev_value);
		if (DB_FAILURE_MACRO(status))
		{
		    adf_scb->adf_errcb.ad_errclass = ADF_USER_ERROR;
		    psf_adf_error(&adf_scb->adf_errcb, &psq_cb->psq_error, cb);
		    return(status);
		}
		
		coldesc->att_type = ev_value.db_datatype;
		coldesc->att_width = ev_value.db_length;
		coldesc->att_prec = ev_value.db_prec;
		coldesc->att_collID = ev_value.db_collID;
	    }
	} /* If valid data type */

        /* If client can not handle i8 INTs downgrade to i4 */
        if ( abs(coldesc->att_type) == DB_INT_TYPE) 
        {
            adf_scb = (ADF_CB *) cb->pss_adfcb;
            if ( !(adf_scb->adf_proto_level & AD_I8_PROTO))
            {
                if(coldesc->att_type < 0)
                {
                    null_adjust = 1;
                }
                if((coldesc->att_width - null_adjust) == sizeof(i8))
                {
                    coldesc->att_width -= sizeof(i4);
                }
            }
        }
    }
    else
    {
	coldesc->att_type = (DB_DT_ID) DB_NODT;
	coldesc->att_width = (i4) 0;
	coldesc->att_prec = (i4) 0;
	coldesc->att_collID = (i4) -1;
	coldesc->att_geomtype = (i2) -1;
	coldesc->att_srid = (i4) -1;
	coldesc->att_encflags = (i2) 0;
	coldesc->att_encwid = 0;
    }

    return(E_DB_OK);
}
Ejemplo n.º 3
0
DB_STATUS
adc_hg_dtln(
ADF_CB              *adf_scb,
DB_DATA_VALUE	    *adc_fromdv,
DB_DATA_VALUE	    *adc_hgdv)
{
    DB_STATUS		db_stat;
    i4			bdt     = abs((i4) adc_fromdv->db_datatype);
    i4			bdtv;
    i4			dtinfo;	/* Data type status bits for this type */

    for (;;)
    {
        /* Check the consistency of the input datatype id */
	bdtv = ADI_DT_MAP_MACRO(bdt);
        if (bdtv <= 0  ||  bdtv > ADI_MXDTS
		||  Adf_globs->Adi_dtptrs[bdtv] == NULL)
	{
	    db_stat = adu_error(adf_scb, E_AD2004_BAD_DTID, 0);
	    break;
	}

	/* Return error for datatypes that cannot be used in a relation or
	** do not support histograms */
	/* Get datatype status bits into dtinfo */
	db_stat = adi_dtinfo(adf_scb, adc_fromdv->db_datatype, &dtinfo);
	if (!(dtinfo & AD_INDB) || (dtinfo & AD_NOHISTOGRAM))
	{
	    /* This datatype can't be used in a relation or doesn't support
	    ** histograms */
	    db_stat = adu_error(adf_scb, E_AD3011_BAD_HG_DTID, 0);
	    break;
	}

#ifdef xDEBUG
	    /* Check the consistency of adc_fromdv's length */
	    if (db_stat = adc_lenchk(adf_scb, FALSE, adc_fromdv, NULL))
	        break;
#endif  /* xDEBUG */

	/*
	** Now call the low-level routine to do the work.  Note that if the
	** datatype is nullable, we use a temp DV_DATA_VALUE which gets set
	** to the corresponding base datatype and length.
	*/

	if (adc_fromdv->db_datatype > 0)	/* non-nullable */
	{
            db_stat = (*Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]->
			    adi_dt_com_vect.adp_hg_dtln_addr)
				(adf_scb, adc_fromdv, adc_hgdv);
	}
	else					/* nullable */
	{
	    DB_DATA_VALUE tmp_dv = *adc_fromdv;

	    tmp_dv.db_datatype = bdt;
	    tmp_dv.db_length--;

            db_stat = (*Adf_globs->Adi_dtptrs[ADI_DT_MAP_MACRO(bdt)]->
			adi_dt_com_vect.adp_hg_dtln_addr)
				(adf_scb, &tmp_dv, adc_hgdv);
	}
	break;
    }	    /* end of for stmt */

    return(db_stat);
}
Ejemplo n.º 4
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 */