/** * INTERNAL: Return the value of the field from the row or a value holder on the query to obtain * the object. Check for batch + aggregation reading. */ public Object valueFromRow( AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery query, AbstractSession executionSession) throws DatabaseException { Ref ref = (Ref) row.get(getField()); if (ref == null) { return null; } Struct struct; try { ((DatabaseAccessor) executionSession.getAccessor()).incrementCallCount(executionSession); java.sql.Connection connection = ((DatabaseAccessor) executionSession.getAccessor()).getConnection(); struct = (Struct) executionSession.getPlatform().getRefValue(ref, executionSession, connection); } catch (java.sql.SQLException exception) { throw DatabaseException.sqlException(exception, executionSession, false); } AbstractRecord targetRow = ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor()) .buildRowFromStructure(struct); ((DatabaseAccessor) executionSession.getAccessor()).decrementCallCount(); return getReferenceDescriptor().getObjectBuilder().buildObject(query, targetRow, joinManager); }
/** INTERNAL: Build a ADT structure from the row data. */ public Struct buildStructureFromRow( AbstractRecord row, AbstractSession session, java.sql.Connection connection) throws DatabaseException { Struct structure; boolean reconnected = false; try { if (connection == null) { ((DatabaseAccessor) session.getAccessor()).incrementCallCount(session); reconnected = true; connection = ((DatabaseAccessor) session.getAccessor()).getConnection(); } Object[] fields = new Object[getOrderedFields().size()]; for (int index = 0; index < getOrderedFields().size(); index++) { DatabaseField field = (DatabaseField) getOrderedFields().elementAt(index); fields[index] = row.get(field); } structure = session.getPlatform().createStruct(getStructureName(), fields, session, connection); } catch (java.sql.SQLException exception) { throw DatabaseException.sqlException(exception, session, false); } finally { if (reconnected) { ((DatabaseAccessor) session.getAccessor()).decrementCallCount(); } } return structure; }
/** * INTERNAL: Build and return the appropriate field value for the specified set of nested rows. * The database better be expecting an ARRAY. It looks like we can ignore inheritance here.... */ public Object buildFieldValueFromNestedRows( Vector nestedRows, String structureName, AbstractSession session) throws DatabaseException { Object[] fields = new Object[nestedRows.size()]; java.sql.Connection connection = ((DatabaseAccessor) session.getAccessor()).getConnection(); boolean reconnected = false; try { if (connection == null) { ((DatabaseAccessor) session.getAccessor()).incrementCallCount(session); reconnected = true; connection = ((DatabaseAccessor) session.getAccessor()).getConnection(); } int i = 0; for (Enumeration stream = nestedRows.elements(); stream.hasMoreElements(); ) { AbstractRecord nestedRow = (AbstractRecord) stream.nextElement(); fields[i++] = this.buildStructureFromRow(nestedRow, session, connection); } return session.getPlatform().createArray(structureName, fields, session, connection); } catch (java.sql.SQLException exception) { throw DatabaseException.sqlException(exception, session, false); } finally { if (reconnected) { ((DatabaseAccessor) session.getAccessor()).decrementCallCount(); } } }
/** * INTERNAL: Build the appropriate field value for the specified set of direct values. The * database better be expecting an ARRAY. */ public Object buildFieldValueFromDirectValues( Vector directValues, String elementDataTypeName, AbstractSession session) throws DatabaseException { Object[] fields = Helper.arrayFromVector(directValues); try { ((DatabaseAccessor) session.getAccessor()).incrementCallCount(session); java.sql.Connection connection = ((DatabaseAccessor) session.getAccessor()).getConnection(); return session.getPlatform().createArray(elementDataTypeName, fields, session, connection); } catch (java.sql.SQLException ex) { throw DatabaseException.sqlException(ex, session, false); } finally { ((DatabaseAccessor) session.getAccessor()).decrementCallCount(); } }
/** * INTERNAL: Build and return the field value from the specified nested database row. The database * better be expecting a Struct. */ public Object buildFieldValueFromNestedRow(AbstractRecord nestedRow, AbstractSession session) throws DatabaseException { java.sql.Connection connection = ((DatabaseAccessor) session.getAccessor()).getConnection(); return this.buildStructureFromRow(nestedRow, session, connection); }
/** * Return the next sequence value. First check the global pool, if empty then allocate new * sequences locally. */ public Object getNextValue(Sequence sequence, AbstractSession writeSession) { String seqName = sequence.getName(); if (sequence.getPreallocationSize() > 1) { Queue sequencesForName = getPreallocationHandler().getPreallocated(seqName); // First grab the first sequence value without locking, a lock is only required if empty. Object sequenceValue = sequencesForName.poll(); if (sequenceValue != null) { return sequenceValue; } // KeepLocked indicates whether the sequence lock should be kept for the whole duration of // this method. // Of course the lock should be released in any case when the method returns or throws an // exception. // This is only used if a sequence transaction was begun by the unit of work, // and will be committed before the unit of work commit. boolean keepLocked = false; if (!getOwnerSession().getDatasourceLogin().shouldUseExternalTransactionController() && !writeSession.isInTransaction()) { // To prevent several threads from simultaneously allocating a separate bunch of // sequencing numbers each. With keepLocked==true the first thread locks out others // until it copies the obtained sequence numbers to the global storage. // Note that this optimization possible only in non-jts case when there is no transaction. acquireLock(seqName); try { sequenceValue = sequencesForName.poll(); if (sequenceValue != null) { return sequenceValue; } writeSession.beginTransaction(); // write accessor is set in begin keepLocked = true; } finally { if (!keepLocked) { releaseLock(seqName); } } } Accessor accessor; Vector localSequencesForName; if (!keepLocked) { writeSession.beginTransaction(); // write accessor is set in begin } try { accessor = writeSession.getAccessor(); SequencingCallbackImpl seqCallbackImpl = getCallbackImpl(writeSession, accessor); Map localSequences = seqCallbackImpl.getPreallocatedSequenceValues(); localSequencesForName = (Vector) localSequences.get(seqName); if ((localSequencesForName == null) || localSequencesForName.isEmpty()) { localSequencesForName = sequence.getGeneratedVector(null, writeSession); localSequences.put(seqName, localSequencesForName); logDebugLocalPreallocation(writeSession, seqName, localSequencesForName, accessor); } } catch (RuntimeException ex) { if (keepLocked) { releaseLock(seqName); } try { // make sure to rollback the transaction we've begun writeSession.rollbackTransaction(); } catch (Exception rollbackException) { // ignore rollback exception } // don't eat the original exception throw ex; } try { try { // commitTransaction may copy preallocated sequence numbers // from localSequences to preallocationHandler: that happens // if it isn't a nested transaction, and sequencingCallback.afterCommit // method has been called. // In this case: // 1. localSequences corresponding to the accessor // has been removed from accessorToPreallocated; // 2. All its members are empty (therefore localSequenceForName is empty). writeSession.commitTransaction(); } catch (DatabaseException ex) { try { // make sure to rollback the transaction we've begun writeSession.rollbackTransaction(); } catch (Exception rollbackException) { // ignore rollback exception } // don't eat the original exception throw ex; } if (!localSequencesForName.isEmpty()) { // localSeqencesForName is not empty, that means // sequencingCallback has not been called. sequenceValue = localSequencesForName.remove(0); return sequenceValue; } else { // localSeqencesForName is empty, that means // sequencingCallback has been called. sequenceValue = sequencesForName.poll(); if (sequenceValue != null) { return sequenceValue; } return getNextValue(sequence, writeSession); } } finally { if (keepLocked) { releaseLock(seqName); } } } else { writeSession.beginTransaction(); try { // preallocation size is 1 - just return the first (and only) element of the allocated // vector. Object sequenceValue = sequence.getGeneratedVector(null, writeSession).firstElement(); writeSession.commitTransaction(); return sequenceValue; } catch (RuntimeException ex) { try { // make sure to rollback the transaction we've begun writeSession.rollbackTransaction(); } catch (Exception rollbackException) { // ignore rollback exception } // don't eat the original exception throw ex; } } }