Project

General

Profile

6714.patch

Dănuț Filimon, 10/27/2022 06:01 AM

Download (12.1 KB)

View differences:

new/src/com/goldencode/p2j/persist/OutputTableCopier.java 2022-10-27 09:58:05 +0000
9 9
** 002 CA  20190311 A buffer may be active as the source for multiple output table parameters.
10 10
** 003 CA  20190728 This needs to be processed first, before buffer's are closing their scope.
11 11
** 004 CA  20221006 Added JMX instrumentation for 'finished'. Refs #6814
12
** 005 DDF 20221027 Added additional parameter to differentiate type of copy operation. (refs. #6714)
12 13
*/
13 14
/*
14 15
** This program is free software: you can redistribute it and/or modify
......
85 86
   
86 87
   /** The table parameter where to copy the data. */
87 88
   private TableParameter outputParam;
89
   
90
   /** Used to check if copy should be done using insert or delete-update. */
91
   private boolean shouldInsert;
88 92

  
89 93
   /**
90 94
    * Creates a copier for the table.
......
93 97
    *           A buffer of the table which should be copied.
94 98
    * @param    outputParam
95 99
    *           The table parameter where to copy the data.
100
    * @param    shouldInsert
101
    *           {@code true} Copy is done using insert based on select.
102
    *           {@code false} Copy is done using delete-update.
96 103
    */
97
   public OutputTableCopier(TemporaryBuffer srcBuf, TableParameter outputParam)
104
   public OutputTableCopier(TemporaryBuffer srcBuf, TableParameter outputParam, boolean shouldInsert)
98 105
   {
99 106
      this.srcBuf = srcBuf;
100 107
      this.outputParam = outputParam;
108
      this.shouldInsert = shouldInsert;
101 109
   }
102 110

  
103 111
   /** Copies data in OUTPUT direction.*/
104 112
   @Override
105 113
   public void finished()
106 114
   {
107
      COPIER.timer(() -> srcBuf.performOutputCopy(outputParam));
115
      COPIER.timer(() -> srcBuf.performOutputCopy(outputParam, shouldInsert));
108 116
   }
109 117

  
110 118
   /** No-op. */
......
136 144
   {
137 145
      return WeightFactor.FIRST;
138 146
   }
139
}
147
}
new/src/com/goldencode/p2j/persist/TemporaryBuffer.java 2022-10-27 09:58:15 +0000
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