/** Close our index ScanController. */ private void closeIndexSC() throws StandardException { /* Only consider closing index SC if we own it. */ if (ownIndexSC && indexSC != null) { indexSC.close(); indexSC = null; } }
/** * Delete a row from our index. This assumes our index ScanController is positioned before the row * by setScan if we own the SC, otherwise it is positioned on the row by the underlying index * scan. * * <p>This verifies the row exists and is unique. * * @exception StandardException Thrown on error */ private void doDelete() throws StandardException { if (ownIndexSC) { if (!indexSC.next()) { // This means that the entry for the index does not exist, this // is a serious problem with the index. Past fixed problems // like track 3703 can leave db's in the field with this problem // even though the bug in the code which caused it has long // since been fixed. Then the problem can surface months later // when the customer attempts to upgrade. By "ignoring" the // missing row here the problem is automatically "fixed" and // since the code is trying to delete the row anyway it doesn't // seem like such a bad idea. It also then gives a tool to // support to be able to fix some system catalog problems where // they can delete the base rows by dropping the system objects // like stored statements. /* dem 2013/04/10 - temporarily comment this out while we are getting snapshot isolation DDL support in place if (SanityManager.DEBUG) SanityManager.THROWASSERT( "Index row "+RowUtil.toString(ourIndexRow)+ " not found in conglomerateid " + indexCID + "Current scan = " + indexSC); */ Object[] args = new Object[2]; args[0] = ourIndexRow.getRowArray()[ourIndexRow.getRowArray().length - 1]; args[1] = new Long(indexCID); Monitor.getStream() .println( MessageService.getCompleteMessage( SQLState.LANG_IGNORE_MISSING_INDEX_ROW_DURING_DELETE, args)); // just return indicating the row has been deleted. return; } } indexSC.delete(); }
/** * 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 */); } }