Project

General

Profile

rbval.patch

Eric Faulhaber, 02/18/2021 05:09 PM

Download (12.5 KB)

View differences:

src/com/goldencode/p2j/persist/RecordBuffer.java 2021-02-18 17:51:32 +0000
1119 1119
**     OM  20201218          Fixed implementation for error and rejected attributes/hidden fields.
1120 1120
**     OM  20210127          Replaced TableMapper.getLegacyName() triple map lookup with direct access to
1121 1121
**                           local dmoMeta.legacyTable.
1122
**     ECF 20210117          Do not update DMO state when explicitly validating. Attempt to flush a transient
1123
**                           record if still in the buffer when its scope ends.
1122 1124
*/
1123 1125

  
1124 1126
/*
......
3191 3193
            {
3192 3194
               // in batch assign mode, standard validation happens before assign triggers are fired
3193 3195
               Record dmo = buffer.getCurrentRecord();
3194
               buffer.validateMaybeFlush(dmo, false);
3196
               buffer.validateMaybeFlush(dmo, false, false);
3195 3197
               
3196 3198
               // fire assign triggers, if any
3197 3199
               TriggerTracker tracker = buffer.getTriggerTracker();
......
6717 6719
         // validate and persist the record
6718 6720
         if (currentRecord.checkState(DmoState.NEW) || currentRecord.checkState(DmoState.CHANGED))
6719 6721
         {
6720
            validateMaybeFlush(currentRecord, true);
6722
            validateMaybeFlush(currentRecord, true, false);
6721 6723
         }
6722 6724
         else if (currentRecord.checkState(DmoState.INVALID))
6723 6725
         {
......
10039 10041
            if (currentRecord.checkState(DmoState.INVALID))
10040 10042
            {
10041 10043
               // release the broken record as if undone
10044
               // TODO: is this still correct, now that we no longer update the DMO state to INVALID on a
10045
               // failed, explicit validation?
10042 10046
               setCurrentRecord(null, true, false, false, false);
10043 10047
            }
10044 10048
            else
10045 10049
            {
10046
               try
10047
               {
10048
                  flush();
10049
               }
10050
               catch (ValidationException exc)
10051
               {
10052
                  // if the current referenced record does not pass validation,
10053
                  // it means it was never flushed when it was created in the 
10054
                  // first place. so, before allowing the validation exception
10055
                  // to be processed, we must release this not-valid record
10056
                  setCurrentRecord(null, true, false, false, false);
10057
                  
10058
                  throw exc;
10059
               }
10050
               // flush the transient record currently in the buffer, which will attempt validation;
10051
               // the create will be aborted if this record is invalid
10052
               flush(true);
10060 10053
            }
10061 10054
         }
10062 10055
         
......
10294 10287
   throws ValidationException,
10295 10288
          PersistenceException
10296 10289
   {
10297
      validateMaybeFlush(dmo, false);
10290
      validateMaybeFlush(dmo, false, true);
10298 10291
   }
10299 10292
   
10300 10293
   /**
......
10821 10814
    *          Record whose data is to be validated and optionally flushed to the database.
10822 10815
    * @param   flush
10823 10816
    *          {@code true} to validate and persist DMO's data; {@code false} to validate only.
10817
    * @param   explicit
10818
    *          {@code true} if this validation was explicitly requested by business logic; {@code false} if
10819
    *          it is implicit/organic (e.g., in response to a record being updated).
10824 10820
    *
10825 10821
    * @return  The changed property, or {@code null} if there is no current record or if we are in
10826 10822
    *          batch mode.
......
10832 10828
    *          if there was a validation error. This represents an application level data
10833 10829
    *          validation failure and is recoverable.
10834 10830
    */
10835
   private Object[] validateMaybeFlush(Record dmo, boolean flush)
10831
   private Object[] validateMaybeFlush(Record dmo, boolean flush, boolean explicit)
10836 10832
   throws PersistenceException,
10837 10833
          ValidationException
10838 10834
   {
......
10851 10847
                                             persistenceContext.getNursery(),
10852 10848
                                             uniqueTracker,
10853 10849
                                             uniqueTrackerCtx,
10854
                                             flush);
10850
                                             flush,
10851
                                             !explicit);
10855 10852
      try
10856 10853
      {
10857 10854
         diffs = validation.validateMaybeFlush();
......
11175 11172
         {
11176 11173
            activeScopeDepth = -1;
11177 11174
            
11178
            // Mark current record unavailable; however, a no-undo buffer appears to retain its
11179
            // current record and continue reporting errors with an invalid record beyond the
11180
            // buffer's scope
11181
            setCurrentRecord(null, false, false, false, false);
11175
            // attempt to flush a transient record in the buffer at the time its block scope ends; this will
11176
            // trigger validation and may report an error
11177
            if (isTransient())
11178
            {
11179
               try
11180
               {
11181
                  flush(true);
11182
               }
11183
               catch (ValidationException exc)
11184
               {
11185
                  reportValidationException(exc, this, false);
11186
               }
11187
            }
11182 11188
            
11183 11189
            // The snapshot is no longer available
11184 11190
            snapshot = null;
......
12297 12303
               {
12298 12304
                  try
12299 12305
                  {
12300
                     diffs = validateMaybeFlush(currentRecord, false);
12306
                     diffs = validateMaybeFlush(currentRecord, false, false);
12301 12307
                  }
12302 12308
                  catch (ValidationException exc)
12303 12309
                  {
......
13445 13451
   }
13446 13452
   
13447 13453
   /**
13448
    * Set table statistics record
13449
    * @param tableStats
13450
    *        table statistics record
13454
    * Set table statistics record.
13455
    * 
13456
    * @param   tableStats
13457
    *          Table statistics record
13451 13458
    */
13452 13459
   private void setTableStats(TableStats tableStats)
13453 13460
   {
13454 13461
      this.tableStats = tableStats;
13455 13462
   }
13456

  
13463
   
13457 13464
   /**
13458 13465
    * Getter for the {@link #propsBySetter} map.
13459 13466
    * 
......
13463 13470
   {
13464 13471
      return propsBySetter;
13465 13472
   }
13466

  
13473
   
13467 13474
   /**
13468 13475
    * Getter for the {@link #propsByGetter} map.
13469 13476
    * 
......
13473 13480
   {
13474 13481
      return propsByGetter;
13475 13482
   }
13476

  
13483
   
13477 13484
   /**
13478 13485
    * Getter for the {@link #setterDatums} map.
13479 13486
    * 
......
13483 13490
   {
13484 13491
      return setterDatums;
13485 13492
   }
13486

  
13493
   
13487 13494
   /**
13488 13495
    * Getter for the {@link #getterDatums} map.
13489 13496
    * 
......
13493 13500
   {
13494 13501
      return getterDatums;
13495 13502
   }
13496

  
13503
   
13497 13504
   /**
13498 13505
    * Information needed by a getter or setter method to affect the datum of one property (or one
13499 13506
    * element within an extent property), namely, the property's name and optional extent index,
src/com/goldencode/p2j/persist/orm/RecordMeta.java 2021-02-04 20:37:19 +0000
2 2
** Module   : RecordMeta.java
3 3
** Abstract : Information required to perform CRUD operations on a specific DMO type.
4 4
**
5
** Copyright (c) 2019-2020, Golden Code Development Corporation.
5
** Copyright (c) 2019-2021, Golden Code Development Corporation.
6 6
**
7 7
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
8 8
** 001 ECF 20191015 First revision. Information required to perform basic CRUD operations on a
......
13 13
**     OM  20201001 Improved DMO manipulation performance by caching slow Property annotation access.
14 14
**     OM  20201002 Use DmoMeta cached information instead of map lookups.
15 15
**     OM  20201007 Replaced inlined column name with TemporaryBuffer.MULTIPLEX_FIELD_NAME.
16
**     ECF 20210204 Removed word index unsupported log message.
16 17
*/
17 18

  
18 19
/*
......
710 711
      {
711 712
         if (next.word())
712 713
         {
713
            // TODO: handle word index
714
            
715
//            if (log.isLoggable(Level.WARNING))
716
//            {
717
//               String msg = "Word indices are not supported in this version of FWD: " +
718
//                            dmoIface.getCanonicalName() +
719
//                            ": " +
720
//                            next.name();
721
//               log.log(Level.WARNING, msg);
722
//            }
723
            
714
            // TODO: handle word index; how do word indices affect validation?
724 715
            continue;
725 716
         }
726 717
         
src/com/goldencode/p2j/persist/orm/Validation.java 2021-02-18 17:46:06 +0000
16 16
**     AIL 20201020 Closed unclosed prepared statement.
17 17
**     ECF 20201201 Fixed FFC invalidation for flush update case when record was validated previously.
18 18
**         20210126 Ensure all unvalidated unique indices are validated at flush time.
19
**     ECF 20210117 Do not update DMO state when explicitly validating.
19 20
*/
20 21

  
21 22
/*
......
118 119
   /** Whether to flush the record; {@code false} to validate only */
119 120
   private final boolean flush;
120 121
   
122
   /** Whether to update the DMO state as a side effect of validation */
123
   private final boolean updateState;
124
   
121 125
   /** Whether we are validating the most recently updated DMO property only, or the entire DMO */
122 126
   private final boolean singleProp;
123 127
   
......
165 169
    *          Context-local API helper for unique constraint tracking.
166 170
    * @param   flush
167 171
    *          {@code true} to validate and persist DMO's data; {@code false} to validate only.
172
    * @param   updateState
173
    *          Update the DMO's index and validation state as a side effect of validation. This should be set
174
    *          to {@code true} for implicit/organic validation; {@code false} for explicit validation.
168 175
    */
169 176
   public Validation(RecordBuffer buffer,
170 177
                     BaseRecord dmo,
......
173 180
                     RecordNursery nursery,
174 181
                     UniqueTracker uniqueTracker,
175 182
                     UniqueTracker.Context uniqueTrackerCtx,
176
                     boolean flush)
183
                     boolean flush,
184
                     boolean updateState)
177 185
   {
178 186
      this.buffer = buffer;
179 187
      this.dmo = dmo;
......
183 191
      this.uniqueTracker = uniqueTracker;
184 192
      this.uniqueTrackerCtx = uniqueTrackerCtx;
185 193
      this.flush = flush;
194
      this.updateState = updateState;
186 195
      this.singleProp = dmo.getActiveOffset() >= 0;
187 196
   }
188 197
   
......
300 309
         // before the unique constraint checks, which will clear the changed property state
301 310
         Object[] diff = singleProp ? dmo.getActiveUpdateDiffs() : null;
302 311
         
303
         // validate fully updated unique indices, if any
304
         BitSet valUnique = dmo.getUnvalidatedIndices(offset, flush);
312
         // validate fully updated unique indices, if any, or all indices if flushing or not updating index
313
         // state
314
         BitSet valUnique = dmo.getUnvalidatedIndices(offset, flush || !updateState);
305 315
         if (!valUnique.isEmpty())
306 316
         {
307 317
            // validate unique indices (and flush, if flush was requested)
......
318 328
         // update the nursery if we did not already flush and:
319 329
         // * the table has no remaining index needing update; or
320 330
         // * any indices for a new record were updated
321
         if (isNew && !flushed)
331
         if (isNew && (!flushed && updateState))
322 332
         {
323 333
            if (dmo.getIndexState().isEmpty())
324 334
            {
......
340 350
            }
341 351
         }
342 352
         
343
         if (!flushed)
353
         if (!flushed && updateState)
344 354
         {
345 355
            if (singleProp)
346 356
            {
......
430 440
            uniqueTrackerCtx.rollbackChange(uniqueTracker, token);
431 441
         }
432 442
         
433
         // mark record as having failed validation; it will stay this way until it passes
434
         dmo.updateState(session, INVALID, true);
443
         if (updateState)
444
         {
445
            // mark record as having failed validation; it will stay this way until it passes
446
            dmo.updateState(session, INVALID, true);
447
         }
435 448
         
436 449
         throw exc;
437 450
      }
......
785 798
      
786 799
      String msg = bufferName + "." + fi.legacy + " is mandatory, but has unknown (?) value";
787 800
      
788
      dmo.updateState(buffer.getSession(false), INVALID, true);
801
      if (updateState)
802
      {
803
         dmo.updateState(buffer.getSession(false), INVALID, true);
804
      }
789 805
      
790 806
      throw new ValidationException(msg, 110);
791 807
   }