Beispiel #1
0
/*{
** Name: ule_initiate	- Provide server constant info for the server header
**
** Description:
**      This routine takes in the server constant parameters SERVER NAME and
**      NODE NAME, placing them in an area which is easily found to place on 
**      all error messages.
**
** Inputs:
**      node_name                       Pointer to node name, which is
**      l_node_name                     characters long
**      server_name                     Same for server name
**      l_server_name
**
** Outputs:
**      None.
**	Returns:
**	    VOID
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      06-Aug-1987 (fred)
**          Created.
**      21-Mar-2005 (mutma03)
**          cleanup of node translation code for clusters.
**	07-jan-2008 (joea)
**	    Undo 28-jun-2001 and 21-mar-2005 cluster nickname changes.
*/
VOID
ule_initiate( char *node_name, i4  l_node_name, char *server_name,
	      i4  l_server_name )
{
    PID proc_id;
    char fmt[20];

    if (Ule_started <= 0)
    {
        PCpid(&proc_id);
	
	MEfill(sizeof(ULE_MHDR), (u_char)' ', (PTR)&Ule_mhdr);	
	MEmove( l_node_name,
		(PTR)  node_name,
		(char) ' ',
		sizeof(Ule_mhdr.ule_node),
		(PTR)  &Ule_mhdr.ule_node[0]);
	MEmove(	l_server_name,
		(PTR)  server_name,
		(char) ' ',
		sizeof(Ule_mhdr.ule_server),
		(PTR)  &Ule_mhdr.ule_server[0]);
	MEfill(	sizeof(Ule_mhdr.ule_session),
		(u_char) '*',
		(PTR)  &Ule_mhdr.ule_session[0]);
	Ule_mhdr.ule_pad1[0] = ':',
	    Ule_mhdr.ule_pad1[1] = ':',
	    Ule_mhdr.ule_pad1[2] = '['; 	
	Ule_mhdr.ule_pad2[0] = ',',
	    Ule_mhdr.ule_pad2[1] = ' '; 	
        STprintf( fmt, "%s", PIDFMT );
        STprintf(Ule_mhdr.ule_pid, fmt, proc_id);
        Ule_mhdr.ule_pad3[0] = ',',
	Ule_mhdr.ule_pad3[1] = ' ';
	Ule_mhdr.ule_pad4[0] = ',';
	Ule_mhdr.ule_pad4[1] = ' ';
	MEfill(	sizeof(Ule_mhdr.ule_source),
		(char) ' ',
		(PTR) &Ule_mhdr.ule_source[0]);
	Ule_mhdr.ule_pad5[0] = ']',
	    Ule_mhdr.ule_pad5[1] = ':',
	    Ule_mhdr.ule_pad5[2] = ' '; 	
	Ule_started = 1;
    }
}
Beispiel #2
0
VOID
qee_d1_qid(
    QEE_DSH		*v_dsh_p)
{
    QEE_DDB_CB	    *qee_p = v_dsh_p->dsh_ddb_cb;
    DB_CURSOR_ID    *csr_p;
    SYSTIME	    tm_now;
    char	    hi_ascii[QEK_015_LEN],
                lo_ascii[QEK_015_LEN],
                pid_ascii[QEK_015_LEN],
                temp[QEK_050_LEN + DB_CURSOR_MAXNAME];
    PID		    pid;		/* an i4 */


    PCpid(& pid);			/* get process (server) id */
    CVla(pid, pid_ascii);		/* convert to ascii */

    TMnow(& tm_now);

    csr_p = & qee_p->qee_d4_given_qid;
    csr_p->db_cursor_id[0] = tm_now.TM_secs;
    csr_p->db_cursor_id[1] = tm_now.TM_msecs;
    CVla(tm_now.TM_secs, hi_ascii);
    CVla(tm_now.TM_msecs, lo_ascii);
    STpolycat((i4) 4,			/* 4 constituent pieces */
              "dd", lo_ascii, hi_ascii, pid_ascii, temp);
    MEmove(STlength(temp), temp, ' ',
           DB_CURSOR_MAXNAME, csr_p->db_cur_name);

    csr_p = & qee_p->qee_d5_local_qid;
    csr_p->db_cursor_id[0] = 0;
    csr_p->db_cursor_id[1] = 0;
    MEfill(DB_CURSOR_MAXNAME, ' ', (PTR) csr_p->db_cur_name);

    return;
}
Beispiel #3
0
DB_STATUS
qee_d2_tmp(
    QEF_RCB		*qef_rcb,
    QEE_DSH		*dsh,
    ULM_RCB		*ulm)
{
    DB_STATUS	    status = E_DB_OK;
    QEF_QP_CB	    *qp_p = dsh->dsh_qp_ptr;
    QEQ_DDQ_CB	    *ddq_p = & qp_p->qp_ddq_cb;
    QEE_DDB_CB	    *qee_p = dsh->dsh_ddb_cb;
    DB_CURSOR_ID    *csr_p;


    if (ddq_p->qeq_d3_elt_cnt > 0)
    {
        SYSTIME	    tm_now,
                    tm_last;
        char	    hi_ascii[QEK_015_LEN],
                    lo_ascii[QEK_015_LEN],
                    /*
                    		    pid_ascii[QEK_015_LEN],
                    */
                    temp[QEK_050_LEN+DB_MAXNAME];/* must be > DB_MAXNAME */
        DD_TAB_NAME    *name_p;
        i4	    *long_p;
        /*
        	PID	    pid;		** an i4 **
        */
        i4	    m, n;
        char	    *p, *q;
        u_i2	    hi_len,
                    /*
                    		    lo_len,
                    */
                    tmp_len;

#define	QEE_10SQL_NAME_LEN    10


        /* allocate space for array of temporary-table names and
        ** generate their names */

        /* 1.  allocate array for DD_TAB_NAMEs */

        ulm->ulm_psize = ddq_p->qeq_d3_elt_cnt * sizeof(DD_TAB_NAME);
        if (status = qec_malloc(ulm))
        {
            qef_rcb->error.err_code = ulm->ulm_error.err_code;
            qed_u10_trap();
            return(status);
        }

        qee_p->qee_d1_tmp_p = (DD_TAB_NAME *) ulm->ulm_pptr;
        /* ptr to array of DD_TAB_NAMEs */
        /* 2.  allocate array for i4 status */

        ulm->ulm_psize = ddq_p->qeq_d3_elt_cnt * sizeof(i4);
        if (status = qec_malloc(ulm))
        {
            qef_rcb->error.err_code = ulm->ulm_error.err_code;
            qed_u10_trap();
            return(status);
        }

        qee_p->qee_d2_sts_p = (i4 *)
                              ulm->ulm_pptr; 	/* ptr to array of i4s */

        /* initialize both allocated arrays */

        name_p = qee_p->qee_d1_tmp_p;
        long_p = qee_p->qee_d2_sts_p;

        tm_last.TM_secs = 0;
        tm_last.TM_msecs = 0;
        /*
        	PCpid(& pid);		** get process (server) id **
        	CVla(pid, pid_ascii);	** convert to ascii **
        */
        for (n = 0; n < ddq_p->qeq_d3_elt_cnt; n++)
        {
            /* 3.  generate temporary table name */

            TMnow(& tm_now);

            if (tm_now.TM_secs == tm_last.TM_secs)
            {
                if (tm_now.TM_msecs <= tm_last.TM_msecs)
                    tm_now.TM_msecs = tm_last.TM_msecs + 1;
            }
            CVla(tm_now.TM_secs, hi_ascii);
            CVla(tm_now.TM_msecs, lo_ascii);

            hi_len = STlength(hi_ascii);

            /* transpose the hi_ascii string to get lower digits */

            p = hi_ascii;
            q = hi_ascii + hi_len - 1;		/* backup past EOS */
            for (m = 0; m < (i4) hi_len - 1; m++)	/* do length - 1 characters */
            {
                *p = *q;
                p++;
                q--;
            }

            STpolycat((i4) 3,	/* 3 constituent pieces */
                      "z", lo_ascii, hi_ascii, temp);

            tmp_len = STlength(temp);

            /* use at most 10 characters */

            if (tmp_len > QEE_10SQL_NAME_LEN)
                tmp_len = QEE_10SQL_NAME_LEN;

            MEmove(tmp_len, temp, ' ', sizeof(DD_TAB_NAME),
                   (char *)name_p);

            STRUCT_ASSIGN_MACRO(tm_now, tm_last);
            /* save for comparison */
            name_p++;		/* pt to next slot */

            /* 4.  initialize status word for this table */

            *long_p = QEE_00M_NIL;
            long_p++;		/* pt to next status word */
        } /* for */
    }
    else
    {
        qee_p->qee_d1_tmp_p = (DD_TAB_NAME *) NULL;
        qee_p->qee_d2_sts_p = (i4 *) NULL;
    }

    /* 5.  initialize */

    qee_p->qee_d3_status = QEE_00Q_NIL;

    if (! (qp_p->qp_status & QEQP_RPT))
    {
        /* initialize if not repeat query */

        csr_p = & qee_p->qee_d4_given_qid;
        csr_p->db_cursor_id[0] = 0;
        csr_p->db_cursor_id[1] = 0;
        MEfill(DB_CURSOR_MAXNAME, ' ', (PTR) csr_p->db_cur_name);
    }

    csr_p = & qee_p->qee_d5_local_qid;
    csr_p->db_cursor_id[0] = 0;
    csr_p->db_cursor_id[1] = 0;
    MEfill(DB_CURSOR_MAXNAME, ' ', (PTR) csr_p->db_cur_name);

    return(status);
}
Beispiel #4
0
/*{
** Name: openTempTable		- Open a temp table used for set input
**                                  procedure.
**
** Description:
**      The current execution environment is saved and an
**      environment is created in which to execute the
**      named procedure.
**
**      This procedure is only called when a nested procedure is invoked.
**      This can occur the first time through, or if the procedure is not
**      found (LOAD_QP) or the plan was deemed invalid (INVALID_QUERY) then
**      the procedure is re-entered in this routine.
**
**      If rules are turned off (QEF_T_NORULES) then this procedure returns
**      immediately.
**
** Inputs:
**      qef_rcb
**	tempTableNumber		index to dsh temptable array for temporary
**				table to be created.
**
** Outputs:
**      Returns:
**          E_DB_{OK,WARN,ERROR,FATAL} (from table creation)
**      Exceptions:
**          none
**
** Side Effects:
**          none
**
** History:
**	18-jul-96 (inkdo01)
**	    Created.
**	29-oct-1998 (somsa01)
**	    If we are opening a Global Temporary Table, turn on the
**	    DMT_SESSION_TEMP flag in dmt_flags_mask before the open.
**	    (Bug #94059)
**	12-nov-1998 (somsa01)
**	    Added another parameter, and refined the check for a Global
**	    Session Temporary Table.  (Bug #94059)
**	15-mar-04 (inkdo01)
**	    dsh_tempTables is now an array of ptrs.
**	13-Jul-2004 (schka24)
**	    Pass in dsh so we get the right one for sure.
**	30-Jul-2004 (jenjo02)
**	    Use dsh_dmt_id rather than qef_dmt_id transaction context.
**	4-Jun-2009 (kschendel) b122118
**	    Use open-and-link utility.
*/
static DB_STATUS openTempTable(
	QEF_RCB 	*rcb,
	QEE_DSH		*dsh,
	i4		tempTableNumber,
	bool		gttparm
)
{
    QEE_TEMP_TABLE  *tempTable = dsh->dsh_tempTables[ tempTableNumber ];
    DMT_CB	    *dmt = tempTable->tt_dmtcb;
    DMR_CB	    *dmr = tempTable->tt_dmrcb;
    DM_MDATA	    dm_mdata;
    DB_STATUS status = E_DB_OK;

    for (;;)	/* something to break out of */
    {
	/* create the table if it doesn't already exist */

	if ( !( tempTable->tt_statusFlags & TT_CREATED ) )
	{
	    dmt->dmt_db_id = rcb->qef_db_id;
	    dmt->dmt_tran_id = dsh->dsh_dmt_id;
	    MEmove(8, (PTR) "$default", (char) ' ', 
	            sizeof(DB_LOC_NAME),
	            (PTR) dmt->dmt_location.data_address);
	    dmt->dmt_location.data_in_size = sizeof(DB_LOC_NAME);

	    dmt->dmt_flags_mask = DMT_DBMS_REQUEST;
	    if (gttparm)
		dmt->dmt_flags_mask |= DMT_SESSION_TEMP;
	    dmr->dmr_flags_mask = 0;
	    /*
	    ** We assume that the sort key descriptor was set up
	    ** earlier, probably at QEE time.
	    */

	    if ( tempTable->tt_statusFlags & TT_PLEASE_SORT )
		dmt->dmt_flags_mask |= DMT_LOAD;

	    if ( tempTable->tt_statusFlags & TT_NO_DUPLICATES )
		dmr->dmr_flags_mask |= DMR_NODUPLICATES;

	    dmr->dmr_count = 1;
	    dmr->dmr_s_estimated_records = TT_TUPLE_COUNT_GUESS;
	    dmr->dmr_tid = 0;
	    dm_mdata.data_address = dsh->dsh_row[ tempTable->tt_tuple ];
	    dm_mdata.data_size =
		dsh->dsh_qp_ptr->qp_row_len[ tempTable->tt_tuple ];
	    dmr->dmr_mdata = &dm_mdata;

	    status = dmf_call(DMT_CREATE_TEMP, dmt);
	    if (status != E_DB_OK)
	    {
	        if (dmt->error.err_code == E_DM0078_TABLE_EXISTS)
	        {
		    dsh->dsh_error.err_code = E_QE0050_TEMP_TABLE_EXISTS;
		    status = E_DB_ERROR;
	        }
	        else
	        {
		    dsh->dsh_error.err_code = dmt->error.err_code;
	        }
	        break;
	    }

	    /* Open the temp table */
	    dmt->dmt_flags_mask = 0;
	    if (gttparm)
		dmt->dmt_flags_mask |= DMT_SESSION_TEMP;
	    dmt->dmt_sequence = dsh->dsh_stmt_no;
	    dmt->dmt_access_mode = DMT_A_WRITE;
	    dmt->dmt_lock_mode = DMT_X;
	    dmt->dmt_update_mode = DMT_U_DIRECT;
	
	    status = qen_openAndLink(dmt, dsh);
	    if (status != E_DB_OK)
	    {
	        break;
	    }

            tempTable->tt_statusFlags |= TT_CREATED;
	    dmr->dmr_access_id = dmt->dmt_record_access_id;
	}	/* end of table creation */

	break;
    }	/* end of code block */

    return( status );
}
Beispiel #5
0
/*{
** Name: psy_dbpriv - GRANT/REVOKE database privileges
**
**  INTERNAL PSF call format: status = psy_dbpriv(&psy_cb, sess_cb);
**  EXTERNAL     call format: status = psy_call (PSY_DBPRIV,&psy_cb, sess_cb);
**
** Description:
**	This procedure is sued to grant and revoke database privileges.
**	A template iidbpriv tuple is built and shipped to RDF.
**	Eventually, the tuple is added/merged into iidbpriv.
**	This procedure is called for SQL language only.
**
** Inputs:
**      psy_cb
**	    .psy_usrq			list of grantees
**	    .psy_tblq			list of objects
**	    .psy_gtype			grantee type
**	    .psy_grant			statement type (GRANT or REVOKE)
**	    .psy_fl_dbpriv		control flags
**	    .psy_qdio_limit		query I/O  limit
**	    .psy_qrow_limit		query row  limit
**	    .psy_qcpu_limit		query CPU  limit
**	    .psy_qpage_limit		query page limit
**	    .psy_qcost_limit		query cost limit
**	    .psy_idle_limit		idle time  limit
**	    .psy_connect_limit		connect time  limit
**	    .psy_priority_limit		priority   limit
**	sess_cb				Pointer to session control block
**					(Can be NULL)
**
** Outputs:
**      psy_cb
**	    .psy_error			Filled in if error happens
**	Returns:
**	    E_DB_OK			Function completed normally.
**	    E_DB_WARN			Function completed with warning(s);
**	    E_DB_ERROR			Function failed; non-catastrophic error
**	    E_DB_SEVERE			Function failed; catastrophic error
**	Exceptions:
**	    none
**
** Side Effects:
**	    None.
**
** History:
**	10-apr-89 (ralph)
**          written
**	06-jun-89 (ralph)
**	    corrected unix portability problems
**	24-jun-89 (ralph)
**	    corrected internal error message
**	06-sep-89 (ralph)
**	    added support for GRANT/REVOKE ON ALL DATABASES
**	    removed DBGR_DEFAULT
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	19-jul-92 (andre)
**	    changes were made to enable a user to specify privileges to PUBLIC
**	    along with one or more user authorization identifiers
**	10-aug-93 (andre)
**	    fixed cause of a compiler warning
*/
DB_STATUS
psy_dbpriv(
	PSY_CB             *psy_cb,
	PSS_SESBLK	   *sess_cb)
{
    DB_STATUS		status = E_DB_OK;
    DB_STATUS		stat;
    i4		err_code;
    RDF_CB		rdf_cb;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_PRIVILEGES	dbprtuple;
    register DB_PRIVILEGES *dbprtup = &dbprtuple;
    PSY_USR		*psy_usr;
    PSY_TBL		*psy_tbl;
    bool		grant_to_public;
    bool		leave_loop = TRUE;
    
    /* This code is called for SQL only */

    do
    {
	/* Fill in the RDF request block */

	pst_rdfcb_init(&rdf_cb, sess_cb);
	if (psy_cb->psy_grant == PSY_DGRANT)
	    rdf_rb->rdr_update_op   = RDR_APPEND;
	else if (psy_cb->psy_grant == PSY_DREVOKE)
	    rdf_rb->rdr_update_op   = RDR_DELETE;
	else
	{
	    /* Invalid operation specified in psy_grant */
	    err_code = E_PS0D45_INVALID_GRANT_OP;
	    (VOID) psf_error(E_PS0D45_INVALID_GRANT_OP, 0L,
			     PSF_INTERR, &err_code, &psy_cb->psy_error, 0);
	    status   = E_DB_ERROR;
	    break;
	}
	rdf_rb->rdr_status	    = DB_SQL;
	rdf_rb->rdr_types_mask  = RDR_DBPRIV;
	rdf_rb->rdr_qrytuple    = (PTR) dbprtup;
	rdf_rb->rdr_qtuple_count = 1;

	/* Initialize the template iidbpriv tuple */

	dbprtup->dbpr_gtype	  = psy_cb->psy_gtype;
	dbprtup->dbpr_control	  = psy_cb->psy_ctl_dbpriv;
	dbprtup->dbpr_dbflags	  = 0;
	dbprtup->dbpr_flags	  = psy_cb->psy_fl_dbpriv;
	dbprtup->dbpr_qrow_limit  = psy_cb->psy_qrow_limit;
	dbprtup->dbpr_qdio_limit  = psy_cb->psy_qdio_limit;
	dbprtup->dbpr_qcpu_limit  = psy_cb->psy_qcpu_limit;
	dbprtup->dbpr_qpage_limit = psy_cb->psy_qpage_limit;
	dbprtup->dbpr_qcost_limit = psy_cb->psy_qcost_limit;
	dbprtup->dbpr_connect_time_limit = psy_cb->psy_connect_limit;
	dbprtup->dbpr_idle_time_limit    = psy_cb->psy_idle_limit;
	dbprtup->dbpr_priority_limit     = psy_cb->psy_priority_limit;

	MEfill(sizeof(dbprtup->dbpr_database), (u_char) ' ',
	    (PTR) &dbprtup->dbpr_database);

	MEfill(sizeof(dbprtup->dbpr_reserve), (u_char) ' ',
	    (PTR) dbprtup->dbpr_reserve);

	/* Point to first database object, if any */

	psy_tbl = (PSY_TBL *)psy_cb->psy_tblq.q_next;

	/* No database objects means GRANT/REVOKE ON ALL DATABASES */

	if (psy_tbl == (PSY_TBL *) &psy_cb->psy_tblq)
	    dbprtup->dbpr_dbflags |= DBPR_ALLDBS;

	/*
	** Pass the template tuples to RDF for each database/grantee.
	** RDF/QEF will return E_DB_INFO if a database/grantee is rejected,
	** or E_DB_WARN is a database is rejected.  Anything worse than
	** E_DB_WARN is a fatal error.
	*/

	/* Process each database/grantee */
	for (;;)
	{
	    /*
	    ** Copy in database name if one was provided.
	    ** None will be provided if ON ALL DATABASES was specified.
	    */
	    if (psy_tbl != (PSY_TBL *) &psy_cb->psy_tblq)
		MEcopy((PTR)&psy_tbl->psy_tabnm,
		       sizeof(dbprtup->dbpr_database),
		       (PTR)&dbprtup->dbpr_database);

	    grant_to_public = (psy_cb->psy_flags & PSY_PUBLIC) != 0;
	    psy_usr = (PSY_USR *)  psy_cb->psy_usrq.q_next;

	    do
	    {
		if (grant_to_public)
		{
		    /*
		    ** user specified TO/FROM PUBLIC, possibly along with other
		    ** user auth ids; we will process TO/FROM PUBLIC first
		    */
		    dbprtup->dbpr_gtype = DBGR_PUBLIC;
		    
		    MEmove(sizeof("public") - 1, (PTR) "public", ' ',
			sizeof(dbprtup->dbpr_gname),
			(PTR) &dbprtup->dbpr_gname);
		}
		else
		{
		    STRUCT_ASSIGN_MACRO(psy_usr->psy_usrnm,
			dbprtup->dbpr_gname);
		}
		
		stat = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);
		status = (stat > status) ? stat : status;
		if (stat > E_DB_INFO)
		    break;

		if (grant_to_public)
		{
		    dbprtup->dbpr_gtype = psy_cb->psy_gtype;

		    /*
		    ** remember that we have processed GRANT TO PUBLIC on this
		    ** database or on the installation
		    */
		    grant_to_public = FALSE;
		}
		else
		{
		    psy_usr = (PSY_USR *) psy_usr->queue.q_next;
		}

	    } while (psy_usr != (PSY_USR *) &psy_cb->psy_usrq);

	    /* Break out if failure */
	    if (DB_FAILURE_MACRO(status))
		break;

	    /* Point to next database object */
	    psy_tbl = (PSY_TBL *)  psy_tbl->queue.q_next;

	    /* Break out if no more objects */
	    if (psy_tbl == (PSY_TBL *) &psy_cb->psy_tblq)
		break;
	}

	/* We are done */

	/* leave_loop has already been set to TRUE */
    } while (!leave_loop);

    if (DB_FAILURE_MACRO(status))
	(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, 
			     &psy_cb->psy_error);

    return    (status);
}
Beispiel #6
0
static	DB_STATUS
qen_ts_dump(
QEN_SHD		   *shd,
QEE_DSH		   *dsh,
QEN_NODE           *node,
i4		   rowno,
bool		   heap_sort,
bool		   no_qef )
{
    PTR		*cbs = dsh->dsh_cbs;
    DMT_CB	*dmt = (DMT_CB *)cbs[node->node_qen.qen_tsort.tsort_create];
    DMR_CB	*dmr_load = (DMR_CB*)cbs[node->node_qen.qen_tsort.tsort_load];
    DMR_CB	*dmr_get = (DMR_CB*) cbs[node->node_qen.qen_tsort.tsort_get];
    DMT_CHAR_ENTRY	char_array[2];
    DB_STATUS	status;


    for (;;)	    /* to break off in case of error */
    {
	/* Initialize the DMT_CB for the sorter table */
	dmt->dmt_flags_mask = DMT_LOAD | DMT_DBMS_REQUEST;
	dmt->dmt_db_id = dsh->dsh_qefcb->qef_rcb->qef_db_id;
	dmt->dmt_tran_id = dsh->dsh_dmt_id;
	MEmove(8, (PTR) "$default", (char) ' ', 
	    sizeof(DB_LOC_NAME),
	    (PTR) dmt->dmt_location.data_address);
	dmt->dmt_location.data_in_size = sizeof(DB_LOC_NAME);


	/* Initialize table attribute descriptors */
	dmt->dmt_attr_array.ptr_address = 
		    (PTR) node->node_qen.qen_tsort.tsort_atts;
	dmt->dmt_attr_array.ptr_in_count = 
		    node->node_qen.qen_tsort.tsort_acount;
	dmt->dmt_attr_array.ptr_size = sizeof (DMF_ATTR_ENTRY);

	/* Initialize the the sort key descriptors */
	dmt->dmt_key_array.ptr_address = 
		(PTR) node->node_qen.qen_tsort.tsort_satts;
	dmt->dmt_key_array.ptr_in_count = 
		node->node_qen.qen_tsort.tsort_scount;
	dmt->dmt_key_array.ptr_size = sizeof (DMT_KEY_ENTRY);

	/*  Pass the page size */
	char_array[0].char_id = DMT_C_PAGE_SIZE;
	char_array[0].char_value = node->node_qen.qen_tsort.tsort_pagesize;
	char_array[1].char_id = DMT_C_DUPLICATES;
	char_array[1].char_value = DMT_C_ON; /* duplicate rows allowed */
	dmt->dmt_char_array.data_address = (PTR) &char_array;
	dmt->dmt_char_array.data_in_size = 2 * sizeof(DMT_CHAR_ENTRY);

	/* Create the sorter table */
	status = dmf_call(DMT_CREATE_TEMP, dmt);
	if (status != E_DB_OK)
	{
	    if (dmt->error.err_code == E_DM0078_TABLE_EXISTS)
	    {
		dsh->dsh_error.err_code = E_QE0050_TEMP_TABLE_EXISTS;
		status = E_DB_ERROR;
	    }
	    else
	    {
		dsh->dsh_error.err_code = dmt->error.err_code;
	    }
	    break;
	}

	/* Open the sorter table */
	dmt->dmt_flags_mask = 0;
	dmt->dmt_sequence = dsh->dsh_stmt_no;
	dmt->dmt_access_mode = DMT_A_WRITE;
	dmt->dmt_lock_mode = DMT_X;
	dmt->dmt_update_mode = DMT_U_DIRECT;
	dmt->dmt_char_array.data_address = 0;
	dmt->dmt_char_array.data_in_size = 0;
	
	status = qen_openAndLink(dmt, dsh);
	if (status != E_DB_OK)
	{
	    break;
	}

	/* Initialize the DMR_CB for loading the sorter */
	dmr_load->dmr_access_id = dmt->dmt_record_access_id;
	dmr_load->dmr_count = 1;
	dmr_load->dmr_flags_mask = (node->node_qen.qen_tsort.tsort_dups |
					DMR_SORT_NOCOPY);
	dmr_load->dmr_s_estimated_records = node->qen_est_tuples;
	dmr_load->dmr_tid = 0;

	/* Initialize the DMR_CB for reading the sorter */
	dmr_get->dmr_access_id = dmt->dmt_record_access_id;
	dmr_get->dmr_data.data_address = dsh->dsh_row[rowno];
	dmr_get->dmr_data.data_in_size =  dsh->dsh_qp_ptr->qp_row_len[rowno];
	dmr_get->dmr_tid = 0;

	if (no_qef)
	    break;				/* leave, if nothing there */

	/* If we have tuples in the in-memory sort buffer, load them into
	** DMF sorter table now and write current tuple. */
        if (heap_sort) status = qes_dump(dsh, shd, dmr_load);
	 else status = qes_dumploop(dsh, shd, dmr_load);
	break;
    }	/* end of error-break loop */
    return (status);
}
Beispiel #7
0
DB_STATUS
dmc_add_db(
DMC_CB    *dmc_cb)
{
    DMC_CB		*dmc = dmc_cb;
    DM_SVCB		*svcb = dmf_svcb;
    DMC_LOC_ENTRY	*location;
    i4		loc_count;
    i4		flags;
    i4		mode;
    i4		dm2mode;
    i4		error,local_error;
    DMM_LOC_LIST	*loc_ptr[4];
    DB_STATUS		status;
    DMP_DCB		*dcb;

    CLRDBERR(&dmc->error);

    for (status = E_DB_ERROR;;)
    {
	/*	Verify control block parameters. */

	if (dmc->dmc_op_type != DMC_DATABASE_OP)
	{
	    SETDBERR(&dmc->error, 0, E_DM000C_BAD_CB_TYPE);
	    break;
	}

	if (dmc->dmc_id != svcb->svcb_id)
	{
	    SETDBERR(&dmc->error, 0, E_DM002D_BAD_SERVER_ID);
	    break;
	}

	flags = 0;
	if (dmc->dmc_flags_mask &
	    ~(DMC_NOJOURNAL | DMC_JOURNAL | DMC_FSTCOMMIT | DMC_SOLECACHE |
              DMC_CNF_LOCKED | DMC_CVCFG | DMC_ADMIN_DB | DMC_DMCM))
	{
	    SETDBERR(&dmc->error, 0, E_DM001A_BAD_FLAG);
	    break;
	}
	if (dmc->dmc_flags_mask & DMC_NOJOURNAL)
	    flags |= DM2D_NOJOURNAL;
	if (dmc->dmc_flags_mask & DMC_JOURNAL)
	    flags |= DM2D_JOURNAL;
	if (dmc->dmc_flags_mask & DMC_FSTCOMMIT)
	    flags |= DM2D_FASTCOMMIT;
	if (dmc->dmc_flags_mask & DMC_SOLECACHE)
	    flags |= DM2D_BMSINGLE;
	if (dmc->dmc_flags_mask & DMC_CVCFG)
	    flags |= DM2D_CVCFG;
        
        /* b97083 - Is the CNF file already locked by caller? */
        if (dmc->dmc_flags_mask & DMC_CNF_LOCKED)
            flags |= DM2D_CNF_LOCKED;

	if (dmc->dmc_s_type & DMC_S_SINGLE)
	    flags |= DM2D_SINGLE;
	if (dmc->dmc_s_type & DMC_S_MULTIPLE)
	    flags |= DM2D_MULTIPLE;

        /*
        ** (ICL phil.p)
        */
        if (dmc->dmc_flags_mask & DMC_DMCM)
            flags |= DM2D_DMCM;

        if (dmc->dmc_flags_mask2 & DMC2_READONLYDB)
            flags |= DM2D_READONLYDB;

	/* No MO objects if so requested */
	if ( dmc->dmc_flags_mask2 & DMC2_NODBMO ||
	     mode == DMC_A_CREATE || mode == DMC_A_DESTROY )
	{
	    flags |= DM2D_NODBMO;
	}

	/*
	** It is an error to specify Fast Commit without specifying to
	** use a single buffer manager.
        ** (ICL phil.p) UNLESS running DMCM, which effectively means
        ** running FastCommit in a Multi-Cache environment.
	*/

        if (!(flags & DM2D_DMCM))
        {
            if ((flags & (DM2D_FASTCOMMIT | DM2D_BMSINGLE)) == DM2D_FASTCOMMIT)
	    {
		SETDBERR(&dmc->error, 0, E_DM0115_FCMULTIPLE);
                break;
	    }
        }

	mode = dmc->dmc_db_access_mode;
	if (mode != DMC_A_READ &&
	    mode != DMC_A_WRITE &&
	    mode != DMC_A_CREATE &&
	    mode != DMC_A_DESTROY)
	{
	    SETDBERR(&dmc->error, 0, E_DM000F_BAD_DB_ACCESS_MODE);
	    break;
	}
	dm2mode = (mode == DMC_A_READ) ? DM2D_A_READ : DM2D_A_WRITE;

	/*  Check that at least one location was passed in. */

	location = (DMC_LOC_ENTRY *)dmc->dmc_db_location.data_address;
	loc_count = dmc->dmc_db_location.data_in_size / sizeof(DMC_LOC_ENTRY);
	if (loc_count == 0)
	{
	    SETDBERR(&dmc->error, 0, E_DM002A_BAD_PARAMETER);
	    break;
	}
	    
	/*  Check if database should be created. */

	if (mode == DMC_A_CREATE)
	{
	    SCF_CB              scf_cb;
	    SCF_SCI             sci_list[2]; 
	    DB_NAME		collation;
	    DB_NAME		ucollation;
	    char		*p;
	    char		ucolname[] = "udefault";
	    i4		dbservice;

	    scf_cb.scf_length = sizeof(SCF_CB);
	    scf_cb.scf_type = SCF_CB_TYPE;
	    scf_cb.scf_facility = DB_DMF_ID;
	    scf_cb.scf_session = (SCF_SESSION)dmc->dmc_session_id;
	    scf_cb.scf_ptr_union.scf_sci = (SCI_LIST *)sci_list;
	    sci_list[0].sci_length = sizeof(dbservice);
	    sci_list[0].sci_code = SCI_DBSERVICE;
	    sci_list[0].sci_aresult = (char *)&dbservice;
	    sci_list[0].sci_rlength = 0;
	    scf_cb.scf_len_union.scf_ilength = 1;

	    status = scf_call(SCU_INFORMATION, &scf_cb);
	    if (status != E_DB_OK)
	    {
		uleFormat(&scf_cb.scf_error, 0, (CL_ERR_DESC *)NULL, 
		    ULE_LOG, NULL, (char *)0, (i4)0, (i4 *)0, 
		    &error, 0);
		SETDBERR(&dmc->error, 0, E_DM002F_BAD_SESSION_ID);
		break;
	    }

	    /*	Collation for iidbdb can only be the default. */

	    MEfill(sizeof(collation.db_name), ' ', collation.db_name);
	    NMgtAt("II_COLLATION", &p);
	    if (p && *p)
		MEmove(STlength(p), p, ' ', sizeof(collation.db_name), 
				collation.db_name);
	    MEmove(STlength(ucolname), ucolname, ' ', 
		   sizeof(ucollation.db_name), ucollation.db_name);

	    loc_ptr[0] = (DMM_LOC_LIST *) &loc_list[0];
	    loc_ptr[1] = (DMM_LOC_LIST *) &loc_list[1];
	    loc_ptr[2] = (DMM_LOC_LIST *) &loc_list[2];
	    loc_ptr[3] = (DMM_LOC_LIST *) &loc_list[3];

	    /* Even though the iidbdb is not "operative" at this stage, we
	    ** will mark it as operative in the config file now (it will not
	    ** be marked operative in the iidatabase catalog until after it
	    ** is fully created).  Although we would like to mark the iidbdb
	    ** "inoperative" in the config file now and update it to operative
	    ** status when creation is successfully completed (as is done for
	    ** all other DBs) the internal procedure "iiqef_alter_db" which
	    ** updates this bit will not work on the iidbdb; see comments in
	    ** createdb regarding this problem.
	    */ 
	    status = dmm_add_create(0, &dmc->dmc_db_name, &dmc->dmc_db_owner,
		 1, dbservice, DU_OPERATIVE, 
		(DB_LOC_NAME *) &dbdb_location, 11, "II_DATABASE", 4, 
		loc_ptr, collation.db_name, ucollation.db_name, &dmc->error);

	    if (status != E_DB_OK)
	    {
		if (dmc->error.err_code > E_DM_INTERNAL)
		{
		    uleFormat( &dmc->error, 0, NULL, ULE_LOG , NULL,
			    (char * )0, 0L, (i4 *)0, &local_error, 0);
		    SETDBERR(&dmc->error, 0, E_DM0084_ERROR_ADDING_DB);
		}
		break;
	    }
	}
	else if (mode == DMC_A_DESTROY)
	{
	    return (E_DB_OK);
	}

	/*  Call the physical layer to construct a DCB for this database. */

	status = dm2d_add_db(flags, &dm2mode, &dmc->dmc_db_name, 
		&dmc->dmc_db_owner, loc_count, (DM2D_LOC_ENTRY *)location, &dcb, 
		(i4 *)dmc->dmc_lock_list, &dmc->error);
	if (status != E_DB_OK)
	{
	    if (dmc->error.err_code > E_DM_INTERNAL)
	    {
		uleFormat( &dmc->error, 0, NULL, ULE_LOG , NULL,
		    (char * )0, 0L, (i4 *)0, &local_error, 0);
		SETDBERR(&dmc->error, 0, E_DM0084_ERROR_ADDING_DB);
	    }
	    break;
	}

	/*  Use the access mode passed back */
	dmc->dmc_db_access_mode = 
		(dm2mode == DM2D_A_READ) ? DMC_A_READ : DMC_A_WRITE;
	dmc->dmc_db_id = (char *)dcb;
	dmc->dmc_dbservice = dcb->dcb_dbservice;
	dmc->dmc_dbcmptlvl = dcb->dcb_dbcmptlvl;
	dmc->dmc_1dbcmptminor = dcb->dcb_1dbcmptminor;
	return (E_DB_OK);
    }

    return (status);
}
Beispiel #8
0
/*{
** Name: psy_gproc - Get a database procedure definition from
**		     the system catalogs.
**
** Description:
**
** Inputs:
**	    psq_cb	    
**		psq_cursid
**		    db_cur_name	    dbproc name
**	    sess_cb
**		pss_user	    current user name
**		pss_dba		    dba name
**	    qsf_rb	    
**	    rdf_cb
**	    dbp_owner		    name of the owner whose dbproc will be
**				    looked up iff gproc_mask & PSS_DBP_BY_OWNER.
**	    gproc_mask		    mask used to specify the possible owners of
**				    the dbproc to look for
**		PSS_USRDBP	    look for dbproc owned by the current user
**		PSS_DBADBP	    look for dbproc owned by the DBA
**		PSS_INGDBP	    look for dbproc owned by $INGRES
**		PSS_DBP_BY_OWNER    look for dbproc owned by the specific user
**
**				    NOTE: if PSS_DBP_BY_OWNER is set,
**				          PSS_USRDBP, PSS_DBADBP, and PSS_INGDBP
**					  will be disregarded
**					  otherwise, we expect that PSS_USRDBP
**					  will be always set, while PSS_DBADBP
**					  and PSS_INGDBP may or may not be set
**
** Outputs:
**	    alt_user		    set to point the name of dbproc owner if
**				    different from cb->pss_user
**	    psq_cb
**		psq_error	    filled in if an error occurred
**
**	    ret_flags		    bits may be set to pass info to the caller
**		PSS_MISSING_DBPROC  dbproc not found
**
** Exceptions:
**	    none
**
** Returns
**	E_DB_OK, E_DB_ERROR
**
** Side Effects:
**	    Allocates memory.
**
** History:
**      27-apr-88 (stec)
**	    Created.
**	04-aug-88 (stec)
**	    Improve recovery of resources.
**	17-aug-88 (stec)
**	    Change bad STRUCT_ASSIGN statements.
**	28-sep-88 (stec)
**	    Do not lock object on cleanup.
**	28-sep-88 (stec)
**	    Must not unfix RDF entry.
**	16-mar-89 (andre)
**	    Added a new parameter - alt_user.
**	    psy_gproc will no longer reset pss_user or set pss_ruset.  Instead
**	    it may set the ptr passed to it to the name of the dbproc owner.
**	16-mar-89 (neil)
**	    Modified psy_gproc to access the procedure through the specified
**	    owner (psq_als_owner) if psq_alias_set is on.
**	27-apr-89 (andre)
**	    Further modify to search for dbprocs owned by $ingres if the search
**	    by user and DBA failed.  The search part of the function has been,
**	    essentially, rewritten.
**	12-mar-90 (andre)
**	    set rdr_2types_mask to 0.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	01-jun-90 (andre)
**	    Changed interface to allow caller to explicitly specify the possible
**	    owners of the dbproc to look for.
**	01-oct-91 (andre)
**	    Added ret_flags to the interface - this field will be used to pass
**	    additional info to the caller.  in particular, it will allow us to
**	    signal certain classes of errors (e.g. dbproc not found) without
**	    setting return status to E_DB_ERROR, thus enabling the caller to
**	    distinguish such errors from unexpected errors
**	15-oct-1993 (rog)
**	    We need to use ulm_copy() instead of MEcopy() when copying query
**	    text that might be more than 64k.
**	12-jan-94 (andre)
**	    As a part of fix for bug 58048, we must remove the assumption that 
**	    either PSS_USRDBP or PSS_DBP_BY_OWNER bit will always be set in 
**	    gproc_mask.  Now we will be prepared to handle PSS_DBP_BY_OWNER or
**	    one or more of PSS_USRDBP, PSS_DBADBP, and PSS_INGDBP.
**	13-jan-94 (andre)
**	    if we fail to find a dbproc, we will set PSS_MISSING_DBPROC in 
**	    *ret_flags, but leave it up to the caller to issue an error 
**	    message - this way the caller can decide whether this warrants an 
**	    error message and if so can choose his favourite error message
*/
DB_STATUS
psy_gproc(
	PSQ_CB		*psq_cb,
	PSS_SESBLK	*sess_cb,
	QSF_RCB		*qsf_rb,
	RDF_CB		*rdf_cb,
	DB_OWN_NAME	**alt_user,
	DB_OWN_NAME	*dbp_owner,
	i4		gproc_mask,
	i4		*ret_flags)
{
    DB_STATUS		status, stat;
    i4		err_code;
    RDD_QRYMOD		*pinfo;
    PSQ_QDESC		*qdesc;
    bool		leave_loop = TRUE;
    DB_PROCEDURE *dbp;
    SXF_ACCESS  access;
    i4	msgid;
    i4	local_status;

    *ret_flags = 0;

    /* First call RDF to retrieve the definition
    ** of the procedure.
    */

    /* Initialize the RDF control block */
    pst_rdfcb_init(rdf_cb, sess_cb);

    (VOID) MEcopy((PTR) psq_cb->psq_cursid.db_cur_name,
	sizeof (DB_DBP_NAME),
	(PTR) &rdf_cb->rdf_rb.rdr_name.rdr_prcname);
    rdf_cb->rdf_rb.rdr_types_mask = RDR_PROCEDURE | RDR_BY_NAME;

    /* assume that the dbproc is owned by the current user */
    *alt_user = (DB_OWN_NAME *) NULL;
    
    do
    {
	if (gproc_mask & (PSS_USRDBP | PSS_DBP_BY_OWNER))
	{
	    if (gproc_mask & PSS_USRDBP)
	    {
		STRUCT_ASSIGN_MACRO(sess_cb->pss_user, 
		    rdf_cb->rdf_rb.rdr_owner);
	    }
	    else
	    {
		STRUCT_ASSIGN_MACRO((*dbp_owner), rdf_cb->rdf_rb.rdr_owner);
		if (MEcmp((PTR)&sess_cb->pss_user, (PTR) dbp_owner,
			  sizeof(DB_OWN_NAME)))
		{
		    *alt_user = dbp_owner;		/* Try someone else */
		}
	    }

	    /* Get the text */
	    status = rdf_call(RDF_GETINFO, (PTR) rdf_cb);

	    /*
	    ** We do not want to continue search if:
	    ** 1) dbproc was found					    OR
	    ** 2) we got an error other that PROC_NOT_FOUND		    OR
	    ** 3) caller requested a dbproc owned by a specific user
	    **    (gproc_mask & PSS_DBP_BY_OWNER)			    OR
	    */
	    if (   DB_SUCCESS_MACRO(status)				    
		|| rdf_cb->rdf_error.err_code != E_RD0201_PROC_NOT_FOUND   
		|| gproc_mask & PSS_DBP_BY_OWNER)
	    {
	        break;
	    }
	}

	/* 
	** if we were told to check whether a dbproc is owned by the DBA, do so
	** unless the DBA is the current user and we have already established 
	** that the current user does not own a dbproc with this name
	*/
	if (   gproc_mask & PSS_DBADBP 
	    && (   ~gproc_mask & PSS_USRDBP
		|| MEcmp((PTR) &sess_cb->pss_user, 
		       (PTR) &sess_cb->pss_dba.db_tab_own, sizeof(DB_OWN_NAME))
	       )
	   )
	{
	    STRUCT_ASSIGN_MACRO(sess_cb->pss_dba.db_tab_own,
				rdf_cb->rdf_rb.rdr_owner);

	    /*
	    ** If we succeed and the DBA is different from the current user, 
	    ** the procedure text will have to be parsed in the context of 
	    ** dbproc's owner, i.e. DBA.  Note that if we were also asked to 
	    ** check whether the dbproc is owned by the current user and still 
	    ** found ourselves here, DBA must be different from the current user
	    */
	    if (   gproc_mask & PSS_USRDBP
		|| MEcmp((PTR) &sess_cb->pss_user,
		       (PTR) &sess_cb->pss_dba.db_tab_own, sizeof(DB_OWN_NAME)))
	    {
	        *alt_user = &sess_cb->pss_dba.db_tab_own;
	    }

	    /* Get the text */
	    status = rdf_call(RDF_GETINFO, (PTR) rdf_cb);

	    /*
	    ** We do not want to continue search if:
	    ** 1) dbproc was found				OR
	    ** 2) we got an error other that PROC_NOT_FOUND
	    */
	    if (DB_SUCCESS_MACRO(status) ||
	        rdf_cb->rdf_error.err_code != E_RD0201_PROC_NOT_FOUND)
	    {
		break;
	    }
	}

	if (gproc_mask & PSS_INGDBP)
	{
	    MEmove(sizeof(*sess_cb->pss_cat_owner), (PTR)sess_cb->pss_cat_owner,
		   ' ', DB_OWN_MAXNAME, (PTR) &rdf_cb->rdf_rb.rdr_owner); 
	}
	else
	{
	    /*
	    ** if user has not requested that a dbproc owned by $INGRES be
	    ** looked up, might as well get out of the loop
	    */
	    break;
	}
	
	/* 
	** if we were told to check whether a dbproc is owned by $ingres, do so
	** unless the $ingres is the current user and we have already 
	** established that the current user does not own a dbproc with this 
	** name or $ingres is the DBA and we have already established that the
	** DBA does not own a dbproc with this name
	*/
	if (   (   ~gproc_mask & PSS_USRDBP
	        || MEcmp((PTR)&sess_cb->pss_user, 
		       (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME))
	       )
	    && (   ~gproc_mask & PSS_DBADBP
		|| MEcmp((PTR) &sess_cb->pss_dba.db_tab_own,
	               (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME))
	       )
	   )
	{
	    /*
	    ** If we succeed, the procedure text will have to be parsed in
	    ** the context of the original owner, i.e. $ingres.
	    */
	    *alt_user = &rdf_cb->rdf_rb.rdr_owner;
	    /*
	    ** If we succeed and $ingres is not the current user, the procedure
	    ** text will have to be parsed in the context of dbproc's owner, 
	    ** i.e. $ingres.  Note that if we were also asked to check whether 
	    ** the dbproc is owned by the current user and still found ourselves
	    ** here, the current user must NOT be $ingres
	    */
	    if (   gproc_mask & PSS_USRDBP
		|| MEcmp((PTR) &sess_cb->pss_user,
		       (PTR) &rdf_cb->rdf_rb.rdr_owner, sizeof(DB_OWN_NAME)))
	    {
	        *alt_user = &sess_cb->pss_dba.db_tab_own;
	    }


	    /* Get the text */
	    status = rdf_call(RDF_GETINFO, (PTR) rdf_cb);
	}
	
	/* leave_loop has already been set to TRUE */
    } while (!leave_loop);

    if (DB_FAILURE_MACRO(status))
    {
	if (rdf_cb->rdf_error.err_code == E_RD0201_PROC_NOT_FOUND)
	{
	    /*
	    ** dbproc was not found - set a bit in ret_flags and reset status to
	    ** E_DB_OK to enable callers to distinguish between this and other
	    ** errors
	    */
	    status = E_DB_OK;
	    *ret_flags |= PSS_MISSING_DBPROC;
	}
	else
	{
	    (VOID) psf_rdf_error(RDF_GETINFO, &rdf_cb->rdf_error,
				 &psq_cb->psq_error);
	}
	return(status);
    }

    /* we get here only if the dbproc was found */
    
    /*
    ** If the procedure has a security label, validate it
    */
    dbp=rdf_cb->rdf_info_blk->rdr_dbp;

    /* Initialize the QSF control block */
    qsf_rb->qsf_type = QSFRB_CB;
    qsf_rb->qsf_ascii_id = QSFRB_ASCII_ID;
    qsf_rb->qsf_length = sizeof(QSF_RCB);
    qsf_rb->qsf_owner = (PTR)DB_PSF_ID;
    qsf_rb->qsf_sid = sess_cb->pss_sessid;
    qsf_rb->qsf_obj_id.qso_type = QSO_QTEXT_OBJ;
    qsf_rb->qsf_obj_id.qso_lname = 0;

    /* Having retrieved the text place it in QSF
    ** because the parser expects it to be there.
    */
    status = qsf_call(QSO_CREATE, qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	i4	    qerr = qsf_rb->qsf_error.err_code;

	if (qerr == E_QS0001_NOMEM)
	{
	    (VOID) psf_error(qerr, qerr,
		PSF_CALLERR, &err_code, &psq_cb->psq_error, 0);
	}
	else
	{
	    (VOID) psf_error(E_PS0A05_BADMEMREQ, qerr,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	}

	goto cleanup2;
    }

    /* Object is locked exclusively now. */

    pinfo = rdf_cb->rdf_rb.rdr_procedure;

    /* Allocate enough memory for the query descriptor
    ** plus the length of text.
    */
    qsf_rb->qsf_sz_piece = sizeof(PSQ_QDESC) +
	pinfo->rdf_l_querytext + 3; /* one space, one null,
				    ** one for safety.
				    */

    status = qsf_call(QSO_PALLOC, qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	i4	    qerr = qsf_rb->qsf_error.err_code;

	if (qerr == E_QS0001_NOMEM)
	{
	    (VOID) psf_error(qerr, qerr,
		PSF_CALLERR, &err_code, &psq_cb->psq_error, 0);
	}
	else
	{
	    (VOID) psf_error(E_PS0A05_BADMEMREQ, qerr,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	}

	goto cleanup1;
    }

    qdesc = (PSQ_QDESC *) qsf_rb->qsf_piece;

    /* Initialize query descriptor. */
    qdesc->psq_qrysize = pinfo->rdf_l_querytext + 1; /* 1 trailing space */
    qdesc->psq_datasize = 0;
    qdesc->psq_dnum = 0;
    qdesc->psq_qrytext = (char *)(qdesc + 1); /* Ptr arithmetic, should point
				    ** right after the PSQ_QDESC.
				    */
    qdesc->psq_qrydata = (DB_DATA_VALUE **) NULL;

    /* QSF memory has been allocated now, copy
    ** the text from RDF.
    */
    ulm_copy((PTR) pinfo->rdf_querytext,
	     (i4) pinfo->rdf_l_querytext,
	     (PTR) qdesc->psq_qrytext);

    /* Add a space after the text and null terminate. */
    {
	char	*p;

	p = qdesc->psq_qrytext;		/* beginning of text */
	p += pinfo->rdf_l_querytext;	/* 1st char past end */
	*p++ = ' ';
	*p = '\0';			/* 2nd char past end */
    }

    /* Set root for the QSF object */
    qsf_rb->qsf_root = qsf_rb->qsf_piece;

    status = qsf_call(QSO_SETROOT, qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	(VOID) psf_error(E_PS0A05_BADMEMREQ, qsf_rb->qsf_error.err_code,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	goto cleanup1;
    }

    status = qsf_call(QSO_UNLOCK, qsf_rb);

    if (DB_FAILURE_MACRO(status))
    {
	(VOID) psf_error(E_PS0B05_CANT_UNLOCK, qsf_rb->qsf_error.err_code,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	goto cleanup1;
    }

    psq_cb->psq_qid = qsf_rb->qsf_obj_id.qso_handle;

    return (status);

cleanup1:
    /* Destroy the object, it's already locked. */
    stat = qsf_call(QSO_DESTROY, qsf_rb);

    if (DB_FAILURE_MACRO(stat))
    {
	(VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb->qsf_error.err_code,
		PSF_INTERR, &err_code, &psq_cb->psq_error, 0);
	if (stat > status)
	    status = stat;
    }

cleanup2:
    /* RDF object can be released now. */

    stat = rdf_call(RDF_UNFIX, (PTR) rdf_cb);

    if (DB_FAILURE_MACRO(stat))
    {
	(VOID) psf_rdf_error(RDF_UNFIX,
	    &rdf_cb->rdf_error, &psq_cb->psq_error);
	if (stat > status)
	    status = stat;
    }

    return (status);
}
Beispiel #9
0
/*{
** Name: psy_gsequence	- Get description of a sequence from RDF.
**
** Description:
** 	This routine calls RDF to return the iisequence tuple for a sequence,
**	then moves certain columns into the PSS_SEQINFO structure for its caller.
**	It is used by psl to verify the existence of a sequence referenced in 
**	a sequence operation (next/current value) and return definition information.
**
** Inputs:
**	sess_cb				Pointer to session control block.
**	    .pss_user			User/owner of the event.
**	seq_own				Sequence owner (from syntax).
**	seq_name			Sequence name (from syntax).
**	seq_mask			flag field
**	    PSS_USRSEQ	    search for sequence owned by the current user
**	    PSS_DBASEQ	    search for sequence owned by the DBA
**				    (must not be set unless 
**				    (seq_mask & PSS_USRSEQ))
**	    PSS_INGSEQ	    search for sequence owned by $ingres
**                                  (must not be set unless
**                                  (seq_mask & PSS_USRSEQ))
**	    PSS_SEQ_BY_OWNER	    search for sequence owned by the specified 
**				    owner
**	    PSS_SEQ_BY_ID	    search for sequence by id
**		NOTE:		    PSS_USRSEQ <==> !PSS_SEQ_BY_OWNER
**				    PSS_SEQ_BY_ID ==> !PSS_SEQ_BY_OWNER
**				    PSS_SEQ_BY_ID ==> !PSS_USRSEQ
**	privs				Pointer to privilege bit map (if we're to
**					check privileges on this sequence) or NULL.
**	qmode				Query mode (for errors).
**	grant_all			Flag indicating GRANT ALL accompanied request.
**
** Outputs:
**	seq_info			Pointer to sequence information block
**	    .pss_seqname		Sequence name.
**	    .pss_owner			Sequence owner.
**	    .pss_seqid			Internal sequence ID.
**	    .pss_dt			Sequence value datatype.
**	    .pss_length			Sequence value length.
**	    .pss_secid			Sequence security ID.
**      err_blk
**	    .err_code			Filled in if an error happens:
**		E_US1914_SEQ_NOT_FOUND	  Cannot find sequence definition.
**		Generally, the error codes returned by RDF and QEU
**		qrymod processing routines are passed back to the caller
**		except where they are user errors (eg, sequence doesn't exist).
**
**	Returns:
**	    E_DB_OK, E_DB_WARN, E_DB_ERROR, E_DB_FATAL
**	Exceptions:
**	    none
**
** Side Effects:
**	none
**
** History:
**	18-mar-02 (inkdo01)
**	    Cloned from psy_gevent for sequence support.
**	21-feb-03 (inkdo01)
**	    Add seq_mask to control iisequence retrieval.
**	24-apr-03 (inkdo01)
**	    Reset IISEQUENCE ptr for secondary calls to RDF.
**	24-apr-03 (inkdo01)
**	    Fix "not found" message for "drop sequence".
**      09-Mar-2010 (coomi01) b123351
**          Block users from dropping dba sequences.
**      29-Apr-2010 (coomi01) b123638
**          Backout the above change, then put in a test
**          to prevent delete dba's sequence by non dba.  
**          This allows non-dba to find sequence for 
**          updating.
**	15-Oct-2010 (kschendel) SIR 124544
**	    Update psl-command-string call.
*/
DB_STATUS
psy_gsequence(
	PSS_SESBLK      *sess_cb,
	DB_OWN_NAME	*seq_own,
	DB_NAME		*seq_name,
	i4		seq_mask,
	PSS_SEQINFO	*seq_info,
	DB_IISEQUENCE	*seqp,
	i4		*ret_flags,
	i4		*privs,
	i4		qmode,
	i4		grant_all,
	DB_ERROR	*err_blk)
{
    DB_STATUS		status;
    RDF_CB		rdf_seq;	/* RDF for sequence */
    DB_IISEQUENCE	seqtuple;	/* sequence tuple to retrieve into */
    i4		err_code;
    bool	leave_loop = TRUE;

    *ret_flags = 0;

    /* First retrieve sequence tuple from RDF */
    if (seqp == NULL)
	seqp = &seqtuple;

    /* zero out RDF_CB and init common elements */
    pst_rdfcb_init(&rdf_seq, sess_cb);

    /* init relevant elements */
    {
	rdf_seq.rdf_rb.rdr_types_mask = RDR_BY_NAME;
	rdf_seq.rdf_rb.rdr_2types_mask = RDR2_SEQUENCE;
	MEmove(sizeof(DB_NAME), (PTR) seq_name, ' ',
	    sizeof(DB_NAME), (PTR) &rdf_seq.rdf_rb.rdr_name.rdr_seqname);
	STRUCT_ASSIGN_MACRO((*seq_own), rdf_seq.rdf_rb.rdr_owner);
    }
    
    rdf_seq.rdf_rb.rdr_update_op = RDR_OPEN;
    rdf_seq.rdf_rb.rdr_qtuple_count = 1;
    rdf_seq.rdf_rb.rdr_qrytuple = (PTR) seqp;

    do     		/* something to break out of */
    {
	status = rdf_call(RDF_GETINFO, (PTR) &rdf_seq);

	/*
	** if caller specified sequence owner name, or
	**    the sequence was found, or
	**    an error other than "sequence not found" was encountered,
	**  bail out
	*/
	if (   seq_mask & PSS_SEQ_BY_OWNER
	    || status == E_DB_OK
	    || rdf_seq.rdf_error.err_code != E_RD0013_NO_TUPLE_FOUND
	   )
	    break;

	/*
	** if sequence was not found, and
	**    - caller requested that DBA's sequences be considered, and
	**    - user is not the DBA,
	**    - check we are not attempting to destroy the sequence.
	** check if the sequence is owned by the DBA
	*/
	if ((qmode != PSQ_DSEQUENCE) &&
	       seq_mask & PSS_DBASEQ
	    && MEcmp((PTR) &sess_cb->pss_dba.db_tab_own, 
		   (PTR) &sess_cb->pss_user, sizeof(DB_OWN_NAME))
	   )
	{
	    STRUCT_ASSIGN_MACRO(sess_cb->pss_dba.db_tab_own,
				rdf_seq.rdf_rb.rdr_owner);
	    rdf_seq.rdf_rb.rdr_qtuple_count = 1;
	    rdf_seq.rdf_rb.rdr_qrytuple = (PTR) &seqtuple;
	    status = rdf_call(RDF_GETINFO, (PTR) &rdf_seq);
	    if (status == E_DB_OK)
		STRUCT_ASSIGN_MACRO(seqtuple, *seqp);
	}

	/*
	** if still not found, and
	**   - caller requested that sequences owned by $ingres be considered, and
	**   - user is not $ingres and
	**   - DBA is not $ingres,
	** check if the sequence is owned by $ingres
	*/
	if (   status != E_DB_OK
	    && rdf_seq.rdf_error.err_code == E_RD0013_NO_TUPLE_FOUND
	    && seq_mask & PSS_INGSEQ
	   )
	{
	    if (   MEcmp((PTR) &sess_cb->pss_user,
			 (PTR) sess_cb->pss_cat_owner,
			 sizeof(DB_OWN_NAME)) 
		&& MEcmp((PTR) &sess_cb->pss_dba.db_tab_own,
			 (PTR) sess_cb->pss_cat_owner,
			 sizeof(DB_OWN_NAME))
	       )
	    {
		STRUCT_ASSIGN_MACRO((*sess_cb->pss_cat_owner),
				    rdf_seq.rdf_rb.rdr_owner);
		rdf_seq.rdf_rb.rdr_qtuple_count = 1;
		rdf_seq.rdf_rb.rdr_qrytuple = (PTR) &seqtuple;
		status = rdf_call(RDF_GETINFO, (PTR) &rdf_seq);
		if (status == E_DB_OK)
		    STRUCT_ASSIGN_MACRO(seqtuple, *seqp);
	    }
	}

	/* leave_loop has already been set to TRUE */
    } while (!leave_loop);

    if (status != E_DB_OK)
    {
	if (rdf_seq.rdf_error.err_code == E_RD0013_NO_TUPLE_FOUND)
	{
	    if (qmode == PSQ_ASEQUENCE || qmode == PSQ_DSEQUENCE)
	    {
		_VOID_ psf_error(6419L, 0L,
		    PSF_USERERR, &err_code, err_blk, 1,
		    psf_trmwhite(sizeof(*seq_name), 
		    (PTR)seq_name), (PTR)seq_name);
	    }
	    else /* must be DML currval/nextval request */
	    {
		char        qry[PSL_MAX_COMM_STRING];
		i4     qry_len;

		psl_command_string(qmode, sess_cb, qry, &qry_len);
		_VOID_ psf_error(6420L, 0L,
		    PSF_USERERR, &err_code, err_blk, 2,
		    qry_len, qry,
		    psf_trmwhite(sizeof(*seq_name), (char *) seq_name),
		    (PTR) seq_name);
	    }
	    if (sess_cb->pss_dbp_flags & PSS_DBPROC)
		sess_cb->pss_dbp_flags |= PSS_MISSING_OBJ;

	    *ret_flags |= PSS_MISSING_SEQUENCE;
	    status = E_DB_OK;
	}
	else /* some other error */
	{
	    _VOID_ psf_rdf_error(RDF_GETINFO, &rdf_seq.rdf_error, err_blk);
	}

	return (status);
    } /* If RDF did not return the sequence tuple */

    STRUCT_ASSIGN_MACRO(rdf_seq.rdf_rb.rdr_owner, (*seq_own));
					/* copy back successful owner */

    if (seq_info != NULL)
    {
	/* fill in a sequence descriptor */
	STRUCT_ASSIGN_MACRO(seqp->dbs_name, seq_info->pss_seqname);
	STRUCT_ASSIGN_MACRO(seqp->dbs_owner, seq_info->pss_seqown);
	STRUCT_ASSIGN_MACRO(seqp->dbs_uniqueid, seq_info->pss_seqid);
	seq_info->pss_dt = seqp->dbs_type;
	seq_info->pss_length = seqp->dbs_length;
	seq_info->pss_prec = seqp->dbs_prec;
    }

    /*
    ** if we are parsing a dbproc and the sequence which we have just looked up
    ** is owned by the dbproc's owner, we will add the sequence to the dbproc's
    ** independent object list unless it has already been added.
    ** Note that only sequences owned by the current user will be included into
    ** the list of independent objects.
    **
    ** NOTE: we do not build independent object list for system-generated
    **	     dbprocs
    */
    if (   sess_cb->pss_dbp_flags & PSS_DBPROC
	&& ~sess_cb->pss_dbp_flags & PSS_SYSTEM_GENERATED
        && !MEcmp((PTR) &sess_cb->pss_user, (PTR) &seqp->dbs_owner,
		  sizeof(sess_cb->pss_user))
       )
    {
	status = pst_add_1indepobj(sess_cb, &seqp->dbs_uniqueid,
	    PSQ_OBJTYPE_IS_SEQUENCE, (DB_DBP_NAME *) NULL,
	    &sess_cb->pss_indep_objs.psq_objs, sess_cb->pss_dependencies_stream,
	    err_blk);

	if (DB_FAILURE_MACRO(status))
	{
	    return(status);
	}
    }
		  
    if (privs && *privs)
    {
	i4	    privs_to_find = *privs;

	status = psy_seqperm(&rdf_seq, &privs_to_find, sess_cb, seq_info, qmode,
	    grant_all, err_blk);
	if (DB_FAILURE_MACRO(status))
	{
	    return (status);
	}
	else if (privs_to_find)
	{
	    if (grant_all && *privs != privs_to_find)
	    {
		/*
		** if we are processing GRANT ALL and psy_seqperm() has
		** determined that the user may grant some but not all
		** privileges on the sequence, reset the privilege map
		** accordingly
		*/
		*privs &= ~(privs_to_find & ~((i4) DB_GRANT_OPTION));
	    }
	    else
	    {
		*ret_flags |= PSS_INSUF_SEQ_PRIVS;
		return(E_DB_OK);
	    }
	} /* If no permission */
    }

    return(E_DB_OK);

}
Beispiel #10
0
DB_STATUS
adi_tyid(
ADF_CB             *adf_scb,
ADI_DT_NAME        *adi_dname,
DB_DT_ID           *adi_did)
{
    i4                  s;
    i4                  n;
    i4                  i;
    i4                  cmp;
    char		*c1;
    char		*c2;
    ADI_DT_NAME         dt_name;
    bool		dategiven = FALSE;

    s = sizeof(adi_dname->adi_dtname);
    c2 = &adi_dname->adi_dtname[0];

    if (c2 && ((*c2 == 'd') || (*c2 == 'D')))
    {
          if (STbcompare (c2, 0, "date", 0, TRUE) == 0)
          {
	    dategiven = TRUE;
            if (adf_scb->adf_date_type_alias & AD_DATE_TYPE_ALIAS_INGRES)
            {
                /* replace the input string with ingresdate */
                MEmove(10, (PTR)"ingresdate", '\0',
                                sizeof(ADI_DT_NAME), (PTR)&dt_name.adi_dtname);
		dt_name.adi_dtname[10]='\0';
            }
            else if (adf_scb->adf_date_type_alias & AD_DATE_TYPE_ALIAS_ANSI)
            {
                /* replace the input string with ansidate */
                MEmove(8, (PTR)"ansidate", '\0',
                                sizeof(ADI_DT_NAME), (PTR)&dt_name.adi_dtname);
		dt_name.adi_dtname[8]='\0';
            }
            else
            {
                return (adu_error(adf_scb, E_AD5065_DATE_ALIAS_NOTSET, 0));
            }
          }
    }

    for(n=1; n <= ADI_MXDTS; n++)
    {
	if (Adf_globs->Adi_datatypes[n].adi_dtid == DB_NODT) break;

	cmp = 1;
	c1 = &Adf_globs->Adi_datatypes[n].adi_dtname.adi_dtname[0];
	if (dategiven == TRUE)
	  c2 = (PTR)&dt_name.adi_dtname;
	else
    	  c2 = &adi_dname->adi_dtname[0];
	i = 0;

	while ((i++ < s)  &&  (*c1 != 0  ||  *c2 != 0))
	{
	    if (*c1++ != *c2++)
	    {
		cmp = 0;
		break;
	    }
	}

	if (cmp)
	{
	    *adi_did = Adf_globs->Adi_datatypes[n].adi_dtid;
	    return(E_DB_OK);
	}
    }

    *adi_did = DB_NODT;
    return(adu_error(adf_scb, E_AD2003_BAD_DTNAME, 0));
}
Beispiel #11
0
/*{
** Name: psy_drop_synonym - Drop an IISYNONYM tuple.
**
** Description:
**	Call RDF_UPDATE to delete a tuple from IISYNONYM.
** Inputs:
**	psy_cb		PSY control block.
**	sess_cb		PSF session control block.
** Outputs:
**	Exceptions:
**	    none
** Returns:
**	E_DB_OK			synonym tuple has been deleted successfully;
**	error status from RDF	otherwise
**
** Side Effects:
**	    Modifies system catalogs.
**
** History:
**      19-apr-90 (andre)
**	    Created.
**      22-may-90 (teg)
**          init rdr_instr to RDF_NO_INSTR
**	03-aug-92 (barbara)
**	    Invalidate base table infoblk from RDF's cache.
**	10-aug-93 (andre)
**	    fixed causes of compiler warnings
**	13-sep-93 (andre)
**	    QEF will assume responsibility for altering timestamps of tables
**	    (or underlying tables of views) synonym(s) on which have been 
**	    dropped.  We will supply QEF with the id of the object on which 
**	    the synonym was defined
**	22-oct-93 (andre)
**	    In the unlikely event that RDF's cache entry for the synonym named 
**	    in the DROP SYNONYM statement is stale and the synonym no longer 
**	    exists, RDF will return E_RD014A_NONEXISTENT_SYNONYM which we will 
**	    translate into 2753L
*/
DB_STATUS
psy_drop_synonym(
	PSY_CB	   *psy_cb,
	PSS_SESBLK *sess_cb)
{
    RDF_CB		rdf_cb;
    RDF_CB		rdf_inv_cb;
    DB_IISYNONYM	syn_tuple;
    register RDR_RB	*rdf_rb = &rdf_cb.rdf_rb;
    DB_STATUS		status;
    register i4	syn_count;
    i4		err_code;


    /* Initialize the RDF request block. */
    pst_rdfcb_init(&rdf_cb, sess_cb);
    pst_rdfcb_init(&rdf_inv_cb, sess_cb);
    STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner);
    rdf_rb->rdr_2types_mask = (RDF_TYPES) RDR2_SYNONYM;
    rdf_rb->rdr_update_op = RDR_DELETE;
    rdf_rb->rdr_qrytuple = (PTR) &syn_tuple;
    rdf_rb->rdr_tabid.db_tab_base = DM_B_SYNONYM_TAB_ID;
    rdf_rb->rdr_tabid.db_tab_index = DM_I_SYNONYM_TAB_ID;

    MEmove(sizeof(DB_OWN_NAME), (char *)&sess_cb->pss_user, ' ',
           sizeof(DB_SYNOWN), (char *)&syn_tuple.db_synowner);

    for (syn_count = 0; syn_count < psy_cb->psy_numtabs; syn_count++)
    {
	/* store synonym name in the tuple */
	MEmove(sizeof(DB_TAB_NAME), (char *)(psy_cb->psy_tabname + syn_count),
	       ' ', sizeof(DB_SYNNAME), (char *)&syn_tuple.db_synname);
	
	syn_tuple.db_syntab_id.db_tab_base = 
	    psy_cb->psy_tables[syn_count].db_tab_base;
	
	syn_tuple.db_syntab_id.db_tab_index = 
	    psy_cb->psy_tables[syn_count].db_tab_index;

	/* Drop a tuple from IISYNONYM */
	status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb);

	if (DB_FAILURE_MACRO(status))
	{
	    if (rdf_cb.rdf_error.err_code == E_RD0144_DROP_SYNONYM)
	    {
		(VOID) psf_error(E_PS0456_DROP_SYN_ERROR, 0L, PSF_USERERR,
		    &err_code, &psy_cb->psy_error, 1,
		    psf_trmwhite(sizeof(DB_SYNNAME), 
			(char *) &syn_tuple.db_synname),
		    &syn_tuple.db_synname);
	    }
	    else if (rdf_cb.rdf_error.err_code == E_RD014A_NONEXISTENT_SYNONYM)
	    {
		/* 
		** looks like RDF cache entry was stale - tell user that 
		** synonym did not exist and proceed on to the next entry
		*/
		status = E_DB_OK;

		(VOID) psf_error(2753L, 0L, PSF_USERERR, &err_code,
		    &psy_cb->psy_error, 2,
		    sizeof("DROP SYNONYM") - 1, "DROP SYNONYM",
		    psf_trmwhite(sizeof(DB_SYNNAME), 
			(char *) &syn_tuple.db_synname),
		    &syn_tuple.db_synname);
		
		continue;
	    }
	    else
	    {
		(VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error,
		    &psy_cb->psy_error);
	    }
	    break;
	}


	STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[syn_count],
			    rdf_inv_cb.rdf_rb.rdr_tabid);
				
	status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_inv_cb);

	if (DB_FAILURE_MACRO(status))
	{
	    (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_inv_cb.rdf_error,
				&psy_cb->psy_error);
	    break;
	}
    }

    return (status);
}
Beispiel #12
0
/*{
** Name: scu_xencode - encrypt a character string
**
** Description:
**      This function uses CI routines to encrypt a character string.
**	Since the character string is used to generate the key schedule,
**	the encryption is essentially one-way (you'd need to know the
**	password to decode the password....)  This routine was designed
**	to encrypt application_id passwords.
**
** Inputs:
**      SCU_XENCODE			the opcode to scf_call()
**      scf_cb                          control block in which is specified
**          .scf_ptr_union.scf_xpassword
**			                pointer to buffer to be encrypted
**          .scf_nbr_union.scf_xpasskey
**			                pointer to seed for key schedule
**          .scf_len_union.scf_xpwdlen
**					length of password and key seed
**
** Outputs:
**      scf_cb                          the same control block
**          .error                      the error control area
**              .err_code               E_SC_OK or ...
**					E_SC0261_XENCODE_BAD_PARM
**					E_SC0262_XENCODE_BAD_RESULT
**	Returns:
**	    E_DB_{OK, WARNING, ERROR, FATAL}
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	24-mar-89 (ralph)
**          Written for terminator
**	20-may-89 (ralph)
**	    Changed encryption to use separate key
**	06-jun-89 (ralph)
**	    Fixed unix compile problems
**	06-may-1993 (ralph)
**	    DELIM_IDENT:
**	    Translate key seed to lower case prior to encryption.
**	2-Jul-1993 (daveb)
**	    prototyped.
**	14-jul-93 (ed)
**	    replacing <dbms.h> by <gl.h> <sl.h> <iicommon.h> <dbdbms.h>
**	12-Sep-2007 (drivi01)
**	    Modified scu_xencode function to fix numerous bugs.
**	    The buffers for password manipulation shouldn't exceed
**	    the size of scb_xpassword field in SCF control block,
**	    otherwise the data will be truncated.
*/
DB_STATUS
scu_xencode(SCF_CB *scf_cb, SCD_SCB *scb )
{
    STATUS	status;
    CI_KS	KS;
    char	inbuffer[DB_PASSWORD_LENGTH+1];
    char	outbuffer[DB_PASSWORD_LENGTH+1];
    char	keybuffer[DB_PASSWORD_LENGTH];
    u_i2	i2_size;
    i4		longnat_size;
    i4		nat_size;
    char	*char_ptr;

#define	PASSINIT    "hjodvwHOJHOJhodh498032&*&*#)$&*jpkshghjlg58925fjkdjkpg"

    status = E_DB_OK;
    CLRDBERR(&scf_cb->scf_error);

    /* Ensure input parameter is okay */

    if ((scf_cb->scf_len_union.scf_xpwdlen <= 0)		||
	(scf_cb->scf_len_union.scf_xpwdlen >= sizeof(inbuffer)) ||
	(scf_cb->scf_nbr_union.scf_xpasskey  == NULL)		||
	(scf_cb->scf_ptr_union.scf_xpassword == NULL))
    {
	sc0ePut(NULL, E_SC0261_XENCODE_BAD_PARM, NULL, 0);
	SETDBERR(&scf_cb->scf_error, 0, E_SC0261_XENCODE_BAD_PARM);
	return(E_DB_ERROR);
    }


    /* Copy string to input buffer */

    MEmove(scf_cb->scf_len_union.scf_xpwdlen,
		 (PTR)scf_cb->scf_ptr_union.scf_xpassword,
		 (char)'\0',
		 sizeof(inbuffer),
		 (PTR)inbuffer);

    /* Copy key to key buffer */

    MEmove(scf_cb->scf_len_union.scf_xpwdlen,
		 (PTR)scf_cb->scf_nbr_union.scf_xpasskey,
		 (char)'?',
		 sizeof(keybuffer),
		 (PTR)keybuffer);

    /* Fold the key to lower case */

    for (nat_size = sizeof(keybuffer), char_ptr = keybuffer;
	 nat_size > 0;
	 nat_size = CMbytedec(nat_size, char_ptr), char_ptr = CMnext(char_ptr))
    {
	CMtolower(char_ptr, char_ptr);
    }

	 

    /* Remove white space from input string */

    nat_size = STzapblank(inbuffer, outbuffer);

    /* Check size */

    if ((nat_size <= 0) ||
	(nat_size > sizeof(outbuffer)-1))
    {
	sc0ePut(NULL, E_SC0261_XENCODE_BAD_PARM, NULL, 0);
	SETDBERR(&scf_cb->scf_error, 0, E_SC0261_XENCODE_BAD_PARM);
	return(E_DB_ERROR);
    }

    /* Initialize input buffer to "garbage" */

    MEmove(sizeof(PASSINIT), (PTR)PASSINIT, (char)'?',
		 sizeof(inbuffer), (PTR)inbuffer);

    /* Normalize the string back into input buffer */

    MEcopy((PTR)outbuffer, nat_size, (PTR)inbuffer);

    /* Reset output buffer to blanks */

    MEfill(sizeof(outbuffer),
		 (u_char)' ',
		 (PTR)outbuffer);

    /*
    ** First, encrypt the key seed using the string to encode.
    ** Then,  encrypt the string using the encrypted seed.
    ** This is done to prevent two roles with the same password
    ** from having the same encrypted value.
    ** Note that this makes the encryption one-way, since
    ** the password must be provided to decrypt the password!
    */

    /* Generate the key schedule to encrypt the key seed */

    (VOID)CIsetkey((PTR)inbuffer, KS);

    /* Encrypt the key seed */

    longnat_size = DB_PASSWORD_LENGTH;
    (VOID)CIencode((PTR)keybuffer, longnat_size, KS, (PTR)outbuffer);

    /* Generate the second key schedule */

    (VOID)CIsetkey((PTR)keybuffer, KS);

    /* Encode the string */

	longnat_size = DB_PASSWORD_LENGTH;
    (VOID)CIencode((PTR)inbuffer, longnat_size, KS, (PTR)outbuffer);

    /* Make sure it was really encoded */

    if ((char *)STskipblank(outbuffer, (i4)sizeof(outbuffer))
		!= NULL)
    {
	/* It was; copy result to caller's area */

	i2_size = scf_cb->scf_len_union.scf_xpwdlen;
	MEmove(sizeof(outbuffer), (PTR)outbuffer, (char)' ',
		     i2_size, (PTR)scf_cb->scf_ptr_union.scf_xpassword);
    }
    else
    {
	/* The encryption did not work; return an error */

	sc0ePut(NULL, E_SC0262_XENCODE_BAD_RESULT, NULL, 0);
	SETDBERR(&scf_cb->scf_error, 0, E_SC0262_XENCODE_BAD_RESULT);
	status = E_DB_ERROR;
    }

    return(status);
}