コード例 #1
0
ファイル: opjunion.c プロジェクト: saqibjamil/Ingres
/*{
** Name: opj_ctree	- compare tree for purposes of "union equality"
**
** Description:
**      This routine will return TRUE if the qualifications are 
**      structurally equivalent, and reference the same var nodes 
**
** Inputs:
**      subquery                        ptr to subquery containing qual
**      qual                            qual to compare
**      usubquery                       ptr to union subquery
**      uqual                           ptr to qual in union subquery
**
** Outputs:
**	Returns:
**	    TRUE if qualifications are equivalent 
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      27-jun-89 (seputis)
**          initial creation
[@history_template@]...
*/
static bool
opj_ctree(
	OPS_SUBQUERY       *subquery,
	PST_QNODE          *qual,
	OPV_IVARS	   varno,
	OPS_SUBQUERY       *usubquery,
	PST_QNODE          *uqual)
{
    for (;qual; qual = qual->pst_right, uqual = uqual->pst_right)
    {
	if (!uqual)
	    break;
	if (qual->pst_sym.pst_type == PST_VAR)
	{
	    DB_ATT_ID	attid;

	    if (uqual->pst_sym.pst_type != PST_VAR)
		return(FALSE);
	    opj_uvar(subquery, qual, varno, &attid); /* get the
				    ** union view attribute */
	    return (attid.db_att_id 
		== 
		uqual->pst_sym.pst_value.pst_s_var.pst_atno.db_att_id);
				    /* make sure the same attribute number
				    ** is referenced */
	}
	else
	{   /* use regular comparision routine for all other nodes */
	    PST_QNODE	*lqual;
	    PST_QNODE	*rqual;
	    PST_QNODE	*luqual;
	    PST_QNODE	*ruqual;
	    bool	ret_val;

	    lqual = qual->pst_left;
	    rqual = qual->pst_right;
	    qual->pst_left = (PST_QNODE *)NULL;
	    qual->pst_right = (PST_QNODE *)NULL;
	    luqual = uqual->pst_left;
	    ruqual = uqual->pst_right;
	    uqual->pst_left = (PST_QNODE *)NULL;
	    uqual->pst_right = (PST_QNODE *)NULL;
	    ret_val = opv_ctrees(subquery->ops_global, qual, uqual);
	    qual->pst_left= lqual;
	    qual->pst_right = rqual;
	    uqual->pst_left= luqual;
	    uqual->pst_right = ruqual;
	    if (!ret_val)
		return(FALSE);
	}
	if (qual->pst_left)
	{
	    if (!opj_ctree(subquery, qual->pst_left, varno, usubquery, uqual->pst_left))
		return(FALSE);
	}
    }
    return(qual == uqual);
}
コード例 #2
0
ファイル: opaoptim.c プロジェクト: saqibjamil/Ingres
/*{
** Name: opa_rqual	- remove unnecessary clauses in the qualification
**
** Description:
**      This routine will traverse the qualification of the outer aggregate 
**      which has just been optimized and remove any unnecessary 
**      qualifications, which may occur due to the optimization
**
** Inputs:
**      subquery                        ptr to subquery containing qualification
**      previous			ptr to ptr to qualification list 
**                                      of outer aggregate
**
** Outputs:
**	Returns:
**	    VOID
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	16-apr-86 (seputis)
**          initial creation
[@history_line@]...
*/
static VOID
opa_rqual(
	OPS_SUBQUERY	   *subquery,
	PST_QNODE          **previous)
{
    register PST_QNODE  *bop;   /* ptr to binary operator node associated
                                ** with the qualification
                                */
    register PST_QNODE	*qual;  /* ptr to qualification being analyzed */

    for (qual = *previous;	/* get initial qualification */
	qual && (qual->pst_sym.pst_type == PST_AND); /* check for end of list */
	qual = *previous)	/* get the next qualification 
				** in list */
    {
	/* if this is an EQ node then check for an unnecessary compare */
	bop = qual->pst_left;
	if (bop->pst_sym.pst_type == PST_BOP 
	    && 
	    bop->pst_sym.pst_value.pst_s_op.pst_opno 
	    == 
	    subquery->ops_global->ops_cb->ops_server->opg_eq
	    &&
	    opv_ctrees(subquery->ops_global, bop->pst_left, bop->pst_right)
	    )
	{
	    /* eliminate the equality clause if the left and right side
	    ** are equal
	    */
	    subquery->ops_vmflag = FALSE; /* map invalid since qual is removed*/
	    *previous = qual->pst_right; /* throw away link */
	    continue;   /* previous ptr is still valid so go to top of
			** loop without updating previous
			*/
	}
	previous = &(*previous)->pst_right;
    }
}
コード例 #3
0
ファイル: opaoptim.c プロジェクト: saqibjamil/Ingres
/*{
** Name: opa_commit	- commit the subsitutions found in opa_checkopt
**
** Description:
**      This routine will traverse the outer aggregate in the same way
**      as opa_checkopt but in this traversal, all the substitutions will
**      be made, since it has been determined that they were useful. 
**
** Inputs:
**      global                          global state variable
**      bylist                          bylist used for substitutions
**      varno				var number of inner aggregate
**
** Outputs:
**      root                            ptr to subtree which will have
**                                      all possible substitutions made
**	Returns:
**	    E_DB_OK
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	16-apr-86 (seputis)
**          initial creation
**	5-dec-90 (seputis)
**	    fix b34217 - define eqc for update when agg substitution occurs.
**	6-may-91 (seputis)
**	    fix b37347 - do not substitute constant nodes, since simple
		aggregates have not been fully processed at this point
[@history_line@]...
*/
static VOID
opa_commit(
	OPS_STATE          *global,
	PST_QNODE          *bylist,
	PST_QNODE          **root,
	OPV_IGVARS          varno)
{
    PST_QNODE           *node;	    /* ptr to current by list element being
                                    ** substituted
                                    */

    if ( *root )
    {
	for(node = bylist;	    /* get first element of by list */
	    node && node->pst_sym.pst_type != PST_TREE; /* at the end of 
                                   ** the bylist ? */
	    node = node->pst_left) /* get next bydom attribute */
	{
	    if ( opv_ctrees( global, *root, node->pst_right ) )
	    {
		/* query tree matched so perform substitution */
		DB_ATT_ID    attribute;  /* attribute number of inner aggregate
					** bylist element
					*/
		attribute.db_att_id = node->pst_sym.pst_value.pst_s_rsdm.
		    pst_rsno; 
		/* FIXME - do we need to do a PNODERSLV here??? */
		if ((*root)->pst_sym.pst_type != PST_VAR)
		{
		    /* if node is not a var node then create a new var
                    ** node for the substitution
                    */
		    if ((*root)->pst_sym.pst_type != PST_CONST)
			(*root) = opv_varnode(global, &node->pst_sym.pst_dataval,
			    varno, &attribute); /* do not substitute constant
					** nodes since it is not required and
					** made cause problems if simple aggregates
					** are referenced - fix bug 37347 */
		}
		else
		{
		    if ((global->ops_gmask & OPS_TCHECK)
			&&
			((*root)->pst_sym.pst_value.pst_s_var.pst_atno.db_att_id == DB_IMTID)
			&&
			(   (*root)->pst_sym.pst_value.pst_s_var.pst_vno 
			    ==
			    global->ops_qheader->pst_restab.pst_resvno
			))
		    {	/* if this is the TID eqc which will be used for the
			** update then keep track of it in
			** the global structure, since update by TID will need
			** to be via this temporary by list attribute */
			global->ops_tvar = varno;
			STRUCT_ASSIGN_MACRO( attribute,	global->ops_tattr);
		    }
		    /* if it is already a var then just change it */
		    (*root)->pst_sym.pst_value.pst_s_var.pst_vno = varno;
		    STRUCT_ASSIGN_MACRO( attribute,
			(*root)->pst_sym.pst_value.pst_s_var.pst_atno);
		}
		return;
	    }
	}
	/* try the subtrees if none of the bylist elements matched */
	{
	    if ((*root)->pst_sym.pst_type == PST_VAR)
	    {
		return;
	    }
	    else
	    {
		opa_commit(global, bylist, &((*root)->pst_left), varno);
		opa_commit(global, bylist, &((*root)->pst_right), varno);
	    }
	}
    }
    return;
}
コード例 #4
0
ファイル: opaoptim.c プロジェクト: saqibjamil/Ingres
/*{
** Name: opa_checkopt	- check for possibility of optimization
**
** Description:
**      This routine will create variable map of what the outer aggregate
**      would appear like if all possible substitutions of the inner aggregate
**      bylist attributes were made.  The map of the all the inner aggregate
**      bylist elements used in the substitution is also created.  Thus, if
**      no substitutions are made then this map would be empty.
**
** Inputs:
**      global                          global state variable
**      root                            root of query tree which will
**                                      be analyzed for possible substitutions
**                                      - this root is a subtree of the outer
**                                      aggregate.
**      bylist                          base of bylist which will be
**                                      used for substitutions
**
** Outputs:
**      usedmap                         ptr to map of all variables found
**                                      in the "hit list" i.e. map of variables
**                                      which will be replaced if the
**                                      substitution were actually made
**	newmap				ptr to varmap of root, filled in if 
**					the substitutions were actually made
**	Returns:
**	    varmap of root if the substitutions were actually made
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	15-apr-86 (seputis)
**          initial creation
**	4-dec-02 (inkdo01)
**	    Return variable changed to a call-by-ref parm to support
**	    range table expansion.
[@history_line@]...
*/
static VOID
opa_checkopt(
	OPS_STATE          *global,
	PST_QNODE          *bylist,
	PST_QNODE          *root,
	OPV_GBMVARS	   *usedmap,
	OPV_GBMVARS	   *newmap)
{
    PST_QNODE           *node;	    /* ptr to current by list element being
                                    ** substituted
                                    */

    MEfill(sizeof(*newmap), 0, (char *)newmap); /* init the bit map */

    if ( root )
    {
	for(node = bylist;	    /* get first element of by list */
	    node && node->pst_sym.pst_type != PST_TREE; /* at the end of 
                                    ** the bylist ? */
	    node = node->pst_left)  /* get next bydom attribute */
	{
	    if ( opv_ctrees( global, root, node->pst_right ) )
	    {
		opv_mapvar( root, usedmap); /* update map of global range 
                                    ** variables used in subtree */
		return;             /* substitution is made so no vars will
                                    ** be contributed to the map of the tree
                                    ** after substitution i.e. return 0
                                    */
	    }
	}
	/* try the subtrees if none of the bylist elements matched */
	{
	    OPV_GBMVARS	    tempmap; /* used to create bit map for var node*/

	    if (root->pst_sym.pst_type == PST_VAR)
	    {
		OPV_GRV	    *gvarp;	    /* global range var associated
					    ** with this node */
		BTset( (i4)root->pst_sym.pst_value.pst_s_var.pst_vno, 
		       (char *)newmap);
		gvarp = global->ops_rangetab.opv_base->
		    opv_grv[root->pst_sym.pst_value.pst_s_var.pst_vno];
		if (gvarp->opv_gsubselect
		    &&
		    gvarp->opv_gsubselect->opv_subquery)
		{
		    MEcopy((char *)&gvarp->opv_gsubselect->opv_subquery->
			ops_correlated, sizeof(tempmap), (char *)&tempmap);
		    BTor(OPV_MAXVAR, (char *)&gvarp->opv_gsubselect->opv_subquery->
			ops_fcorelated, (char *)&tempmap);
		    if (BTcount((char *)&tempmap, OPV_MAXVAR))
		    {   /* if a correlated subquery is referenced then the
			** correlated variables cannot be substituted 
                	** - FIXME need to find all correlated vars, and see if
                	** enough attributes exist to supply correlated values
                	** this can be done by running opa_subselect in OPAFINAL.C
                	** prior to this optimization
                	** ... also need to make sure the correlated subquery
                	** is not used in another context as determined by
                	** opa_compat
                	** - for now do not substitute correlated variables
                	*/
			BTor( (i4)BITS_IN(OPV_GBMVARS), (char *)
			    &gvarp->opv_gsubselect->opv_subquery->ops_correlated,
			    (char *)newmap);
			BTor( (i4)BITS_IN(OPV_GBMVARS), (char *)
			    &gvarp->opv_gsubselect->opv_subquery->ops_fcorelated,
			    (char *)newmap);
		    }
		}
		return;		    /* return map with bit set for this var
                                    ** since a substition will not be made, so
                                    ** the var will appear in the optimized tree
                                    ** if it is created */
	    }
	    else
	    {
		opa_checkopt( global, bylist, root->pst_left, usedmap, newmap);
		MEcopy((char *)newmap, sizeof(tempmap), (char *)&tempmap);
		BTand(OPV_MAXVAR, (char *)usedmap, (char *)&tempmap);
		if (BTcount((char *)&tempmap, OPV_MAXVAR))
		    /* if the maps have an intersection then abort the search
                    ** since there will not be a commit made
                    */
		    return;

		/* traverse the right side of the tree */
		opa_checkopt( global, bylist, root->pst_right,usedmap, &tempmap);
		BTor(OPV_MAXVAR, (char *)&tempmap, (char *)newmap);
		return;
		    
	    }
	}
    }
    MEfill(sizeof(*newmap), 0, (char *)newmap); /* return empty map */
    return;
}
コード例 #5
0
ファイル: opabyprj.c プロジェクト: fosslc/Ingres
/*{
** Name: opa_bydom_project	- project the "by domains" if necessary
**
** Description:
**	set the opa_projection flag if we need to project the by domain values
**
**	We don't need to project the by_doms if the aggregate qualification
**      is a subset of the qualification in the parent query
**	In the future, we can implement the code that would turn off projections
**	if the parent restriction was at least as restrictive as the BOOL_EXPR.
**	This would cover the following types of examples:
**		ret (x=sum(r.a by r.b where r.c < C)) where r.c < C - 1.
**			or
**		ret (x=sum(r.a by r.b where r.c = A or r.c = B)) where r.c = A
**
**	The idea is that if the BOOL_EXPR created by-vals with no agg result
**	values then the more restrictive parent qual will throw at
**	least those rows out (and possibly more).
**	However, determining restrictiveness levels is more complicated and I am
**	not sure that it will be needed or will benefit that many people. The
**	Intellegent user can always add a qualification to the outer
**	that mirrors the inner to remove duplicates. Unfortunately this
**	requires knowledge of an implementation.
**
** Inputs:
**      subquery                        ptr to subquery being analzyed
**
** Outputs:
**	Returns:
**	    TRUE - if the "by domain values" require projection
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	13-apr-86 (seputis)
**          initial creation from bydom_project
[@history_line@]...
*/
static bool
opa_bydomproject(
    OPS_SUBQUERY       *subquery)
{
    PST_QNODE           *inner;	    /* ptr to qualification list for inner
                                    ** aggregate */
    PST_QNODE           *outer;	    /* ptr to qualification list for outer
				    ** aggregate */

    if (subquery->ops_root->pst_right
            &&
            (subquery->ops_root->pst_right->pst_sym.pst_type == PST_QLEND)
       )
        return(FALSE);		    /* there is no qualification so do not
                                    ** project */

    outer = subquery->ops_agg.opa_father->ops_root->pst_right;/* this
				    ** node is the right branch of the parent
				    ** subquery root node, which should be the
				    ** qualification in both the aghead case
				    ** and root node case
				    */

    /* Since there is a list of subqueries, the multi_parent failure can
    ** be eliminated if code was written to test each of the subqueries
    ** which will be executed together (FIXME)
    */
    if ((outer && (outer->pst_sym.pst_type == PST_QLEND)) /* if no
				    ** parent qualification */
            ||
            subquery->ops_agg.opa_multi_parent
       )			    /* OR more than one parent for this
				    ** aggregate */
        return (TRUE);		    /* project since aggregate qualification
				    ** is not a subset of the parent's
				    */

    opj_normalize(subquery, &subquery->ops_root->pst_right);
    /* normalize inner subquery if necessary*/
    opj_normalize(subquery->ops_agg.opa_father,
                  &subquery->ops_agg.opa_father->ops_root->pst_right);    /* normalize
				    ** outer subquery if necessary*/

    outer = subquery->ops_agg.opa_father->ops_root->pst_right;/* this
				    ** node is the right branch of the parent
				    ** subquery root node, which should be the
				    ** qualification in both the aghead case
				    ** and root node case
				    */
    /*find a match for each qualification in the aggregate qualification list */
    for (inner = subquery->ops_root->pst_right; /* qualification is on the
				    ** right branch of the root node */
            inner->pst_sym.pst_type != PST_QLEND;
            inner = inner->pst_right)   /*get next inner conjunct of qualification*/
    {
        bool	    status; /* TRUE if projection is required */
        PST_QNODE	    *tmp;   /* used to traverse parent qualification
				    ** list
				    */
        status = TRUE;	    /* assume projection is required until
				    ** a match is found in the parent's list
				    */
        for (tmp = outer;
                tmp->pst_sym.pst_type != PST_QLEND;
                tmp = tmp->pst_right)
        {
            if (opv_ctrees(subquery->ops_global, inner->pst_left,
                           tmp->pst_left)
               )
            {
                /* compare the inner aggregate conjunct tree with the
                        ** each conjunct of the outer aggregate qualification,
                ** - if a match is found then try the next inner conjunct
                ** - if a match is not found then the qualification
                        ** may not be a subset so a projection is required
                */
                status = FALSE; /* do not project */
                break;
            }
        }

        if (status)
            return(TRUE);   /* quit if no matching qual in outer qual
				** - project is required since qualification
				** is not a subset
				*/


    }
    return (FALSE); /* do not project since the aggregate qualification
		    ** is a subset of the parent's qualification
		    */
}