Beispiel #1
0
/*
** Name: adu_ascii_2arg() - Convert a data value to character string data value.
**
** Description:
**      Support the two argument version of string functions CHAR(), VARCHAR(),
**      TEXT() and C().  Simply call adu_ascii() to do the real work.
**
** Inputs:
**	adf_scb				Pointer to an ADF session control block.
**      dv1                             DB_DATA_VALUE describing Ingres datatype
**					to be converted.
**	    .db_datatype		Its type.
**	    .db_prec			Its precision/scale.
**	    .db_length			Its length.
**	    .db_data			Ptr to the data to be converted into
**					a character string.
**	rdv				DB_DATA_VALUE describing character
**					string result.
**	    .db_length			The maximum length of the result.
**	    .db_data			Ptr to buffer to hold converted string.
**
** Outputs:
**	adf_scb				Pointer to an ADF session control block.
**	rdv
**	    .db_data			The converted string.
**
**      Returns:
**	      The following DB_STATUS codes may be returned:
**	    E_DB_OK, E_DB_WARN, E_DB_ERROR, E_DB_SEVERE, E_DB_FATAL
**
**	      If a DB_STATUS code other than E_DB_OK is returned, the caller
**	    can look in the field adf_scb.adf_errcb.ad_errcode to determine
**	    the ADF error code.  The following is a list of possible ADF error
**	    codes that can be returned by this routine:
**
**	    E_AD0000_OK			Routine completed successfully.
**	    E_AD5001_BAD_STRING_TYPE	Either dv1's or rdv's datatype was
**					inappropriate for this operation.
**
**  History:
**     31-dec-1992 (stevet)
**         Created.
**     10-jun-1993 (stevet)
**         Modified to disable string truncation detection since this function
**         is behaved like the left() function.
*/
DB_STATUS
adu_ascii_2arg(
ADF_CB			*adf_scb,
DB_DATA_VALUE	        *dv1,
DB_DATA_VALUE	        *dv2,
DB_DATA_VALUE		*rdv)
{
    ADF_STRTRUNC_OPT  input_strtrunc=adf_scb->adf_strtrunc_opt;
    STATUS            status;

    adf_scb->adf_strtrunc_opt = ADF_IGN_STRTRUNC;
    if (dv1->db_datatype == DB_NCHR_TYPE || dv1->db_datatype == DB_NVCHR_TYPE)
	status = adu_nvchr_coerce(adf_scb, dv1, rdv);
    else
	status = adu_ascii(adf_scb, dv1, rdv);
    adf_scb->adf_strtrunc_opt = input_strtrunc;
    return( status);
}
Beispiel #2
0
DB_STATUS
adu_like_all(
	ADF_CB		*adf_scb,
	DB_DATA_VALUE	*src_dv,
	DB_DATA_VALUE	*pat_dv,
	DB_DATA_VALUE	*esc_dv,
	u_i4		pat_flags,
	i4		*rcmp)
{
    DB_STATUS db_stat = E_DB_OK;
    AD_PAT_SEA_CTX _sea_ctx;
    AD_PAT_SEA_CTX *sea_ctx = &_sea_ctx;
    AD_PATDATA _patdata;
    AD_PATDATA *patdata;
    AD_PAT_DA_CTX da_ctx;
    DB_DATA_VALUE dv_tmp1;
    DB_DATA_VALUE dv_tmp2;
    DB_DATA_VALUE *s1 = src_dv, *p1 = pat_dv;
    i4 rcmp1 = 0;
    i4 long_seen = 0;
    DB_STATUS db_stat1 = E_DB_OK;
    char tmp[2000];
    i2 saved_uninorm_flag = adf_scb->adf_uninorm_flag;
    static struct {
	ADU_PATCOMP_FUNC *compile;
	ADU_PATEXEC_FUNC *execute;
    } rtns[] = {
	{adu_patcomp_like,     adu_pat_execute},
	{adu_patcomp_like,     adu_pat_execute_col},
	{adu_patcomp_like_uni, adu_pat_execute_uni},
    };
    enum rtns_idx {
	LIKE, LIKE_COLLATION, LIKE_UNICODE 
    } form = LIKE;
    
    if (pat_dv->db_datatype == DB_PAT_TYPE)
    {
	patdata = (AD_PATDATA*)pat_dv->db_data;
	if (ME_ALIGN_MACRO(patdata, sizeof(i2)) != (PTR)patdata)
	{
	    if ((i2)sizeof(_patdata) >= pat_dv->db_length)
		patdata = &_patdata;
	    else
	    {
		patdata = (AD_PATDATA*)MEreqmem(0, pat_dv->db_length,
			    FALSE, &db_stat);
		if (!patdata || db_stat)
		    return db_stat;
	    }
	    MEcopy(pat_dv->db_data, pat_dv->db_length, patdata);
	}
	pat_flags = patdata->patdata.flags|
		    (patdata->patdata.flags2<<16);
	/* Pre-compiled pattern */
	{
	    i4 i;
	    /* ->patdata is passed in preset with a valid [PATDATA_LENGTH] -
	    ** save it now as we will clear the lot */
	    MEfill(sizeof(*sea_ctx), 0, (PTR)sea_ctx);
	    sea_ctx->patdata = patdata;
	    /*sea_ctx->buffer = NULL;*/
	    /*sea_ctx->bufend = NULL;*/
	    /*sea_ctx->buftrueend = NULL;*/
	    /*sea_ctx->seg_offset = 0;*/
	    /*sea_ctx->buflen = 0;*/
	    /*sea_ctx->at_bof = FALSE;*/
	    /*sea_ctx->at_eof = FALSE;*/
	    /*sea_ctx->trace = FALSE;*/
	    /*sea_ctx->force_fail = FALSE;*/
	    /*sea_ctx->cmplx_lim_exc = FALSE;*/
	    /*sea_ctx->stalled = NULL;*/
	    /*sea_ctx->pending = NULL;*/
	    /*sea_ctx->free = NULL;*/
	    /*sea_ctx->setbuf = NULL;*/
#if PAT_DBG_TRACE>0
	    /*sea_ctx->nid = 0;*/
	    /*sea_ctx->infile = NULL;*/
	    /*sea_ctx->outfile = NULL;*/
#endif
	    /*sea_ctx->nctxs_extra = 0;*/
	    sea_ctx->nctxs = DEF_THD;
	    for (i = DEF_THD-1; i >= 0; i--)
	    {
		sea_ctx->ctxs[i].next = sea_ctx->free;
		sea_ctx->free = &sea_ctx->ctxs[i];
	    }
	}
	db_stat = adu_patcomp_set_pats(sea_ctx);

	/* If prior patcomp flagged force_fail - obey it */
	if (patdata->patdata.flags2 & AD_PAT2_FORCE_FAIL)
	    sea_ctx->force_fail = TRUE;
    }
    else
    {
	patdata = &_patdata;
	/* Tell compiler size we are prepared for */
	patdata->patdata.length = sizeof(_patdata)/sizeof(_patdata.vec[0]);
	sea_ctx->patdata = patdata;
	/*
	** To allow for default processing we have the user specified
	** case flags to deal with. If AD_PAT_WITH_CASE or AD_PAT_WO_CASE
	** is set then we use that setting to override any collation
	** case request. If neither are set we obey the collation.
	*/
	if (pat_flags & AD_PAT_WITH_CASE)
	{
	    pat_flags &= ~AD_PAT_WO_CASE;
	}
	else if (!(pat_flags & AD_PAT_WO_CASE) &&
		(src_dv->db_collID == DB_UNICODE_CASEINSENSITIVE_COLL ||
		pat_dv->db_collID == DB_UNICODE_CASEINSENSITIVE_COLL))
	{
	    pat_flags |= AD_PAT_WO_CASE;
	}
	/*
	** From this point on, the AD_PAT_WITH_CASE flag is ignored as
	** its state has been folded into the AD_PAT_WO_CASE flag.
	*/
    }

    if (ADU_pat_legacy == -1)
	pat_flags &= ~AD_PAT_WO_CASE;
    else if (ADU_pat_legacy == -2)
	pat_flags |= AD_PAT_WO_CASE;

    dv_tmp1.db_data = NULL;
    dv_tmp2.db_data = NULL;

    switch (abs(src_dv->db_datatype))
    {
    case DB_LNVCHR_TYPE:
    case DB_LNLOC_TYPE:
	long_seen = 1;
    case DB_NVCHR_TYPE:
    case DB_NCHR_TYPE:
    case DB_UTF8_TYPE:
    case DB_NQTXT_TYPE:
	form = LIKE_UNICODE;
	/* All handled directly by DA */
	break;
    case DB_LVCH_TYPE:
    case DB_LCLOC_TYPE:
	if (adf_scb->adf_utf8_flag & AD_UTF8_ENABLED)
	    form = LIKE_UNICODE;
    case DB_LBYTE_TYPE:
    case DB_LBLOC_TYPE:
	long_seen = 1;
    case DB_BYTE_TYPE:
    case DB_VBYTE_TYPE:
	/* All handled directly by DA */
	break;
    case DB_CHR_TYPE:
	pat_flags |= AD_PAT_BIGNORE;	/* Ignore blanks */
	/*FALLTHROUGH*/
    case DB_CHA_TYPE:
    case DB_VCH_TYPE:
    case DB_TXT_TYPE:
    case DB_LTXT_TYPE:
	if (adf_scb->adf_utf8_flag & AD_UTF8_ENABLED)
	{
	    form = LIKE_UNICODE;
	    dv_tmp1.db_datatype = DB_NVCHR_TYPE;
	    dv_tmp1.db_length = src_dv->db_length * 4 + DB_CNTSIZE;
	    dv_tmp1.db_prec = 0;
	    dv_tmp1.db_collID = -1;
	    if (dv_tmp1.db_length < (i2)sizeof(tmp))
		dv_tmp1.db_data = tmp;
	    else
	    {
		dv_tmp1.db_data = (char *) MEreqmem (0, dv_tmp1.db_length, TRUE, &db_stat);
		if (db_stat)
		    return db_stat;
	    }
            adf_scb->adf_uninorm_flag = AD_UNINORM_NFC;
	    db_stat = adu_nvchr_fromutf8(adf_scb, src_dv, &dv_tmp1);
            adf_scb->adf_uninorm_flag = saved_uninorm_flag;
	    src_dv = &dv_tmp1;
	}
	break;
    default:
	return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0));
    }

    /*
    ** See how the pattern looks and coerce appropriatly
    */
    switch (abs(pat_dv->db_datatype))
    {
    case DB_LNVCHR_TYPE:
    case DB_LNLOC_TYPE:
	long_seen = 1;
    case DB_NVCHR_TYPE:
    case DB_NCHR_TYPE:
    case DB_UTF8_TYPE:
    case DB_NQTXT_TYPE:
	if (form != LIKE_UNICODE)
	{
	    DB_DATA_VALUE dv_tmp3;
	    form = LIKE_UNICODE;
	    dv_tmp1.db_datatype = DB_NVCHR_TYPE;
	    dv_tmp1.db_length = src_dv->db_length * 3 + DB_CNTSIZE;
	    dv_tmp1.db_prec = 0;
	    dv_tmp1.db_collID = -1;
	    dv_tmp3.db_datatype = DB_NVCHR_TYPE;
	    dv_tmp3.db_length = src_dv->db_length * 3 + DB_CNTSIZE;
	    dv_tmp3.db_prec = 0;
	    dv_tmp3.db_collID = -1;
	    if (dv_tmp1.db_length < (i2)sizeof(tmp))
		dv_tmp1.db_data = tmp;
	    else
	    {
		dv_tmp1.db_data = (char *) MEreqmem (0, dv_tmp1.db_length, TRUE, &db_stat);
		if (db_stat)
		    return db_stat;
	    }
	    dv_tmp3.db_data = (char *) MEreqmem (0, dv_tmp3.db_length, TRUE, &db_stat);
	    if (db_stat)
		return db_stat;
	    if (db_stat = adu_nvchr_coerce(adf_scb, src_dv, &dv_tmp3))
	    {
		if (dv_tmp1.db_data && dv_tmp1.db_data != tmp)
		    MEfree((char *)dv_tmp1.db_data);
		return db_stat;
	    }

            adf_scb->adf_uninorm_flag = AD_UNINORM_NFC;
	    db_stat = adu_unorm(adf_scb, &dv_tmp3, &dv_tmp1);
            adf_scb->adf_uninorm_flag = saved_uninorm_flag;
	    MEfree((char *)dv_tmp3.db_data);
	    if (db_stat)
	    {
		if (dv_tmp1.db_data && dv_tmp1.db_data != tmp)
		    MEfree((char *)dv_tmp1.db_data);
		return db_stat;
	    }
	    src_dv = &dv_tmp1;
	}
	break;
    case DB_CHR_TYPE:
	pat_flags |= AD_PAT_BIGNORE;	/* Ignore blanks */
	/*FALLTHROUGH*/
    case DB_LVCH_TYPE:
    case DB_LCLOC_TYPE:
    case DB_LBYTE_TYPE:
    case DB_LBLOC_TYPE:
    case DB_BYTE_TYPE:
    case DB_VBYTE_TYPE:
    case DB_CHA_TYPE:
    case DB_VCH_TYPE:
    case DB_TXT_TYPE:
    case DB_LTXT_TYPE:
	if (form == LIKE_UNICODE)
	{
	    DB_DATA_VALUE dv_tmp3;
	    dv_tmp2.db_datatype = DB_NVCHR_TYPE;
	    dv_tmp2.db_length = pat_dv->db_length * 4 + DB_CNTSIZE;
	    dv_tmp2.db_prec = 0;
	    dv_tmp2.db_collID = -1;
	    dv_tmp3.db_datatype = DB_NVCHR_TYPE;
	    dv_tmp3.db_length = pat_dv->db_length * 3 + DB_CNTSIZE;
	    dv_tmp3.db_prec = 0;
	    dv_tmp3.db_collID = -1;
	    if (dv_tmp2.db_length < (i2)sizeof(tmp) && dv_tmp1.db_data != tmp)
		dv_tmp2.db_data = tmp;
	    else
	    {
		dv_tmp2.db_data = (char *) MEreqmem (0, dv_tmp2.db_length, TRUE, &db_stat);
		if (db_stat)
		    return db_stat;
	    }
	    if (adf_scb->adf_utf8_flag & AD_UTF8_ENABLED)
            {
                adf_scb->adf_uninorm_flag = AD_UNINORM_NFC;
		db_stat = adu_nvchr_fromutf8(adf_scb, pat_dv, &dv_tmp2);
                adf_scb->adf_uninorm_flag = saved_uninorm_flag;
            }
	    else
	    {
		dv_tmp3.db_data = (char *) MEreqmem (0, dv_tmp3.db_length, TRUE, &db_stat);
		if (db_stat)
		    return db_stat;
		if (db_stat = adu_nvchr_coerce(adf_scb, pat_dv, &dv_tmp3))
		{
		    if (dv_tmp2.db_data && dv_tmp2.db_data != tmp)
			MEfree((char *)dv_tmp2.db_data);
		    return db_stat;
		}
                adf_scb->adf_uninorm_flag = AD_UNINORM_NFC;
		db_stat = adu_unorm(adf_scb, &dv_tmp3, &dv_tmp2);
                adf_scb->adf_uninorm_flag = saved_uninorm_flag;
		MEfree((char *)dv_tmp3.db_data);
		if (db_stat)
		{
		    if (dv_tmp2.db_data && dv_tmp2.db_data != tmp)
			MEfree((char *)dv_tmp2.db_data);
		    return db_stat;
		}
	    }
	    pat_dv = &dv_tmp2;
	}
	break;
    case DB_PAT_TYPE:
	if (patdata->patdata.flags2 & AD_PAT2_UNICODE)
	    form = LIKE_UNICODE;
	else if (patdata->patdata.flags2 & AD_PAT2_COLLATE)
	    form = LIKE_COLLATION;
	break;
    default:
	return(adu_error(adf_scb, E_AD9999_INTERNAL_ERROR, 0));
    }

    if (abs(pat_dv->db_datatype) != DB_PAT_TYPE)
    {
	if (form == LIKE && adf_scb->adf_collation)
	{
	    form = LIKE_COLLATION;
	    pat_flags |= (AD_PAT2_COLLATE<<16);
	}
	else if (form == LIKE_UNICODE)
	    pat_flags |= (AD_PAT2_UNICODE<<16);

	if (ADU_pat_legacy > 0 &&
		    !long_seen &&
		    (pat_flags & AD_PAT_FORM_MASK) == AD_PAT_FORM_LIKE)
	{
	    if (form == LIKE_UNICODE)
		db_stat1 = adu_ulike(adf_scb, s1, p1,
			(UCS2*)(esc_dv?esc_dv->db_data:0), &rcmp1);
	    else
		db_stat1 = adu_like(adf_scb, s1, p1,
			(u_char*)(esc_dv?esc_dv->db_data:0), &rcmp1);
	    if (ADU_pat_legacy == 3)
	    {
		/* Look no further */
		*rcmp = rcmp1;
		if (dv_tmp1.db_data && dv_tmp1.db_data != tmp)
		    MEfree((char *)dv_tmp1.db_data);
		if (dv_tmp2.db_data && dv_tmp2.db_data != tmp)
		    MEfree((char *)dv_tmp2.db_data);
		return db_stat1;
	    }
	}

	/* Compile the input pattern */
	db_stat = (rtns[form].compile)(adf_scb, pat_dv, esc_dv, pat_flags, sea_ctx);
    }
    if (!db_stat && sea_ctx)
    {
	if (sea_ctx->force_fail)
	    *rcmp = 1;
	else
	{
	    /* Init the data access */
	    if (!(db_stat = adu_patda_init(adf_scb, src_dv, sea_ctx, &da_ctx)))
	    {
		/* Do the search */
		db_stat = (rtns[form].execute)(sea_ctx, &da_ctx, rcmp);
	    }
	    /* Cleanup the data access */
	    (VOID)adu_patda_term(&da_ctx);
	    if (!db_stat && sea_ctx->cmplx_lim_exc)
		db_stat = adu_error(adf_scb, E_AD1026_PAT_TOO_CPLX, 0);
        }
    }
    adu_patcomp_free(sea_ctx);

    if (dv_tmp1.db_data && dv_tmp1.db_data != tmp)
	MEfree((char *)dv_tmp1.db_data);
    if (dv_tmp2.db_data && dv_tmp2.db_data != tmp)
	MEfree((char *)dv_tmp2.db_data);
    if (patdata != &_patdata && (PTR)patdata != pat_dv->db_data)
	MEfree((PTR)patdata);

    if (ADU_pat_legacy > 0 &&
		!long_seen &&
		(pat_flags & AD_PAT_FORM_MASK) == AD_PAT_FORM_LIKE)
    {
	if (db_stat1 && db_stat)
	{
	    /* Old unsupported? - just report */
	    TRdisplay("%s old fail - %d %d osts=%d nsts=%d\n",
		pat_flags & AD_PAT_WO_CASE?"ILIKE":"LIKE",
		s1->db_datatype, p1->db_datatype,
		db_stat1, db_stat);
	}
	else if (db_stat1 && !db_stat)
	{
	    /* NEW SOLUTION - */
	    TRdisplay("%s new support - %d %d osts=%d\n",
		pat_flags & AD_PAT_WO_CASE?"ILIKE":"LIKE",
		s1->db_datatype, p1->db_datatype,
		db_stat1);
	}
	else if (!db_stat1 && db_stat)
	{
	    i4 sl, pl;
	    char *s, *p;
	    /*NEW PROB - report & fixup */
	    adu_lenaddr(adf_scb, s1, &sl, &s);
	    adu_lenaddr(adf_scb, p1, &pl, &p);
	    TRdisplay("%s new problem - %d %d nsts=%d ores=%d nres=%d '%.#s' '%.#s'\n",
		pat_flags & AD_PAT_WO_CASE?"ILIKE":"LIKE",
		s1->db_datatype, p1->db_datatype,
		db_stat,
		rcmp1, *rcmp,
		sl,s,pl,p);
	    if (ADU_pat_legacy > 1)
	    {
		*rcmp = rcmp1;
		db_stat = db_stat1;
	    }
	}
	else if (*rcmp != rcmp1)
	{
	    i4 sl, pl;
	    char *s, *p;
	    /*NEW PROB - report & fixup */
	    adu_lenaddr(adf_scb, s1, &sl, &s);
	    adu_lenaddr(adf_scb, p1, &pl, &p);
	    TRdisplay("%s bad? %d %d ores=%d nres=%d '%.#s' '%.#s'\n",
		pat_flags & AD_PAT_WO_CASE?"ILIKE":"LIKE",
		s1->db_datatype, p1->db_datatype,
		rcmp1, *rcmp,
		sl,s,pl,p);
	    if (ADU_pat_legacy > 1)
	    {
		*rcmp = rcmp1;
		db_stat = db_stat1;
	    }
	}
    }
    return db_stat;
}