/** * Insert the given row into the given conglomerate and check for duplicate key error. * * @param row The row to insert * @exception StandardException Thrown on duplicate key error */ private void insertAndCheckDups(ExecIndexRow row) throws StandardException { openIndexCC(); int insertStatus = indexCC.insert(row.getRowArray()); if (insertStatus == ConglomerateController.ROWISDUPLICATE) { /* ** We have a duplicate key error. */ String indexOrConstraintName = indexName; // now get table name, and constraint name if needed LanguageConnectionContext lcc = activation.getLanguageConnectionContext(); DataDictionary dd = lcc.getDataDictionary(); // get the descriptors ConglomerateDescriptor cd = dd.getConglomerateDescriptor(indexCID); UUID tableID = cd.getTableID(); TableDescriptor td = dd.getTableDescriptor(tableID); String tableName = td.getName(); if (indexOrConstraintName == null) // no index name passed in { ConstraintDescriptor conDesc = dd.getConstraintDescriptor(td, cd.getUUID()); indexOrConstraintName = conDesc.getConstraintName(); } throw StandardException.newException( SQLState.LANG_DUPLICATE_KEY_CONSTRAINT, indexOrConstraintName, tableName); } if (SanityManager.DEBUG) { if (insertStatus != 0) { SanityManager.THROWASSERT("Unknown insert status " + insertStatus); } } }
/** Close our index Conglomerate Controller */ private void closeIndexCC() throws StandardException { if (indexCC != null) indexCC.close(); indexCC = null; }
/** * Position our index scan to 'ourIndexRow'. * * <p>This creates the scan the first time it is called. * * @exception StandardException Thrown on error */ private void setScan() throws StandardException { /* * -sf- Derby makes an assumption about system tables that isn't true * for Splice land, which results in WriteConflicts occurring * when you try to drop tables * * With indices, Derby only ever creates start and stop keys for the scan. * However, if the entire index is to be scanned, one or more column in the start/stop * key may be null. With db this was apparently treated acceptably, but in Splice * this results in garbage start and stop row keys, which in turn results in deleting * every row in the index instead of deleting just the rows of interest. * * Thus, the following hack. When the row is not entirely filled, we convert * the start/stop key into a single ANDed equals qualifier[], and use that instead */ DataValueDescriptor[] ourRowDvds = ourIndexRow.getRowArray(); int numNonNull = ourRowDvds.length; for (int i = 0; i < ourRowDvds.length; i++) { if (ourRowDvds[i].isNull()) { numNonNull--; } } Qualifier[][] qualifiers = null; if (numNonNull < ourRowDvds.length) { qualifiers = new Qualifier[1][]; qualifiers[0] = new Qualifier[numNonNull]; for (int dvdPos = 0, qualPos = 0; dvdPos < ourRowDvds.length; dvdPos++) { if (ourRowDvds[dvdPos].isNull()) continue; ScanQualifier qualifier = new GenericScanQualifier(); qualifier.setQualifier( dvdPos, ourRowDvds[dvdPos], DataValueDescriptor.ORDER_OP_EQUALS, false, false, false); qualifiers[0][qualPos] = qualifier; } } /* Get the SC from the activation if re-using */ if (!ownIndexSC) { indexSC = activation.getIndexScanController(); } else if (indexSC == null) { RowLocation templateBaseRowLocation = baseCC.newRowLocationTemplate(); /* DataDictionary doesn't have compiled info */ if (indexSCOCI == null) { indexSC = tc.openScan( indexCID, false, /* hold */ TransactionController.OPENMODE_FORUPDATE, /* forUpdate */ lockMode, isolationLevel, (FormatableBitSet) null, /* all fields */ ourIndexRow.getRowArray(), /* startKeyValue */ ScanController.GE, /* startSearchOp */ qualifiers, /* qualifier */ ourIndexRow.getRowArray(), /* stopKeyValue */ ScanController.GT /* stopSearchOp */); } else { indexSC = tc.openCompiledScan( false, /* hold */ TransactionController.OPENMODE_FORUPDATE, /* forUpdate */ lockMode, isolationLevel, (FormatableBitSet) null, /* all fields */ ourIndexRow.getRowArray(), /* startKeyValue */ ScanController.GE, /* startSearchOp */ qualifiers, /* qualifier */ ourIndexRow.getRowArray(), /* stopKeyValue */ ScanController.GT, /* stopSearchOp */ indexSCOCI, indexDCOCI); } } else { indexSC.reopenScan( ourIndexRow.getRowArray(), /* startKeyValue */ ScanController.GE, /* startSearchOperator */ qualifiers, /* qualifier */ ourIndexRow.getRowArray(), /* stopKeyValue */ ScanController.GT /* stopSearchOperator */); } }