Exemplo n.º 1
0
/*{
** Name: dmu_pindex - Creates multiple indices on a table.
**
**  INTERNAL DMF call format:      status = dmu_pindex(&dmu_cb);
**
**  EXTERNAL call format:          status = dmf_call(DMU_PINDEX_TABLE,&dmu_cb);
**
** Description:
**    The dmu_index function handles the creation of indices.
**    This dmu function is allowed inside a user specified transaction.
**    The table name must not be the same as a system table name and must 
**    not be the same name as any other table owned by the same user. 
**    The table that this index is defined on must exist and must be
**    identified by use of the internal identifier obtained from a dmt_show
**    operation.  It is assumed that the caller has verified that the
**    base table is owned by the same user.
**
** Inputs:
**      .dmu_cb
**          .type                           Must be set to DMU_UTILITY_CB.
**          .length                         Must be at least sizeof(DMU_CB).
**          .dmu_tran_id                    Must be the current transaction 
**                                          identifier returned from the begin 
**                                          transaction operation.
**          .dmu_flags_mask                 Must be zero.
**          .dmu_tbl_id                     Internal name of table to be 
**                                          indexed.
**          .dmu_index_name                 External name of index to be 
**                                          created.
**          .dmu_location.data_address      Pointer to array of locations.
**                                          Each entry in array is of type
**                                          DB_LOC_NAME.  
**	    .dmu_location.data_in_size      The size of the location array
**                                          in bytes.
**          .dmu_olocation.data_address     This holds source of gateway
**					    table if this is a gateway register.
**          .dmu_key_array.ptr_address      Pointer to an area used to input
**                                          an array of pointer to entries
**					    of type DMU_KEY_ENTRY.  
**                                          See below for description of 
**                                          <dmu_key_list> entries.
**          .dmu_key_array.ptr_size         Size of an entry.
**          .dmu_key_array.ptr_in_count     Count of entries.
**	    .dmu_attr_array.ptr_address	    Pointer to to area used to input
**					    an array or pointers to entries
**					    of type DMU_KEY_ENTRY.
**					    If this entry is not passed in
**					    all the key's given in the key
**					    array are considered part of the
**					    key.  If this pass in, only the
**					    keys in this list are considered
**					    part of the key.  The keys listed
**					    in this list must be a prefix set
**					    of the keys listed in the key array.
**          .dmu_attr_array.ptr_size        Size of an entry.
**          .dmu_attr_array.ptr_in_count    Count of entries.
**          .dmu_char_array.data_address    Pointer to an area used to input
**                                          an array of entries of type
**                                          DMU_CHAR_ENTRY.
**                                          See below for description of 
**                                          <dmu_char_array> entries.
**          .dmu_char_array.data_in_size    Length of char_array in bytes.
**	    .dmu_gwchar_array.data_address  Pointer to an array of gateway table
**					    characteristics.  These are used
**					    if the table is a DMU_GATEWAY type
**					    table.  These characteristics are
**					    passed directly down to the Ingres
**					    Gateway system.
**	    .dmu_gwchar_array.data_in_size  Length of gwchar_array in bytes.
**	    .dmu_gwattr_array.ptr_address   Pointer to array of pointers, each
**					    of which describes gateway specific
**					    information about a table column.
**					    This is used only if the table is
**					    a DMU_GATEWAY type table.  These
**					    entries are passed directly down to
**					    the Ingres Gateway system.
**	    .dmu_gwattr_array.ptr_size	    The size of each element in array.
**	    .dmu_gwattr_array.ptr_address   The number of pointers in the array.
**
**          <dmu_key_array> entries are of type DMU_KEY_ENTRY and
**          must have following format:
**          key_attr_name                   Name of attribute.
**          key_order                       Must be DMU_ASCENDING.
**
**          <dmu_char_array> entries are of type DMU_CHAR_ENTRY and
**          must have following format:
**          char_id                         Must be one of the dmu 
**                                          characteristics like 
**                                          DMU_STRUCTURE,
**                                          DMU_IFILL,
**					    DMU_DATAFILL,
**					    DMU_LEAFILL,
**                                          DMU_MINPAGES,
**                                          DMU_MAXPAGES,
**                                          DMU_UNIQUE,
**					    DMU_COMPRESSED,
**					    DMU_GATEWAY,
**					    DMU_INDEX_COMP.
**					    DMU_CONCURRENT_ACCESS
**					    DMU_DIMENSION
**					    DMU_TABLE_PRIORITY
**          char_value                      The value to associate with above
**                                          characteristic.
**
** Output:
**      dmu_cb 
**          .dmu_idx_id                     The internal table identifier 
**                                          assigned to this index.
**          .error.err_code                 One of the following error numbers.
**                                          E_DM0000_OK                
**                                          E_DM0006_BAD_ATTR_FLAG
**                                          E_DM0007_BAD_ATTR_NAME
**                                          E_DM0009_BAD_ATTR_SIZE
**                                          E_DM0008_BAD_ATTR_PRECISION
**                                          E_DM000A_BAD_ATTR_TYPE
**                                          E_DM000B_BAD_CB_LENGTH
**                                          E_DM000C_BAD_CB_TYPE
**					    E_DM000D_BAD_CHAR_ID
**					    E_DM000E_BAD_CHAR_VALUE
**                                          E_DM0010_BAD_DB_ID
**                                          E_DM001C_BAD_KEY_SEQUENCE.
**                                          E_DM001D_BAD_LOCATION_NAME.
**                                          E_DM001E_DUP_LOCATION_NAME.
**                                          E_DM001A_BAD_FLAG
**                                          E_DM0021_TABLES_TOO_MANY
**                                          E_DM002A_BAD_PARAMETER
**                                          E_DM0039_BAD_TABLE_NAME
**                                          E_DM003A_BAD_TABLE_OWNER
**                                          E_DM003B_BAD_TRAN_ID
**                                          E_DM0042_DEADLOCK
**                                          E_DM0045_DUPLICATE_KEY
**                                          E_DM004A_INTERNAL_ERROR
**                                          E_DM004B_LOCK_QUOTA_EXCEEDED
**                                          E_DM0054_NONEXISTENT_TABLE
**                                          E_DM0059_NOT_ALL_KEYS
**                                          E_DM005D_TABLE_ACCESS_CONFLICT
**                                          E_DM005E_CANT_UPDATE_SYSCAT
**                                          E_DM005F_CANT_INDEX_CORE_SYSCAT
**                                          E_DM0064_USER_INTR
**                                          E_DM0065_USER_ABORT
**	    				    E_DM006A_TRAN_ACCESS_CONFLICT
**                                          E_DM0071_LOCATIONS_TOO_MANY
**                                          E_DM0072_NO_LOCATION
**                                          E_DM0078_TABLE_EXISTS
**					    E_DM007D_BTREE_BAD_KEY_LENGTH
**					    E_DM010F_ISAM_BAD_KEY_LENGTH
**					    E_DM0110_COMP_BAD_KEY_LENGTH
**					    E_DM0092_ERROR_INDEXING_TABLE
**                                          E_DM009F_ILLEGAL_OPERATION
**                                          E_DM0100_DB_INCONSISTENT
**                                          E_DM0103_TUPLE_TOO_WIDE
**                                          E_DM010C_TRAN_ABORTED
**                                          E_DM0125_DDL_SECURITY_ERROR
**
**          .error.err_data                 Set to attribute in error by 
**                                          returning index into attribute list.
**      Returns:
**          E_DB_OK                         Function completed normally. 
**          E_DB_WARN                       Function completed normally with 
**                                          a termination status which is in 
**                                          dmu_cb.error.err_code.
**          E_DB_ERROR                      Function completed abnormally with 
**                                          a termination status which is in
**                                          dmu_cb.error.err_code.
**          E_DB_FATAL                      Function completed with a fatal
**                                          error which must be handled
**                                          immediately.  The fatal status is in
**                                          dmu_cb.error.err_code.
**
** History:
**      01-may-98 (nanpr01) 
**          Created from dmu_index.
**      18-mar-1999 (stial01)
**          Copy err_code, err_data into corresponding dmu cb, not 1st. 
**      01-may-1999 (stial01)
**          Fixed error handling.
**      17-Apr-2001 (horda03) Bug 104402
**          Added support for TCB_NOT_UNIQUE attribute.
**	15-jul-2002 (hayke02)
**	    Initialise systemGenerated et al at the beginning of the
**	    dmu/indx_cb for loop. This prevents non-system generated
**	    (constraint) persistent indices being marked as such after a
**	    system generated index has already been processed. This change
**	    fixes bug 107621.
**      24-jul-2002 (hanal04) Bug 108330 INGSRV 1847
**          Initialise the new indxcb_dmveredo field.
**	22-Dec-2003 (jenjo02)
**	    Added DMU_GLOBAL_INDEX for Partitioned Table Project.
**	6-Feb-2004 (schka24)
**	    Get rid of DMU statement count and its limit.
**	08-jul-2004 (thaju02)
**	    Online Modify - init indxcb_online_fhdr_pageno.
**	    (B112610)
**	11-Mar-2005 (thaju02)
**	    Use $online idxs relation info. (B114069)
**	11-Nov-2005 (jenjo02)
**	    Replaced dmx_show() with the more robust 
**	    dmxCheckForInterrupt() to standardize external
**	    interrupt handling.
**	15-Aug-2006 (jonj)
**	    Moved guts to common dmuIndexSetup().
**      25-oct-2006 (stial01)
**          Fixed initialization of DM2U_INDEX_CB
**	24-Oct-2008 (jonj)
**	    Cleaned up readability, fix potential memory leak.
**	22-Jul-2009 (thaju02)
**	    For E_DM007D, dmu_tup_cnt was not getting set. 
*/
DB_STATUS
dmu_pindex(DMU_CB    *dmu_cbs)
{
    DMU_CB		*dmu = dmu_cbs;
    DMU_CB		*ndmu;
    DM2U_INDEX_CB	*indx_cb, *indx_cbs, *curr_indx_cb = NULL;
    DB_OWN_NAME		table_owner;
    DB_TAB_NAME		table_name;
    DML_XCB		*xcb;
    i4			error,local_error;
    i4			NiX, k, tot_size;
    DB_STATUS		status;

    CLRDBERR(&dmu->error);

    /* Count how many control block was passed */
    ndmu = dmu;

    for ( NiX = 0; ndmu; NiX++ )
	ndmu = (DMU_CB*)ndmu->q_next;

    if (NiX == 1)
    {
	status = dmu_index(dmu);
	return(status);
    }

    tot_size = sizeof(DM2U_INDEX_CB) * NiX; 
    status = dm0m_allocate(tot_size, 0, 
			   (i4)DM2U_IND_CB, (i4)DM2U_IND_ASCII_ID, 
			   (char *)dmu, (DM_OBJECT **)&indx_cbs, &dmu->error);
    if (status != E_DB_OK)
    {
	uleFormat(&dmu->error, 0, NULL, ULE_LOG, NULL, 
		NULL, 0, NULL, &local_error, 0);
	return(E_DB_ERROR);
    }

    ndmu = dmu;
    indx_cb = indx_cbs;

    for (k = 0; k < NiX; k++)
    {
	indx_cb->indxcb_tab_name = &table_name;
	indx_cb->indxcb_tab_owner = &table_owner;

	if ( status = dmuIndexSetup(ndmu, (PTR)indx_cb) )
	{
	    /* copy error info to "first" dmu */
	    dmu->error = ndmu->error;
	    break;
	}

	/* Now link up the control blocks */
	indx_cb->q_next = NULL;
	indx_cb->q_prev = NULL;
	if (curr_indx_cb != (DM2U_INDEX_CB *) NULL)
	    curr_indx_cb->q_next = indx_cb;
	curr_indx_cb = indx_cb;

	ndmu = (DMU_CB*)ndmu->q_next;
	indx_cb++;
    }

    if (dmu->error.err_code)
    {
	if (dmu->error.err_code > E_DM_INTERNAL)
	{
	    uleFormat(&dmu->error, 0, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, 
		(char * )NULL, (i4)0, (i4 *)NULL, &local_error, 0);
	    SETDBERR(&dmu->error, 0, E_DM0092_ERROR_INDEXING_TABLE);
	}

	/* No leaking! */
	dm0m_deallocate((DM_OBJECT **) &indx_cbs);

	return(E_DB_ERROR);
    }

    /* Calls the physical layer to process the rest of the index create */
    status = dm2u_pindex(indx_cbs);

    for (k = 0, ndmu = dmu, indx_cb = indx_cbs; k < NiX; 
	 k++, indx_cb++, ndmu = (DMU_CB *)ndmu->q_next)
    {
	/* Audit successful index on TABLE. */
	if ( status == E_DB_OK && dmf_svcb->svcb_status & SVCB_C2SECURE )
	{
	  status = dma_write_audit(
	     SXF_E_TABLE,
	     SXF_A_SUCCESS | SXF_A_INDEX,
	     ndmu->dmu_index_name.db_tab_name, /* index name */
	     sizeof(ndmu->dmu_index_name.db_tab_name),
	     &ndmu->dmu_owner,		   /* Table/view owner */
	     I_SX2011_INDEX_CREATE,
	     FALSE, /* Not force */
	     &ndmu->error, NULL);
	}

	if ( status )
	{
	    /* Find the first one that got an error */
	    if ( ndmu->error.err_code == 0 )
		continue;

	    if (ndmu->error.err_code > E_DM_INTERNAL)
	    {
		uleFormat(&ndmu->error, 0, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, 
		    (char * )NULL, (i4)0, (i4 *)NULL, &local_error, 0);
		SETDBERR(&ndmu->error, 0, E_DM0092_ERROR_INDEXING_TABLE);
	    }
	    else if ( xcb = indx_cb->indxcb_xcb )
		switch (ndmu->error.err_code)
	    {
		case E_DM004B_LOCK_QUOTA_EXCEEDED:
		case E_DM0112_RESOURCE_QUOTA_EXCEED:
		case E_DM0092_ERROR_INDEXING_TABLE:
		case E_DM0045_DUPLICATE_KEY:
	        case E_DM006A_TRAN_ACCESS_CONFLICT:
		    xcb->xcb_state |= XCB_STMTABORT;
		    break;

		case E_DM0042_DEADLOCK:
		case E_DM004A_INTERNAL_ERROR:
		case E_DM0100_DB_INCONSISTENT:
		    xcb->xcb_state |= XCB_TRANABORT;
		    break;
		case E_DM0065_USER_INTR:
		    xcb->xcb_state |= XCB_USER_INTR;
		    break;
		case E_DM010C_TRAN_ABORTED:
		    xcb->xcb_state |= XCB_FORCE_ABORT;
		    break;
		case E_DM007D_BTREE_BAD_KEY_LENGTH:
		    ndmu->dmu_tup_cnt = indx_cb->indxcb_maxklen;
		    break;
	    }
	    break;
	}
    } 

    dm0m_deallocate((DM_OBJECT **) &indx_cbs);

    return(status);
}
Exemplo n.º 2
0
/*{
** Name: dmfinfo	- Database information display.
**
** Description:
**
** Inputs:
**      journal_context			Pointer to DMF_JSX
**	dcb				Pointer to DCB.
**
** Outputs:
**      err_code                        Reason for error return status.
**	Returns:
**	    E_DB_OK
**	    E_DB_ERROR
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**      01-nov-1986 (Derek)
**          Created for Jupiter.
**	03-feb-1989 (EdHsu)
**	    Updated for online backup.
**	09-apr-1990 (Sandyh)
**	    Added inconsistency reason.
**	17-may-90 (bryanp)
**	    Display the new DUMP_DIR_EXISTS status in the database descriptor.
**      25-feb-1991 (rogerk)
**          Added check for JOURNAL_DISABLED status.  Also added some
**          comment messages for some database states.  These were added
**          for the Archiver Stability project.
**      25-mar-1991 (rogerk)
**          Added checks for NOLOGGING status and nologging inconsistency types.
**      30-apr-1991 (bryanp)
**          Support trace processing ("#x").
**      8-nov-1992 (ed)
**          remove DB_MAXNAME dependency
**	04-nov-92 (jrb)
**	    Changed "SORT" to "WORK" for multi-location sorts project.
**	30-nov-92 (robf)
**	     Add C2 security auditing.
**	14-dec-1992 (rogerk)
**	    Reduced Logging Project: Changed database inconsistent codes.
**	18-jan-1993 (rogerk)
**	    Fixed problem with reporting inconsistency codes added in last
**	    integration.  Shifted TRdisplay vector over one to get correct
**	    output.
**	24-may-1993 (jnash)
**	    Show last journaled log address in <%d:%d:%d> format.
**	20-sep-1993 (bryanp)
**	    Fix TRdisplay calls to line up properly with DB_MAX_NAME=32.
**	20-sep-1993 (jnash)
**	    Fix problem where dump information not presented.  Also include
**	    version information in infodb output.
**	14-oct-93 (jrb)
**	    Added informational line to say when the db is NOT journaled.
**	22-nov-1993 (jnash)
**	    B53797.  Apply Walt's 6.4 VMS fix where if a database never 
**	    checkpointed, INFODB AVs.  Use CL_OFFSETOF rather than zero-pointer
**          construction in TRdisplay statement.  Bug caused by compiler
**          bug when dmfinfo.c containing original expression was compiled
**          with /opt.
**      15-feb-1994 (andyw)
**          Modified dmfinfo to check for checkpoint sequence number of
**          journals and dumps instead of using DSC_CKP_INPROGRESS.
**      15-feb-1994 (andyw)
**          Modified the dump log address incorporating the standard
**          address format <a:b:c> bug reference 58553.
**	25-apr-1994 (bryanp) B62023
**	    Used CL_OFFSETOF to format and display the components of the
**		checkpoint history and dump history. The old technique using
**		casts of null pointers doesn't work on the Alpha.
**      13-Dec-1994 (liibi01)
**          Cross integration from 6.4 (Bug 56364).
**          Added new inconsistency class instance RFP_FAIL as
**          side effect of fix to bug 56364.
**      24-jan-1995 (stial01)
**          BUG 66473: display if checkpoint is table checkpoint
**      12-sep-1995 (thaju02)
**          Added routine output_tbllist().  Implementation of 
**          sending to output the contents of the checkpoint table list
**          file.
**	 6-feb-1996 (nick)
**	    Call to output_tbllist() was missing the err_code param - this
**	    caused an access violation if output_tbllist() tried to set it.
**	    Moved call to output_tbllist() to a) ensure we security audit
**	    the operation, b) ensure the checkpoint in question exists and
**	    c) the output format looks like normal 'infodb'.
**	12-mar-96 (nick)
**	    'Next table id' is actually the last one.
**	29-mar-96 (nick)
**	    Change CKP_INPROGRESS back to CKP.
**	17-may-96 (nick)
**	    Move RFP_FAIL in the TRformat().
**	28-feb-1997 (angusm)
**	    Output collation sequence defined for database. (SIR 72251)
**	07-aug-2000 (somsa01)
**	    When printing out the table list, we were incorrectly passing
**	    an argument to TRformat().
**	12-apr-2005 (gupsh01)
**	    Added support for unicode information.
[@history_template@]...
*/
DB_STATUS
dmfinfo(
DMF_JSX		    *jsx,
DMP_DCB		    *dcb,
DB_STATUS	    *err_code)
{
    DM0C_CNF		*config;
    DM0C_CNF		*cnf;
    i4		i;
    i4		length;
    DB_STATUS		status;
    DB_STATUS		local_status;
    STATUS		cl_status;
    bool                jnode_info = FALSE;
    bool		dnode_info = FALSE;
    char		line_buffer[132];
    CL_ERR_DESC         sys_err;
    SXF_ACCESS		access;
    LG_HEADER		log_hdr;


    if (jsx->jsx_status & JSX_TRACE) 
	TRset_file(TR_F_OPEN, "infodb.dbg", 10, &sys_err);

    /*	Pretend the database is exclusive. */

    dcb->dcb_status |= DCB_S_EXCLUSIVE;

    /*	Lock the database. */

    status = dm0c_open(dcb, 0, dmf_svcb->svcb_lock_list, &config,
	err_code);
    /*
    **	Make sure access is security audited.
    */
    if ( dmf_svcb->svcb_status & SVCB_C2SECURE )
    {
	access = SXF_A_SELECT;
	if (status)
	    access |= SXF_A_FAIL;
	else
	    access |= SXF_A_SUCCESS;
	
	local_status = dma_write_audit( SXF_E_DATABASE,
		    access,
		    dcb->dcb_name.db_db_name, /* Object name (database) */
		    sizeof(dcb->dcb_name.db_db_name), /* Object name (database) */
		    &dcb->dcb_db_owner, /* Object owner */
		    I_SX2711_INFODB,   /*  Message */
		    TRUE,		    /* Force */
		    err_code, NULL);

	if (local_status != E_DB_OK)
	    status=local_status;
    }

    if (status != E_DB_OK)
	return (status);
    cnf = config;

    TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
	"%18*=%@ Database Information%17*=\n\n");
    if (STcompare("                                ",
		  cnf->cnf_dsc->dsc_collation)==0)
	STcopy("default", cnf->cnf_dsc->dsc_collation);
    TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
	"    Database : (%~t,%~t)  ID : 0x%x  Default collation : %~t\n",
	sizeof(cnf->cnf_dsc->dsc_name), &cnf->cnf_dsc->dsc_name,
	sizeof(cnf->cnf_dsc->dsc_owner), &cnf->cnf_dsc->dsc_owner,
        cnf->cnf_dsc->dsc_dbid,
	sizeof(cnf->cnf_dsc->dsc_collation) ,&cnf->cnf_dsc->dsc_collation);

    /* Provide Unicode support information here */
    TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
	"    Unicode enabled : %s\n",
	cnf->cnf_dsc->dsc_dbservice & DU_UTYPES_ALLOWED ? "Yes" : "No");

    if (cnf->cnf_dsc->dsc_dbservice & DU_UTYPES_ALLOWED)
    {	
      TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
      "    Default unicode collation : %~t \t Unicode normalization : %s\n", 
	sizeof(cnf->cnf_dsc->dsc_ucollation) ,&cnf->cnf_dsc->dsc_ucollation,
        (cnf->cnf_dsc->dsc_dbservice & DU_UNICODE_NFC) ? "NFC" : "NFD");
    }

    if (jsx->jsx_status1 & JSX1_OUT_FILE)
    {
        status = output_tbllist(jsx, dcb, cnf, err_code);
    	(void)dm0c_close(cnf, 0, err_code);
        return(status);
    }

    TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
	"    Extents  : %d    Last Table Id : %d\n",
	cnf->cnf_dsc->dsc_ext_count, cnf->cnf_dsc->dsc_last_table_id);
    TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
	"    Config File Version Id : 0x%x   Database Version Id : %d\n", 
	cnf->cnf_dsc->dsc_cnf_version, cnf->cnf_dsc->dsc_c_version);

    /*
    ** Show mode of operation: production on | off 
    **                         online checkpoint enabled | disabled
    */
    TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
	"    Mode     : DDL %s, ONLINE CHECKPOINT %s\n",
	cnf->cnf_dsc->dsc_dbaccess & DU_PRODUCTION ? "DISALLOWED" : "ALLOWED",
	cnf->cnf_dsc->dsc_dbaccess & DU_NOBACKUP ? "DISABLED" : "ENABLED");

    /*
    ** The flag is 'DSC_DUMP_DIR_EXISTS', but we report it as 'CFG_BACKUP',
    ** since its current use is to enable config file auto-backup.
    */
    TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
        "    Status   : %v\n\n",
        "VALID,JOURNAL,CKP,DUMP,ROLL_FORWARD,SMINC,PART,,PRE,CFG_BACKUP,\
	JOURNAL_DISABLED,NOLOGGING",
		cnf->cnf_dsc->dsc_status);

    /*
    ** Print database status information comments.
    */

    if (!(cnf->cnf_dsc->dsc_status & DSC_VALID))
    {
        TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
            "%15* The Database is Inconsistent.\n");
        TRformat(dmf_put_line, 0, line_buffer, sizeof(line_buffer),
            "%19* Cause of Inconsistency:  %w\n",
            ",REC_OPEN_FAILURE,RECOVER_ERROR,REDO_ERROR,UNDO_ERROR,OPEN_COUNT,,\
WILL_COMMIT_ERR,NOLOGGING_ERROR,NOLOGGING_OPENDB,,RFP_FAIL",
            cnf->cnf_dsc->dsc_inconst_code);  
    }
Exemplo n.º 3
0
DB_STATUS
dmu_modify(DMU_CB    *dmu_cb)
{
    DM_SVCB		*svcb = dmf_svcb;
    DMU_CB		*dmu = dmu_cb;
    DML_XCB		*xcb;
    DML_ODCB		*odcb;
    DM2U_MOD_CB		local_mcb, *mcb = &local_mcb;

    i4			recovery;
    i4			truncate;
    i4			duplicates;
    i4			i,j;
    i4			indicator;
    i4			error, local_error;
    DB_STATUS		status;
    bool                bad_loc;
    i4			blob_add_extend = 0;
    bool                used_default_page_size = TRUE;
    i4			page_size;
    i4			verify_options;
    i4			mask;
    i4			has_extensions = 0;
    DB_OWN_NAME		table_owner;
    DB_TAB_NAME		table_name;
    bool		got_action;
    bool		is_table_debug;
    bool		reorg;

    CLRDBERR(&dmu->error);

    /* Any modify should make table recovery disallowed except for the
    ** alter_status options which change logical, physical consistency
    ** and table recovery bit itself
    */
    mcb->mcb_mod_options2 = DM2U_2_TBL_RECOVERY_DEFAULT;

    do
    {
	/*  Check for bad flags. */

	mask = ~(DMU_VGRANT_OK | DMU_INTERNAL_REQ | DMU_RETINTO
		| DMU_PARTITION | DMU_MASTER_OP | DMU_ONLINE_START | DMU_ONLINE_END
		| DMU_NO_PAR_INDEX | DMU_PIND_CHAINED | DMU_NODEPENDENCY_CHECK);
        if ( (dmu->dmu_flags_mask & mask) != 0)
	{
	    SETDBERR(&dmu->error, 0, E_DM001A_BAD_FLAG);
	    break;
	}

	/*  Validate the transaction id. */

	xcb = (DML_XCB *)dmu->dmu_tran_id;
	if (dm0m_check((DM_OBJECT *)xcb, (i4)XCB_CB) != E_DB_OK)
	{
	    SETDBERR(&dmu->error, 0, E_DM003B_BAD_TRAN_ID);
	    break;
	}

	/* Check for external interrupts */
	if ( xcb->xcb_scb_ptr->scb_ui_state )
	    dmxCheckForInterrupt(xcb, &error);

	if ( xcb->xcb_state )
	{
	    if (xcb->xcb_state & XCB_USER_INTR)
	    {
		SETDBERR(&dmu->error, 0, E_DM0065_USER_INTR);
		break;
	    }
	    if (xcb->xcb_state & XCB_FORCE_ABORT)
	    {
		SETDBERR(&dmu->error, 0, E_DM010C_TRAN_ABORTED);
		break;
	    }
	    if (xcb->xcb_state & XCB_ABORT)
	    {
		SETDBERR(&dmu->error, 0, E_DM0064_USER_ABORT);
		break;
	    }	    
	}

	/*  Check the database identifier. */

	odcb = (DML_ODCB *)dmu->dmu_db_id;
	if (dm0m_check((DM_OBJECT *)odcb, (i4)ODCB_CB) != E_DB_OK)
	{
	    SETDBERR(&dmu->error, 0, E_DM0010_BAD_DB_ID);
	    break;
	}

	mcb->mcb_db_lockmode = DM2T_X;

	/*  Check that this is a update transaction on the database 
        **  that can be updated. */
	if (odcb != xcb->xcb_odcb_ptr)
	{
	    SETDBERR(&dmu->error, 0, E_DM005D_TABLE_ACCESS_CONFLICT);
	    break;
	}

	/* Prime the MCB */
	mcb->mcb_dcb = odcb->odcb_dcb_ptr;
	mcb->mcb_xcb = xcb;
	mcb->mcb_tbl_id = &dmu->dmu_tbl_id;
	mcb->mcb_omcb = (DM2U_OMCB*)NULL;
	mcb->mcb_dmu = dmu;
	mcb->mcb_structure = 0;
	mcb->mcb_i_fill = 0;
	mcb->mcb_l_fill = 0;
	mcb->mcb_d_fill = 0;
	mcb->mcb_unique = FALSE;
	mcb->mcb_compressed = TCB_C_NONE;
        mcb->mcb_index_compressed = FALSE;
	mcb->mcb_temporary = FALSE;
	mcb->mcb_merge = FALSE;
	mcb->mcb_clustered = FALSE;
	mcb->mcb_modoptions = 0;
	mcb->mcb_min_pages = 0;
	mcb->mcb_max_pages = 0;
	mcb->mcb_allocation = 0;
	mcb->mcb_extend = 0;
	mcb->mcb_page_type = TCB_PG_INVALID;
	mcb->mcb_page_size = svcb->svcb_page_size;
	mcb->mcb_tup_info = &dmu->dmu_tup_cnt;
	mcb->mcb_reltups = 0;
	mcb->mcb_tab_name = &table_name;
	mcb->mcb_tab_owner = &table_owner;
	mcb->mcb_has_extensions = &has_extensions;
	mcb->mcb_relstat2 = 0;
	mcb->mcb_flagsmask = dmu->dmu_flags_mask;
	mcb->mcb_tbl_pri = 0;
	mcb->mcb_rfp_entry = (DM2U_RFP_ENTRY*)NULL;
	mcb->mcb_new_part_def = (DB_PART_DEF*)dmu->dmu_part_def;
	mcb->mcb_new_partdef_size = dmu->dmu_partdef_size;
	mcb->mcb_verify = 0;

	dmu->dmu_tup_cnt = 0;
        truncate = 0;
	reorg = FALSE;
	duplicates = -1;
	verify_options = 0;
	got_action = FALSE;

	/* FIXME better messages (in general) */
	/* If there's a partdef it has to be one-piece, else bad param */
	if (dmu->dmu_part_def != NULL
	  && dmu->dmu_part_def->ndims > 0
	  && (dmu->dmu_part_def->part_flags & DB_PARTF_ONEPIECE) == 0)
	{
	    SETDBERR(&dmu->error, 0, E_DM002A_BAD_PARAMETER);
	    break;
	}

	/* Disassemble the modify action.
	** FIXME this used to be buried in the characteristics array.
	** It would make much more sense to just carry the action
	** code through, but that will have to wait for another day.
	*/
	got_action = FALSE;
	switch (dmu->dmu_action)
	{
	case DMU_ACT_STORAGE:
	    if (BTtest(DMU_STRUCTURE, dmu->dmu_chars.dmu_indicators))
	    {
		got_action = TRUE;
		mcb->mcb_structure = dmu->dmu_chars.dmu_struct;
	    }
	    break;

	case DMU_ACT_ADDEXTEND:
	    got_action = TRUE;
	    mcb->mcb_mod_options2 |= DM2U_2_ADD_EXTEND;
	    break;

	case DMU_ACT_ENCRYPT:
	    got_action = TRUE;
	    mcb->mcb_mod_options2 |= DM2U_2_ENCRYPT;
	    break;

	case DMU_ACT_LOG_CONSISTENT:
	    if (BTtest(DMU_ACTION_ONOFF, dmu->dmu_chars.dmu_indicators))
	    {
		got_action = TRUE;
		mcb->mcb_mod_options2 &= ~DM2U_2_TBL_RECOVERY_DEFAULT;
		if ( dmu->dmu_chars.dmu_flags & DMU_FLAG_ACTON )
		    mcb->mcb_mod_options2 |= DM2U_2_LOG_CONSISTENT;
		else
		    mcb->mcb_mod_options2 |= DM2U_2_LOG_INCONSISTENT;
	    }
	    break;

	case DMU_ACT_MERGE:
	    got_action = TRUE;
	    mcb->mcb_merge = TRUE;
	    break;

	case DMU_ACT_PERSISTENCE:
	    if (BTtest(DMU_PERSISTS_OVER_MODIFIES, dmu->dmu_chars.dmu_indicators))
	    {
		got_action = TRUE;
		mcb->mcb_mod_options2 |= (dmu->dmu_chars.dmu_flags & DMU_FLAG_PERSISTENCE) ?
			DM2U_2_PERSISTS_OVER_MODIFIES :
			DM2U_2_NOPERSIST_OVER_MODIFIES;
	    }
	    break;

	case DMU_ACT_PHYS_CONSISTENT:
	    if (BTtest(DMU_ACTION_ONOFF, dmu->dmu_chars.dmu_indicators))
	    {
		got_action = TRUE;
		mcb->mcb_mod_options2 &= ~DM2U_2_TBL_RECOVERY_DEFAULT;
		if ( dmu->dmu_chars.dmu_flags & DMU_FLAG_ACTON )
		    mcb->mcb_mod_options2 |= DM2U_2_PHYS_CONSISTENT;
		else
		    mcb->mcb_mod_options2 |= DM2U_2_PHYS_INCONSISTENT;
	    }
	    break;

	case DMU_ACT_PRIORITY:
	    if (BTtest(DMU_TABLE_PRIORITY, dmu->dmu_chars.dmu_indicators))
		got_action = TRUE;
	    /* flag setting when we hit the priority char */
	    break;

	case DMU_ACT_READONLY:
	    if (BTtest(DMU_ACTION_ONOFF, dmu->dmu_chars.dmu_indicators))
	    {
		got_action = TRUE;
		if ( dmu->dmu_chars.dmu_flags & DMU_FLAG_ACTON )
		    mcb->mcb_mod_options2 |= DM2U_2_READONLY;
		else
		    mcb->mcb_mod_options2 |= DM2U_2_NOREADONLY;
	    }
	    break;

	case DMU_ACT_REORG:
	    got_action = TRUE;
	    reorg = TRUE;
	    break;

	case DMU_ACT_TABLE_RECOVERY:
	    if (BTtest(DMU_ACTION_ONOFF, dmu->dmu_chars.dmu_indicators))
	    {
		got_action = TRUE;
		mcb->mcb_mod_options2 &= ~DM2U_2_TBL_RECOVERY_DEFAULT;
		if ( dmu->dmu_chars.dmu_flags & DMU_FLAG_ACTON )
		    mcb->mcb_mod_options2 |= DM2U_2_TBL_RECOVERY_ALLOWED;
		else
		    mcb->mcb_mod_options2 |= DM2U_2_TBL_RECOVERY_DISALLOWED;
	    }
	    break;

	case DMU_ACT_TRUNC:
	    got_action = TRUE;
	    truncate++;
	    break;

	case DMU_ACT_USCOPE:
	    if (BTtest(DMU_STATEMENT_LEVEL_UNIQUE, dmu->dmu_chars.dmu_indicators))
	    {
		got_action = TRUE;
		mcb->mcb_mod_options2 |= DM2U_2_STATEMENT_LEVEL_UNIQUE;
	    }
	    break;

	case DMU_ACT_VERIFY:
	    if (BTtest(DMU_VACTION, dmu->dmu_chars.dmu_indicators))
	    {
		got_action = TRUE;
		mcb->mcb_verify = dmu->dmu_chars.dmu_vaction;
	    }
	    break;
	} /* switch */

	if (! got_action)
	{
	    SETDBERR(&dmu->error, 0, E_DM000E_BAD_CHAR_VALUE);
	    break;
	}

	/* Disassemble the characteristics.
	** FIXME probably better to just carry it through, but one step
	** at a time!
	*/
	indicator = -1;
	while ((indicator = BTnext(indicator, dmu->dmu_chars.dmu_indicators, DMU_CHARIND_LAST)) != -1)
	{
	    switch (indicator)
	    {
	    case DMU_ACTION_ONOFF:
	    case DMU_STRUCTURE:
		/* Already picked it up, just skip on */
		continue;

	    case DMU_IFILL:
		mcb->mcb_i_fill = dmu->dmu_chars.dmu_nonleaff;
		if (mcb->mcb_i_fill > 100)
		    mcb->mcb_i_fill = 100;
		continue;

	    case DMU_LEAFFILL:
		mcb->mcb_l_fill = dmu->dmu_chars.dmu_leaff;
		if (mcb->mcb_l_fill > 100)
		    mcb->mcb_l_fill = 100;
		continue;

	    case DMU_DATAFILL:
		mcb->mcb_d_fill = dmu->dmu_chars.dmu_fillfac;
		if (mcb->mcb_d_fill > 100)
		    mcb->mcb_d_fill = 100;
		continue;

	    case DMU_PAGE_SIZE:
		used_default_page_size = FALSE;
		mcb->mcb_page_size = dmu->dmu_chars.dmu_page_size;
		if (mcb->mcb_page_size != 2048   && mcb->mcb_page_size != 4096  &&
		    mcb->mcb_page_size != 8192   && mcb->mcb_page_size != 16384 &&
		    mcb->mcb_page_size != 32768  && mcb->mcb_page_size != 65536)
		{
		    SETDBERR(&dmu->error, indicator, E_DM000E_BAD_CHAR_VALUE);
		    break;
		}
		else if (!dm0p_has_buffers(mcb->mcb_page_size))
		{
		    SETDBERR(&dmu->error, 0, E_DM0157_NO_BMCACHE_BUFFERS);
		    break;
		}		    
		else
		{
		    continue;
		}

	    case DMU_MINPAGES:
		mcb->mcb_min_pages = dmu->dmu_chars.dmu_minpgs;
		continue;

	    case DMU_MAXPAGES:
		mcb->mcb_max_pages = dmu->dmu_chars.dmu_maxpgs;
		continue;

	    case DMU_UNIQUE:
		mcb->mcb_unique = TRUE;
		continue;

	    case DMU_DCOMPRESSION:
		/* Translate DMU_xxx to TCB compression types */
		if (dmu->dmu_chars.dmu_dcompress == DMU_COMP_ON)
		    mcb->mcb_compressed = TCB_C_DEFAULT;
		else if (dmu->dmu_chars.dmu_dcompress == DMU_COMP_HI)
		    mcb->mcb_compressed = TCB_C_HICOMPRESS;
		continue;

            case DMU_KCOMPRESSION:
                mcb->mcb_index_compressed =
			(dmu->dmu_chars.dmu_kcompress != DMU_COMP_OFF);
                continue;

	    case DMU_TEMP_TABLE:
		mcb->mcb_temporary = TRUE;
		continue;

	    case DMU_RECOVERY:
		recovery = (dmu->dmu_chars.dmu_flags & DMU_FLAG_RECOVERY) != 0;
		if (recovery)
		{
		    /* recovery isn't currently supported */
		    SETDBERR(&dmu->error, indicator, E_DM000D_BAD_CHAR_ID);
		    break;
		}
		continue;

	    case DMU_DUPLICATES:
		duplicates = 0;
		if (dmu->dmu_chars.dmu_flags & DMU_FLAG_DUPS)
		    duplicates = 1;
		continue;

	    case DMU_ALLOCATION:
		mcb->mcb_allocation = dmu->dmu_chars.dmu_alloc;
		continue;

	    case DMU_EXTEND:
		mcb->mcb_extend = dmu->dmu_chars.dmu_extend;
		continue;

	    case DMU_VACTION:
		/* Already got it, just skip on */
		continue;

	    case DMU_VOPTION:
		verify_options = dmu->dmu_chars.dmu_voption;
		continue;

	    case DMU_STATEMENT_LEVEL_UNIQUE:
		if (dmu->dmu_chars.dmu_flags & DMU_FLAG_UNIQUE_STMT)
		    mcb->mcb_relstat2 |= TCB_STATEMENT_LEVEL_UNIQUE;
		continue;

	    case DMU_PERSISTS_OVER_MODIFIES:
		if (dmu->dmu_chars.dmu_flags & DMU_FLAG_PERSISTENCE)
		    mcb->mcb_relstat2 |= TCB_PERSISTS_OVER_MODIFIES;
		continue;

	    case DMU_SYSTEM_GENERATED:
		mcb->mcb_relstat2 |= TCB_SYSTEM_GENERATED;
		continue;

	    case DMU_SUPPORTS_CONSTRAINT:
		mcb->mcb_relstat2 |= TCB_SUPPORTS_CONSTRAINT;
		continue;

	    case DMU_NOT_UNIQUE:
		mcb->mcb_relstat2 |= TCB_NOT_UNIQUE;
		continue;

	    case DMU_NOT_DROPPABLE:
		mcb->mcb_relstat2 |= TCB_NOT_DROPPABLE;
		continue;

	    case DMU_ROW_SEC_AUDIT:
		mcb->mcb_relstat2 |= TCB_ROW_AUDIT;
		continue;

	    case DMU_TABLE_PRIORITY:
		mcb->mcb_tbl_pri = dmu->dmu_chars.dmu_cache_priority;
		if (mcb->mcb_tbl_pri < 0 || mcb->mcb_tbl_pri > DB_MAX_TABLEPRI)
		{
		    SETDBERR(&dmu->error, indicator, E_DM000E_BAD_CHAR_VALUE);
		    break;
		}
		/*
		** DMU_TABLE_PRIORITY    is set if priority came from WITH clause.
		** DMU_TO_TABLE_PRIORITY is set if priority came from MODIFY TO clause.
		*/
		if (dmu->dmu_action != DMU_ACT_PRIORITY)
		    mcb->mcb_mod_options2 |= DM2U_2_TABLE_PRIORITY;
		else
		    mcb->mcb_mod_options2 |= DM2U_2_TO_TABLE_PRIORITY;
		continue;

	    case DMU_BLOBEXTEND:
		blob_add_extend = dmu->dmu_chars.dmu_blobextend;
		continue;

	    case DMU_CLUSTERED:
		mcb->mcb_clustered = (dmu->dmu_chars.dmu_flags & DMU_FLAG_CLUSTERED) != 0;
		continue;

	    case DMU_CONCURRENT_UPDATES:
		/* Translate from PSF flag to DMU internal flag */
		if (dmu->dmu_chars.dmu_flags & DMU_FLAG_CONCUR_U)
		    mcb->mcb_flagsmask |= DMU_ONLINE_START;
		continue;

	    default:
		/* Ignore anything else, might be for CREATE, who knows */
		continue;
	    }
	    break;
	}

	/*
	** If no page size specified, set page_size to zero
	** In this case the current page size will be used
	*/
	if (used_default_page_size)
	    mcb->mcb_page_size = 0;

	/* Save a local copy for dmpe_modify, since dm2u_modify can alter mcb */
	page_size = mcb->mcb_page_size;

	if (mcb->mcb_structure == TCB_HEAP)
	{
	    if (mcb->mcb_d_fill == 0)
		mcb->mcb_d_fill = DM_F_HEAP;
	}
	else if (mcb->mcb_structure == TCB_ISAM)
	{
	    if (mcb->mcb_i_fill == 0)
		mcb->mcb_i_fill = DM_FI_ISAM;
	    if (mcb->mcb_d_fill == 0)
	    {
		if (mcb->mcb_compressed != TCB_C_NONE)
		    mcb->mcb_d_fill = DM_F_CISAM;
		else
		    mcb->mcb_d_fill = DM_F_ISAM;
	    }
	}
	else if (mcb->mcb_structure == TCB_HASH)
	{
	    if (mcb->mcb_d_fill == 0)
	    {
		if (mcb->mcb_compressed != TCB_C_NONE)
		    mcb->mcb_d_fill = DM_F_CHASH;
		else
		    mcb->mcb_d_fill = DM_F_HASH;
	    }
	    if (mcb->mcb_min_pages == 0)
	    {
		if (mcb->mcb_compressed != TCB_C_NONE)
		    mcb->mcb_min_pages = 1;
		else
		    mcb->mcb_min_pages = 10;

		/* If user specified max pages, don't set minpages higher */
		if (mcb->mcb_min_pages > mcb->mcb_max_pages && mcb->mcb_max_pages != 0)
		    mcb->mcb_min_pages = mcb->mcb_max_pages;
	    }
	    if (mcb->mcb_max_pages == 0)
		mcb->mcb_max_pages = 8388607;
	}
	else if (mcb->mcb_structure == TCB_BTREE || mcb->mcb_merge)
	{
            if (DMZ_AM_MACRO(16) && !mcb->mcb_temporary)
            {
                /* DM616 -- forces index compression to be used: */
                mcb->mcb_index_compressed = TRUE;
            }

	    if (mcb->mcb_i_fill == 0)
		mcb->mcb_i_fill = DM_FI_BTREE;
	    if (mcb->mcb_l_fill == 0)
		mcb->mcb_l_fill = DM_FL_BTREE;
	    if (mcb->mcb_d_fill == 0)
	    {
		if (mcb->mcb_compressed != TCB_C_NONE)
		    mcb->mcb_d_fill = DM_F_CBTREE;
		else
		    mcb->mcb_d_fill = DM_F_BTREE;
	    }
	}
	else if (truncate)
	{
	    if (mcb->mcb_d_fill == 0)
		mcb->mcb_d_fill = DM_F_HEAP;
	}

	if (mcb->mcb_structure == TCB_HASH && mcb->mcb_min_pages > mcb->mcb_max_pages)
	{
	    SETDBERR(&dmu->error, 0, E_DM000D_BAD_CHAR_ID);
	    break;
	}

	mcb->mcb_kcount = dmu->dmu_key_array.ptr_in_count;
	mcb->mcb_key = (DMU_KEY_ENTRY**) dmu->dmu_key_array.ptr_address;
	if (mcb->mcb_kcount && (mcb->mcb_key == (DMU_KEY_ENTRY**)NULL ||
              dmu->dmu_key_array.ptr_size != sizeof(DMU_KEY_ENTRY)))
	{
	    SETDBERR(&dmu->error, 0, E_DM002A_BAD_PARAMETER);
	    break;
	}

	if (truncate)
	{
	    mcb->mcb_kcount = 0;
	    mcb->mcb_modoptions |= DM2U_TRUNCATE;
	}
	if (duplicates == 1)
	    mcb->mcb_modoptions |= DM2U_DUPLICATES;
	else if (duplicates == 0)
	    mcb->mcb_modoptions |= DM2U_NODUPLICATES;
	/* else duplicates == -1, set neither flag */
	if (reorg)
	    mcb->mcb_modoptions |= DM2U_REORG;

	/* CLUSTERED implies and requires Unique */
	if ( mcb->mcb_clustered && mcb->mcb_structure == TCB_BTREE )
	    mcb->mcb_unique = TRUE;
	else
	    mcb->mcb_clustered = FALSE;


	if (mcb->mcb_verify)
	{
	    if (verify_options == 0)
	    {
		/*  Apply defaults. */

		switch (mcb->mcb_verify)
		{
		case DMU_V_VERIFY:
		    verify_options = DMU_T_LINK | DMU_T_RECORD | DMU_T_ATTRIBUTE;
		    break;

		case DMU_V_REPAIR:
		case DMU_V_DEBUG:
		    verify_options = DMU_T_BITMAP;
		    break;

		case DMU_V_PATCH:
		case DMU_V_FPATCH:
		    break;
		}
	    }
	    /* Shift modifiers into place */
	    mcb->mcb_verify |= (verify_options << DM1U_MODSHIFT);
	}
	is_table_debug = ((mcb->mcb_verify & DM1U_OPMASK) == DM1U_DEBUG);

	/* Check the location names for duplicates, too many. */

	mcb->mcb_location = (DB_LOC_NAME*)NULL;
	mcb->mcb_l_count = 0;
	if (dmu->dmu_location.data_address && 
	    (dmu->dmu_location.data_in_size >= sizeof(DB_LOC_NAME)) &&
	    mcb->mcb_temporary == FALSE)
	{
	    mcb->mcb_location = (DB_LOC_NAME *) dmu->dmu_location.data_address;
	    mcb->mcb_l_count = dmu->dmu_location.data_in_size/sizeof(DB_LOC_NAME);
	    if (mcb->mcb_l_count > DM_LOC_MAX)
	    {
		SETDBERR(&dmu->error, 0, E_DM0071_LOCATIONS_TOO_MANY);
		break;
	    }
	    bad_loc = FALSE;
	    for (i = 0; i < mcb->mcb_l_count; i++)
	    {
		for (j = 0; j < i; j++)
		{
		    /* 
                    ** Compare this location name against other 
                    ** already given, they cannot be the same.
                    */

		    if (MEcmp(mcb->mcb_location[j].db_loc_name,
                              mcb->mcb_location[i].db_loc_name,
			      sizeof(DB_LOC_NAME)) == 0 )
		    {
			SETDBERR(&dmu->error, i, E_DM001E_DUP_LOCATION_NAME);
			bad_loc = TRUE;
			break;
		    }	    	    
		}
		if (bad_loc == TRUE)
		    break;		    
	    }

	    if (bad_loc == TRUE)
		break;
	}
	else
	{
	    /* There must a location list if you are reorganizing
            ** to a different number of locations.
            */
	    if (reorg)
	    {
		if (dmu->dmu_location.data_address &&
					    dmu->dmu_location.data_in_size)
		    SETDBERR(&dmu->error, 0, E_DM001F_LOCATION_LIST_ERROR);
		else
		    SETDBERR(&dmu->error, 0, E_DM0072_NO_LOCATION);
		break;	    
	    }
	}

	mcb->mcb_partitions = (DMU_PHYPART_CHAR*)NULL;
	mcb->mcb_nparts = 0;
	if ( dmu->dmu_ppchar_array.data_address && 
	     dmu->dmu_ppchar_array.data_in_size >= sizeof(DMU_PHYPART_CHAR) )
	{
	    mcb->mcb_partitions = (DMU_PHYPART_CHAR*)dmu->dmu_ppchar_array.data_address;
	    mcb->mcb_nparts = dmu->dmu_ppchar_array.data_in_size
			/ sizeof(DMU_PHYPART_CHAR);
	}
    
	if ((xcb->xcb_x_type & XCB_RONLY) && !is_table_debug)
	{
	    SETDBERR(&dmu->error, 0, E_DM006A_TRAN_ACCESS_CONFLICT);
	    break;
	}

	/*
	** If this is the first write operation for this transaction,
	** then we need to write the begin transaction record.
	*/
	if ((xcb->xcb_flags & XCB_DELAYBT) != 0 && mcb->mcb_temporary == FALSE
	  && !is_table_debug)
	{
	    status = dmxe_writebt(xcb, TRUE, &dmu->error);
	    if (status != E_DB_OK)
	    {
		xcb->xcb_state |= XCB_TRANABORT;
		break;
	    }
	}

        /* Calls the physical layer to process the rest of the modify */

	status = dm2u_modify(mcb, &dmu->error);

	if (status == E_DB_OK && has_extensions)
	{
	    if ((mcb->mcb_mod_options2 & DM2U_2_ADD_EXTEND) && blob_add_extend == 0)
		status = E_DB_OK;
	    else
	    {
		/* FIX ME make modify etabs optional !! */
		/* Add flag to modify top make modify etabs optional */
		/* Add sysmod dbname tablename blob-column-name */
#ifdef xDEBUG
		TRdisplay("Modify etabs for %~t %~t\n",
		    sizeof(DB_TAB_NAME), table_name.db_tab_name,
		    sizeof(DB_OWN_NAME), table_owner.db_own_name);
#endif
		status = dmpe_modify(dmu, odcb->odcb_dcb_ptr, xcb,
			    &dmu->dmu_tbl_id, mcb->mcb_db_lockmode, mcb->mcb_temporary,
			    truncate, (i4)0, blob_add_extend, &dmu->error);
	    }
	}
	  
	    
	/*	Audit successful MODIFY/PATCH of TABLE. */

	if ( status == E_DB_OK && dmf_svcb->svcb_status & SVCB_C2SECURE )
	{
	    i4 msgid;
	    i4 access = SXF_A_SUCCESS;

	    if ((mcb->mcb_verify & DM1U_OPMASK) == DM1U_PATCH ||
		(mcb->mcb_verify & DM1U_OPMASK) == DM1U_FPATCH)
	    {
		access |= SXF_A_ALTER;
		msgid = I_SX271A_TABLE_PATCH;
	    }
	    else 
	    {
		access |= SXF_A_MODIFY;
		msgid = I_SX270F_TABLE_MODIFY;
	    }
	    /*
	    **	Audit success
	    */
	    status = dma_write_audit(
			SXF_E_TABLE,
			access,
			table_name.db_tab_name,	/* Table/view name */
			sizeof(table_name.db_tab_name),	/* Table/view name */
			&table_owner,	/* Table/view owner */
			msgid, 
			FALSE, /* Not force */
			&dmu->error, NULL);
	}

	if (status == E_DB_OK)
	{
	    /* If modify to reorg or merge then return no tuple count info. */
	    if (reorg || (mcb->mcb_merge) || (mcb->mcb_verify != 0))
	    {
		dmu->dmu_tup_cnt = DM_NO_TUPINFO;
	    }
	    return (E_DB_OK);
	}
	else
	{
            if (dmu->error.err_code > E_DM_INTERNAL)
            {
                uleFormat(&dmu->error, 0, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, 
		    (char * )NULL, (i4)0, (i4 *)NULL, &local_error, 0);
		SETDBERR(&dmu->error, 0, E_DM0091_ERROR_MODIFYING_TABLE);
            }
	    switch (dmu->error.err_code)
	    {
		case E_DM004B_LOCK_QUOTA_EXCEEDED:
		case E_DM0112_RESOURCE_QUOTA_EXCEED:
		case E_DM0091_ERROR_MODIFYING_TABLE:
		case E_DM009B_ERROR_CHK_PATCH_TABLE:
		case E_DM0045_DUPLICATE_KEY:
		case E_DM0137_GATEWAY_ACCESS_ERROR:
	        case E_DM006A_TRAN_ACCESS_CONFLICT:
		    xcb->xcb_state |= XCB_STMTABORT;
		    break;

		case E_DM0042_DEADLOCK:
		case E_DM004A_INTERNAL_ERROR:
		case E_DM0100_DB_INCONSISTENT:
		    xcb->xcb_state |= XCB_TRANABORT;
		    break;
		case E_DM0065_USER_INTR:
		    xcb->xcb_state |= XCB_USER_INTR;
		    break;
		case E_DM010C_TRAN_ABORTED:
		    xcb->xcb_state |= XCB_FORCE_ABORT;
		    break;
		case E_DM007D_BTREE_BAD_KEY_LENGTH:
		    dmu->dmu_tup_cnt = dmu->dmu_tup_cnt; /* same for now */
		default:
                    break;
	    }
	}
    } while (FALSE);

    if (dmu->error.err_code > E_DM_INTERNAL)
    {
	uleFormat(&dmu->error, 0, (CL_ERR_DESC *)NULL, ULE_LOG, NULL, 
	    (char * )NULL, (i4)0, (i4 *)NULL, &local_error, 0);
	SETDBERR(&dmu->error, 0, E_DM0091_ERROR_MODIFYING_TABLE);
    }

    return (E_DB_ERROR);
}