585 |
585 |
** parameter and bound to another buffer.
|
586 |
586 |
** OM 20221012 The TriggerTracker are bound to DMO, not to the buffer they are contained into.
|
587 |
587 |
** OM 20221019 Do not assign new PK for replaced records in copyAllRows().
|
|
588 |
* DDF 20221027 Optimization when copying temp-tables based on multiplexID
|
|
589 |
* by using delete-update instead of insert based on select. (refs. #6714)
|
588 |
590 |
*/
|
589 |
591 |
|
590 |
592 |
/*
|
... | ... | |
2274 |
2276 |
}
|
2275 |
2277 |
dstBuf.outputParameters.add(src);
|
2276 |
2278 |
|
2277 |
|
OutputTableCopier copier = new OutputTableCopier(dstBuf, src);
|
|
2279 |
Object referent = ProcedureManager.thisProcedure().get();
|
|
2280 |
boolean isPersistent = ProcedureManager._isPersistent(referent);
|
|
2281 |
boolean isExternalBlock = dstBuf.getTxHelper().isExternalBlock();
|
|
2282 |
BufferImpl dstBufImpl = (BufferImpl) dstDMO;
|
|
2283 |
boolean isAfterTable = dstBufImpl.isAfterBuffer();
|
|
2284 |
|
|
2285 |
boolean shouldInsert = (isPersistent || !isExternalBlock) || isAfterTable;
|
|
2286 |
OutputTableCopier copier = new OutputTableCopier(dstBuf, src, shouldInsert);
|
2278 |
2287 |
ProcedureManager.executeOnReturn(copier::finished, copier.weight());
|
2279 |
2288 |
}
|
2280 |
2289 |
}
|
... | ... | |
6375 |
6384 |
*/
|
6376 |
6385 |
protected void performOutputCopy(TableParameter outputParameter)
|
6377 |
6386 |
{
|
|
6387 |
performOutputCopy(outputParameter, true);
|
|
6388 |
}
|
|
6389 |
|
|
6390 |
/**
|
|
6391 |
* Copy output data for the linked table parameter, if any.
|
|
6392 |
*
|
|
6393 |
* @param outputParameter
|
|
6394 |
* The table parameter where to copy the data.
|
|
6395 |
* @param shouldInsert
|
|
6396 |
* If the output copy should be done using an insert based
|
|
6397 |
* on select or a delete-update operation.
|
|
6398 |
*/
|
|
6399 |
protected void performOutputCopy(TableParameter outputParameter, boolean shouldInsert)
|
|
6400 |
{
|
6378 |
6401 |
if (!outputParameters.contains(outputParameter))
|
6379 |
6402 |
{
|
6380 |
6403 |
// was already processed (by i.e. scope close)
|
... | ... | |
6390 |
6413 |
|
6391 |
6414 |
if (outputParameter.getTable() != null)
|
6392 |
6415 |
{
|
6393 |
|
boolean res = copyAllRows(srcRec,
|
6394 |
|
tempDMO,
|
6395 |
|
outputParameter.getTable(),
|
6396 |
|
outputParameter.isAppend(),
|
6397 |
|
CopyTableMode.OUTPUT_TABLE_PARAM_MODE);
|
|
6416 |
boolean res = false;
|
|
6417 |
if (shouldInsert)
|
|
6418 |
{
|
|
6419 |
res = copyAllRows(srcRec,
|
|
6420 |
tempDMO,
|
|
6421 |
outputParameter.getTable(),
|
|
6422 |
outputParameter.isAppend(),
|
|
6423 |
CopyTableMode.OUTPUT_TABLE_PARAM_MODE);
|
|
6424 |
}
|
|
6425 |
else
|
|
6426 |
{
|
|
6427 |
TemporaryBuffer targetBuf = (TemporaryBuffer)
|
|
6428 |
((BufferReference) outputParameter.getTable())
|
|
6429 |
.buffer();
|
|
6430 |
int targetMultiplex = targetBuf.getMultiplexID();
|
|
6431 |
try
|
|
6432 |
{
|
|
6433 |
if (!outputParameter.isAppend())
|
|
6434 |
{
|
|
6435 |
removeRecords(null, null, null, true, targetMultiplex);
|
|
6436 |
}
|
|
6437 |
removeRecords(null, null, null, false, targetMultiplex);
|
|
6438 |
res = true;
|
|
6439 |
}
|
|
6440 |
catch (PersistenceException e)
|
|
6441 |
{
|
|
6442 |
LOG.log(Level.WARNING, "Failed to perform delete-update copy", e);
|
|
6443 |
}
|
|
6444 |
}
|
|
6445 |
|
6398 |
6446 |
if (!res)
|
|
6447 |
{
|
6399 |
6448 |
deferCopyError();
|
|
6449 |
}
|
6400 |
6450 |
}
|
6401 |
6451 |
else
|
6402 |
6452 |
{
|
... | ... | |
7282 |
7332 |
private void removeRecords(DataModelObject[] extDMOs, String where, Object[] args, boolean forceDelete)
|
7283 |
7333 |
throws PersistenceException
|
7284 |
7334 |
{
|
|
7335 |
removeRecords(extDMOs, where, args, forceDelete, multiplexID);
|
|
7336 |
}
|
|
7337 |
|
|
7338 |
/**
|
|
7339 |
* Remove or change the multiplex ID for all record rows from the backing table which meet the
|
|
7340 |
* specified criteria. Because temp table instances are multiplexed across nested buffer scopes
|
|
7341 |
* and across multiple buffers which use the same backing DMO type, the backing table cannot be
|
|
7342 |
* dropped until after the last buffer scope referencing the backing table in the current
|
|
7343 |
* context has been closed. This method is invoked for all buffer scope closing events.
|
|
7344 |
* This is also the worker method for the {@link #deleteAll()} and
|
|
7345 |
* {@link RecordBuffer#delete(DataModelObject[], String, Object[])} methods.
|
|
7346 |
*
|
|
7347 |
* @param extDMOs
|
|
7348 |
* The DMOs for the external (additional) buffers that are accessed in inner
|
|
7349 |
* subselect, or {@code null} in case of a simple {@code where} predicate.
|
|
7350 |
* @param where
|
|
7351 |
* An HQL where clause snippet which defines the restriction
|
|
7352 |
* criteria to apply to the delete. All references to properties
|
|
7353 |
* in a DMO must be unqualified. <code>null</code> to delete all
|
|
7354 |
* records whose multiplex IDs match that of this buffer.
|
|
7355 |
* @param args
|
|
7356 |
* Query substitution parameters required by the where clause.
|
|
7357 |
* <code>null</code> if there are no substitutions or no where clause.
|
|
7358 |
* @param forceDelete
|
|
7359 |
* Force the records to be deleted from the table, not just
|
|
7360 |
* marking them with a negative multiplex ID.
|
|
7361 |
* @param targetMultiplexID
|
|
7362 |
* Used to delete records from a buffer and then update the multiplex
|
|
7363 |
* of the source buffer to the targetMultiplexID instead of inserting all the records.
|
|
7364 |
* The default value is the multiplexID.
|
|
7365 |
*
|
|
7366 |
* @throws PersistenceException
|
|
7367 |
* if an error occurs performing the bulk delete operation.
|
|
7368 |
*/
|
|
7369 |
private void removeRecords(DataModelObject[] extDMOs,
|
|
7370 |
String where,
|
|
7371 |
Object[] args,
|
|
7372 |
boolean forceDelete,
|
|
7373 |
int targetMultiplexID)
|
|
7374 |
throws PersistenceException
|
|
7375 |
{
|
7285 |
7376 |
Record currentRec = getCurrentRecord();
|
7286 |
7377 |
|
7287 |
7378 |
// after executing this method, the buffer is empty regardless the where predicate matches
|
... | ... | |
7298 |
7389 |
|
7299 |
7390 |
if (extDMOs == null || extDMOs.length == 0)
|
7300 |
7391 |
{
|
7301 |
|
ffCache.invalidate(getDmoInfo().getId(), multiplexID);
|
|
7392 |
ffCache.invalidate(getDmoInfo().getId(), targetMultiplexID);
|
7302 |
7393 |
}
|
7303 |
7394 |
else
|
7304 |
7395 |
{
|
7305 |
7396 |
int len = extDMOs.length;
|
7306 |
7397 |
List<Long> tableIds = new ArrayList<>(len + 1);
|
7307 |
|
tableIds.add(FastFindCache.combine(getDmoInfo().getId(), multiplexID));
|
|
7398 |
tableIds.add(FastFindCache.combine(getDmoInfo().getId(), targetMultiplexID));
|
7308 |
7399 |
for (int i = 0; i < len; i++)
|
7309 |
7400 |
{
|
7310 |
7401 |
RecordBuffer buffer = ((BufferReference) extDMOs[i]).buffer();
|
... | ... | |
7321 |
7412 |
return;
|
7322 |
7413 |
}
|
7323 |
7414 |
|
7324 |
|
// if we are not within a transaction, or this temp-table is not undoable
|
7325 |
|
forceDelete = forceDelete || !isUndoable() || !bufferManager.isTransaction();
|
|
7415 |
if (targetMultiplexID == multiplexID)
|
|
7416 |
{
|
|
7417 |
// if we are not within a transaction, or this temp-table is not undoable
|
|
7418 |
forceDelete = forceDelete || !isUndoable() || !bufferManager.isTransaction();
|
|
7419 |
}
|
7326 |
7420 |
|
7327 |
7421 |
boolean hasWhere = (where != null);
|
7328 |
7422 |
Persistence persistence = getPersistence();
|
... | ... | |
7352 |
7446 |
buf.append(aliasDot);
|
7353 |
7447 |
buf.append(MULTIPLEX_FIELD_NAME);
|
7354 |
7448 |
buf.append(" = ");
|
7355 |
|
buf.append(multiplexID);
|
|
7449 |
|
|
7450 |
if (forceDelete && targetMultiplexID != multiplexID)
|
|
7451 |
{
|
|
7452 |
buf.append(targetMultiplexID);
|
|
7453 |
}
|
|
7454 |
else
|
|
7455 |
{
|
|
7456 |
buf.append(multiplexID);
|
|
7457 |
}
|
|
7458 |
|
7356 |
7459 |
String mpidWhere = buf.toString();
|
7357 |
7460 |
|
7358 |
7461 |
HQLExpression query = new HQLExpression();
|
... | ... | |
7364 |
7467 |
else
|
7365 |
7468 |
{
|
7366 |
7469 |
query.append("update ");
|
7367 |
|
Map<Class<?>, Map<Integer, Integer>> map = local.inUseMPIDs;
|
7368 |
|
Map<Integer, Integer> inUse = map.get(getDMOInterface());
|
7369 |
|
|
7370 |
|
delMPID = local.getNextMPID(inUse);
|
|
7470 |
if (targetMultiplexID == multiplexID)
|
|
7471 |
{
|
|
7472 |
Map<Class<?>, Map<Integer, Integer>> map = local.inUseMPIDs;
|
|
7473 |
Map<Integer, Integer> inUse = map.get(getDMOInterface());
|
|
7474 |
|
|
7475 |
delMPID = local.getNextMPID(inUse);
|
|
7476 |
}
|
|
7477 |
else
|
|
7478 |
{
|
|
7479 |
delMPID = targetMultiplexID;
|
|
7480 |
}
|
7371 |
7481 |
}
|
7372 |
7482 |
|
7373 |
7483 |
String table = getTable();
|
... | ... | |
7410 |
7520 |
query.append(mpidWhere);
|
7411 |
7521 |
if (hasOO)
|
7412 |
7522 |
{
|
7413 |
|
list.append(dmoAlias).append(".").append(MULTIPLEX_FIELD_NAME).append("=").append(multiplexID);
|
|
7523 |
list.append(dmoAlias).append(".").append(MULTIPLEX_FIELD_NAME).append("=").append(targetMultiplexID);
|
7414 |
7524 |
}
|
7415 |
7525 |
if (hasWhere)
|
7416 |
7526 |
{
|
... | ... | |
7529 |
7639 |
// execute a simple query to determine if there is any record in this virtual table
|
7530 |
7640 |
String checkStmt =
|
7531 |
7641 |
"select tt." + Session.PK + " from " + table + " tt " +
|
7532 |
|
"where tt." + MULTIPLEX_FIELD_NAME + " = " + multiplexID + " limit 1";
|
|
7642 |
"where tt." + MULTIPLEX_FIELD_NAME + " = " + targetMultiplexID + " limit 1";
|
7533 |
7643 |
Long id = persistence.getSingleSQLResult(checkStmt, null);
|
7534 |
7644 |
full = (id == null);
|
7535 |
7645 |
}
|
... | ... | |
7546 |
7656 |
// if the virtual table is now empty, mark it as such
|
7547 |
7657 |
if (full)
|
7548 |
7658 |
{
|
7549 |
|
local.emptyTableFlags.put(multiplexID, Boolean.TRUE);
|
|
7659 |
if (forceDelete)
|
|
7660 |
{
|
|
7661 |
local.emptyTableFlags.put(targetMultiplexID, Boolean.TRUE);
|
|
7662 |
}
|
|
7663 |
else
|
|
7664 |
{
|
|
7665 |
local.emptyTableFlags.put(multiplexID, Boolean.TRUE);
|
|
7666 |
if (targetMultiplexID != multiplexID)
|
|
7667 |
{
|
|
7668 |
local.emptyTableFlags.put(targetMultiplexID, Boolean.FALSE);
|
|
7669 |
}
|
|
7670 |
}
|
|
7671 |
|
7550 |
7672 |
}
|
7551 |
7673 |
}
|
7552 |
7674 |
|