Example #1
0
/*{
** Name: opx_error	- this routine will report an optimizer error
**
** Description:
**      This routine will report a E_DB_ERROR optimizer error.  The routine
**      will not return but instead generate an internal exception and
**      exit via the exception handling mechanism.  The error code will be
**      placed directly in the user's calling control block.  A ptr to this
**      block was placed in the session control block (which can be requested
**      from SCF)
**
** Inputs:
**      error                           optimizer error code to report
**
** Outputs:
**	Returns:
**	    - routine does not return
**	Exceptions:
**	    - internal exception generated
**
** Side Effects:
**	    the exception handling routines are responsible for
**          deallocating OPF resources bound to this session.
**
** History:
**	3-jul-86 (seputis)
**          initial creation
[@history_line@]...
*/
VOID
opx_error(
	OPX_ERROR          error)
{
    OPS_CB              *opscb;			/* ptr to session control block
                                                ** for this optimization */
    opscb = ops_getcb();
    opscb->ops_retstatus = E_DB_ERROR;          /* return status code */
    opx_rerror( opscb->ops_callercb, error);    /* log error */
    EXsignal( (EX)EX_JNP_LJMP, (i4)1, (long)error);/* signal an optimizer long
                                                ** jump */
}
Example #2
0
/*{
** Name: opx_exception	- handle unknown exception for optimizer
**
** Description:
**      This routine will handle unknown exceptions for the optimizer
**
** Inputs:
**      ex_args                         argument list from exception handler
**
** Outputs:
**	Returns:
**	    STATUS - appropriate CL return code for exception handler
**	Exceptions:
**
**
** Side Effects:
**
**
** History:
**      20-jan-87 (seputis)
**	    initial creation
**      7-nov-88 (seputis)
**          use EXsys_report
**      26-jun-91 (seputis)
**          added check for OPC access violations
**	11-mar-92 (rog)
**	    Use EXsys_report for everything, not just EXSEGVIO.  Call
**	    scs_avformat to dump info about the offending session.  Remove
**	    underscores from EX return statuses.
**	02-jul-1993 (rog)
**	    Call ulx_exception() to handle all of the reporting duties.
**	    OPF should need to call adx_handler, so remove call to
**	    opx_adfexception().
[@history_line@]...
[@history_template@]...
*/
STATUS
opx_exception(
	EX_ARGS            *args)
{
    /* unexpected exception so record the error and return to
    ** deallocate resources */

    OPS_CB	*opscb; /* session control block */
    OPF_CB	*opfcb; /* caller's control block */
    OPX_ERROR	errorcode; /* error code for exception */

    opscb = ops_getcb();	/* get optimizer session control block */
    opfcb = opscb->ops_state->ops_caller_cb; /* report unexpected exception
                                ** otherwise */
    if (opfcb->opf_errorblock.err_code == E_OP0082_UNEXPECTED_EX)
    {	/* try to check for exception within an exception as soon as possible */
	errorcode = E_OP0083_UNEXPECTED_EXEX; /* second exception
				** occurred so do not deallocate
				** any resources */
	opscb->ops_retstatus = E_DB_SEVERE; /* make sure an high enough priority
                                ** error is reported */
    }
    else
    {
	if (opscb->ops_state->ops_gmask & OPS_OPCEXCEPTION)
	    errorcode = E_OP08A2_EXCEPTION; /* check for exception in
				** OPC component of OPF */
	else
	    errorcode = E_OP0082_UNEXPECTED_EX; /* check for exception
				** in non-OPC components of OPF */
    }

    ulx_exception( args, DB_OPF_ID, E_OP0901_UNKNOWN_EXCEPTION, TRUE);

    if (opscb->ops_retstatus != E_DB_SEVERE
	&&
	opscb->ops_retstatus != E_DB_FATAL)
	opscb->ops_retstatus = E_DB_ERROR; /* make sure an high enough priority
                                ** error is reported */
    opx_rerror(opscb->ops_state->ops_caller_cb, errorcode);/*log error*/
    return (EXDECLARE);        /* return to exception handler declaration pt */
}
Example #3
0
/*{
** Name: ops_alter	- alter session or server state for OPF
**
** Description:
**      This routine contains all processing of the SET commands for the
**      optimizer.  These commands can be at the server or session level.
**      There is currently no protection mechanism available for which
**      users are able to access these SET commands.  There probably should
**      be a system catalog created to decide privileges and min and max
**      values allowable for a session.  Currently, all users can do anything
**      at all.  This routine will not do anything in terms of checking
**      privileges.
**
**      SET [[SESSION] | SERVER] CPUFACTOR <value>
**      SET [[SESSION] | SERVER] TIMEOUT   <value>
**      SET [[SESSION] | SERVER] QEP
**      SET [[SESSION] | SERVER] NOQEP
**      SET [[SESSION] | SERVER] RET_INTO <storage_structure>
**
**      FIXME need to use semaphores to access global structures.
**
** Inputs:
**      opf_cb                          ptr to caller's control block
**
** Outputs:
**	Returns:
**	    E_DB_OK
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	30-jun-86 (seputis)
**          initial creation
[@history_line@]...
*/
DB_STATUS
ops_alter(
    OPF_CB             *opf_cb)
{
    DB_STATUS           status;			/* user return status */

    switch (opf_cb->opf_level)
    {
    case OPF_SERVER:
    {   /* change operating characteristics of the server */
        DB_STATUS	temp_status;
        /* get exclusive access before updating */
        status = ops_exlock(opf_cb,
                            &((OPS_CB *)(opf_cb->opf_scb))->ops_server->opg_semaphore);
        if (DB_FAILURE_MACRO(status))
            break;
        temp_status = ops_change( opf_cb,
                                  &((OPG_CB*)opf_cb->opf_server)->opg_alter);
        /* release exclusive access */
        status = ops_unlock(opf_cb,
                            &((OPS_CB *)(opf_cb->opf_scb))->ops_server->opg_semaphore);
        if (DB_SUCCESS_MACRO(status))
            status = temp_status;
        break;
    }
    case OPF_SESSION:
    {   /* change operating characteristics of this session */
        status = ops_change( opf_cb, &((OPS_CB *)(opf_cb->opf_scb))->ops_alter);
        break;
    }
    default:
# ifdef E_OP0089_ALTER
    {
        opx_rerror( opf_cb, E_OP0089_ALTER);
        return( E_DB_ERROR );
    }
#endif
    }
    return (status);
}
Example #4
0
/*{
** Name: ops_change	- change characteristics for SET command
**
** Description:
**      This routine will change the characteristics of an OPS_ALTER
**      control block
**
** Inputs:
**      opf_cb                          ptr to caller's control block
**      altercb                         ptr to alter control block to update
**
** Outputs:
**	Returns:
**	    E_DB_OK, E_DB_ERROR
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	1-jul-86 (seputis)
**          initial creation
**	8-aug-89 (seputis)
**          added OPF_SUBSELECT
**	12-jul-90 (seputis)
**	    added OPS_ARESOURCE and OPS_ANORESOURCE for b30809
**	22-jul-02 (inkdo01)
**	    Added OPF_[NO]OPTIMIZEONLY to obviate need for tp auth.
**	4-june-03 (inkdo01)
**	    Added "set [no]ojflatten" as synonym for tp op134.
**	11-june-03 (inkdo01)
**	    Added support for "set joinop [no]newenum", "set [no]hash".
**	4-mar-04 (inkdo01)
**	    Added support for "set [no]parallel [n]".
**      17-Aug-2010 (horda03) b124274
**          IF SET QEP and opf_value set then enable Segmented QEP
**          displays. disable otherwise.
[@history_line@]...
*/
static DB_STATUS
ops_change(
    OPF_CB             *opf_cb,
    OPS_ALTER          *altercb)
{
    i4			opcode;			/* characteristic to be changed
                                                */
    DB_DEBUG_CB		debugcb;
    opcode = opf_cb->opf_alter;
    {
        switch (opcode)
        {
        case OPF_MEMORY:
        {
            altercb->ops_maxmemory = opf_cb->opf_value; /* new default memory */
            break;
        }
        case OPF_INLIST_THRESH:
        {
            altercb->ops_inlist_thresh = opf_cb->opf_value; /* new default inlist threshold */
            break;
        }
        case OPF_TIMEOUT:
        {
            altercb->ops_timeout = TRUE;
            altercb->ops_sestime = opf_cb->opf_value; /* new default timeout */
            break;
        }
        case OPF_TIMEOUTABORT:
        {
            altercb->ops_timeout = TRUE;
            altercb->ops_timeoutabort = opf_cb->opf_value;
            break;
        }
        case OPF_NOTIMEOUT:
        {
            altercb->ops_timeout = FALSE;
            break;
        }
        case OPF_CPUFACTOR:
        {
            altercb->ops_cpufactor = opf_cb->opf_value; /* new default weight
		** between CPU and I/O */
            break;
        }
        case OPF_QEP:
        {
            altercb->ops_qep = TRUE;	        /* print QEP */
            altercb->ops_qep_flag = opf_cb->opf_value ? ULD_FLAG_SEGMENTS : ULD_FLAG_NONE;
            break;
        }
        case OPF_NOQEP:
        {
            altercb->ops_qep = FALSE;	        /* print qep */
            altercb->ops_qep_flag = ULD_FLAG_NONE;
            break;
        }
        case OPF_RET_INTO:
        {
            altercb->ops_storage = opf_cb->opf_value;	/* default storage
		** structure for temps */
            altercb->ops_compressed = opf_cb->opf_compressed;	/* default
		** compressed mode structure
		** for temps */
            break;
        }
        case OPF_SUBSELECT:
        {
            /* FIXME - probably should make this a session control variable
            ** rather than using a trace flag */
            debugcb.db_trswitch = DB_TR_ON;
            debugcb.db_value_count = 0;
            debugcb.db_trace_point = OPT_GMAX + OPT_F004_FLATTEN;
            opt_call(&debugcb);	    /* turn OFF flattening */
            break;
        }
        case OPF_NOSUBSELECT:
        {
            debugcb.db_trswitch = DB_TR_OFF;
            debugcb.db_value_count = 0;
            debugcb.db_trace_point = OPT_GMAX + OPT_F004_FLATTEN;
            opt_call(&debugcb);	    /* turn ON flattening */
            break;
        }
        case OPF_OJSUBSELECT:
        {
            debugcb.db_trswitch = DB_TR_OFF;
            debugcb.db_value_count = 0;
            debugcb.db_trace_point = OPT_GMAX + OPT_F006_NONOTEX;
            opt_call(&debugcb);	    /* turn ON OJ flattening */
            break;
        }
        case OPF_NOOJSUBSELECT:
        {
            debugcb.db_trswitch = DB_TR_ON;
            debugcb.db_value_count = 0;
            debugcb.db_trace_point = OPT_GMAX + OPT_F006_NONOTEX;
            opt_call(&debugcb);	    /* turn OFF OJ flattening */
            break;
        }
        case OPF_OPTIMIZEONLY:
        {
            debugcb.db_trswitch = DB_TR_ON;
            debugcb.db_value_count = 0;
            debugcb.db_trace_point = OPT_GMAX + OPT_F032_NOEXECUTE;
            opt_call(&debugcb);	    /* turn OFF execution */
            break;
        }
        case OPF_NOOPTIMIZEONLY:
        {
            debugcb.db_trswitch = DB_TR_OFF;
            debugcb.db_value_count = 0;
            debugcb.db_trace_point = OPT_GMAX + OPT_F032_NOEXECUTE;
            opt_call(&debugcb);	    /* turn ON execution */
            break;
        }
        case OPF_HASH:
        {
            altercb->ops_hash = TRUE;		/* enable hash join/agg */
            break;
        }
        case OPF_NOHASH:
        {
            altercb->ops_hash = FALSE;		/* disable hash join/agg */
            break;
        }
        case OPF_NEWENUM:
        {
            altercb->ops_newenum = TRUE;	/* enable new enumeration */
            break;
        }
        case OPF_NONEWENUM:
        {
            altercb->ops_newenum = FALSE;	/* disable new enumeration */
            break;
        }
        case OPF_PARALLEL:
        {
            altercb->ops_parallel = TRUE;	/* enable || query plans */
            if (opf_cb->opf_value >= 0)
                altercb->ops_pq_dop = opf_cb->opf_value;
            /* update degree of ||ism */
            break;
        }
        case OPF_NOPARALLEL:
        {
            altercb->ops_parallel = FALSE;	/* disable || query plans */
            break;
        }
        case OPF_ARESOURCE:
        {
            altercb->ops_amask |= OPS_ARESOURCE; /* causes enumeration
    ** to be used in all cases so that
    ** resource control gets accurate
    ** estimates */
            break;
        }
        case OPF_ANORESOURCE:
        {
            altercb->ops_amask &= (~OPS_ARESOURCE); /* turns off enumeration
    ** for single table queries so that
    ** resource control will not get accurate
    ** estimates if it is used */
            break;
        }
        case OPF_CARDCHK:
        {
            altercb->ops_nocardchk = FALSE; /* Enable cardinality checks */
            break;
        }
        case OPF_NOCARDCHK:
        {
            altercb->ops_nocardchk = TRUE; /* Ignore card checks (legacy mode) */
            break;
        }
# ifdef E_OP0089_ALTER
        default:
        {
            opx_rerror( opf_cb, E_OP0089_ALTER);
            return( E_DB_ERROR );
        }
# endif
        }
    }
    return (E_DB_OK);
}
Example #5
0
/*{
** Name: opn_timeout	- check for timeout condition
**
** Description:
**      Check the various indications that timeout has occurred. 
**
** Inputs:
**      subquery                        ptr to subquery state
**
** Outputs:
**
**	Returns:
**	    bool - TRUE is timeout condition has been detected 
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      14-may-90 (seputis)
**          - b21582, do not allow large CPU gaps before checking
**	    for a timeout condition
**	26-nov-90 (seputis)
**	    - added support for new server startup flags
**      31-jan-91 (seputis)
**          - use more time to optimize queries in DB procedures
**      20-mar-91 (seputis)
**          - b 36600 added calls to CSswitch to allow context 
**	switching if no query plan is found or notimeout is used 
**      3-dec-92 (ed)
**          OP255 was doing a notimeout on all subqueries if the second
**	    parameter was set
**	31-jan-97 (inkdo01)
**	    Simplify CSswitch interface so that all calls to timeout 
**	    result in a CSswitch call. This fixes a CPU lockout problem 
**	    in (at least) Solaris, because the switch depended largely
**	   on faulty quantum testing logic in CSstatistics.
**	15-sep-98 (sarjo01)
**	    Redo of function, adding support for ops_timeoutabort
**	14-jul-99 (inkdo01)
**	    Add code to do quick exit for where-less idiot queries.
**	13-Feb-2007 (kschendel)
**	    Replace CSswitch with better CScancelCheck.
[@history_template@]...
*/
bool
opn_timeout(
	OPS_SUBQUERY       *subquery)
{
    OPS_CB          *scb;               /* ptr to session control block for
                                        ** currently active user */
    OPS_STATE       *global;            /* ptr to global state variable */

    if (subquery->ops_mask & OPS_IDIOT_NOWHERE && subquery->ops_bestco) return(TRUE);
					    /* if idiot query (join, but no where)
					    ** and we have valid plan, quit now */

    global = subquery->ops_global;	    /* get ptr to global state variable
                                            */
    scb = global->ops_cb;		    /* get ptr to active session control
                                            ** block */
    if (scb->ops_alter.ops_timeout)	    /* TRUE if optimizer should timeout
                                            */
    {
        i4		    joinop_timeout;
        i4		    joinop_abort;
        joinop_timeout = scb->ops_alter.ops_sestime;
        joinop_abort   = scb->ops_alter.ops_timeoutabort;

        if (joinop_abort == 0)
	{
	    if (subquery->ops_bestco)
	    {
	        TIMERSTAT	    timer_block;
	        STATUS		    cs_status;
	        i4		    nowcpu;    /* cpu time used by process */
	        OPO_COST	    miladjust; /* adjustment to cost to obtain
                                               ** millisec equivalent */
	        i4		    first;     /* plan to timeout */
	        i4		    second;    /* subquery plan to timeout */
	        bool		    planid_timeout; /* check if tracing flag is
					            ** set and override timeout
					            ** check with new one */

	        planid_timeout = FALSE;
	        if ((global->ops_qheader->pst_numparm > 0)
			||
		    global->ops_procedure->pst_isdbp)
	            miladjust = scb->ops_alter.ops_tout *
                                         scb->ops_alter.ops_repeat; 
					    /* use more time to optimize
					    ** a repeat query */
	        else
		    miladjust = scb->ops_alter.ops_tout;

	        if (scb->ops_check)
	        {
		    if (opt_svtrace( scb, OPT_F125_TIMEFACTOR, &first, &second)
		        &&
		        first>0)    /* see if there is a miladjust factor
				    ** from the user */
		        miladjust = (miladjust*first)/100.0;
				    /* this will increase/decrease
				    ** the amount of time required to timeout */
		    planid_timeout = 
		        opt_svtrace( scb, OPT_F127_TIMEOUT, &first, &second);
				    /* this will time out based on subquery
				    ** plan id and number of plans being
				    ** evaluated */
	        }


		if (cs_status = CSstatistics(&timer_block, (i4)0))
		{   /* get cpu time used by session from SCF to calculate
                    ** difference from when optimization began FIXME - this
                    ** is an expensive routine to call, perhaps some other
                    ** way of timing out could be used such as number of CO
                    ** nodes processed */
		    opx_verror(E_DB_ERROR, E_OP0490_CSSTATISTICS, 
			(OPX_FACILITY)cs_status);
		}
		nowcpu = timer_block.stat_cpu -global->ops_estate.opn_startime;

	        if (
		    (((nowcpu > (miladjust * subquery->ops_cost)) ||
					    /* if the amount of time spent so 
					    ** far on optimization is roughly 
                                            ** about how much time the best 
                                            ** solution found so far
					    ** will take to execute, then stop
                                            */
		      ( (joinop_timeout > 0) && (nowcpu > joinop_timeout)))
		    && 
		    (   !planid_timeout	    /* if the plan timeout tracing is
					    ** set then this should override
					    ** the normal timeout mechanism */
			||
			(   (second != 0)
			    &&
			    (second != subquery->ops_tsubquery) /* apply timeout
					    ** to all query plans except the
					    ** one specified */
			)
		    ))
		    ||
		    ( planid_timeout
		        &&
		      (first <= subquery->ops_tcurrent)
		        &&
		      (	(second == 0)	    /* check if all plans should be
					    ** timed out */
			||
			(second == subquery->ops_tsubquery) /* check if a
					    ** particular subquery is being
					    ** search for */
		      )
		    ))
	        {
		    opx_verror(E_DB_WARN, E_OP0006_TIMEOUT, (OPX_FACILITY)0);
		    return(TRUE);
	        }
	    }
	}
	else
	{
            TIMERSTAT           timer_block;
            STATUS              cs_status;
            i4             nowcpu;    /* cpu time used by process */
            OPO_COST            miladjust; /* adjustment to cost to obtain
                                           ** millisec equivalent */
            i4             first;     /* plan to timeout */
            i4             second;    /* subquery plan to timeout */
            bool                planid_timeout; /* check if tracing flag is
                                                ** set and override timeout
                                                ** check with new one */
	    if (joinop_timeout == 0 || joinop_timeout >= joinop_abort)
		joinop_timeout = joinop_abort; 
            planid_timeout = FALSE;
            if ((global->ops_qheader->pst_numparm > 0)
                    ||
                global->ops_procedure->pst_isdbp)
                miladjust = scb->ops_alter.ops_tout *
                                     scb->ops_alter.ops_repeat;
                                        /* use more time to optimize
                                        ** a repeat query */
            else
                miladjust = scb->ops_alter.ops_tout;

            if (scb->ops_check)
            {
                if (opt_svtrace( scb, OPT_F125_TIMEFACTOR, &first, &second)
                    &&
                    first>0)    /* see if there is a miladjust factor
                                ** from the user */
                    miladjust = (miladjust*first)/100.0;
                                /* this will increase/decrease
                                ** the amount of time required to timeout */
                planid_timeout =
                    opt_svtrace( scb, OPT_F127_TIMEOUT, &first, &second);
                                /* this will time out based on subquery
                                ** plan id and number of plans being
                                ** evaluated */
            }
            if (cs_status = CSstatistics(&timer_block, (i4)0))
            {
                opx_verror(E_DB_ERROR, E_OP0490_CSSTATISTICS,
                    (OPX_FACILITY)cs_status);
            }
            nowcpu = timer_block.stat_cpu -global->ops_estate.opn_startime;

            if ( subquery->ops_bestco
		 &&
                ( (
                 ((nowcpu > (miladjust * subquery->ops_cost)) ||
                  ((joinop_timeout > 0) && (nowcpu > joinop_timeout)))
                     &&
                 ( !planid_timeout ||
                    ( (second != 0)
                        &&
                        (second != subquery->ops_tsubquery)
                    )
                  )
                 )
                ||
                ( planid_timeout
                    &&
                  (first <= subquery->ops_tcurrent)
                    &&
                  ( (second == 0)
                    ||
                    (second == subquery->ops_tsubquery)
                  ))

                ) )
            {
                opx_verror(E_DB_WARN, E_OP0006_TIMEOUT, (OPX_FACILITY)0);
                return(TRUE);
            }
	    else if (nowcpu > joinop_abort)
	    {
		if (subquery->ops_bestco)
		{
    		    opx_verror(E_DB_WARN, E_OP0006_TIMEOUT, (OPX_FACILITY)0);
		    return(TRUE);
		}
		else
		{
		    scb->ops_interrupt = TRUE;
	            opx_rerror(subquery->ops_global->ops_caller_cb,
                               E_OP0018_TIMEOUTABORT);
		}
	    }
	} /* else */
    }
    /* Check for cancels if OS-threaded, time-slice if internal threaded */
    CScancelCheck(global->ops_cb->ops_sid);
    return(FALSE);
}