/*{ ** 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); }
/*{ ** 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); }
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); }