You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by rh...@apache.org on 2022/08/21 18:20:01 UTC
svn commit: r1903614 [6/6] - in /db/derby/code/branches/10.15: ./ java/org.apache.derby.engine/org/apache/derby/impl/sql/compile/ java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/ java/org.apache.derby.tests/org/apache/derbyTesting/functi...
Modified: db/derby/code/branches/10.15/java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/TemporaryRowHolderImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.15/java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/TemporaryRowHolderImpl.java?rev=1903614&r1=1903613&r2=1903614&view=diff
==============================================================================
--- db/derby/code/branches/10.15/java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/TemporaryRowHolderImpl.java (original)
+++ db/derby/code/branches/10.15/java/org.apache.derby.engine/org/apache/derby/impl/sql/execute/TemporaryRowHolderImpl.java Sun Aug 21 18:20:01 2022
@@ -52,133 +52,133 @@ import java.util.Properties;
*/
class TemporaryRowHolderImpl implements TemporaryRowHolder
{
- public static final int DEFAULT_OVERFLOWTHRESHOLD = 5;
+ public static final int DEFAULT_OVERFLOWTHRESHOLD = 5;
- protected static final int STATE_UNINIT = 0;
- protected static final int STATE_INSERT = 1;
- protected static final int STATE_DRAIN = 2;
-
-
- protected ExecRow[] rowArray;
- protected int lastArraySlot;
- private int numRowsIn;
- protected int state = STATE_UNINIT;
-
- private long CID;
- private boolean conglomCreated;
- private ConglomerateController cc;
- private Properties properties;
- private ScanController scan;
- private ResultDescription resultDescription;
- /** Activation object with local state information. */
- Activation activation;
-
- private boolean isUniqueStream;
-
- /* beetle 3865 updateable cursor use index. A virtual memory heap is a heap that has in-memory
- * part to get better performance, less overhead. No position index needed. We read from and write
- * to the in-memory part as much as possible. And we can insert after we start retrieving results.
- * Could be used for other things too.
- */
- private boolean isVirtualMemHeap;
- private boolean uniqueIndexCreated;
- private boolean positionIndexCreated;
- private long uniqueIndexConglomId;
- private long positionIndexConglomId;
- private ConglomerateController uniqueIndex_cc;
- private ConglomerateController positionIndex_cc;
- private DataValueDescriptor[] uniqueIndexRow = null;
- private DataValueDescriptor[] positionIndexRow = null;
- private RowLocation destRowLocation; //row location in the temporary conglomerate
- private SQLLongint position_sqllong;
+ protected static final int STATE_UNINIT = 0;
+ protected static final int STATE_INSERT = 1;
+ protected static final int STATE_DRAIN = 2;
+
+
+ protected ExecRow[] rowArray;
+ protected int lastArraySlot;
+ private int numRowsIn;
+ protected int state = STATE_UNINIT;
+
+ private long CID;
+ private boolean conglomCreated;
+ private ConglomerateController cc;
+ private Properties properties;
+ private ScanController scan;
+ private ResultDescription resultDescription;
+ /** Activation object with local state information. */
+ Activation activation;
+
+ private boolean isUniqueStream;
+
+ /* beetle 3865 updateable cursor use index. A virtual memory heap is a heap that has in-memory
+ * part to get better performance, less overhead. No position index needed. We read from and write
+ * to the in-memory part as much as possible. And we can insert after we start retrieving results.
+ * Could be used for other things too.
+ */
+ private boolean isVirtualMemHeap;
+ private boolean uniqueIndexCreated;
+ private boolean positionIndexCreated;
+ private long uniqueIndexConglomId;
+ private long positionIndexConglomId;
+ private ConglomerateController uniqueIndex_cc;
+ private ConglomerateController positionIndex_cc;
+ private DataValueDescriptor[] uniqueIndexRow = null;
+ private DataValueDescriptor[] positionIndexRow = null;
+ private RowLocation destRowLocation; //row location in the temporary conglomerate
+ private SQLLongint position_sqllong;
- /**
- * Uses the default overflow to
- * a conglomerate threshold (5).
- *
- * @param activation the activation
- * @param properties the properties of the original table. Used
- * to help the store use optimal page size, etc.
- * @param resultDescription the result description. Relevant for the getResultDescription
- * call on the result set returned by getResultSet. May be null
- */
- public TemporaryRowHolderImpl
- (
- Activation activation,
- Properties properties,
- ResultDescription resultDescription
- )
- {
- this(activation, properties, resultDescription,
- DEFAULT_OVERFLOWTHRESHOLD, false, false);
- }
+ /**
+ * Uses the default overflow to
+ * a conglomerate threshold (5).
+ *
+ * @param activation the activation
+ * @param properties the properties of the original table. Used
+ * to help the store use optimal page size, etc.
+ * @param resultDescription the result description. Relevant for the getResultDescription
+ * call on the result set returned by getResultSet. May be null
+ */
+ public TemporaryRowHolderImpl
+ (
+ Activation activation,
+ Properties properties,
+ ResultDescription resultDescription
+ )
+ {
+ this(activation, properties, resultDescription,
+ DEFAULT_OVERFLOWTHRESHOLD, false, false);
+ }
- /**
- * Uses the default overflow to
- * a conglomerate threshold (5).
- *
- * @param activation the activation
- * @param properties the properties of the original table. Used
- * to help the store use optimal page size, etc.
- * @param resultDescription the result description. Relevant for the getResultDescription
- * call on the result set returned by getResultSet. May be null
- * @param isUniqueStream - true , if it has to be temporary row holder unique stream
- */
- public TemporaryRowHolderImpl
- (
- Activation activation,
- Properties properties,
- ResultDescription resultDescription,
- boolean isUniqueStream
- )
- {
- this(activation, properties, resultDescription, 1, isUniqueStream,
- false);
- }
-
-
- /**
- * Create a temporary row holder with the defined overflow to conglom
- *
- * @param activation the activation
- * @param properties the properties of the original table. Used
- * to help the store use optimal page size, etc.
- * @param resultDescription the result description. Relevant for the getResultDescription
- * call on the result set returned by getResultSet. May be null
- * @param overflowToConglomThreshold on an attempt to insert
- * this number of rows, the rows will be put
- * into a temporary conglomerate.
- */
- public TemporaryRowHolderImpl
- (
- Activation activation,
- Properties properties,
- ResultDescription resultDescription,
- int overflowToConglomThreshold,
- boolean isUniqueStream,
- boolean isVirtualMemHeap
- )
- {
- if (SanityManager.DEBUG)
- {
- if (overflowToConglomThreshold <= 0)
- {
- SanityManager.THROWASSERT("It is assumed that "+
- "the overflow threshold is > 0. "+
- "If you you need to change this you have to recode some of "+
- "this class.");
- }
- }
-
- this.activation = activation;
- this.properties = properties;
- this.resultDescription = resultDescription;
- this.isUniqueStream = isUniqueStream;
- this.isVirtualMemHeap = isVirtualMemHeap;
- rowArray = new ExecRow[overflowToConglomThreshold];
- lastArraySlot = -1;
- }
+ /**
+ * Uses the default overflow to
+ * a conglomerate threshold (5).
+ *
+ * @param activation the activation
+ * @param properties the properties of the original table. Used
+ * to help the store use optimal page size, etc.
+ * @param resultDescription the result description. Relevant for the getResultDescription
+ * call on the result set returned by getResultSet. May be null
+ * @param isUniqueStream - true , if it has to be temporary row holder unique stream
+ */
+ public TemporaryRowHolderImpl
+ (
+ Activation activation,
+ Properties properties,
+ ResultDescription resultDescription,
+ boolean isUniqueStream
+ )
+ {
+ this(activation, properties, resultDescription, 1, isUniqueStream,
+ false);
+ }
+
+
+ /**
+ * Create a temporary row holder with the defined overflow to conglom
+ *
+ * @param activation the activation
+ * @param properties the properties of the original table. Used
+ * to help the store use optimal page size, etc.
+ * @param resultDescription the result description. Relevant for the getResultDescription
+ * call on the result set returned by getResultSet. May be null
+ * @param overflowToConglomThreshold on an attempt to insert
+ * this number of rows, the rows will be put
+ * into a temporary conglomerate.
+ */
+ public TemporaryRowHolderImpl
+ (
+ Activation activation,
+ Properties properties,
+ ResultDescription resultDescription,
+ int overflowToConglomThreshold,
+ boolean isUniqueStream,
+ boolean isVirtualMemHeap
+ )
+ {
+ if (SanityManager.DEBUG)
+ {
+ if (overflowToConglomThreshold <= 0)
+ {
+ SanityManager.THROWASSERT("It is assumed that "+
+ "the overflow threshold is > 0. "+
+ "If you you need to change this you have to recode some of "+
+ "this class.");
+ }
+ }
+
+ this.activation = activation;
+ this.properties = properties;
+ this.resultDescription = resultDescription;
+ this.isUniqueStream = isUniqueStream;
+ this.isVirtualMemHeap = isVirtualMemHeap;
+ rowArray = new ExecRow[overflowToConglomThreshold];
+ lastArraySlot = -1;
+ }
/* Avoid materializing a stream just because it goes through a temp table.
* It is OK to have a stream in the temp table (in memory or spilled to
@@ -199,67 +199,67 @@ class TemporaryRowHolderImpl implements
*
* Beetle 4896.
*/
- private ExecRow cloneRow(ExecRow inputRow)
- {
- DataValueDescriptor[] cols = inputRow.getRowArray();
- int ncols = cols.length;
- ExecRow cloned = ((ValueRow) inputRow).cloneMe();
- for (int i = 0; i < ncols; i++)
- {
- if (cols[i] != null)
- {
- /* Rows are 1-based, cols[] is 0-based */
+ private ExecRow cloneRow(ExecRow inputRow)
+ {
+ DataValueDescriptor[] cols = inputRow.getRowArray();
+ int ncols = cols.length;
+ ExecRow cloned = ((ValueRow) inputRow).cloneMe();
+ for (int i = 0; i < ncols; i++)
+ {
+ if (cols[i] != null)
+ {
+ /* Rows are 1-based, cols[] is 0-based */
cloned.setColumn(i + 1, cols[i].cloneHolder());
- }
- }
- if (inputRow instanceof IndexValueRow)
- return new IndexValueRow(cloned);
- else
- return cloned;
- }
-
- /**
- * Insert a row
- *
- * @param inputRow the row to insert
- *
- * @exception StandardException on error
- */
- public void insert(ExecRow inputRow)
- throws StandardException
- {
-
- if (SanityManager.DEBUG)
- {
- if(!isUniqueStream && !isVirtualMemHeap)
- SanityManager.ASSERT(state != STATE_DRAIN, "you cannot insert rows after starting to drain");
- }
- if (! isVirtualMemHeap)
- state = STATE_INSERT;
-
- if(uniqueIndexCreated)
- {
- if(isRowAlreadyExist(inputRow))
- return;
- }
-
- numRowsIn++;
-
- if (lastArraySlot + 1 < rowArray.length)
- {
- rowArray[++lastArraySlot] = cloneRow(inputRow);
+ }
+ }
+ if (inputRow instanceof IndexValueRow)
+ return new IndexValueRow(cloned);
+ else
+ return cloned;
+ }
+
+ /**
+ * Insert a row
+ *
+ * @param inputRow the row to insert
+ *
+ * @exception StandardException on error
+ */
+ public void insert(ExecRow inputRow)
+ throws StandardException
+ {
+
+ if (SanityManager.DEBUG)
+ {
+ if(!isUniqueStream && !isVirtualMemHeap)
+ SanityManager.ASSERT(state != STATE_DRAIN, "you cannot insert rows after starting to drain");
+ }
+ if (! isVirtualMemHeap)
+ state = STATE_INSERT;
+
+ if(uniqueIndexCreated)
+ {
+ if(isRowAlreadyExist(inputRow))
+ return;
+ }
+
+ numRowsIn++;
+
+ if (lastArraySlot + 1 < rowArray.length)
+ {
+ rowArray[++lastArraySlot] = cloneRow(inputRow);
- //In case of unique stream we push every thing into the
- // conglomerates for time being, we keep one row in the array for
- // the template.
+ //In case of unique stream we push every thing into the
+ // conglomerates for time being, we keep one row in the array for
+ // the template.
if (!isUniqueStream) {
- return;
+ return;
}
- }
+ }
- if (!conglomCreated)
- {
- TransactionController tc = activation.getTransactionController();
+ if (!conglomCreated)
+ {
+ TransactionController tc = activation.getTransactionController();
// TODO-COLLATE, I think collation needs to get set always correctly
// but did see what to get collate id when there was no result
@@ -278,107 +278,147 @@ class TemporaryRowHolderImpl implements
int collation_ids[] = null;
/*
- TODO-COLLATE - if we could count on resultDescription I think the
- following would work.
-
- if (resultDescription != null)
- {
- // init collation id info from resultDescription for create call
- collation_ids = new int[resultDescription.getColumnCount()];
+ TODO-COLLATE - if we could count on resultDescription I think the
+ following would work.
- for (int i = 0; i < collation_ids.length; i++)
- {
- collation_ids[i] =
- resultDescription.getColumnDescriptor(
- i + 1).getType().getCollationType();
- }
- }
+ if (resultDescription != null)
+ {
+ // init collation id info from resultDescription for create call
+ collation_ids = new int[resultDescription.getColumnCount()];
+
+ for (int i = 0; i < collation_ids.length; i++)
+ {
+ collation_ids[i] =
+ resultDescription.getColumnDescriptor(
+ i + 1).getType().getCollationType();
+ }
+ }
*/
- /*
- ** Create the conglomerate with the template row.
- */
- CID =
+ /*
+ ** Create the conglomerate with the template row.
+ */
+ CID =
tc.createConglomerate(
"heap",
- inputRow.getRowArray(),
+ makeTemplateRow(inputRow.getRowArray()),
null, //column sort order - not required for heap
collation_ids,
properties,
TransactionController.IS_TEMPORARY |
TransactionController.IS_KEPT);
- conglomCreated = true;
+ conglomCreated = true;
+
+ cc = tc.openConglomerate(CID,
+ false,
+ TransactionController.OPENMODE_FORUPDATE,
+ TransactionController.MODE_TABLE,
+ TransactionController.ISOLATION_SERIALIZABLE);
+ if(isUniqueStream)
+ destRowLocation = cc.newRowLocationTemplate();
- cc = tc.openConglomerate(CID,
- false,
- TransactionController.OPENMODE_FORUPDATE,
- TransactionController.MODE_TABLE,
- TransactionController.ISOLATION_SERIALIZABLE);
- if(isUniqueStream)
- destRowLocation = cc.newRowLocationTemplate();
-
- }
-
- int status = 0;
- if(isUniqueStream)
- {
- cc.insertAndFetchLocation(inputRow.getRowArray(), destRowLocation);
- insertToPositionIndex(numRowsIn -1, destRowLocation);
- //create the unique index based on input row ROW Location
- if(!uniqueIndexCreated)
- isRowAlreadyExist(inputRow);
+ }
+
+ int status = 0;
+ if(isUniqueStream)
+ {
+ cc.insertAndFetchLocation(inputRow.getRowArray(), destRowLocation);
+ insertToPositionIndex(numRowsIn -1, destRowLocation);
+ //create the unique index based on input row ROW Location
+ if(!uniqueIndexCreated)
+ isRowAlreadyExist(inputRow);
- }else
- {
+ }else
+ {
status = cc.insert(inputRow.getRowArray());
- if (isVirtualMemHeap)
- state = STATE_INSERT;
- }
-
- if (SanityManager.DEBUG)
- {
- if (status != 0)
- {
- SanityManager.THROWASSERT("got funky status ("+status+") back from "+
- "ConglomerateConstroller.insert()");
- }
- }
- }
-
-
- /**
- * Maintain an unique index based on the input row's row location in the
- * base table, this index make sures that we don't insert duplicate rows
- * into the temporary heap.
- * @param inputRow the row we are inserting to temporary row holder
- * @exception StandardException on error
- */
-
-
- private boolean isRowAlreadyExist(ExecRow inputRow) throws StandardException
- {
- DataValueDescriptor rlColumn;
- RowLocation baseRowLocation;
- rlColumn = inputRow.getColumn(inputRow.nColumns());
-
- if(CID!=0 && rlColumn instanceof SQLRef)
- {
- baseRowLocation =
- (RowLocation) (rlColumn).getObject();
+ if (isVirtualMemHeap)
+ state = STATE_INSERT;
+ }
+
+ if (SanityManager.DEBUG)
+ {
+ if (status != 0)
+ {
+ SanityManager.THROWASSERT("got funky status ("+status+") back from "+
+ "ConglomerateConstroller.insert()");
+ }
+ }
+ }
+
+ /**
+ * Make a template row for creating the spillover conglomerate. We only do this
+ * for MERGE statments. MERGE processing can temporarily stuff literal nulls into
+ * the DataValueDescriptor slot for an autoincrement column. The null DataValueDescriptor
+ * can not be used to create the layout of the spillover conglomerate. See DERBY-7144.
+ *
+ * @param originalRow The original row
+ */
+ private DataValueDescriptor[] makeTemplateRow(DataValueDescriptor[] originalRow)
+ throws StandardException {
+
+ boolean useOriginalRow = true;
+
+ for (DataValueDescriptor dvd : originalRow)
+ {
+ if (dvd == null)
+ {
+ useOriginalRow = false;
+ break;
+ }
+ }
+
+ if (useOriginalRow) { return originalRow; }
+ else
+ {
+ int columnCount = resultDescription.getColumnCount();
+ ExecRow emptyRow = activation.getExecutionFactory().getValueRow(columnCount);
+
+ for (int idx = 1; idx <= columnCount; idx++)
+ {
+ emptyRow.setColumn
+ (
+ idx,
+ resultDescription.getColumnDescriptor(idx).getType().getNullabilityType(true).getNull()
+ );
+ }
+
+ return emptyRow.getRowArray();
+ }
+ }
+
+ /**
+ * Maintain an unique index based on the input row's row location in the
+ * base table, this index make sures that we don't insert duplicate rows
+ * into the temporary heap.
+ * @param inputRow the row we are inserting to temporary row holder
+ * @exception StandardException on error
+ */
+
+
+ private boolean isRowAlreadyExist(ExecRow inputRow) throws StandardException
+ {
+ DataValueDescriptor rlColumn;
+ RowLocation baseRowLocation;
+ rlColumn = inputRow.getColumn(inputRow.nColumns());
+
+ if(CID!=0 && rlColumn instanceof SQLRef)
+ {
+ baseRowLocation =
+ (RowLocation) (rlColumn).getObject();
- if(!uniqueIndexCreated)
- {
- TransactionController tc =
- activation.getTransactionController();
- int numKeys = 2;
- uniqueIndexRow = new DataValueDescriptor[numKeys];
- uniqueIndexRow[0] = baseRowLocation;
- uniqueIndexRow[1] = baseRowLocation;
- Properties props = makeIndexProperties(uniqueIndexRow, CID);
- uniqueIndexConglomId =
- tc.createConglomerate(
+ if(!uniqueIndexCreated)
+ {
+ TransactionController tc =
+ activation.getTransactionController();
+ int numKeys = 2;
+ uniqueIndexRow = new DataValueDescriptor[numKeys];
+ uniqueIndexRow[0] = baseRowLocation;
+ uniqueIndexRow[1] = baseRowLocation;
+ Properties props = makeIndexProperties(uniqueIndexRow, CID);
+ uniqueIndexConglomId =
+ tc.createConglomerate(
"BTREE",
uniqueIndexRow,
null,
@@ -387,63 +427,63 @@ class TemporaryRowHolderImpl implements
(TransactionController.IS_TEMPORARY |
TransactionController.IS_KEPT));
- uniqueIndex_cc = tc.openConglomerate(
- uniqueIndexConglomId,
- false,
- TransactionController.OPENMODE_FORUPDATE,
- TransactionController.MODE_TABLE,
- TransactionController.ISOLATION_SERIALIZABLE);
- uniqueIndexCreated = true;
- }
-
- uniqueIndexRow[0] = baseRowLocation;
- uniqueIndexRow[1] = baseRowLocation;
- // Insert the row into the secondary index.
- int status;
+ uniqueIndex_cc = tc.openConglomerate(
+ uniqueIndexConglomId,
+ false,
+ TransactionController.OPENMODE_FORUPDATE,
+ TransactionController.MODE_TABLE,
+ TransactionController.ISOLATION_SERIALIZABLE);
+ uniqueIndexCreated = true;
+ }
+
+ uniqueIndexRow[0] = baseRowLocation;
+ uniqueIndexRow[1] = baseRowLocation;
+ // Insert the row into the secondary index.
+ int status;
if ((status = uniqueIndex_cc.insert(uniqueIndexRow))!= 0)
- {
- if(status == ConglomerateController.ROWISDUPLICATE)
- {
- return true ; // okay; we don't insert duplicates
- }
- else
- {
- if (SanityManager.DEBUG)
- {
- if (status != 0)
- {
- SanityManager.THROWASSERT("got funky status ("+status+") back from "+
- "Unique Index insert()");
- }
- }
- }
- }
- }
-
- return false;
- }
-
-
- /**
- * Maintain an index that will allow us to read from the
- * temporary heap in the order we inserted.
- * @param position - the number of the row we are inserting into heap
- * @param rl the row to Location in the temporary heap
- * @exception StandardException on error
- */
-
- private void insertToPositionIndex(int position, RowLocation rl ) throws StandardException
- {
- if(!positionIndexCreated)
- {
- TransactionController tc = activation.getTransactionController();
- int numKeys = 2;
- position_sqllong = new SQLLongint();
- positionIndexRow = new DataValueDescriptor[numKeys];
- positionIndexRow[0] = position_sqllong;
- positionIndexRow[1] = rl;
- Properties props = makeIndexProperties(positionIndexRow, CID);
- positionIndexConglomId =
+ {
+ if(status == ConglomerateController.ROWISDUPLICATE)
+ {
+ return true ; // okay; we don't insert duplicates
+ }
+ else
+ {
+ if (SanityManager.DEBUG)
+ {
+ if (status != 0)
+ {
+ SanityManager.THROWASSERT("got funky status ("+status+") back from "+
+ "Unique Index insert()");
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Maintain an index that will allow us to read from the
+ * temporary heap in the order we inserted.
+ * @param position - the number of the row we are inserting into heap
+ * @param rl the row to Location in the temporary heap
+ * @exception StandardException on error
+ */
+
+ private void insertToPositionIndex(int position, RowLocation rl ) throws StandardException
+ {
+ if(!positionIndexCreated)
+ {
+ TransactionController tc = activation.getTransactionController();
+ int numKeys = 2;
+ position_sqllong = new SQLLongint();
+ positionIndexRow = new DataValueDescriptor[numKeys];
+ positionIndexRow[0] = position_sqllong;
+ positionIndexRow[1] = rl;
+ Properties props = makeIndexProperties(positionIndexRow, CID);
+ positionIndexConglomId =
tc.createConglomerate(
"BTREE",
positionIndexRow,
@@ -453,7 +493,7 @@ class TemporaryRowHolderImpl implements
(TransactionController.IS_TEMPORARY |
TransactionController.IS_KEPT));
- positionIndex_cc =
+ positionIndex_cc =
tc.openConglomerate(
positionIndexConglomId,
false,
@@ -461,63 +501,63 @@ class TemporaryRowHolderImpl implements
TransactionController.MODE_TABLE,
TransactionController.ISOLATION_SERIALIZABLE);
- positionIndexCreated = true;
- }
+ positionIndexCreated = true;
+ }
- position_sqllong.setValue(position);
- positionIndexRow[0] = position_sqllong;
- positionIndexRow[1] = rl;
- //insert the row location to position index
+ position_sqllong.setValue(position);
+ positionIndexRow[0] = position_sqllong;
+ positionIndexRow[1] = rl;
+ //insert the row location to position index
positionIndex_cc.insert(positionIndexRow);
- }
+ }
+
+ /**
+ * Get a result set for scanning what has been inserted
+ * so far.
+ *
+ * @return a result set to use
+ */
+ public CursorResultSet getResultSet()
+ {
+ state = STATE_DRAIN;
+ TransactionController tc = activation.getTransactionController();
+ if(isUniqueStream)
+ {
+ return new TemporaryRowHolderResultSet(tc, rowArray,
+ resultDescription, isVirtualMemHeap,
+ true, positionIndexConglomId, this);
+ }
+ else
+ {
+ return new TemporaryRowHolderResultSet(tc, rowArray, resultDescription, isVirtualMemHeap, this);
+
+ }
+ }
- /**
- * Get a result set for scanning what has been inserted
- * so far.
- *
- * @return a result set to use
- */
- public CursorResultSet getResultSet()
- {
- state = STATE_DRAIN;
- TransactionController tc = activation.getTransactionController();
- if(isUniqueStream)
- {
- return new TemporaryRowHolderResultSet(tc, rowArray,
- resultDescription, isVirtualMemHeap,
- true, positionIndexConglomId, this);
- }
- else
- {
- return new TemporaryRowHolderResultSet(tc, rowArray, resultDescription, isVirtualMemHeap, this);
-
- }
- }
-
- /**
- * Purge the row holder of all its rows.
- * Resets the row holder so that it can
- * accept new inserts. A cheap way to
- * recycle a row holder.
- *
- * @exception StandardException on error
- */
- public void truncate() throws StandardException
- {
- close();
+ /**
+ * Purge the row holder of all its rows.
+ * Resets the row holder so that it can
+ * accept new inserts. A cheap way to
+ * recycle a row holder.
+ *
+ * @exception StandardException on error
+ */
+ public void truncate() throws StandardException
+ {
+ close();
if (SanityManager.DEBUG) {
SanityManager.ASSERT(lastArraySlot == -1);
SanityManager.ASSERT(state == STATE_UNINIT);
SanityManager.ASSERT(!conglomCreated);
SanityManager.ASSERT(CID == 0);
}
- for (int i = 0; i < rowArray.length; i++)
- {
- rowArray[i] = null;
- }
+ for (int i = 0; i < rowArray.length; i++)
+ {
+ rowArray[i] = null;
+ }
- numRowsIn = 0;
- }
+ numRowsIn = 0;
+ }
/**
* Accessor to get the id of the temporary conglomerate. Temporary
@@ -525,99 +565,99 @@ class TemporaryRowHolderImpl implements
* temporary conglomerate has been created.
* @return Conglomerate ID of temporary conglomerate
*/
- public long getTemporaryConglomId()
- {
+ public long getTemporaryConglomId()
+ {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(CID == 0 && !conglomCreated ||
- CID < 0 && conglomCreated);
+ CID < 0 && conglomCreated);
+ }
+ return CID;
+ }
+
+ public long getPositionIndexConglomId()
+ {
+ return positionIndexConglomId;
+ }
+
+
+
+ private Properties makeIndexProperties(DataValueDescriptor[]
+ indexRowArray, long conglomId ) throws StandardException {
+ int nCols = indexRowArray.length;
+ Properties props = new Properties();
+ props.put("allowDuplicates", "false");
+ // all columns form the key, (currently) required
+ props.put("nKeyFields", String.valueOf(nCols));
+ props.put("nUniqueColumns", String.valueOf(nCols-1));
+ props.put("rowLocationColumn", String.valueOf(nCols-1));
+ props.put("baseConglomerateId", String.valueOf(conglomId));
+ return props;
+ }
+
+ public void setRowHolderTypeToUniqueStream()
+ {
+ isUniqueStream = true;
+ }
+
+ /**
+ * Clean up
+ *
+ * @exception StandardException on error
+ */
+ public void close() throws StandardException
+ {
+ if (scan != null)
+ {
+ scan.close();
+ scan = null;
}
- return CID;
- }
- public long getPositionIndexConglomId()
- {
- return positionIndexConglomId;
- }
-
-
-
- private Properties makeIndexProperties(DataValueDescriptor[]
- indexRowArray, long conglomId ) throws StandardException {
- int nCols = indexRowArray.length;
- Properties props = new Properties();
- props.put("allowDuplicates", "false");
- // all columns form the key, (currently) required
- props.put("nKeyFields", String.valueOf(nCols));
- props.put("nUniqueColumns", String.valueOf(nCols-1));
- props.put("rowLocationColumn", String.valueOf(nCols-1));
- props.put("baseConglomerateId", String.valueOf(conglomId));
- return props;
- }
-
- public void setRowHolderTypeToUniqueStream()
- {
- isUniqueStream = true;
- }
-
- /**
- * Clean up
- *
- * @exception StandardException on error
- */
- public void close() throws StandardException
- {
- if (scan != null)
- {
- scan.close();
- scan = null;
- }
-
- if (cc != null)
- {
- cc.close();
- cc = null;
- }
-
- if (uniqueIndex_cc != null)
- {
- uniqueIndex_cc.close();
- uniqueIndex_cc = null;
- }
-
- if (positionIndex_cc != null)
- {
- positionIndex_cc.close();
- positionIndex_cc = null;
- }
-
- TransactionController tc = activation.getTransactionController();
-
- if (uniqueIndexCreated)
- {
- tc.dropConglomerate(uniqueIndexConglomId);
- uniqueIndexCreated = false;
- }
-
- if (positionIndexCreated)
- {
- tc.dropConglomerate(positionIndexConglomId);
- positionIndexCreated = false;
- }
-
- if (conglomCreated)
- {
- tc.dropConglomerate(CID);
- conglomCreated = false;
+ if (cc != null)
+ {
+ cc.close();
+ cc = null;
+ }
+
+ if (uniqueIndex_cc != null)
+ {
+ uniqueIndex_cc.close();
+ uniqueIndex_cc = null;
+ }
+
+ if (positionIndex_cc != null)
+ {
+ positionIndex_cc.close();
+ positionIndex_cc = null;
+ }
+
+ TransactionController tc = activation.getTransactionController();
+
+ if (uniqueIndexCreated)
+ {
+ tc.dropConglomerate(uniqueIndexConglomId);
+ uniqueIndexCreated = false;
+ }
+
+ if (positionIndexCreated)
+ {
+ tc.dropConglomerate(positionIndexConglomId);
+ positionIndexCreated = false;
+ }
+
+ if (conglomCreated)
+ {
+ tc.dropConglomerate(CID);
+ conglomCreated = false;
CID = 0;
- }
+ }
else
{
if (SanityManager.DEBUG) {
SanityManager.ASSERT(CID == 0, "CID(" + CID + ")==0");
}
}
- state = STATE_UNINIT;
- lastArraySlot = -1;
- }
+ state = STATE_UNINIT;
+ lastArraySlot = -1;
+ }
}
Modified: db/derby/code/branches/10.15/java/org.apache.derby.tests/org/apache/derbyTesting/functionTests/tests/lang/MergeStatementTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.15/java/org.apache.derby.tests/org/apache/derbyTesting/functionTests/tests/lang/MergeStatementTest.java?rev=1903614&r1=1903613&r2=1903614&view=diff
==============================================================================
--- db/derby/code/branches/10.15/java/org.apache.derby.tests/org/apache/derbyTesting/functionTests/tests/lang/MergeStatementTest.java (original)
+++ db/derby/code/branches/10.15/java/org.apache.derby.tests/org/apache/derbyTesting/functionTests/tests/lang/MergeStatementTest.java Sun Aug 21 18:20:01 2022
@@ -9561,6 +9561,128 @@ public class MergeStatementTest extends
}
+ public void test_063_Derby7144() throws SQLException {
+ Connection conn = openUserConnection( TEST_DBO );
+
+ goodStatement(conn, "CREATE TABLE targetData_7144 (ID BIGINT GENERATED ALWAYS AS IDENTITY)");
+ goodStatement(conn, "CREATE TABLE sourceData_7144(CATEGORY INTEGER)");
+ goodStatement(conn, "INSERT INTO sourceData_7144 VALUES (10), (20)");
+
+ // the following statement used to kill the connection and raise the following error:
+ //
+ // ERROR XJ001: Java exception: 'ASSERT FAILED row template is null for column[0].: org.apache.derby.shared.common.sanity.AsserFailure'.
+ goodStatement
+ (
+ conn,
+ "MERGE INTO targetData_7144 target USING sourceData_7144 source ON 1 < 2\n" +
+ "WHEN NOT MATCHED THEN INSERT (id) VALUES (DEFAULT)\n"
+ );
+ assertResults
+ (
+ conn,
+ "SELECT * FROM targetData_7144",
+ new String[][]
+ {
+ { "1" },
+ { "2" },
+ },
+ false
+ );
+
+ // next test
+ goodStatement(conn, "CREATE TABLE targetData3_7144 (ID BIGINT GENERATED BY DEFAULT AS IDENTITY)");
+ goodStatement
+ (
+ conn,
+ "MERGE INTO targetData3_7144 target USING sourceData_7144 source ON 1 < 2\n" +
+ "WHEN NOT MATCHED THEN INSERT (id) VALUES (100)\n"
+ );
+ assertResults
+ (
+ conn,
+ "SELECT * FROM targetData3_7144",
+ new String[][]
+ {
+ { "100" },
+ { "100" },
+ },
+ false
+ );
+
+ // next test
+ goodStatement
+ (
+ conn,
+ "CREATE TABLE targetData_2_7144 (\n" +
+ " ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY NOT NULL,\n" +
+ " CATEGORY INTEGER NOT NULL,\n" +
+ " VALUE DOUBLE NOT NULL,\n" +
+ " ATTIME TIMESTAMP NOT NULL,\n" +
+ " AGGDATE DATE NOT NULL,\n" +
+ " AGGCOUNT INTEGER NOT NULL,\n" +
+ "\n" +
+ " UNIQUE (AGGDATE, CATEGORY)\n" +
+ " )\n"
+ );
+ goodStatement
+ (
+ conn,
+ "CREATE TABLE sourceData2_7144\n" +
+ "(\n" +
+ " CATEGORY INTEGER,\n" +
+ " VALUE DOUBLE,\n" +
+ " ATTIME TIMESTAMP,\n" +
+ " AGGDATE DATE,\n" +
+ " AGGCOUNT INTEGER\n" +
+ ")\n"
+ );
+ goodStatement
+ (
+ conn,
+ "INSERT INTO sourceData2_7144 VALUES\n" +
+ "(1, 45.67, TIMESTAMP('2022-07-29 01:24:21.336'), DATE('2022-07-29'), 3),\n" +
+ "(4, 37.15, TIMESTAMP('2022-07-29 01:24:21.336'), DATE('2022-07-29'), 3),\n" +
+ "(2, 123.34, TIMESTAMP('2022-07-31 01:38:24.66'), DATE('2022-07-31'), 3),\n" +
+ "(1, 78.9, TIMESTAMP('2022-07-31 01:38:24.66'), DATE('2022-07-31'), 2),\n" +
+ "(3, 1.2, TIMESTAMP('2022-07-31 01:38:24.66'), DATE('2022-07-31'), 1),\n" +
+ "(4, 5.6, TIMESTAMP('2022-07-31 01:38:24.66'), DATE('2022-07-31'), 1)\n"
+ );
+
+ // this statement used to kill the connection and raise the following error:
+ //
+ // ERROR XJ001: Java exception: 'ASSERT FAILED row template is null for column[0].: org.apache.derby.shared.common.sanity.AssetFailure'.
+ goodStatement
+ (
+ conn,
+ "MERGE INTO targetData_2_7144 target\n" +
+ " USING sourceData2_7144 source\n" +
+ " ON target.CATEGORY = source.CATEGORY\n" +
+ " AND target.AGGDATE = source.AGGDATE\n" +
+ " WHEN MATCHED THEN\n" +
+ " UPDATE SET VALUE = target.VALUE + source.VALUE,\n" +
+ " ATTIME = CASE WHEN source.ATTIME < target.ATTIME THEN target.ATTIME ELSE source.ATTIME END,\n" +
+ " AGGCOUNT = target.AGGCOUNT + source.AGGCOUNT\n" +
+ " WHEN NOT MATCHED THEN\n" +
+ " INSERT (CATEGORY, VALUE, ATTIME, AGGDATE, AGGCOUNT)\n" +
+ " VALUES (source.CATEGORY, source.VALUE, source.ATTIME, source.AGGDATE, source.AGGCOUNT)\n"
+ );
+ assertResults
+ (
+ conn,
+ "SELECT * FROM targetData_2_7144",
+ new String[][]
+ {
+ { "1", "1", "45.67", "2022-07-29 01:24:21.336", "2022-07-29", "3" },
+ { "2", "4", "37.15", "2022-07-29 01:24:21.336", "2022-07-29", "3" },
+ { "3", "2", "123.34", "2022-07-31 01:38:24.66", "2022-07-31", "3" },
+ { "4", "1", "78.9", "2022-07-31 01:38:24.66", "2022-07-31", "2" },
+ { "5", "3", "1.2", "2022-07-31 01:38:24.66", "2022-07-31", "1" },
+ { "6", "4", "5.6", "2022-07-31 01:38:24.66", "2022-07-31", "1" }
+ },
+ false
+ );
+ }
+
///////////////////////////////////////////////////////////////////////////////////
//
// ROUTINES