use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class DataDictionaryImpl method addRemovePermissionsDescriptor.
/**
* Add or remove a permission to/from the permission database.
*
* @param add if true then the permission is added, if false the permission is removed
* @param perm
* @param grantee
* @param tc
*
* @return True means revoke has removed a privilege from system
* table and hence the caller of this method should send invalidation
* actions to PermssionDescriptor's dependents.
*/
public boolean addRemovePermissionsDescriptor(boolean add, PermissionsDescriptor perm, String grantee, TransactionController tc) throws StandardException {
int catalogNumber = perm.getCatalogNumber();
// It is possible for grant statements to look like following
// grant execute on function f_abs to mamata2, mamata3;
// grant all privileges on t11 to mamata2, mamata3;
// This means that dd.addRemovePermissionsDescriptor will be called
// twice for TablePermsDescriptor and twice for RoutinePermsDescriptor,
// once for each grantee.
// First it's called for mamta2. When a row is inserted for mamta2
// into the correct system table for the permission descriptor, the
// permission descriptor's uuid gets populated with the uuid of
// the row that just got inserted into the system table for mamta2
// Now, when dd.addRemovePermissionsDescriptor gets called again for
// mamta3, the permission descriptor's uuid will still be set to
// the uuid that was used for mamta2. If we do not reset the
// uuid to null, we will think that there is a duplicate row getting
// inserted for the same uuid. In order to get around this, we should
// reset the UUID of passed PermissionDescriptor everytime this method
// is called. This way, there will be no leftover values from previous
// call of this method.
perm.setUUID(null);
perm.setGrantee(grantee);
TabInfoImpl ti = getNonCoreTI(catalogNumber);
PermissionsCatalogRowFactory rf = (PermissionsCatalogRowFactory) ti.getCatalogRowFactory();
int primaryIndexNumber = rf.getPrimaryKeyIndexNumber();
ConglomerateController heapCC = tc.openConglomerate(ti.getHeapConglomerate(), // do not keep open across commits
false, 0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ);
RowLocation rl = null;
try {
rl = heapCC.newRowLocationTemplate();
} finally {
heapCC.close();
heapCC = null;
}
ExecIndexRow key = rf.buildIndexKeyRow(primaryIndexNumber, perm);
ExecRow existingRow = ti.getRow(tc, key, primaryIndexNumber);
if (existingRow == null) {
if (!add) {
// permission and hence uuid can't be non-null
return false;
} else {
// We didn't find an entry in system catalog and this is grant so
// so that means we have to enter a new row in system catalog for
// this grant.
ExecRow row = ti.getCatalogRowFactory().makeRow(perm, (TupleDescriptor) null);
int insertRetCode = ti.insertRow(row, tc);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(insertRetCode == TabInfoImpl.ROWNOTDUPLICATE, "Race condition in inserting table privilege.");
}
}
} else {
// add/remove these permissions to/from the existing permissions
boolean[] colsChanged = new boolean[existingRow.nColumns()];
boolean[] indicesToUpdate = new boolean[rf.getNumIndexes()];
int changedColCount = 0;
if (add) {
changedColCount = rf.orPermissions(existingRow, perm, colsChanged);
} else {
changedColCount = rf.removePermissions(existingRow, perm, colsChanged);
}
if (changedColCount == 0) {
// just return
return false;
}
if (!add) {
// set the uuid of the passed permission descriptor to
// corresponding rows's uuid in permissions system table. The
// permission descriptor's uuid is required to have the
// dependency manager send the revoke privilege action to
// all the dependent objects on that permission descriptor.
rf.setUUIDOfThePassedDescriptor(existingRow, perm);
}
if (changedColCount < 0) {
// No permissions left in the current row
ti.deleteRow(tc, key, primaryIndexNumber);
} else if (changedColCount > 0) {
int[] colsToUpdate = new int[changedColCount];
changedColCount = 0;
for (int i = 0; i < colsChanged.length; i++) {
if (colsChanged[i])
colsToUpdate[changedColCount++] = i + 1;
}
if (SanityManager.DEBUG) {
SanityManager.ASSERT(changedColCount == colsToUpdate.length, "return value of " + rf.getClass().getName() + ".orPermissions does not match the number of booleans it set in colsChanged.");
}
ti.updateRow(key, existingRow, primaryIndexNumber, indicesToUpdate, colsToUpdate, tc);
}
}
// Remove cached permissions data. The cache may hold permissions data for this key even if
// the row in the permissions table is new. In that case the cache may have an entry indicating no
// permissions
removePermEntryInCache(perm);
// any invalidation actions to anyone and hence return false
if (add) {
return false;
} else {
return true;
}
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class DataDictionaryImpl method updateCurrentSequenceValue.
/**
* Set the current value of an ANSI/ISO sequence. This method does not perform
* any sanity checking but assumes that the caller knows what they are doing. If the
* old value on disk is not what we expect it to be, then we are in a race with another
* session. They won and we don't update the value on disk. However, if the old value
* is null, that is a signal to us that we should update the value on disk anyway.
*
* @param tc Transaction Controller to use.
* @param rowLocation Row in SYSSEQUENCES to update.
* @param wait True if we should wait for locks
* @param oldValue What we expect to find in the CURRENTVALUE column.
* @param newValue What to stuff into the CURRENTVALUE column.
*
* @return Returns true if the value was successfully updated, false if we lost a race with another session.
*
* @exception StandardException thrown on failure.
*/
public boolean updateCurrentSequenceValue(TransactionController tc, RowLocation rowLocation, boolean wait, Long oldValue, Long newValue) throws StandardException {
int columnNum = SYSSEQUENCESRowFactory.SYSSEQUENCES_CURRENT_VALUE;
FormatableBitSet columnToUpdate = new FormatableBitSet(SYSSEQUENCESRowFactory.SYSSEQUENCES_COLUMN_COUNT);
TabInfoImpl ti = getNonCoreTI(SYSSEQUENCES_CATALOG_NUM);
ConglomerateController heapCC = null;
SYSSEQUENCESRowFactory rf = (SYSSEQUENCESRowFactory) ti.getCatalogRowFactory();
ExecRow row = rf.makeEmptyRow();
// FormatableBitSet is 0 based.
// current value.
columnToUpdate.set(columnNum - 1);
try {
/* if wait is true then we need to do a wait while trying to
open/fetch from the conglomerate. note we use wait both to
open as well as fetch from the conglomerate.
*/
heapCC = tc.openConglomerate(ti.getHeapConglomerate(), false, (TransactionController.OPENMODE_FORUPDATE | ((wait) ? 0 : TransactionController.OPENMODE_LOCK_NOWAIT)), TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ);
boolean baseRowExists = heapCC.fetch(rowLocation, row.getRowArray(), columnToUpdate, wait);
//
if (!baseRowExists) {
return false;
}
NumberDataValue oldValueOnDisk = (NumberDataValue) row.getColumn(columnNum);
SQLLongint expectedOldValue;
if (oldValue == null) {
expectedOldValue = new SQLLongint();
} else {
expectedOldValue = new SQLLongint(oldValue.longValue());
}
// only update value if what's on disk is what we expected
if ((oldValue == null) || (expectedOldValue.compare(oldValueOnDisk) == 0)) {
SQLLongint newValueOnDisk;
if (newValue == null) {
newValueOnDisk = new SQLLongint();
} else {
newValueOnDisk = new SQLLongint(newValue.longValue());
}
row.setColumn(columnNum, newValueOnDisk);
heapCC.replace(rowLocation, row.getRowArray(), columnToUpdate);
return true;
} else {
return false;
}
} finally {
if (heapCC != null) {
heapCC.close();
}
}
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class DataDictionaryImpl method getConstraints.
/**
* Return an List which of the relevant column matching
* the indexed criteria. If nothing matches, returns an
* empty List (never returns null).
*
* @param uuid The id of the constraint
* @param indexId The index id in SYS.SYSCONSTRAINTS
* @param columnNum The column to retrieve
*
* @return a list of UUIDs in an List.
*
* @exception StandardException Thrown on error
*/
public List<UUID> getConstraints(UUID uuid, int indexId, int columnNum) throws StandardException {
ExecIndexRow indexRow1;
ExecRow outRow;
RowLocation baseRowLocation;
ConglomerateController heapCC = null;
ScanController scanController = null;
TransactionController tc;
TabInfoImpl ti = getNonCoreTI(SYSCONSTRAINTS_CATALOG_NUM);
SYSCONSTRAINTSRowFactory rf = (SYSCONSTRAINTSRowFactory) ti.getCatalogRowFactory();
TableDescriptor td = null;
List<UUID> slist = new ArrayList<UUID>();
if (SanityManager.DEBUG) {
SanityManager.ASSERT(indexId == SYSCONSTRAINTSRowFactory.SYSCONSTRAINTS_INDEX1_ID || indexId == SYSCONSTRAINTSRowFactory.SYSCONSTRAINTS_INDEX3_ID, "bad index id, must be one of the indexes on a uuid");
SanityManager.ASSERT(columnNum > 0 && columnNum <= SYSCONSTRAINTSRowFactory.SYSCONSTRAINTS_COLUMN_COUNT, "invalid column number for column to be retrieved");
}
try {
/* Use tableIDOrderable in both start and stop positions for scan */
DataValueDescriptor orderable = getIDValueAsCHAR(uuid);
/* Set up the start/stop position for the scan */
ExecIndexRow keyRow = (ExecIndexRow) exFactory.getIndexableRow(1);
keyRow.setColumn(1, orderable);
// Get the current transaction controller
tc = getTransactionCompile();
outRow = rf.makeEmptyRow();
heapCC = tc.openConglomerate(ti.getHeapConglomerate(), false, 0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ);
// create an index row template
indexRow1 = getIndexRowFromHeapRow(ti.getIndexRowGenerator(indexId), heapCC.newRowLocationTemplate(), outRow);
// just interested in one column
DataValueDescriptor[] rowTemplate = new DataValueDescriptor[SYSCONSTRAINTSRowFactory.SYSCONSTRAINTS_COLUMN_COUNT];
FormatableBitSet columnToGetSet = new FormatableBitSet(SYSCONSTRAINTSRowFactory.SYSCONSTRAINTS_COLUMN_COUNT);
columnToGetSet.set(columnNum - 1);
rowTemplate[columnNum - 1] = new SQLChar();
// Scan the index and go to the data pages for qualifying rows
scanController = tc.openScan(// conglomerate to open
ti.getIndexConglomerate(indexId), // don't hold open across commit
false, // for read
0, TransactionController.MODE_RECORD, // RESOLVE: should be level 2
TransactionController.ISOLATION_REPEATABLE_READ, // all fields as objects
(FormatableBitSet) null, // start position - exact key match.
keyRow.getRowArray(), // startSearchOperation
ScanController.GE, // scanQualifier (none)
null, // stop position - exact key match.
keyRow.getRowArray(), // stopSearchOperation
ScanController.GT);
while (scanController.fetchNext(indexRow1.getRowArray())) {
baseRowLocation = (RowLocation) indexRow1.getColumn(indexRow1.nColumns());
// get the row and grab the uuid
boolean base_row_exists = heapCC.fetch(baseRowLocation, rowTemplate, columnToGetSet);
if (SanityManager.DEBUG) {
// it can not be possible for heap row to disappear while
// holding scan cursor on index at ISOLATION_REPEATABLE_READ.
SanityManager.ASSERT(base_row_exists, "base row not found");
}
slist.add(uuidFactory.recreateUUID((String) ((DataValueDescriptor) rowTemplate[columnNum - 1]).getObject()));
}
} finally {
if (heapCC != null) {
heapCC.close();
}
if (scanController != null) {
scanController.close();
}
}
return slist;
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class DataDictionaryImpl method visitRoleGrants.
/**
* Scan the {roleid, grantee, grantor} index on SYSROLES,
* locate rows containing authId in column columnNo.
*
* The action argument can be either <code>EXISTS</code> or
* <code>DROP</code> (to check for existence, or to drop that row).
*
* If the scan proves too slow, we should add more indexes. only.
*
* @param ti <code>TabInfoImpl</code> for SYSROLES.
* @param rf row factory for SYSROLES
* @param columnNo the column number to match <code>authId</code> against
* @param tc transaction controller
* @param action drop matching rows (<code>DROP</code>), or return
* <code>true</code> if there is a matching row
* (<code>EXISTS</code>)
*
* @return action=EXISTS: return {@code true} if there is a matching row
* else return {@code false}.
* @exception StandardException
*/
private boolean visitRoleGrants(TabInfoImpl ti, SYSROLESRowFactory rf, int columnNo, String authId, TransactionController tc, int action) throws StandardException {
ConglomerateController heapCC = tc.openConglomerate(ti.getHeapConglomerate(), false, 0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ);
DataValueDescriptor authIdOrderable = new SQLVarchar(authId);
ScanQualifier[][] scanQualifier = exFactory.getScanQualifier(1);
scanQualifier[0][0].setQualifier(columnNo - 1, /* to zero-based */
authIdOrderable, Orderable.ORDER_OP_EQUALS, false, false, false);
ScanController sc = tc.openScan(ti.getIndexConglomerate(rf.SYSROLES_INDEX_ID_EE_OR_IDX), // don't hold open across commit
false, // for update
0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ, // all fields as objects
(FormatableBitSet) null, // start position -
(DataValueDescriptor[]) null, // startSearchOperation - none
0, //
scanQualifier, // stop position -through last row
(DataValueDescriptor[]) null, // stopSearchOperation - none
0);
try {
ExecRow outRow = rf.makeEmptyRow();
ExecIndexRow indexRow = getIndexRowFromHeapRow(ti.getIndexRowGenerator(rf.SYSROLES_INDEX_ID_EE_OR_IDX), heapCC.newRowLocationTemplate(), outRow);
while (sc.fetchNext(indexRow.getRowArray())) {
if (action == DataDictionaryImpl.EXISTS) {
return true;
} else if (action == DataDictionaryImpl.DROP) {
ti.deleteRow(tc, indexRow, rf.SYSROLES_INDEX_ID_EE_OR_IDX);
}
}
} finally {
if (sc != null) {
sc.close();
}
if (heapCC != null) {
heapCC.close();
}
}
return false;
}
use of org.apache.derby.iapi.store.access.ConglomerateController in project derby by apache.
the class BTreePostCommit method openIndex.
/**
* Open index for either table level or row level update.
* <p>
* @param lock_level For table level use TransactionManager.MODE_TABLE,
* for row level use TransactionManager.MODE_RECORD
* @param lock_mode For table level use LockingPolicy.MODE_CONTAINER,
* for row level use LockingPolicy.MODE_RECORD
*
* @exception StandardException Standard exception policy.
*/
private final OpenBTree openIndex(TransactionManager internal_xact, int lock_level, int lock_mode) throws StandardException {
OpenBTree open_btree = new OpenBTree();
ConglomerateController base_cc = btree.lockTable(internal_xact, (ContainerHandle.MODE_FORUPDATE | ContainerHandle.MODE_LOCK_NOWAIT), lock_level, TransactionController.ISOLATION_REPEATABLE_READ);
open_btree.init((TransactionManager) null, internal_xact, // open the container
(ContainerHandle) null, internal_xact.getRawStoreXact(), false, (ContainerHandle.MODE_FORUPDATE | ContainerHandle.MODE_LOCK_NOWAIT), lock_level, btree.getBtreeLockingPolicy(internal_xact.getRawStoreXact(), lock_level, lock_mode, TransactionController.ISOLATION_REPEATABLE_READ, base_cc, open_btree), btree, // No logical undo necessry.
(LogicalUndo) null, (DynamicCompiledOpenConglomInfo) null);
return (open_btree);
}
Aggregations